Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src-tauri/src/acp/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3036,6 +3036,13 @@ fn claude_raw_sdk_session_meta(
/// Codex to keep the blast radius off other agents (e.g. Claude's native
/// AskUserQuestion, which would otherwise un-gate and duplicate the
/// codeg-mcp ask tool).
/// - Cursor only: `_meta["parameterizedModelPicker"] = true` — Cursor
/// ACP then publishes the base model plus separate session config
/// options for reasoning / effort / thinking / context / fast, instead
/// of one exploded `model` list whose values look like
/// `claude-opus-4-6[thinking=true,context=200k,effort=high]`. The chat
/// composer already renders each advertised option. Cursor staff
/// documented this `_meta` flag as the client opt-in (2026-05-22).
/// - Claude Code only: `_meta["subagent-transcript"] = true` — opt into
/// claude-agent-acp ≥0.63's subagent transcript forwarding (#881, SDK
/// `forwardSubagentText`). Subagent text/thought chunks then stream with
Expand Down Expand Up @@ -3082,6 +3089,14 @@ fn build_client_capabilities(
if agent_type == AgentType::ClaudeCode {
meta.insert("subagent-transcript".to_string(), serde_json::Value::Bool(true));
}
if agent_type == AgentType::Cursor {
// Cursor checks strictly for boolean true. Unknown agents ignore
// the key, so this stays Cursor-scoped on purpose.
meta.insert(
"parameterizedModelPicker".to_string(),
serde_json::Value::Bool(true),
);
}
// The capabilities array is deliberately "sessionFailure" ONLY.
// claude-agent-acp 0.69.0 and codex-acp 1.4.0 added a second AIR
// capability, "agentFileChangeReport": advertise it and every prompt may
Expand Down Expand Up @@ -12276,6 +12291,15 @@ mod tests {
assert!(deepseek.get("elicitation").is_some());
assert!(deepseek.get("_meta").is_none());

// Cursor: native model + effort/context/fast options, no elicitation.
let cursor = caps_of(AgentType::Cursor);
assert_eq!(
cursor["_meta"]["parameterizedModelPicker"],
serde_json::Value::Bool(true)
);
assert!(cursor["_meta"].get("subagent-transcript").is_none());
assert!(cursor.get("elicitation").is_none());

// Everyone else: neither gate; fs + terminal always advertised.
let other = caps_of(AgentType::Gemini);
assert!(other.get("_meta").is_none());
Expand Down
Loading