pforge_config/
types.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
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)]
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, 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: HashMap<String, String>,
66        #[serde(default)]
67        stream: bool,
68    },
69    Http {
70        name: String,
71        description: String,
72        endpoint: String,
73        method: HttpMethod,
74        #[serde(default)]
75        auth: Option<AuthConfig>,
76        #[serde(default)]
77        headers: HashMap<String, String>,
78    },
79    Pipeline {
80        name: String,
81        description: String,
82        steps: Vec<PipelineStep>,
83    },
84}
85
86impl ToolDef {
87    pub fn name(&self) -> &str {
88        match self {
89            ToolDef::Native { name, .. } => name,
90            ToolDef::Cli { name, .. } => name,
91            ToolDef::Http { name, .. } => name,
92            ToolDef::Pipeline { name, .. } => name,
93        }
94    }
95}
96
97#[derive(Debug, Clone, Deserialize, Serialize)]
98pub struct HandlerRef {
99    pub path: String,
100    #[serde(default)]
101    pub inline: Option<String>,
102}
103
104#[derive(Debug, Clone, Deserialize, Serialize)]
105pub struct ParamSchema {
106    #[serde(flatten)]
107    pub fields: HashMap<String, ParamType>,
108}
109
110#[derive(Debug, Clone, Deserialize, Serialize)]
111#[serde(untagged)]
112pub enum ParamType {
113    Simple(SimpleType),
114    Complex {
115        #[serde(rename = "type")]
116        ty: SimpleType,
117        #[serde(default)]
118        required: bool,
119        #[serde(default)]
120        default: Option<serde_json::Value>,
121        #[serde(default)]
122        description: Option<String>,
123        #[serde(default)]
124        validation: Option<Validation>,
125    },
126}
127
128#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
129#[serde(rename_all = "lowercase")]
130pub enum SimpleType {
131    String,
132    Integer,
133    Float,
134    Boolean,
135    Array,
136    Object,
137}
138
139#[derive(Debug, Clone, Deserialize, Serialize)]
140pub struct Validation {
141    #[serde(default)]
142    pub min: Option<f64>,
143    #[serde(default)]
144    pub max: Option<f64>,
145    #[serde(default)]
146    pub pattern: Option<String>,
147    #[serde(default)]
148    pub min_length: Option<usize>,
149    #[serde(default)]
150    pub max_length: Option<usize>,
151}
152
153#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
154#[serde(rename_all = "UPPERCASE")]
155pub enum HttpMethod {
156    Get,
157    Post,
158    Put,
159    Delete,
160    Patch,
161}
162
163#[derive(Debug, Clone, Deserialize, Serialize)]
164#[serde(tag = "type", rename_all = "lowercase")]
165pub enum AuthConfig {
166    Bearer { token: String },
167    Basic { username: String, password: String },
168    ApiKey { key: String, header: String },
169}
170
171#[derive(Debug, Clone, Deserialize, Serialize)]
172pub struct PipelineStep {
173    pub tool: String,
174    #[serde(default)]
175    pub input: Option<serde_json::Value>,
176    #[serde(default)]
177    pub output_var: Option<String>,
178    #[serde(default)]
179    pub condition: Option<String>,
180    #[serde(default)]
181    pub error_policy: ErrorPolicy,
182}
183
184#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Default)]
185#[serde(rename_all = "snake_case")]
186pub enum ErrorPolicy {
187    #[default]
188    FailFast,
189    Continue,
190}
191
192#[derive(Debug, Clone, Deserialize, Serialize)]
193pub struct ResourceDef {
194    pub uri_template: String,
195    pub handler: HandlerRef,
196    #[serde(default)]
197    pub supports: Vec<ResourceOperation>,
198}
199
200#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
201#[serde(rename_all = "lowercase")]
202pub enum ResourceOperation {
203    Read,
204    Write,
205    Subscribe,
206}
207
208#[derive(Debug, Clone, Deserialize, Serialize)]
209pub struct PromptDef {
210    pub name: String,
211    pub description: String,
212    pub template: String,
213    #[serde(default)]
214    pub arguments: HashMap<String, ParamType>,
215}
216
217#[derive(Debug, Clone, Deserialize, Serialize)]
218pub struct StateDef {
219    pub backend: StateBackend,
220    pub path: String,
221    #[serde(default)]
222    pub options: HashMap<String, serde_json::Value>,
223}
224
225#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
226#[serde(rename_all = "lowercase")]
227pub enum StateBackend {
228    Sled,
229    Memory,
230}
231
232fn default_transport() -> TransportType {
233    TransportType::Stdio
234}