Skip to main content

golem_schema/schema/tool/
mod.rs

1// Copyright 2024-2026 Golem Cloud
2//
3// Licensed under the Golem Source License v1.1 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://license.golem.cloud/LICENSE
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Native, serializable data model for `golem:tool/common@0.1.0` tool metadata.
16//!
17//! A *tool* is a callable unit described by a single metadata record. The model
18//! is CLI-native (commands, subcommands, options, flags, positionals).
19//!
20//! Types and values are not modeled here: every input/output type and every
21//! metadata-time value is expressed with the shared `golem:core/types@2.0.0`
22//! schema model, exactly as the agent model does. A [`Tool`] owns a single
23//! [`SchemaGraph`] — the named-type registry shared by all of its commands —
24//! and each typed position embeds a recursive [`SchemaType`]; metadata-time
25//! defaults and `value-is` literals embed a recursive [`SchemaValue`]. The
26//! flattening into the WIT `schema-graph` / `type-node-index` /
27//! `schema-value-tree` wire form happens in [`wit`].
28//!
29//! The only tool-specific recursion site is the command tree: a flattened
30//! command hierarchy with the root at index 0 and children referenced by
31//! [`CommandIndex`].
32//!
33//! Producer-side construction invariants are checked by [`validation`]. The
34//! deterministic per-command input record shape shared by tool clients and
35//! tool implementations is defined by [`canonical`].
36
37use crate::schema::graph::SchemaGraph;
38use crate::schema::schema_type::SchemaType;
39use crate::schema::schema_value::SchemaValue;
40use serde::{Deserialize, Serialize};
41
42pub mod canonical;
43pub mod compatibility;
44pub mod constraints;
45#[cfg(feature = "full")]
46mod protobuf;
47pub mod validation;
48#[cfg(all(
49    any(feature = "guest", feature = "host"),
50    not(all(feature = "guest", feature = "host"))
51))]
52pub mod wit;
53
54/// Index into [`CommandTree::nodes`].
55#[derive(
56    Debug,
57    Clone,
58    Copy,
59    PartialEq,
60    Eq,
61    Hash,
62    PartialOrd,
63    Ord,
64    Serialize,
65    Deserialize,
66    golem_schema_derive::IntoSchema,
67    golem_schema_derive::FromSchema,
68)]
69#[cfg_attr(
70    feature = "full",
71    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
72)]
73#[cfg_attr(feature = "full", desert(transparent))]
74#[serde(transparent)]
75pub struct CommandIndex(pub i32);
76
77impl CommandIndex {
78    /// Returns the index as a `usize`, or `None` if it is negative.
79    pub fn as_usize(self) -> Option<usize> {
80        usize::try_from(self.0).ok()
81    }
82}
83
84/// Top-level tool metadata record.
85#[derive(
86    Debug,
87    Clone,
88    PartialEq,
89    Serialize,
90    Deserialize,
91    golem_schema_derive::IntoSchema,
92    golem_schema_derive::FromSchema,
93)]
94#[cfg_attr(
95    feature = "full",
96    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
97)]
98#[cfg_attr(feature = "full", desert(evolution()))]
99pub struct Tool {
100    pub version: String,
101    pub requires_filesystem: bool,
102    pub commands: CommandTree,
103    /// Named-type registry shared by this tool's commands. Typed positions in
104    /// the command tree may reference these definitions via
105    /// [`SchemaType::Ref`]. Use [`SchemaGraph::empty`] when there are no shared
106    /// definitions to declare.
107    ///
108    /// The graph's `root` field is a structurally-required placeholder (empty
109    /// record); only `defs` is consumed. The real roots are the per-position
110    /// embedded [`SchemaType`]s.
111    #[serde(default = "SchemaGraph::empty")]
112    pub schema: SchemaGraph,
113}
114
115impl Tool {
116    /// Returns the name of the tool: the name of the root node of its command tree.
117    pub fn name(&self) -> Option<&str> {
118        self.commands.nodes.first().map(|node| node.name.as_str())
119    }
120}
121
122/// Metadata describing a tool middleware component.
123#[derive(
124    Debug,
125    Clone,
126    PartialEq,
127    Serialize,
128    Deserialize,
129    golem_schema_derive::IntoSchema,
130    golem_schema_derive::FromSchema,
131)]
132#[cfg_attr(
133    feature = "full",
134    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
135)]
136#[cfg_attr(feature = "full", desert(evolution()))]
137pub struct ToolMiddleware {
138    pub name: String,
139    pub version: String,
140    pub aliases: Vec<String>,
141    pub doc: Doc,
142    pub scope: ToolMiddlewareScope,
143    pub parameter_schema: SchemaGraph,
144}
145
146#[derive(
147    Debug,
148    Clone,
149    PartialEq,
150    Serialize,
151    Deserialize,
152    golem_schema_derive::IntoSchema,
153    golem_schema_derive::FromSchema,
154)]
155#[cfg_attr(
156    feature = "full",
157    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
158)]
159#[cfg_attr(feature = "full", desert(evolution()))]
160#[serde(tag = "kind", content = "value", rename_all = "kebab-case")]
161pub enum ToolMiddlewareScope {
162    Monomorphic(Box<MonomorphicToolMiddlewareScope>),
163    Universal,
164}
165
166#[derive(
167    Debug,
168    Clone,
169    PartialEq,
170    Serialize,
171    Deserialize,
172    golem_schema_derive::IntoSchema,
173    golem_schema_derive::FromSchema,
174)]
175#[cfg_attr(
176    feature = "full",
177    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
178)]
179#[cfg_attr(feature = "full", desert(evolution()))]
180pub struct MonomorphicToolMiddlewareScope {
181    pub presented: Tool,
182    pub expected: Option<Tool>,
183}
184
185/// Flattened command hierarchy. Always non-empty; the root command is at index 0.
186#[derive(
187    Debug,
188    Clone,
189    PartialEq,
190    Serialize,
191    Deserialize,
192    golem_schema_derive::IntoSchema,
193    golem_schema_derive::FromSchema,
194)]
195#[cfg_attr(
196    feature = "full",
197    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
198)]
199#[cfg_attr(feature = "full", desert(evolution()))]
200pub struct CommandTree {
201    pub nodes: Vec<CommandNode>,
202}
203
204/// A node in the command tree. May dispatch to subcommands, run its own body, or
205/// both. Globals declared here apply to this command's own body and to every
206/// descendant subcommand body.
207#[derive(
208    Debug,
209    Clone,
210    PartialEq,
211    Serialize,
212    Deserialize,
213    golem_schema_derive::IntoSchema,
214    golem_schema_derive::FromSchema,
215)]
216#[cfg_attr(
217    feature = "full",
218    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
219)]
220#[cfg_attr(feature = "full", desert(evolution()))]
221pub struct CommandNode {
222    pub name: String,
223    pub aliases: Vec<String>,
224    pub doc: Doc,
225    pub globals: Globals,
226    pub subcommands: Vec<CommandIndex>,
227    pub body: Option<CommandBody>,
228}
229
230#[derive(
231    Debug,
232    Clone,
233    PartialEq,
234    Default,
235    Serialize,
236    Deserialize,
237    golem_schema_derive::IntoSchema,
238    golem_schema_derive::FromSchema,
239)]
240#[cfg_attr(
241    feature = "full",
242    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
243)]
244#[cfg_attr(feature = "full", desert(evolution()))]
245pub struct Globals {
246    pub options: Vec<OptionSpec>,
247    pub flags: Vec<FlagSpec>,
248}
249
250#[derive(
251    Debug,
252    Clone,
253    PartialEq,
254    Serialize,
255    Deserialize,
256    golem_schema_derive::IntoSchema,
257    golem_schema_derive::FromSchema,
258)]
259#[cfg_attr(
260    feature = "full",
261    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
262)]
263#[cfg_attr(feature = "full", desert(evolution()))]
264pub struct CommandBody {
265    pub positionals: Positionals,
266    pub options: Vec<OptionSpec>,
267    pub flags: Vec<FlagSpec>,
268    pub constraints: Vec<Constraint>,
269    pub stdin: Option<StreamSpec>,
270    pub stdout: Option<StreamSpec>,
271    pub stderr: Option<StreamSpec>,
272    pub result: Option<ResultSpec>,
273    pub errors: Vec<ErrorCase>,
274    pub annotations: Option<CommandAnnotations>,
275}
276
277/// Behavioral hints surfaced to MCP and other LLM-facing surfaces, following
278/// the MCP convention.
279#[derive(
280    Debug,
281    Clone,
282    Copy,
283    PartialEq,
284    Eq,
285    Serialize,
286    Deserialize,
287    golem_schema_derive::IntoSchema,
288    golem_schema_derive::FromSchema,
289)]
290#[cfg_attr(
291    feature = "full",
292    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
293)]
294#[cfg_attr(feature = "full", desert(evolution()))]
295pub struct CommandAnnotations {
296    pub read_only: bool,
297    pub destructive: bool,
298    pub idempotent: bool,
299    pub open_world: bool,
300}
301
302#[derive(
303    Debug,
304    Clone,
305    PartialEq,
306    Default,
307    Serialize,
308    Deserialize,
309    golem_schema_derive::IntoSchema,
310    golem_schema_derive::FromSchema,
311)]
312#[cfg_attr(
313    feature = "full",
314    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
315)]
316#[cfg_attr(feature = "full", desert(evolution()))]
317pub struct Positionals {
318    pub fixed: Vec<Positional>,
319    pub tail: Option<TailPositional>,
320}
321
322#[derive(
323    Debug,
324    Clone,
325    PartialEq,
326    Serialize,
327    Deserialize,
328    golem_schema_derive::IntoSchema,
329    golem_schema_derive::FromSchema,
330)]
331#[cfg_attr(
332    feature = "full",
333    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
334)]
335#[cfg_attr(feature = "full", desert(evolution()))]
336pub struct Positional {
337    pub name: String,
338    pub doc: Doc,
339    pub value_name: Option<String>,
340    /// Schema of the positional's value.
341    pub type_: SchemaType,
342    /// Default value, interpreted against [`type_`](Self::type_).
343    pub default: Option<SchemaValue>,
344    pub required: bool,
345    /// If true, the positional's value may be read from standard input.
346    pub accepts_stdio: bool,
347}
348
349#[derive(
350    Debug,
351    Clone,
352    PartialEq,
353    Serialize,
354    Deserialize,
355    golem_schema_derive::IntoSchema,
356    golem_schema_derive::FromSchema,
357)]
358#[cfg_attr(
359    feature = "full",
360    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
361)]
362#[cfg_attr(feature = "full", desert(evolution()))]
363pub struct TailPositional {
364    pub name: String,
365    pub doc: Doc,
366    pub value_name: Option<String>,
367    /// Schema of a single tail item.
368    pub item_type: SchemaType,
369    pub min: u32,
370    pub max: Option<u32>,
371    /// Token required before tail items (e.g. `--` for `git log -- <paths>`).
372    pub separator: Option<String>,
373    /// If true, tokens after `separator` are not flag-parsed.
374    pub verbatim: bool,
375    /// If true, the tail items may be read from standard input.
376    pub accepts_stdio: bool,
377}
378
379#[derive(
380    Debug,
381    Clone,
382    PartialEq,
383    Serialize,
384    Deserialize,
385    golem_schema_derive::IntoSchema,
386    golem_schema_derive::FromSchema,
387)]
388#[cfg_attr(
389    feature = "full",
390    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
391)]
392#[cfg_attr(feature = "full", desert(evolution()))]
393pub struct OptionSpec {
394    pub long: String,
395    pub short: Option<char>,
396    pub aliases: Vec<String>,
397    pub doc: Doc,
398    pub value_name: Option<String>,
399    pub shape: OptionShape,
400    /// Default value, interpreted against the option's value type.
401    pub default: Option<SchemaValue>,
402    pub required: bool,
403    pub env_var: Option<String>,
404}
405
406#[derive(
407    Debug,
408    Clone,
409    PartialEq,
410    Serialize,
411    Deserialize,
412    golem_schema_derive::IntoSchema,
413    golem_schema_derive::FromSchema,
414)]
415#[cfg_attr(
416    feature = "full",
417    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
418)]
419#[cfg_attr(feature = "full", desert(evolution()))]
420#[serde(tag = "kind", content = "value", rename_all = "kebab-case")]
421pub enum OptionShape {
422    /// Required value: `--opt VALUE` or `--opt=VALUE`.
423    Scalar(SchemaType),
424    /// Bare presence collapses to `default`; with value parses normally.
425    OptionalScalar(SchemaType),
426    /// Repeatable scalar option (`-e a -e b`); the collected value is a list
427    /// of the element type.
428    RepeatableList(RepeatableListShape),
429    /// Repeatable key-value option (`-c a=1 -c b=2`); the collected value is a
430    /// [`SchemaType::Map`], never a `list<tuple>`.
431    RepeatableMap(RepeatableMapShape),
432}
433
434#[derive(
435    Debug,
436    Clone,
437    PartialEq,
438    Serialize,
439    Deserialize,
440    golem_schema_derive::IntoSchema,
441    golem_schema_derive::FromSchema,
442)]
443#[cfg_attr(
444    feature = "full",
445    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
446)]
447#[cfg_attr(feature = "full", desert(evolution()))]
448pub struct RepeatableListShape {
449    pub repetition: Repetition,
450    /// Schema of a single collected element.
451    pub item_type: SchemaType,
452}
453
454#[derive(
455    Debug,
456    Clone,
457    PartialEq,
458    Serialize,
459    Deserialize,
460    golem_schema_derive::IntoSchema,
461    golem_schema_derive::FromSchema,
462)]
463#[cfg_attr(
464    feature = "full",
465    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
466)]
467#[cfg_attr(feature = "full", desert(evolution()))]
468pub struct RepeatableMapShape {
469    pub repetition: Repetition,
470    /// A [`SchemaType::Map`] node; the collected value is this map.
471    pub map_type: SchemaType,
472    /// What happens when the same key is supplied more than once.
473    pub duplicate_key_policy: DuplicateKeyPolicy,
474}
475
476/// Resolution policy for a repeated key in a [`OptionShape::RepeatableMap`].
477#[derive(
478    Debug,
479    Clone,
480    Copy,
481    PartialEq,
482    Eq,
483    Serialize,
484    Deserialize,
485    golem_schema_derive::IntoSchema,
486    golem_schema_derive::FromSchema,
487)]
488#[cfg_attr(
489    feature = "full",
490    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
491)]
492#[cfg_attr(feature = "full", desert(evolution()))]
493#[serde(rename_all = "kebab-case")]
494pub enum DuplicateKeyPolicy {
495    /// A repeated key is a usage error.
496    Reject,
497    /// A repeated key takes the last supplied value.
498    LastWins,
499}
500
501#[derive(
502    Debug,
503    Clone,
504    Copy,
505    PartialEq,
506    Eq,
507    Serialize,
508    Deserialize,
509    golem_schema_derive::IntoSchema,
510    golem_schema_derive::FromSchema,
511)]
512#[cfg_attr(
513    feature = "full",
514    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
515)]
516#[cfg_attr(feature = "full", desert(evolution()))]
517#[serde(tag = "kind", content = "value", rename_all = "kebab-case")]
518pub enum Repetition {
519    /// `--inc a --inc b`
520    Repeated,
521    /// `--inc=a,b`
522    Delimited(char),
523    /// Both surface forms accepted.
524    Either(char),
525}
526
527#[derive(
528    Debug,
529    Clone,
530    PartialEq,
531    Serialize,
532    Deserialize,
533    golem_schema_derive::IntoSchema,
534    golem_schema_derive::FromSchema,
535)]
536#[cfg_attr(
537    feature = "full",
538    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
539)]
540#[cfg_attr(feature = "full", desert(evolution()))]
541pub struct FlagSpec {
542    pub long: String,
543    pub short: Option<char>,
544    pub aliases: Vec<String>,
545    pub doc: Doc,
546    pub shape: FlagShape,
547    pub env_var: Option<String>,
548}
549
550#[derive(
551    Debug,
552    Clone,
553    Copy,
554    PartialEq,
555    Eq,
556    Serialize,
557    Deserialize,
558    golem_schema_derive::IntoSchema,
559    golem_schema_derive::FromSchema,
560)]
561#[cfg_attr(
562    feature = "full",
563    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
564)]
565#[cfg_attr(feature = "full", desert(evolution()))]
566#[serde(tag = "kind", content = "value", rename_all = "kebab-case")]
567pub enum FlagShape {
568    BoolFlag(BoolFlagShape),
569    /// Counted flag (`-vvv`); optional max count.
570    CountFlag(Option<u32>),
571}
572
573#[derive(
574    Debug,
575    Clone,
576    Copy,
577    PartialEq,
578    Eq,
579    Serialize,
580    Deserialize,
581    golem_schema_derive::IntoSchema,
582    golem_schema_derive::FromSchema,
583)]
584#[cfg_attr(
585    feature = "full",
586    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
587)]
588#[cfg_attr(feature = "full", desert(evolution()))]
589pub struct BoolFlagShape {
590    pub default: bool,
591    /// If true, `--no-<name>` is auto-synthesized.
592    pub negatable: bool,
593}
594
595#[derive(
596    Debug,
597    Clone,
598    PartialEq,
599    Serialize,
600    Deserialize,
601    golem_schema_derive::IntoSchema,
602    golem_schema_derive::FromSchema,
603)]
604#[cfg_attr(
605    feature = "full",
606    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
607)]
608#[cfg_attr(feature = "full", desert(evolution()))]
609#[serde(tag = "kind", content = "value", rename_all = "kebab-case")]
610pub enum Ref {
611    Present(String),
612    ValueIs(ValueIsRef),
613}
614
615#[derive(
616    Debug,
617    Clone,
618    PartialEq,
619    Serialize,
620    Deserialize,
621    golem_schema_derive::IntoSchema,
622    golem_schema_derive::FromSchema,
623)]
624#[cfg_attr(
625    feature = "full",
626    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
627)]
628#[cfg_attr(feature = "full", desert(evolution()))]
629pub struct ValueIsRef {
630    pub name: String,
631    /// Literal value, interpreted against the declared type of `name`.
632    pub value: SchemaValue,
633}
634
635#[derive(
636    Debug,
637    Clone,
638    PartialEq,
639    Serialize,
640    Deserialize,
641    golem_schema_derive::IntoSchema,
642    golem_schema_derive::FromSchema,
643)]
644#[cfg_attr(
645    feature = "full",
646    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
647)]
648#[cfg_attr(feature = "full", desert(evolution()))]
649#[serde(tag = "kind", content = "value", rename_all = "kebab-case")]
650pub enum Constraint {
651    RequiresAll(Vec<Ref>),
652    AllOrNone(Vec<Ref>),
653    RequiresAny(Vec<Ref>),
654    MutexGroups(Vec<RefGroup>),
655    Implies(ImpliesC),
656    Forbids(ForbidsC),
657}
658
659#[derive(
660    Debug,
661    Clone,
662    PartialEq,
663    Serialize,
664    Deserialize,
665    golem_schema_derive::IntoSchema,
666    golem_schema_derive::FromSchema,
667)]
668#[cfg_attr(
669    feature = "full",
670    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
671)]
672#[cfg_attr(feature = "full", desert(evolution()))]
673pub struct RefGroup {
674    pub refs: Vec<Ref>,
675}
676
677#[derive(
678    Debug,
679    Clone,
680    PartialEq,
681    Serialize,
682    Deserialize,
683    golem_schema_derive::IntoSchema,
684    golem_schema_derive::FromSchema,
685)]
686#[cfg_attr(
687    feature = "full",
688    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
689)]
690#[cfg_attr(feature = "full", desert(evolution()))]
691pub struct ImpliesC {
692    pub lhs_quant: Quantifier,
693    pub lhs: Vec<Ref>,
694    pub rhs_quant: Quantifier,
695    pub rhs: Vec<Ref>,
696}
697
698#[derive(
699    Debug,
700    Clone,
701    PartialEq,
702    Serialize,
703    Deserialize,
704    golem_schema_derive::IntoSchema,
705    golem_schema_derive::FromSchema,
706)]
707#[cfg_attr(
708    feature = "full",
709    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
710)]
711#[cfg_attr(feature = "full", desert(evolution()))]
712pub struct ForbidsC {
713    pub lhs_quant: Quantifier,
714    pub lhs: Vec<Ref>,
715    pub rhs: Vec<Ref>,
716}
717
718#[derive(
719    Debug,
720    Clone,
721    Copy,
722    PartialEq,
723    Eq,
724    Serialize,
725    Deserialize,
726    golem_schema_derive::IntoSchema,
727    golem_schema_derive::FromSchema,
728)]
729#[cfg_attr(
730    feature = "full",
731    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
732)]
733#[cfg_attr(feature = "full", desert(evolution()))]
734#[serde(rename_all = "kebab-case")]
735pub enum Quantifier {
736    All,
737    Any,
738}
739
740#[derive(
741    Debug,
742    Clone,
743    PartialEq,
744    Eq,
745    Serialize,
746    Deserialize,
747    golem_schema_derive::IntoSchema,
748    golem_schema_derive::FromSchema,
749)]
750#[cfg_attr(
751    feature = "full",
752    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
753)]
754#[cfg_attr(feature = "full", desert(evolution()))]
755pub struct StreamSpec {
756    pub doc: Doc,
757    pub mime: Vec<String>,
758    pub required: bool,
759}
760
761#[derive(
762    Debug,
763    Clone,
764    PartialEq,
765    Serialize,
766    Deserialize,
767    golem_schema_derive::IntoSchema,
768    golem_schema_derive::FromSchema,
769)]
770#[cfg_attr(
771    feature = "full",
772    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
773)]
774#[cfg_attr(feature = "full", desert(evolution()))]
775#[serde(rename = "ToolResultSpec")]
776pub struct ResultSpec {
777    /// Schema of the result value.
778    pub type_: SchemaType,
779    pub doc: Doc,
780    pub formatters: Vec<Formatter>,
781    pub default_formatter: String,
782}
783
784#[derive(
785    Debug,
786    Clone,
787    PartialEq,
788    Eq,
789    Serialize,
790    Deserialize,
791    golem_schema_derive::IntoSchema,
792    golem_schema_derive::FromSchema,
793)]
794#[cfg_attr(
795    feature = "full",
796    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
797)]
798#[cfg_attr(feature = "full", desert(evolution()))]
799pub struct Formatter {
800    pub name: String,
801    pub doc: Doc,
802}
803
804#[derive(
805    Debug,
806    Clone,
807    PartialEq,
808    Serialize,
809    Deserialize,
810    golem_schema_derive::IntoSchema,
811    golem_schema_derive::FromSchema,
812)]
813#[cfg_attr(
814    feature = "full",
815    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
816)]
817#[cfg_attr(feature = "full", desert(evolution()))]
818pub struct ErrorCase {
819    pub name: String,
820    pub doc: Doc,
821    pub kind: ErrorKind,
822    pub exit_code: u8,
823    /// Schema of the error payload, if any.
824    pub payload: Option<SchemaType>,
825}
826
827#[derive(
828    Debug,
829    Clone,
830    Copy,
831    PartialEq,
832    Eq,
833    Serialize,
834    Deserialize,
835    golem_schema_derive::IntoSchema,
836    golem_schema_derive::FromSchema,
837)]
838#[cfg_attr(
839    feature = "full",
840    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
841)]
842#[cfg_attr(feature = "full", desert(evolution()))]
843#[serde(rename_all = "kebab-case")]
844pub enum ErrorKind {
845    UsageError,
846    RuntimeError,
847}
848
849#[derive(
850    Debug,
851    Clone,
852    PartialEq,
853    Eq,
854    Default,
855    Serialize,
856    Deserialize,
857    golem_schema_derive::IntoSchema,
858    golem_schema_derive::FromSchema,
859)]
860#[cfg_attr(
861    feature = "full",
862    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
863)]
864#[cfg_attr(feature = "full", desert(evolution()))]
865pub struct Doc {
866    pub summary: String,
867    pub description: String,
868    pub examples: Vec<Example>,
869}
870
871#[derive(
872    Debug,
873    Clone,
874    PartialEq,
875    Eq,
876    Serialize,
877    Deserialize,
878    golem_schema_derive::IntoSchema,
879    golem_schema_derive::FromSchema,
880)]
881#[cfg_attr(
882    feature = "full",
883    derive(desert_rust::BinaryCodec, golem_schema_derive::PoemSchema)
884)]
885#[cfg_attr(feature = "full", desert(evolution()))]
886pub struct Example {
887    pub title: String,
888    pub body: String,
889}