agentmux_srv/server/
http_layout.rs1use super::*;
8
9pub(super) async fn handle_layout(State(state): State<AppState>) -> impl IntoResponse {
11 Json(service::agent_layout(&state.mstore))
12}
13
14pub(super) async fn handle_list_windows(State(state): State<AppState>) -> impl IntoResponse {
16 Json(service::agent_windows(&state.mstore))
17}
18
19pub(super) async fn handle_list_workspaces(State(state): State<AppState>) -> impl IntoResponse {
21 Json(service::agent_workspaces(&state.mstore))
22}
23
24#[derive(serde::Deserialize)]
25pub(super) struct ListTabsQuery {
26 #[serde(default)]
28 pub(super) workspace_id: Option<String>,
29 #[serde(default)]
32 pub(super) block_id: Option<String>,
33}
34
35pub(super) async fn handle_list_tabs(
38 State(state): State<AppState>,
39 Query(q): Query<ListTabsQuery>,
40) -> impl IntoResponse {
41 let ws_id = q.workspace_id.filter(|w| !w.is_empty()).or_else(|| {
42 q.block_id
43 .filter(|b| !b.is_empty())
44 .and_then(|b| service::resolve_agent_context(&state.mstore, &b).ok())
45 .and_then(|ctx| ctx.workspace_id)
46 });
47 Json(service::agent_tabs(&state.mstore, ws_id.as_deref()))
48}
49
50pub(super) async fn handle_tab_activate(
53 State(state): State<AppState>,
54 Json(req): Json<TabActivateRequest>,
55) -> impl IntoResponse {
56 let tab_id = req.tab_id.trim().to_string();
57 if tab_id.is_empty() {
58 return (StatusCode::BAD_REQUEST, Json(json!({ "error": "missing tab_id" }))).into_response();
59 }
60 let ws_id = match service::workspace_id_for_tab(&state.mstore, &tab_id) {
61 Some(w) => w,
62 None => return (StatusCode::NOT_FOUND, Json(json!({ "error": format!("no workspace owns tab {tab_id}") }))).into_response(),
63 };
64 let call = crate::backend::service::WebCallType {
65 service: "workspace".to_string(),
66 method: "SetActiveTab".to_string(),
67 uicontext: None,
68 args: vec![json!(ws_id), json!(tab_id)],
69 };
70 finish_name_call(&state, call, json!({ "success": true, "tab_id": tab_id })).await
71}
72
73pub(super) async fn handle_tab_new(
77 State(state): State<AppState>,
78 Json(req): Json<TabNewRequest>,
79) -> impl IntoResponse {
80 let name = req.name.map(|n| n.trim().chars().take(128).collect::<String>()).unwrap_or_default();
81 let workspace_id = match req.workspace_id.filter(|w| !w.is_empty()) {
82 Some(w) => w,
83 None => match resolve_own(&state, req.block_id, |c| c.workspace_id.clone()) {
84 Ok(w) => w,
85 Err(resp) => return resp,
86 },
87 };
88 let call = crate::backend::service::WebCallType {
89 service: "workspace".to_string(),
90 method: "CreateTab".to_string(),
91 uicontext: None,
92 args: vec![json!(workspace_id), json!(name), json!(true)],
94 };
95 finish_name_call(&state, call, json!({ "success": true, "workspace_id": workspace_id })).await
96}
97
98pub(super) async fn handle_window_focus(
101 State(state): State<AppState>,
102 Json(req): Json<WindowFocusRequest>,
103) -> impl IntoResponse {
104 let window_id = match req.window_id.filter(|w| !w.is_empty()) {
105 Some(w) => w,
106 None => match resolve_own(&state, req.block_id, |c| c.window_id.clone()) {
107 Ok(w) => w,
108 Err(resp) => return resp,
109 },
110 };
111 let call = crate::backend::service::WebCallType {
112 service: "client".to_string(),
113 method: "FocusWindow".to_string(),
114 uicontext: None,
115 args: vec![json!(window_id)],
116 };
117 finish_name_call(&state, call, json!({ "success": true, "window_id": window_id })).await
118}