Fix Claude effort tiers to use CLI catalog ids and bridge alias lookups#313
Conversation
The Claude provider's effort-tier defaults referenced model ids (claude-opus-4-7, claude-sonnet-4.6, claude-haiku-4.5) that the Claude CLI catalog (default/opus/haiku aliases) never advertises, so executor reasoning-effort validation could not resolve supported efforts and the high tier failed with 'Unsupported reasoning effort "xhigh" requested for model "unknown". Supported efforts: unknown'. - Point CLAUDE_DEFAULTS at CLI catalog aliases (haiku/sonnet/opus) and drop the pinned effort for Haiku, which advertises no effort levels - Add findClaudeCatalogModel: exact, provider-default-sentinel, dotted-to-dashed, and family (id/name/description) catalog matching - Map the CLI model description into IModelInfo so 'sonnet' can match the 'default' alias whose description names the family - Resolve provider metadata in chat-base-executor via the matcher for Claude, including provider-default turns with no model id - Advertise conservative supportedReasoningEfforts on the curated Claude fallback model list so offline validation still resolves - Keep unknown tier model ids and stored efforts visible in the admin effort-tier editor instead of rendering blank selects Tests: matcher unit tests, tier default updates, executor regression tests for the alias catalog, legacy dashed ids, provider-default turns, and the actionable unsupported-effort error; admin editor coverage for unknown ids. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…turns An SSE subscriber attaching to a running process triggers store.requestFlush(), which invokes the executor's registered flushConversationTurn. When the turn completed concurrently, the flush's upsertStreamingTurn could land after appendConversationTurn( filterStreaming) had already persisted the final assistant turn — the upsert found no streaming row and re-inserted the buffered content as a permanent duplicate streaming turn. The UI then rendered five timestamped bubbles for a four-turn conversation (flaky e2e queue-conversation-mock.spec.ts 'full conversation' under CI load). - Track turnFinalized per process session; streaming flushes no-op once the turn's final assistant turn is persisted - Serialize streaming flushes and final appends through a per-process turnWriteChain so they cannot interleave on async stores - Route the five filterStreaming append sites (chat, follow-up success/ error, lifecycle-runner success/error) through the new appendFinalConversationTurn helper - Flush still snapshots buffer/timeline synchronously at call time so throttled flushes persist progressively growing content; a flush after session cleanup stays a no-op Tests: base-executor-flush-race.test.ts covers late flush after final append, flush-then-append replacement, concurrent ordering both ways, active-turn flushing, post-cleanup no-op, and multi-turn reset; executor, queue-bridge, SSE-replay suites and the e2e mock spec (3x) pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Added a second commit fixing the Root cause: when an SSE subscriber attaches to a running process, Fix: 🤖 Generated with Claude Code |
What changed
The Claude agent provider's high effort tier failed every chat turn with:
Root cause: the hardcoded Claude effort-tier defaults referenced model ids (
claude-opus-4-7,claude-sonnet-4.6,claude-haiku-4.5) that the Claude CLI catalog never advertises — the CLI's initialize response lists short aliases (default,opus,haiku) with per-modelsupportedEffortLevels. The executor's exact-id metadata lookup therefore never resolved supported efforts, and provider-default sentinel models were stripped toundefinedbefore validation, producing themodel "unknown"variant. The very-low tier also pinnedlowon Haiku, which advertises no effort levels at all.CLAUDE_DEFAULTSat CLI catalog aliases (haiku/sonnet/opus) and drop the pinned effort for HaikufindClaudeCatalogModel(newclaude-model-catalog.tsin coc-agent-sdk): exact, provider-default-sentinel, dotted→dashed, and family (id/name/description) matching, so legacy stored ids keep workingdescriptionintoIModelInfososonnetcan match thedefaultalias whose description names the familychat-base-executorvia the matcher for Claude, including provider-default turns with no model id — an unsupported effort now fails with the actual supported list instead ofunknownsupportedReasoningEffortson the curated Claude fallback model list so validation still resolves when CLI discovery failsNotes for reviewers
control_requestinitialize protocollistModels()uses:default= Sonnet 4.6 (low/medium/high/max),opus= Opus 4.8 (low/medium/high/xhigh/max),haiku= no effort support🤖 Generated with Claude Code