Skip to content

fix(ai): pass the sonnet alias to Claude CLI, not claude-sonnet#327

Open
M3NT1 wants to merge 3 commits into
JerryZLiu:mainfrom
M3NT1:fix/claude-cli-model-alias
Open

fix(ai): pass the sonnet alias to Claude CLI, not claude-sonnet#327
M3NT1 wants to merge 3 commits into
JerryZLiu:mainfrom
M3NT1:fix/claude-cli-model-alias

Conversation

@M3NT1

@M3NT1 M3NT1 commented Jul 19, 2026

Copy link
Copy Markdown

Summary

The Claude CLI's --model flag accepts aliases (sonnet, opus, fable) or full names (claude-fable-5), but rejects the bare claude-sonnet with:

There's an issue with the selected model (claude-sonnet). It may not exist or you may not have access to it.

→ exit 1. Every batch since the screenshot-recording pipeline landed failed with this exact error, and the user-visible symptom was that no Claude-sourced cards ever appeared in the timeline.

transcriptionModelConfiguration() and activityCardModelConfiguration() in ClaudeProvider were hard-coding claude-sonnet. This commit replaces both with sonnet so the CLI picks the latest Sonnet release on the user's account.

The follow-up PR (#327) replaces this hard-coded value with the user's choice from a new Settings picker, but this PR is the minimal fix that gets the existing flow working.

Files changed

  • Dayflow/Core/AI/ClaudeProvider+Transcription.swiftclaude-sonnetsonnet
  • Dayflow/Core/AI/ClaudeProvider+ActivityCards.swiftclaude-sonnetsonnet
  • DayflowTests/CodexClaudeProviderTests.swift — updated the two affected assertions

Depends on

Test plan

  • xcodebuild build -configuration Debug — succeeds
  • xcodebuild test -only-testing:DayflowTests — all unit tests pass
  • Manual: run claude -p --model sonnet --output-format json "OK" and confirm exit 0 with modelUsage.claude-sonnet-5 in the response.
  • Manual: in Dayflow, trigger a batch and confirm the llm_calls table now logs model=sonnet with status=success (previously model=claude-sonnet with status=failure).

M3NT1 added 3 commits July 19, 2026 21:51
The toast that warns the user about missing screen-recording access was
gated on 'getSavedPreference() == true || appState.isRecording', but the
recorder forces isRecording off the moment it detects the permission is
missing, and getSavedPreference() is nil for users who have never
explicitly toggled it. Net effect: the notice never surfaced for the
exact case it was meant to alert on, and the user had no UI signal that
recording was broken (the Resume button appeared to do nothing).

Switch the guard to the 'didOnboard' UserDefaults flag so the notice
appears whenever the user has completed onboarding and the permission
is missing. Also re-evaluate the notice on every tab change to .timeline
so a user who lands on the timeline after dismissing elsewhere still
sees it (the session-dismiss flag prevents spam).
Cards in the timeline now carry a small 'Provider · Model' badge so
the user can see at a glance which model produced them. Older cards
saved before this change render without the badge (no placeholder),
because the new fields are optional in the JSON metadata column —
no DB migration required.

Three places show the badge:
- Canvas timeline card (CanvasActivityCard) — a small text line
  below the time range
- Right-side detail card (MainView/ActivityCard) — a chip next to
  the category badge with a sparkles icon
- Review-mode swipe card (TimelineReviewCard) — a chip next to the
  category pill

A new 'TimelineActivity.providerBadge' computed property centralises
the provider-id → human-label mapping (e.g. 'gemini' → 'Gemini',
'chatgpt_claude' → 'Claude' or 'ChatGPT' based on the model name),
and looks up the model alias through ClaudeModel / CodexModel enums
so 'sonnet' displays as 'Claude Sonnet' rather than the raw alias.

Storage: TimelineCard, TimelineCardShell, TimelineActivity, and
the TimelineMetadata JSON envelope gained optional 'providerId' and
'modelId' fields. LLMService stamps these onto every card it writes,
using 'activeContext.id.providerLabel' for the provider and a new
'providerModelId(for:)' helper for the model.
The Claude CLI's --model flag accepts aliases (sonnet, opus, fable)
or full names (claude-fable-5), but rejects the bare 'claude-sonnet'
with 'It may not exist or you may not have access to it' → exit 1.
Every batch since the screenshot-recording pipeline landed failed
with this exact error, and the user-visible symptom was that no
Claude-sourced cards ever appeared in the timeline.

transcriptionModelConfiguration() and activityCardModelConfiguration()
in ClaudeProvider were hard-coding 'claude-sonnet'; this commit
replaces both with 'sonnet' so the CLI picks the latest Sonnet
release on the user's account.

Tests in CodexClaudeProviderTests were updated to assert the
new 'sonnet' default (and the updated Codex GPT 5.6-luna default,
which is handled in a separate commit).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant