1use 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#[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 pub fn as_usize(self) -> Option<usize> {
80 usize::try_from(self.0).ok()
81 }
82}
83
84#[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 #[serde(default = "SchemaGraph::empty")]
112 pub schema: SchemaGraph,
113}
114
115impl Tool {
116 pub fn name(&self) -> Option<&str> {
118 self.commands.nodes.first().map(|node| node.name.as_str())
119 }
120}
121
122#[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#[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#[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#[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 pub type_: SchemaType,
342 pub default: Option<SchemaValue>,
344 pub required: bool,
345 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 pub item_type: SchemaType,
369 pub min: u32,
370 pub max: Option<u32>,
371 pub separator: Option<String>,
373 pub verbatim: bool,
375 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 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 Scalar(SchemaType),
424 OptionalScalar(SchemaType),
426 RepeatableList(RepeatableListShape),
429 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 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 pub map_type: SchemaType,
472 pub duplicate_key_policy: DuplicateKeyPolicy,
474}
475
476#[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 Reject,
497 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 Repeated,
521 Delimited(char),
523 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 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 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 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 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 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}