1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, Default, Serialize, Deserialize)]
14pub struct PaginationParams {
15 #[serde(default = "default_page")]
17 pub page: usize,
18 #[serde(default = "default_per_page")]
20 pub per_page: usize,
21}
22
23fn default_page() -> usize {
24 1
25}
26
27fn default_per_page() -> usize {
28 20
29}
30
31impl PaginationParams {
32 pub fn new(page: usize, per_page: usize) -> Self {
33 Self { page, per_page }
34 }
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct PaginatedResponse<T> {
40 pub items: Vec<T>,
42 pub total: usize,
44 pub page: usize,
46 pub per_page: usize,
48 pub total_pages: usize,
50}
51
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
58pub struct SkillServiceRequirement {
59 pub name: String,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 pub description: Option<String>,
62 pub optional: bool,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub default_port: Option<u16>,
65 pub status: ServiceStatus,
66}
67
68#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
70pub struct SkillSummary {
71 pub name: String,
72 pub version: String,
73 pub description: String,
74 pub source: String,
75 pub runtime: String,
76 pub tools_count: usize,
77 pub instances_count: usize,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub last_used: Option<String>,
80 pub execution_count: u64,
81 #[serde(default, skip_serializing_if = "Vec::is_empty")]
82 pub required_services: Vec<SkillServiceRequirement>,
83}
84
85#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
87pub struct SkillDetail {
88 #[serde(flatten)]
89 pub summary: SkillSummary,
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub full_description: Option<String>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub author: Option<String>,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub repository: Option<String>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub license: Option<String>,
98 pub tools: Vec<ToolInfo>,
99 pub instances: Vec<InstanceInfo>,
100}
101
102#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
104pub struct ToolInfo {
105 pub name: String,
106 pub description: String,
107 pub parameters: Vec<ParameterInfo>,
108 pub streaming: bool,
109}
110
111#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
113pub struct ParameterInfo {
114 pub name: String,
115 #[serde(rename = "type")]
116 pub param_type: String,
117 pub description: String,
118 pub required: bool,
119 #[serde(skip_serializing_if = "Option::is_none")]
120 pub default_value: Option<String>,
121}
122
123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
125pub struct InstanceInfo {
126 pub name: String,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub description: Option<String>,
129 pub is_default: bool,
130 pub config_keys: Vec<String>,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct InstallSkillRequest {
136 pub source: String,
137 #[serde(skip_serializing_if = "Option::is_none")]
138 pub name: Option<String>,
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub git_ref: Option<String>,
141 #[serde(default)]
142 pub force: bool,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct InstallSkillResponse {
148 pub success: bool,
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub name: Option<String>,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub version: Option<String>,
153 #[serde(skip_serializing_if = "Option::is_none")]
154 pub error: Option<String>,
155 pub tools_count: usize,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct ExecutionRequest {
165 pub skill: String,
166 pub tool: String,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 pub instance: Option<String>,
169 #[serde(default)]
170 pub args: HashMap<String, serde_json::Value>,
171 #[serde(default)]
172 pub stream: bool,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub timeout_secs: Option<u64>,
175}
176
177#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
179pub struct ExecutionResponse {
180 pub id: String,
181 pub status: ExecutionStatus,
182 pub output: String,
183 #[serde(skip_serializing_if = "Option::is_none")]
184 pub error: Option<String>,
185 pub duration_ms: u64,
186 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
187 pub metadata: HashMap<String, String>,
188}
189
190#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
192#[serde(rename_all = "lowercase")]
193pub enum ExecutionStatus {
194 Pending,
195 Running,
196 Success,
197 Failed,
198 Timeout,
199 Cancelled,
200}
201
202#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
204pub struct ExecutionHistoryEntry {
205 pub id: String,
206 pub skill: String,
207 pub tool: String,
208 pub instance: String,
209 pub status: ExecutionStatus,
210 pub duration_ms: u64,
211 pub started_at: String,
212 #[serde(skip_serializing_if = "Option::is_none")]
213 pub error: Option<String>,
214 #[serde(skip_serializing_if = "Option::is_none")]
215 pub output: Option<String>,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
224pub struct SearchRequest {
225 pub query: String,
226 #[serde(default = "default_top_k")]
227 pub top_k: usize,
228 #[serde(skip_serializing_if = "Option::is_none")]
229 pub skill_filter: Option<String>,
230 #[serde(default)]
231 pub include_examples: bool,
232}
233
234fn default_top_k() -> usize {
235 5
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize)]
240pub struct SearchResult {
241 pub id: String,
242 pub skill: String,
243 pub tool: String,
244 pub content: String,
245 pub score: f32,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 pub rerank_score: Option<f32>,
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
252pub struct SearchResponse {
253 pub results: Vec<SearchResult>,
254 #[serde(skip_serializing_if = "Option::is_none")]
255 pub query_info: Option<QueryInfo>,
256 pub duration_ms: u64,
257}
258
259#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct QueryInfo {
262 pub normalized: String,
263 pub intent: String,
264 pub confidence: f32,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
273pub struct SearchConfigResponse {
274 pub embedding_provider: String,
275 pub embedding_model: String,
276 pub dimensions: usize,
277 pub vector_backend: String,
278 pub hybrid_search_enabled: bool,
279 pub reranking_enabled: bool,
280 pub indexed_documents: usize,
281}
282
283#[derive(Debug, Clone, Default, Serialize, Deserialize)]
285pub struct UpdateSearchConfigRequest {
286 #[serde(skip_serializing_if = "Option::is_none")]
287 pub embedding_provider: Option<String>,
288 #[serde(skip_serializing_if = "Option::is_none")]
289 pub embedding_model: Option<String>,
290 #[serde(skip_serializing_if = "Option::is_none")]
291 pub vector_backend: Option<String>,
292 #[serde(skip_serializing_if = "Option::is_none")]
293 pub enable_hybrid: Option<bool>,
294 #[serde(skip_serializing_if = "Option::is_none")]
295 pub enable_reranking: Option<bool>,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct IndexResponse {
301 pub success: bool,
302 pub documents_indexed: usize,
303 pub duration_ms: u64,
304 pub message: String,
305 pub stats: IndexStats,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
310pub struct IndexStats {
311 pub documents_added: usize,
312 pub documents_updated: usize,
313 pub total_documents: usize,
314 pub index_size_bytes: Option<usize>,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct AppConfig {
320 pub default_timeout_secs: u64,
321 pub max_concurrent_executions: usize,
322 pub enable_history: bool,
323 pub max_history_entries: usize,
324 pub search: SearchConfigResponse,
325}
326
327#[derive(Debug, Clone, Default, Serialize, Deserialize)]
329pub struct UpdateAppConfigRequest {
330 #[serde(skip_serializing_if = "Option::is_none")]
331 pub default_timeout_secs: Option<u64>,
332 #[serde(skip_serializing_if = "Option::is_none")]
333 pub max_concurrent_executions: Option<usize>,
334 #[serde(skip_serializing_if = "Option::is_none")]
335 pub enable_history: Option<bool>,
336 #[serde(skip_serializing_if = "Option::is_none")]
337 pub max_history_entries: Option<usize>,
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct HealthResponse {
347 pub status: String,
348 pub healthy: bool,
349 pub components: HashMap<String, ComponentHealth>,
350 pub version: String,
351 pub uptime_secs: u64,
352}
353
354#[derive(Debug, Clone, Serialize, Deserialize)]
356pub struct ComponentHealth {
357 pub name: String,
358 pub healthy: bool,
359 #[serde(skip_serializing_if = "Option::is_none")]
360 pub message: Option<String>,
361}
362
363#[derive(Debug, Clone, Serialize, Deserialize)]
365pub struct VersionResponse {
366 pub version: String,
367 #[serde(skip_serializing_if = "Option::is_none")]
368 pub build: Option<String>,
369 #[serde(skip_serializing_if = "Option::is_none")]
370 pub commit: Option<String>,
371 #[serde(skip_serializing_if = "Option::is_none")]
372 pub rust_version: Option<String>,
373 pub wasmtime_version: String,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
382pub struct ImportManifestRequest {
383 pub content: String,
384 #[serde(default)]
385 pub merge: bool,
386 #[serde(default)]
387 pub install: bool,
388}
389
390#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
392pub struct ParsedSkill {
393 pub name: String,
394 pub source: String,
395 pub runtime: String,
396 #[serde(skip_serializing_if = "Option::is_none")]
397 pub description: Option<String>,
398 pub instances: Vec<ParsedInstance>,
399 #[serde(skip_serializing_if = "Option::is_none")]
400 pub docker_config: Option<DockerConfig>,
401}
402
403#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
405pub struct ParsedInstance {
406 pub name: String,
407 pub config_keys: Vec<String>,
408 pub env_keys: Vec<String>,
409 pub is_default: bool,
410}
411
412#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
414pub struct DockerConfig {
415 pub image: String,
416 #[serde(skip_serializing_if = "Option::is_none")]
417 pub entrypoint: Option<String>,
418 #[serde(default)]
419 pub volumes: Vec<String>,
420 #[serde(skip_serializing_if = "Option::is_none")]
421 pub working_dir: Option<String>,
422 #[serde(skip_serializing_if = "Option::is_none")]
423 pub memory: Option<String>,
424 #[serde(skip_serializing_if = "Option::is_none")]
425 pub cpus: Option<String>,
426 #[serde(skip_serializing_if = "Option::is_none")]
427 pub network: Option<String>,
428}
429
430#[derive(Debug, Clone, Serialize, Deserialize)]
432pub struct ImportManifestResponse {
433 pub success: bool,
434 pub skills: Vec<ParsedSkill>,
435 pub skills_count: usize,
436 pub installed_count: usize,
437 #[serde(default)]
438 pub warnings: Vec<String>,
439 #[serde(default)]
440 pub errors: Vec<String>,
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize)]
445pub struct ValidateManifestRequest {
446 pub content: String,
447}
448
449#[derive(Debug, Clone, Serialize, Deserialize)]
451pub struct ValidateManifestResponse {
452 pub valid: bool,
453 pub skills: Vec<ParsedSkill>,
454 #[serde(default)]
455 pub errors: Vec<String>,
456 #[serde(default)]
457 pub warnings: Vec<String>,
458}
459
460#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
466pub struct ServiceStatus {
467 pub name: String,
468 pub running: bool,
469 #[serde(skip_serializing_if = "Option::is_none")]
470 pub pid: Option<u32>,
471 #[serde(skip_serializing_if = "Option::is_none")]
472 pub port: Option<u16>,
473 #[serde(skip_serializing_if = "Option::is_none")]
474 pub url: Option<String>,
475 #[serde(skip_serializing_if = "Option::is_none")]
476 pub error: Option<String>,
477}
478
479#[derive(Debug, Clone, Serialize, Deserialize)]
481pub struct ServicesStatusResponse {
482 pub services: Vec<ServiceStatus>,
483}
484
485#[derive(Debug, Clone, Serialize, Deserialize)]
487pub struct StartServiceRequest {
488 pub service: String,
489 #[serde(skip_serializing_if = "Option::is_none")]
490 pub port: Option<u16>,
491}
492
493#[derive(Debug, Clone, Serialize, Deserialize)]
495pub struct StartServiceResponse {
496 pub success: bool,
497 pub status: ServiceStatus,
498 pub message: String,
499}
500
501#[derive(Debug, Clone, Serialize, Deserialize)]
503pub struct StopServiceRequest {
504 pub service: String,
505}
506
507#[derive(Debug, Clone, Serialize, Deserialize)]
513pub struct TestConnectionRequest {
514 pub embedding_provider: String,
515 pub embedding_model: String,
516 pub vector_backend: String,
517 #[serde(skip_serializing_if = "Option::is_none")]
518 pub qdrant_url: Option<String>,
519 #[serde(skip_serializing_if = "Option::is_none")]
520 pub ollama_url: Option<String>,
521}
522
523#[derive(Debug, Clone, Serialize, Deserialize)]
525pub struct TestConnectionResponse {
526 pub success: bool,
527 pub embedding_provider_status: ComponentHealth,
528 pub vector_backend_status: ComponentHealth,
529 pub duration_ms: u128,
530 pub message: String,
531}
532
533#[derive(Debug, Clone, Serialize, Deserialize)]
535pub struct TestPipelineRequest {
536 pub embedding_provider: String,
537 pub embedding_model: String,
538 pub vector_backend: String,
539 pub enable_hybrid: bool,
540 pub enable_reranking: bool,
541 #[serde(skip_serializing_if = "Option::is_none")]
542 pub qdrant_url: Option<String>,
543}
544
545#[derive(Debug, Clone, Serialize, Deserialize)]
547pub struct TestPipelineResponse {
548 pub success: bool,
549 pub index_stats: PipelineIndexStats,
550 pub search_results: Vec<PipelineSearchResult>,
551 pub duration_ms: u128,
552 pub message: String,
553}
554
555#[derive(Debug, Clone, Serialize, Deserialize)]
557pub struct PipelineIndexStats {
558 pub documents_indexed: usize,
559 pub indexing_duration_ms: u64,
560 pub embedding_duration_ms: u64,
561}
562
563#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
565pub struct PipelineSearchResult {
566 pub id: String,
567 pub content: String,
568 pub score: f32,
569 #[serde(skip_serializing_if = "Option::is_none")]
570 pub rerank_score: Option<f32>,
571 pub metadata: DocumentMetadata,
572}
573
574#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
576pub struct DocumentMetadata {
577 #[serde(skip_serializing_if = "Option::is_none")]
578 pub skill_name: Option<String>,
579 #[serde(skip_serializing_if = "Option::is_none")]
580 pub tool_name: Option<String>,
581 #[serde(default)]
582 pub tags: Vec<String>,
583}
584
585#[derive(Debug, Clone, Serialize, Deserialize)]
591pub struct AgentConfig {
592 pub runtime: AgentRuntime,
593 pub model_config: AgentModelConfig,
594 pub timeout_secs: u64,
595 #[serde(skip_serializing_if = "Option::is_none")]
596 pub claude_code_path: Option<String>,
597}
598
599impl Default for AgentConfig {
600 fn default() -> Self {
601 Self {
602 runtime: AgentRuntime::ClaudeCode,
603 model_config: AgentModelConfig::default(),
604 timeout_secs: 300,
605 claude_code_path: None,
606 }
607 }
608}
609
610#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
612#[serde(rename_all = "kebab-case")]
613pub enum AgentRuntime {
614 ClaudeCode,
615 Gemini,
616 #[serde(rename = "openai")]
617 OpenAI,
618 Custom,
619}
620
621#[derive(Debug, Clone, Serialize, Deserialize)]
623pub struct AgentModelConfig {
624 pub provider: String,
625 pub model: String,
626 pub temperature: f32,
627 pub max_tokens: usize,
628}
629
630impl Default for AgentModelConfig {
631 fn default() -> Self {
632 Self {
633 provider: "anthropic".to_string(),
634 model: "claude-sonnet-4".to_string(),
635 temperature: 0.7,
636 max_tokens: 4096,
637 }
638 }
639}
640
641#[derive(Debug, Clone, Serialize, Deserialize)]
643pub struct GetAgentConfigResponse {
644 pub config: AgentConfig,
645 pub available_runtimes: Vec<RuntimeInfo>,
646 pub available_models: HashMap<String, Vec<ModelInfo>>,
647 pub claude_code_detected: bool,
648 #[serde(skip_serializing_if = "Option::is_none")]
649 pub claude_code_version: Option<String>,
650}
651
652#[derive(Debug, Clone, Serialize, Deserialize)]
654pub struct RuntimeInfo {
655 pub runtime: AgentRuntime,
656 pub name: String,
657 pub description: String,
658 pub supported_providers: Vec<String>,
659 pub available: bool,
660}
661
662#[derive(Debug, Clone, Serialize, Deserialize)]
664pub struct ModelInfo {
665 pub id: String,
666 pub name: String,
667 pub max_tokens: usize,
668 pub supports_tools: bool,
669}
670
671#[derive(Debug, Clone, Default, Serialize, Deserialize)]
673pub struct UpdateAgentConfigRequest {
674 #[serde(skip_serializing_if = "Option::is_none")]
675 pub runtime: Option<AgentRuntime>,
676 #[serde(skip_serializing_if = "Option::is_none")]
677 pub model_config: Option<AgentModelConfig>,
678 #[serde(skip_serializing_if = "Option::is_none")]
679 pub timeout_secs: Option<u64>,
680 #[serde(skip_serializing_if = "Option::is_none")]
681 pub claude_code_path: Option<String>,
682}