feat(claude-models): resolve the Claude model list at runtime - #237
Conversation
Claude built its model list twice: the new-session preflight probe adapter and the in-session sessionModelsV1 publisher, which rebuilt it from AGENT_MODEL_CONFIG. Two producers of the same concept can disagree about which models exist and which effort tiers they support. Introduce one owner (backends/claude/models/resolveClaudeModelCatalog): the curated catalog augmented with whatever the Anthropic Models API reports. Both producers read it. Curated entries keep their hand-authored labels and effort defaults, dated snapshot ids collapse onto their static alias, and models from a generation below the curated floor are dropped — the Models API lists everything the account may call, including generations Claude Code can no longer run. Any failure falls back to the curated catalog. Results are cached per resolved account config dir + endpoint + ambient-credential fingerprint, so a session start does not pay a network round trip and a credential swap is not served a previous account's list. Credentials belong to the endpoint they are sent to. The catalog honors ANTHROPIC_BASE_URL, because Happier's built-in Z.AI, DeepSeek, and MiniMax Claude profiles point it at a gateway and pair it with a gateway-issued ANTHROPIC_AUTH_TOKEN; the on-disk Claude Code subscription token is Anthropic-only and is never sent to a third-party gateway. Credential precedence mirrors isolateClaudeRuntimeAuthEnv: for a bound session the ambient auth env keys the spawn would strip are ignored, keeping only ANTHROPIC_API_KEY for the anthropic service. Reading a key the spawn deletes would describe one account for a session that runs as another. The probe adapter is typed as a session controls probe adapter — the shape the caller actually invokes — so it no longer drops connectedServices, and the catalog entry partitions the probe cache by binding. Effort and ultracode require evidence of support rather than trusting an unrecognised model id. reasoningEffort is session-scoped and is not cleared when the model changes, so an unknown id alone is not a reason to forward a carried level. The selected model's reported tiers are resolved once when the mode is built and travel on it as modelEffortLevels, so spawn-time resolution and launch-option hashing see the same value and hashing stays a pure function of the mode. The request is clamped to those tiers; with no tiers nothing is sent. A discovered id that merely contains a curated alias uses its own reported tiers, not the alias table. Curated models keep their static table, so Haiku still never receives --effort or ultracode, and neither does a session with no model selected. Claude stays on dynamicProbe: 'static-only'. Turning the app onto the dynamic model path is a separate, user-visible change and lands on its own.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
WalkthroughClaude now discovers account-specific models from Anthropic, propagates model capabilities through runtime and session flows, supports profile-aware provider probing, and preserves extended-context model identifiers across metadata and UI model options. ChangesClaude dynamic model discovery
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant NewSessionUI
participant ProbeAgentModels
participant ClaudePreflightModelsProbeAdapter
participant ClaudeModelCatalog
participant AnthropicModelsAPI
NewSessionUI->>ProbeAgentModels: request models with profile context
ProbeAgentModels->>ClaudePreflightModelsProbeAdapter: forward credentials and profile
ClaudePreflightModelsProbeAdapter->>ClaudeModelCatalog: resolve account-specific catalog
ClaudeModelCatalog->>AnthropicModelsAPI: fetch model capabilities
AnthropicModelsAPI-->>ClaudeModelCatalog: return discovered models
ClaudeModelCatalog-->>ClaudePreflightModelsProbeAdapter: return merged descriptors
ClaudePreflightModelsProbeAdapter-->>ProbeAgentModels: return probe models
ProbeAgentModels-->>NewSessionUI: return model options and metadata
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryClaude model discovery now resolves the account-specific catalog at runtime and carries discovered model metadata through session startup and the UI.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains in the eligible follow-up scope. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/cli/src/backends/claude/models/fetchAnthropicModels.ts | Adds defensive Anthropic-compatible model fetching with credential-specific headers, timeout handling, redirect rejection, and response parsing. |
| apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts | Centralizes credential-aware model resolution, cache isolation, static fallback, and curated metadata enrichment. |
| apps/cli/src/backends/claude/runClaude.ts | Carries model-scoped effort evidence through both Claude runtime startup paths and awaits bounded resolution before message-mode construction. |
| apps/cli/src/backends/claude/sessionModels/reconcileClaudeSessionModelsState.ts | Reconciles catalog and Agent SDK model publications into one session model state. |
| apps/ui/sources/sync/domains/models/modelOptions.ts | Builds dynamic model rows while preserving discovered model metadata and model-specific options. |
| apps/ui/sources/components/sessions/new/hooks/screenModel/useNewSessionPreflightModelsState.ts | Adds profile-aware model probing, persistence, refresh handling, and stale-result protection. |
| packages/agents/src/models.ts | Extends the shared model descriptor contract with runtime-discovered model metadata. |
Sequence Diagram
sequenceDiagram
participant UI as New-session UI
participant CLI as CLI model probe
participant Catalog as Claude catalog resolver
participant API as Anthropic Models API
participant Session as Claude session
UI->>CLI: Probe models for profile and workspace
CLI->>Catalog: Resolve credential-aware catalog
Catalog->>API: GET /v1/models
alt Successful response
API-->>Catalog: Account model descriptors
Catalog-->>CLI: Dynamic models plus curated metadata
else Missing credential or request failure
Catalog-->>CLI: Curated fallback catalog
end
CLI-->>UI: Model list and per-model options
UI->>Session: Start with selected model and options
Session->>Catalog: Resolve effort tiers
Catalog-->>Session: Model-scoped tier evidence
Reviews (9): Last reviewed commit: "test(claude): type startup mode regressi..." | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/cli/src/backends/claude/runClaude.ts (1)
963-975: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winThe first turn after a model change spawns without reported tiers.
Line 967 sets
currentModel, then startsrefreshCurrentModelEffortLevelswithout awaiting it. Line 851 clearscurrentModelEffortLevelsat the transition. The handler continues synchronously and buildsenhancedModeat Lines 1046-1059 with the now-emptycurrentModelEffortLevels.For a discovered (non-curated) model,
resolveEvidencedClaudeEffortLevelsthen finds no evidence.--effortand ultracode are dropped for that turn, andhashClaudeEnhancedModeForQueuehasheseffort: null. The user-selected effort silently does not apply until a later message. The same sequence exists in the fast-start path at Lines 1894 and 1966.
resolveClaudeModelCatalogcaches results, so awaiting the refresh before buildingenhancedModeis normally cheap. Consider making the user-message handler await the refresh (or resolve tiers at push time) so the selected effort applies on the first turn.#!/bin/bash # Check the catalog cache and timeout semantics before deciding to await the refresh. fd -t f 'resolveClaudeModelCatalog.ts' apps/cli/src | xargs -r rg -n -C6 'cache|timeoutMs|export async function|export function'Also applies to: 1046-1059
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/runClaude.ts` around lines 963 - 975, Ensure the user-message handling path awaits completion of refreshCurrentModelEffortLevels after updating currentModel and before constructing enhancedMode, so the first turn uses the refreshed effort tiers. Apply the same sequencing fix in the fast-start path around its model update and enhancedMode construction, preserving existing model-reset and timestamp behavior.
🧹 Nitpick comments (7)
apps/cli/src/backends/claude/preflight/anthropicModelsFetch.ts (1)
64-78: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueCompute the parsed values once.
readCapabilitiescallsreadEffortTiertwice per tier, and line 106 callsreadCapabilitiestwice for the same entry. The results are pure, so a single call per value is enough and reads more clearly.♻️ Proposed refactor
function readCapabilities(value: unknown): AnthropicModelCapabilities | undefined { const caps = readObject(value); const effort = readObject(caps?.effort); if (!effort) return undefined; + const tiers = { + low: readEffortTier(effort.low), + medium: readEffortTier(effort.medium), + high: readEffortTier(effort.high), + xhigh: readEffortTier(effort.xhigh), + max: readEffortTier(effort.max), + } as const; return { effort: { ...(typeof effort.supported === 'boolean' ? { supported: effort.supported } : {}), - ...(readEffortTier(effort.low) ? { low: readEffortTier(effort.low) } : {}), - ...(readEffortTier(effort.medium) ? { medium: readEffortTier(effort.medium) } : {}), - ...(readEffortTier(effort.high) ? { high: readEffortTier(effort.high) } : {}), - ...(readEffortTier(effort.xhigh) ? { xhigh: readEffortTier(effort.xhigh) } : {}), - ...(readEffortTier(effort.max) ? { max: readEffortTier(effort.max) } : {}), + ...Object.fromEntries(Object.entries(tiers).filter(([, tier]) => tier !== undefined)), }, }; }+ const capabilities = readCapabilities(entry?.capabilities); entries.push({ id, ...(displayName ? { displayName } : {}), ...(maxInputTokens !== undefined ? { maxInputTokens } : {}), - ...(readCapabilities(entry?.capabilities) ? { capabilities: readCapabilities(entry?.capabilities) } : {}), + ...(capabilities ? { capabilities } : {}), });Also applies to: 102-107
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/preflight/anthropicModelsFetch.ts` around lines 64 - 78, Update readCapabilities to call readEffortTier once for each effort tier, store each parsed result, and reuse it when constructing the returned capabilities. In the entry-processing flow around readCapabilities, call readCapabilities once per entry and reuse its result instead of invoking it twice.apps/cli/src/backends/claude/preflight/deriveDiscoveredClaudeModel.ts (1)
8-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winShare the Ultracode copy with the static catalog instead of duplicating it.
The comment states this string mirrors
withClaudeEffortModelOptionsin the agents package. Two copies will drift. Export the description from the canonical Claude provider module inpackages/agentsand import it here.As per coding guidelines: "Reuse or extend canonical implementations instead of adding similar-but-different logic."
#!/bin/bash # Locate the curated Ultracode option copy and check whether it is already exported. rg -nP -C4 'Ultracode|ultracode' packages/agents/src | head -80 rg -nP -C6 'withClaudeEffortModelOptions' packages/agents/src🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/preflight/deriveDiscoveredClaudeModel.ts` around lines 8 - 11, Remove the local ULTRACODE_DESCRIPTION constant and export the canonical Ultracode description from the Claude provider module in packages/agents alongside withClaudeEffortModelOptions. Import and reuse that exported symbol in deriveDiscoveredClaudeModel so discovered and curated models share one source of truth.apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts (1)
272-321: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winConsider de-duplicating concurrent resolutions.
The preflight probe and the
sessionModelsV1publisher can both resolve the catalog at session start. Both miss the cache and both issue a network fetch for the same key. Store the in-flight promise in the map so the second caller awaits the first. Pruning expired entries during that write also keepscatalogCachefrom growing for every rotated credential.♻️ Sketch
-type CatalogCacheEntry = Readonly<{ models: readonly AgentModelDescriptor[]; expiresAtMs: number }>; -const catalogCache = new Map<string, CatalogCacheEntry>(); +type CatalogCacheEntry = Readonly<{ models: readonly AgentModelDescriptor[]; expiresAtMs: number }>; +const catalogCache = new Map<string, CatalogCacheEntry>(); +const inFlightCatalogFetches = new Map<string, Promise<readonly AgentModelDescriptor[]>>();Then wrap the fetch-and-store block in a promise stored under
cacheKey, and delete it in afinally.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts` around lines 272 - 321, Update resolveClaudeModelCatalog and the catalogCache flow to track in-flight resolutions per cacheKey so concurrent callers await one fetch instead of issuing duplicate network requests. Store the fetch-and-cache promise before awaiting it, remove it in finally, and preserve existing success/failure TTL behavior. During writes, prune expired cache entries so rotated credentials do not grow catalogCache indefinitely.apps/ui/sources/sync/domains/models/modelOptions.ts (1)
153-155: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueExtract one reader for
extendedContextModelId. Four sites now repeat the same "string, non-blank, trimmed" normalization. Add a single helper in the models domain (for examplereadExtendedContextModelId(value: unknown): string | undefined) and call it from each site, so the normalization rule has one owner.
apps/ui/sources/sync/domains/models/modelOptions.ts#L153-L155: replace the inline guard ingetModelOptionsForPreflightModelListwith the helper, and export the helper from this module.apps/ui/sources/sync/domains/models/modelOptions.ts#L287-L289: replace the inline guard inresolveModelOptionsForSessionwith the helper.apps/ui/sources/sync/domains/models/parsePreflightModelListFromProbeModelsResult.ts#L18-L20: replace the inline guard with the helper.apps/ui/sources/sync/domains/models/dynamicModelProbeCache.ts#L50-L52: replace the inline guard with the helper.As per coding guidelines: "If similar logic already exists, extend or extract the canonical owner instead of creating a second path."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ui/sources/sync/domains/models/modelOptions.ts` around lines 153 - 155, Extract and export a canonical readExtendedContextModelId helper that returns a trimmed string only for string, non-blank inputs, otherwise undefined. Update getModelOptionsForPreflightModelList and resolveModelOptionsForSession in apps/ui/sources/sync/domains/models/modelOptions.ts (anchor 153-155 and sibling 287-289), plus apps/ui/sources/sync/domains/models/parsePreflightModelListFromProbeModelsResult.ts (18-20) and apps/ui/sources/sync/domains/models/dynamicModelProbeCache.ts (50-52), to use this helper instead of their inline normalization guards.Source: Coding guidelines
apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.test.ts (1)
17-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSpread the original module in the credential-file mock.
This factory replaces the whole module with one export. If any module in the import graph starts to use another export of
claudeCodeCredentialFile, this suite fails for an unrelated reason. TheanthropicModelsFetchmock above already usesimportOriginal. Use the same pattern here.♻️ Proposed change
-vi.mock('`@/backends/claude/connectedServices/nativeAuth/claudeCodeCredentialFile`', () => ({ - readClaudeCodeNativeCredential: readClaudeCodeNativeCredentialMock, -})); +vi.mock('`@/backends/claude/connectedServices/nativeAuth/claudeCodeCredentialFile`', async (importOriginal) => { + const actual = await importOriginal< + typeof import('`@/backends/claude/connectedServices/nativeAuth/claudeCodeCredentialFile`') + >(); + return { ...actual, readClaudeCodeNativeCredential: readClaudeCodeNativeCredentialMock }; +});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.test.ts` around lines 17 - 19, Update the claudeCodeCredentialFile mock factory around readClaudeCodeNativeCredentialMock to import and spread the original module exports, overriding only readClaudeCodeNativeCredential. Preserve all other exports so future imports do not break this test suite.apps/cli/src/capabilities/probes/resolveAgentProbeVariant.test.ts (1)
5-52: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAssert variant stability for an equivalent binding.
The current assertions only prove separation. A variant implementation that generates a new value on every call would pass these tests and disable cache reuse. Resolve the same profile binding twice and assert that both values are equal.
Before retaining this new suite, inventory existing
resolveAgentProbeVariantcoverage and consolidate overlapping cases.As per coding guidelines, “Assert observable behavior and stable contracts” and “Do a test inventory before adding tests.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/capabilities/probes/resolveAgentProbeVariant.test.ts` around lines 5 - 52, Update the resolveAgentProbeVariant test suite to first consolidate overlapping coverage with existing tests, then add an assertion that resolving the identical Claude profile binding twice returns equal variants, preserving cache reuse while retaining distinct variants for different bindings.Source: Coding guidelines
apps/cli/src/backends/claude/runClaude.ts (1)
1513-1542: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueDeclare
resolveClaudeHelpProbeTimeoutMsbefore this closure.Line 1533 reads
resolveClaudeHelpProbeTimeoutMs, but thatconstis declared at Line 1557. The current call sites (Lines 1822, 1894, 2151) all run inside later callbacks, so the binding is initialized by then. A future direct call during startup would throw aReferenceErrorfrom the temporal dead zone.Move the
resolveClaudeHelpProbeTimeoutMsdeclaration aboverefreshCurrentModelEffortLevels. The extraction suggested for Lines 833-868 also removes this ordering hazard.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/runClaude.ts` around lines 1513 - 1542, Move the const declaration for resolveClaudeHelpProbeTimeoutMs above the refreshCurrentModelEffortLevels closure so the closure never references it before initialization. Preserve its existing implementation and behavior while removing the temporal-dead-zone ordering hazard.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts`:
- Around line 102-110: Update isAnthropicFirstPartyBaseUrl to require the parsed
URL protocol to be HTTPS in addition to matching anthropic.com or its
subdomains. Ensure HTTP URLs return false, while preserving the existing
handling for null and invalid URLs.
In `@apps/cli/src/backends/claude/remote/claudeRemoteAgentSdk.ts`:
- Around line 696-710: Ensure model-specific effort tiers are used only for the
model they describe: in
apps/cli/src/backends/claude/remote/claudeRemoteAgentSdk.ts (696-710), pass
supportedLevels only when effortModelId equals mode.model; in
apps/cli/src/backends/claude/cli/terminalOptions.ts (192-196), apply the
equivalent effectiveModel versus normalized mode.model guard; in
apps/cli/src/backends/claude/cli/terminalOptions.ts (230-238), apply the same
guard to resolveClaudeUltracodeForModel; and in
apps/cli/src/backends/claude/claudeRemote.ts (228-232), pass
mode.modelEffortLevels only when argOverrides.model is absent or matches
initial.mode.model.
In `@apps/cli/src/backends/claude/runClaude.ts`:
- Around line 833-868: Extract the duplicated model-effort tracking logic from
the current refresh function and its counterpart near the second path into a
shared createClaudeModelEffortLevelsTracker({ resolveTimeoutMs }) factory
returning refresh and getLevels, then use that tracker in both callers while
preserving normalization, transition clearing, curated-model handling, and
stale-resolution guards. In the catalog lookup catch, add logger.debug with the
model and failure details so lookup failures are visible without changing
fallback behavior.
In
`@apps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.ts`:
- Around line 20-25: Update the session model resolution flow around
resolveClaudeModelCatalog so catalog publication no longer returns early when
--effort is unsupported. Always resolve and publish discovered models, while
suppressing only the effort option when probeHelpText lacks --effort; add a
regression test covering a discovered model under that probe condition.
In `@apps/cli/src/backends/claude/utils/claudeEffort.ts`:
- Around line 49-63: Restrict the static effort-level fallback in
resolveEvidencedClaudeEffortLevels to curated model IDs, so non-curated
discovered IDs with no reported tiers return no levels even when
resolveClaudeEffortLevelsForKnownAliasOrModel matches a substring alias.
Preserve reported-tier precedence and curated-model behavior, verify bare
aliases remain supported as intended, and add coverage for a discovered
substring-matching ID such as claude-opus-5-preview with empty supportedLevels.
---
Outside diff comments:
In `@apps/cli/src/backends/claude/runClaude.ts`:
- Around line 963-975: Ensure the user-message handling path awaits completion
of refreshCurrentModelEffortLevels after updating currentModel and before
constructing enhancedMode, so the first turn uses the refreshed effort tiers.
Apply the same sequencing fix in the fast-start path around its model update and
enhancedMode construction, preserving existing model-reset and timestamp
behavior.
---
Nitpick comments:
In `@apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.test.ts`:
- Around line 17-19: Update the claudeCodeCredentialFile mock factory around
readClaudeCodeNativeCredentialMock to import and spread the original module
exports, overriding only readClaudeCodeNativeCredential. Preserve all other
exports so future imports do not break this test suite.
In `@apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts`:
- Around line 272-321: Update resolveClaudeModelCatalog and the catalogCache
flow to track in-flight resolutions per cacheKey so concurrent callers await one
fetch instead of issuing duplicate network requests. Store the fetch-and-cache
promise before awaiting it, remove it in finally, and preserve existing
success/failure TTL behavior. During writes, prune expired cache entries so
rotated credentials do not grow catalogCache indefinitely.
In `@apps/cli/src/backends/claude/preflight/anthropicModelsFetch.ts`:
- Around line 64-78: Update readCapabilities to call readEffortTier once for
each effort tier, store each parsed result, and reuse it when constructing the
returned capabilities. In the entry-processing flow around readCapabilities,
call readCapabilities once per entry and reuse its result instead of invoking it
twice.
In `@apps/cli/src/backends/claude/preflight/deriveDiscoveredClaudeModel.ts`:
- Around line 8-11: Remove the local ULTRACODE_DESCRIPTION constant and export
the canonical Ultracode description from the Claude provider module in
packages/agents alongside withClaudeEffortModelOptions. Import and reuse that
exported symbol in deriveDiscoveredClaudeModel so discovered and curated models
share one source of truth.
In `@apps/cli/src/backends/claude/runClaude.ts`:
- Around line 1513-1542: Move the const declaration for
resolveClaudeHelpProbeTimeoutMs above the refreshCurrentModelEffortLevels
closure so the closure never references it before initialization. Preserve its
existing implementation and behavior while removing the temporal-dead-zone
ordering hazard.
In `@apps/cli/src/capabilities/probes/resolveAgentProbeVariant.test.ts`:
- Around line 5-52: Update the resolveAgentProbeVariant test suite to first
consolidate overlapping coverage with existing tests, then add an assertion that
resolving the identical Claude profile binding twice returns equal variants,
preserving cache reuse while retaining distinct variants for different bindings.
In `@apps/ui/sources/sync/domains/models/modelOptions.ts`:
- Around line 153-155: Extract and export a canonical readExtendedContextModelId
helper that returns a trimmed string only for string, non-blank inputs,
otherwise undefined. Update getModelOptionsForPreflightModelList and
resolveModelOptionsForSession in
apps/ui/sources/sync/domains/models/modelOptions.ts (anchor 153-155 and sibling
287-289), plus
apps/ui/sources/sync/domains/models/parsePreflightModelListFromProbeModelsResult.ts
(18-20) and apps/ui/sources/sync/domains/models/dynamicModelProbeCache.ts
(50-52), to use this helper instead of their inline normalization guards.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: c85e2571-7b76-4ac6-bd60-cebe1ee7eca8
📒 Files selected for processing (31)
apps/cli/src/backends/claude/claudeRemote.tsapps/cli/src/backends/claude/cli/terminalOptions.tsapps/cli/src/backends/claude/connectedServices/resolveClaudeConnectedServiceStableAuthDir.tsapps/cli/src/backends/claude/index.tsapps/cli/src/backends/claude/loop.tsapps/cli/src/backends/claude/models/resolveClaudeModelCatalog.test.tsapps/cli/src/backends/claude/models/resolveClaudeModelCatalog.tsapps/cli/src/backends/claude/preflight/anthropicModelsFetch.test.tsapps/cli/src/backends/claude/preflight/anthropicModelsFetch.tsapps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.test.tsapps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.tsapps/cli/src/backends/claude/preflight/deriveDiscoveredClaudeModel.test.tsapps/cli/src/backends/claude/preflight/deriveDiscoveredClaudeModel.tsapps/cli/src/backends/claude/remote/claudeRemoteAgentSdk.tsapps/cli/src/backends/claude/remote/modeHash.tsapps/cli/src/backends/claude/runClaude.tsapps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.tsapps/cli/src/backends/claude/unifiedTerminal/runtimeControlIntegration.tsapps/cli/src/backends/claude/utils/claudeEffort.test.tsapps/cli/src/backends/claude/utils/claudeEffort.tsapps/cli/src/capabilities/probes/agentModelsProbe.staticOnly.test.tsapps/cli/src/capabilities/probes/resolveAgentProbeVariant.test.tsapps/ui/sources/components/sessions/new/hooks/screenModel/useNewSessionPreflightModelsState.refresh.test.tsxapps/ui/sources/sync/domains/models/dynamicModelProbeCache.tsapps/ui/sources/sync/domains/models/modelOptions.test.tsapps/ui/sources/sync/domains/models/modelOptions.tsapps/ui/sources/sync/domains/models/parsePreflightModelListFromProbeModelsResult.tsapps/ui/sources/sync/domains/state/storageTypes.tsdocs/agents-catalog.mdpackages/agents/src/index.tspackages/agents/src/models.ts
💤 Files with no reviewable changes (1)
- apps/cli/src/capabilities/probes/agentModelsProbe.staticOnly.test.ts
dc3343a to
fcd3a1c
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/cli/src/backends/claude/utils/claudeEffort.ts (1)
159-166: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse exported arrow functions for the new CLI helpers.
apps/cli/src/backends/claude/utils/claudeEffort.ts#L159-L166: convertresolveModeEffortLevelsForModelto an exportedconstarrow function.apps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.ts#L25-L68: convertcreateClaudeModelEffortLevelsTrackerto an exportedconstarrow function.As per coding guidelines: “Prefer arrow functions over function declarations.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/utils/claudeEffort.ts` around lines 159 - 166, Convert resolveModeEffortLevelsForModel in apps/cli/src/backends/claude/utils/claudeEffort.ts:159-166 to an exported const arrow function, preserving its parameters and behavior. Also convert createClaudeModelEffortLevelsTracker in apps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.ts:25-68 to an exported const arrow function, preserving its existing implementation and API.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.ts`:
- Around line 25-68: The exported createClaudeModelEffortLevelsTracker needs
focused unit coverage. Add tests using the existing Claude model test helpers
for blank-model reset, curated-model lookup bypass, catalog-resolution failure,
and a late catalog result after refresh changes the model; assert that stale or
failed lookups do not publish effort levels for the current model.
---
Nitpick comments:
In `@apps/cli/src/backends/claude/utils/claudeEffort.ts`:
- Around line 159-166: Convert resolveModeEffortLevelsForModel in
apps/cli/src/backends/claude/utils/claudeEffort.ts:159-166 to an exported const
arrow function, preserving its parameters and behavior. Also convert
createClaudeModelEffortLevelsTracker in
apps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.ts:25-68 to
an exported const arrow function, preserving its existing implementation and
API.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 2c3553b1-37dd-47cd-868f-05b76a05dba1
📒 Files selected for processing (13)
apps/cli/src/backends/claude/claudeRemote.tsapps/cli/src/backends/claude/cli/terminalOptions.tsapps/cli/src/backends/claude/loop.tsapps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.tsapps/cli/src/backends/claude/models/resolveClaudeModelCatalog.tsapps/cli/src/backends/claude/remote/claudeRemoteAgentSdk.tsapps/cli/src/backends/claude/remote/modeHash.tsapps/cli/src/backends/claude/runClaude.tsapps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.test.tsapps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.tsapps/cli/src/backends/claude/unifiedTerminal/runtimeControlIntegration.tsapps/cli/src/backends/claude/utils/claudeEffort.test.tsapps/cli/src/backends/claude/utils/claudeEffort.ts
🚧 Files skipped from review as they are similar to previous changes (8)
- apps/cli/src/backends/claude/utils/claudeEffort.test.ts
- apps/cli/src/backends/claude/remote/claudeRemoteAgentSdk.ts
- apps/cli/src/backends/claude/claudeRemote.ts
- apps/cli/src/backends/claude/unifiedTerminal/runtimeControlIntegration.ts
- apps/cli/src/backends/claude/cli/terminalOptions.ts
- apps/cli/src/backends/claude/remote/modeHash.ts
- apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts
- apps/cli/src/backends/claude/runClaude.ts
fcd3a1c to
b5f85d7
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.test.ts`:
- Around line 125-129: Add an explicit assertion that releaseFirst is available
before invoking it in the first lookup setup, and fail with a clear error when
it is null. Keep the subsequent await first only after this validation so the
test does not rely on the timeout.
- Around line 33-44: Update the createTracker helper to explicitly return
ReturnType<typeof createClaudeModelEffortLevelsTracker>, and convert both
effortCapabilities and createTracker to arrow functions while preserving their
behavior. Run the CLI workspace typecheck to verify the changes.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 8d62db3e-3be3-470d-823e-5657f227d5cc
📒 Files selected for processing (1)
apps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.test.ts
b5f85d7 to
2c5ca81
Compare
|
@coderabbitai full review All eight threads from the previous rounds are addressed and answered as of 2c5ca81. The Summary of what changed since that review:
|
|
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.test.ts`:
- Around line 53-56: Update the test suite’s afterEach cleanup to reset the
shared catalogCache after restoring and recreating envScope, ensuring no cached
model catalog remains available to later tests sharing the module context.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 6da88220-e46e-44e5-80d6-8861d2c7470a
📒 Files selected for processing (1)
apps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.test.ts
2c5ca81 to
cbaa550
Compare
cbaa550 to
af97ce0
Compare
|
@coderabbitai on the outside-diff finding at You were right on both counts, including the part I had reasoned my way out of. I had documented this
Both user-message handlers are now One case your report did not cover, now also fixed: a session whose model never changes never hit a Verification: 67 passed across the models, effort, modeHash and startup-ordering lanes; |
|
Tip For best results, initiate chat on the files or code changes.
Thank you for validating the 🐇 ✅ ✏️ Learnings added
If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! You are interacting with an AI system. |
af97ce0 to
5cb244e
Compare
Flip Claude to dynamicProbe: 'auto' so the app runs the preflight models probe and consumes the sessionModelsV1 list the CLI already publishes. The flip switches the app from the static row builder to the dynamic one, which carried less per-model metadata: `extendedContextModelId` was dropped by the persisted session-model schema, the preflight parse, the probe cache, and both dynamic row builders. AgentInput gates the 1M-context toggle on that field, so without this the toggle would disappear for Claude and a session already on claude-sonnet-4-6[1m] would lose its model controls. Carry the field through every hop, and restore it from the catalog in mergeDynamicModelOptionWithCatalog so a curated model arriving through the dynamic path keeps its extended-context variant even when the dynamic source has no reason to know about it. A dynamic source that declares its own variant is honored too. `extendedContextModelId` is the only ModelOption field the dynamic path was missing; the rest (label, description, modelOptions) already flowed or were backfilled from the catalog. Still open, tracked separately and not user-blocking for the list itself: - modelEffortLevels is resolved once against options.modelId, so switching model mid-session keeps the previous model's tiers; - the first turn builds its mode before the catalog resolves, so the first spawn of a discovered-model session carries no tiers.
5cb244e to
ba5645d
Compare
|
@coderabbitai full review |
|
@greptileai review |
✅ Action performedFull review finished. |
|
@coderabbitai review |
|
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
apps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.test.ts (1)
123-130: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd an explicit return type to
runProbe.The other helpers in this file declare return types.
runProbedoes not.♻️ Proposed change
-async function runProbe() { +async function runProbe(): Promise<Array<Record<string, unknown>> | null> { return claudePreflightModelsProbeAdapter.probeModelsRaw?.({ cwd: '/tmp', timeoutMs: 1_500, backendTarget: undefined, accountSettings: null, }) as Promise<Array<Record<string, unknown>> | null>; }As per path instructions: "Always use types for function parameters and return values in TypeScript".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.test.ts` around lines 123 - 130, Update the runProbe helper to declare an explicit Promise return type matching the existing asserted result: an array of records or null. Keep its current probeModelsRaw invocation and behavior unchanged.Source: Path instructions
apps/cli/src/capabilities/probes/agentModelsProbe.ts (1)
464-466: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the guarded cache writes into one helper.
The pattern
if (!usesProviderOwnedCache) { agentModelsProbeCache.setSuccess(...) }is repeated at nine sites. A future branch that writes to the cache can omit the guard and leak a provider-owned result into the shared cache. One helper closes that gap and shortens each branch.♻️ Proposed refactor
+ const cacheSuccess = (value: ProbedAgentModelsResult, ttlMs: number): void => { + if (usesProviderOwnedCache) return; + agentModelsProbeCache.setSuccess(cacheKey, value, { nowMs: nowMs2, ttlMs }); + }; + const cacheError = (ttlMs: number): void => { + if (usesProviderOwnedCache) return; + agentModelsProbeCache.setError(cacheKey, { nowMs: nowMs2, ttlMs }); + };Each site then becomes a single call, for example:
- if (!usesProviderOwnedCache) { - agentModelsProbeCache.setSuccess(cacheKey, fallback, { nowMs: nowMs2, ttlMs: PROBE_MODELS_SUCCESS_TTL_MS }); - } + cacheSuccess(fallback, PROBE_MODELS_SUCCESS_TTL_MS); return fallback;Also applies to: 485-499, 528-538, 554-572, 598-613
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/capabilities/probes/agentModelsProbe.ts` around lines 464 - 466, Extract the repeated usesProviderOwnedCache guard and agentModelsProbeCache.setSuccess call into a helper near the existing probe logic, with parameters for the cache key, value, and timing/options. Replace all nine guarded cache-write sites, including the fallback write in the shown branch, with calls to this helper so every shared-cache success write consistently enforces the provider-owned-cache exclusion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts`:
- Around line 79-92: Update mergeStaticWithDiscovered to track normalized IDs
accepted from entries and filter out subsequent duplicates before
buildDiscoveredClaudeModelDescriptor runs. Retain one canonical discovered entry
when an alias and dated snapshot normalize to the same ID, while preserving
static-model filtering. Add coverage for both entries being returned together
and producing a single discovered row.
In `@apps/cli/src/backends/claude/models/resolveClaudeModelProbeTarget.ts`:
- Around line 77-95: Update normalizeExplicitBaseUrl to reject any explicit URL
whose protocol is not https:, including http:, by returning 'invalid' before
accepting the resolved endpoint. Add a regression test covering an HTTP
ANTHROPIC_BASE_URL and assert the model-discovery resolution returns null.
In `@apps/cli/src/backends/claude/runClaude.fastStart.integration.test.ts`:
- Around line 536-602: Update the test around runClaude to exercise the
fast-start branch by using terminal/local startup settings that make
shouldUseFastStart true, while preserving the deferred catalog readiness
assertions. If retaining the existing remote setup, rename and narrow the test
to explicitly cover only standard-runner readiness, and add a separate
fast-start case with equivalent assertions.
In `@apps/cli/src/backends/claude/runClaude.ts`:
- Around line 2055-2056: Synchronize the fast-start model state in the override
callback that updates options.model by also updating currentModel and
currentModelUpdatedAt. Ensure the initial launch and model-specific effort
resolution use the persisted override rather than stale session state, and add
coverage for a resumed session with a persisted model override.
In
`@apps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.ts`:
- Around line 65-76: Update the supportsEffort logic in
publishClaudeSessionModelsMetadataBestEffort to inspect only the availableModels
entry matching state.currentModelId, derive that model’s supported option IDs,
and remove every effort-dependent override not advertised by the selected model,
including reasoning_effort and ultracode. Preserve the existing metadata
reconciliation flow and add regression coverage for mixed-capability model
selections.
In `@docs/agents-catalog.md`:
- Around line 162-168: The documentation paragraph must accurately describe
Claude model-catalog caching: state that only a warm cache entry lets session
start avoid another network round trip, and revise the cache identity to use the
endpoint, credential kind, and SHA-256 hash of the resolved credential value.
Remove the claim that it includes the resolved account config directory or is
limited to ambient-credential fingerprints.
---
Nitpick comments:
In
`@apps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.test.ts`:
- Around line 123-130: Update the runProbe helper to declare an explicit Promise
return type matching the existing asserted result: an array of records or null.
Keep its current probeModelsRaw invocation and behavior unchanged.
In `@apps/cli/src/capabilities/probes/agentModelsProbe.ts`:
- Around line 464-466: Extract the repeated usesProviderOwnedCache guard and
agentModelsProbeCache.setSuccess call into a helper near the existing probe
logic, with parameters for the cache key, value, and timing/options. Replace all
nine guarded cache-write sites, including the fallback write in the shown
branch, with calls to this helper so every shared-cache success write
consistently enforces the provider-owned-cache exclusion.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: f953d4cc-8c54-4ff3-b174-c36dce649214
📒 Files selected for processing (61)
apps/cli/src/api/types.tsapps/cli/src/backends/catalog.test.tsapps/cli/src/backends/claude/claudeRemote.tsapps/cli/src/backends/claude/cli/terminalOptions.tsapps/cli/src/backends/claude/connectedServices/resolveClaudeConnectedServiceStableAuthDir.tsapps/cli/src/backends/claude/index.tsapps/cli/src/backends/claude/loop.tsapps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.test.tsapps/cli/src/backends/claude/models/claudeModelEffortLevelsTracker.tsapps/cli/src/backends/claude/models/deriveDiscoveredClaudeModel.test.tsapps/cli/src/backends/claude/models/deriveDiscoveredClaudeModel.tsapps/cli/src/backends/claude/models/fetchAnthropicModels.test.tsapps/cli/src/backends/claude/models/fetchAnthropicModels.tsapps/cli/src/backends/claude/models/resolveClaudeModelCatalog.test.tsapps/cli/src/backends/claude/models/resolveClaudeModelCatalog.tsapps/cli/src/backends/claude/models/resolveClaudeModelProbeTarget.test.tsapps/cli/src/backends/claude/models/resolveClaudeModelProbeTarget.tsapps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.test.tsapps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.tsapps/cli/src/backends/claude/remote/buildClaudeSessionModelsMetadataFromSupportedModels.tsapps/cli/src/backends/claude/remote/claudeRemoteAgentSdk.tsapps/cli/src/backends/claude/remote/modeHash.tsapps/cli/src/backends/claude/runClaude.fastStart.integration.test.tsapps/cli/src/backends/claude/runClaude.tsapps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.test.tsapps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.tsapps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.test.tsapps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.tsapps/cli/src/backends/claude/sessionModels/reconcileClaudeSessionModelsState.tsapps/cli/src/backends/claude/unifiedTerminal/dialogChoice/injectionDialogRouting.test.tsapps/cli/src/backends/claude/unifiedTerminal/runtimeControlIntegration.test.tsapps/cli/src/backends/claude/unifiedTerminal/runtimeControlIntegration.tsapps/cli/src/backends/claude/utils/claudeEffort.test.tsapps/cli/src/backends/claude/utils/claudeEffort.tsapps/cli/src/capabilities/probes/agentModelsProbe.cache.test.tsapps/cli/src/capabilities/probes/agentModelsProbe.staticOnly.test.tsapps/cli/src/capabilities/probes/agentModelsProbe.tsapps/cli/src/capabilities/probes/preflightSessionControlsProbeAdapterTypes.tsapps/cli/src/capabilities/probes/resolveAgentProbeVariant.test.tsapps/cli/src/rpc/handlers/capabilities.probeModels.cwd.test.tsapps/cli/src/rpc/handlers/capabilities.tsapps/ui/sources/components/sessions/new/components/NewSessionEngineOptionDetail.tsxapps/ui/sources/components/sessions/new/components/NewSessionFavoriteModelsDetail.tsxapps/ui/sources/components/sessions/new/hooks/screenModel/useNewSessionAgentPickerControls.tsxapps/ui/sources/components/sessions/new/hooks/screenModel/useNewSessionPreflightModelsState.cwd.test.tsxapps/ui/sources/components/sessions/new/hooks/screenModel/useNewSessionPreflightModelsState.persistence.test.tsxapps/ui/sources/components/sessions/new/hooks/screenModel/useNewSessionPreflightModelsState.refresh.test.tsxapps/ui/sources/components/sessions/new/hooks/screenModel/useNewSessionPreflightModelsState.tsapps/ui/sources/components/sessions/new/hooks/useNewSessionScreenModel.tsxapps/ui/sources/sync/domains/models/dynamicModelProbeCache.tsapps/ui/sources/sync/domains/models/modelOptions.test.tsapps/ui/sources/sync/domains/models/modelOptions.tsapps/ui/sources/sync/domains/models/parsePreflightModelListFromProbeModelsResult.tsapps/ui/sources/sync/domains/sessionControl/readSessionControlMetadata.test.tsapps/ui/sources/sync/domains/sessionControl/schema.tsapps/ui/sources/sync/domains/state/storageTypes.tsdocs/agents-catalog.mdpackages/agents/src/index.tspackages/agents/src/models.tspackages/agents/src/sessionControls/metadata.spec.tspackages/agents/src/sessionControls/metadata.ts
|
@coderabbitai review @greptile-apps please review the current head 599812c. |
|
🧠 Learnings used✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cli/src/backends/claude/runClaude.fastStart.integration.test.ts`:
- Line 642: In the test containing getOrCreateSessionSpy.mockImplementation,
save the spy’s existing implementation before overriding it, then restore that
implementation in the existing finally block alongside sessionSyncClientSpy.
Ensure later tests receive their configured session responses.
In
`@apps/cli/src/backends/claude/unifiedTerminal/resumeChoice/claudeUnifiedResumeChoiceStartupResolver.ts`:
- Around line 59-65: Add regression tests in
claudeUnifiedResumeChoiceStartupResolver.test.ts for startupMode.ultracode ===
true, asserting the resolver accepts both the ultracode and xhigh targets. Keep
existing reasoningEffort coverage unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 4c82af40-881c-4a6a-a2ac-90015521f667
📒 Files selected for processing (9)
apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.test.tsapps/cli/src/backends/claude/models/resolveClaudeModelCatalog.tsapps/cli/src/backends/claude/runClaude.fastStart.integration.test.tsapps/cli/src/backends/claude/runClaude.tsapps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.test.tsapps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.tsapps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.tsapps/cli/src/backends/claude/unifiedTerminal/resumeChoice/claudeUnifiedResumeChoiceStartupResolver.tsdocs/agents-catalog.md
🚧 Files skipped from review as they are similar to previous changes (6)
- apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.test.ts
- docs/agents-catalog.md
- apps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.ts
- apps/cli/src/backends/claude/runClaude.ts
- apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts
- apps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.ts
|
@coderabbitai review @greptile-apps please review the current head 2484abc. |
|
🧠 Learnings used✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/cli/src/backends/claude/unifiedTerminal/resumeChoice/claudeUnifiedResumeChoiceStartupResolver.test.ts (1)
415-415: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd explicit TypeScript types.
Declare the
_targetandcaptureparameter types and thePromise<void>return types.As per coding guidelines: “Always use types for function parameters and return values in TypeScript.”
Suggested annotations
- wait: async () => undefined, + wait: async (): Promise<void> => undefined, ... - async (_target, capture) => { + async (_target: 'ultracode' | 'xhigh', capture: string): Promise<void> => {Also applies to: 423-423
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/unifiedTerminal/resumeChoice/claudeUnifiedResumeChoiceStartupResolver.test.ts` at line 415, Update the async callback functions around the affected resolver tests to explicitly type both parameters, _target and capture, and annotate their return type as Promise<void>. Apply the same annotations to the additional callback occurrence noted in the review, using the existing target and capture types from the surrounding test APIs.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@apps/cli/src/backends/claude/unifiedTerminal/resumeChoice/claudeUnifiedResumeChoiceStartupResolver.test.ts`:
- Around line 435-436: Extend the assertions for the relevant resume-choice test
to verify that createFakeControlPort’s sentRaw collection is empty, alongside
the existing sentLiteral and sentKeys checks, ensuring no raw control sequence
bypasses the test.
---
Nitpick comments:
In
`@apps/cli/src/backends/claude/unifiedTerminal/resumeChoice/claudeUnifiedResumeChoiceStartupResolver.test.ts`:
- Line 415: Update the async callback functions around the affected resolver
tests to explicitly type both parameters, _target and capture, and annotate
their return type as Promise<void>. Apply the same annotations to the additional
callback occurrence noted in the review, using the existing target and capture
types from the surrounding test APIs.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: d813c218-261c-4c34-b349-a03379b6cf0b
📒 Files selected for processing (2)
apps/cli/src/backends/claude/runClaude.fastStart.integration.test.tsapps/cli/src/backends/claude/unifiedTerminal/resumeChoice/claudeUnifiedResumeChoiceStartupResolver.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/cli/src/backends/claude/runClaude.fastStart.integration.test.ts
|
@coderabbitai review |
|
@greptileai review |
✅ Action performedReview finished.
|
|
@coderabbitai review @greptileai review the current head c4ef502. |
|
I will apply the existing endpoint-routing guidance for Claude model discovery during this review. 🧠 Learnings used✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cli/src/backends/claude/runClaude.fastStart.integration.test.ts`:
- Around line 640-684: Save the existing implementation of getOrCreateSessionSpy
before replacing it with the fast-start test implementation, then restore that
saved implementation in the finally cleanup block. Keep the existing runtime
capability and module mock cleanup unchanged.
In `@apps/cli/src/backends/claude/runClaude.ts`:
- Around line 1237-1249: Update the standard initial mode construction around
resolveClaudeInstalledRuntimeSessionMode to retain the mode object, then refresh
model effort data in onSessionReady before updating that object’s model and
effort-tier fields, matching the fast-start flow. Ensure supported selected
models receive effort and Ultracode values on the initial standard launch, and
add a regression test covering standard-runner startup.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: be7930be-5f78-4a5c-98dd-e553446a1854
📒 Files selected for processing (20)
apps/cli/src/backends/claude/models/fetchAnthropicModels.test.tsapps/cli/src/backends/claude/models/fetchAnthropicModels.tsapps/cli/src/backends/claude/models/resolveClaudeModelCatalog.test.tsapps/cli/src/backends/claude/models/resolveClaudeModelCatalog.tsapps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.test.tsapps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.tsapps/cli/src/backends/claude/runClaude.fastStart.integration.test.tsapps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.tsapps/cli/src/backends/claude/runClaude.tsapps/cli/src/backends/claude/sessionControls/probeClaudeHelpText.tsapps/cli/src/backends/claude/sessionControls/probeClaudeInstalledRuntimeCapabilities.test.tsapps/cli/src/backends/claude/sessionControls/probeClaudeInstalledRuntimeCapabilities.tsapps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.test.tsapps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.tsapps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.test.tsapps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.tsapps/cli/src/capabilities/probes/agentModelsProbe.staticOnly.test.tsapps/cli/src/capabilities/probes/agentModelsProbe.tsdocs/agents-catalog.mdpackages/agents/src/models.ts
💤 Files with no reviewable changes (1)
- apps/cli/src/backends/claude/sessionControls/probeClaudeHelpText.ts
🚧 Files skipped from review as they are similar to previous changes (11)
- apps/cli/src/backends/claude/models/fetchAnthropicModels.test.ts
- apps/cli/src/backends/claude/sessionControls/resolveClaudeSessionModelsState.test.ts
- docs/agents-catalog.md
- apps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.ts
- apps/cli/src/backends/claude/preflight/claudePreflightModelsProbeAdapter.test.ts
- apps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.ts
- apps/cli/src/backends/claude/models/fetchAnthropicModels.ts
- packages/agents/src/models.ts
- apps/cli/src/backends/claude/sessionControls/publishClaudeSessionModelsMetadataBestEffort.test.ts
- apps/cli/src/backends/claude/models/resolveClaudeModelCatalog.ts
- apps/cli/src/capabilities/probes/agentModelsProbe.ts
|
Both exact-head CodeRabbit findings were reproduced and fixed in commit 139c0ee. The standard and fast paths now share one startup effort-evidence refresh owner, and the leaked test mock is restored. @coderabbitai please review the current exact head 139c0ee. @greptile-apps please review the current exact head 139c0ee, including all changes since your prior review. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
target='139c0eeecd5b668e5e964d75e2c1adeef1c9ab22'
echo '== Checked-out commit =='
git rev-parse HEAD
echo '== Target commit =='
git rev-parse "${target}^{commit}"
echo '== Commit metadata =='
git show --no-ext-diff --format=fuller --no-renames --stat "$target"
echo '== Changed files =='
git diff-tree --no-commit-id --name-status -r "$target"
echo '== Patch =='
git diff --no-ext-diff --no-renames "${target}^" "$target" -- \
apps/cli/src/backends/claude/runClaude.ts \
apps/cli/src/backends/claude/runClaude.fastStart.integration.test.ts \
apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.ts
echo '== Outline: production startup file =='
ast-grep outline apps/cli/src/backends/claude/runClaude.ts --items all --type function --match 'runClaude|refresh|Tracker|fastStart|startup' || true
echo '== Refresh tracker call sites =='
rg -n -C 5 --type ts \
'\b(createClaudeModelEffortLevelsTracker|modelEffortTracker\.(refresh|refreshWithin)|refresh.*[Ee]ffort)' \
apps/cli/src/backends/claude
echo '== Test mock setup and restoration =='
rg -n -C 8 --type ts \
'\b(vi\.(mock|unmock|restoreAllMocks|resetAllMocks|clearAllMocks)|mock.*(restore|reset)|afterEach|beforeEach)\b' \
apps/cli/src/backends/claude/runClaude.fastStart.integration.test.ts \
apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.tsLength of output: 81277 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== runClaude: initial mode construction and standard loop call =='
sed -n '1200,1335p' apps/cli/src/backends/claude/runClaude.ts
echo '== runClaude: fast-start initial mode construction and loop call =='
sed -n '2020,2165p' apps/cli/src/backends/claude/runClaude.ts
echo '== loop outline =='
ast-grep outline apps/cli/src/backends/claude/loop.ts --items all --type function --match 'loop|onSessionReady|initialClaudeUnifiedTerminalMode'
echo '== loop: initial mode and session-ready call sites =='
rg -n -C 12 --type ts \
'\b(initialClaudeUnifiedTerminalMode|onSessionReady)\b' \
apps/cli/src/backends/claude/loop.ts
echo '== mode consumers in Claude backend =='
rg -n -C 5 --type ts \
'\binitialClaudeUnifiedTerminalMode\b' \
apps/cli/src/backends/claude
echo '== Changed standard-path test and test lifecycle =='
sed -n '280,325p' apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.ts
sed -n '635,735p' apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.ts
echo '== Changed fast-start test and surrounding lifecycle =='
sed -n '375,470p' apps/cli/src/backends/claude/runClaude.fastStart.integration.test.ts
sed -n '605,700p' apps/cli/src/backends/claude/runClaude.fastStart.integration.test.tsLength of output: 53852
I found no new issues in the reported fixes.
I did not run tests in the sandbox. ✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.ts (1)
654-693: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy liftUse typed loop parameters and test the real loop path.
This test mocks the first-party
looporchestration helper, so it does not verify thatinitialClaudeUnifiedTerminalModereaches the launcher. Use a real loop with only the process or transport boundary mocked. Replace bothanyannotations withParameters<typeof loop>[0]andEnhancedMode | undefined.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.ts` around lines 654 - 693, Update the startup metadata ordering test to exercise the real Claude loop orchestration, mocking only the process or transport boundary needed to stop execution rather than mocking loop itself. Replace the loop callback parameter’s any type with Parameters<typeof loop>[0], and type initialMode as EnhancedMode | undefined while asserting the mode reaches the launcher.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.ts`:
- Around line 688-690: Replace the broad any annotations in the loop mock setup
with a LoopParams type derived from Parameters<typeof loop>[0]. Use LoopParams
for the mock callback parameter and type initialMode consistently with
params.initialClaudeUnifiedTerminalMode.
---
Nitpick comments:
In `@apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.ts`:
- Around line 654-693: Update the startup metadata ordering test to exercise the
real Claude loop orchestration, mocking only the process or transport boundary
needed to stop execution rather than mocking loop itself. Replace the loop
callback parameter’s any type with Parameters<typeof loop>[0], and type
initialMode as EnhancedMode | undefined while asserting the mode reaches the
launcher.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 817bdfe1-881a-4ab4-8291-3b2c3c7931a1
📒 Files selected for processing (3)
apps/cli/src/backends/claude/runClaude.fastStart.integration.test.tsapps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.tsapps/cli/src/backends/claude/runClaude.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/cli/src/backends/claude/runClaude.fastStart.integration.test.ts
- apps/cli/src/backends/claude/runClaude.ts
|
Addressed the latest exact-head CodeRabbit type-safety finding in fa239ff4d34213a613bdf515dd961195106f742c7. @coderabbitai please review the current exact head fa239ff4d34213a613bdf515dd961195106f742c7. @greptile-apps please review the current exact head fa239ff4d34213a613bdf515dd961195106f742c7. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
target='fa239ff4d34213a613bdf515dd961195106f742c7'
echo '== Checked-out commit =='
git rev-parse HEAD || true
echo '== Target commit =='
git rev-parse "${target}^{commit}" 2>&1 || true
echo '== Commit metadata =='
git show --no-ext-diff --format=fuller --no-renames --stat "$target" 2>&1 | head -100
echo '== Changed files =='
git diff-tree --no-commit-id --name-status -r "$target" 2>&1
echo '== Patch =='
git diff --no-ext-diff --no-renames "${target}^" "$target" 2>&1Length of output: 1427 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== Checked-out commit (actual current head) =='
git rev-parse HEAD
echo '== Commit metadata =='
git show --no-ext-diff --format=fuller --no-renames --stat HEAD | head -100
echo '== Changed files vs parent =='
git diff-tree --no-commit-id --name-status -r HEAD
echo '== Full patch vs parent =='
git diff --no-ext-diff --no-renames HEAD~1 HEADLength of output: 2297 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== Usage of initialMode after this block =='
rg -n -B2 -A15 'let initialMode' apps/cli/src/backends/claude/runClaude.startupMetadataOrdering.test.ts
echo '== loop() signature for initialClaudeUnifiedTerminalMode type =='
ast-grep outline apps/cli/src/backends/claude/loop.ts --items all --type function --match 'loop'
rg -n 'initialClaudeUnifiedTerminalMode' apps/cli/src/backends/claude/loop.ts | head -20Length of output: 1866 The fix is confirmed.
The fix replaces two I did not run tests in the sandbox. 🧠 Learnings used✅ Action performedReview finished.
|
Follow-up implementation and verificationPosted by @happier-bot on behalf of the implementation/review pass. We completed the requested follow-up work on this PR and pushed it to the current head, The main product decision is now represented explicitly: when an authenticated Claude Models API request succeeds, that response owns model membership and API-provided capability/context facts. Happier's curated static catalog enriches matching returned rows with presentation and known local metadata, but it no longer silently adds model IDs that the selected account did not return. A successful empty result remains authoritative empty. Static rows remain the cold fallback when discovery fails, while a bounded same-credential last-good dynamic snapshot protects an already-running daemon from transient failures. The follow-up commits also:
Why this shape: dynamic discovery should answer “what this selected account can use now,” while static knowledge remains valuable for display metadata, known aliases/options, and failure continuity. Treating the static and dynamic lists as an unconditional union would continue exposing unavailable models; deleting the static catalog entirely would make transient API failures unnecessarily disruptive and would discard curated option metadata that the endpoint does not fully describe. We also manually ported the same intent into the evolved Verification
Remaining evidence gapsThe repository-wide PR check set is not globally green: several broad typecheck, package, E2E, Windows installer, and release-contract jobs failed or were cancelled. We are not treating those jobs as feature passes merely because the focused corridor is green. A final composed live OAuth Models API call was also not rerun because no valid live credential was available at closeout, and the Dev focused UI runner stalled and was interrupted. Those are remaining integration/release-validation gaps rather than hidden claims of completion. Full audit and intent-port evidence is recorded in |
|
Very good, thank you very much @danljungstrom ! |
Summary
Claude's model list was pinned to a curated static catalog and built twice — once by the new-session
preflight probe, once by the in-session
sessionModelsV1publisher. This gives it a single ownersourced from the Anthropic Models API, and switches the app onto it.
Why
Reported in Discord: "the models listed for cluade are very old, you have to use custom model"
(https://discord.com/channels/1467127365317558402/1478724067195355240/1535308686354944040). A static
catalog means every Claude release needs a code change plus an app release before users can select
the new model, so this complaint recurs on each launch — and the custom-model field is the workaround
people fall back to.
The CLI already published
sessionModelsV1for Claude sessions, but the app discarded it because thecatalog declared
dynamicProbe: 'static-only'— an active producer with its consumer gated off.Reading order
Two commits, meant to be read in order:
389608360refactor: give the Claude model list a single owner (23 files) — where the listcomes from, credential routing, effort/ultracode semantics, spawn plumbing. No user-visible
change: Claude is still
static-onlyat the end of this commit.af97ce02bfeat!: consume the dynamic Claude model list (11 files) — the flip, plus theper-model metadata the dynamic UI path was dropping.
62% of the diff is tests. New production logic is concentrated in three new files —
resolveClaudeModelCatalog.ts,anthropicModelsFetch.ts,deriveDiscoveredClaudeModel.ts. The twofiles worth the most attention are
apps/cli/src/backends/claude/runClaude.ts(spawn path, twoindependent runtime scopes) and
apps/ui/sources/sync/domains/models/modelOptions.ts(thestatic-vs-dynamic row builders).
How to test
cd apps/ui && yarn typecheck— 0 errors.cd apps/ui && yarn vitest run sources/sync/domains/models sources/components/sessions/pickers sources/components/sessions/new/hooks/screenModel/useNewSessionPreflightModelsState.refresh.test.tsx— 93 passed / 9 files.
cd apps/cli && yarn vitest run src/backends/claude src/capabilities— 16 failed / 308 passed(325 files). All 16 failures are pre-existing on
dev; see Notes.curated list; curated entries keep their labels, effort defaults, and 1M-context toggle. With no
credential or no network, the list falls back to the curated catalog.
Notes
Credential routing. The catalog honors
ANTHROPIC_BASE_URL— the built-in Z.AI, DeepSeek andMiniMax Claude profiles point it at a gateway and pair it with a gateway-issued
ANTHROPIC_AUTH_TOKEN, so a hardcoded Anthropic endpoint would have sent a third-party token toAnthropic. The on-disk Claude Code subscription token is Anthropic-only and never leaves it.
Credential precedence mirrors
isolateClaudeRuntimeAuthEnv: for a bound session the ambient auth envkeys the spawn strips are ignored, keeping only
ANTHROPIC_API_KEYfor theanthropicservice. Thecatalog cache is keyed on resolved config dir + endpoint + a SHA-256 fingerprint of the credential
actually used, so a re-auth cannot inherit another account's list; a credential that cannot be read
bypasses the cache entirely rather than writing a placeholder entry that would evict a valid one.
Effort/ultracode.
reasoningEffortis session-scoped and is not cleared when the model changes,so an unrecognised model id is not evidence a carried level is supported. Tiers are resolved once when
the mode is built and travel on it as
modelEffortLevels, so spawn resolution and launch-optionhashing see the same value and hashing stays a pure function of the mode. Requests clamp to those
tiers; with none, nothing is sent. Curated models keep their static table, so Haiku still never
receives
--effort.Effort applies from the first turn. An earlier revision resolved a model's tiers with a
fire-and-forget refresh while the message handler continued synchronously, so
--effortandultracode were dropped for the first turn after any model change (and for a session whose model
never changed at all). Both user-message handlers now await the tier resolution before building the
mode.
SessionClientalready awaits its user-message callback, andresolveClaudeModelCatalogcaches, so this costs a no-op after the first resolve.
Pre-existing failures on
dev, measured not assumed.yarn workspace @happier-dev/cli typecheckfails on
devitself:That file is byte-identical between this branch and
dev. For tests, I ransrc/backends/claudeandsrc/capabilitieson this branch and again on a detached4b76fc8c6: both produce the same 16failing files,
diffclean. None appear in this diff. That lane is also mildly flaky — three runs onthis branch gave 16, 17, 16 failing files, with the two captured file lists identical, so the stable
set is 16.
AI disclosure
Authored with Claude Code (Opus 5), reviewed by Codex (gpt-5.5) across four rounds and by CodeRabbit and Greptile on this PR. Codex found three
real defects on this branch — ambient credentials preempting a bound account, a stale-tier race across
the spawn path, and cache staleness on credential rotation. CodeRabbit found six more, including the first-turn effort gap above; all are fixed and covered by tests. Checks executed on
af97ce02b, rebased onto4b76fc8c6:cd apps/cli && yarn typecheck— 1 error, pre-existing ondev(above)cd apps/cli && yarn vitest run src/backends/claude src/capabilities— 16 failed / 308 passed, failing set identical todevcd apps/ui && yarn typecheck— 0 errorscd apps/ui && yarn vitest run sources/sync/domains/models sources/components/sessions/pickers sources/components/sessions/new/hooks/screenModel/useNewSessionPreflightModelsState.refresh.test.tsx— 93 passed / 9 filesNot verified: no code on this branch was executed against the live Anthropic Models API, and no session
was spawned end-to-end. The
GET /v1/modelscontract (200 over a subscription OAuth token,capabilities.efforttiers,display_name,max_input_tokens) was confirmed by a manual spike beforethis work; the fetch, merge, credential-routing and spawn paths are covered by unit tests with a mocked
fetch boundary only. The full
apps/uisuite could not be run — it aborts withERR_IPC_CHANNEL_CLOSEDin this environment, including with
--no-file-parallelism; the targeted lanes above cover every UIfile this branch touches. Codex's reviews were static analysis only — its sandbox is read-only and
could not execute tests.
Checklist
dev(notmain)Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Note
Resolve Claude model list at runtime via the Anthropic API instead of static configuration
/v1/modelsAPI viaresolveClaudeModelCatalog, with curated presentation metadata (name, description,extendedContextModelId) overlaid when a model matches a curated entry.probeClaudeInstalledRuntimeCapabilitiesto detect whether the installed Claude CLI supports--effortand ultracode, replacing the previous help-text string probing; model options are filtered per capability at probe time.createClaudeModelEffortLevelsTrackerto resolve and cache supported effort tiers per selected model with concurrency guards and a bounded 400ms wait before building initial launch modes.reconcileClaudeSessionModelsStateto deterministically merge catalog- and Agent SDK-sourced model publications, preserving ordering andcurrentModelIdrules per source.modelProbeCachePolicy: 'provider-owned', bypassing generic cache storage and returningcacheable: false; probe cache keys are partitioned byprofileIdwhen supplied.extendedContextModelIdthrough the full pipeline: API parsing, catalog resolution, preflight probes, session metadata, and UI state.supportedLevels, so existing queued or cached hashes will not match after this change.Macroscope summarized fa239ff.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation