feat: declare per-model capabilities on session/new - #24
Merged
Conversation
`configOptions` is rebuilt per model, so a client reading it learns nothing
about any other model — and ACP has no request that asks. Attach the catalog
we already hold as `_meta.lody.modelCapabilities`
(`{ version: 1, models: { <id>: { effortValues?, fastMode? } } }`).
Self-declared and advisory: the live session state stays the authority.
Model: claude-opus-5[1m]
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
configOptionsis rebuilt on every model switch: the Fast toggle is presentonly while
supportsFastMode, and the effort list belongs to the current model.A client reading the
session/newsnapshot therefore learns nothing about anyother model — and ACP has no request that asks.
Lody was reading those options as an agent-wide capability catalog, so selecting
a model other than the probed one produced answers like "this agent has no fast
mode" for a model that does, or the reverse.
What
Attach the catalog the SDK already handed us to the
session/newresponse:{ "sessionId": "…", "modes": { /* unchanged */ }, "configOptions": [ /* unchanged */ ], "_meta": { "lody": { "modelCapabilities": { "version": 1, "models": { "sonnet": { "effortValues": ["low", "medium", "high"], "fastMode": true }, "fable": { "fastMode": false } } } } } }Built from the
ModelInfo[]already in hand —supportedEffortLevels(onlywhen
supportsEffort) andsupportsFastMode. No new source of truth, no extrarequest.
effortValuesis omitted rather than emptied for a model that does notsupport effort, so "no effort control" and "an empty list" stay distinguishable.
Contract
Self-declared and advisory. It may describe a control the snapshot does not
carry; it never grants permission, authorizes a value, or rejects one. The live
session state remains the authority.
A model absent from
modelsis unknown, not unsupported. The consumertherefore reads the catalog whole or ignores it whole, and treats it as stale
after a TTL or a change of adapter version.
Emitted only when the model list is non-empty, so a client that ignores
_metasees a byte-identical response.
Consumer
Read by Lody in LodyAI/Lody#333, which ships first and reads an absent
declaration as "nothing to say" — so this can merge on its own schedule.
Test
npx tsc --noEmit,npx eslint src/acp-agent.ts, andprettier --checkclean.🤖 Generated with Claude Code