fix(sessions): keep a session's model through recovery, refuse it off claude

SessionState now carries the model a session launched with, and both
recovery constructors (mux recovery and reboot restore) pass it back, so a
recovered session relaunches on the same --model rather than the account
default. A top-level `model` sent with any other CLI is refused, since
those take their model in their own config object, and an empty string
means no per-session model, as it does for modelOverride.

CLAUDE.md now describes both routes for a Claude model. The tests pin
which of `model` and `modelOverride` reaches the launch and which the
case file, and that a model opening with a dash renders as --model's value.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michael Grundberg
2026-10-01 17:24:12 +02:00
co-authored by Claude Opus 5.5
parent 4123d229f4
commit 3df113fc54
12 changed files with 136 additions and 12 deletions
+4 -1
View File
@@ -529,12 +529,15 @@ export const CreateSessionSchema = z.object({
/**
* Claude model for THIS session only, passed as `claude --model <id>`; nothing is written to
* disk. Wins over the app-wide default model. Same character set as the registry's
* `model-claude` pattern, so a value accepted here is never rejected at launch.
* `model-claude` pattern, so a value accepted here is never rejected at launch. An empty
* string means no per-session model, as it does for `modelOverride`. Claude only: the route
* refuses it for any other CLI.
*/
model: z
.string()
.max(100)
.regex(/^[a-zA-Z0-9._\-[\]]+$/)
.or(z.literal(''))
.optional(),
openCodeConfig: OpenCodeConfigSchema,
codexConfig: CodexConfigSchema,