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