Skip to content

fix(web-ui): scope task model picker changes per task#470

Open
oshea-patrick wants to merge 3 commits into
cline:mainfrom
oshea-patrick:fix/task-cline-provider-default-model
Open

fix(web-ui): scope task model picker changes per task#470
oshea-patrick wants to merge 3 commits into
cline:mainfrom
oshea-patrick:fix/task-cline-provider-default-model

Conversation

@oshea-patrick
Copy link
Copy Markdown

@oshea-patrick oshea-patrick commented May 8, 2026

Summary

Closes #469.

When task-level Cline settings partially override the workspace defaults, the task detail model picker can initialize or persist the wrong model. This PR fixes two related bugs:

  1. A task with a provider override but no explicit model could initialize from the global Cline model instead of the overridden provider's default model
  2. Changing the model from an existing task chat/detail panel could write to workspace-global Cline settings instead of materializing a task-specific override

Changes

  • Provider-default model resolution: getInitialTaskModelId now consults the provider catalog to resolve the correct default model when a task overrides providerId but not modelId
  • Task-scoped persistence: The detail-panel model picker now writes task-level overrides even when the task was previously inheriting defaults (onTaskClineSettingsChanged presence is sufficient)
  • Board mutation: applyTaskDetailClineSettingsChange no longer requires pre-existing explicit task settings to materialize a concrete override
  • Dirty-state fix: hasUnsavedChanges now compares effective model selections (resolving blanks to provider defaults) so async catalog loading does not transiently flip the settings UI into an unsaved state

Tests Added

  • Provider-default model resolution when taskClineSettings has providerId but no modelId
  • No transient hasUnsavedChanges flash during async provider catalog loading
  • Task model override materialization for inherited tasks via the chat picker
  • Cross-task provider/model isolation in board state mutations
  • Sequential task start payloads carry their own clineSettings
  • Detail-panel model persistence routes to task callback vs workspace save

Validation

cd web-ui
NODE_OPTIONS=--max-old-space-size=8192 ./node_modules/.bin/vitest run \
  src/state/board-state.test.ts \
  src/hooks/use-task-sessions.test.tsx \
  src/components/detail-panels/cline-agent-chat-panel.model-persistence.test.tsx \
  src/hooks/use-runtime-settings-cline-controller.test.tsx \
  --maxWorkers=1
# 63 tests passed

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 8, 2026

Greptile Summary

This PR fixes two related bugs in the task-level model picker: a task overriding only providerId could initialize from the wrong (global) model, and saving a model change from a detail panel without pre-existing task settings could write to workspace-wide config instead of the task. The fix is well-structured and covered by a thorough test suite (63 tests across 4 files).

  • Provider-default resolution (getInitialTaskModelId): When taskClineSettings has providerId but no modelId, the hook now consults the async provider catalog to derive the correct default, with getComparableModelId used in hasUnsavedChanges to avoid a transient dirty-state flash while the catalog is loading.
  • Task-scoped persistence (shouldPersistTaskClineSettings): The detail-panel model picker now routes to the task callback whenever onTaskClineSettingsChanged is provided — not only when the task already had explicit Cline settings — and applyTaskDetailClineSettingsChange in board state no longer gates on a pre-existing explicit agent setting, so an inherited task can have its first concrete override materialized correctly.

Confidence Score: 5/5

Safe to merge — all changed paths are covered by dedicated tests and the logic correctly scopes model changes to the intended task.

The three changed behaviours (provider-default model resolution, task-scoped persistence routing, and board-state override materialization) each have direct test coverage. The async catalog-loading race that previously caused a transient dirty state is resolved by comparing effective model IDs rather than raw state values, and the test with a deferred catalog promise explicitly verifies no intermediate dirty snapshot occurs. No pre-existing guards are weakened in ways that could affect unrelated code paths.

No files require special attention.

Important Files Changed

Filename Overview
web-ui/src/hooks/use-runtime-settings-cline-controller.ts Adds getInitialTaskModelId, getComparableModelId, and getResetModelId helpers; hasUnsavedChanges now compares effective model IDs to prevent transient dirty-state during async catalog load
web-ui/src/state/board-state.ts applyTaskDetailClineSettingsChange no longer requires pre-existing explicit agent settings and now calls updateTask directly, correctly materializing task overrides for inherited tasks
web-ui/src/components/detail-panels/cline-agent-chat-panel.tsx shouldPersistTaskClineSettings now includes the onTaskClineSettingsChanged !== undefined condition so detail-panel model changes always route to the task callback when one exists
web-ui/src/components/detail-panels/cline-agent-chat-panel.model-persistence.test.tsx New test file covering task-callback routing vs workspace-save fallback for detail-panel model selection
web-ui/src/hooks/use-runtime-settings-cline-controller.test.tsx Adds two tests: provider-default model resolution for task overrides with only providerId, and no transient hasUnsavedChanges flash during deferred catalog load
web-ui/src/hooks/use-task-sessions.test.tsx Adds cross-task provider/model isolation test; refactors mock to be task-specific via mockImplementation
web-ui/src/state/board-state.test.ts Adds tests for inherited-task materialization and cross-task isolation in board state mutations

Reviews (2): Last reviewed commit: "fix(web-ui): keep task model picker chan..." | Re-trigger Greptile

Comment thread web-ui/src/hooks/use-runtime-settings-cline-controller.ts
@oshea-patrick oshea-patrick changed the title fix(web-ui): respect task provider default model fix(web-ui): keep task Cline model selection scoped per task May 8, 2026
@oshea-patrick oshea-patrick changed the title fix(web-ui): keep task Cline model selection scoped per task fix(web-ui): scope task model picker changes per task May 8, 2026
@oshea-patrick oshea-patrick marked this pull request as draft May 8, 2026 13:21
@oshea-patrick oshea-patrick marked this pull request as ready for review May 8, 2026 13:21
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.

bug: task-level Cline model picker can initialize or persist the wrong model

1 participant