zagens_runtime/runtime_api/
mod.rs1use std::path::PathBuf;
4use std::sync::Arc;
5
6use crate::automation_manager::SharedAutomationManager;
7use crate::config::Config;
8use crate::runtime_threads::SharedRuntimeThreadManager;
9use crate::session_manager::SessionManager;
10use crate::task_manager::SharedTaskManager;
11
12pub mod openapi;
13
14mod automations;
15mod blackboards;
16mod mcp;
17mod office;
18mod router;
19mod sessions;
20mod skills;
21mod state;
22mod stream;
23mod tasks;
24mod threads;
25mod topic_memory;
26mod usage;
27pub(crate) mod workspace;
28
29pub(crate) use automations::{
30 create_automation, delete_automation, get_automation, list_automation_runs, list_automations,
31 pause_automation, resume_automation, run_automation, update_automation,
32};
33pub(crate) use blackboards::{get_blackboard, list_blackboards};
34pub(crate) use mcp::{
35 add_mcp_server, delete_mcp_server, discover_mcp, get_mcp_server, list_mcp_calls,
36 list_mcp_servers, list_mcp_tools, merge_mcp_config_json, reload_mcp_config, update_mcp_server,
37};
38pub(crate) use office::get_office_environment;
39pub(crate) use sessions::{
40 delete_session, get_resume_task, get_session, list_sessions, resume_session_thread,
41};
42pub(crate) use skills::{create_skill, import_skill_local, install_skill_remote, list_skills};
43pub(crate) use tasks::{cancel_task, clear_tasks, create_task, get_task, list_tasks};
44pub(crate) use threads::{
45 browse_thread_workspace, browse_workspace_by_root, compact_thread, create_thread,
46 edit_last_thread_turn, fork_thread, fork_thread_at_user_message, get_thread,
47 get_thread_checklist, get_thread_context, get_thread_harness_cycles,
48 get_thread_harness_task_graph, get_thread_scratchpad_status, init_thread_scratchpad,
49 interrupt_thread_turn, list_thread_snapshots, list_threads, list_threads_summary,
50 persist_thread_session, read_thread_workspace_file, read_workspace_file_by_root,
51 resolve_approval, restore_thread_snapshot, resume_thread, start_thread_turn, steer_thread_turn,
52 update_thread,
53};
54pub(crate) use topic_memory::get_topic_memory;
55pub(crate) use usage::{get_routing_rules, get_usage, rebuild_symbol_index, set_routing_rules};
56pub(crate) use workspace::workspace_status;
57
58pub use router::build_router;
59
60pub(crate) use sessions::ResumeTaskTracker;
61
62#[cfg(test)]
63pub(crate) use zagens_runtime_api::cors_layer;
64
65#[derive(Clone)]
66pub struct RuntimeApiState {
67 config: Config,
68 workspace: PathBuf,
69 task_manager: SharedTaskManager,
70 runtime_threads: SharedRuntimeThreadManager,
71 cors_origins: Vec<String>,
72 mcp_config_path: PathBuf,
73 automations: SharedAutomationManager,
74 runtime_token: Option<String>,
75 process_started_at_ms: u128,
76 token_fingerprint: Arc<String>,
77 shared_session_manager: Arc<SessionManager>,
78 resume_tracker: sessions::ResumeTaskTracker,
79 shared_mcp_pool: std::sync::Arc<tokio::sync::Mutex<crate::mcp::McpPool>>,
81}
82
83impl RuntimeApiState {
84 #[allow(clippy::too_many_arguments)]
85 pub(crate) fn new(
86 config: Config,
87 workspace: PathBuf,
88 task_manager: SharedTaskManager,
89 runtime_threads: SharedRuntimeThreadManager,
90 cors_origins: Vec<String>,
91 mcp_config_path: PathBuf,
92 automations: SharedAutomationManager,
93 runtime_token: Option<String>,
94 process_started_at_ms: u128,
95 token_fingerprint: Arc<String>,
96 shared_session_manager: Arc<SessionManager>,
97 resume_tracker: sessions::ResumeTaskTracker,
98 shared_mcp_pool: std::sync::Arc<tokio::sync::Mutex<crate::mcp::McpPool>>,
99 ) -> Self {
100 Self {
101 config,
102 workspace,
103 task_manager,
104 runtime_threads,
105 cors_origins,
106 mcp_config_path,
107 automations,
108 runtime_token,
109 process_started_at_ms,
110 token_fingerprint,
111 shared_session_manager,
112 resume_tracker,
113 shared_mcp_pool,
114 }
115 }
116}
117
118pub(crate) fn truncate_text(text: &str, max_chars: usize) -> String {
119 let char_count = text.chars().count();
120 if char_count <= max_chars {
121 return text.to_string();
122 }
123 let truncated: String = text.chars().take(max_chars.saturating_sub(3)).collect();
124 format!("{truncated}...")
125}
126
127pub(crate) use zagens_runtime_api::ApiError;
128
129pub(crate) fn map_thread_err(err: anyhow::Error) -> ApiError {
130 let message = err.to_string();
131 if message.contains("not found") {
132 ApiError::not_found(message)
133 } else if message.contains("already has an active turn")
134 || message.contains("No active turn")
135 || message.contains("is not active")
136 || message.contains("no pending approval for")
137 || message.contains("pending approval scope mismatch")
138 {
139 ApiError::conflict(message)
140 } else {
141 ApiError::bad_request(message)
142 }
143}
144
145#[cfg(test)]
146#[path = "tests.rs"]
147mod tests;