Correct what the thread route publishes

988cbfd40d31 · AtlantisPleb · · parent 727ab02ececd

Correct what the thread route publishes

Two comments said `POST /api/v1/threads` publishes no model parameter. It does.
The server's own capability manifest documents it — an enum over
`Models.ids()`, with a default, refused with a field-level 422 outside the enum
and `model_unavailable` for a listed model whose provider is not configured.

The behaviour the comments were defending is still right: report the model the
grant named rather than the one the flag asked for. That is true because the
grant pins the model for the thread's life, not because the request has nowhere
to say it. Same conclusion, honest reason.

It also changes what `Shift+Tab: lane` would take to build, so the note in
`tui.rs` now says that: a lane control is possible, but changing a model means
opening a new thread, which makes it a session decision rather than a
keystroke.

Found by the agent porting `runtime.rs`, which checked the manifest instead of
believing the comment. This is a reland: the first push reported success and
the commit is not in main's history, so it was lost rather than merged.

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified crates/openagents-cli/src/interactive.rs
  • modified crates/openagents-cli/src/tui.rs

Diff

2 files changed, +13 -8

crates/openagents-cli/src/interactive.rs modified +5 -3

@@ -55,9 +55,11 @@ pub enum TurnEvent {

55 55
    Failed(String),
56 56
    /// The model the server's grant named for that turn.
57 57
    ///
58
    /// It is reported rather than assumed because the CLI cannot choose it:
59
    /// `POST /api/v1/threads` publishes no model parameter, and the grant it
60
    /// returns pins the model that answers.
58
    /// Reported rather than assumed. `POST /api/v1/threads` does take a
59
    /// `model`, but what answers is whatever the returned grant pins — a value
60
    /// outside the enum is refused, and a listed model whose provider is not
61
    /// configured is refused as `model_unavailable`. So the request is a
62
    /// preference and the grant is the fact, and this carries the fact.
61 63
    Model(String),
62 64
}
63 65
crates/openagents-cli/src/tui.rs modified +8 -5

@@ -387,11 +387,14 @@ pub fn composer_text_width(frame_width: u16) -> usize {

387 387
///
388 388
/// `Tab: effort` toggled nothing: it appended the words `[Toggled reasoning
389 389
/// effort]` to the transcript, and `execute_turn` has no effort field to send
390
/// even if it had meant it. `Shift+Tab: lane` was never handled at all, and a
391
/// lane control here cannot do what its name says: `POST /api/v1/threads`
392
/// publishes no model parameter, and the grant it returns pins the model that
393
/// answers. The bar reports that model instead, which is a fact rather than a
394
/// request.
390
/// even if it had meant it. `Shift+Tab: lane` was never handled at all.
391
///
392
/// A lane control here is buildable — `POST /api/v1/threads` does take a
393
/// `model`, and `oa coder --lane` uses it — but it would have to open a new
394
/// thread to change one, since the grant a thread returns pins the model for
395
/// that thread's whole life. Mid-session cycling is therefore a session
396
/// decision, not a keystroke. Until that exists, the bar reports the model the
397
/// grant named, which is a fact rather than a request.
395 398
const HINTS: [&str; 4] = [
396 399
    "Enter: send",
397 400
    "Esc: exit",

This page updates live while a promote is in flight · changelog