ActiveSession::response() rebuilds a NewSessionResponse from its internal fields, but config_options is not among them — the field is never stored on ActiveSession in the first place. Any client that works through ActiveSession therefore sees config_options: None no matter what the agent sent.
Versions
agent-client-protocol 2.0.0
agent-client-protocol-schema 1.5.0
Evidence
NewSessionResponse (schema-1.5.0/src/v1/agent.rs:1087-1112) carries four fields:
pub struct NewSessionResponse {
pub session_id: SessionId,
pub modes: Option<SessionModeState>,
pub config_options: Option<Vec<SessionConfigOption>>,
pub meta: Option<Meta>,
}
ActiveSession (2.0.0/src/session.rs:506-529) stores session_id, update_rx, update_tx, modes, meta, connection and the handler registrations — there is no config_options field (grep -c config_options src/session.rs → 0).
Consequently response() (2.0.0/src/session.rs:570-574) cannot return it:
pub fn response(&self) -> NewSessionResponse {
NewSessionResponse::new(self.session_id.clone())
.modes(self.modes.clone())
.meta(self.meta.clone())
}
No .config_options(...), so the value is dropped by construction rather than by accident.
Why it matters
config_options is how 2.0.0 expresses model selection: a SessionConfigOption with category: Some(SessionConfigOptionCategory::Model) and a SessionConfigSelect kind, changed via SetSessionConfigOptionRequest. The dedicated models / SessionModelState API was removed, so this is now the only route.
A client built on ActiveSession — the high-level API the crate steers you toward — cannot render a model picker at all. The remaining options are to intercept and re-parse the raw JSON-RPC traffic (duplicating parsing the library already does), or to keep a separate cache outside the session object. We ended up doing the former as a temporary workaround, which is what prompted this report.
Scope of what we verified
We verified the drop by reading the crate sources at the versions above, not by observing a configOptions payload end-to-end: the agent we integrate against still emits the pre-2.0 models shape, so we could not exercise the happy path. The defect is visible in the type and the constructor regardless of any agent's behaviour — config_options has nowhere to be stored.
Expected
ActiveSession should keep config_options from the original NewSessionResponse and include it in response(), exactly as it already does for modes and meta. An accessor alongside modes() would also work.
ActiveSession::response()rebuilds aNewSessionResponsefrom its internal fields, butconfig_optionsis not among them — the field is never stored onActiveSessionin the first place. Any client that works throughActiveSessiontherefore seesconfig_options: Noneno matter what the agent sent.Versions
agent-client-protocol2.0.0agent-client-protocol-schema1.5.0Evidence
NewSessionResponse(schema-1.5.0/src/v1/agent.rs:1087-1112) carries four fields:ActiveSession(2.0.0/src/session.rs:506-529) storessession_id,update_rx,update_tx,modes,meta,connectionand the handler registrations — there is noconfig_optionsfield (grep -c config_options src/session.rs→0).Consequently
response()(2.0.0/src/session.rs:570-574) cannot return it:No
.config_options(...), so the value is dropped by construction rather than by accident.Why it matters
config_optionsis how 2.0.0 expresses model selection: aSessionConfigOptionwithcategory: Some(SessionConfigOptionCategory::Model)and aSessionConfigSelectkind, changed viaSetSessionConfigOptionRequest. The dedicatedmodels/SessionModelStateAPI was removed, so this is now the only route.A client built on
ActiveSession— the high-level API the crate steers you toward — cannot render a model picker at all. The remaining options are to intercept and re-parse the raw JSON-RPC traffic (duplicating parsing the library already does), or to keep a separate cache outside the session object. We ended up doing the former as a temporary workaround, which is what prompted this report.Scope of what we verified
We verified the drop by reading the crate sources at the versions above, not by observing a
configOptionspayload end-to-end: the agent we integrate against still emits the pre-2.0modelsshape, so we could not exercise the happy path. The defect is visible in the type and the constructor regardless of any agent's behaviour —config_optionshas nowhere to be stored.Expected
ActiveSessionshould keepconfig_optionsfrom the originalNewSessionResponseand include it inresponse(), exactly as it already does formodesandmeta. An accessor alongsidemodes()would also work.