feat(cursor): wire /models /agents /cancel to cursor-agent configOptions#492
feat(cursor): wire /models /agents /cancel to cursor-agent configOptions#492brettchien wants to merge 3 commits intoopenabdev:mainfrom
Conversation
Closes openabdev#489. Key changes: - discord slash handlers defer_ephemeral first, then get_or_create the pooled ACP session, then edit_response with the select menu built from the session's cached configOptions. - /models runs a silent "ping" probe after set_config_option to catch cursor-agent's soft-reject (`AI Model Not Found` / `Model name is not valid`) and falls back to `default[]` (Auto). Probe timeout is configurable via `[agent].probe_timeout_secs` (default 15s); on timeout the probe is cancelled and the same fallback runs. - Cap StringSelectMenu at Discord's 25-option limit, preserving the current value and `default[]` when truncating (cursor-agent returns 26 models on a Pro account). - Treat `agent` and `mode` categories as aliases so the same `/agents` command works against both kiro-cli (category=agent) and cursor-agent (category=mode). Adds `ProbeResult` + `probe_prompt` on AcpConnection and `probe_session` + `probe_timeout_secs` on SessionPool. Docs updated in `docs/cursor.md` with the /models behaviour + probe semantics. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Strip the proactive probe + auto-fallback-to-Auto workaround for cursor-agent's soft-reject behaviour. Per project policy we trust the ACP protocol: `setOk:true` means the switch succeeded. The upstream cursor-agent bug where `set_config_option` accepts unroutable models is tracked in openabdev#493 and reported via the Cursor forum. Retained: - /models, /agents, /cancel wired to ACP `configOptions` - `defer_ephemeral` + `edit_response` pattern to avoid Discord 3s deadline - Pre-flight `get_or_create` so the command works before first @mention - 25-option cap on Discord select menus (cursor-agent returns 26 models on Pro accounts); current/default pinned when truncating - `agent`/`mode` category alias for kiro-cli compatibility Removed: - `AcpConnection::probe_prompt` and `ProbeResult` (connection.rs) - `SessionPool::probe_session` and `probe_timeout_secs` (pool.rs) - `AgentConfig.probe_timeout_secs` field (config.rs) - `Handler::fallback_to_auto` and all /models probe logic (discord.rs) - `probe_timeout_secs` example in config.toml.example - Proactive-probe section in docs/cursor.md, replaced with "Soft rejects from unroutable models" passthrough explanation docs/cursor.md now includes a Known Limitations subsection listing the three upstream ACP compliance gaps (setOk for unroutable models, unfiltered model list, process-local loadSession), all linked to openabdev#493. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Drop the current-value + `default[]` pinning logic inside `build_config_select`. The pin was motivated by preserving Auto when truncating from 26 to 25 cursor-agent models, but `"default[]"` is a cursor-specific literal and the extra complexity buys little — Auto is already first in cursor-agent's model list, so a straight in-order `take(25)` keeps it. When `current_value` sits at position >25 the dropdown won't show it as the default, but the live session retains the selection on cursor's side; user can switch again by rerunning `/models`. This keeps `build_config_select` ACP-agnostic: no vendor literals, no assumptions about which option is the "fallback". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
OpenAB PR ScreeningThis is a manually uploaded screening report from the OpenAB project-screening flow for context collection and reviewer handoff.
Screening reportIntentpr the concrete problem is twofold. first, cursor-backed channels currently miss the intended assumption: deploy-time cursor support already exists in-tree through the existing cursor image, helm values, and docs, so this pr is intentionally about discord interaction flow and policy boundary, not first-time packaging. Featthis is a feature and interaction-hardening pass centered in in plain terms, it makes cursor sessions behave like a real first-class ACP backend for discord controls:
notably, the ACP transport, pool internals, and config parsing layer stay untouched. that is a good boundary. Who It Servesthe primary beneficiary is discord users running openab against secondarily it serves maintainers and deployers. the docs now make the startup model invariant and upstream cursor-agent defects explicit, which reduces false debugging loops where openab gets blamed for cursor's bad protocol behavior. Rewritten Promptimplement cursor-compatible discord config controls without adding cursor-specific heuristics to the ACP layer. acceptance criteria:
validation:
if issue Merge Pitchthis is worth merging because it closes a real product gap for cursor-backed deployments with relatively tight scope. users get the same slash-command control surface other ACP backends already expose, and the implementation does it in the right layer: discord handler and docs, not protocol-shaping hacks. risk is moderate but localized. the code changes sit in interaction timing and pooled session bootstrapping, which can regress command UX if wrong, but they do not alter the ACP core. the likely reviewer concern is not the handler logic itself. it is whether this pr is claiming to close more than it actually does, because Best-Practice ComparisonOpenClaw: the relevant principle is boundary discipline. route work explicitly, surface failures honestly, and do not smuggle backend-specific recovery rules into the wrong layer. this pr matches that better than the earlier probe-and-fallback direction. durable job persistence and retry/backoff are not directly relevant here because this is an interactive discord control path, not a scheduled execution pipeline. Hermes Agent: the relevant principle is making state transitions explicit before acting. the defer-first plus net: the useful lesson from both reference systems is not their runtime architecture. it is their refusal to paper over undefined state with wishful logic. Implementation Options
Comparison Table
Recommendationtake option 1. the pr is strongest when treated as a focused interaction-layer improvement plus documentation cleanup. it fixes a real user-facing gap, keeps the ACP boundary honest, and avoids merging policy-confused workaround code just because cursor-agent is sloppy. if maintainers still want a dedicated the one thing to watch in review is scope accounting: if |
Closes #489.
Discussion: https://discord.com/channels/1491295327620169908/1491365150664560881/1495774750226645133
Upstream cursor-agent ACP compliance gaps tracked separately in #493.
Summary
/models,/agents,/cancelnow work end-to-end againstcursor-agent acp.defer_ephemeral→pool.get_or_create(thread_key)→ build select menu from the session's cachedconfigOptions→edit_response. No more "start a conversation first" dead-end, and the 3s Discord interaction deadline is honoured even on cold-start sessions.take(25)— no vendor-specific pinning. cursor-agent returns 26 models on a Pro account; the last one is dropped.agent/modecategory treated as aliases so the same/agentshandler works against both kiro-cli (category=agent) and cursor-agent (category=mode). Per ACP spec the reserved value is"mode".set_config_option. If cursor-agent accepts an unroutable model withsetOk:trueand then soft-rejects on the next prompt, that soft-reject is passed through to the channel. Upstream bug tracked in tracking: cursor-agent ACP compliance issues — upstream bugs affecting /models #493.Changes
src/discord.rs— newhandle_config_command(shared by /models and /agents),handle_config_select,handle_cancel_command;build_config_selectwith ACP-agnostic 25-option cap; category alias table.config.toml.example— documents the--model autostartup gotcha in the cursor-agent section.docs/cursor.md— Model Selection section with startup--model autotable and passthrough semantics; new Known Limitations subsection listing three upstream cursor-agent ACP compliance gaps (all linked to tracking: cursor-agent ACP compliance issues — upstream bugs affecting /models #493).No changes in
src/acp/connection.rs,src/acp/pool.rs, orsrc/config.rs— ACP layer untouched.Test plan
cargo checkcleancargo test --release— 74/74 passopenab-cursorpod running cursor-agent2026.04.15-dccdccd:/modelslists 25 models (truncated from 26) with the current value highlightedcomposer-2) →✅ Switched to composer-2, next prompt routes there/agentslists Agent / Plan / Ask (regression from v0.7.8 where it returned "No agent options available" against cursor-agent)/cancelagainst an in-flight prompt →session/cancel→stopReason: cancelled(~15ms roundtrip, verified in pod logs)"\n\nCheck your settings to continue"for an unroutable model and OpenAB forwarded it unchanged (new variant beyond theAI Model Not Found/Model name is not validfamily, noted for tracking: cursor-agent ACP compliance issues — upstream bugs affecting /models #493)Revision history
ping, detected cursor-agent's plain-text soft-reject, and auto-fell-back todefault[]on hit.set_config_optionsemantics intact and surfaces the upstream bug directly in-channel."default[]") also removed — kept as a plain in-ordertake(25)sobuild_config_selecthas no vendor literals.🤖 Generated with Claude Code