Current section
Files
Jump to
Current section
Files
src/tools/calculator.gleam
import gleam/dynamic
import gleam/int
import gleam/result
import starflow/schema
import starflow/tool
type Operation {
Add
Subtract
Multiply
Divide
}
type Calculator {
Calculator(Operation, Float, Float)
}
pub fn tool() -> tool.Tool {
tool.Tool(
name: "calculator",
description: "Performs basic arithmetic calculations",
schema: schema.object([
schema.required(
"operation",
schema.enum(["add", "subtract", "multiply", "divide"]),
),
schema.required("a", schema.number()),
schema.required("b", schema.number()),
]),
output: schema.number(),
apply: apply,
)
}
fn apply(input: dynamic.Dynamic) {
use Calculator(op, a, b) <- result.map(decoder(input))
case op {
Add -> a +. b
Subtract -> a -. b
Multiply -> a *. b
Divide -> a /. b
}
|> tool.Number
}
fn decoder(
input: dynamic.Dynamic,
) -> Result(Calculator, List(dynamic.DecodeError)) {
input
|> dynamic.decode3(
Calculator,
dynamic.field(named: "operation", of: fn(a) {
use a <- result.try(dynamic.string(a))
case a {
"add" -> Ok(Add)
"subtract" -> Ok(Subtract)
"multiply" -> Ok(Multiply)
"divide" -> Ok(Divide)
_ ->
Error([
dynamic.DecodeError(
"one of add, subtract, multiple, and divide",
a,
[],
),
])
}
}),
dynamic.field(
named: "a",
of: dynamic.any([
dynamic.float,
fn(x) { x |> dynamic.int |> result.map(int.to_float) },
]),
),
dynamic.field(
named: "b",
of: dynamic.any([
dynamic.float,
fn(x) { x |> dynamic.int |> result.map(int.to_float) },
]),
),
)
}