diff --git a/docs/src/content/next/how-to-guides.mdx b/docs/src/content/next/how-to-guides.mdx index 68b3da1f15..4a7f262e3f 100644 --- a/docs/src/content/next/how-to-guides.mdx +++ b/docs/src/content/next/how-to-guides.mdx @@ -9,5 +9,5 @@ Practical, step-by-step guides for building with Golem. Each guide covers a spec - + diff --git a/docs/src/content/next/how-to-guides/moonbit.mdx b/docs/src/content/next/how-to-guides/moonbit.mdx index b378344d72..3cd6ab55b2 100644 --- a/docs/src/content/next/how-to-guides/moonbit.mdx +++ b/docs/src/content/next/how-to-guides/moonbit.mdx @@ -15,6 +15,7 @@ Guides specific to developing Golem agents in MoonBit. + diff --git a/docs/src/content/next/how-to-guides/moonbit/_meta.js b/docs/src/content/next/how-to-guides/moonbit/_meta.js index 5ebacded94..b7724bb189 100644 --- a/docs/src/content/next/how-to-guides/moonbit/_meta.js +++ b/docs/src/content/next/how-to-guides/moonbit/_meta.js @@ -9,6 +9,7 @@ export default { "golem-annotate-agent-moonbit": "Annotating Agent Methods (MoonBit)", "golem-atomic-block-moonbit": "Atomic Blocks and Durability Controls (MoonBit)", "golem-call-from-external-moonbit": "Calling Agents from External MoonBit Applications", + "golem-agent-reflection-moonbit": "Calling Agents with Runtime Reflection (MoonBit)", "golem-call-another-agent-moonbit": "Calling Another Agent (MoonBit)", "golem-configure-durability-moonbit": "Configuring Agent Durability (MoonBit)", "golem-add-cors-moonbit": "Configuring CORS for MoonBit HTTP Endpoints", diff --git a/docs/src/content/next/how-to-guides/moonbit/golem-agent-reflection-moonbit.mdx b/docs/src/content/next/how-to-guides/moonbit/golem-agent-reflection-moonbit.mdx new file mode 100644 index 0000000000..7fc1ef667b --- /dev/null +++ b/docs/src/content/next/how-to-guides/moonbit/golem-agent-reflection-moonbit.mdx @@ -0,0 +1,130 @@ +# Calling Agents with Runtime Reflection (MoonBit) + +Use generated clients when the complete target definition is available at +compile time. Otherwise choose one authority and invocation path explicitly: +caller-authored codecs, runtime-reflected schemas, or direct schema-free +`SchemaValue` calls. + +## Discover and inspect schemas + +```moonbit +let available = @reflection.get_all_agent_types() +guard @reflection.get_agent_type("CounterAgent") is Some(counter_type) else { + raise @reflection.ReflectError::Discovery("CounterAgent is unavailable") +} +guard counter_type.find_method("add") is Some(add) else { + raise @reflection.ReflectError::Discovery("add is unavailable") +} +``` + +Agent type names and reflection identity strings are environment-scoped. +`AgentType` exposes the currently implementing component as deployment +metadata, plus its lifecycle mode, constructor `SchemaRef`, and method schemas. +Reflection clients do not pin that component ID. `SchemaRef::pack_json` +converts canonical JSON into a schema-native value; `unpack_json` performs the +awaited conversion back. + +## Use the three Level 3 invocation paths + +JSON convenience automatically packs and unpacks: + +```moonbit +let counter = counter_type.get_json(Json::object({ + "name": Json::string("main"), +})) +let result = counter.invoke_json( + "add", + Json::object({ "by": Json::number(5.0) }), +) +``` + +For explicit reflected packing, call `add.input.pack_json`, invoke through +`invoke_value`, await the result, and call the output `SchemaRef::unpack_json`. + +For direct values, manually construct the positional record and use a dynamic +client: + +```moonbit +let result = dynamic.invoke_value( + "add", + @model.SchemaValue::Record([@model.SchemaValue::U32(5U)]), +) +``` + +Direct clients never discover or validate schemas. Constructor and method +record fields must be packed in declaration order; the runtime authoritatively +accepts or rejects the attempt. + +Both reflected and direct clients support awaited, trigger, and scheduled +calls through `invoke_value`, `trigger_value`, and `schedule_value`. Awaited +calls use the asynchronous host invocation path and can carry live streams. +Reflected trigger and scheduled calls reject methods whose input or output +schema contains a stream. + +## Define a caller-codec typed contract + +`CallerCodecClient` does not discover payload schemas. The caller's +`IntoSchema` and `FromSchema` implementations are the schema authority: + +```moonbit +#derive.golem_schema +struct CounterId { name : String } +#derive.golem_schema +struct AddInput { by : UInt } +#derive.golem_schema +struct AddOutput { value : UInt } + +let counter = @reflection.CallerCodecClient::create( + "CounterAgent", + CounterId::{ name: "main" }, +) +let result : @reflection.Invocation[AddOutput] = counter.invoke( + "add", + AddInput::{ by: 5U }, +) +``` + +The type name is resolved to its current implementing component in the +environment; callers do not pin component metadata. Existing IDs can be bound +with `CallerCodecClient::bind(agent_id)`. Caller codecs remain authoritative +for payload encoding and decoding. + +For trigger or scheduled caller-codec calls, pass an output type tag so the +SDK can reject live streams in either direction: + +```moonbit +counter.trigger( + "reset", + ResetInput::{}, + (@schema.type_tag() : @schema.TypeTag[Unit]), +) +``` + +## Raw lifecycle attempts + +- Use a supplied `ParsedAgentId` with `DynamicAgentClient::from_agent_id`, or + inspect it with `ParsedAgentId::parts`. +- Use `DynamicAgentClient::lookup` for a manually packed durable identity + without a phantom UUID. +- Use `resume_phantom` with a known UUID. +- Use `new_phantom` to generate a UUID and receive the client, reusable + `ParsedAgentId`, and phantom UUID together. +- Use `DynamicAgentClient::ephemeral` for a raw invocation address built from + the type name and manually packed constructor values. + +Raw lifecycle helpers perform no discovery, schema validation, lifecycle-mode +verification, or local factory checks. The runtime is authoritative. + +An ephemeral address has no guaranteed reusable pre-invocation identity. The +final identity comes from invocation metadata and must not be treated as a +resumable durable identity. + +## Choose an invocation path + +| Situation | Use | +|---|---| +| Generated definition available | Generated agent client | +| Typed contract owned by the caller | `CallerCodecClient` resolved by environment type name | +| Runtime-selected method with automatic JSON conversion | `invoke_json` | +| Explicit runtime-schema packing | `SchemaRef::pack_json`, `invoke_value`, `unpack_json` | +| Schema-free infrastructure with Golem values | `DynamicAgentClient` | diff --git a/golem-skills/skills/moonbit/golem-agent-reflection-moonbit/SKILL.md b/golem-skills/skills/moonbit/golem-agent-reflection-moonbit/SKILL.md new file mode 100644 index 0000000000..8e8c00c8a2 --- /dev/null +++ b/golem-skills/skills/moonbit/golem-agent-reflection-moonbit/SKILL.md @@ -0,0 +1,135 @@ +--- +name: golem-agent-reflection-moonbit +description: "Discovering and calling Golem agents through runtime reflection in MoonBit. Use when agent types or methods are selected dynamically, schemas must be inspected at runtime, caller-authored codecs are needed, or SchemaValue calls must avoid discovery." +--- + +# Calling Agents with Runtime Reflection (MoonBit) + +Use generated clients when the complete target definition is available at +compile time. Otherwise choose one authority and invocation path explicitly: +caller-authored codecs, runtime-reflected schemas, or direct schema-free +`SchemaValue` calls. + +## Discover and inspect schemas + +```moonbit +let available = @reflection.get_all_agent_types() +guard @reflection.get_agent_type("CounterAgent") is Some(counter_type) else { + raise @reflection.ReflectError::Discovery("CounterAgent is unavailable") +} +guard counter_type.find_method("add") is Some(add) else { + raise @reflection.ReflectError::Discovery("add is unavailable") +} +``` + +Agent type names and reflection identity strings are environment-scoped. +`AgentType` exposes the currently implementing component as deployment +metadata, plus its lifecycle mode, constructor `SchemaRef`, and method schemas. +Reflection clients do not pin that component ID. `SchemaRef::pack_json` +converts canonical JSON into a schema-native value; `unpack_json` performs the +awaited conversion back. + +## Use the three Level 3 invocation paths + +JSON convenience automatically packs and unpacks: + +```moonbit +let counter = counter_type.get_json(Json::object({ + "name": Json::string("main"), +})) +let result = counter.invoke_json( + "add", + Json::object({ "by": Json::number(5.0) }), +) +``` + +For explicit reflected packing, call `add.input.pack_json`, invoke through +`invoke_value`, await the result, and call the output `SchemaRef::unpack_json`. + +For direct values, manually construct the positional record and use a dynamic +client: + +```moonbit +let result = dynamic.invoke_value( + "add", + @model.SchemaValue::Record([@model.SchemaValue::U32(5U)]), +) +``` + +Direct clients never discover or validate schemas. Constructor and method +record fields must be packed in declaration order; the runtime authoritatively +accepts or rejects the attempt. + +Both reflected and direct clients support awaited, trigger, and scheduled +calls through `invoke_value`, `trigger_value`, and `schedule_value`. Awaited +calls use the asynchronous host invocation path and can carry live streams. +Reflected trigger and scheduled calls reject methods whose input or output +schema contains a stream. + +## Define a caller-codec typed contract + +`CallerCodecClient` does not discover payload schemas. The caller's +`IntoSchema` and `FromSchema` implementations are the schema authority: + +```moonbit +#derive.golem_schema +struct CounterId { name : String } +#derive.golem_schema +struct AddInput { by : UInt } +#derive.golem_schema +struct AddOutput { value : UInt } + +let counter = @reflection.CallerCodecClient::create( + "CounterAgent", + CounterId::{ name: "main" }, +) +let result : @reflection.Invocation[AddOutput] = counter.invoke( + "add", + AddInput::{ by: 5U }, +) +``` + +The type name is resolved to its current implementing component in the +environment; callers do not pin component metadata. Existing IDs can be bound +with `CallerCodecClient::bind(agent_id)`. Caller codecs remain authoritative +for payload encoding and decoding. + +For trigger or scheduled caller-codec calls, pass an output type tag so the +SDK can reject live streams in either direction: + +```moonbit +counter.trigger( + "reset", + ResetInput::{}, + (@schema.type_tag() : @schema.TypeTag[Unit]), +) +``` + +## Raw lifecycle attempts + +- Use a supplied `ParsedAgentId` with `DynamicAgentClient::from_agent_id`, or + inspect it with `ParsedAgentId::parts`. +- Use `DynamicAgentClient::lookup` for a manually packed durable identity + without a phantom UUID. +- Use `resume_phantom` with a known UUID. +- Use `new_phantom` to generate a UUID and receive the client, reusable + `ParsedAgentId`, and phantom UUID together. +- Use `DynamicAgentClient::ephemeral` for a raw invocation address built from + the type name and manually packed constructor values. + +Raw lifecycle helpers perform no discovery, schema validation, lifecycle-mode +verification, or local factory checks. The runtime is authoritative. + +An ephemeral address has no guaranteed reusable pre-invocation identity. The +final identity comes from invocation metadata and must not be treated as a +resumable durable identity. + +## Choose an invocation path + +| Situation | Use | +|---|---| +| Generated definition available | Generated agent client | +| Typed contract owned by the caller | `CallerCodecClient` resolved by environment type name | +| Runtime-selected method with automatic JSON conversion | `invoke_json` | +| Explicit runtime-schema packing | `SchemaRef::pack_json`, `invoke_value`, `unpack_json` | +| Schema-free infrastructure with Golem values | `DynamicAgentClient` | diff --git a/golem-skills/tests/harness/scenarios/rpc-5-runtime-reflection.yaml b/golem-skills/tests/harness/scenarios/rpc-5-runtime-reflection.yaml index 73a3bae415..3131221b97 100644 --- a/golem-skills/tests/harness/scenarios/rpc-5-runtime-reflection.yaml +++ b/golem-skills/tests/harness/scenarios/rpc-5-runtime-reflection.yaml @@ -193,3 +193,62 @@ steps: equals: "reflected value" - path: "$.directValue" equals: "direct value" + + - id: "create-moonbit-project" + only_if: + language: "moonbit" + create_project: + name: test-app + verify: + build: true + + - id: "add-moonbit-reflected-rpc" + only_if: + language: "moonbit" + prompt: > + In the MoonBit test-app project, add a durable `ReflectionTarget` agent + identified by a string `name`, with an `echo` method accepting and + returning a string. Add a durable `ReflectionCaller` whose async `run` + method discovers `ReflectionTarget`, inspects `echo`, and invokes it + through the JSON convenience path with `hello`. + + Also invoke the same target through a discovery-free + `CallerCodecClient` with caller-authored record codecs and the message + `caller codec`. Explicitly pack JSON through the reflected method + `SchemaRef`, invoke its value API, await the result, and unpack it as + `reflected value`. Finally bind a `DynamicAgentClient` to the same + `AgentId`, manually construct a positional `SchemaValue::Record`, and + invoke `echo` with `direct value` without schemas. + + Return a schema-derived record containing `listed`, `type_name`, + `method_name`, `json_value`, `caller_codec`, `reflected_value`, and + `direct_value`. Make sure the project builds successfully. + expectedSkills: + - "golem-agent-reflection" + - "golem-agent-reflection-moonbit" + verify: + build: true + deploy: true + + - id: "verify-moonbit-reflected-rpc" + only_if: + language: "moonbit" + invoke_json: + agent: 'ReflectionCaller("main")' + method: "run" + expect: + result_json: + - path: "$.listed" + equals: true + - path: "$.type_name" + equals: "ReflectionTarget" + - path: "$.method_name" + equals: "echo" + - path: "$.json_value" + equals: "hello" + - path: "$.caller_codec" + equals: "caller codec" + - path: "$.reflected_value" + equals: "reflected value" + - path: "$.direct_value" + equals: "direct value" diff --git a/sdks/moonbit/golem_sdk/README.mbt.md b/sdks/moonbit/golem_sdk/README.mbt.md index ac126876df..248a38326c 100644 --- a/sdks/moonbit/golem_sdk/README.mbt.md +++ b/sdks/moonbit/golem_sdk/README.mbt.md @@ -377,6 +377,7 @@ Use `golem build` and `golem deploy` with a `golem.yaml` application manifest. S - **Agent registry** — register multiple agent types in a single component via `#derive.agent` - **Custom data types** — `#derive.golem_schema` implements every nexessary trait to use custom data types on the public interface of your agents - **Agent-to-agent RPC** — auto-generated client stubs (`CounterClient`); stream-bearing methods are awaited, while stream-free methods also support fire-and-forget and scheduled invocations +- **Runtime reflection** — discover agent types, pack reflected schemas, define caller-codec clients, or invoke direct `SchemaValue`s - **Agent tools** — code-first tool descriptors, command trees, constraints, custom errors, runtime dispatch, and typed tool RPC clients via `#derive.tool` - **Tool middleware** — monomorphic policy/adapter middleware and universal transparent middleware with invocation-scoped underlying capabilities - **Multimodal input** — accept mixed text, binary, and custom modality data via `#derive.multimodal` and `@multimodal.Multimodal[T]` @@ -397,6 +398,7 @@ Use `golem build` and `golem deploy` with a `golem.yaml` application manifest. S | `logging` | Structured logging with named loggers and level filtering | | `context` | Span-based tracing and invocation context | | `rpc` | Agent-to-agent RPC helpers | +| `reflection` | Runtime discovery, reflected JSON packing, caller-codec clients, and schema-free value invocation | | `tool-core` | Host-neutral tool descriptors, schemas, canonical input handling, and error model | | `tool` | Ordinary tool registry, dispatch, help rendering, and ambient typed RPC client runtime | | `tool-middleware` | Host-neutral middleware registry, opaque invocation carriers, typed/universal underlying capabilities, and ownership enforcement | diff --git a/sdks/moonbit/golem_sdk/reflection/caller_codec.mbt b/sdks/moonbit/golem_sdk/reflection/caller_codec.mbt new file mode 100644 index 0000000000..c4021352e5 --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/caller_codec.mbt @@ -0,0 +1,143 @@ +///| +/// Typed client whose `IntoSchema` and `FromSchema` implementations are +/// authored by the caller. The environment-unique type name is the invocation +/// address; no reflected schema is consulted. +pub(all) struct CallerCodecClient { + priv transport : Transport + reusable_identity : ParsedAgentId? +} + +///| +pub fn[C : @schema.IntoSchema] CallerCodecClient::create( + type_name : String, + constructor_input : C, + phantom_id? : @types.Uuid? = None, +) -> CallerCodecClient raise ReflectError { + let constructor_value = @schema.to_value_as(constructor_input) + let identity = ParsedAgentId::create( + type_name, + constructor_value, + phantom_id~, + ) + { + transport: Transport::create(type_name, constructor_value, phantom_id), + reusable_identity: Some(identity), + } +} + +///| +pub fn CallerCodecClient::bind( + agent_id : ParsedAgentId, +) -> CallerCodecClient raise ReflectError { + let parts = agent_id.parts() + { + transport: Transport::create( + parts.type_name, + parts.constructor_value, + parts.phantom_id, + ), + reusable_identity: Some(agent_id), + } +} + +///| +pub async fn[I : @schema.IntoSchema, O : @schema.FromSchema] CallerCodecClient::invoke( + self : CallerCodecClient, + method_name : String, + input : I, +) -> Invocation[O] { + let invocation = self.transport.invoke_value( + method_name, + @schema.to_value_as(input), + ) + let value = match invocation.value { + Some(value) => + @schema.from_value_as(value) catch { + error => + raise ReflectError::Schema( + "failed to decode typed output: \{repr(error)}", + ) + } + None => raise ReflectError::Schema("typed method returned unit") + } + { metadata: invocation.metadata, value, } +} + +///| +pub async fn[I : @schema.IntoSchema] CallerCodecClient::invoke_unit( + self : CallerCodecClient, + method_name : String, + input : I, +) -> Invocation[Unit] { + let invocation = self.transport.invoke_value( + method_name, + @schema.to_value_as(input), + ) + guard invocation.value is None else { + raise ReflectError::Schema("unit method returned a value") + } + { metadata: invocation.metadata, value: (), } +} + +///| +pub fn[I : @schema.IntoSchema, O : @schema.IntoSchema] CallerCodecClient::trigger( + self : CallerCodecClient, + method_name : String, + input : I, + output : @schema.TypeTag[O], +) -> InvocationMetadata raise ReflectError { + reject_caller_codec_non_awaited_streams( + method_name, + "trigger", + (@schema.type_tag() : @schema.TypeTag[I]), + output, + ) + self.transport.trigger_value(method_name, @schema.to_value_as(input)) +} + +///| +pub fn[I : @schema.IntoSchema, O : @schema.IntoSchema] CallerCodecClient::schedule( + self : CallerCodecClient, + scheduled_at : @systemClock.Instant, + method_name : String, + input : I, + output : @schema.TypeTag[O], +) -> ScheduledInvocation raise ReflectError { + reject_caller_codec_non_awaited_streams( + method_name, + "schedule", + (@schema.type_tag() : @schema.TypeTag[I]), + output, + ) + self.transport.schedule_value( + scheduled_at, + method_name, + @schema.to_value_as(input), + ) +} + +///| +fn[I : @schema.IntoSchema, O : @schema.IntoSchema] reject_caller_codec_non_awaited_streams( + method_name : String, + operation : String, + input : @schema.TypeTag[I], + output : @schema.TypeTag[O], +) -> Unit raise ReflectError { + let input_graph = @schema.schema_graph_of_tag(input) catch { + error => raise Schema("failed to build caller-owned schema: \{repr(error)}") + } + let output_graph = @schema.schema_graph_of_tag(output) catch { + error => raise Schema("failed to build caller-owned schema: \{repr(error)}") + } + guard !SchemaRef::new(input_graph).contains_stream() && + !SchemaRef::new(output_graph).contains_stream() else { + raise Schema( + operation + " is unavailable for streaming method '" + method_name + "'", + ) + } +} + +///| +pub fn CallerCodecClient::drop(self : CallerCodecClient) -> Unit { + self.transport.drop() +} diff --git a/sdks/moonbit/golem_sdk/reflection/dynamic_client.mbt b/sdks/moonbit/golem_sdk/reflection/dynamic_client.mbt new file mode 100644 index 0000000000..54704ff85e --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/dynamic_client.mbt @@ -0,0 +1,113 @@ +///| +/// Schema-free client for manually packed `SchemaValue` calls. Constructing +/// this client performs no discovery or local lifecycle verification. +pub(all) struct DynamicAgentClient { + priv transport : Transport + reusable_identity : ParsedAgentId? +} + +///| +pub fn DynamicAgentClient::from_agent_id( + agent_id : ParsedAgentId, +) -> DynamicAgentClient raise ReflectError { + let parts = agent_id.parts() + { + transport: Transport::create( + parts.type_name, + parts.constructor_value, + parts.phantom_id, + ), + reusable_identity: Some(agent_id), + } +} + +///| +/// Attempts a durable lookup by manually constructing an identity without a +/// phantom UUID. The runtime authoritatively accepts or rejects the operation. +pub fn DynamicAgentClient::lookup( + type_name : String, + constructor_value : @model.SchemaValue, +) -> DynamicAgentClient raise ReflectError { + DynamicAgentClient::from_agent_id( + ParsedAgentId::create(type_name, constructor_value), + ) +} + +///| +/// Attempts to resume a durable phantom from a known UUID. +pub fn DynamicAgentClient::resume_phantom( + type_name : String, + constructor_value : @model.SchemaValue, + phantom_id : @types.Uuid, +) -> DynamicAgentClient raise ReflectError { + DynamicAgentClient::from_agent_id( + ParsedAgentId::create( + type_name, + constructor_value, + phantom_id=Some(phantom_id), + ), + ) +} + +///| +/// Generates a phantom UUID and exposes both the reusable agent identity and +/// the UUID used to construct it. +pub fn DynamicAgentClient::new_phantom( + type_name : String, + constructor_value : @model.SchemaValue, +) -> CreatedPhantomClient raise ReflectError { + let phantom_id = @apiHost.generate_idempotency_key() + let agent_id = ParsedAgentId::create( + type_name, + constructor_value, + phantom_id=Some(phantom_id), + ) + { agent_id, phantom_id, client: DynamicAgentClient::from_agent_id(agent_id), } +} + +///| +/// Constructs a raw ephemeral invocation address. No reusable pre-invocation +/// identity is guaranteed; use the final identity returned in invocation +/// metadata. +pub fn DynamicAgentClient::ephemeral( + type_name : String, + constructor_value : @model.SchemaValue, +) -> DynamicAgentClient raise ReflectError { + { + transport: Transport::create(type_name, constructor_value, None), + reusable_identity: None, + } +} + +///| +pub async fn DynamicAgentClient::invoke_value( + self : DynamicAgentClient, + method_name : String, + input : @model.SchemaValue, +) -> Invocation[@model.SchemaValue?] { + self.transport.invoke_value(method_name, input) +} + +///| +pub fn DynamicAgentClient::trigger_value( + self : DynamicAgentClient, + method_name : String, + input : @model.SchemaValue, +) -> InvocationMetadata raise ReflectError { + self.transport.trigger_value(method_name, input) +} + +///| +pub fn DynamicAgentClient::schedule_value( + self : DynamicAgentClient, + scheduled_at : @systemClock.Instant, + method_name : String, + input : @model.SchemaValue, +) -> ScheduledInvocation raise ReflectError { + self.transport.schedule_value(scheduled_at, method_name, input) +} + +///| +pub fn DynamicAgentClient::drop(self : DynamicAgentClient) -> Unit { + self.transport.drop() +} diff --git a/sdks/moonbit/golem_sdk/reflection/identity.mbt b/sdks/moonbit/golem_sdk/reflection/identity.mbt new file mode 100644 index 0000000000..074df6a77a --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/identity.mbt @@ -0,0 +1,32 @@ +///| +/// Constructs an agent ID from manually packed constructor values. This is a +/// schema-free operation: the runtime is authoritative about whether the +/// requested lifecycle operation is valid. +pub fn ParsedAgentId::create( + type_name : String, + constructor_value : @model.SchemaValue, + phantom_id? : @types.Uuid? = None, +) -> ParsedAgentId raise ReflectError { + let wire = @model.schema_value_to_wit(constructor_value) catch { + error => raise Schema("failed to encode constructor value: \{repr(error)}") + } + match @agentHost.make_agent_id(type_name, wire, phantom_id) { + Ok(value) => { value, } + Err(error) => raise Identity(agent_error_message(error)) + } +} + +///| +pub fn ParsedAgentId::parts( + self : ParsedAgentId, +) -> ParsedAgentIdParts raise ReflectError { + match @agentHost.parse_agent_id(self.value) { + Ok((type_name, constructor_input, phantom_id)) => { + let typed = @model_host.typed_schema_value_from_wit(constructor_input) catch { + error => raise Schema("failed to decode agent ID: \{repr(error)}") + } + { type_name, constructor_value: typed.value, phantom_id, } + } + Err(error) => raise Identity(agent_error_message(error)) + } +} diff --git a/sdks/moonbit/golem_sdk/reflection/moon.pkg b/sdks/moonbit/golem_sdk/reflection/moon.pkg new file mode 100644 index 0000000000..21aee9c1c6 --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/moon.pkg @@ -0,0 +1,13 @@ +import { + "golemcloud/golem_sdk/interface/golem/core/types", + "golemcloud/golem_sdk/interface/golem/agent/common", + "golemcloud/golem_sdk/interface/golem/agent/host" @agentHost, + "golemcloud/golem_sdk/interface/golem/api/host" @apiHost, + "golemcloud/golem_sdk/interface/wasi/clocks/system-clock" @systemClock, + "golemcloud/golem_sdk/schema", + "golemcloud/golem_sdk/schema_model" @model, + "golemcloud/golem_sdk/schema_model_host" @model_host, + "moonbitlang/core/string", +} + +supported_targets = "+wasm" diff --git a/sdks/moonbit/golem_sdk/reflection/pkg.generated.mbti b/sdks/moonbit/golem_sdk/reflection/pkg.generated.mbti new file mode 100644 index 0000000000..e98c3e872e --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/pkg.generated.mbti @@ -0,0 +1,149 @@ +// Generated using `moon info`, DON'T EDIT IT +package "golemcloud/golem_sdk/reflection" + +import { + "golemcloud/golem_sdk/interface/golem/agent/host", + "golemcloud/golem_sdk/interface/golem/core/types", + "golemcloud/golem_sdk/interface/wasi/clocks/system-clock", + "golemcloud/golem_sdk/schema", + "golemcloud/golem_sdk/schema_model", + "moonbitlang/core/debug", +} + +// Values +pub fn get_agent_type(String) -> AgentType? raise ReflectError + +pub fn get_agent_type_by_agent_id(ParsedAgentId) -> AgentType? raise ReflectError + +pub fn get_all_agent_types() -> Array[AgentType] raise ReflectError + +// Errors +pub(all) suberror ReflectError { + Discovery(String) + Identity(String) + Schema(String) + Json(String) + Remote(String) +} derive(Eq, @debug.Debug) + +// Types and methods +pub(all) struct AgentMethod { + name : String + description : String + prompt_hint : String? + input : SchemaRef + output : SchemaRef? +} derive(Eq, @debug.Debug) + +pub(all) enum AgentMode { + Durable + Ephemeral +} derive(Eq, @debug.Debug) + +pub(all) struct AgentType { + name : String + description : String + source_language : String + mode : AgentMode + implemented_by : @types.ComponentId + constructor_input : SchemaRef + methods : Array[AgentMethod] +} derive(Eq, @debug.Debug) +pub fn AgentType::agent_id_json(Self, Json, phantom_id? : @types.Uuid?) -> ParsedAgentId raise ReflectError +pub fn AgentType::agent_id_value(Self, @schema_model.SchemaValue, phantom_id? : @types.Uuid?) -> ParsedAgentId raise ReflectError +pub fn AgentType::ephemeral_json(Self, Json) -> ReflectedAgentClient raise ReflectError +pub fn AgentType::ephemeral_value(Self, @schema_model.SchemaValue) -> ReflectedAgentClient raise ReflectError +pub fn AgentType::find_method(Self, String) -> AgentMethod? +pub fn AgentType::get_json(Self, Json) -> ReflectedAgentClient raise ReflectError +pub fn AgentType::get_value(Self, @schema_model.SchemaValue) -> ReflectedAgentClient raise ReflectError +pub fn AgentType::new_phantom_json(Self, Json) -> ReflectedAgentClient raise ReflectError +pub fn AgentType::new_phantom_value(Self, @schema_model.SchemaValue) -> ReflectedAgentClient raise ReflectError +pub fn AgentType::resume_phantom_json(Self, Json, @types.Uuid) -> ReflectedAgentClient raise ReflectError +pub fn AgentType::resume_phantom_value(Self, @schema_model.SchemaValue, @types.Uuid) -> ReflectedAgentClient raise ReflectError + +pub(all) struct CallerCodecClient { + reusable_identity : ParsedAgentId? + // private fields +} +pub fn CallerCodecClient::bind(ParsedAgentId) -> Self raise ReflectError +pub fn[C : @schema.IntoSchema] CallerCodecClient::create(String, C, phantom_id? : @types.Uuid?) -> Self raise ReflectError +pub fn CallerCodecClient::drop(Self) -> Unit +pub async fn[I : @schema.IntoSchema, O : @schema.FromSchema] CallerCodecClient::invoke(Self, String, I) -> Invocation[O] +pub async fn[I : @schema.IntoSchema] CallerCodecClient::invoke_unit(Self, String, I) -> Invocation[Unit] +pub fn[I : @schema.IntoSchema, O : @schema.IntoSchema] CallerCodecClient::schedule(Self, @system-clock.Instant, String, I, @schema.TypeTag[O]) -> ScheduledInvocation raise ReflectError +pub fn[I : @schema.IntoSchema, O : @schema.IntoSchema] CallerCodecClient::trigger(Self, String, I, @schema.TypeTag[O]) -> InvocationMetadata raise ReflectError + +pub(all) struct CreatedPhantomClient { + agent_id : ParsedAgentId + phantom_id : @types.Uuid + client : DynamicAgentClient +} + +pub(all) struct DynamicAgentClient { + reusable_identity : ParsedAgentId? + // private fields +} +pub fn DynamicAgentClient::drop(Self) -> Unit +pub fn DynamicAgentClient::ephemeral(String, @schema_model.SchemaValue) -> Self raise ReflectError +pub fn DynamicAgentClient::from_agent_id(ParsedAgentId) -> Self raise ReflectError +pub async fn DynamicAgentClient::invoke_value(Self, String, @schema_model.SchemaValue) -> Invocation[@schema_model.SchemaValue?] +pub fn DynamicAgentClient::lookup(String, @schema_model.SchemaValue) -> Self raise ReflectError +pub fn DynamicAgentClient::new_phantom(String, @schema_model.SchemaValue) -> CreatedPhantomClient raise ReflectError +pub fn DynamicAgentClient::resume_phantom(String, @schema_model.SchemaValue, @types.Uuid) -> Self raise ReflectError +pub fn DynamicAgentClient::schedule_value(Self, @system-clock.Instant, String, @schema_model.SchemaValue) -> ScheduledInvocation raise ReflectError +pub fn DynamicAgentClient::trigger_value(Self, String, @schema_model.SchemaValue) -> InvocationMetadata raise ReflectError + +pub(all) struct Invocation[T] { + metadata : InvocationMetadata + value : T +} derive(Eq, @debug.Debug) + +pub(all) struct InvocationMetadata { + agent_id : ParsedAgentId + idempotency_key : String +} derive(Eq, @debug.Debug) + +pub(all) struct ParsedAgentId { + value : String +} derive(Eq, @debug.Debug) +pub fn ParsedAgentId::create(String, @schema_model.SchemaValue, phantom_id? : @types.Uuid?) -> Self raise ReflectError +pub fn ParsedAgentId::parts(Self) -> ParsedAgentIdParts raise ReflectError + +pub(all) struct ParsedAgentIdParts { + type_name : String + constructor_value : @schema_model.SchemaValue + phantom_id : @types.Uuid? +} derive(Eq, @debug.Debug) + +pub(all) struct ReflectedAgentClient { + reusable_identity : ParsedAgentId? + phantom_id : @types.Uuid? + // private fields +} +pub fn ReflectedAgentClient::drop(Self) -> Unit +pub async fn ReflectedAgentClient::invoke_json(Self, String, Json) -> Invocation[Json?] +pub async fn ReflectedAgentClient::invoke_value(Self, String, @schema_model.SchemaValue) -> Invocation[@schema_model.SchemaValue?] +pub fn ReflectedAgentClient::schedule_json(Self, @system-clock.Instant, String, Json) -> ScheduledInvocation raise ReflectError +pub fn ReflectedAgentClient::schedule_value(Self, @system-clock.Instant, String, @schema_model.SchemaValue) -> ScheduledInvocation raise ReflectError +pub fn ReflectedAgentClient::trigger_json(Self, String, Json) -> InvocationMetadata raise ReflectError +pub fn ReflectedAgentClient::trigger_value(Self, String, @schema_model.SchemaValue) -> InvocationMetadata raise ReflectError + +pub(all) struct ScheduledInvocation { + metadata : InvocationMetadata + cancellation_token : @host.CancellationToken +} +pub fn ScheduledInvocation::cancel(Self) -> Unit +pub fn ScheduledInvocation::drop(Self) -> Unit + +pub(all) struct SchemaRef { + graph : @schema_model.SchemaGraph + root : @schema_model.SchemaType +} derive(Eq, @debug.Debug) +pub fn SchemaRef::contains_stream(Self) -> Bool +pub fn SchemaRef::new(@schema_model.SchemaGraph) -> Self +pub fn SchemaRef::pack_json(Self, Json) -> @schema_model.SchemaValue raise ReflectError +pub fn SchemaRef::unpack_json(Self, @schema_model.SchemaValue) -> Json raise ReflectError + +// Type aliases + +// Traits diff --git a/sdks/moonbit/golem_sdk/reflection/reflected_client.mbt b/sdks/moonbit/golem_sdk/reflection/reflected_client.mbt new file mode 100644 index 0000000000..850a3783f0 --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/reflected_client.mbt @@ -0,0 +1,405 @@ +///| +/// A method discovered from the runtime-owned agent schema. +pub(all) struct AgentMethod { + name : String + description : String + prompt_hint : String? + input : SchemaRef + output : SchemaRef? +} derive(Debug, Eq) + +///| +/// An agent type discovered from the runtime registry. +pub(all) struct AgentType { + name : String + description : String + source_language : String + mode : AgentMode + implemented_by : @types.ComponentId + constructor_input : SchemaRef + methods : Array[AgentMethod] +} derive(Debug, Eq) + +///| +/// A reflected client and any reusable identity created before invocation. +/// Ephemeral clients have no reusable identity until invocation metadata is +/// returned by the runtime. +pub(all) struct ReflectedAgentClient { + priv agent_type : AgentType + priv transport : Transport + reusable_identity : ParsedAgentId? + phantom_id : @types.Uuid? +} + +///| +fn decode_root_type( + graph : @types.SchemaGraph, + root : Int, +) -> @model.SchemaType raise ReflectError { + let decoded = @model.schema_graph_from_wit({ ..graph, root, }) catch { + error => raise Schema("failed to decode reflected schema: \{repr(error)}") + } + decoded.root +} + +///| +fn decode_input( + graph : @types.SchemaGraph, + decoded : @model.SchemaGraph, + input : @common.InputSchema, +) -> SchemaRef raise ReflectError { + let raw_fields = match input { + Parameters(fields) => fields + } + let fields : Array[@model.NamedFieldType] = [] + for field in raw_fields { + match field.source { + UserSupplied => + fields.push({ + name: field.name, + body: decode_root_type(graph, field.schema), + metadata: field.metadata, + }) + AutoInjected(_) => () + } + } + SchemaRef::new({ + defs: decoded.defs, + root: @model.schema_type(Record(fields)), + }) +} + +///| +fn decode_output( + graph : @types.SchemaGraph, + decoded : @model.SchemaGraph, + output : @common.OutputSchema, +) -> SchemaRef? raise ReflectError { + match output { + Unit => None + Single(root) => + Some( + SchemaRef::new({ + defs: decoded.defs, + root: decode_root_type(graph, root), + }), + ) + } +} + +///| +fn decode_agent_type( + registered : @common.RegisteredAgentType, +) -> AgentType raise ReflectError { + let raw = registered.agent_type + let decoded = @model.schema_graph_from_wit(raw.schema) catch { + error => raise Schema("failed to decode reflected schema: \{repr(error)}") + } + let methods : Array[AgentMethod] = [] + for raw_method in raw.methods { + methods.push({ + name: raw_method.name, + description: raw_method.description, + prompt_hint: raw_method.prompt_hint, + input: decode_input(raw.schema, decoded, raw_method.input_schema), + output: decode_output(raw.schema, decoded, raw_method.output_schema), + }) + } + { + name: raw.type_name, + description: raw.description, + source_language: raw.source_language, + mode: match raw.mode { + DURABLE => Durable + EPHEMERAL => Ephemeral + }, + implemented_by: registered.implemented_by, + constructor_input: decode_input( + raw.schema, + decoded, + raw.constructor_.input_schema, + ), + methods, + } +} + +///| +pub fn get_all_agent_types() -> Array[AgentType] raise ReflectError { + @agentHost.get_all_agent_types().map(decode_agent_type) +} + +///| +pub fn get_agent_type(name : String) -> AgentType? raise ReflectError { + match @agentHost.get_agent_type(name) { + Some(agent_type) => Some(decode_agent_type(agent_type)) + None => None + } +} + +///| +pub fn get_agent_type_by_agent_id( + agent_id : ParsedAgentId, +) -> AgentType? raise ReflectError { + match @agentHost.get_agent_type_by_agent_id(agent_id.value) { + Some(agent_type) => Some(decode_agent_type(agent_type)) + None => None + } +} + +///| +pub fn AgentType::find_method(self : AgentType, name : String) -> AgentMethod? { + self.methods.iter().find_first(entry => entry.name == name) +} + +///| +pub fn AgentType::agent_id_value( + self : AgentType, + constructor_value : @model.SchemaValue, + phantom_id? : @types.Uuid? = None, +) -> ParsedAgentId raise ReflectError { + ParsedAgentId::create(self.name, constructor_value, phantom_id~) +} + +///| +pub fn AgentType::agent_id_json( + self : AgentType, + constructor_json : Json, + phantom_id? : @types.Uuid? = None, +) -> ParsedAgentId raise ReflectError { + self.agent_id_value( + self.constructor_input.pack_json(constructor_json), + phantom_id~, + ) +} + +///| +fn AgentType::client_value( + self : AgentType, + constructor_value : @model.SchemaValue, + phantom_id : @types.Uuid?, + reusable_identity : ParsedAgentId?, +) -> ReflectedAgentClient raise ReflectError { + { + agent_type: self, + transport: Transport::create(self.name, constructor_value, phantom_id), + reusable_identity, + phantom_id, + } +} + +///| +pub fn AgentType::get_value( + self : AgentType, + constructor_value : @model.SchemaValue, +) -> ReflectedAgentClient raise ReflectError { + guard self.mode == Durable else { + raise Identity( + "existing identity lookup is unavailable for ephemeral agents", + ) + } + let identity = self.agent_id_value(constructor_value) + self.client_value(constructor_value, None, Some(identity)) +} + +///| +pub fn AgentType::get_json( + self : AgentType, + constructor_json : Json, +) -> ReflectedAgentClient raise ReflectError { + self.get_value(self.constructor_input.pack_json(constructor_json)) +} + +///| +pub fn AgentType::resume_phantom_value( + self : AgentType, + constructor_value : @model.SchemaValue, + phantom_id : @types.Uuid, +) -> ReflectedAgentClient raise ReflectError { + guard self.mode == Durable else { + raise Identity("phantom identities are unavailable for ephemeral agents") + } + let identity = self.agent_id_value( + constructor_value, + phantom_id=Some(phantom_id), + ) + self.client_value(constructor_value, Some(phantom_id), Some(identity)) +} + +///| +pub fn AgentType::resume_phantom_json( + self : AgentType, + constructor_json : Json, + phantom_id : @types.Uuid, +) -> ReflectedAgentClient raise ReflectError { + self.resume_phantom_value( + self.constructor_input.pack_json(constructor_json), + phantom_id, + ) +} + +///| +pub fn AgentType::new_phantom_value( + self : AgentType, + constructor_value : @model.SchemaValue, +) -> ReflectedAgentClient raise ReflectError { + guard self.mode == Durable else { + raise Identity("phantom identities are unavailable for ephemeral agents") + } + let phantom_id = @apiHost.generate_idempotency_key() + self.resume_phantom_value(constructor_value, phantom_id) +} + +///| +pub fn AgentType::new_phantom_json( + self : AgentType, + constructor_json : Json, +) -> ReflectedAgentClient raise ReflectError { + self.new_phantom_value(self.constructor_input.pack_json(constructor_json)) +} + +///| +pub fn AgentType::ephemeral_value( + self : AgentType, + constructor_value : @model.SchemaValue, +) -> ReflectedAgentClient raise ReflectError { + guard self.mode == Ephemeral else { + raise Identity("ephemeral invocation is unavailable for durable agents") + } + self.client_value(constructor_value, None, None) +} + +///| +pub fn AgentType::ephemeral_json( + self : AgentType, + constructor_json : Json, +) -> ReflectedAgentClient raise ReflectError { + self.ephemeral_value(self.constructor_input.pack_json(constructor_json)) +} + +///| +fn ReflectedAgentClient::require_method( + self : ReflectedAgentClient, + name : String, +) -> AgentMethod raise ReflectError { + match self.agent_type.find_method(name) { + Some(entry) => entry + None => + raise Discovery( + "agent type '" + self.agent_type.name + "' has no method '" + name + "'", + ) + } +} + +///| +pub async fn ReflectedAgentClient::invoke_value( + self : ReflectedAgentClient, + method_name : String, + input : @model.SchemaValue, +) -> Invocation[@model.SchemaValue?] { + let entry = self.require_method(method_name) + let invocation = self.transport.invoke_value(method_name, input) + validate_invocation_output(entry, invocation) +} + +///| +pub async fn ReflectedAgentClient::invoke_json( + self : ReflectedAgentClient, + method_name : String, + input : Json, +) -> Invocation[Json?] { + let entry = self.require_method(method_name) + let invocation = self.transport.invoke_value( + method_name, + entry.input.pack_json(input), + ) + let value = match (entry.output, invocation.value) { + (None, None) => None + (Some(schema), Some(value)) => Some(schema.unpack_json(value)) + (None, Some(_)) => raise Schema("unit method returned a value") + (Some(_), None) => raise Schema("value-returning method returned unit") + } + { metadata: invocation.metadata, value, } +} + +///| +pub fn ReflectedAgentClient::trigger_value( + self : ReflectedAgentClient, + method_name : String, + input : @model.SchemaValue, +) -> InvocationMetadata raise ReflectError { + let entry = self.require_method(method_name) + reject_non_awaited_streams(entry, "trigger") + self.transport.trigger_value(method_name, input) +} + +///| +pub fn ReflectedAgentClient::trigger_json( + self : ReflectedAgentClient, + method_name : String, + input : Json, +) -> InvocationMetadata raise ReflectError { + let entry = self.require_method(method_name) + reject_non_awaited_streams(entry, "trigger") + self.transport.trigger_value(method_name, entry.input.pack_json(input)) +} + +///| +pub fn ReflectedAgentClient::schedule_value( + self : ReflectedAgentClient, + scheduled_at : @systemClock.Instant, + method_name : String, + input : @model.SchemaValue, +) -> ScheduledInvocation raise ReflectError { + let entry = self.require_method(method_name) + reject_non_awaited_streams(entry, "schedule") + self.transport.schedule_value(scheduled_at, method_name, input) +} + +///| +pub fn ReflectedAgentClient::schedule_json( + self : ReflectedAgentClient, + scheduled_at : @systemClock.Instant, + method_name : String, + input : Json, +) -> ScheduledInvocation raise ReflectError { + let entry = self.require_method(method_name) + reject_non_awaited_streams(entry, "schedule") + self.transport.schedule_value( + scheduled_at, + method_name, + entry.input.pack_json(input), + ) +} + +///| +fn reject_non_awaited_streams( + entry : AgentMethod, + operation : String, +) -> Unit raise ReflectError { + let output_contains_stream = match entry.output { + Some(output) => output.contains_stream() + None => false + } + guard !entry.input.contains_stream() && !output_contains_stream else { + raise Schema( + operation + " is unavailable for streaming method '" + entry.name + "'", + ) + } +} + +///| +fn validate_invocation_output( + entry : AgentMethod, + invocation : Invocation[@model.SchemaValue?], +) -> Invocation[@model.SchemaValue?] raise ReflectError { + match (entry.output, invocation.value) { + (None, None) | (Some(_), Some(_)) => invocation + (None, Some(_)) => raise Schema("unit method returned a value") + (Some(_), None) => raise Schema("single-output method returned no value") + } +} + +///| +pub fn ReflectedAgentClient::drop(self : ReflectedAgentClient) -> Unit { + self.transport.drop() +} diff --git a/sdks/moonbit/golem_sdk/reflection/schema_ref.mbt b/sdks/moonbit/golem_sdk/reflection/schema_ref.mbt new file mode 100644 index 0000000000..91ae3fb466 --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/schema_ref.mbt @@ -0,0 +1,646 @@ +///| +/// A graph-backed view of one reflected schema root. +pub(all) struct SchemaRef { + graph : @model.SchemaGraph + root : @model.SchemaType +} derive(Debug, Eq) + +///| +pub fn SchemaRef::new(graph : @model.SchemaGraph) -> SchemaRef { + { root: graph.root, graph, } +} + +///| +/// Reports whether this schema root contains a live stream, following named +/// references without looping on recursive definitions. +pub fn SchemaRef::contains_stream(self : SchemaRef) -> Bool { + self.type_contains_stream(self.root, Map([])) +} + +///| +fn SchemaRef::type_contains_stream( + self : SchemaRef, + schema : @model.SchemaType, + visited : Map[String, Unit], +) -> Bool { + match schema.body { + Stream(_) => true + Ref(id) => + if visited.contains(id) { + false + } else { + visited[id] = () + match self.graph.defs.iter().find_first(def => def.id == id) { + Some(def) => self.type_contains_stream(def.body, visited) + None => false + } + } + Record(fields) => + fields.any(field => self.type_contains_stream(field.body, visited)) + Variant(cases) => + cases.any(case => { + match case.payload { + Some(payload) => self.type_contains_stream(payload, visited) + None => false + } + }) + Tuple(elements) => + elements.any(element => self.type_contains_stream(element, visited)) + List(element) + | FixedList(element, _) + | Option(element) + | Secret({ inner: element, .. }) => + self.type_contains_stream(element, visited) + Map(key, value) => + self.type_contains_stream(key, visited) || + self.type_contains_stream(value, visited) + Result(ok, err) => { + let ok_contains = match ok { + Some(element) => self.type_contains_stream(element, visited) + None => false + } + let err_contains = match err { + Some(element) => self.type_contains_stream(element, visited) + None => false + } + ok_contains || err_contains + } + Union(branches) => + branches.any(branch => self.type_contains_stream(branch.body, visited)) + Future(inner) => + match inner { + Some(element) => self.type_contains_stream(element, visited) + None => false + } + _ => false + } +} + +///| +fn SchemaRef::resolve( + self : SchemaRef, + schema : @model.SchemaType, +) -> @model.SchemaType raise ReflectError { + match schema.body { + Ref(id) => + match self.graph.defs.iter().find_first(def => def.id == id) { + Some(def) => self.resolve(def.body) + None => raise Schema("dangling schema reference '" + id + "'") + } + _ => schema + } +} + +///| +fn json_object(value : Json) -> Map[String, Json] raise ReflectError { + match value { + Object(fields) => fields + _ => raise Json("expected a JSON object") + } +} + +///| +fn json_array(value : Json) -> Array[Json] raise ReflectError { + match value { + Array(values) => values + _ => raise Json("expected a JSON array") + } +} + +///| +fn json_string(value : Json) -> String raise ReflectError { + match value { + String(value) => value + _ => raise Json("expected a JSON string") + } +} + +///| +fn json_number(value : Json) -> Double raise ReflectError { + match value { + Number(value, ..) => value + _ => raise Json("expected a JSON number") + } +} + +///| +fn json_integer( + value : Json, + minimum : Double, + maximum : Double, +) -> Double raise ReflectError { + let value = json_number(value) + guard !value.is_nan() && !value.is_inf() && value == value.trunc() else { + raise Json("expected a finite integer") + } + guard value >= minimum && value <= maximum else { + raise Json("integer is outside the supported range") + } + value +} + +///| +fn required_field( + fields : Map[String, Json], + name : String, +) -> Json raise ReflectError { + match fields.get(name) { + Some(value) => value + None => raise Json("missing field '" + name + "'") + } +} + +///| +fn find_string_index(values : Array[String], expected : String) -> Int? { + for index in 0.. Int? { + for index in 0.. Bool raise ReflectError { + match rule { + Prefix(prefix) => + match json { + String(value) => value.has_prefix(prefix) + _ => false + } + Suffix(suffix) => + match json { + String(value) => value.has_suffix(suffix) + _ => false + } + Contains(part) => + match json { + String(value) => value.contains(part) + _ => false + } + Regex(pattern) => + match json { + String(value) => { + let regex = @string.Regex::Regex(pattern) catch { + error => + raise Json("invalid union discriminator regex: \{repr(error)}") + } + regex.execute(value) is Some(_) + } + _ => false + } + FieldEquals(expected) => + match json { + Object(fields) => + match fields.get(expected.field_name) { + Some(String(value)) => + match expected.literal { + Some(literal) => value == literal + None => true + } + Some(_) => expected.literal is None + None => false + } + _ => false + } + FieldAbsent(name) => + match json { + Object(fields) => !fields.contains(name) + _ => false + } + } +} + +///| +pub fn SchemaRef::pack_json( + self : SchemaRef, + value : Json, +) -> @model.SchemaValue raise ReflectError { + self.pack(self.resolve(self.root), value) +} + +///| +pub fn SchemaRef::unpack_json( + self : SchemaRef, + value : @model.SchemaValue, +) -> Json raise ReflectError { + self.unpack(self.resolve(self.root), value) +} + +///| +fn SchemaRef::unpack( + self : SchemaRef, + schema : @model.SchemaType, + value : @model.SchemaValue, +) -> Json raise ReflectError { + match (schema.body, value) { + (@model.SchemaTypeBody::Bool, @model.SchemaValue::Bool(value)) => + Json::boolean(value) + (@model.SchemaTypeBody::S8(_), @model.SchemaValue::S8(value)) + | (@model.SchemaTypeBody::S16(_), @model.SchemaValue::S16(value)) + | (@model.SchemaTypeBody::S32(_), @model.SchemaValue::S32(value)) => + Json::number(value.to_double()) + (@model.SchemaTypeBody::S64(_), @model.SchemaValue::S64(value)) => + Json::number(value.to_double()) + (@model.SchemaTypeBody::U8(_), @model.SchemaValue::U8(value)) => + Json::number(value.to_int().to_double()) + (@model.SchemaTypeBody::U16(_), @model.SchemaValue::U16(value)) + | (@model.SchemaTypeBody::U32(_), @model.SchemaValue::U32(value)) => + Json::number(value.reinterpret_as_int().to_double()) + (@model.SchemaTypeBody::U64(_), @model.SchemaValue::U64(value)) => + Json::number(value.to_double()) + (@model.SchemaTypeBody::F32(_), @model.SchemaValue::F32(value)) => + Json::number(value.to_double()) + (@model.SchemaTypeBody::F64(_), @model.SchemaValue::F64(value)) => + Json::number(value) + (@model.SchemaTypeBody::Char, @model.SchemaValue::Char(value)) => + Json::string(value.to_string()) + (@model.SchemaTypeBody::String, @model.SchemaValue::String(value)) => + Json::string(value) + (@model.SchemaTypeBody::Record(expected), @model.SchemaValue::Record(values) + ) => { + guard values.length() == expected.length() else { + raise Schema("record value length does not match schema") + } + let fields : Map[String, Json] = Map([]) + for index in 0.. { + guard values.length() == expected.length() else { + raise Schema("tuple value length does not match schema") + } + let result : Array[Json] = [] + for index in 0.. { + let result : Array[Json] = [] + for entry in values { + result.push(self.unpack(self.resolve(element), entry)) + } + Json::array(result) + } + (@model.SchemaTypeBody::Option(_), @model.SchemaValue::Option(None)) => + Json::null() + ( + @model.SchemaTypeBody::Option(element), + @model.SchemaValue::Option(Some(value)), + ) => self.unpack(self.resolve(element), value) + (@model.SchemaTypeBody::Enum(cases), @model.SchemaValue::Enum(index)) => { + let index = index.reinterpret_as_int() + guard index >= 0 && index < cases.length() else { + raise Schema("enum case index is outside the schema") + } + Json::string(cases[index]) + } + (@model.SchemaTypeBody::Flags(names), @model.SchemaValue::Flags(enabled)) => { + guard names.length() == enabled.length() else { + raise Schema("flags value length does not match schema") + } + let result : Array[Json] = [] + for index in 0.. { + let index = index.reinterpret_as_int() + guard index >= 0 && index < cases.length() else { + raise Schema("variant case index is outside the schema") + } + let entry = cases[index] + match (entry.payload, payload) { + (None, None) => Json::string(entry.name) + (Some(schema), Some(value)) => { + let fields : Map[String, Json] = Map([]) + fields[entry.name] = self.unpack(self.resolve(schema), value) + Json::object(fields) + } + _ => raise Schema("variant payload does not match schema") + } + } + (@model.SchemaTypeBody::Map(key, entry), @model.SchemaValue::Map(values)) => { + let result : Array[Json] = [] + for value in values { + result.push( + Json::array([ + self.unpack(self.resolve(key), value.key), + self.unpack(self.resolve(entry), value.value), + ]), + ) + } + Json::array(result) + } + (@model.SchemaTypeBody::Result(ok, _), @model.SchemaValue::ResultOk(payload) + ) => + Json::object({ + "ok": ( + match (ok, payload) { + (None, None) => Json::null() + (Some(schema), Some(value)) => + self.unpack(self.resolve(schema), value) + _ => raise Schema("result ok payload does not match schema") + } : Json), + }) + ( + @model.SchemaTypeBody::Result(_, err), + @model.SchemaValue::ResultErr(payload), + ) => + Json::object({ + "err": ( + match (err, payload) { + (None, None) => Json::null() + (Some(schema), Some(value)) => + self.unpack(self.resolve(schema), value) + _ => raise Schema("result err payload does not match schema") + } : Json), + }) + (@model.SchemaTypeBody::Text(_), @model.SchemaValue::Text(text, language)) => { + let fields : Map[String, Json] = { "text": Json::string(text) } + match language { + Some(language) => fields["language"] = Json::string(language) + None => () + } + Json::object(fields) + } + (@model.SchemaTypeBody::Path(_), @model.SchemaValue::Path(value)) + | (@model.SchemaTypeBody::Url(_), @model.SchemaValue::Url(value)) => + Json::string(value) + ( + @model.SchemaTypeBody::Union(branches), + @model.SchemaValue::Union(tag, value), + ) => + match branches.iter().find_first(branch => branch.tag == tag) { + Some(branch) => self.unpack(self.resolve(branch.body), value) + None => raise Schema("union tag '" + tag + "' is outside the schema") + } + (@model.SchemaTypeBody::Binary(_), @model.SchemaValue::Binary(_, _)) + | (@model.SchemaTypeBody::Datetime, @model.SchemaValue::Datetime(_)) + | (@model.SchemaTypeBody::Duration, @model.SchemaValue::Duration(_)) + | (@model.SchemaTypeBody::Quantity(_), @model.SchemaValue::Quantity(_)) => + raise Json("this rich schema type is not yet supported by the JSON codec") + (@model.SchemaTypeBody::Secret(_), @model.SchemaValue::Secret(_)) + | (@model.SchemaTypeBody::QuotaToken(_), @model.SchemaValue::QuotaToken(_)) + | ( + @model.SchemaTypeBody::PermissionCard(_), + @model.SchemaValue::PermissionCard(_), + ) => raise Json("capability values have no JSON representation") + (@model.SchemaTypeBody::Future(_), _) + | (@model.SchemaTypeBody::Stream(_), _) => + raise Json("future and stream values have no JSON representation") + (@model.SchemaTypeBody::Ref(_), _) => + raise Schema("unresolved schema reference") + _ => raise Schema("schema value does not match the reflected schema") + } +} + +///| +fn SchemaRef::pack( + self : SchemaRef, + schema : @model.SchemaType, + json : Json, +) -> @model.SchemaValue raise ReflectError { + match schema.body { + Bool => + match json { + True => Bool(true) + False => Bool(false) + _ => raise Json("expected a JSON boolean") + } + S8(_) => S8(json_integer(json, -128.0, 127.0).to_int()) + S16(_) => S16(json_integer(json, -32768.0, 32767.0).to_int()) + S32(_) => S32(json_integer(json, -2147483648.0, 2147483647.0).to_int()) + S64(_) => + S64( + json_integer(json, -9007199254740991.0, 9007199254740991.0).to_int64(), + ) + U8(_) => U8(json_integer(json, 0.0, 255.0).to_uint().to_byte()) + U16(_) => U16(json_integer(json, 0.0, 65535.0).to_uint()) + U32(_) => U32(json_integer(json, 0.0, 4294967295.0).to_uint()) + U64(_) => U64(json_integer(json, 0.0, 9007199254740991.0).to_uint64()) + F32(_) => { + let value = json_number(json) + guard !value.is_nan() && !value.is_inf() else { + raise Json("expected a finite number") + } + F32(Float::from_double(value)) + } + F64(_) => { + let value = json_number(json) + guard !value.is_nan() && !value.is_inf() else { + raise Json("expected a finite number") + } + F64(value) + } + Char => { + let text = json_string(json) + guard text.char_length() == 1 else { + raise Json("expected one character") + } + Char(text.get_char(0).unwrap()) + } + String => String(json_string(json)) + Record(expected) => { + let fields = json_object(json) + for item in fields { + let (name, _) = item + guard expected.any(field => field.name == name) else { + raise Json("unknown field '" + name + "'") + } + } + let values = expected.map(field => { + self.pack(self.resolve(field.body), required_field(fields, field.name)) + }) + Record(values) + } + Tuple(expected) => { + let values = json_array(json) + guard values.length() == expected.length() else { + raise Json("tuple length does not match schema") + } + let packed : Array[@model.SchemaValue] = [] + for index in 0.. + List( + json_array(json).map(value => self.pack(self.resolve(element), value)), + ) + FixedList(element, length) => { + let values = json_array(json) + guard values.length() == length.reinterpret_as_int() else { + raise Json("fixed-list length does not match schema") + } + FixedList(values.map(value => self.pack(self.resolve(element), value))) + } + Option(element) => + match json { + Null => Option(None) + value => Option(Some(self.pack(self.resolve(element), value))) + } + Enum(cases) => { + let name = json_string(json) + match find_string_index(cases, name) { + Some(index) => Enum(index.reinterpret_as_uint()) + None => raise Json("unknown enum case '" + name + "'") + } + } + Flags(names) => { + let requested_json = json_array(json) + let requested : Array[String] = [] + for entry in requested_json { + let name = json_string(entry) + guard names.any(expected => expected == name) else { + raise Json("unknown flag '" + name + "'") + } + guard !requested.any(existing => existing == name) else { + raise Json("duplicate flag '" + name + "'") + } + requested.push(name) + } + Flags(names.map(name => requested.any(requested => requested == name))) + } + Variant(cases) => + match json { + String(name) => + match find_variant_index(cases, name) { + Some(index) => + if cases[index].payload is None { + Variant(index.reinterpret_as_uint(), None) + } else { + raise Json("variant case '" + name + "' requires a payload") + } + None => + raise Json("unknown payload-free variant case '" + name + "'") + } + Object(fields) => { + guard fields.length() == 1 else { + raise Json("expected a single-key variant object") + } + let (name, payload_json) = fields.iter().next().unwrap() + match find_variant_index(cases, name) { + Some(index) => + match cases[index].payload { + Some(payload) => + Variant( + index.reinterpret_as_uint(), + Some(self.pack(self.resolve(payload), payload_json)), + ) + None => raise Json("variant case '" + name + "' has no payload") + } + None => raise Json("unknown payload variant case '" + name + "'") + } + } + _ => raise Json("expected a variant string or object") + } + Map(key, entry) => + Map( + json_array(json).map(item => { + let pair = json_array(item) + guard pair.length() == 2 else { + raise Json("expected a two-element map entry") + } + { + key: self.pack(self.resolve(key), pair[0]), + value: self.pack(self.resolve(entry), pair[1]), + } + }), + ) + Result(ok, err) => { + let fields = json_object(json) + guard fields.length() == 1 else { + raise Json("expected exactly one 'ok' or 'err' result field") + } + if fields.get("ok") is Some(payload) { + ResultOk( + match ok { + Some(schema) => Some(self.pack(self.resolve(schema), payload)) + None => + if payload is Null { + None + } else { + raise Json("expected null unit ok payload") + } + }, + ) + } else if fields.get("err") is Some(payload) { + ResultErr( + match err { + Some(schema) => Some(self.pack(self.resolve(schema), payload)) + None => + if payload is Null { + None + } else { + raise Json("expected null unit err payload") + } + }, + ) + } else { + raise Json("expected an 'ok' or 'err' result object") + } + } + Text(_) => { + let fields = json_object(json) + Text( + json_string(required_field(fields, "text")), + fields.get("language").map(json_string), + ) + } + Path(_) => Path(json_string(json)) + Url(_) => Url(json_string(json)) + Union(branches) => { + let matching = branches.filter(branch => { + discriminator_matches(branch.discriminator, json) + }) + guard matching.length() == 1 else { + raise Json( + "expected exactly one matching union branch, found \{matching.length()}", + ) + } + let branch = matching[0] + Union(branch.tag, self.pack(self.resolve(branch.body), json)) + } + Binary(_) | Datetime | Duration | Quantity(_) => + raise Json("this rich schema type is not yet supported by the JSON codec") + Secret(_) | QuotaToken(_) | PermissionCard(_) => + raise Json("capability values cannot be constructed from JSON") + Future(_) | Stream(_) => + raise Json("future and stream values have no JSON representation") + Ref(_) => raise Schema("unresolved schema reference") + } +} diff --git a/sdks/moonbit/golem_sdk/reflection/schema_ref_wbtest.mbt b/sdks/moonbit/golem_sdk/reflection/schema_ref_wbtest.mbt new file mode 100644 index 0000000000..ed0c7dbedc --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/schema_ref_wbtest.mbt @@ -0,0 +1,138 @@ +///| +fn test_schema(body : @model.SchemaTypeBody) -> SchemaRef { + SchemaRef::new({ defs: [], root: @model.schema_type(body), }) +} + +///| +test "record JSON round-trips through reflected SchemaValue" { + let metadata = @model.empty_metadata() + let schema = test_schema( + Record([ + { name: "message", body: @model.schema_type(String), metadata, }, + { name: "count", body: @model.schema_type(U32(None)), metadata, }, + ]), + ) + let input = Json::object({ + "message": Json::string("hello"), + "count": Json::number(3.0), + }) + assert_eq(schema.unpack_json(schema.pack_json(input)), input) +} + +///| +test "flags JSON uses names while SchemaValue uses positions" { + let schema = test_schema(Flags(["read", "write", "admin"])) + let input = Json::array([Json::string("write"), Json::string("admin")]) + assert_eq( + schema.pack_json(input), + @model.SchemaValue::Flags([false, true, true]), + ) + assert_eq(schema.unpack_json(schema.pack_json(input)), input) +} + +///| +test "record JSON rejects unknown fields" { + let schema = test_schema(Record([])) + try schema.pack_json(Json::object({ "extra": Json::number(1.0) })) catch { + _ => () + } noraise { + _ => fail("expected unknown field to be rejected") + } +} + +///| +test "stream detection follows nested and recursive definitions" { + let metadata = @model.empty_metadata() + let schema = SchemaRef::new({ + defs: [ + { + id: "recursive", + name: None, + body: @model.schema_type( + Record([ + { + name: "next", + body: @model.schema_type(Ref("recursive")), + metadata, + }, + { + name: "events", + body: @model.schema_type(Stream(Some(@model.schema_type(String)))), + metadata, + }, + ]), + ), + }, + ], + root: @model.schema_type(Ref("recursive")), + }) + assert_true(schema.contains_stream()) + assert_false(test_schema(List(@model.schema_type(String))).contains_stream()) +} + +///| +fn test_invocation( + value : @model.SchemaValue?, +) -> Invocation[@model.SchemaValue?] { + { + metadata: { + agent_id: { value: "test-agent", }, + idempotency_key: "test-key", + }, + value, + } +} + +///| +test "reflected output validation rejects missing and unexpected values" { + let unit_method : AgentMethod = { + name: "unit", + description: "", + prompt_hint: None, + input: test_schema(Record([])), + output: None, + } + let value_method = { + ..unit_method, + name: "value", + output: Some(test_schema(String)), + } + try validate_invocation_output(value_method, test_invocation(None)) catch { + Schema(message) => + assert_eq(message, "single-output method returned no value") + error => fail("unexpected error: \{repr(error)}") + } noraise { + _ => fail("expected a missing output to be rejected") + } + try + validate_invocation_output( + unit_method, + test_invocation(Some(@model.SchemaValue::String("unexpected"))), + ) + catch { + Schema(message) => assert_eq(message, "unit method returned a value") + error => fail("unexpected error: \{repr(error)}") + } noraise { + _ => fail("expected an unexpected output to be rejected") + } +} + +///| +test "non-awaited reflected methods reject nested streams" { + let entry : AgentMethod = { + name: "streaming", + description: "", + prompt_hint: None, + input: test_schema(Record([])), + output: Some(test_schema(List(@model.schema_type(Stream(None))))), + } + try reject_non_awaited_streams(entry, "trigger") catch { + Schema(message) => + assert_eq( + message, "trigger is unavailable for streaming method 'streaming'", + ) + error => fail("unexpected error: \{repr(error)}") + } noraise { + _ => fail("expected a streaming method to be rejected") + } +} diff --git a/sdks/moonbit/golem_sdk/reflection/transport.mbt b/sdks/moonbit/golem_sdk/reflection/transport.mbt new file mode 100644 index 0000000000..c17f7cb1b8 --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/transport.mbt @@ -0,0 +1,109 @@ +///| +priv struct Transport { + raw : @agentHost.WasmRpc +} + +///| +fn Transport::create( + type_name : String, + constructor_value : @model.SchemaValue, + phantom_id : @types.Uuid?, +) -> Transport raise ReflectError { + let constructor_input = @model.schema_value_to_wit(constructor_value) catch { + error => raise Schema("failed to encode constructor value: \{repr(error)}") + } + match + @agentHost.WasmRpc::create(type_name, constructor_input, phantom_id, []) { + Ok(raw) => { raw, } + Err(error) => raise rpc_error(error) + } +} + +///| +fn invocation_metadata( + metadata : @agentHost.InvocationMetadata, +) -> InvocationMetadata { + { + agent_id: { value: metadata.agent_id, }, + idempotency_key: metadata.idempotency_key, + } +} + +///| +async fn Transport::invoke_value( + self : Transport, + method_name : String, + input : @model.SchemaValue, +) -> Invocation[@model.SchemaValue?] { + let wire = @model.schema_value_to_wit(input) catch { + error => raise Schema("failed to encode invocation input: \{repr(error)}") + } + let pending = self.raw.async_invoke_and_await(method_name, wire, None) + defer pending.future.drop() + let result = { + errdefer pending.future.cancel() + pending.future.get() + } + match result { + Ok(output) => { + let value = match output { + Some(output) => { + let decoded = @model_host.schema_value_from_wit(output) catch { + error => + raise Schema("failed to decode invocation output: \{repr(error)}") + } + Some(decoded) + } + None => None + } + { metadata: invocation_metadata(pending.metadata), value, } + } + Err(error) => raise rpc_error(error) + } +} + +///| +fn Transport::trigger_value( + self : Transport, + method_name : String, + input : @model.SchemaValue, +) -> InvocationMetadata raise ReflectError { + let wire = @model.schema_value_to_wit(input) catch { + error => raise Schema("failed to encode invocation input: \{repr(error)}") + } + match self.raw.invoke(method_name, wire, None) { + Ok(metadata) => invocation_metadata(metadata) + Err(error) => raise rpc_error(error) + } +} + +///| +fn Transport::schedule_value( + self : Transport, + scheduled_at : @systemClock.Instant, + method_name : String, + input : @model.SchemaValue, +) -> ScheduledInvocation raise ReflectError { + let wire = @model.schema_value_to_wit(input) catch { + error => raise Schema("failed to encode invocation input: \{repr(error)}") + } + match + self.raw.schedule_cancelable_invocation( + scheduled_at, + method_name, + wire, + None, + ) { + Ok(receipt) => + { + metadata: invocation_metadata(receipt.metadata), + cancellation_token: receipt.cancellation_token, + } + Err(error) => raise rpc_error(error) + } +} + +///| +fn Transport::drop(self : Transport) -> Unit { + self.raw.drop() +} diff --git a/sdks/moonbit/golem_sdk/reflection/types.mbt b/sdks/moonbit/golem_sdk/reflection/types.mbt new file mode 100644 index 0000000000..b4c1c26488 --- /dev/null +++ b/sdks/moonbit/golem_sdk/reflection/types.mbt @@ -0,0 +1,88 @@ +///| +/// Failure reported while discovering, packing, or invoking an agent through +/// the reflection APIs. +pub(all) suberror ReflectError { + Discovery(String) + Identity(String) + Schema(String) + Json(String) + Remote(String) +} derive(Debug, Eq) + +///| +pub(all) enum AgentMode { + Durable + Ephemeral +} derive(Debug, Eq) + +///| +/// A reusable agent identity. Ephemeral invocation addresses do not have one +/// before invocation; their final identity is returned in invocation metadata. +pub(all) struct ParsedAgentId { + value : String +} derive(Debug, Eq) + +///| +pub(all) struct ParsedAgentIdParts { + type_name : String + constructor_value : @model.SchemaValue + phantom_id : @types.Uuid? +} derive(Debug, Eq) + +///| +pub(all) struct InvocationMetadata { + agent_id : ParsedAgentId + idempotency_key : String +} derive(Debug, Eq) + +///| +pub(all) struct Invocation[T] { + metadata : InvocationMetadata + value : T +} derive(Debug, Eq) + +///| +pub(all) struct ScheduledInvocation { + metadata : InvocationMetadata + cancellation_token : @agentHost.CancellationToken +} + +///| +/// Both identities produced when attempting to create a durable phantom. +pub(all) struct CreatedPhantomClient { + agent_id : ParsedAgentId + phantom_id : @types.Uuid + client : DynamicAgentClient +} + +///| +pub fn ScheduledInvocation::cancel(self : ScheduledInvocation) -> Unit { + self.cancellation_token.cancel() +} + +///| +pub fn ScheduledInvocation::drop(self : ScheduledInvocation) -> Unit { + self.cancellation_token.drop() +} + +///| +fn agent_error_message(error : @common.AgentError) -> String { + match error { + InvalidInput(message) => "invalid input: " + message + InvalidMethod(message) => "invalid method: " + message + InvalidType(message) => "invalid type: " + message + InvalidAgentId(message) => "invalid agent id: " + message + CustomError(_) => "custom remote agent error" + } +} + +///| +fn rpc_error(error : @agentHost.RpcError) -> ReflectError { + match error { + ProtocolError(message) => Remote("RPC protocol error: " + message) + Denied(message) => Remote("RPC denied: " + message) + NotFound(message) => Remote("RPC target not found: " + message) + RemoteInternalError(message) => Remote("remote internal error: " + message) + RemoteAgentError(error) => Remote(agent_error_message(error)) + } +} diff --git a/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/golem_tool_clients.mbt b/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/golem_tool_clients.mbt index 33865ded76..ec12280f8c 100644 --- a/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/golem_tool_clients.mbt +++ b/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/golem_tool_clients.mbt @@ -31,25 +31,33 @@ pub fn MoonbitStreamingClient::stream( let __golem_def = __golem_tool_def_MoonBitStreaming() let __golem_index = match __golem_def.command_index_by_path(["stream"]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = [] __golem_values.push(("mode", @schema.to_value_as(mode))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.start(["stream"], __golem_input, Some(stdin), true, fn(_) { - Err("remote custom tool error is not declared by this client") - }) { + match self + .client + .start( + ["stream"], __golem_input, Some(stdin), true, fn(_) { + Err("remote custom tool error is not declared by this client") + }, + ) { Err(__golem_error) => Err(__golem_error) Ok(__golem_invocation) => @tool.typed_invocation(__golem_invocation, @tool.decode_result_value) @@ -92,14 +100,17 @@ pub fn CanonicalGrepClient::canonical_grep( let __golem_def = __golem_tool_def_CanonicalGrep() let __golem_index = match __golem_def.command_index_by_path([]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = [] @@ -109,13 +120,18 @@ pub fn CanonicalGrepClient::canonical_grep( __golem_values.push(("extra-patterns", @schema.to_value_as(extra_patterns))) __golem_values.push(("max-count", @schema.to_value_as(max_count))) __golem_values.push(("files", @schema.to_value_as(files))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.start([], __golem_input, Some(stdin), true, fn(__golem_value) { - CanonicalGrepError::from_error_payload_value(__golem_value) - }) { + match self + .client + .start( + [], __golem_input, Some(stdin), true, fn(__golem_value) { + CanonicalGrepError::from_error_payload_value(__golem_value) + }, + ) { Err(__golem_error) => Err(__golem_error) Ok(__golem_invocation) => @tool.typed_invocation(__golem_invocation, @tool.decode_result_value) @@ -135,14 +151,17 @@ pub async fn CanonicalGrepClient::replace( let __golem_def = __golem_tool_def_CanonicalGrep() let __golem_index = match __golem_def.command_index_by_path(["replace"]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = [] @@ -151,11 +170,14 @@ pub async fn CanonicalGrepClient::replace( __golem_values.push(("pattern", @schema.to_value_as(pattern))) __golem_values.push(("replacement", @schema.to_value_as(replacement))) __golem_values.push(("files", @schema.to_value_as(files))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.invoke_and_await_tool_error(["replace"], __golem_input, None) { + match self + .client + .invoke_and_await_tool_error(["replace"], __golem_input, None) { Err(__golem_error) => Err(__golem_error) Ok(__golem_result) => @tool.decode_result_value(__golem_result) } @@ -197,14 +219,17 @@ pub async fn CanonicalGitClient::commit( let __golem_def = __golem_tool_def_CanonicalGit() let __golem_index = match __golem_def.command_index_by_path(["commit"]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = [] @@ -218,11 +243,12 @@ pub async fn CanonicalGitClient::commit( __golem_values.push(("signoff", @schema.to_value_as(signoff))) __golem_values.push(("reset-author", @schema.to_value_as(reset_author))) __golem_values.push(("output", @schema.to_value_as(output))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.invoke_and_await_tool_error(["commit"], __golem_input, None) { + match self.client.invoke_and_await_tool_error(["commit"], __golem_input, None) { Err(__golem_error) => Err(__golem_error) Ok(__golem_result) => @tool.decode_result_value(__golem_result) } @@ -255,7 +281,7 @@ pub fn CanonicalGitClient::remote( __golem_prefix.push(("git-dir", @schema.to_value_as(git_dir))) __golem_prefix.push(("paginate", @schema.to_value_as(paginate))) __golem_prefix.push(("config", @schema.to_value_as(config))) - { client: self.client, prefix: __golem_prefix, } + { client: self.client, prefix: __golem_prefix } } ///| @@ -270,17 +296,19 @@ pub async fn CanonicalGitRemoteClient::add( fetch : Bool, ) -> Result[Unit, @tool.ToolError[CanonicalRemoteError]] { let __golem_def = __golem_tool_def_CanonicalGit() - let __golem_index = match - __golem_def.command_index_by_path(["remote", "add"]) { + let __golem_index = match __golem_def.command_index_by_path(["remote", "add"]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = self.prefix.copy() @@ -290,15 +318,14 @@ pub async fn CanonicalGitRemoteClient::add( __golem_values.push(("master", @schema.to_value_as(master))) __golem_values.push(("tags", @schema.to_value_as(tags))) __golem_values.push(("fetch", @schema.to_value_as(fetch))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.invoke_and_await_tool_error( - ["remote", "add"], - __golem_input, - None, - ) { + match self + .client + .invoke_and_await_tool_error(["remote", "add"], __golem_input, None) { Err(__golem_error) => Err(__golem_error) Ok(__golem_result) => @tool.decode_result_empty(__golem_result) } @@ -311,30 +338,32 @@ pub async fn CanonicalGitRemoteClient::remove( name : String, ) -> Result[Unit, @tool.ToolError[CanonicalRemoteError]] { let __golem_def = __golem_tool_def_CanonicalGit() - let __golem_index = match - __golem_def.command_index_by_path(["remote", "remove"]) { - Some(__golem_index) => __golem_index - None => - return Err( - @tool.tool_protocol_error( - "generated command path is missing from descriptor", - ), - ) - } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_index = + match __golem_def.command_index_by_path(["remote", "remove"]) { + Some(__golem_index) => __golem_index + None => { + return Err( + @tool.tool_protocol_error( + "generated command path is missing from descriptor", + ), + ) + } + } + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = self.prefix.copy() __golem_values.push(("name", @schema.to_value_as(name))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.invoke_and_await_tool_error( - ["remote", "remove"], - __golem_input, - None, - ) { + match self + .client + .invoke_and_await_tool_error(["remote", "remove"], __golem_input, None) { Err(__golem_error) => Err(__golem_error) Ok(__golem_result) => @tool.decode_result_empty(__golem_result) } @@ -352,17 +381,20 @@ pub async fn CanonicalGitRemoteClient::set_url( delete : Bool, ) -> Result[Unit, @tool.ToolError[CanonicalSetUrlError]] { let __golem_def = __golem_tool_def_CanonicalGit() - let __golem_index = match - __golem_def.command_index_by_path(["remote", "set-url"]) { - Some(__golem_index) => __golem_index - None => - return Err( - @tool.tool_protocol_error( - "generated command path is missing from descriptor", - ), - ) - } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_index = + match __golem_def.command_index_by_path(["remote", "set-url"]) { + Some(__golem_index) => __golem_index + None => { + return Err( + @tool.tool_protocol_error( + "generated command path is missing from descriptor", + ), + ) + } + } + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = self.prefix.copy() @@ -372,15 +404,14 @@ pub async fn CanonicalGitRemoteClient::set_url( __golem_values.push(("push", @schema.to_value_as(push))) __golem_values.push(("add", @schema.to_value_as(add))) __golem_values.push(("delete", @schema.to_value_as(delete))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.invoke_and_await_tool_error( - ["remote", "set-url"], - __golem_input, - None, - ) { + match self + .client + .invoke_and_await_tool_error(["remote", "set-url"], __golem_input, None) { Err(__golem_error) => Err(__golem_error) Ok(__golem_result) => @tool.decode_result_empty(__golem_result) } @@ -409,7 +440,7 @@ pub fn CanonicalGitClient::stash( let __golem_prefix = [] __golem_prefix.push(("verbose", @schema.to_value_as(verbose))) __golem_prefix.push(("git-dir", @schema.to_value_as(git_dir))) - { client: self.client, prefix: __golem_prefix, } + { client: self.client, prefix: __golem_prefix } } ///| @@ -422,24 +453,28 @@ pub async fn CanonicalGitStashClient::stash( let __golem_def = __golem_tool_def_CanonicalGit() let __golem_index = match __golem_def.command_index_by_path(["stash"]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = self.prefix.copy() __golem_values.push(("message", @schema.to_value_as(message))) __golem_values.push(("keep-index", @schema.to_value_as(keep_index))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.invoke_and_await_tool_error(["stash"], __golem_input, None) { + match self.client.invoke_and_await_tool_error(["stash"], __golem_input, None) { Err(__golem_error) => Err(__golem_error) Ok(__golem_result) => @tool.decode_result_empty(__golem_result) } @@ -453,31 +488,32 @@ pub async fn CanonicalGitStashClient::pop( index : UInt?, ) -> Result[Unit, @tool.ToolError[CanonicalStashError]] { let __golem_def = __golem_tool_def_CanonicalGit() - let __golem_index = match - __golem_def.command_index_by_path(["stash", "pop"]) { + let __golem_index = match __golem_def.command_index_by_path(["stash", "pop"]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = self.prefix.copy() __golem_values.push(("name", @schema.to_value_as(name))) __golem_values.push(("index", @schema.to_value_as(index))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.invoke_and_await_tool_error( - ["stash", "pop"], - __golem_input, - None, - ) { + match self + .client + .invoke_and_await_tool_error(["stash", "pop"], __golem_input, None) { Err(__golem_error) => Err(__golem_error) Ok(__golem_result) => @tool.decode_result_empty(__golem_result) } @@ -491,31 +527,33 @@ pub async fn CanonicalGitStashClient::apply( index : UInt?, ) -> Result[Unit, @tool.ToolError[CanonicalStashError]] { let __golem_def = __golem_tool_def_CanonicalGit() - let __golem_index = match - __golem_def.command_index_by_path(["stash", "apply"]) { - Some(__golem_index) => __golem_index - None => - return Err( - @tool.tool_protocol_error( - "generated command path is missing from descriptor", - ), - ) - } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_index = + match __golem_def.command_index_by_path(["stash", "apply"]) { + Some(__golem_index) => __golem_index + None => { + return Err( + @tool.tool_protocol_error( + "generated command path is missing from descriptor", + ), + ) + } + } + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = self.prefix.copy() __golem_values.push(("name", @schema.to_value_as(name))) __golem_values.push(("index", @schema.to_value_as(index))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } - match - self.client.invoke_and_await_tool_error( - ["stash", "apply"], - __golem_input, - None, - ) { + match self + .client + .invoke_and_await_tool_error(["stash", "apply"], __golem_input, None) { Err(__golem_error) => Err(__golem_error) Ok(__golem_result) => @tool.decode_result_empty(__golem_result) } @@ -539,14 +577,17 @@ pub async fn CanonicalGitClient::log( let __golem_def = __golem_tool_def_CanonicalGit() let __golem_index = match __golem_def.command_index_by_path(["log"]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = [] @@ -560,7 +601,9 @@ pub async fn CanonicalGitClient::log( __golem_values.push(("oneline", @schema.to_value_as(oneline))) __golem_values.push(("graph", @schema.to_value_as(graph))) __golem_values.push(("paths", @schema.to_value_as(paths))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } match self.client.invoke_and_await_tool_error(["log"], __golem_input, None) { @@ -596,19 +639,24 @@ pub async fn CanonicalBigBoundClient::canonical_big_bound( let __golem_def = __golem_tool_def_CanonicalBigBound() let __golem_index = match __golem_def.command_index_by_path([]) { Some(__golem_index) => __golem_index - None => + None => { return Err( @tool.tool_protocol_error( "generated command path is missing from descriptor", ), ) + } } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } let __golem_values = [] __golem_values.push(("count", @schema.to_value_as(count))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ __golem_error => return Err(@tool.tool_protocol_error(repr(__golem_error))) } match self.client.invoke_and_await_tool_error([], __golem_input, None) { diff --git a/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/golem_tools.mbt b/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/golem_tools.mbt index b8e4f00349..8c6e9c5349 100644 --- a/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/golem_tools.mbt +++ b/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/golem_tools.mbt @@ -3,31 +3,35 @@ ///| /// #warnings("-unused_try") -pub impl @tool.ToolErrorSchema for CanonicalGrepError with fn error_cases() { - Ok([ - { - name: "invalid-pattern", - doc: { - summary: "The supplied pattern is not a valid regular expression.", - description: "", - examples: [], - }, - kind: @toolCommon.ErrorKind::USAGE_ERROR, - exit_code: 2, - payload: Some( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - ), - }, - { - name: "no-match", - doc: { summary: "No line matched.", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::RUNTIME_ERROR, - exit_code: 1, - payload: None, - }, - ]) catch { +pub impl @tool.ToolErrorSchema for CanonicalGrepError with error_cases() { + try { + Ok( + [ + { + name: "invalid-pattern", + doc: { + summary: "The supplied pattern is not a valid regular expression.", + description: "", + examples: [], + }, + kind: @toolCommon.ErrorKind::USAGE_ERROR, + exit_code: 2, + payload: Some( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + ), + }, + { + name: "no-match", + doc: { summary: "No line matched.", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::RUNTIME_ERROR, + exit_code: 1, + payload: None, + }, + ], + ) + } catch{ __golem_error => Err(@tool.ToolBuildError::schema_model(__golem_error.to_string())) } @@ -35,35 +39,43 @@ pub impl @tool.ToolErrorSchema for CanonicalGrepError with fn error_cases() { ///| /// -pub impl @tool.ToolErrorSchema for CanonicalGrepError with fn to_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalGrepError with to_error_payload_value( self, ) { match self { - InvalidPattern(reason~) => - Ok(@schema.try_into_typed_schema_value(reason)) catch { + InvalidPattern(reason~) => { + try { + Ok(@schema.try_into_typed_schema_value(reason)) + } catch{ __golem_error => Err(__golem_error.to_string()) } - NoMatch => - Ok(@schema.try_into_typed_schema_value(())) catch { + } + NoMatch => { + try { + Ok(@schema.try_into_typed_schema_value(())) + } catch{ __golem_error => Err(__golem_error.to_string()) } + } } } ///| /// -pub impl @tool.ToolErrorSchema for CanonicalGrepError with fn from_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalGrepError with from_error_payload_value( __golem_value, ) { - let __golem_decoded : String? = Some( - @schema.from_value_as(__golem_value.value), - ) catch { + let __golem_decoded :String? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { return Ok(InvalidPattern(reason=__golem_payload)) } - let __golem_decoded : Unit? = Some(@schema.from_value_as(__golem_value.value)) catch { + let __golem_decoded :Unit? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { @@ -82,34 +94,38 @@ extend CanonicalGrepError with @tool.ToolErrorSchema::{ ///| /// #warnings("-unused_try") -pub impl @tool.ToolErrorSchema for CanonicalCommitError with fn error_cases() { - Ok([ - { - name: "nothing-staged", - doc: { summary: "", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::RUNTIME_ERROR, - exit_code: 1, - payload: None, - }, - { - name: "dirty-merge", - doc: { summary: "", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::RUNTIME_ERROR, - exit_code: 128, - payload: None, - }, - { - name: "bad-author-format", - doc: { summary: "", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::USAGE_ERROR, - exit_code: 129, - payload: Some( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - ), - }, - ]) catch { +pub impl @tool.ToolErrorSchema for CanonicalCommitError with error_cases() { + try { + Ok( + [ + { + name: "nothing-staged", + doc: { summary: "", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::RUNTIME_ERROR, + exit_code: 1, + payload: None, + }, + { + name: "dirty-merge", + doc: { summary: "", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::RUNTIME_ERROR, + exit_code: 128, + payload: None, + }, + { + name: "bad-author-format", + doc: { summary: "", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::USAGE_ERROR, + exit_code: 129, + payload: Some( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + ), + }, + ], + ) + } catch{ __golem_error => Err(@tool.ToolBuildError::schema_model(__golem_error.to_string())) } @@ -117,45 +133,58 @@ pub impl @tool.ToolErrorSchema for CanonicalCommitError with fn error_cases() { ///| /// -pub impl @tool.ToolErrorSchema for CanonicalCommitError with fn to_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalCommitError with to_error_payload_value( self, ) { match self { - NothingStaged => - Ok(@schema.try_into_typed_schema_value(())) catch { + NothingStaged => { + try { + Ok(@schema.try_into_typed_schema_value(())) + } catch{ __golem_error => Err(__golem_error.to_string()) } - DirtyMerge => - Ok(@schema.try_into_typed_schema_value(())) catch { + } + DirtyMerge => { + try { + Ok(@schema.try_into_typed_schema_value(())) + } catch{ __golem_error => Err(__golem_error.to_string()) } - BadAuthorFormat(author~) => - Ok(@schema.try_into_typed_schema_value(author)) catch { + } + BadAuthorFormat(author~) => { + try { + Ok(@schema.try_into_typed_schema_value(author)) + } catch{ __golem_error => Err(__golem_error.to_string()) } + } } } ///| /// -pub impl @tool.ToolErrorSchema for CanonicalCommitError with fn from_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalCommitError with from_error_payload_value( __golem_value, ) { - let __golem_decoded : Unit? = Some(@schema.from_value_as(__golem_value.value)) catch { + let __golem_decoded :Unit? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { return Ok(NothingStaged) } - let __golem_decoded : Unit? = Some(@schema.from_value_as(__golem_value.value)) catch { + let __golem_decoded :Unit? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { return Ok(DirtyMerge) } - let __golem_decoded : String? = Some( - @schema.from_value_as(__golem_value.value), - ) catch { + let __golem_decoded :String? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { @@ -174,23 +203,27 @@ extend CanonicalCommitError with @tool.ToolErrorSchema::{ ///| /// #warnings("-unused_try") -pub impl @tool.ToolErrorSchema for CanonicalLogError with fn error_cases() { - Ok([ - { - name: "bad-revision", - doc: { summary: "", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::USAGE_ERROR, - exit_code: 128, - payload: None, - }, - { - name: "not-a-repository", - doc: { summary: "", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::USAGE_ERROR, - exit_code: 129, - payload: None, - }, - ]) catch { +pub impl @tool.ToolErrorSchema for CanonicalLogError with error_cases() { + try { + Ok( + [ + { + name: "bad-revision", + doc: { summary: "", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::USAGE_ERROR, + exit_code: 128, + payload: None, + }, + { + name: "not-a-repository", + doc: { summary: "", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::USAGE_ERROR, + exit_code: 129, + payload: None, + }, + ], + ) + } catch{ __golem_error => Err(@tool.ToolBuildError::schema_model(__golem_error.to_string())) } @@ -198,33 +231,43 @@ pub impl @tool.ToolErrorSchema for CanonicalLogError with fn error_cases() { ///| /// -pub impl @tool.ToolErrorSchema for CanonicalLogError with fn to_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalLogError with to_error_payload_value( self, ) { match self { - BadRevision => - Ok(@schema.try_into_typed_schema_value(())) catch { + BadRevision => { + try { + Ok(@schema.try_into_typed_schema_value(())) + } catch{ __golem_error => Err(__golem_error.to_string()) } - NotARepository => - Ok(@schema.try_into_typed_schema_value(())) catch { + } + NotARepository => { + try { + Ok(@schema.try_into_typed_schema_value(())) + } catch{ __golem_error => Err(__golem_error.to_string()) } + } } } ///| /// -pub impl @tool.ToolErrorSchema for CanonicalLogError with fn from_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalLogError with from_error_payload_value( __golem_value, ) { - let __golem_decoded : Unit? = Some(@schema.from_value_as(__golem_value.value)) catch { + let __golem_decoded :Unit? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { return Ok(BadRevision) } - let __golem_decoded : Unit? = Some(@schema.from_value_as(__golem_value.value)) catch { + let __golem_decoded :Unit? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { @@ -243,20 +286,24 @@ extend CanonicalLogError with @tool.ToolErrorSchema::{ ///| /// #warnings("-unused_try") -pub impl @tool.ToolErrorSchema for CanonicalRemoteError with fn error_cases() { - Ok([ - { - name: "no-such-remote", - doc: { summary: "", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::USAGE_ERROR, - exit_code: 128, - payload: Some( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - ), - }, - ]) catch { +pub impl @tool.ToolErrorSchema for CanonicalRemoteError with error_cases() { + try { + Ok( + [ + { + name: "no-such-remote", + doc: { summary: "", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::USAGE_ERROR, + exit_code: 128, + payload: Some( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + ), + }, + ], + ) + } catch{ __golem_error => Err(@tool.ToolBuildError::schema_model(__golem_error.to_string())) } @@ -264,25 +311,28 @@ pub impl @tool.ToolErrorSchema for CanonicalRemoteError with fn error_cases() { ///| /// -pub impl @tool.ToolErrorSchema for CanonicalRemoteError with fn to_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalRemoteError with to_error_payload_value( self, ) { match self { - NoSuchRemote(name~) => - Ok(@schema.try_into_typed_schema_value(name)) catch { + NoSuchRemote(name~) => { + try { + Ok(@schema.try_into_typed_schema_value(name)) + } catch{ __golem_error => Err(__golem_error.to_string()) } + } } } ///| /// -pub impl @tool.ToolErrorSchema for CanonicalRemoteError with fn from_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalRemoteError with from_error_payload_value( __golem_value, ) { - let __golem_decoded : String? = Some( - @schema.from_value_as(__golem_value.value), - ) catch { + let __golem_decoded :String? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { @@ -301,20 +351,24 @@ extend CanonicalRemoteError with @tool.ToolErrorSchema::{ ///| /// #warnings("-unused_try") -pub impl @tool.ToolErrorSchema for CanonicalSetUrlError with fn error_cases() { - Ok([ - { - name: "failed", - doc: { summary: "", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::RUNTIME_ERROR, - exit_code: 1, - payload: Some( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - ), - }, - ]) catch { +pub impl @tool.ToolErrorSchema for CanonicalSetUrlError with error_cases() { + try { + Ok( + [ + { + name: "failed", + doc: { summary: "", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::RUNTIME_ERROR, + exit_code: 1, + payload: Some( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + ), + }, + ], + ) + } catch{ __golem_error => Err(@tool.ToolBuildError::schema_model(__golem_error.to_string())) } @@ -322,25 +376,28 @@ pub impl @tool.ToolErrorSchema for CanonicalSetUrlError with fn error_cases() { ///| /// -pub impl @tool.ToolErrorSchema for CanonicalSetUrlError with fn to_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalSetUrlError with to_error_payload_value( self, ) { match self { - Failed(__golem_payload) => - Ok(@schema.try_into_typed_schema_value(__golem_payload)) catch { + Failed(__golem_payload) => { + try { + Ok(@schema.try_into_typed_schema_value(__golem_payload)) + } catch{ __golem_error => Err(__golem_error.to_string()) } + } } } ///| /// -pub impl @tool.ToolErrorSchema for CanonicalSetUrlError with fn from_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalSetUrlError with from_error_payload_value( __golem_value, ) { - let __golem_decoded : String? = Some( - @schema.from_value_as(__golem_value.value), - ) catch { + let __golem_decoded :String? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { @@ -359,20 +416,24 @@ extend CanonicalSetUrlError with @tool.ToolErrorSchema::{ ///| /// #warnings("-unused_try") -pub impl @tool.ToolErrorSchema for CanonicalStashError with fn error_cases() { - Ok([ - { - name: "no-such-stash", - doc: { summary: "", description: "", examples: [], }, - kind: @toolCommon.ErrorKind::USAGE_ERROR, - exit_code: 128, - payload: Some( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - ), - }, - ]) catch { +pub impl @tool.ToolErrorSchema for CanonicalStashError with error_cases() { + try { + Ok( + [ + { + name: "no-such-stash", + doc: { summary: "", description: "", examples: [] }, + kind: @toolCommon.ErrorKind::USAGE_ERROR, + exit_code: 128, + payload: Some( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + ), + }, + ], + ) + } catch{ __golem_error => Err(@tool.ToolBuildError::schema_model(__golem_error.to_string())) } @@ -380,25 +441,28 @@ pub impl @tool.ToolErrorSchema for CanonicalStashError with fn error_cases() { ///| /// -pub impl @tool.ToolErrorSchema for CanonicalStashError with fn to_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalStashError with to_error_payload_value( self, ) { match self { - NoSuchStash(name~) => - Ok(@schema.try_into_typed_schema_value(name)) catch { + NoSuchStash(name~) => { + try { + Ok(@schema.try_into_typed_schema_value(name)) + } catch{ __golem_error => Err(__golem_error.to_string()) } + } } } ///| /// -pub impl @tool.ToolErrorSchema for CanonicalStashError with fn from_error_payload_value( +pub impl @tool.ToolErrorSchema for CanonicalStashError with from_error_payload_value( __golem_value, ) { - let __golem_decoded : String? = Some( - @schema.from_value_as(__golem_value.value), - ) catch { + let __golem_decoded :String? = try { + Some(@schema.from_value_as(__golem_value.value)) + } catch{ _ => None } if __golem_decoded is Some(__golem_payload) { @@ -438,10 +502,7 @@ fn __golem_tool_concat_globals( ///| /// -fn __golem_tool_rebase_node( - node : @tool.CommandNodeDef, - offset : Int, -) -> @tool.CommandNodeDef { +fn __golem_tool_rebase_node(node : @tool.CommandNodeDef, offset : Int) -> @tool.CommandNodeDef { { name: node.name, aliases: node.aliases, @@ -463,14 +524,11 @@ fn __golem_tool_extract_prepared(def : @tool.ToolDef) -> @tool.ToolDef { ///| /// -fn __golem_tool_append_prepared( - def : @tool.ToolDef, - child : @tool.ToolDef, -) -> @tool.ToolDef { +fn __golem_tool_append_prepared(def : @tool.ToolDef, child : @tool.ToolDef) -> @tool.ToolDef { let offset = def.commands.length() let commands = def.commands.copy() let root = commands[0] - commands[0] = { + commands[0] = { name: root.name, aliases: root.aliases, doc: root.doc, @@ -481,86 +539,96 @@ fn __golem_tool_append_prepared( for node in child.commands { commands.push(__golem_tool_rebase_node(node, offset)) } - { version: def.version, commands, } + { version: def.version, commands } } ///| /// fn __golem_tool_def_raw_MoonBitStreaming() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "1.0.0", commands: [ { name: "moonbit-streaming", aliases: [], - doc: { summary: "", description: "", examples: [], }, - globals: { options: [], flags: [], }, + doc: { summary: "", description: "", examples: [] }, + globals: { options: [], flags: [] }, subcommands: [1], body: None, }, { name: "stream", aliases: [], - doc: { summary: "", description: "", examples: [], }, - globals: { options: [], flags: [], }, + doc: { summary: "", description: "", examples: [] }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [ + body: Some( + { + positionals: { + fixed: [ + { + name: "mode", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [], + flags: [], + constraints: [], + stdin: Some( + { + doc: { summary: "", description: "", examples: [] }, + mime: [], + required: true, + }, + ), + stdout: Some( + { + doc: { summary: "", description: "", examples: [] }, + mime: [], + required: true, + }, + ), + result: Some( { - name: "mode", - doc: { summary: "", description: "", examples: [], }, - value_name: None, type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + (@schema.TypeTag::{ } : @schema.TypeTag[UInt64]), ), - default: None, - required: true, - accepts_stdio: false, + doc: { summary: "", description: "", examples: [] }, + formatters: [ + { + name: "default", + doc: { summary: "", description: "", examples: [] }, + }, + ], + default_formatter: "default", }, - ], - tail: None, - }, - options: [], - flags: [], - constraints: [], - stdin: Some({ - doc: { summary: "", description: "", examples: [], }, - mime: [], - required: true, - }), - stdout: Some({ - doc: { summary: "", description: "", examples: [], }, - mime: [], - required: true, - }), - result: Some({ - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[UInt64]), ), - doc: { summary: "", description: "", examples: [], }, - formatters: [ + errors: [], + annotations: Some( { - name: "default", - doc: { summary: "", description: "", examples: [], }, + read_only: false, + destructive: true, + idempotent: false, + open_world: true, }, - ], - default_formatter: "default", - }), - errors: [], - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), + }, + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -575,13 +643,13 @@ fn __golem_tool_def_prepare_MoonBitStreaming( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "1.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -600,7 +668,7 @@ fn __golem_tool_def_prepare_MoonBitStreaming( ) let def = prepared def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -608,13 +676,15 @@ fn __golem_tool_def_prepare_MoonBitStreaming( ///| /// fn __golem_tool_def_MoonBitStreaming() -> @tool.ToolDef { - __golem_tool_def_prepare_MoonBitStreaming( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_tool_def_prepare_MoonBitStreaming( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } @@ -630,35 +700,49 @@ async fn __golem_tool_invoke_MoonBitStreaming( __golem_principal : @tool.Principal, ) -> Result[@toolCommon.InvocationResult, @toolCommon.ToolError] { let __golem_def = __golem_tool_def_MoonBitStreaming() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return @tool.reject_wire_invocation( - __golem_input, - __golem_stdin, - @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), - ) - } - let __golem_decoded = @tool.decode_canonical_input( - __golem_def, __golem_index, __golem_input, "tool moonbit-streaming invocation", - ) catch { - __golem_error => + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return @tool.reject_wire_invocation( + __golem_input, + __golem_stdin, + @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), + ) + } + } + let __golem_decoded = try { + @tool.decode_canonical_input( + __golem_def, + __golem_index, + __golem_input, + "tool moonbit-streaming invocation", + ) + } catch{ + __golem_error => { return @tool.reject_undecoded_invocation(__golem_stdin, __golem_error) + } } match __golem_index { 1 => { - let mode : String = @tool.decode_canonical_field( - __golem_decoded, "mode", "tool moonbit-streaming command stream", - ) catch { - __golem_error => + let mode :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "mode", + "tool moonbit-streaming command stream", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } let stdin = match __golem_stdin { Some(__golem_stream) => __golem_stream - None => + None => { return @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @@ -666,10 +750,11 @@ async fn __golem_tool_invoke_MoonBitStreaming( "required stdin stream is missing", ), ) + } } let stdout = match __golem_stdout { Some(__golem_output) => __golem_output - None => + None => { return @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @@ -677,23 +762,28 @@ async fn __golem_tool_invoke_MoonBitStreaming( "required stdout stream is missing", ), ) + } } let __golem_value = MoonBitStreaming::stream(mode, stdin, stdout) Ok( - @tool.invocation_result_value(__golem_value) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + try { + @tool.invocation_result_value(__golem_value) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error }, ) } - _ => + _ => { @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), ) + } } } @@ -701,7 +791,7 @@ async fn __golem_tool_invoke_MoonBitStreaming( /// fn __golem_tool_def_raw_CanonicalGrep() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "2.0.0", commands: [ { @@ -727,16 +817,18 @@ fn __golem_tool_def_raw_CanonicalGrep() -> @tool.ToolDef { shape: @tool.OptionShapeDef::Scalar( @schema.into_schema_graph( ( - @schema.TypeTag::{ } : - @schema.TypeTag[CanonicalGrepColorMode]), + @schema.TypeTag::{ } + : @schema.TypeTag[CanonicalGrepColorMode] + ), ), ), default: Some( @tool.literal_to_schema_value( @schema.into_schema_graph( ( - @schema.TypeTag::{ } : - @schema.TypeTag[CanonicalGrepColorMode]), + @schema.TypeTag::{ } + : @schema.TypeTag[CanonicalGrepColorMode] + ), ), @tool.ToolLiteral::Scalar("Auto"), ), @@ -755,140 +847,156 @@ fn __golem_tool_def_raw_CanonicalGrep() -> @tool.ToolDef { description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } + ), env_var: None, }, ], }, subcommands: [1], - body: Some({ - positionals: { - fixed: [ - { - name: "pattern", - doc: { - summary: "regular expression", - description: "", - examples: [], + body: Some( + { + positionals: { + fixed: [ + { + name: "pattern", + doc: { + summary: "regular expression", + description: "", + examples: [], + }, + value_name: None, + type_: @tool.refine_text( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + Some("^.+$"), + None, + None, + ), + default: None, + required: true, + accepts_stdio: false, + }, + ], + tail: Some( + { + name: "files", + doc: { + summary: "files to search", + description: "", + examples: [], + }, + value_name: None, + item_type: @tool.refine_path( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + ), + Some(@types.PathDirection::INPUT), + Some(@types.PathKind::FILE), + None, + ), + min: 0U, + max: None, + separator: None, + verbatim: false, + accepts_stdio: true, }, + ), + }, + options: [ + { + long: "extra-patterns", + short: Some('\u{65}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, value_name: None, - type_: @tool.refine_text( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + shape: @tool.OptionShapeDef::RepeatableList( + { + repetition: @toolCommon.Repetition::Either('\u{2c}'), + item_type: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + }, + ), + default: None, + required: false, + env_var: None, + }, + { + long: "max-count", + short: Some('\u{6e}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( + @tool.refine_numeric( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[UInt]), + ), + Some("1"), + None, + None, ), - Some("^.+$"), - None, - None, ), default: None, - required: true, - accepts_stdio: false, + required: false, + env_var: None, }, ], - tail: Some({ - name: "files", - doc: { - summary: "files to search", - description: "", - examples: [], + flags: [], + constraints: [], + stdin: Some( + { + doc: { summary: "", description: "", examples: [] }, + mime: [], + required: true, }, - value_name: None, - item_type: @tool.refine_path( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), - ), - Some(@types.PathDirection::INPUT), - Some(@types.PathKind::FILE), - None, - ), - min: 0U, - max: None, - separator: None, - verbatim: false, - accepts_stdio: true, - }), - }, - options: [ - { - long: "extra-patterns", - short: Some('\u{65}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::RepeatableList({ - repetition: @toolCommon.Repetition::Either('\u{2c}'), - item_type: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - }), - default: None, - required: false, - env_var: None, - }, - { - long: "max-count", - short: Some('\u{6e}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @tool.refine_numeric( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[UInt]), + ), + stdout: Some( + { + doc: { summary: "", description: "", examples: [] }, + mime: [], + required: true, + }, + ), + result: Some( + { + type_: @schema.into_schema_graph( + ( + @schema.TypeTag::{ } + : @schema.TypeTag[Array[CanonicalGrepHit]] ), - Some("1"), - None, - None, ), - ), - default: None, - required: false, - env_var: None, - }, - ], - flags: [], - constraints: [], - stdin: Some({ - doc: { summary: "", description: "", examples: [], }, - mime: [], - required: true, - }), - stdout: Some({ - doc: { summary: "", description: "", examples: [], }, - mime: [], - required: true, - }), - result: Some({ - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[Array[CanonicalGrepHit]]), + doc: { + summary: "Search files for a regular expression. Bare `canonical-grep` runs this body.", + description: "", + examples: [], + }, + formatters: [ + { + name: "default", + doc: { summary: "", description: "", examples: [] }, + }, + ], + default_formatter: "default", + }, ), - doc: { - summary: "Search files for a regular expression. Bare `canonical-grep` runs this body.", - description: "", - examples: [], + errors: match CanonicalGrepError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error }, - formatters: [ + annotations: Some( { - name: "default", - doc: { summary: "", description: "", examples: [], }, + read_only: false, + destructive: true, + idempotent: false, + open_world: true, }, - ], - default_formatter: "default", - }), - errors: match CanonicalGrepError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), }, { name: "replace", @@ -904,21 +1012,23 @@ fn __golem_tool_def_raw_CanonicalGrep() -> @tool.ToolDef { long: "color", short: None, aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, value_name: None, shape: @tool.OptionShapeDef::Scalar( @schema.into_schema_graph( ( - @schema.TypeTag::{ } : - @schema.TypeTag[CanonicalGrepColorMode]), + @schema.TypeTag::{ } + : @schema.TypeTag[CanonicalGrepColorMode] + ), ), ), default: Some( @tool.literal_to_schema_value( @schema.into_schema_graph( ( - @schema.TypeTag::{ } : - @schema.TypeTag[CanonicalGrepColorMode]), + @schema.TypeTag::{ } + : @schema.TypeTag[CanonicalGrepColorMode] + ), ), @tool.ToolLiteral::Scalar("Auto"), ), @@ -932,99 +1042,106 @@ fn __golem_tool_def_raw_CanonicalGrep() -> @tool.ToolDef { long: "case-sensitive", short: Some('\u{69}'), aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } + ), env_var: None, }, ], }, subcommands: [], - body: Some({ - positionals: { - fixed: [ - { - name: "pattern", - doc: { summary: "", description: "", examples: [], }, - value_name: None, - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - default: None, - required: true, - accepts_stdio: false, - }, + body: Some( + { + positionals: { + fixed: [ + { + name: "pattern", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + { + name: "replacement", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + ], + tail: Some( + { + name: "files", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + item_type: @tool.refine_path( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + ), + Some(@types.PathDirection::IN_OUT), + Some(@types.PathKind::FILE), + None, + ), + min: 0U, + max: None, + separator: None, + verbatim: false, + accepts_stdio: false, + }, + ), + }, + options: [], + flags: [], + constraints: [], + stdin: None, + stdout: None, + result: Some( { - name: "replacement", - doc: { summary: "", description: "", examples: [], }, - value_name: None, type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + (@schema.TypeTag::{ } : @schema.TypeTag[UInt64]), ), - default: None, - required: true, - accepts_stdio: false, + doc: { + summary: "Replace matching text in place.", + description: "", + examples: [], + }, + formatters: [ + { + name: "default", + doc: { summary: "", description: "", examples: [] }, + }, + ], + default_formatter: "default", }, - ], - tail: Some({ - name: "files", - doc: { summary: "", description: "", examples: [], }, - value_name: None, - item_type: @tool.refine_path( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), - ), - Some(@types.PathDirection::IN_OUT), - Some(@types.PathKind::FILE), - None, - ), - min: 0U, - max: None, - separator: None, - verbatim: false, - accepts_stdio: false, - }), - }, - options: [], - flags: [], - constraints: [], - stdin: None, - stdout: None, - result: Some({ - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[UInt64]), ), - doc: { - summary: "Replace matching text in place.", - description: "", - examples: [], + errors: match CanonicalGrepError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error }, - formatters: [ + annotations: Some( { - name: "default", - doc: { summary: "", description: "", examples: [], }, + read_only: false, + destructive: true, + idempotent: false, + open_world: true, }, - ], - default_formatter: "default", - }), - errors: match CanonicalGrepError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -1039,13 +1156,13 @@ fn __golem_tool_def_prepare_CanonicalGrep( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "2.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -1064,7 +1181,7 @@ fn __golem_tool_def_prepare_CanonicalGrep( ) let def = prepared def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -1072,13 +1189,15 @@ fn __golem_tool_def_prepare_CanonicalGrep( ///| /// fn __golem_tool_def_CanonicalGrep() -> @tool.ToolDef { - __golem_tool_def_prepare_CanonicalGrep( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_tool_def_prepare_CanonicalGrep( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } @@ -1094,75 +1213,124 @@ async fn __golem_tool_invoke_CanonicalGrep( __golem_principal : @tool.Principal, ) -> Result[@toolCommon.InvocationResult, @toolCommon.ToolError] { let __golem_def = __golem_tool_def_CanonicalGrep() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return @tool.reject_wire_invocation( - __golem_input, - __golem_stdin, - @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), - ) - } - let __golem_decoded = @tool.decode_canonical_input( - __golem_def, __golem_index, __golem_input, "tool canonical-grep invocation", - ) catch { - __golem_error => + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return @tool.reject_wire_invocation( + __golem_input, + __golem_stdin, + @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), + ) + } + } + let __golem_decoded = try { + @tool.decode_canonical_input( + __golem_def, + __golem_index, + __golem_input, + "tool canonical-grep invocation", + ) + } catch{ + __golem_error => { return @tool.reject_undecoded_invocation(__golem_stdin, __golem_error) + } } match __golem_index { 0 => { - let case_sensitive : Bool = @tool.decode_canonical_field( - __golem_decoded, "case-sensitive", "tool canonical-grep command canonical-grep", - ) catch { - __golem_error => + let case_sensitive :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "case-sensitive", + "tool canonical-grep command canonical-grep", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, - ) + __golem_decoded, + __golem_stdin, + __golem_error, + ) + } } - let color : CanonicalGrepColorMode = @tool.decode_canonical_field( - __golem_decoded, "color", "tool canonical-grep command canonical-grep", - ) catch { - __golem_error => + let color :CanonicalGrepColorMode = try { + @tool.decode_canonical_field( + __golem_decoded, + "color", + "tool canonical-grep command canonical-grep", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let pattern : String = @tool.decode_canonical_field( - __golem_decoded, "pattern", "tool canonical-grep command canonical-grep", - ) catch { - __golem_error => + let pattern :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "pattern", + "tool canonical-grep command canonical-grep", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let extra_patterns : Array[String] = @tool.decode_canonical_field( - __golem_decoded, "extra-patterns", "tool canonical-grep command canonical-grep", - ) catch { - __golem_error => + let extra_patterns :Array[String] = try { + @tool.decode_canonical_field( + __golem_decoded, + "extra-patterns", + "tool canonical-grep command canonical-grep", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let max_count : UInt? = @tool.decode_canonical_field( - __golem_decoded, "max-count", "tool canonical-grep command canonical-grep", - ) catch { - __golem_error => + let max_count :UInt? = try { + @tool.decode_canonical_field( + __golem_decoded, + "max-count", + "tool canonical-grep command canonical-grep", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let files : Array[@schema.Path] = @tool.decode_canonical_field( - __golem_decoded, "files", "tool canonical-grep command canonical-grep", - ) catch { - __golem_error => + let files :Array[@schema.Path] = try { + @tool.decode_canonical_field( + __golem_decoded, + "files", + "tool canonical-grep command canonical-grep", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } let stdin = match __golem_stdin { Some(__golem_stream) => __golem_stream - None => + None => { return @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @@ -1170,10 +1338,11 @@ async fn __golem_tool_invoke_CanonicalGrep( "required stdin stream is missing", ), ) + } } let stdout = match __golem_stdout { Some(__golem_output) => __golem_output - None => + None => { return @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @@ -1181,37 +1350,50 @@ async fn __golem_tool_invoke_CanonicalGrep( "required stdout stream is missing", ), ) + } } - match - CanonicalGrep::canonical_grep( - case_sensitive, color, pattern, extra_patterns, max_count, files, stdin, - stdout, - ) { - Ok(__golem_value) => + match CanonicalGrep::canonical_grep( + case_sensitive, + color, + pattern, + extra_patterns, + max_count, + files, + stdin, + stdout, + ) { + Ok(__golem_value) => { Ok( - @tool.invocation_result_value(__golem_value) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + try { + @tool.invocation_result_value(__golem_value) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error }, ) + } Err(error) => { - let payload = match - CanonicalGrepError::to_error_payload_value(error) { + let payload = match CanonicalGrepError::to_error_payload_value(error) { Ok(payload) => payload - Err(encode_error) => + Err(encode_error) => { return Err( @toolCommon.ToolError::InvalidResult( "failed serializing custom tool error: " + encode_error, ), ) + } } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } @@ -1227,86 +1409,132 @@ async fn __golem_tool_invoke_CanonicalGrep( ), ) } - let case_sensitive : Bool = @tool.decode_canonical_field( - __golem_decoded, "case-sensitive", "tool canonical-grep command replace", - ) catch { - __golem_error => + let case_sensitive :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "case-sensitive", + "tool canonical-grep command replace", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let color : CanonicalGrepColorMode = @tool.decode_canonical_field( - __golem_decoded, "color", "tool canonical-grep command replace", - ) catch { - __golem_error => + let color :CanonicalGrepColorMode = try { + @tool.decode_canonical_field( + __golem_decoded, + "color", + "tool canonical-grep command replace", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let pattern : String = @tool.decode_canonical_field( - __golem_decoded, "pattern", "tool canonical-grep command replace", - ) catch { - __golem_error => + let pattern :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "pattern", + "tool canonical-grep command replace", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let replacement : String = @tool.decode_canonical_field( - __golem_decoded, "replacement", "tool canonical-grep command replace", - ) catch { - __golem_error => + let replacement :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "replacement", + "tool canonical-grep command replace", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let files : Array[@schema.Path] = @tool.decode_canonical_field( - __golem_decoded, "files", "tool canonical-grep command replace", - ) catch { - __golem_error => + let files :Array[@schema.Path] = try { + @tool.decode_canonical_field( + __golem_decoded, + "files", + "tool canonical-grep command replace", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - match - CanonicalGrep::replace( - case_sensitive, color, pattern, replacement, files, - ) { - Ok(__golem_value) => + match CanonicalGrep::replace( + case_sensitive, + color, + pattern, + replacement, + files, + ) { + Ok(__golem_value) => { Ok( - @tool.invocation_result_value(__golem_value) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + try { + @tool.invocation_result_value(__golem_value) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error }, ) + } Err(error) => { - let payload = match - CanonicalGrepError::to_error_payload_value(error) { + let payload = match CanonicalGrepError::to_error_payload_value(error) { Ok(payload) => payload - Err(encode_error) => + Err(encode_error) => { return Err( @toolCommon.ToolError::InvalidResult( "failed serializing custom tool error: " + encode_error, ), ) + } } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } } } - _ => + _ => { @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), ) + } } } @@ -1314,7 +1542,7 @@ async fn __golem_tool_invoke_CanonicalGrep( /// fn __golem_tool_def_raw_CanonicalGit() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "0.0.0", commands: [ { @@ -1325,7 +1553,7 @@ fn __golem_tool_def_raw_CanonicalGit() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [1, 2], body: None, }, @@ -1343,12 +1571,12 @@ fn __golem_tool_def_raw_CanonicalGit() -> @tool.ToolDef { long: "git-dir", short: None, aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, value_name: None, shape: @tool.OptionShapeDef::Scalar( @tool.refine_path( @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), ), None, Some(@types.PathKind::DIRECTORY), @@ -1359,7 +1587,7 @@ fn __golem_tool_def_raw_CanonicalGit() -> @tool.ToolDef { @tool.literal_to_schema_value( @tool.refine_path( @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), ), None, Some(@types.PathKind::DIRECTORY), @@ -1375,15 +1603,20 @@ fn __golem_tool_def_raw_CanonicalGit() -> @tool.ToolDef { long: "config", short: Some('\u{63}'), aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, value_name: None, - shape: @tool.OptionShapeDef::RepeatableMap({ - repetition: @toolCommon.Repetition::Repeated, - map_type: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[Map[String, String]]), - ), - duplicate_key_policy: @toolCommon.DuplicateKeyPolicy::REJECT, - }), + shape: @tool.OptionShapeDef::RepeatableMap( + { + repetition: @toolCommon.Repetition::Repeated, + map_type: @schema.into_schema_graph( + ( + @schema.TypeTag::{ } + : @schema.TypeTag[Map[String, String]] + ), + ), + duplicate_key_policy: @toolCommon.DuplicateKeyPolicy::REJECT, + }, + ), default: None, required: false, env_var: None, @@ -1394,7 +1627,7 @@ fn __golem_tool_def_raw_CanonicalGit() -> @tool.ToolDef { long: "verbose", short: Some('\u{76}'), aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, shape: @toolCommon.FlagShape::CountFlag(Some(3U)), env_var: None, }, @@ -1402,384 +1635,408 @@ fn __golem_tool_def_raw_CanonicalGit() -> @tool.ToolDef { long: "paginate", short: None, aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: true, - negatable: true, - }), + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: true, negatable: true } + ), env_var: None, }, ], }, subcommands: [], - body: Some({ - positionals: { fixed: [], tail: None, }, - options: [ - { - long: "message", - short: Some('\u{6d}'), - aliases: ["msg"], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - ), - default: None, - required: true, - env_var: None, - }, - { - long: "author", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @tool.refine_text( + body: Some( + { + positionals: { fixed: [], tail: None }, + options: [ + { + long: "message", + short: Some('\u{6d}'), + aliases: ["msg"], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + (@schema.TypeTag::{ } : @schema.TypeTag[String]), ), - Some("^.+ <.+@.+>$"), - None, - None, ), - ), - default: None, - required: false, - env_var: Some("GIT_AUTHOR_NAME"), - }, - { - long: "output", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @schema.into_schema_graph( - ( - @schema.TypeTag::{ } : - @schema.TypeTag[CanonicalGitOutputMode]), + default: None, + required: true, + env_var: None, + }, + { + long: "author", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( + @tool.refine_text( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + Some("^.+ <.+@.+>$"), + None, + None, + ), ), - ), - default: Some( - @tool.literal_to_schema_value( + default: None, + required: false, + env_var: Some("GIT_AUTHOR_NAME"), + }, + { + long: "output", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( @schema.into_schema_graph( ( - @schema.TypeTag::{ } : - @schema.TypeTag[CanonicalGitOutputMode]), + @schema.TypeTag::{ } + : @schema.TypeTag[CanonicalGitOutputMode] + ), ), - @tool.ToolLiteral::Scalar("Human"), ), - ), - required: false, - env_var: None, - }, - ], - flags: [ - { - long: "amend", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: true, - }), - env_var: None, - }, - { - long: "signoff", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: true, - }), - env_var: None, - }, - { - long: "reset-author", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, - }, - ], - constraints: [ - @tool.ConstraintDef::Implies({ - lhs_quant: @toolCommon.Quantifier::ALL, - lhs: [@tool.RefDef::Present("reset-author")], - rhs_quant: @toolCommon.Quantifier::ALL, - rhs: [@tool.RefDef::Present("amend")], - }), - @tool.ConstraintDef::RequiresAll([ - @tool.RefDef::ValueIs({ - name: "output", - value: @tool.ValueIsLiteralDef::Deferred( - @tool.ToolLiteral::Scalar("Json"), + default: Some( + @tool.literal_to_schema_value( + @schema.into_schema_graph( + ( + @schema.TypeTag::{ } + : @schema.TypeTag[CanonicalGitOutputMode] + ), + ), + @tool.ToolLiteral::Scalar("Human"), + ), ), - }), - ]), - ], - stdin: None, - stdout: None, - result: Some({ - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[CanonicalCommitResult]), - ), - doc: { - summary: "Record changes to the repository.", - description: "", - examples: [], - }, - formatters: [ + required: false, + env_var: None, + }, + ], + flags: [ { - name: "human", - doc: { summary: "", description: "", examples: [], }, + long: "amend", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: true } + ), + env_var: None, }, { - name: "porcelain", - doc: { summary: "", description: "", examples: [], }, + long: "signoff", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: true } + ), + env_var: None, }, { - name: "json", - doc: { summary: "", description: "", examples: [], }, + long: "reset-author", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } + ), + env_var: None, }, ], - default_formatter: "human", - }), - errors: match CanonicalCommitError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + constraints: [ + @tool.ConstraintDef::Implies( + { + lhs_quant: @toolCommon.Quantifier::ALL, + lhs: [@tool.RefDef::Present("reset-author")], + rhs_quant: @toolCommon.Quantifier::ALL, + rhs: [@tool.RefDef::Present("amend")], + }, + ), + @tool.ConstraintDef::RequiresAll( + [ + @tool.RefDef::ValueIs( + { + name: "output", + value: @tool.ValueIsLiteralDef::Deferred( + @tool.ToolLiteral::Scalar("Json"), + ), + }, + ), + ], + ), + ], + stdin: None, + stdout: None, + result: Some( + { + type_: @schema.into_schema_graph( + ( + @schema.TypeTag::{ } + : @schema.TypeTag[CanonicalCommitResult] + ), + ), + doc: { + summary: "Record changes to the repository.", + description: "", + examples: [], + }, + formatters: [ + { + name: "human", + doc: { summary: "", description: "", examples: [] }, + }, + { + name: "porcelain", + doc: { summary: "", description: "", examples: [] }, + }, + { + name: "json", + doc: { summary: "", description: "", examples: [] }, + }, + ], + default_formatter: "human", + }, + ), + errors: match CanonicalCommitError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error + }, + annotations: Some( + { + read_only: false, + destructive: true, + idempotent: false, + open_world: true, + }, + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), }, { name: "log", aliases: [], - doc: { summary: "Show commit logs.", description: "", examples: [], }, - globals: { options: [], flags: [], }, + doc: { summary: "Show commit logs.", description: "", examples: [] }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [], - tail: Some({ - name: "paths", - doc: { summary: "", description: "", examples: [], }, - value_name: None, - item_type: @tool.refine_path( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), - ), - Some(@types.PathDirection::INPUT), - Some(@types.PathKind::FILE), - None, - ), - min: 0U, - max: None, - separator: Some("--"), - verbatim: false, - accepts_stdio: false, - }), - }, - options: [ - { - long: "max-count", - short: Some('\u{6e}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @tool.refine_numeric( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[Int64]), + body: Some( + { + positionals: { + fixed: [], + tail: Some( + { + name: "paths", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + item_type: @tool.refine_path( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + ), + Some(@types.PathDirection::INPUT), + Some(@types.PathKind::FILE), + None, ), - Some("0"), - Some("9223372036854775807"), - None, - ), + min: 0U, + max: None, + separator: Some("--"), + verbatim: false, + accepts_stdio: false, + }, ), - default: None, - required: false, - env_var: None, }, - { - long: "since", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@types.Datetime]), + options: [ + { + long: "max-count", + short: Some('\u{6e}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( + @tool.refine_numeric( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[Int64]), + ), + Some("0"), + Some("9223372036854775807"), + None, + ), ), - ), - default: None, - required: false, - env_var: None, - }, - { - long: "until", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@types.Datetime]), + default: None, + required: false, + env_var: None, + }, + { + long: "since", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[@types.Datetime]), + ), ), - ), - default: None, - required: false, - env_var: None, - }, - { - long: "author", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::RepeatableList({ - repetition: @toolCommon.Repetition::Delimited('\u{2c}'), - item_type: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + default: None, + required: false, + env_var: None, + }, + { + long: "until", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[@types.Datetime]), + ), ), - }), - default: None, - required: false, - env_var: None, - }, - { - long: "grep", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::RepeatableList({ - repetition: @toolCommon.Repetition::Either('\u{2c}'), - item_type: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + default: None, + required: false, + env_var: None, + }, + { + long: "author", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::RepeatableList( + { + repetition: @toolCommon.Repetition::Delimited('\u{2c}'), + item_type: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + }, ), - }), - default: None, - required: false, - env_var: None, - }, - ], - flags: [ - { - long: "all-match", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, - }, - { - long: "invert-grep", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, - }, - { - long: "oneline", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, - }, - { - long: "graph", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, - }, - ], - constraints: [ - @tool.ConstraintDef::AllOrNone([ - @tool.RefDef::Present("all-match"), - @tool.RefDef::Present("grep"), - ]), - ], - stdin: None, - stdout: None, - result: Some({ - type_: @schema.into_schema_graph( - ( - @schema.TypeTag::{ } : - @schema.TypeTag[Array[CanonicalLogEntry]]), - ), - doc: { - summary: "Show commit logs.", - description: "", - examples: [], - }, - formatters: [ + default: None, + required: false, + env_var: None, + }, { - name: "oneline", - doc: { summary: "", description: "", examples: [], }, + long: "grep", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::RepeatableList( + { + repetition: @toolCommon.Repetition::Either('\u{2c}'), + item_type: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + }, + ), + default: None, + required: false, + env_var: None, }, + ], + flags: [ { - name: "short", - doc: { summary: "", description: "", examples: [], }, + long: "all-match", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } + ), + env_var: None, }, { - name: "medium", - doc: { summary: "", description: "", examples: [], }, + long: "invert-grep", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } + ), + env_var: None, }, { - name: "full", - doc: { summary: "", description: "", examples: [], }, + long: "oneline", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } + ), + env_var: None, + }, + { + long: "graph", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } + ), + env_var: None, }, ], - default_formatter: "medium", - }), - errors: match CanonicalLogError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + constraints: [ + @tool.ConstraintDef::AllOrNone( + [ + @tool.RefDef::Present("all-match"), + @tool.RefDef::Present("grep"), + ], + ), + ], + stdin: None, + stdout: None, + result: Some( + { + type_: @schema.into_schema_graph( + ( + @schema.TypeTag::{ } + : @schema.TypeTag[Array[CanonicalLogEntry]] + ), + ), + doc: { + summary: "Show commit logs.", + description: "", + examples: [], + }, + formatters: [ + { + name: "oneline", + doc: { summary: "", description: "", examples: [] }, + }, + { + name: "short", + doc: { summary: "", description: "", examples: [] }, + }, + { + name: "medium", + doc: { summary: "", description: "", examples: [] }, + }, + { + name: "full", + doc: { summary: "", description: "", examples: [] }, + }, + ], + default_formatter: "medium", + }, + ), + errors: match CanonicalLogError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error + }, + annotations: Some( + { + read_only: true, + destructive: true, + idempotent: true, + open_world: true, + }, + ), }, - annotations: Some({ - read_only: true, - destructive: true, - idempotent: true, - open_world: true, - }), - }), + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -1794,13 +2051,13 @@ fn __golem_tool_def_prepare_CanonicalGit( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "0.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -1830,12 +2087,12 @@ fn __golem_tool_def_prepare_CanonicalGit( long: "git-dir", short: None, aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, value_name: None, shape: @tool.OptionShapeDef::Scalar( @tool.refine_path( @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), ), None, Some(@types.PathKind::DIRECTORY), @@ -1846,7 +2103,7 @@ fn __golem_tool_def_prepare_CanonicalGit( @tool.literal_to_schema_value( @tool.refine_path( @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), ), None, Some(@types.PathKind::DIRECTORY), @@ -1862,15 +2119,17 @@ fn __golem_tool_def_prepare_CanonicalGit( long: "config", short: Some('\u{63}'), aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, value_name: None, - shape: @tool.OptionShapeDef::RepeatableMap({ - repetition: @toolCommon.Repetition::Repeated, - map_type: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[Map[String, String]]), - ), - duplicate_key_policy: @toolCommon.DuplicateKeyPolicy::REJECT, - }), + shape: @tool.OptionShapeDef::RepeatableMap( + { + repetition: @toolCommon.Repetition::Repeated, + map_type: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[Map[String, String]]), + ), + duplicate_key_policy: @toolCommon.DuplicateKeyPolicy::REJECT, + }, + ), default: None, required: false, env_var: None, @@ -1881,7 +2140,7 @@ fn __golem_tool_def_prepare_CanonicalGit( long: "verbose", short: Some('\u{76}'), aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, shape: @toolCommon.FlagShape::CountFlag(Some(3U)), env_var: None, }, @@ -1889,21 +2148,22 @@ fn __golem_tool_def_prepare_CanonicalGit( long: "paginate", short: None, aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: true, - negatable: true, - }), + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: true, negatable: true } + ), env_var: None, }, ], }, None, - Some({ - summary: "Manage the set of tracked repositories.", - description: "", - examples: [], - }), + Some( + { + summary: "Manage the set of tracked repositories.", + description: "", + examples: [], + }, + ), Some(["rmt"]), ) let def = __golem_tool_append_prepared(def, child) @@ -1915,12 +2175,12 @@ fn __golem_tool_def_prepare_CanonicalGit( long: "git-dir", short: None, aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, value_name: None, shape: @tool.OptionShapeDef::Scalar( @tool.refine_path( @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), ), None, Some(@types.PathKind::DIRECTORY), @@ -1931,7 +2191,7 @@ fn __golem_tool_def_prepare_CanonicalGit( @tool.literal_to_schema_value( @tool.refine_path( @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Path]), ), None, Some(@types.PathKind::DIRECTORY), @@ -1949,23 +2209,25 @@ fn __golem_tool_def_prepare_CanonicalGit( long: "verbose", short: Some('\u{76}'), aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, shape: @toolCommon.FlagShape::CountFlag(Some(3U)), env_var: None, }, ], }, None, - Some({ - summary: "Stash changes in a dirty working directory.", - description: "", - examples: [], - }), + Some( + { + summary: "Stash changes in a dirty working directory.", + description: "", + examples: [], + }, + ), None, ) let def = __golem_tool_append_prepared(def, child) def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -1973,13 +2235,15 @@ fn __golem_tool_def_prepare_CanonicalGit( ///| /// fn __golem_tool_def_CanonicalGit() -> @tool.ToolDef { - __golem_tool_def_prepare_CanonicalGit( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_tool_def_prepare_CanonicalGit( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } @@ -1995,24 +2259,32 @@ async fn __golem_tool_invoke_CanonicalGit( __golem_principal : @tool.Principal, ) -> Result[@toolCommon.InvocationResult, @toolCommon.ToolError] { let __golem_def = __golem_tool_def_CanonicalGit() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return @tool.reject_wire_invocation( - __golem_input, - __golem_stdin, - @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), - ) - } - let __golem_decoded = @tool.decode_canonical_input( - __golem_def, __golem_index, __golem_input, "tool canonical-git invocation", - ) catch { - __golem_error => + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return @tool.reject_wire_invocation( + __golem_input, + __golem_stdin, + @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), + ) + } + } + let __golem_decoded = try { + @tool.decode_canonical_input( + __golem_def, + __golem_index, + __golem_input, + "tool canonical-git invocation", + ) + } catch{ + __golem_error => { return @tool.reject_undecoded_invocation(__golem_stdin, __golem_error) + } } - if __golem_command_path.length() > 0 && - ["remote", "rmt"].contains(__golem_command_path[0]) { + if __golem_command_path.length() > 0 && ["remote", "rmt"].contains( + __golem_command_path[0], + ) { return @tool.invoke_registered_subtool( "remote", __golem_command_path[1:].to_owned(), @@ -2022,8 +2294,9 @@ async fn __golem_tool_invoke_CanonicalGit( __golem_principal, ) } - if __golem_command_path.length() > 0 && - ["stash"].contains(__golem_command_path[0]) { + if __golem_command_path.length() > 0 && ["stash"].contains( + __golem_command_path[0], + ) { return @tool.invoke_registered_subtool( "stash", __golem_command_path[1:].to_owned(), @@ -2044,116 +2317,201 @@ async fn __golem_tool_invoke_CanonicalGit( ), ) } - let verbose : UInt = @tool.decode_canonical_field( - __golem_decoded, "verbose", "tool canonical-git command commit", - ) catch { - __golem_error => + let verbose :UInt = try { + @tool.decode_canonical_field( + __golem_decoded, + "verbose", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let git_dir : @schema.Path = @tool.decode_canonical_field( - __golem_decoded, "git-dir", "tool canonical-git command commit", - ) catch { - __golem_error => + let git_dir :@schema.Path = try { + @tool.decode_canonical_field( + __golem_decoded, + "git-dir", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let paginate : Bool = @tool.decode_canonical_field( - __golem_decoded, "paginate", "tool canonical-git command commit", - ) catch { - __golem_error => + let paginate :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "paginate", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let config : Map[String, String] = @tool.decode_canonical_field( - __golem_decoded, "config", "tool canonical-git command commit", - ) catch { - __golem_error => + let config :Map[String, String] = try { + @tool.decode_canonical_field( + __golem_decoded, + "config", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let message : String = @tool.decode_canonical_field( - __golem_decoded, "message", "tool canonical-git command commit", - ) catch { - __golem_error => + let message :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "message", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let author : String? = @tool.decode_canonical_field( - __golem_decoded, "author", "tool canonical-git command commit", - ) catch { - __golem_error => + let author :String? = try { + @tool.decode_canonical_field( + __golem_decoded, + "author", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let amend : Bool = @tool.decode_canonical_field( - __golem_decoded, "amend", "tool canonical-git command commit", - ) catch { - __golem_error => + let amend :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "amend", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let signoff : Bool = @tool.decode_canonical_field( - __golem_decoded, "signoff", "tool canonical-git command commit", - ) catch { - __golem_error => + let signoff :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "signoff", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let reset_author : Bool = @tool.decode_canonical_field( - __golem_decoded, "reset-author", "tool canonical-git command commit", - ) catch { - __golem_error => + let reset_author :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "reset-author", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let output : CanonicalGitOutputMode = @tool.decode_canonical_field( - __golem_decoded, "output", "tool canonical-git command commit", - ) catch { - __golem_error => + let output :CanonicalGitOutputMode = try { + @tool.decode_canonical_field( + __golem_decoded, + "output", + "tool canonical-git command commit", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - match - CanonicalGit::commit( - verbose, git_dir, paginate, config, message, author, amend, signoff, reset_author, - output, - ) { - Ok(__golem_value) => + match CanonicalGit::commit( + verbose, + git_dir, + paginate, + config, + message, + author, + amend, + signoff, + reset_author, + output, + ) { + Ok(__golem_value) => { Ok( - @tool.invocation_result_value(__golem_value) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + try { + @tool.invocation_result_value(__golem_value) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error }, ) + } Err(error) => { - let payload = match - CanonicalCommitError::to_error_payload_value(error) { - Ok(payload) => payload - Err(encode_error) => - return Err( - @toolCommon.ToolError::InvalidResult( - "failed serializing custom tool error: " + encode_error, - ), - ) - } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = + match CanonicalCommitError::to_error_payload_value(error) { + Ok(payload) => payload + Err(encode_error) => { + return Err( + @toolCommon.ToolError::InvalidResult( + "failed serializing custom tool error: " + encode_error, + ), + ) + } + } + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } @@ -2169,126 +2527,212 @@ async fn __golem_tool_invoke_CanonicalGit( ), ) } - let max_count : Int64? = @tool.decode_canonical_field( - __golem_decoded, "max-count", "tool canonical-git command log", - ) catch { - __golem_error => + let max_count :Int64? = try { + @tool.decode_canonical_field( + __golem_decoded, + "max-count", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let since : @types.Datetime? = @tool.decode_canonical_field( - __golem_decoded, "since", "tool canonical-git command log", - ) catch { - __golem_error => + let since :@types.Datetime? = try { + @tool.decode_canonical_field( + __golem_decoded, + "since", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let until : @types.Datetime? = @tool.decode_canonical_field( - __golem_decoded, "until", "tool canonical-git command log", - ) catch { - __golem_error => + let until :@types.Datetime? = try { + @tool.decode_canonical_field( + __golem_decoded, + "until", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let author : Array[String] = @tool.decode_canonical_field( - __golem_decoded, "author", "tool canonical-git command log", - ) catch { - __golem_error => + let author :Array[String] = try { + @tool.decode_canonical_field( + __golem_decoded, + "author", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let grep : Array[String] = @tool.decode_canonical_field( - __golem_decoded, "grep", "tool canonical-git command log", - ) catch { - __golem_error => + let grep :Array[String] = try { + @tool.decode_canonical_field( + __golem_decoded, + "grep", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let all_match : Bool = @tool.decode_canonical_field( - __golem_decoded, "all-match", "tool canonical-git command log", - ) catch { - __golem_error => + let all_match :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "all-match", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let invert_grep : Bool = @tool.decode_canonical_field( - __golem_decoded, "invert-grep", "tool canonical-git command log", - ) catch { - __golem_error => + let invert_grep :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "invert-grep", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let oneline : Bool = @tool.decode_canonical_field( - __golem_decoded, "oneline", "tool canonical-git command log", - ) catch { - __golem_error => + let oneline :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "oneline", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let graph : Bool = @tool.decode_canonical_field( - __golem_decoded, "graph", "tool canonical-git command log", - ) catch { - __golem_error => + let graph :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "graph", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let paths : Array[@schema.Path] = @tool.decode_canonical_field( - __golem_decoded, "paths", "tool canonical-git command log", - ) catch { - __golem_error => + let paths :Array[@schema.Path] = try { + @tool.decode_canonical_field( + __golem_decoded, + "paths", + "tool canonical-git command log", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - match - CanonicalGit::log( - max_count, since, until, author, grep, all_match, invert_grep, oneline, - graph, paths, - ) { - Ok(__golem_value) => + match CanonicalGit::log( + max_count, + since, + until, + author, + grep, + all_match, + invert_grep, + oneline, + graph, + paths, + ) { + Ok(__golem_value) => { Ok( - @tool.invocation_result_value(__golem_value) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + try { + @tool.invocation_result_value(__golem_value) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error }, ) + } Err(error) => { let payload = match CanonicalLogError::to_error_payload_value(error) { Ok(payload) => payload - Err(encode_error) => + Err(encode_error) => { return Err( @toolCommon.ToolError::InvalidResult( "failed serializing custom tool error: " + encode_error, ), ) + } } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } } } - _ => + _ => { @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), ) + } } } @@ -2296,7 +2740,7 @@ async fn __golem_tool_invoke_CanonicalGit( /// fn __golem_tool_def_raw_CanonicalRemote() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "0.0.0", commands: [ { @@ -2307,14 +2751,14 @@ fn __golem_tool_def_raw_CanonicalRemote() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [1, 2, 3], body: None, }, { name: "add", aliases: [], - doc: { summary: "Add a remote.", description: "", examples: [], }, + doc: { summary: "Add a remote.", description: "", examples: [] }, globals: { options: [], flags: [ @@ -2322,167 +2766,175 @@ fn __golem_tool_def_raw_CanonicalRemote() -> @tool.ToolDef { long: "verbose", short: None, aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, shape: @toolCommon.FlagShape::CountFlag(Some(3U)), env_var: None, }, ], }, subcommands: [], - body: Some({ - positionals: { - fixed: [ + body: Some( + { + positionals: { + fixed: [ + { + name: "name", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @tool.refine_text( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + Some("^[a-zA-Z][a-zA-Z0-9_-]*$"), + None, + None, + ), + default: None, + required: true, + accepts_stdio: false, + }, + { + name: "url", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @tool.refine_url( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Url]), + ), + Some(["https"]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [ { - name: "name", - doc: { summary: "", description: "", examples: [], }, + long: "track", + short: Some('\u{74}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, value_name: None, - type_: @tool.refine_text( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), - ), - Some("^[a-zA-Z][a-zA-Z0-9_-]*$"), - None, - None, + shape: @tool.OptionShapeDef::RepeatableList( + { + repetition: @toolCommon.Repetition::Repeated, + item_type: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + }, ), default: None, - required: true, - accepts_stdio: false, + required: false, + env_var: None, }, { - name: "url", - doc: { summary: "", description: "", examples: [], }, + long: "master", + short: Some('\u{6d}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, value_name: None, - type_: @tool.refine_url( + shape: @tool.OptionShapeDef::Scalar( @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Url]), + (@schema.TypeTag::{ } : @schema.TypeTag[String]), ), - Some(["https"]), ), default: None, - required: true, - accepts_stdio: false, + required: false, + env_var: None, }, ], - tail: None, - }, - options: [ - { - long: "track", - short: Some('\u{74}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::RepeatableList({ - repetition: @toolCommon.Repetition::Repeated, - item_type: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + flags: [ + { + long: "tags", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: true, negatable: true } ), - }), - default: None, - required: false, - env_var: None, - }, - { - long: "master", - short: Some('\u{6d}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + env_var: None, + }, + { + long: "fetch", + short: Some('\u{66}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } ), - ), - default: None, - required: false, - env_var: None, - }, - ], - flags: [ - { - long: "tags", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: true, - negatable: true, - }), - env_var: None, - }, - { - long: "fetch", - short: Some('\u{66}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, + env_var: None, + }, + ], + constraints: [], + stdin: None, + stdout: None, + result: None, + errors: match CanonicalRemoteError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error }, - ], - constraints: [], - stdin: None, - stdout: None, - result: None, - errors: match CanonicalRemoteError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + annotations: Some( + { + read_only: false, + destructive: false, + idempotent: false, + open_world: true, + }, + ), }, - annotations: Some({ - read_only: false, - destructive: false, - idempotent: false, - open_world: true, - }), - }), + ), }, { name: "remove", aliases: ["rm"], - doc: { summary: "Remove a remote.", description: "", examples: [], }, - globals: { options: [], flags: [], }, + doc: { summary: "Remove a remote.", description: "", examples: [] }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [ - { - name: "name", - doc: { summary: "", description: "", examples: [], }, - value_name: None, - type_: @tool.refine_text( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + body: Some( + { + positionals: { + fixed: [ + { + name: "name", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @tool.refine_text( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + Some("^[a-zA-Z][a-zA-Z0-9_-]*$"), + None, + None, ), - Some("^[a-zA-Z][a-zA-Z0-9_-]*$"), - None, - None, - ), - default: None, - required: true, - accepts_stdio: false, + default: None, + required: true, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [], + flags: [], + constraints: [], + stdin: None, + stdout: None, + result: None, + errors: match CanonicalRemoteError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error + }, + annotations: Some( + { + read_only: false, + destructive: true, + idempotent: true, + open_world: true, }, - ], - tail: None, - }, - options: [], - flags: [], - constraints: [], - stdin: None, - stdout: None, - result: None, - errors: match CanonicalRemoteError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: true, - open_world: true, - }), - }), + ), }, { name: "set-url", @@ -2492,114 +2944,117 @@ fn __golem_tool_def_raw_CanonicalRemote() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [ + body: Some( + { + positionals: { + fixed: [ + { + name: "name", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + { + name: "newurl", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @tool.refine_url( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Url]), + ), + Some(["https"]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + { + name: "oldurl", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @tool.refine_url( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Url]), + ), + Some(["https"]), + ), + default: None, + required: false, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [], + flags: [ { - name: "name", - doc: { summary: "", description: "", examples: [], }, - value_name: None, - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + long: "push", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } ), - default: None, - required: true, - accepts_stdio: false, + env_var: None, }, { - name: "newurl", - doc: { summary: "", description: "", examples: [], }, - value_name: None, - type_: @tool.refine_url( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Url]), - ), - Some(["https"]), + long: "add", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } ), - default: None, - required: true, - accepts_stdio: false, + env_var: None, }, { - name: "oldurl", - doc: { summary: "", description: "", examples: [], }, - value_name: None, - type_: @tool.refine_url( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[@schema.Url]), - ), - Some(["https"]), + long: "delete", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } ), - default: None, - required: false, - accepts_stdio: false, + env_var: None, }, ], - tail: None, - }, - options: [], - flags: [ - { - long: "push", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, - }, - { - long: "add", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, - }, - { - long: "delete", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, + constraints: [ + @tool.ConstraintDef::MutexGroups( + [ + { refs: [@tool.RefDef::Present("add")], }, + { refs: [@tool.RefDef::Present("delete")], }, + ], + ), + ], + stdin: None, + stdout: None, + result: None, + errors: match CanonicalSetUrlError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error }, - ], - constraints: [ - @tool.ConstraintDef::MutexGroups([ - { refs: [@tool.RefDef::Present("add")], }, - { refs: [@tool.RefDef::Present("delete")], }, - ]), - ], - stdin: None, - stdout: None, - result: None, - errors: match CanonicalSetUrlError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + annotations: Some( + { + read_only: false, + destructive: true, + idempotent: false, + open_world: true, + }, + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -2614,13 +3069,13 @@ fn __golem_tool_def_prepare_CanonicalRemote( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "0.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -2639,7 +3094,7 @@ fn __golem_tool_def_prepare_CanonicalRemote( ) let def = prepared def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -2647,13 +3102,15 @@ fn __golem_tool_def_prepare_CanonicalRemote( ///| /// fn __golem_tool_def_CanonicalRemote() -> @tool.ToolDef { - __golem_tool_def_prepare_CanonicalRemote( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_tool_def_prepare_CanonicalRemote( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } @@ -2669,21 +3126,28 @@ async fn __golem_tool_invoke_CanonicalRemote( __golem_principal : @tool.Principal, ) -> Result[@toolCommon.InvocationResult, @toolCommon.ToolError] { let __golem_def = __golem_tool_def_CanonicalRemote() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return @tool.reject_wire_invocation( - __golem_input, - __golem_stdin, - @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), - ) - } - let __golem_decoded = @tool.decode_canonical_input( - __golem_def, __golem_index, __golem_input, "tool remote invocation", - ) catch { - __golem_error => + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return @tool.reject_wire_invocation( + __golem_input, + __golem_stdin, + @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), + ) + } + } + let __golem_decoded = try { + @tool.decode_canonical_input( + __golem_def, + __golem_index, + __golem_input, + "tool remote invocation", + ) + } catch{ + __golem_error => { return @tool.reject_undecoded_invocation(__golem_stdin, __golem_error) + } } match __golem_index { 1 => { @@ -2696,81 +3160,133 @@ async fn __golem_tool_invoke_CanonicalRemote( ), ) } - let verbose : UInt = @tool.decode_canonical_field( - __golem_decoded, "verbose", "tool remote command add", - ) catch { - __golem_error => + let verbose :UInt = try { + @tool.decode_canonical_field( + __golem_decoded, + "verbose", + "tool remote command add", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let name : String = @tool.decode_canonical_field( - __golem_decoded, "name", "tool remote command add", - ) catch { - __golem_error => + let name :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "name", + "tool remote command add", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let url : @schema.Url = @tool.decode_canonical_field( - __golem_decoded, "url", "tool remote command add", - ) catch { - __golem_error => + let url :@schema.Url = try { + @tool.decode_canonical_field( + __golem_decoded, + "url", + "tool remote command add", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let track : Array[String] = @tool.decode_canonical_field( - __golem_decoded, "track", "tool remote command add", - ) catch { - __golem_error => + let track :Array[String] = try { + @tool.decode_canonical_field( + __golem_decoded, + "track", + "tool remote command add", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let master : String? = @tool.decode_canonical_field( - __golem_decoded, "master", "tool remote command add", - ) catch { - __golem_error => + let master :String? = try { + @tool.decode_canonical_field( + __golem_decoded, + "master", + "tool remote command add", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let tags : Bool = @tool.decode_canonical_field( - __golem_decoded, "tags", "tool remote command add", - ) catch { - __golem_error => + let tags :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "tags", + "tool remote command add", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let fetch : Bool = @tool.decode_canonical_field( - __golem_decoded, "fetch", "tool remote command add", - ) catch { - __golem_error => + let fetch :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "fetch", + "tool remote command add", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - match - CanonicalRemote::add(verbose, name, url, track, master, tags, fetch) { + match CanonicalRemote::add(verbose, name, url, track, master, tags, fetch) { Ok(__golem_value) => Ok(@tool.invocation_result_empty()) Err(error) => { - let payload = match - CanonicalRemoteError::to_error_payload_value(error) { - Ok(payload) => payload - Err(encode_error) => - return Err( - @toolCommon.ToolError::InvalidResult( - "failed serializing custom tool error: " + encode_error, - ), - ) - } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = + match CanonicalRemoteError::to_error_payload_value(error) { + Ok(payload) => payload + Err(encode_error) => { + return Err( + @toolCommon.ToolError::InvalidResult( + "failed serializing custom tool error: " + encode_error, + ), + ) + } + } + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } @@ -2786,32 +3302,43 @@ async fn __golem_tool_invoke_CanonicalRemote( ), ) } - let name : String = @tool.decode_canonical_field( - __golem_decoded, "name", "tool remote command remove", - ) catch { - __golem_error => + let name :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "name", + "tool remote command remove", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } match CanonicalRemote::remove(name) { Ok(__golem_value) => Ok(@tool.invocation_result_empty()) Err(error) => { - let payload = match - CanonicalRemoteError::to_error_payload_value(error) { - Ok(payload) => payload - Err(encode_error) => - return Err( - @toolCommon.ToolError::InvalidResult( - "failed serializing custom tool error: " + encode_error, - ), - ) - } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = + match CanonicalRemoteError::to_error_payload_value(error) { + Ok(payload) => payload + Err(encode_error) => { + return Err( + @toolCommon.ToolError::InvalidResult( + "failed serializing custom tool error: " + encode_error, + ), + ) + } + } + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } @@ -2827,83 +3354,130 @@ async fn __golem_tool_invoke_CanonicalRemote( ), ) } - let name : String = @tool.decode_canonical_field( - __golem_decoded, "name", "tool remote command set-url", - ) catch { - __golem_error => + let name :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "name", + "tool remote command set-url", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let newurl : @schema.Url = @tool.decode_canonical_field( - __golem_decoded, "newurl", "tool remote command set-url", - ) catch { - __golem_error => + let newurl :@schema.Url = try { + @tool.decode_canonical_field( + __golem_decoded, + "newurl", + "tool remote command set-url", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let oldurl : @schema.Url? = @tool.decode_canonical_field( - __golem_decoded, "oldurl", "tool remote command set-url", - ) catch { - __golem_error => + let oldurl :@schema.Url? = try { + @tool.decode_canonical_field( + __golem_decoded, + "oldurl", + "tool remote command set-url", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let push : Bool = @tool.decode_canonical_field( - __golem_decoded, "push", "tool remote command set-url", - ) catch { - __golem_error => + let push :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "push", + "tool remote command set-url", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let add : Bool = @tool.decode_canonical_field( - __golem_decoded, "add", "tool remote command set-url", - ) catch { - __golem_error => + let add :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "add", + "tool remote command set-url", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let delete : Bool = @tool.decode_canonical_field( - __golem_decoded, "delete", "tool remote command set-url", - ) catch { - __golem_error => + let delete :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "delete", + "tool remote command set-url", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } match CanonicalRemote::set_url(name, newurl, oldurl, push, add, delete) { Ok(__golem_value) => Ok(@tool.invocation_result_empty()) Err(error) => { - let payload = match - CanonicalSetUrlError::to_error_payload_value(error) { - Ok(payload) => payload - Err(encode_error) => - return Err( - @toolCommon.ToolError::InvalidResult( - "failed serializing custom tool error: " + encode_error, - ), - ) - } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = + match CanonicalSetUrlError::to_error_payload_value(error) { + Ok(payload) => payload + Err(encode_error) => { + return Err( + @toolCommon.ToolError::InvalidResult( + "failed serializing custom tool error: " + encode_error, + ), + ) + } + } + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } } } - _ => + _ => { @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), ) + } } } @@ -2911,7 +3485,7 @@ async fn __golem_tool_invoke_CanonicalRemote( /// fn __golem_tool_def_raw_CanonicalStash() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "0.0.0", commands: [ { @@ -2929,60 +3503,63 @@ fn __golem_tool_def_raw_CanonicalStash() -> @tool.ToolDef { long: "verbose", short: None, aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, shape: @toolCommon.FlagShape::CountFlag(Some(3U)), env_var: None, }, ], }, subcommands: [1, 2], - body: Some({ - positionals: { fixed: [], tail: None, }, - options: [ - { - long: "message", - short: Some('\u{6d}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + body: Some( + { + positionals: { fixed: [], tail: None }, + options: [ + { + long: "message", + short: Some('\u{6d}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), ), - ), - default: None, - required: true, - env_var: None, - }, - ], - flags: [ - { - long: "keep-index", - short: Some('\u{6b}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - shape: @toolCommon.FlagShape::BoolFlag({ - default: false, - negatable: false, - }), - env_var: None, + default: None, + required: true, + env_var: None, + }, + ], + flags: [ + { + long: "keep-index", + short: Some('\u{6b}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, + shape: @toolCommon.FlagShape::BoolFlag( + { default: false, negatable: false } + ), + env_var: None, + }, + ], + constraints: [], + stdin: None, + stdout: None, + result: None, + errors: match CanonicalStashError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error }, - ], - constraints: [], - stdin: None, - stdout: None, - result: None, - errors: match CanonicalStashError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + annotations: Some( + { + read_only: false, + destructive: true, + idempotent: false, + open_world: true, + }, + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), }, { name: "pop", @@ -2992,58 +3569,62 @@ fn __golem_tool_def_raw_CanonicalStash() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [ + body: Some( + { + positionals: { + fixed: [ + { + name: "name", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: false, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [ { - name: "name", - doc: { summary: "", description: "", examples: [], }, + long: "index", + short: Some('\u{69}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, value_name: None, - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + shape: @tool.OptionShapeDef::Scalar( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[UInt]), + ), ), default: None, required: false, - accepts_stdio: false, + env_var: None, }, ], - tail: None, - }, - options: [ - { - long: "index", - short: Some('\u{69}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[UInt]), - ), - ), - default: None, - required: false, - env_var: None, + flags: [], + constraints: [], + stdin: None, + stdout: None, + result: None, + errors: match CanonicalStashError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error }, - ], - flags: [], - constraints: [], - stdin: None, - stdout: None, - result: None, - errors: match CanonicalStashError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + annotations: Some( + { + read_only: false, + destructive: true, + idempotent: false, + open_world: true, + }, + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), }, { name: "apply", @@ -3053,63 +3634,67 @@ fn __golem_tool_def_raw_CanonicalStash() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [ + body: Some( + { + positionals: { + fixed: [ + { + name: "name", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: false, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [ { - name: "name", - doc: { summary: "", description: "", examples: [], }, + long: "index", + short: Some('\u{69}'), + aliases: [], + doc: { summary: "", description: "", examples: [] }, value_name: None, - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + shape: @tool.OptionShapeDef::Scalar( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[UInt]), + ), ), default: None, required: false, - accepts_stdio: false, + env_var: None, }, ], - tail: None, - }, - options: [ - { - long: "index", - short: Some('\u{69}'), - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[UInt]), - ), - ), - default: None, - required: false, - env_var: None, + flags: [], + constraints: [], + stdin: None, + stdout: None, + result: None, + errors: match CanonicalStashError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error }, - ], - flags: [], - constraints: [], - stdin: None, - stdout: None, - result: None, - errors: match CanonicalStashError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + annotations: Some( + { + read_only: false, + destructive: true, + idempotent: false, + open_world: true, + }, + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -3124,13 +3709,13 @@ fn __golem_tool_def_prepare_CanonicalStash( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "0.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -3149,7 +3734,7 @@ fn __golem_tool_def_prepare_CanonicalStash( ) let def = prepared def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -3157,13 +3742,15 @@ fn __golem_tool_def_prepare_CanonicalStash( ///| /// fn __golem_tool_def_CanonicalStash() -> @tool.ToolDef { - __golem_tool_def_prepare_CanonicalStash( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_tool_def_prepare_CanonicalStash( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } @@ -3179,21 +3766,28 @@ async fn __golem_tool_invoke_CanonicalStash( __golem_principal : @tool.Principal, ) -> Result[@toolCommon.InvocationResult, @toolCommon.ToolError] { let __golem_def = __golem_tool_def_CanonicalStash() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return @tool.reject_wire_invocation( - __golem_input, - __golem_stdin, - @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), - ) - } - let __golem_decoded = @tool.decode_canonical_input( - __golem_def, __golem_index, __golem_input, "tool stash invocation", - ) catch { - __golem_error => + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return @tool.reject_wire_invocation( + __golem_input, + __golem_stdin, + @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), + ) + } + } + let __golem_decoded = try { + @tool.decode_canonical_input( + __golem_def, + __golem_index, + __golem_input, + "tool stash invocation", + ) + } catch{ + __golem_error => { return @tool.reject_undecoded_invocation(__golem_stdin, __golem_error) + } } match __golem_index { 0 => { @@ -3206,48 +3800,72 @@ async fn __golem_tool_invoke_CanonicalStash( ), ) } - let verbose : UInt = @tool.decode_canonical_field( - __golem_decoded, "verbose", "tool stash command stash", - ) catch { - __golem_error => + let verbose :UInt = try { + @tool.decode_canonical_field( + __golem_decoded, + "verbose", + "tool stash command stash", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let message : String = @tool.decode_canonical_field( - __golem_decoded, "message", "tool stash command stash", - ) catch { - __golem_error => + let message :String = try { + @tool.decode_canonical_field( + __golem_decoded, + "message", + "tool stash command stash", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let keep_index : Bool = @tool.decode_canonical_field( - __golem_decoded, "keep-index", "tool stash command stash", - ) catch { - __golem_error => + let keep_index :Bool = try { + @tool.decode_canonical_field( + __golem_decoded, + "keep-index", + "tool stash command stash", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } match CanonicalStash::stash(verbose, message, keep_index) { Ok(__golem_value) => Ok(@tool.invocation_result_empty()) Err(error) => { - let payload = match - CanonicalStashError::to_error_payload_value(error) { + let payload = match CanonicalStashError::to_error_payload_value(error) { Ok(payload) => payload - Err(encode_error) => + Err(encode_error) => { return Err( @toolCommon.ToolError::InvalidResult( "failed serializing custom tool error: " + encode_error, ), ) + } } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } @@ -3263,40 +3881,57 @@ async fn __golem_tool_invoke_CanonicalStash( ), ) } - let name : String? = @tool.decode_canonical_field( - __golem_decoded, "name", "tool stash command pop", - ) catch { - __golem_error => + let name :String? = try { + @tool.decode_canonical_field( + __golem_decoded, + "name", + "tool stash command pop", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let index : UInt? = @tool.decode_canonical_field( - __golem_decoded, "index", "tool stash command pop", - ) catch { - __golem_error => + let index :UInt? = try { + @tool.decode_canonical_field( + __golem_decoded, + "index", + "tool stash command pop", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } match CanonicalStash::pop(name, index) { Ok(__golem_value) => Ok(@tool.invocation_result_empty()) Err(error) => { - let payload = match - CanonicalStashError::to_error_payload_value(error) { + let payload = match CanonicalStashError::to_error_payload_value(error) { Ok(payload) => payload - Err(encode_error) => + Err(encode_error) => { return Err( @toolCommon.ToolError::InvalidResult( "failed serializing custom tool error: " + encode_error, ), ) + } } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } @@ -3312,51 +3947,69 @@ async fn __golem_tool_invoke_CanonicalStash( ), ) } - let name : String? = @tool.decode_canonical_field( - __golem_decoded, "name", "tool stash command apply", - ) catch { - __golem_error => + let name :String? = try { + @tool.decode_canonical_field( + __golem_decoded, + "name", + "tool stash command apply", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } - let index : UInt? = @tool.decode_canonical_field( - __golem_decoded, "index", "tool stash command apply", - ) catch { - __golem_error => + let index :UInt? = try { + @tool.decode_canonical_field( + __golem_decoded, + "index", + "tool stash command apply", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } match CanonicalStash::apply(name, index) { Ok(__golem_value) => Ok(@tool.invocation_result_empty()) Err(error) => { - let payload = match - CanonicalStashError::to_error_payload_value(error) { + let payload = match CanonicalStashError::to_error_payload_value(error) { Ok(payload) => payload - Err(encode_error) => + Err(encode_error) => { return Err( @toolCommon.ToolError::InvalidResult( "failed serializing custom tool error: " + encode_error, ), ) + } } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } } } - _ => + _ => { @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), ) + } } } @@ -3364,7 +4017,7 @@ async fn __golem_tool_invoke_CanonicalStash( /// fn __golem_tool_def_raw_CanonicalBigBound() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "0.0.0", commands: [ { @@ -3375,53 +4028,57 @@ fn __golem_tool_def_raw_CanonicalBigBound() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { fixed: [], tail: None, }, - options: [ - { - long: "count", - short: None, - aliases: [], - doc: { summary: "", description: "", examples: [], }, - value_name: None, - shape: @tool.OptionShapeDef::Scalar( - @tool.refine_numeric( - @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[UInt64]), + body: Some( + { + positionals: { fixed: [], tail: None }, + options: [ + { + long: "count", + short: None, + aliases: [], + doc: { summary: "", description: "", examples: [] }, + value_name: None, + shape: @tool.OptionShapeDef::Scalar( + @tool.refine_numeric( + @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[UInt64]), + ), + Some("0"), + Some("18446744073709551615"), + None, ), - Some("0"), - Some("18446744073709551615"), - None, ), - ), - default: None, - required: false, - env_var: None, + default: None, + required: false, + env_var: None, + }, + ], + flags: [], + constraints: [], + stdin: None, + stdout: None, + result: None, + errors: match CanonicalGrepError::error_cases() { + Ok(__golem_errors) => __golem_errors + Err(__golem_error) => raise __golem_error }, - ], - flags: [], - constraints: [], - stdin: None, - stdout: None, - result: None, - errors: match CanonicalGrepError::error_cases() { - Ok(__golem_errors) => __golem_errors - Err(__golem_error) => raise __golem_error + annotations: Some( + { + read_only: false, + destructive: true, + idempotent: false, + open_world: true, + }, + ), }, - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -3436,13 +4093,13 @@ fn __golem_tool_def_prepare_CanonicalBigBound( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "0.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -3461,7 +4118,7 @@ fn __golem_tool_def_prepare_CanonicalBigBound( ) let def = prepared def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -3469,13 +4126,15 @@ fn __golem_tool_def_prepare_CanonicalBigBound( ///| /// fn __golem_tool_def_CanonicalBigBound() -> @tool.ToolDef { - __golem_tool_def_prepare_CanonicalBigBound( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_tool_def_prepare_CanonicalBigBound( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } @@ -3491,21 +4150,28 @@ async fn __golem_tool_invoke_CanonicalBigBound( __golem_principal : @tool.Principal, ) -> Result[@toolCommon.InvocationResult, @toolCommon.ToolError] { let __golem_def = __golem_tool_def_CanonicalBigBound() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return @tool.reject_wire_invocation( - __golem_input, - __golem_stdin, - @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), - ) - } - let __golem_decoded = @tool.decode_canonical_input( - __golem_def, __golem_index, __golem_input, "tool canonical-big-bound invocation", - ) catch { - __golem_error => + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return @tool.reject_wire_invocation( + __golem_input, + __golem_stdin, + @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), + ) + } + } + let __golem_decoded = try { + @tool.decode_canonical_input( + __golem_def, + __golem_index, + __golem_input, + "tool canonical-big-bound invocation", + ) + } catch{ + __golem_error => { return @tool.reject_undecoded_invocation(__golem_stdin, __golem_error) + } } match __golem_index { 0 => { @@ -3518,43 +4184,54 @@ async fn __golem_tool_invoke_CanonicalBigBound( ), ) } - let count : UInt64? = @tool.decode_canonical_field( - __golem_decoded, "count", "tool canonical-big-bound command canonical-big-bound", - ) catch { - __golem_error => + let count :UInt64? = try { + @tool.decode_canonical_field( + __golem_decoded, + "count", + "tool canonical-big-bound command canonical-big-bound", + ) + } catch{ + __golem_error => { return @tool.reject_decoded_invocation( - __golem_decoded, __golem_stdin, __golem_error, + __golem_decoded, + __golem_stdin, + __golem_error, ) + } } match CanonicalBigBound::canonical_big_bound(count) { Ok(__golem_value) => Ok(@tool.invocation_result_empty()) Err(error) => { - let payload = match - CanonicalGrepError::to_error_payload_value(error) { + let payload = match CanonicalGrepError::to_error_payload_value(error) { Ok(payload) => payload - Err(encode_error) => + Err(encode_error) => { return Err( @toolCommon.ToolError::InvalidResult( "failed serializing custom tool error: " + encode_error, ), ) + } } - let payload = @tool.encode_error_payload(payload) catch { - @asyncCore.Cancelled::Cancelled as error => raise error - @toolCommon.ToolError::InvalidResult(message) => + let payload = try { + @tool.encode_error_payload(payload) + } catch{ + @asyncCore.Cancelled::Cancelled as error => raise error + @toolCommon.ToolError::InvalidResult(message) => { return Err(@toolCommon.ToolError::InvalidResult(message)) - error => raise error + } + error => raise error } Err(@toolCommon.ToolError::CustomError(payload)) } } } - _ => + _ => { @tool.reject_decoded_invocation( __golem_decoded, __golem_stdin, @toolCommon.ToolError::InvalidCommandPath(__golem_command_path), ) + } } } @@ -3586,7 +4263,7 @@ fn init { __golem_tool_def_CanonicalBigBound(), __golem_tool_invoke_CanonicalBigBound, ) - } catch { + } catch{ error => abort("failed to register generated tools: " + repr(error)) } } diff --git a/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/moon.pkg b/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/moon.pkg index f68b6c9220..908e75b256 100644 --- a/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/moon.pkg +++ b/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/moon.pkg @@ -1,7 +1,7 @@ import { "golemcloud/golem_sdk/logging", "golemcloud/golem_sdk/webhook", - "golemcloud/golem_sdk/gen", + "golemcloud/golem_sdk/gen" @gen, "golemcloud/golem_sdk/agents", "golemcloud/golem_sdk/schema", "golemcloud/golem_sdk/interface/golem/agent/common", diff --git a/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/pkg.generated.mbti b/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/pkg.generated.mbti index 190500ebd2..108fc7278e 100644 --- a/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/pkg.generated.mbti +++ b/sdks/moonbit/golem_sdk_example1/golem_moonbit_examples/pkg.generated.mbti @@ -18,10 +18,48 @@ import { } // Values +pub fn cabi_realloc(Int, Int, Int, Int) -> Int + pub fn collect_app_config_overrides(AppConfigOverride, Array[String]) -> Array[@common.TypedAgentConfigValue] raise @common.AgentError pub fn collect_database_config_overrides(DatabaseConfigOverride, Array[String]) -> Array[@common.TypedAgentConfigValue] raise @common.AgentError +pub fn wasmExportAsyncInitialize(Int, Int, Int) -> Int + +pub fn wasmExportAsyncInvokeGolemAgentGuest(Int, Int, Int) -> Int + +pub fn wasmExportAsyncInvokeGolemToolGuest(Int, Int, Int) -> Int + +pub fn wasmExportAsyncLoad(Int, Int, Int) -> Int + +pub fn wasmExportAsyncSave(Int, Int, Int) -> Int + +pub fn wasmExportDiscoverAgentTypes() -> Int + +pub fn wasmExportDiscoverAgentTypesPostReturn(Int) -> Unit + +pub fn wasmExportDiscoverTools() -> Int + +pub fn wasmExportDiscoverToolsPostReturn(Int) -> Unit + +pub fn wasmExportGetDefinition() -> Int + +pub fn wasmExportGetDefinitionPostReturn(Int) -> Unit + +pub fn wasmExportGetTool(Int, Int) -> Int + +pub fn wasmExportGetToolPostReturn(Int) -> Unit + +pub fn wasmExportInitialize(Int) -> Int + +pub fn wasmExportInvokeGolemAgentGuest(Int) -> Int + +pub fn wasmExportInvokeGolemToolGuest(Int) -> Int + +pub fn wasmExportLoad(Int, Int, Int, Int) -> Int + +pub fn wasmExportSave() -> Int + // Errors // Types and methods diff --git a/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/golem_tool_middlewares.mbt b/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/golem_tool_middlewares.mbt index c3bddf50d0..9ffa5af60f 100644 --- a/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/golem_tool_middlewares.mbt +++ b/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/golem_tool_middlewares.mbt @@ -2,10 +2,9 @@ ///| /// -fn[T] __golem_middleware_tool_concat_array( - left : Array[T], - right : Array[T], -) -> Array[T] { +fn[T] __golem_middleware_tool_concat_array(left : Array[T], right : Array[T]) -> Array[ + T, +] { let result = left.copy() for value in right { result.push(value) @@ -43,14 +42,12 @@ fn __golem_middleware_tool_rebase_node( ///| /// -fn __golem_middleware_tool_extract_prepared( - def : @tool.ToolDef, -) -> @tool.ToolDef { +fn __golem_middleware_tool_extract_prepared(def : @tool.ToolDef) -> @tool.ToolDef { { version: def.version, - commands: def.commands[1:].map(node => { - __golem_middleware_tool_rebase_node(node, -1) - }), + commands: def.commands[1:].map( + node => __golem_middleware_tool_rebase_node(node, -1) + ), } } @@ -63,25 +60,27 @@ fn __golem_middleware_tool_append_prepared( let offset = def.commands.length() let commands = def.commands.copy() let root = commands[0] - commands[0] = { + commands[0] = { name: root.name, aliases: root.aliases, doc: root.doc, globals: root.globals, - subcommands: __golem_middleware_tool_concat_array(root.subcommands, [offset]), + subcommands: __golem_middleware_tool_concat_array( + root.subcommands, [offset] + ), body: root.body, } for node in child.commands { commands.push(__golem_middleware_tool_rebase_node(node, offset)) } - { version: def.version, commands, } + { version: def.version, commands } } ///| /// fn __golem_middleware_tool_def_raw_Messages() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "0.0.0", commands: [ { @@ -92,64 +91,70 @@ fn __golem_middleware_tool_def_raw_Messages() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [1], body: None, }, { name: "send", aliases: [], - doc: { summary: "", description: "", examples: [], }, - globals: { options: [], flags: [], }, + doc: { summary: "", description: "", examples: [] }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [ + body: Some( + { + positionals: { + fixed: [ + { + name: "message", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [], + flags: [], + constraints: [], + stdin: None, + stdout: None, + result: Some( { - name: "message", - doc: { summary: "", description: "", examples: [], }, - value_name: None, type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + (@schema.TypeTag::{ } : @schema.TypeTag[String]), ), - default: None, - required: true, - accepts_stdio: false, + doc: { summary: "", description: "", examples: [] }, + formatters: [ + { + name: "default", + doc: { summary: "", description: "", examples: [] }, + }, + ], + default_formatter: "default", }, - ], - tail: None, - }, - options: [], - flags: [], - constraints: [], - stdin: None, - stdout: None, - result: Some({ - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), ), - doc: { summary: "", description: "", examples: [], }, - formatters: [ + errors: [], + annotations: Some( { - name: "default", - doc: { summary: "", description: "", examples: [], }, + read_only: false, + destructive: true, + idempotent: false, + open_world: true, }, - ], - default_formatter: "default", - }), - errors: [], - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), + }, + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -164,13 +169,13 @@ fn __golem_middleware_tool_def_prepare_Messages( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "0.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -189,7 +194,7 @@ fn __golem_middleware_tool_def_prepare_Messages( ) let def = prepared def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -197,13 +202,15 @@ fn __golem_middleware_tool_def_prepare_Messages( ///| /// fn __golem_middleware_tool_def_Messages() -> @tool.ToolDef { - __golem_middleware_tool_def_prepare_Messages( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_middleware_tool_def_prepare_Messages( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } @@ -212,7 +219,7 @@ fn __golem_middleware_tool_def_Messages() -> @tool.ToolDef { /// fn __golem_middleware_tool_def_raw_PublicFiles() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "0.0.0", commands: [ { @@ -223,64 +230,70 @@ fn __golem_middleware_tool_def_raw_PublicFiles() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [1], body: None, }, { name: "read", aliases: [], - doc: { summary: "", description: "", examples: [], }, - globals: { options: [], flags: [], }, + doc: { summary: "", description: "", examples: [] }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [ + body: Some( + { + positionals: { + fixed: [ + { + name: "path", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [], + flags: [], + constraints: [], + stdin: None, + stdout: None, + result: Some( { - name: "path", - doc: { summary: "", description: "", examples: [], }, - value_name: None, type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + (@schema.TypeTag::{ } : @schema.TypeTag[String]), ), - default: None, - required: true, - accepts_stdio: false, + doc: { summary: "", description: "", examples: [] }, + formatters: [ + { + name: "default", + doc: { summary: "", description: "", examples: [] }, + }, + ], + default_formatter: "default", }, - ], - tail: None, - }, - options: [], - flags: [], - constraints: [], - stdin: None, - stdout: None, - result: Some({ - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), ), - doc: { summary: "", description: "", examples: [], }, - formatters: [ + errors: [], + annotations: Some( { - name: "default", - doc: { summary: "", description: "", examples: [], }, + read_only: false, + destructive: true, + idempotent: false, + open_world: true, }, - ], - default_formatter: "default", - }), - errors: [], - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), + }, + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -295,13 +308,13 @@ fn __golem_middleware_tool_def_prepare_PublicFiles( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "0.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -320,7 +333,7 @@ fn __golem_middleware_tool_def_prepare_PublicFiles( ) let def = prepared def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -328,13 +341,15 @@ fn __golem_middleware_tool_def_prepare_PublicFiles( ///| /// fn __golem_middleware_tool_def_PublicFiles() -> @tool.ToolDef { - __golem_middleware_tool_def_prepare_PublicFiles( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_middleware_tool_def_prepare_PublicFiles( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } @@ -343,7 +358,7 @@ fn __golem_middleware_tool_def_PublicFiles() -> @tool.ToolDef { /// fn __golem_middleware_tool_def_raw_Storage() -> @tool.ToolDef { try { - let def : @tool.ToolDef = { + let def :@tool.ToolDef = { version: "0.0.0", commands: [ { @@ -354,64 +369,70 @@ fn __golem_middleware_tool_def_raw_Storage() -> @tool.ToolDef { description: "", examples: [], }, - globals: { options: [], flags: [], }, + globals: { options: [], flags: [] }, subcommands: [1], body: None, }, { name: "fetch", aliases: [], - doc: { summary: "", description: "", examples: [], }, - globals: { options: [], flags: [], }, + doc: { summary: "", description: "", examples: [] }, + globals: { options: [], flags: [] }, subcommands: [], - body: Some({ - positionals: { - fixed: [ + body: Some( + { + positionals: { + fixed: [ + { + name: "key", + doc: { summary: "", description: "", examples: [] }, + value_name: None, + type_: @schema.into_schema_graph( + (@schema.TypeTag::{ } : @schema.TypeTag[String]), + ), + default: None, + required: true, + accepts_stdio: false, + }, + ], + tail: None, + }, + options: [], + flags: [], + constraints: [], + stdin: None, + stdout: None, + result: Some( { - name: "key", - doc: { summary: "", description: "", examples: [], }, - value_name: None, type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), + (@schema.TypeTag::{ } : @schema.TypeTag[String]), ), - default: None, - required: true, - accepts_stdio: false, + doc: { summary: "", description: "", examples: [] }, + formatters: [ + { + name: "default", + doc: { summary: "", description: "", examples: [] }, + }, + ], + default_formatter: "default", }, - ], - tail: None, - }, - options: [], - flags: [], - constraints: [], - stdin: None, - stdout: None, - result: Some({ - type_: @schema.into_schema_graph( - (@schema.TypeTag::{ } : @schema.TypeTag[String]), ), - doc: { summary: "", description: "", examples: [], }, - formatters: [ + errors: [], + annotations: Some( { - name: "default", - doc: { summary: "", description: "", examples: [], }, + read_only: false, + destructive: true, + idempotent: false, + open_world: true, }, - ], - default_formatter: "default", - }), - errors: [], - annotations: Some({ - read_only: false, - destructive: true, - idempotent: false, - open_world: true, - }), - }), + ), + }, + ), }, ], } def - } catch { + } catch{ error => abort("invalid generated raw tool definition: " + repr(error)) } } @@ -426,13 +447,13 @@ fn __golem_middleware_tool_def_prepare_Storage( override_aliases : Array[String]?, ) -> @tool.ToolDef { try { - let carrier : @tool.ToolDef = { + let carrier :@tool.ToolDef = { version: "0.0.0", commands: [ { name: "__golem_ancestry", aliases: [], - doc: { summary: "", description: "", examples: [], }, + doc: { summary: "", description: "", examples: [] }, globals: strict_ancestors, subcommands: [], body: None, @@ -451,7 +472,7 @@ fn __golem_middleware_tool_def_prepare_Storage( ) let def = prepared def - } catch { + } catch{ error => abort("invalid generated prepared tool definition: " + repr(error)) } } @@ -459,25 +480,29 @@ fn __golem_middleware_tool_def_prepare_Storage( ///| /// fn __golem_middleware_tool_def_Storage() -> @tool.ToolDef { - __golem_middleware_tool_def_prepare_Storage( - { options: [], flags: [], }, - { options: [], flags: [], }, - None, - None, - None, - ).normalize_inherited_globals() catch { + try { + __golem_middleware_tool_def_prepare_Storage( + { options: [], flags: [] }, + { options: [], flags: [] }, + None, + None, + None, + ).normalize_inherited_globals() + } catch{ error => abort("invalid generated tool definition: " + repr(error)) } } ///| /// -fn[T : @schema.IntoSchema + @schema.FromSchema, E] __golem_middleware_decode_canonical_field( +fn[T : @schema.IntoSchema + @schema.FromSchema, E] __golem_middleware_decode_canonical_field( fields : Array[@tool.CanonicalInputValue], name : String, context : String, ) -> Result[T, @toolMiddleware.ToolInvokeError[E]] { - try @tool.decode_canonical_field(fields, name, context) catch { + try { + @tool.decode_canonical_field(fields, name, context) + } catch{ @toolCommon.ToolError::InvalidToolName(name) => Err(@toolMiddleware.ToolInvokeError::InvalidToolName(name)) @toolCommon.ToolError::InvalidCommandPath(path) => @@ -515,38 +540,48 @@ pub async fn MessagesUnderlying::send( ) -> Result[String, @toolMiddleware.ToolInvokeError[@tool.NoToolError]] { let __golem_command_path = ["send"] let __golem_def = __golem_middleware_tool_def_Messages() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return Err( - @toolMiddleware.ToolInvokeError::InvalidCommandPath( - __golem_command_path, - ), - ) - } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { - __golem_error => + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return Err( + @toolMiddleware.ToolInvokeError::InvalidCommandPath( + __golem_command_path, + ), + ) + } + } + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ + __golem_error => { return Err( @toolMiddleware.ToolInvokeError::InvalidInput(repr(__golem_error)), ) + } } - let __golem_values : Array[(String, @model.SchemaValue)] = [] + let __golem_values :Array[(String, @model.SchemaValue)] = [] __golem_values.push(("message", @schema.to_value_as(message))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { - __golem_error => + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ + __golem_error => { return Err( @toolMiddleware.ToolInvokeError::InvalidInput(repr(__golem_error)), ) + } } - let __golem_result = match - self.underlying.invoke_with(__golem_command_path, __golem_input, None, fn( - _, - ) { - Err("underlying returned a custom error for an infallible command") - }) { - Ok(__golem_result) => __golem_result - Err(__golem_error) => return Err(__golem_error) + let __golem_result = { + match self + .underlying + .invoke_with( + __golem_command_path, __golem_input, None, fn(_) { + Err("underlying returned a custom error for an infallible command") + }, + ) { + Ok(__golem_result) => __golem_result + Err(__golem_error) => return Err(__golem_error) + } } @toolMiddleware.decode_result_value(__golem_result) } @@ -559,44 +594,54 @@ pub struct StorageUnderlying { ///| /// -pub async fn StorageUnderlying::fetch( - self : StorageUnderlying, - key : String, -) -> Result[String, @toolMiddleware.ToolInvokeError[@tool.NoToolError]] { +pub async fn StorageUnderlying::fetch(self : StorageUnderlying, key : String) -> Result[ + String, + @toolMiddleware.ToolInvokeError[@tool.NoToolError], +] { let __golem_command_path = ["fetch"] let __golem_def = __golem_middleware_tool_def_Storage() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return Err( - @toolMiddleware.ToolInvokeError::InvalidCommandPath( - __golem_command_path, - ), - ) - } - let __golem_model = __golem_def.canonical_input_model(__golem_index) catch { - __golem_error => + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return Err( + @toolMiddleware.ToolInvokeError::InvalidCommandPath( + __golem_command_path, + ), + ) + } + } + let __golem_model = try { + __golem_def.canonical_input_model(__golem_index) + } catch{ + __golem_error => { return Err( @toolMiddleware.ToolInvokeError::InvalidInput(repr(__golem_error)), ) + } } - let __golem_values : Array[(String, @model.SchemaValue)] = [] + let __golem_values :Array[(String, @model.SchemaValue)] = [] __golem_values.push(("key", @schema.to_value_as(key))) - let __golem_input = @tool.build_canonical_input(__golem_model, __golem_values) catch { - __golem_error => + let __golem_input = try { + @tool.build_canonical_input(__golem_model, __golem_values) + } catch{ + __golem_error => { return Err( @toolMiddleware.ToolInvokeError::InvalidInput(repr(__golem_error)), ) + } } - let __golem_result = match - self.underlying.invoke_with(__golem_command_path, __golem_input, None, fn( - _, - ) { - Err("underlying returned a custom error for an infallible command") - }) { - Ok(__golem_result) => __golem_result - Err(__golem_error) => return Err(__golem_error) + let __golem_result = { + match self + .underlying + .invoke_with( + __golem_command_path, __golem_input, None, fn(_) { + Err("underlying returned a custom error for an infallible command") + }, + ) { + Ok(__golem_result) => __golem_result + Err(__golem_error) => return Err(__golem_error) + } } @toolMiddleware.decode_result_value(__golem_result) } @@ -624,22 +669,26 @@ async fn __golem_monomorphic_tool_middleware_invoke_MessagePolicy( ] { let __golem_command_path = __golem_invocation.command_path() let __golem_def = __golem_middleware_tool_def_Messages() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return Err( - @toolMiddleware.ToolInvokeError::InvalidCommandPath( - __golem_command_path, - ), - ) - } - let __golem_decoded = match - __golem_invocation.decode_input( - __golem_def, __golem_index, "tool middleware message-policy invocation", + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return Err( + @toolMiddleware.ToolInvokeError::InvalidCommandPath( + __golem_command_path, + ), + ) + } + } + let __golem_decoded = { + match __golem_invocation.decode_input( + __golem_def, + __golem_index, + "tool middleware message-policy invocation", ) { - Ok(__golem_decoded) => __golem_decoded - Err(__golem_error) => return Err(__golem_error) + Ok(__golem_decoded) => __golem_decoded + Err(__golem_error) => return Err(__golem_error) + } } if __golem_def.command_index_by_path(["send"]) == Some(__golem_index) { if __golem_invocation.stdin() is Some(_) { @@ -649,25 +698,31 @@ async fn __golem_monomorphic_tool_middleware_invoke_MessagePolicy( ), ) } - let message : String = match - __golem_middleware_decode_canonical_field( - __golem_decoded, "message", "tool middleware message-policy command send", + let message :String = { + match __golem_middleware_decode_canonical_field( + __golem_decoded, + "message", + "tool middleware message-policy command send", ) { - Ok(__golem_value) => __golem_value - Err(__golem_error) => return Err(__golem_error) - } - let __golem_expected = MessagesUnderlying::{ - underlying: __golem_underlying, + Ok(__golem_value) => __golem_value + Err(__golem_error) => return Err(__golem_error) + } } + let __golem_expected = + MessagesUnderlying::{ underlying: __golem_underlying } match MessagePolicy::send(__golem_expected, message) { - Ok(__golem_result) => + Ok(__golem_result) => { return __golem_invocation.typed_result_value(__golem_result) - Err(__golem_error) => + } + Err(__golem_error) => { return Err( - __golem_invocation.encode_handler_error(__golem_error, fn(_) { - Err("infallible middleware handler returned a custom tool error") - }), + __golem_invocation.encode_handler_error( + __golem_error, fn(_) { + Err("infallible middleware handler returned a custom tool error") + }, + ), ) + } } } Err(@toolMiddleware.ToolInvokeError::InvalidCommandPath(__golem_command_path)) @@ -684,22 +739,26 @@ async fn __golem_monomorphic_tool_middleware_invoke_FileAdapter( ] { let __golem_command_path = __golem_invocation.command_path() let __golem_def = __golem_middleware_tool_def_PublicFiles() - let __golem_index = match - __golem_def.command_index_by_path(__golem_command_path) { - Some(__golem_index) => __golem_index - None => - return Err( - @toolMiddleware.ToolInvokeError::InvalidCommandPath( - __golem_command_path, - ), - ) - } - let __golem_decoded = match - __golem_invocation.decode_input( - __golem_def, __golem_index, "tool middleware file-adapter invocation", + let __golem_index = + match __golem_def.command_index_by_path(__golem_command_path) { + Some(__golem_index) => __golem_index + None => { + return Err( + @toolMiddleware.ToolInvokeError::InvalidCommandPath( + __golem_command_path, + ), + ) + } + } + let __golem_decoded = { + match __golem_invocation.decode_input( + __golem_def, + __golem_index, + "tool middleware file-adapter invocation", ) { - Ok(__golem_decoded) => __golem_decoded - Err(__golem_error) => return Err(__golem_error) + Ok(__golem_decoded) => __golem_decoded + Err(__golem_error) => return Err(__golem_error) + } } if __golem_def.command_index_by_path(["read"]) == Some(__golem_index) { if __golem_invocation.stdin() is Some(_) { @@ -709,25 +768,30 @@ async fn __golem_monomorphic_tool_middleware_invoke_FileAdapter( ), ) } - let path : String = match - __golem_middleware_decode_canonical_field( - __golem_decoded, "path", "tool middleware file-adapter command read", + let path :String = { + match __golem_middleware_decode_canonical_field( + __golem_decoded, + "path", + "tool middleware file-adapter command read", ) { - Ok(__golem_value) => __golem_value - Err(__golem_error) => return Err(__golem_error) - } - let __golem_expected = StorageUnderlying::{ - underlying: __golem_underlying, + Ok(__golem_value) => __golem_value + Err(__golem_error) => return Err(__golem_error) + } } + let __golem_expected = StorageUnderlying::{ underlying: __golem_underlying } match FileAdapter::read(__golem_expected, path) { - Ok(__golem_result) => + Ok(__golem_result) => { return __golem_invocation.typed_result_value(__golem_result) - Err(__golem_error) => + } + Err(__golem_error) => { return Err( - __golem_invocation.encode_handler_error(__golem_error, fn(_) { - Err("infallible middleware handler returned a custom tool error") - }), + __golem_invocation.encode_handler_error( + __golem_error, fn(_) { + Err("infallible middleware handler returned a custom tool error") + }, + ), ) + } } } Err(@toolMiddleware.ToolInvokeError::InvalidCommandPath(__golem_command_path)) @@ -758,10 +822,12 @@ fn __golem_register_tool_middlewares() -> Unit raise { description: "", examples: [], }, - scope: @toolMiddleware.ToolMiddlewareScope::Monomorphic({ - presented: __golem_middleware_tool_def_Messages().to_tool(), - expected: __golem_middleware_tool_def_Messages().to_tool(), - }), + scope: @toolMiddleware.ToolMiddlewareScope::Monomorphic( + { + presented: __golem_middleware_tool_def_Messages().to_tool(), + expected: __golem_middleware_tool_def_Messages().to_tool(), + }, + ), }, __golem_monomorphic_tool_middleware_invoke_MessagePolicy, ) @@ -774,10 +840,12 @@ fn __golem_register_tool_middlewares() -> Unit raise { description: "", examples: [], }, - scope: @toolMiddleware.ToolMiddlewareScope::Monomorphic({ - presented: __golem_middleware_tool_def_PublicFiles().to_tool(), - expected: __golem_middleware_tool_def_Storage().to_tool(), - }), + scope: @toolMiddleware.ToolMiddlewareScope::Monomorphic( + { + presented: __golem_middleware_tool_def_PublicFiles().to_tool(), + expected: __golem_middleware_tool_def_Storage().to_tool(), + }, + ), }, __golem_monomorphic_tool_middleware_invoke_FileAdapter, ) @@ -786,7 +854,9 @@ fn __golem_register_tool_middlewares() -> Unit raise { ///| /// fn init { - __golem_register_tool_middlewares() catch { + try { + __golem_register_tool_middlewares() + } catch{ error => abort("failed to register generated tool middleware: " + repr(error)) } diff --git a/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/moon.pkg b/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/moon.pkg index 1a6eba8ce9..128426daa0 100644 --- a/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/moon.pkg +++ b/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/moon.pkg @@ -2,7 +2,7 @@ import { "golemcloud/golem_sdk/tool-core" @tool, "golemcloud/golem_sdk/tool-middleware" @toolMiddleware, "golemcloud/golem_sdk/gen-tool-middleware" @gen, - "golemcloud/golem_sdk/schema", // Generated by golem_sdk_tools + "golemcloud/golem_sdk/schema" @schema, // Generated by golem_sdk_tools "golemcloud/golem_sdk/schema_model" @model, // Generated by golem_sdk_tools "golemcloud/golem_sdk/interface/golem/tool/common" @toolCommon, // Generated by golem_sdk_tools } diff --git a/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/pkg.generated.mbti b/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/pkg.generated.mbti index 0ec017a8d0..71672873eb 100644 --- a/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/pkg.generated.mbti +++ b/sdks/moonbit/golem_sdk_example1/golem_tool_middleware_examples/pkg.generated.mbti @@ -9,6 +9,20 @@ import { // Values pub async fn audit(@tool-middleware.RawToolInvocation, @tool-middleware.UnderlyingTool) -> Result[@tool-middleware.RawInvocationResult, @tool-middleware.ToolInvokeError[@tool-middleware.RawTypedSchemaValue]] +pub fn cabi_realloc(Int, Int, Int, Int) -> Int + +pub fn wasmExportAsyncInvokeToolMiddleware(Int, Int, Int) -> Int + +pub fn wasmExportDiscoverToolMiddlewares() -> Int + +pub fn wasmExportDiscoverToolMiddlewaresPostReturn(Int) -> Unit + +pub fn wasmExportGetToolMiddleware(Int, Int) -> Int + +pub fn wasmExportGetToolMiddlewarePostReturn(Int) -> Unit + +pub fn wasmExportInvokeToolMiddleware(Int) -> Int + // Errors // Types and methods