Skip to content

feat(hub/acp): translate ACP configOptions into mode/model state events (#334)#336

Merged
physercoe merged 2 commits into
mainfrom
feat/acp-config-options
Jul 19, 2026
Merged

feat(hub/acp): translate ACP configOptions into mode/model state events (#334)#336
physercoe merged 2 commits into
mainfrom
feat/acp-config-options

Conversation

@physercoe

Copy link
Copy Markdown
Owner

Closes #334.

Summary

Newer ACP daemons — kimi-code-ts (ADR-054 D6), added in #335 — report per-session model/mode state via a configOptions select array in the session/new reply instead of the legacy modes/models blocks. ACPDriver only parsed the legacy shape, so the mode/model picker never hydrated for these engines even though session/set_model works on the wire (the gap #334 documents).

Change

New translateConfigOptions(raw) maps the configOptions array into the same mode/model list shape the legacy path already produces — mode entries keyed by id, model entries by modelId (both carrying name) — so the existing id-set caching + synthetic initial-state system event downstream in Start consumes either shape unchanged.

  • Shape-driven + engine-neutral (per the issue's rationale): translates whichever shape arrives; any future ACP adopter (gemini-cli/codex) benefits with no further work.
  • No regression (acceptance deps(actions): Bump softprops/action-gh-release from 2 to 3 #3): filled per category, only when the legacy field is absent, so a legacy-shaped reply produces byte-identical output. The existing TestACPDriver_EmitsInitialModeModelSystemEvent / SetModelDispatch / SetModelDispatch_KimiShape tests stay green.
  • thought_level (acceptance deps(hub): bump modernc.org/sqlite from 1.34.4 to 1.50.0 in /hub #4, out of scope): no mobile picker yet, so its current value rides the initial-state event under a distinct thoughtLevel key for forensics only — never folded into the mode/model reducer.
  • config_option_update mid-session notifications fold into the same system-event path as current_mode_update / current_model_update.

Acceptance criteria

  • configOptions → initial mode/model state event, picker renders with current model preselected (currentModeId/currentModelId set from currentValue).
  • set_model validates against the cached list populated from configOptions (integration test round-trips it).
  • No regression for gemini-cli / Python kimi-code — legacy tests byte-identical.
  • session/load empty/{} carryover unaffected (W7/W7c path untouched; feat(hub/hostrunner): add kimi-code-ts engine family (TypeScript Kimi Code), M1-only via ACP #335's TestSessions_ResumeThreadsACPCursor_KimiCodeTS covers the kimi-code-ts resume case).

Tests

  • TestTranslateConfigOptions — unit; the live kimi-code 0.27.0 capture from feat(hub/acp): translate ACP configOptions into mode/model state events #334 plus malformed JSON, no-configOptions, and empty-value drop.
  • TestACPDriver_ConfigOptionsHydratesModeModelState — integration; asserts the synthesized system event's current ids + thoughtLevel forensics field + a set_model round-trip against the configOptions-advertised model.
  • go vet clean; full internal/hostrunner suite passes locally (Go at /usr/local/go).

🤖 Generated with Claude Code

Ubuntu and others added 2 commits July 19, 2026 13:23
…ts (#334)

Newer ACP daemons (kimi-code-ts, ADR-054 D6) report per-session model/mode
state via a `configOptions` select array in the session/new reply instead of
the legacy `modes`/`models` blocks. ACPDriver only parsed the legacy shape, so
the mode/model picker never hydrated for these engines even though switching
works on the wire.

Add `translateConfigOptions` — maps the `configOptions` array into the same
mode/model lists the legacy path produces (mode entries keyed by `id`, model
entries by `modelId`, both carrying `name`), so a single downstream (id-set
caching + the synthetic initial-state system event) handles either shape.

- Shape-driven + engine-neutral: any future ACP adopter benefits.
- Filled PER CATEGORY, only when the legacy field is absent → legacy-shaped
  replies (gemini-cli, Python kimi-code) produce byte-identical output.
- `thought_level` has no mobile picker yet: its current value rides the
  initial-state event under `thoughtLevel` for forensics only.
- `config_option_update` notifications fold into the same system-event path
  as current_mode_update / current_model_update.

Tests: TestTranslateConfigOptions (unit — kimi 0.27.0 capture, malformed,
empty-value, no-configOptions); TestACPDriver_ConfigOptionsHydratesModeModelState
(integration — initial-state event + current ids + thoughtLevel + a set_model
round-trip validating against the cached list). Legacy mode/model tests stay
green. go vet + full hostrunner suite pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The lint-legacy-markers ratchet flagged the descriptive word "legacy" in the
new configOptions comments as an untargeted compat-debt marker. The older
modes/models ACP shape isn't being removed (gemini-cli / Python kimi-code keep
using it), so "legacy" was inaccurate anyway — reworded to "older" /
"modes/models-shaped". No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@physercoe
physercoe merged commit ea01628 into main Jul 19, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(hub/acp): translate ACP configOptions into mode/model state events

1 participant