chio_cross_protocol/
semantic_hints.rs1use chio_manifest::{LatencyHint, ToolDefinition};
2use serde::{Deserialize, Serialize};
3
4use crate::validation::schema_bool_extension;
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "snake_case", tag = "kind")]
9pub enum BridgeFidelity {
10 Lossless,
11 Adapted { caveats: Vec<String> },
12 Unsupported { reason: String },
13}
14
15impl BridgeFidelity {
16 #[must_use]
17 pub fn published_by_default(&self) -> bool {
18 !matches!(self, Self::Unsupported { .. })
19 }
20
21 #[must_use]
22 pub fn caveats(&self) -> &[String] {
23 match self {
24 Self::Adapted { caveats } => caveats.as_slice(),
25 Self::Lossless | Self::Unsupported { .. } => &[],
26 }
27 }
28
29 #[must_use]
30 pub fn unsupported_reason(&self) -> Option<&str> {
31 match self {
32 Self::Unsupported { reason } => Some(reason.as_str()),
33 Self::Lossless | Self::Adapted { .. } => None,
34 }
35 }
36}
37
38#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct BridgeSemanticHints {
42 pub publish: bool,
43 pub approval_required: bool,
44 pub streams_output: bool,
45 pub supports_cancellation: bool,
46 pub partial_output: bool,
47}
48
49#[must_use]
52pub fn semantic_hints_for_tool(tool: &ToolDefinition) -> BridgeSemanticHints {
53 let publish = schema_bool_extension(&tool.input_schema, "x-chio-publish")
54 .or_else(|| {
55 tool.output_schema
56 .as_ref()
57 .and_then(|schema| schema_bool_extension(schema, "x-chio-publish"))
58 })
59 .unwrap_or(true);
60
61 let approval_required = schema_bool_extension(&tool.input_schema, "x-chio-approval-required")
62 .or_else(|| {
63 tool.output_schema
64 .as_ref()
65 .and_then(|schema| schema_bool_extension(schema, "x-chio-approval-required"))
66 })
67 .unwrap_or(false);
68
69 let streams_output = schema_bool_extension(&tool.input_schema, "x-chio-streaming")
70 .or_else(|| {
71 tool.output_schema
72 .as_ref()
73 .and_then(|schema| schema_bool_extension(schema, "x-chio-streaming"))
74 })
75 .unwrap_or(matches!(
76 tool.latency_hint,
77 Some(LatencyHint::Moderate | LatencyHint::Slow)
78 ));
79
80 let supports_cancellation = schema_bool_extension(&tool.input_schema, "x-chio-cancellation")
81 .or_else(|| {
82 tool.output_schema
83 .as_ref()
84 .and_then(|schema| schema_bool_extension(schema, "x-chio-cancellation"))
85 })
86 .unwrap_or(matches!(tool.latency_hint, Some(LatencyHint::Slow)));
87
88 let partial_output = schema_bool_extension(&tool.input_schema, "x-chio-partial-output")
89 .or_else(|| {
90 tool.output_schema
91 .as_ref()
92 .and_then(|schema| schema_bool_extension(schema, "x-chio-partial-output"))
93 })
94 .unwrap_or(streams_output);
95
96 BridgeSemanticHints {
97 publish,
98 approval_required,
99 streams_output,
100 supports_cancellation,
101 partial_output,
102 }
103}