Skip to content

feat(vscode): add soft max-cost nudge - #11832

Merged
johnnyeric merged 8 commits into
mainfrom
johnnyeric/soft-maxcost-nudge
Jul 2, 2026
Merged

feat(vscode): add soft max-cost nudge#11832
johnnyeric merged 8 commits into
mainfrom
johnnyeric/soft-maxcost-nudge

Conversation

@johnnyeric

@johnnyeric johnnyeric commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Context

Adds the VS Code-side soft max-cost nudge on top of the core max-cost state machine. Users can opt in from Auto-Approve settings by setting a whole-dollar Session Cost Alert; the default remains disabled.

Implementation

  • Sends max-cost settings from the extension host to the webview config context.
  • Tracks assistant/session cost updates and posts a warning question once the configured limit is reached.
  • Lets users continue the session at that limit or stop the running session.
  • Adds warning styling, localized settings/copy, message types, tests, and a patch changeset.

Screenshots / Video

cost-alert-extension.mov

How to Test

Manual/local verification

  • Agent: bun run typecheck from packages/kilo-vscode/ passed.
  • Agent: bun test tests/unit/kilo-provider-load-messages.test.ts from packages/kilo-vscode/ passed: 42 pass, 0 fail.
  • Agent/pre-push: bun turbo typecheck passed: 19 successful, 19 total.

Reviewer test steps

  1. Open Auto-Approve settings and set Session Cost Alert to 1.
  2. Run or load a session whose assistant cost exceeds $1.
  3. Confirm the warning question appears with Continue and Stop behavior.
  4. Choose Continue and confirm the same limit does not immediately re-alert for that session.
  5. Start another over-limit run and choose Stop; confirm the running session aborts.

Checklist

  • Issue linked above, or exception explained
  • Tests/verification described
  • Screenshots/video included for visual changes, or marked N/A
  • Changeset considered for user-facing changes
  • I personally reviewed the diff and can explain the changes, including any AI-assisted work.

@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from f79f92e to 13132a9 Compare June 30, 2026 11:26
@johnnyeric
johnnyeric force-pushed the johnnyeric/maxcost-nudge-core branch from 98517b8 to 7195102 Compare June 30, 2026 12:12
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from dee393e to 34f6565 Compare June 30, 2026 12:25
@johnnyeric
johnnyeric force-pushed the johnnyeric/maxcost-nudge-core branch from 7195102 to 68f1feb Compare June 30, 2026 12:34
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from 34f6565 to 057d592 Compare June 30, 2026 12:41
@johnnyeric johnnyeric changed the title [codex] add soft max-cost nudge add soft max-cost nudge Jun 30, 2026
@johnnyeric johnnyeric changed the title add soft max-cost nudge feat(vscode): add soft max-cost nudge Jun 30, 2026
@johnnyeric
johnnyeric marked this pull request as ready for review June 30, 2026 15:45

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 057d592c85

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/kilo-vscode/src/KiloProvider.ts
Comment thread packages/kilo-vscode/src/KiloProvider.ts
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from 057d592 to c6ccf43 Compare June 30, 2026 15:50
Comment thread packages/kilo-vscode/src/KiloProvider.ts
@kilo-code-bot

kilo-code-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed in This Increment (1 file)
  • packages/kilo-vscode/webview-ui/src/context/cost-alert.ts - the only change in this increment adds custom: false to the cost-alert's QuestionInfo. This suppresses the free-text custom-input box in QuestionDock (Show when={question()?.custom !== false}) for the fixed continue/stop cost-alert prompt, which has no legitimate use for a free-form reply. The field is optional boolean on QuestionInfo and this is the correct, type-safe way to opt out of the default custom-input behavior. No logic changes elsewhere in the file. No new issues found.
Unchanged Files (Not Re-Reviewed)
  • packages/kilo-vscode/src/KiloProvider.ts and other PR files were not modified in this increment and were not re-reviewed; existing active inline findings on those files remain outstanding from prior review rounds.
Previous Review Summaries (7 snapshots, latest commit 7d2c92f)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 7d2c92f)

Status: No Issues Found | Recommendation: Merge

Files Reviewed in This Increment (1 file)
  • packages/kilo-vscode/webview-ui/src/context/cost-alert.ts - the only change in this increment adds custom: false to the cost-alert's QuestionInfo. This suppresses the free-text custom-input box in QuestionDock (Show when={question()?.custom !== false}) for the fixed continue/stop cost-alert prompt, which has no legitimate use for a free-form reply. The field is optional boolean on QuestionInfo and this is the correct, type-safe way to opt out of the default custom-input behavior. No logic changes elsewhere in the file. No new issues found.
Unchanged Files (Not Re-Reviewed)
  • packages/kilo-vscode/src/KiloProvider.ts and other PR files were not modified in this increment and were not re-reviewed; existing active inline findings on those files remain outstanding from prior review rounds.

Previous review (commit 292044d)

Status: No Issues Found | Recommendation: Merge

Files Reviewed in This Increment (1 file)
  • packages/kilo-vscode/webview-ui/src/styles/question-dock.css - the only code change in this increment replaces the warning-tone border-color with an inset box-shadow (and drops now-redundant box-sizing/flex-shrink/border declarations) to avoid a layout shift when the warning border toggles on, per commit "fix(vscode): use inset box-shadow for warning tone to avoid layout changes". This is a pure visual/layout fix with no logic change. The accompanying visual-regression PNG baseline updates are CI-generated artifacts and are out of scope per review policy. No new issues found.
Unchanged Files (Not Re-Reviewed)
  • packages/kilo-vscode/src/KiloProvider.ts and other PR files were not modified in this increment and were not re-reviewed; existing active inline findings on those files remain outstanding from prior review rounds.

Previous review (commit 8c23899)

Status: No Issues Found | Recommendation: Merge

Files Reviewed in This Increment (1 file)
  • packages/kilo-vscode/src/KiloProvider.ts - the only change in this increment removes the previously-flagged dead code: the nudgeWaiters map, the resolveCostWaiters method, and its call site in handleCostAlertResponse. Verified no remaining references to nudgeWaiters, resolveCostWaiters, or unused imports remain, and the surrounding cost-alert flow (requestCostAlert, handleCostAlertResponse, resetMessageCosts) is unaffected. This resolves the previous SUGGESTION with no new issues introduced.

Previous review (commit 652f96a)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-vscode/src/KiloProvider.ts 385 nudgeWaiters/resolveCostWaiters are now fully dead code -- nothing ever calls nudgeWaiters.set(...), so the leftover map/method/call site could be removed now that activeAlerts handles the real dismiss-stale-alert logic.
Files Reviewed in This Increment (2 files)
  • packages/kilo-vscode/src/KiloProvider.ts - verified both previously-reported WARNINGs are now genuinely fixed via the new activeAlerts map: lowering the Session Cost Alert threshold now dismisses stale alerts and re-checks all tracked sessions (line 3442 thread), and remote/local session deletion now dismisses any active alert for that session (line 1973 thread) -- both existing "Addressed" replies are confirmed correct. One new SUGGESTION: the old nudgeWaiters/resolveCostWaiters machinery this replaced is now fully unreachable dead code.
  • packages/kilo-vscode/webview-ui/src/context/cost-alert.ts - confirmed the previously-reported ternary-with-comma SUGGESTION at close() is fixed with a plain if/return.

Pre-existing unresolved threads outside this increment's changed lines (e.g. lines 3062/3063 in KiloProvider.ts) were left untouched per incremental scope and are not duplicated here.

Fix these issues in Kilo Cloud

Previous review (commit 320d1bb)

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/src/KiloProvider.ts 3057 handleCostAlertResponse still posts sessionCostAlertResolved unconditionally after await this.handleAbort(sid), even though handleAbort() returns void and silently no-ops when the abort doesn't actually happen. Verified unchanged at current HEAD despite an "Addressed" reply.
packages/kilo-vscode/src/KiloProvider.ts 3450 The cleanup loop in handleUpdateSetting still iterates this.nudgeWaiters, but no code path ever calls nudgeWaiters.set(...), so the map is always empty and the loop never runs. Lowering the threshold while an alert is open still does not dismiss the stale prompt. Verified unchanged at current HEAD despite an "Addressed" reply.

SUGGESTION

File Line Issue
packages/kilo-vscode/src/KiloProvider.ts 3442 The dead-nudgeWaiters cleanup loop's inner for (const key of ...) shadows the outer handleUpdateSetting(key, ...) parameter, making an already-subtle function harder to follow.
packages/kilo-vscode/webview-ui/src/context/cost-alert.ts 55 close() uses a ternary + comma operator purely for side effects instead of a plain if/early-return.

Fix these issues in Kilo Cloud

Files Reviewed (15 files)
  • packages/kilo-vscode/src/KiloProvider.ts - cost-tracking wiring (MaxCostNudge, maxCostSetting/setMaxCost, requestCostAlert, handleCostAlertResponse, rearm-on-status, message-cost updates, session-delete cleanup); the 2 previously reported WARNINGs remain present
  • packages/kilo-vscode/webview-ui/src/context/cost-alert.ts - new createCostAlertHandler; the previously reported same-limit stale-UUID issue is fixed by iterating/deleting all matching entries instead of find()-ing the first
  • packages/kilo-vscode/webview-ui/src/context/session.tsx - dismissQuestion/closeQuestion wiring into cah; Escape-on-cost-alert no longer implicitly acks "continue"
  • packages/kilo-vscode/webview-ui/src/components/chat/QuestionDock.tsx - autoSubmit, tone, rejectLabel, Escape routing to closeQuestion for cost alerts, no issues
  • packages/kilo-vscode/webview-ui/src/components/settings/AutoApproveTab.tsx - new Session Cost Alert field with digit-only validation, no issues
  • packages/kilo-vscode/webview-ui/src/context/config.tsx - forwards settings from configLoaded/configUpdated, no issues
  • packages/kilo-vscode/webview-ui/src/types/messages/*.ts - new message/type additions for cost alerts, no issues
  • packages/kilo-vscode/webview-ui/src/styles/question-dock.css - warning-tone styling, no issues
  • packages/kilo-vscode/webview-ui/src/i18n/*.ts - new translation keys, consistent with usage
  • packages/kilo-vscode/tests/unit/kilo-provider-load-messages.test.ts - new cost-alert coverage exercises real provider internals, no mock-heavy tests
  • packages/kilo-vscode/tests/unit/prompt-send-contract.test.ts - updated for dismissQuestion rename
  • packages/kilo-vscode/package.json - new maxCost setting and @opencode-ai/core dependency
  • .changeset/soft-maxcost-nudge.md - user-facing changeset present and clearly written
  • packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx - closeQuestion: noop stub, matches context signature

Previous review (commit d1f93cd)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/src/KiloProvider.ts 3057 handleCostAlertResponse still posts sessionCostAlertResolved unconditionally after await this.handleAbort(sid), even though handleAbort() returns void and silently no-ops when the abort doesn't actually happen. Verified unchanged at current HEAD.
packages/kilo-vscode/src/KiloProvider.ts 3442-3450 The cleanup loop in handleUpdateSetting still iterates this.nudgeWaiters, but no code path calls nudgeWaiters.set(...) (confirmed via search), so the map is always empty and this loop never runs. Lowering the threshold while an alert is open still does not dismiss the stale prompt. Verified unchanged at current HEAD.

Fix these issues in Kilo Cloud

Files Reviewed (2 files)
  • packages/kilo-vscode/webview-ui/src/stories/StoryProviders.tsx - adds missing closeQuestion: noop to the mock session value; matches the (requestID: string) => void signature in context/session.tsx, no issues
  • packages/kilo-vscode/src/KiloProvider.ts - re-verified against current HEAD; both previously reported WARNINGs remain present in the code despite "Addressed" replies

Previous review (commit fad3d68)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/src/KiloProvider.ts 3057 handleCostAlertResponse now awaits handleAbort(sid) before posting sessionCostAlertResolved, but handleAbort() returns void and silently no-ops when aborts.stop() resolves false. The warning is still dismissed unconditionally even when the abort did not actually happen, so the reordering does not fix the original race.
packages/kilo-vscode/src/KiloProvider.ts 3442-3450 The cleanup loop in handleUpdateSetting iterates this.nudgeWaiters, but nothing in the class ever calls nudgeWaiters.set(...) — it is only ever read and deleted. The map is therefore always empty, so this loop never runs and lowering the threshold while an alert is open still does not dismiss the stale prompt; it stacks a second QuestionDock for the same session.

Fix these issues in Kilo Cloud

Files Reviewed (38 files)
  • .changeset/soft-maxcost-nudge.md
  • bun.lock
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/question-dock-many-options-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/question-dock-multi-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/question-dock-single-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/labs-tool-call-lab/search-previews-chromium-linux.png
  • packages/kilo-vscode/package.json
  • packages/kilo-vscode/src/KiloProvider.ts - 2 issues
  • packages/kilo-vscode/tests/unit/kilo-provider-load-messages.test.ts
  • packages/kilo-vscode/tests/unit/prompt-send-contract.test.ts
  • packages/kilo-vscode/webview-ui/src/components/chat/QuestionDock.tsx
  • packages/kilo-vscode/webview-ui/src/components/settings/AutoApproveTab.tsx
  • packages/kilo-vscode/webview-ui/src/context/config.tsx
  • packages/kilo-vscode/webview-ui/src/context/session.tsx
  • packages/kilo-vscode/webview-ui/src/i18n/ar.ts
  • packages/kilo-vscode/webview-ui/src/i18n/br.ts
  • packages/kilo-vscode/webview-ui/src/i18n/bs.ts
  • packages/kilo-vscode/webview-ui/src/i18n/da.ts
  • packages/kilo-vscode/webview-ui/src/i18n/de.ts
  • packages/kilo-vscode/webview-ui/src/i18n/en.ts
  • packages/kilo-vscode/webview-ui/src/i18n/es.ts
  • packages/kilo-vscode/webview-ui/src/i18n/fr.ts
  • packages/kilo-vscode/webview-ui/src/i18n/it.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ja.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ko.ts
  • packages/kilo-vscode/webview-ui/src/i18n/nl.ts
  • packages/kilo-vscode/webview-ui/src/i18n/no.ts
  • packages/kilo-vscode/webview-ui/src/i18n/pl.ts
  • packages/kilo-vscode/webview-ui/src/i18n/ru.ts
  • packages/kilo-vscode/webview-ui/src/i18n/th.ts
  • packages/kilo-vscode/webview-ui/src/i18n/tr.ts
  • packages/kilo-vscode/webview-ui/src/i18n/uk.ts
  • packages/kilo-vscode/webview-ui/src/i18n/zh.ts
  • packages/kilo-vscode/webview-ui/src/i18n/zht.ts
  • packages/kilo-vscode/webview-ui/src/styles/question-dock.css
  • packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts
  • packages/kilo-vscode/webview-ui/src/types/messages/questions.ts
  • packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts

Reviewed by claude-sonnet-5-20260630 · Input: 110 · Output: 36.4K · Cached: 4.9M

Review guidance: REVIEW.md from base branch main

@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch 4 times, most recently from b1d54d6 to 3d05ce6 Compare June 30, 2026 16:20
Comment thread packages/kilo-vscode/src/KiloProvider.ts Outdated
Comment thread packages/kilo-vscode/src/KiloProvider.ts
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch 2 times, most recently from 63ea443 to 8279f68 Compare June 30, 2026 16:34
Comment thread packages/kilo-vscode/webview-ui/src/context/session.tsx Outdated
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch 2 times, most recently from 046ab99 to 5e8a130 Compare June 30, 2026 17:01
Comment thread packages/kilo-vscode/src/KiloProvider.ts
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from 5e8a130 to ccec849 Compare June 30, 2026 17:10
Comment thread packages/kilo-vscode/webview-ui/src/context/session.tsx Outdated
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from ccec849 to 14f008d Compare June 30, 2026 17:51
Comment thread packages/kilo-vscode/webview-ui/src/components/chat/QuestionDock.tsx Outdated
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from 14f008d to bc117d0 Compare June 30, 2026 18:03
Comment thread packages/kilo-vscode/src/KiloProvider.ts
Comment thread packages/kilo-vscode/src/KiloProvider.ts
Base automatically changed from johnnyeric/maxcost-nudge-core to main July 1, 2026 10:07
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch 3 times, most recently from d1f93cd to 320d1bb Compare July 1, 2026 13:07
Comment thread packages/kilo-vscode/src/KiloProvider.ts Outdated
Comment thread packages/kilo-vscode/webview-ui/src/context/cost-alert.ts Outdated
Comment thread packages/kilo-vscode/src/KiloProvider.ts
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from 292044d to c5a3eed Compare July 1, 2026 15:45
@johnnyeric
johnnyeric force-pushed the johnnyeric/soft-maxcost-nudge branch from 7d2c92f to 0f9719b Compare July 1, 2026 20:46
@johnnyeric
johnnyeric merged commit 3943462 into main Jul 2, 2026
27 checks passed
@johnnyeric
johnnyeric deleted the johnnyeric/soft-maxcost-nudge branch July 2, 2026 10:36
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
* feat(vscode): add soft max-cost nudge

* fix(vscode): add closeQuestion stub to StoryProviders mock

* fix(vscode): extract cost alert handler to stay under session.tsx max-lines

* fix(vscode): track active cost alerts to dismiss stale prompts on setting change

* fix(vscode): use if/return instead of ternary-with-comma in cost alert close

* fix(vscode): remove dead nudgeWaiters and resolveCostWaiters code

* fix(vscode): use inset box-shadow for warning tone to avoid layout changes

* fix(vscode): disable custom answer input on cost alert question
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.

2 participants