Skip to main content

zagens_runtime_api/openapi/
paths.rs

1//! OpenAPI `paths` — kept in sync with `router.rs` (R-003 A4.1).
2
3use serde_json::{Map, Value, json};
4
5fn schema_ref(name: &str) -> Value {
6    json!({ "$ref": format!("#/components/schemas/{name}") })
7}
8
9fn json_response(schema: &str) -> Value {
10    json!({
11        "description": "OK",
12        "content": {
13            "application/json": { "schema": schema_ref(schema) }
14        }
15    })
16}
17
18fn sse_response() -> Value {
19    json!({
20        "description": "Server-Sent Events stream",
21        "content": {
22            "text/event-stream": { "schema": { "type": "string" } }
23        }
24    })
25}
26
27fn operation(
28    method: &str,
29    operation_id: &str,
30    summary: &str,
31    body: Option<&str>,
32    response: Value,
33    secured: bool,
34) -> (String, Value) {
35    let mut op = Map::new();
36    op.insert("operationId".into(), json!(operation_id));
37    op.insert("summary".into(), json!(summary));
38    if let Some(body_schema) = body {
39        op.insert(
40            "requestBody".into(),
41            json!({
42                "required": true,
43                "content": {
44                    "application/json": { "schema": schema_ref(body_schema) }
45                }
46            }),
47        );
48    }
49    op.insert("responses".into(), json!({ "200": response }));
50    if secured {
51        op.insert("security".into(), json!([{ "BearerAuth": [] }]));
52    }
53    (method.into(), Value::Object(op))
54}
55
56fn json_op(
57    method: &str,
58    operation_id: &str,
59    summary: &str,
60    body: Option<&str>,
61    schema: &str,
62    secured: bool,
63) -> (String, Value) {
64    operation(
65        method,
66        operation_id,
67        summary,
68        body,
69        json_response(schema),
70        secured,
71    )
72}
73
74fn path_item(ops: Vec<(String, Value)>) -> Value {
75    let mut m = Map::new();
76    for (k, v) in ops {
77        m.insert(k, v);
78    }
79    Value::Object(m)
80}
81
82/// Build the OpenAPI `paths` object (Axum `{param}` syntax).
83pub fn build_paths() -> Map<String, Value> {
84    let mut paths = Map::new();
85    let u = true;
86    let mut add = |path: &str, ops: Vec<(String, Value)>| {
87        paths.insert(path.into(), path_item(ops));
88    };
89
90    add(
91        "/health",
92        vec![json_op(
93            "get",
94            "health",
95            "Liveness probe",
96            None,
97            "ErrorBody",
98            false,
99        )],
100    );
101    add(
102        "/internal/probe",
103        vec![json_op(
104            "get",
105            "internalProbe",
106            "Internal readiness probe",
107            None,
108            "ErrorBody",
109            false,
110        )],
111    );
112    add(
113        "/v1/sessions",
114        vec![json_op(
115            "get",
116            "listSessions",
117            "List saved sessions",
118            None,
119            "SessionsListResponse",
120            u,
121        )],
122    );
123    add(
124        "/v1/sessions/{id}",
125        vec![
126            json_op(
127                "get",
128                "getSession",
129                "Load session detail",
130                None,
131                "SessionDetailResponse",
132                u,
133            ),
134            operation(
135                "delete",
136                "deleteSession",
137                "Delete saved session",
138                None,
139                json!({ "description": "Deleted" }),
140                u,
141            ),
142        ],
143    );
144    add(
145        "/v1/sessions/{id}/resume-thread",
146        vec![json_op(
147            "post",
148            "resumeSessionThread",
149            "Resume session into runtime thread",
150            None,
151            "ResumeSessionResponse",
152            u,
153        )],
154    );
155    add(
156        "/v1/resume-tasks/{thread_id}",
157        vec![json_op(
158            "get",
159            "getResumeTask",
160            "Resume seeding status",
161            None,
162            "ResumeSessionResponse",
163            u,
164        )],
165    );
166    add(
167        "/v1/workspace/status",
168        vec![json_op(
169            "get",
170            "workspaceStatus",
171            "Workspace status",
172            None,
173            "ErrorBody",
174            u,
175        )],
176    );
177    add(
178        "/v1/workspace/browse",
179        vec![json_op(
180            "get",
181            "browseWorkspace",
182            "Browse workspace",
183            None,
184            "ErrorBody",
185            u,
186        )],
187    );
188    add(
189        "/v1/workspace/file",
190        vec![json_op(
191            "get",
192            "readWorkspaceFile",
193            "Read workspace file",
194            None,
195            "ErrorBody",
196            u,
197        )],
198    );
199    add(
200        "/v1/stream",
201        vec![operation(
202            "post",
203            "streamTurn",
204            "Create thread and stream turn (SSE)",
205            Some("StreamTurnRequest"),
206            sse_response(),
207            u,
208        )],
209    );
210    add(
211        "/v1/threads",
212        vec![
213            json_op(
214                "get",
215                "listThreads",
216                "List threads",
217                None,
218                "ThreadRecord",
219                u,
220            ),
221            json_op(
222                "post",
223                "createThread",
224                "Create thread",
225                Some("CreateThreadRequest"),
226                "ThreadRecord",
227                u,
228            ),
229        ],
230    );
231    add(
232        "/v1/threads/summary",
233        vec![json_op(
234            "get",
235            "listThreadsSummary",
236            "Thread summaries",
237            None,
238            "ThreadSummary",
239            u,
240        )],
241    );
242    add(
243        "/v1/threads/{id}",
244        vec![
245            json_op("get", "getThread", "Thread detail", None, "ThreadDetail", u),
246            json_op(
247                "patch",
248                "updateThread",
249                "Patch thread",
250                Some("UpdateThreadRequest"),
251                "ThreadRecord",
252                u,
253            ),
254        ],
255    );
256    add(
257        "/v1/threads/{id}/checklist",
258        vec![json_op(
259            "get",
260            "getThreadChecklist",
261            "Thread checklist",
262            None,
263            "ErrorBody",
264            u,
265        )],
266    );
267    add(
268        "/v1/threads/{id}/scratchpad/status",
269        vec![json_op(
270            "get",
271            "getThreadScratchpadStatus",
272            "Scratchpad status",
273            None,
274            "ErrorBody",
275            u,
276        )],
277    );
278    add(
279        "/v1/threads/{id}/context",
280        vec![json_op(
281            "get",
282            "getThreadContext",
283            "Thread context",
284            None,
285            "ErrorBody",
286            u,
287        )],
288    );
289    add(
290        "/v1/threads/{id}/resume",
291        vec![json_op(
292            "post",
293            "resumeThread",
294            "Resume thread",
295            None,
296            "ThreadRecord",
297            u,
298        )],
299    );
300    add(
301        "/v1/threads/{id}/fork",
302        vec![json_op(
303            "post",
304            "forkThread",
305            "Fork thread",
306            None,
307            "ThreadRecord",
308            u,
309        )],
310    );
311    add(
312        "/v1/threads/{id}/fork-at-user-message",
313        vec![json_op(
314            "post",
315            "forkThreadAtUserMessage",
316            "Fork at user message",
317            None,
318            "ThreadRecord",
319            u,
320        )],
321    );
322    add(
323        "/v1/threads/{id}/edit-last-turn",
324        vec![json_op(
325            "post",
326            "editLastThreadTurn",
327            "Edit last turn",
328            None,
329            "StartTurnResponse",
330            u,
331        )],
332    );
333    add(
334        "/v1/threads/{id}/turns",
335        vec![json_op(
336            "post",
337            "startThreadTurn",
338            "Start turn",
339            Some("StartTurnRequest"),
340            "StartTurnResponse",
341            u,
342        )],
343    );
344    add(
345        "/v1/threads/{id}/turns/{turn_id}/steer",
346        vec![json_op(
347            "post",
348            "steerThreadTurn",
349            "Steer in-flight turn",
350            Some("SteerTurnRequest"),
351            "TurnRecord",
352            u,
353        )],
354    );
355    add(
356        "/v1/threads/{id}/turns/{turn_id}/resolve-approval",
357        vec![json_op(
358            "post",
359            "resolveApproval",
360            "Resolve exec approval",
361            None,
362            "ErrorBody",
363            u,
364        )],
365    );
366    add(
367        "/v1/threads/{id}/turns/{turn_id}/interrupt",
368        vec![json_op(
369            "post",
370            "interruptThreadTurn",
371            "Interrupt turn",
372            None,
373            "TurnRecord",
374            u,
375        )],
376    );
377    add(
378        "/v1/threads/{id}/compact",
379        vec![json_op(
380            "post",
381            "compactThread",
382            "Compact thread context",
383            None,
384            "ErrorBody",
385            u,
386        )],
387    );
388    add(
389        "/v1/threads/{id}/persist-session",
390        vec![json_op(
391            "post",
392            "persistThreadSession",
393            "Persist thread to session file",
394            None,
395            "ErrorBody",
396            u,
397        )],
398    );
399    add(
400        "/v1/threads/{id}/snapshots",
401        vec![json_op(
402            "get",
403            "listThreadSnapshots",
404            "List snapshots",
405            None,
406            "ErrorBody",
407            u,
408        )],
409    );
410    add(
411        "/v1/threads/{id}/snapshots/restore",
412        vec![json_op(
413            "post",
414            "restoreThreadSnapshot",
415            "Restore snapshot",
416            None,
417            "ThreadDetail",
418            u,
419        )],
420    );
421    add(
422        "/v1/threads/{id}/workspace/browse",
423        vec![json_op(
424            "get",
425            "browseThreadWorkspace",
426            "Browse thread workspace",
427            None,
428            "ErrorBody",
429            u,
430        )],
431    );
432    add(
433        "/v1/threads/{id}/workspace/file",
434        vec![json_op(
435            "get",
436            "readThreadWorkspaceFile",
437            "Read thread workspace file",
438            None,
439            "ErrorBody",
440            u,
441        )],
442    );
443    add(
444        "/v1/threads/{id}/events",
445        vec![operation(
446            "get",
447            "streamThreadEvents",
448            "Thread events SSE",
449            None,
450            sse_response(),
451            u,
452        )],
453    );
454    add(
455        "/v1/tasks",
456        vec![
457            json_op("get", "listTasks", "List tasks", None, "TasksResponse", u),
458            json_op("post", "createTask", "Create task", None, "TaskRecord", u),
459        ],
460    );
461    add(
462        "/v1/tasks/clear",
463        vec![json_op(
464            "post",
465            "clearTasks",
466            "Clear tasks",
467            None,
468            "ErrorBody",
469            u,
470        )],
471    );
472    add(
473        "/v1/tasks/{id}",
474        vec![json_op("get", "getTask", "Get task", None, "TaskRecord", u)],
475    );
476    add(
477        "/v1/tasks/{id}/cancel",
478        vec![json_op(
479            "post",
480            "cancelTask",
481            "Cancel task",
482            None,
483            "TaskRecord",
484            u,
485        )],
486    );
487    add(
488        "/v1/blackboards",
489        vec![json_op(
490            "get",
491            "listBlackboards",
492            "List blackboards",
493            None,
494            "ErrorBody",
495            u,
496        )],
497    );
498    add(
499        "/v1/blackboards/{id}",
500        vec![json_op(
501            "get",
502            "getBlackboard",
503            "Get blackboard",
504            None,
505            "ErrorBody",
506            u,
507        )],
508    );
509    add(
510        "/v1/topic-memory",
511        vec![json_op(
512            "get",
513            "getTopicMemory",
514            "Topic memory graph",
515            None,
516            "ErrorBody",
517            u,
518        )],
519    );
520    add(
521        "/v1/skills",
522        vec![
523            json_op("get", "listSkills", "List skills", None, "ErrorBody", u),
524            json_op("post", "createSkill", "Create skill", None, "ErrorBody", u),
525        ],
526    );
527    add(
528        "/v1/skills/import",
529        vec![json_op(
530            "post",
531            "importSkillLocal",
532            "Import local skill",
533            None,
534            "ErrorBody",
535            u,
536        )],
537    );
538    add(
539        "/v1/skills/install",
540        vec![json_op(
541            "post",
542            "installSkillRemote",
543            "Install remote skill",
544            None,
545            "ErrorBody",
546            u,
547        )],
548    );
549    add(
550        "/v1/apps/mcp/servers",
551        vec![
552            json_op(
553                "get",
554                "listMcpServers",
555                "List MCP servers",
556                None,
557                "ErrorBody",
558                u,
559            ),
560            json_op(
561                "post",
562                "addMcpServer",
563                "Add MCP server",
564                None,
565                "ErrorBody",
566                u,
567            ),
568        ],
569    );
570    add(
571        "/v1/apps/mcp/servers/{name}",
572        vec![
573            json_op(
574                "get",
575                "getMcpServer",
576                "Get MCP server",
577                None,
578                "ErrorBody",
579                u,
580            ),
581            json_op(
582                "put",
583                "updateMcpServer",
584                "Update MCP server",
585                None,
586                "ErrorBody",
587                u,
588            ),
589            operation(
590                "delete",
591                "deleteMcpServer",
592                "Delete MCP server",
593                None,
594                json!({ "description": "Deleted" }),
595                u,
596            ),
597        ],
598    );
599    add(
600        "/v1/apps/mcp/config/merge",
601        vec![json_op(
602            "post",
603            "mergeMcpConfig",
604            "Merge MCP config JSON",
605            None,
606            "ErrorBody",
607            u,
608        )],
609    );
610    add(
611        "/v1/apps/mcp/tools",
612        vec![json_op(
613            "get",
614            "listMcpTools",
615            "List MCP tools",
616            None,
617            "ErrorBody",
618            u,
619        )],
620    );
621    add(
622        "/v1/automations",
623        vec![
624            json_op(
625                "get",
626                "listAutomations",
627                "List automations",
628                None,
629                "ErrorBody",
630                u,
631            ),
632            json_op(
633                "post",
634                "createAutomation",
635                "Create automation",
636                None,
637                "ErrorBody",
638                u,
639            ),
640        ],
641    );
642    add(
643        "/v1/automations/{id}",
644        vec![
645            json_op(
646                "get",
647                "getAutomation",
648                "Get automation",
649                None,
650                "ErrorBody",
651                u,
652            ),
653            json_op(
654                "patch",
655                "updateAutomation",
656                "Update automation",
657                None,
658                "ErrorBody",
659                u,
660            ),
661            operation(
662                "delete",
663                "deleteAutomation",
664                "Delete automation",
665                None,
666                json!({ "description": "Deleted" }),
667                u,
668            ),
669        ],
670    );
671    add(
672        "/v1/automations/{id}/run",
673        vec![json_op(
674            "post",
675            "runAutomation",
676            "Run automation",
677            None,
678            "ErrorBody",
679            u,
680        )],
681    );
682    add(
683        "/v1/automations/{id}/pause",
684        vec![json_op(
685            "post",
686            "pauseAutomation",
687            "Pause automation",
688            None,
689            "ErrorBody",
690            u,
691        )],
692    );
693    add(
694        "/v1/automations/{id}/resume",
695        vec![json_op(
696            "post",
697            "resumeAutomation",
698            "Resume automation",
699            None,
700            "ErrorBody",
701            u,
702        )],
703    );
704    add(
705        "/v1/automations/{id}/runs",
706        vec![json_op(
707            "get",
708            "listAutomationRuns",
709            "List automation runs",
710            None,
711            "ErrorBody",
712            u,
713        )],
714    );
715    add(
716        "/v1/usage",
717        vec![json_op(
718            "get",
719            "getUsage",
720            "Usage aggregation",
721            None,
722            "UsageAggregation",
723            u,
724        )],
725    );
726    add(
727        "/v1/apps/routing/rules",
728        vec![
729            json_op(
730                "get",
731                "getRoutingRules",
732                "Get routing rules",
733                None,
734                "RoutingRulesDoc",
735                u,
736            ),
737            json_op(
738                "put",
739                "setRoutingRules",
740                "Set routing rules",
741                Some("RoutingRulesDoc"),
742                "RoutingRulesDoc",
743                u,
744            ),
745        ],
746    );
747    add(
748        "/v1/symbol-index/rebuild",
749        vec![json_op(
750            "post",
751            "rebuildSymbolIndex",
752            "Rebuild symbol index",
753            None,
754            "ErrorBody",
755            u,
756        )],
757    );
758
759    paths
760}
761
762/// Path templates registered in this module (guard drift vs `router.rs`).
763pub fn path_template_count() -> usize {
764    build_paths().len()
765}