aboutsummaryrefslogtreecommitdiff
path: root/src/app/api
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-10 15:24:24 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-10 15:33:45 +0300
commit36a1b7f86444871f0c38ff36510a6e3c2eec48c6 (patch)
tree4a2d100eef7f26af7feaa93ce661423c3994c54e /src/app/api
parent8d13492926829c5cf0ea42c8613344cd65ff59fa (diff)
feat: distribute agent detection manifests
Diffstat (limited to 'src/app/api')
-rw-r--r--src/app/api/agents.rs63
-rw-r--r--src/app/api/panes.rs2
2 files changed, 65 insertions, 0 deletions
diff --git a/src/app/api/agents.rs b/src/app/api/agents.rs
index 4077b38c..f89be0ce 100644
--- a/src/app/api/agents.rs
+++ b/src/app/api/agents.rs
@@ -73,11 +73,13 @@ impl App {
ReadSource::Visible => pane.visible_text(),
ReadSource::Recent => pane.recent_text(requested_lines),
ReadSource::RecentUnwrapped => pane.recent_unwrapped_text(requested_lines),
+ ReadSource::Detection => pane.detection_text(),
},
ReadFormat::Ansi => match params.source {
ReadSource::Visible => pane.visible_ansi(),
ReadSource::Recent => pane.recent_ansi(requested_lines),
ReadSource::RecentUnwrapped => pane.recent_unwrapped_ansi(requested_lines),
+ ReadSource::Detection => pane.detection_text(),
},
};
@@ -102,6 +104,67 @@ impl App {
)
}
+ pub(super) fn handle_agent_explain(&mut self, id: String, target: AgentTarget) -> String {
+ let resolved = match self.resolve_terminal_target(&target.target) {
+ Ok(resolved) => resolved,
+ Err(err) => return encode_error_body(id, self.agent_target_error_body(err)),
+ };
+ let Some((pane, _workspace_id)) = self.lookup_runtime(resolved.ws_idx, resolved.pane_id)
+ else {
+ return agent_not_found(id, &target.target);
+ };
+ let Some(terminal_id) = self
+ .state
+ .workspaces
+ .get(resolved.ws_idx)
+ .and_then(|workspace| workspace.terminal_id(resolved.pane_id))
+ else {
+ return agent_not_found(id, &target.target);
+ };
+ let Some(terminal) = self.state.terminals.get(terminal_id) else {
+ return agent_not_found(id, &target.target);
+ };
+ if terminal.full_lifecycle_hook_authority_active() {
+ let explain = serde_json::json!({
+ "agent": terminal.effective_agent_label().unwrap_or("unknown"),
+ "state": crate::detect::manifest::agent_state_label(terminal.state),
+ "manifest_source": null,
+ "manifest_version": null,
+ "cached_remote_version": null,
+ "local_override_shadowing_remote": false,
+ "remote_update_status": null,
+ "remote_update_error": null,
+ "matched_rule": null,
+ "visible_idle": false,
+ "visible_blocker": false,
+ "visible_working": false,
+ "screen_detection_skipped": true,
+ "screen_detection_skip_reason": "full_lifecycle_hook_authority",
+ "skip_state_update": false,
+ "skipped_update_reason": null,
+ "fallback_reason": null,
+ "warning": null,
+ "evaluated_rules": [],
+ });
+ return encode_success(id, ResponseResult::AgentExplain { explain });
+ }
+ let Some(agent) = terminal.effective_known_agent().or(terminal.detected_agent) else {
+ return encode_error(
+ id,
+ "agent_explain_unavailable",
+ format!(
+ "agent target {} does not have a detected agent label",
+ target.target
+ ),
+ );
+ };
+
+ let explain = crate::detect::manifest::explain(agent, &pane.detection_text());
+ let value = crate::detect::manifest::explain_to_json_value(&explain);
+
+ encode_success(id, ResponseResult::AgentExplain { explain: value })
+ }
+
pub(super) fn handle_agent_send(&mut self, id: String, params: AgentSendParams) -> String {
let resolved = match self.resolve_terminal_target(&params.target) {
Ok(resolved) => resolved,
diff --git a/src/app/api/panes.rs b/src/app/api/panes.rs
index d824d26b..5afac850 100644
--- a/src/app/api/panes.rs
+++ b/src/app/api/panes.rs
@@ -616,11 +616,13 @@ impl App {
ReadSource::Visible => pane.visible_text(),
ReadSource::Recent => pane.recent_text(requested_lines),
ReadSource::RecentUnwrapped => pane.recent_unwrapped_text(requested_lines),
+ ReadSource::Detection => pane.detection_text(),
},
ReadFormat::Ansi => match params.source {
ReadSource::Visible => pane.visible_ansi(),
ReadSource::Recent => pane.recent_ansi(requested_lines),
ReadSource::RecentUnwrapped => pane.recent_unwrapped_ansi(requested_lines),
+ ReadSource::Detection => pane.detection_text(),
},
};