pforge_config/
types.rs

1use rustc_hash::FxHashMap;
2use serde::{Deserialize, Serialize};
3
4/// Root configuration structure
5#[derive(Debug, Clone, Deserialize, Serialize)]
6#[serde(deny_unknown_fields)]
7pub struct ForgeConfig {
8    pub forge: ForgeMetadata,
9    #[serde(default)]
10    pub tools: Vec<ToolDef>,
11    #[serde(default)]
12    pub resources: Vec<ResourceDef>,
13    #[serde(default)]
14    pub prompts: Vec<PromptDef>,
15    #[serde(default)]
16    pub state: Option<StateDef>,
17}
18
19#[derive(Debug, Clone, Deserialize, Serialize)]
20pub struct ForgeMetadata {
21    pub name: String,
22    pub version: String,
23    #[serde(default = "default_transport")]
24    pub transport: TransportType,
25    #[serde(default)]
26    pub optimization: OptimizationLevel,
27}
28
29#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
30#[serde(rename_all = "lowercase")]
31pub enum TransportType {
32    Stdio,
33    Sse,
34    #[serde(rename = "websocket")]
35    WebSocket,
36}
37
38#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Default)]
39#[serde(rename_all = "lowercase")]
40pub enum OptimizationLevel {
41    #[default]
42    Debug,
43    Release,
44}
45
46#[derive(Debug, Clone, Deserialize, Serialize)]
47#[serde(tag = "type", rename_all = "snake_case")]
48pub enum ToolDef {
49    Native {
50        name: String,
51        description: String,
52        handler: HandlerRef,
53        params: ParamSchema,
54        #[serde(default)]
55        timeout_ms: Option<u64>,
56    },
57    Cli {
58        name: String,
59        description: String,
60        command: String,
61        args: Vec<String>,
62        #[serde(default)]
63        cwd: Option<String>,
64        #[serde(default)]
65        env: FxHashMap<String, String>,
66        #[serde(default)]
67        stream: bool,
68        /// Timeout in milliseconds for command execution
69        #[serde(default)]
70        timeout_ms: Option<u64>,
71    },
72    Http {
73        name: String,
74        description: String,
75        endpoint: String,
76        method: HttpMethod,
77        #[serde(default)]
78        auth: Option<AuthConfig>,
79        #[serde(default)]
80        headers: FxHashMap<String, String>,
81        /// Timeout in milliseconds for HTTP request
82        #[serde(default)]
83        timeout_ms: Option<u64>,
84    },
85    Pipeline {
86        name: String,
87        description: String,
88        steps: Vec<PipelineStep>,
89    },
90}
91
92impl ToolDef {
93    pub fn name(&self) -> &str {
94        match self {
95            Self::Native { name, .. }
96            | Self::Cli { name, .. }
97            | Self::Http { name, .. }
98            | Self::Pipeline { name, .. } => name,
99        }
100    }
101}
102
103#[derive(Debug, Clone, Deserialize, Serialize)]
104pub struct HandlerRef {
105    pub path: String,
106    #[serde(default)]
107    pub inline: Option<String>,
108}
109
110#[derive(Debug, Clone, Deserialize, Serialize)]
111pub struct ParamSchema {
112    #[serde(flatten)]
113    pub fields: FxHashMap<String, ParamType>,
114}
115
116#[derive(Debug, Clone, Deserialize, Serialize)]
117#[serde(untagged)]
118pub enum ParamType {
119    Simple(SimpleType),
120    Complex {
121        #[serde(rename = "type")]
122        ty: SimpleType,
123        #[serde(default)]
124        required: bool,
125        #[serde(default)]
126        default: Option<serde_json::Value>,
127        #[serde(default)]
128        description: Option<String>,
129        #[serde(default)]
130        validation: Option<Validation>,
131    },
132}
133
134#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
135#[serde(rename_all = "lowercase")]
136pub enum SimpleType {
137    String,
138    Integer,
139    Float,
140    Boolean,
141    Array,
142    Object,
143}
144
145#[derive(Debug, Clone, Deserialize, Serialize)]
146pub struct Validation {
147    #[serde(default)]
148    pub min: Option<f64>,
149    #[serde(default)]
150    pub max: Option<f64>,
151    #[serde(default)]
152    pub pattern: Option<String>,
153    #[serde(default)]
154    pub min_length: Option<usize>,
155    #[serde(default)]
156    pub max_length: Option<usize>,
157}
158
159#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
160#[serde(rename_all = "UPPERCASE")]
161pub enum HttpMethod {
162    Get,
163    Post,
164    Put,
165    Delete,
166    Patch,
167}
168
169#[derive(Debug, Clone, Deserialize, Serialize)]
170#[serde(tag = "type", rename_all = "lowercase")]
171pub enum AuthConfig {
172    Bearer { token: String },
173    Basic { username: String, password: String },
174    ApiKey { key: String, header: String },
175}
176
177#[derive(Debug, Clone, Deserialize, Serialize)]
178pub struct PipelineStep {
179    pub tool: String,
180    #[serde(default)]
181    pub input: Option<serde_json::Value>,
182    #[serde(default)]
183    pub output_var: Option<String>,
184    #[serde(default)]
185    pub condition: Option<String>,
186    #[serde(default)]
187    pub error_policy: ErrorPolicy,
188}
189
190#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Default)]
191#[serde(rename_all = "snake_case")]
192pub enum ErrorPolicy {
193    #[default]
194    FailFast,
195    Continue,
196}
197
198#[derive(Debug, Clone, Deserialize, Serialize)]
199pub struct ResourceDef {
200    pub uri_template: String,
201    pub handler: HandlerRef,
202    #[serde(default)]
203    pub supports: Vec<ResourceOperation>,
204}
205
206#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
207#[serde(rename_all = "lowercase")]
208pub enum ResourceOperation {
209    Read,
210    Write,
211    Subscribe,
212}
213
214#[derive(Debug, Clone, Deserialize, Serialize)]
215pub struct PromptDef {
216    pub name: String,
217    pub description: String,
218    pub template: String,
219    #[serde(default)]
220    pub arguments: FxHashMap<String, ParamType>,
221}
222
223#[derive(Debug, Clone, Deserialize, Serialize)]
224pub struct StateDef {
225    pub backend: StateBackend,
226    pub path: String,
227    #[serde(default)]
228    pub options: FxHashMap<String, serde_json::Value>,
229}
230
231#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
232#[serde(rename_all = "lowercase")]
233pub enum StateBackend {
234    Sled,
235    Memory,
236}
237
238const fn default_transport() -> TransportType {
239    TransportType::Stdio
240}