Skip to content

fix(clients): honor project default models in new threads - #6011

Open
anirudhsama wants to merge 6 commits into
pingdotgg:mainfrom
anirudhsama:t3code/investigate-default-model-settings
Open

fix(clients): honor project default models in new threads#6011
anirudhsama wants to merge 6 commits into
pingdotgg:mainfrom
anirudhsama:t3code/investigate-default-model-settings

Conversation

@anirudhsama

@anirudhsama anirudhsama commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Closes #5796

Problem

Projects with a configured default model did not reliably start fresh drafts with it. Web wrote the currently viewed thread or globally sticky model before the project fallback could apply. Mobile retained a project-local override after submission, so it also continued to beat a configured default.

Fix

Both clients now use the same fresh-draft precedence:

  1. Explicit selection in the currently unsent draft
  2. Configured project default
  3. Last manually selected sticky model
  4. Provider default

Web and desktop resolve the target project's configured model before carried/sticky state. Mobile now separates the unsent draft override from an app-wide persisted sticky selection and clears only the draft-local model after successful submission. Dismissing an unsent draft still preserves its explicit choice; switching to another project does not let that choice beat the other project's configured default.

Validation

  • vp lint apps/web/src/hooks/useHandleNewThread.ts
  • vp test run apps/web/src/composerDraftStore.test.ts (76 tests)
  • vp run --filter @t3tools/web typecheck
  • vp test run apps/mobile/src/state/use-composer-drafts.test.ts apps/mobile/src/lib/modelOptions.test.ts apps/mobile/src/features/threads/new-task-project-selection.test.ts (23 tests)
  • vp run --filter @t3tools/mobile typecheck
  • Integrated browser pass: a GPT-5.6-Sol source thread opened a new draft with the target project's Claude Fable 5 default

Built with GPT-5.6-Sol through the Codex harness in T3 Code.


Note

Medium Risk
Touches persisted composer state on both clients (storage v9 migration and mobile draft file semantics); incorrect precedence or migration could change which model users see on new threads, but behavior is heavily tested and scoped to draft seeding—not send/runtime model binding.

Overview
Aligns web and mobile so fresh new-thread / new-task composers resolve models in the same order: unsent draft pick → project default → app-wide sticky → provider default, instead of letting carried or draft-local state beat a configured project model.

Web adds modelSelectionExplicit on composer drafts so only real picker/trait edits block re-seeding; new-thread flow uses resolveNewThreadModelSelectionOverride (project default over carried model, no self-carry). Storage bumps to v9 and strips non-explicit model seeds from empty draft sessions on upgrade; applyStickyState replaces stale seeded models.

Mobile persists a global sticky model alongside drafts, uses resolveNewTaskModelSelection in the new-task flow, updates sticky on manual model changes, and after a successful send clears draft-local model and workspace so the next task re-resolves defaults. Composer draft persistence waits for hydration before writing to avoid clobbering disk.

Reviewed by Cursor Bugbot for commit d7a5d31. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Honor project default models in new threads via explicit selection tracking

  • Introduces a modelSelectionExplicit flag on composer drafts to distinguish user-picked model selections from seeded defaults. Picker writes and trait edits mark the draft explicit; seed writes do not.
  • New-thread model selection now resolves with precedence: explicit draft pick > project default > sticky selection > carried selection > provider default. Project default wins over carried selection when both exist. See useHandleNewThread.ts and modelOptions.ts.
  • Adds app-wide sticky model selection on mobile via stickyComposerModelSelectionAtom and setStickyComposerModelSelection, persisted alongside drafts. User model changes in the new-task flow update the sticky selection.
  • Strips stale seeded model selections from empty drafts during storage migration (bumps COMPOSER_DRAFT_STORAGE_VERSION to 9 on web). Receipt-only drafts and drafts with content or explicit picks are preserved.
  • Clears draft-local model selection when a new-task flow completes so subsequent tasks re-resolve defaults.
  • Risk: composerDraftStore.applyStickyState now replaces non-explicit draft model selections (including options) with sticky state and may clear the draft entirely if sticky is empty and the draft only carried a non-explicit selection. Reviewers should verify applyStickyState and stripLegacyModelSeedsFromEmptyDraftSessions in composerDraftStore.ts against any consumers expecting seeded models to survive.

Macroscope summarized d7a5d31.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9de7e8b9-1856-4286-8468-5d74454bfd45

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 10, 2026
@anirudhsama anirudhsama changed the title fix(web): honor project default models in new threads fix(clients): honor project default models in new threads Aug 10, 2026
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 10, 2026
Comment thread apps/mobile/src/lib/modelOptions.ts
Comment thread apps/mobile/src/state/use-composer-drafts.ts
Comment thread apps/mobile/src/state/use-composer-drafts.ts
@anirudhsama
anirudhsama marked this pull request as ready for review August 10, 2026 16:03
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Comment thread apps/mobile/src/state/use-composer-drafts.ts
@macroscopeapp

macroscopeapp Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR changes model resolution and draft persistence across web and mobile, adding explicit-selection tracking, sticky model storage, storage migration, and new cleanup and hydration behavior. Because these cross-cutting changes affect which models new threads use and how drafts survive reloads, the scope exceeds a straightforward bug fix.

You can add or adjust custom eligibility rules. Learn more.

zucram commented Aug 13, 2026

Copy link
Copy Markdown

I reproduced the desktop/web upgrade edge case that is not covered by this patch yet.

Environment: macOS desktop 0.0.34-nightly.20260813.1082, remote project with a verified explicit custom Claude/Opus default. The composer still showed GPT-5.6-Sol after reload. Persisted client state had an empty draft session with activeProvider: "codex" and a GPT model selection, while both sticky fields were empty.

The useHandleNewThread precedence change here is necessary and fixes newly initialized/reopened drafts, but COMPOSER_DRAFT_STORAGE_VERSION remains 8 and hydration restores the legacy draft-local model. If that draft is already the routed empty draft, the same-draft reuse path leaves it alone, so ChatComposer continues to let the persisted activeProvider beat the project default.

Suggested follow-up in this PR:

  • bump the web composer storage version;
  • during migration, only for keys that are draft sessions, strip modelSelectionByProvider / activeProvider from legacy empty drafts;
  • define empty using all user-content surfaces (prompt, attachments, terminal/element contexts, preview annotations, review comments);
  • preserve server-thread composer state, runtime/interaction mode, and every draft with user content;
  • add a hydration/migration test proving a legacy empty GPT draft falls through to the project's Claude default while a typed draft keeps its explicit selection.

This is the desktop/web equivalent of the stale mobile-draft review finding, and it is observable in a released desktop build—not just a theoretical upgrade case.

Comment thread apps/mobile/src/state/use-composer-drafts.ts Outdated
Comment thread apps/mobile/src/state/use-composer-drafts.ts Outdated
Comment thread apps/web/src/hooks/useHandleNewThread.ts Outdated
Comment thread apps/web/src/hooks/useHandleNewThread.ts
Comment thread apps/mobile/src/state/use-composer-drafts.ts Outdated
@anirudhsama
anirudhsama force-pushed the t3code/investigate-default-model-settings branch from 6d3c1dd to 5500e58 Compare August 22, 2026 13:46
Comment thread apps/web/src/composerDraftStore.ts
Comment thread apps/web/src/composerDraftStore.ts
Comment thread apps/web/src/hooks/useHandleNewThread.ts
@anirudhsama
anirudhsama force-pushed the t3code/investigate-default-model-settings branch from 5500e58 to 946268c Compare August 22, 2026 15:20

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 946268c. Configure here.

Comment thread apps/web/src/hooks/useHandleNewThread.ts
Comment thread apps/web/src/composerDraftStore.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Project default model is ignored for new threads when another model was selected in a different project

3 participants