fix(web): submit thinking level verbatim and drop the hardcoded default - #1673
Conversation
🦋 Changeset detectedLatest commit: 94dd9bf The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7fad48053b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| model: ModelThinkingInfo | undefined, | ||
| level: ThinkingLevel | undefined, | ||
| ): ThinkingLevel { | ||
| return level ?? defaultThinkingLevelFor(model); |
There was a problem hiding this comment.
Use daemon-resolved thinking for unset preference
When level is undefined, this assumes the daemon will use the model default, but the daemon resolver honors [thinking] config first (packages/agent-core-v2/src/app/model/thinking.ts:79-93), so enabled=false or a configured effort can override the model default. In a fresh web client with no persisted thinking, prompts now omit thinking, meaning Composer/mobile /status can display and /thinking can cycle from a level that is not what will actually run; please use the daemon-resolved status/config value for the unset case instead of deriving it solely from the model.
Useful? React with 👍 / 👎.
| if (nextThinking !== prevThinking) { | ||
| rawState.thinking = prevThinking; | ||
| saveThinkingToStorage(prevThinking); | ||
| applyThinkingLevel(prevThinking); |
There was a problem hiding this comment.
Clear persisted thinking when rolling back to unset
When a model switch fails after prevThinking was unset, this rollback calls applyThinkingLevel(undefined), but applyThinkingLevel only writes localStorage for concrete levels; the target model default saved by the optimistic call remains in storage. Reproduces by switching models from a fresh/no-preference state while the profile POST fails: the UI rolls back for this session, but after reload prompts send the stale explicit effort instead of omitting thinking.
Useful? React with 👍 / 👎.
7fad480 to
8fe65ef
Compare
Align kimi-web's thinking-level handling with the TUI: - Submit the stored level as-is on every prompt path (prompt, steer, skill activation, BTW side chat) instead of coercing it onto the target model's declared efforts. - No stored preference (undefined) instead of a hardcoded 'high' default: prompts omit the thinking override and the daemon resolves the config/model default, same as an unset [thinking] in the TUI. - Model switcher pre-selects the target model's own default level when switching models; re-selecting the current model keeps the level. - Display the effective level (stored value, else the model default) in the composer, mobile sheet, and /status panel.
The stub daemon (dev/stub-daemon.mjs) no longer exists, so the dev:stub npm script and its docs references were dead weight.
…ally - With no stored preference, loadModels() pins the active model's catalog default_effort as a concrete in-memory value, so what the UI shows, what prompts submit, and what the session runs always agree. localStorage stays reserved for levels the user picked. - setThinking and model switches now also write the daemon-wide [thinking] config (same mapping as the TUI's thinkingEffortToConfig), so sessions created by other clients inherit the pick.
94dd9bf to
9dec241
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9dec241470
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (rawState.thinking === undefined) { | ||
| const active = modelById(currentModelId()); | ||
| if (active !== undefined) rawState.thinking = defaultThinkingLevelFor(active); |
There was a problem hiding this comment.
Defer default pin until the active session is known
When there is no stored thinking preference, this pins rawState.thinking during loadModels(), but the first-load flow calls modelProvider.loadModels() before sessions are loaded and before a deep-linked or auto-selected session is chosen. In that path currentModelId() only sees the global default model, so opening an existing session whose model differs from the default can store e.g. off and later submitPrompt sends that explicit value instead of letting the daemon resolve the session/model default.
Useful? React with 👍 / 👎.
Related Issue
None — the problem is explained below.
Problem
kimi-web silently rewrote the user's thinking level before it reached the backend, diverging from the CLI (TUI):
support_efforts— e.g. a carried-overmaxwas downgraded to the model's defaulthigh, so what ran did not match what the user picked.high, a frontend invention with no CLI counterpart. The CLI sends no thinking override when[thinking]is unset and lets the daemon resolve the config/model default.What changed
rawState.thinkingverbatim; the coercion helpers (coerceThinkingForModel,coercePromptThinking) are removed.rawState.thinkingisThinkingLevel | undefined. An absent/invalid stored value means "no preference": prompts omit thethinkingfield and the daemon resolves the default (the kap-server prompt route already treatsthinkingas optional). Only concrete levels are persisted to localStorage.thinkingLevelForModelSwitchnow mirrors the TUI picker: switching onto a different model pre-selects that model's default level; re-selecting the current model keeps the level untouched./statusdisplay the effective level via a neweffectiveThinkingLevelhelper (stored value, else the model default), and/thinkingcycles from it.patchchangeset for@moonshot-ai/kimi-code(web is bundled into the CLI artifact).Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update (behavior fix only; no documented behavior changes).