The --thinking description added in #11656 is long enough that at 120
columns commander wraps it, splitting "omitted leaves provider default"
across two lines. The TUI e2e assertion uses a contiguous getByText, so it
failed on the ubuntu-only TUI test leg, blocking the SDK publish gate.
Widen the help terminal to 200 columns so long descriptions render on a
single line.
The Skills note pointed users to "Settings → Features → Enable Skills,"
but that toggle no longer exists — the Features settings section has no
Skills entry and skills are loaded by default. Point users to the actual
Skills menu (scale icon → Skills tab), consistent with the access path
already documented later in the same page.
Fixes#11740
Co-authored-by: Minhkunn <minh.12072k6@gmail.com>
* fix: Filter SAP AI Core models based on mode-availibility
* chore: fix model picker test
* fix: harden SAP AI Core model filtering
* fix: pin SAP Cloud SDK to 4.6.0
* fix(vscode): simplify SAP AI Core model filtering
---------
Co-authored-by: David Knaack <david.knaack@sap.com>
* fix(vscode): make compact button run real SDK compaction
The compact button (and the typed /compact and /smol commands) sent the
literal text "/compact" to the model as a normal chat message. In the SDK
adapter only /workflow and /skill are expanded as runtime commands, so the
model received "/compact" as a prompt and improvised a fake "Conversation
Summary" without actually reducing the context window (CLINE-2503).
Wire the same SDK effect the CLI's /compact (alias /smol) uses:
- sdk-compaction.ts: compactSessionMessages(), the VSCode analog of the CLI's
compactInteractiveMessages -- a manual-mode createContextCompactionPrepareTurn
over the current transcript, force-enabling compaction and forwarding
telemetry/sessionId.
- sdk-compaction-coordinator.ts: reads the active session transcript, runs the
manual compaction, and restarts the session with the compacted messages via
replaceActiveSession (same sequencing as a mode rebuild), preserving the
session id and emitting a CLI-style status line. Guards no-session, mid-turn,
and empty-transcript cases.
- SdkController.compactTask() exposes it; the condense slash handler now calls
it instead of the no-op ask response.
- Webview: the compact-confirm button and typed /compact + /smol (with an active
task) route to the condense RPC instead of sending literal text.
Adds unit tests for the helper, the coordinator, and the webview send routing.
* chore(vscode): drop trailing newline in condense handler (biome)
* test(vscode): cover manual compact flow
* test(vscode): use portable compact matcher
* test(vscode): assert compact calls without vitest matchers
* test(vscode): keep compact assertion type safe
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* fix(onboarding): restore ClinePass models in onboarding
Root cause: the SDK's fetchClineRecommendedModels (@cline/core) silently
dropped the clinePass list. Its ClineRecommendedModelsData type and
normalizeResponse only handled recommended/free, so the recommended-models
endpoint's clinePass entries were stripped before reaching the extension.
Result: the onboarding ClinePass option appeared but the model list was always
empty ('No ClinePass models are available right now'), regardless of the
ext-cline-pass flag. This also affected any SDK consumer (CLI/JetBrains).
Also reverts the pre-login regression from #11798: that PR gated the first
onboarding screen on the extension-side clinePassEnabled flag, which is only
populated after login (featureFlagsService.poll runs on auth), so the ClinePass
option disappeared on the pre-login 'How will you use Cline?' screen.
Changes:
- @cline/core cline-recommended-models: parse/clone clinePass; include it in
the type and offline fallback; treat clinePass-only responses as non-empty.
- OnboardingView: gate the ClinePass option on the webview useHasFeatureFlag
(works pre-login) instead of the extension-side clinePassEnabled.
- Revert the extension-side clinePassEnabled plumbing added in #11798
(FeatureFlagsService.getClinePassEnabled, state payload, ExtensionMessage,
ExtensionStateContext default).
* test: add clinePass to recommended-models SDK mocks
ClineRecommendedModelsData now requires clinePass; update the mocked SDK
results in refreshClineRecommendedModels.test.ts so check-types passes.
* fix(onboarding): only offer ClinePass when models are available
Gate the ClinePass option on isClinePassEnabled AND models.clinePass.length > 0.
Previously, when the flag was on but the recommended-models request fell back
(or returned no clinePass entries), the option still appeared and routed users
into the ClinePass model step's empty state, where signup is disabled -- a dead
end instead of staying on Free/Frontier/BYOK.
* chore: trim ClinePass gate comment to one line
* fix(sdk): batch outdated-read rewrites in MessageBuilder to preserve provider prefix caches
MessageBuilder previously rewrote stale read_files results to
'[outdated - see the latest file content]' eagerly on every re-read.
Each rewrite mutates bytes in the middle of the provider-facing
transcript, invalidating provider prefix caches (DeepSeek/Anthropic/
MiniMax-style) from that message to the end of the conversation. Agents
re-read files constantly (read -> edit -> verify), so long sessions paid
full uncached input price on most requests.
Now pending outdated rewrites accumulate and only commit once the total
reclaimable bytes cross a 64KB threshold, then apply as a single batch
(one cache break amortized over a large context saving). Committed
rewrites are sticky so subsequent requests stay byte-stable.
* fix(sdk): count only reclaimable locator bytes when batching outdated-read rewrites
Addresses review feedback (greptile P1, codex P2): pendingBytes was
incremented with the whole tool-result block size once per outdated
locator, so multi-file read_files results were overcounted (N stale
locators = N x block bytes), crossing the batch threshold far earlier
than intended and partially defeating the cache-stability guarantee.
Now estimateOutdatedReclaimBytes attributes bytes per stale entry in
the parsed read result (falling back to full text size only when the
whole block is outdated, matching replaceOutdatedReadContent), counted
once per block. Adds a multi-locator regression test where a 3-file
read result is invalidated file-by-file and must only commit when the
actual reclaimable bytes cross the threshold.
Real-session replay improved from 12.6% to 19.7% net-token reduction
with the accurate counting (commits defer longer, breaks amortize
better).
* fix(sdk): drop committed outdated rewrites when history is rolled back
Addresses review P1: committedOutdatedRewrites survived checkpoint
restore/clearHistory (the orchestrator reuses one MessageBuilder), so a
read that became the latest again after rollback stayed rewritten to
'[outdated...]' forever, hiding live file content from the provider.
Two guards: re-validate committed locators against the current index at
apply time, and clear the committed set in resetIndexes — that path only
fires on non-append-only history changes, where the provider prefix is
already broken, so stickiness loses nothing.
Adds a rollback regression test (commit rewrite, restore to before the
re-read, assert full content returns).
* test(sdk): trim redundant comments in rollback regression test
* fix(sdk): keep outdated-rewrite batching state across fresh message rebuilds
Addresses review feedback: the runtime provider path rebuilds Message
objects every request (agentMessagesToMessages constructs new literals),
so the identity-based reindex check fails each build and resetIndexes
fires. Clearing committedOutdatedRewrites there (added for the rollback
P1) recounted already-committed bytes as pending on every request — once
the first 64KB committed, every newly-stale small read rewrote
immediately, degenerating to eager behavior in steady state.
committedOutdatedRewrites now survives resetIndexes. Rollback
correctness is preserved without it: the apply-time re-validation is
identity-free, and commitOutdatedRewrites now prunes committed locators
that are no longer outdated in the current index plus entries whose
tool_use_id left the transcript. Both prunes are no-ops in append-only
growth since outdatedness is monotonic.
Adds two regression tests that route messages through the real
agent-message codec round-trip (fresh objects per build, as production):
steady-state deferral of a small newly-stale read after a committed
large one, and rollback restoring full content.
* fix(sdk): batch orphaned read results and count stale image bytes
Addresses robinnewhouse review (two pre-approval follow-ups):
1. Tool-name lookups went through toolNameByIdCache only, so a
tool_result orphaned by compaction/rollback (paired tool_use gone)
was invisible to the batching scan and pruned from committed state —
reverting its rewrite mid-transcript in exactly the history-shrinking
case the batching needs to survive. resolveToolName now falls back to
tool_result.name at all three lookup sites (transform, reindex,
commit scan).
2. estimateOutdatedReclaimBytes attributed only text/file entries, but
replaceOutdatedReadContent also replaces stale image siblings
(flagged by codex too). Image-heavy sessions accrued ~0 pending bytes
and never crossed the threshold. The estimator now counts stale image
payload bytes using the same positional marker counting as the
rewriter (countOutdatedImageEntries).
Both regression tests fail before this change: orphaned result keeps
its committed rewrite through a codec round-trip, and a 4KB stale image
crosses a 2KB threshold that its ~70-byte text marker alone would not.
* perf(sdk): retune outdated-rewrite threshold to 128KB for executor caps
The 64KB default was calibrated before executor-layer output caps landed
(#11480/#11504: read_files/run_commands/search now cap at 48K chars).
With reads bounded at ~48K, 64KB sat awkwardly — one stale read can't
cross it, two overshoot — making it the worst non-extreme threshold in a
post-cap cost sweep.
Re-measured eager vs batched on 48K-capped transcripts (DeepSeek 10x
cache pricing): batching still beats eager 44-61%, confirming the
mechanism remains valuable after the caps (never-rewrite is now +35%
worse in long sessions). 128KB (~2-3 capped reads) is cheapest in both
short and long shapes, ~5-12 points better than the old 64KB.
Bumps LARGE_CONTENT test fixture to ~140KB so single-large-read commit
tests still exceed the raised threshold.
* fix(sdk): batch structured read tool results
* fix(sdk): resolve orphaned tool names for aggregate truncation
* test(sdk): trim redundant message builder cache tests
* style(sdk): trim message builder comments
* test(sdk): allow schedule history test more time on windows
* fix(sdk): preserve infinity outdated rewrite threshold
* perf(sdk): retune outdated rewrite threshold to 64KB
* Revert "test(sdk): allow schedule history test more time on windows"
This reverts commit ac21ef1702.
* test(sdk): fold message builder cache stability coverage
* fix(sdk): address stale read batching review
* fix(onboarding): show ClinePass models reliably + label the group ClinePass
Two issues:
1. Nightly feature-flag race. ClinePass was gated twice by two different flag
clients: the recommended-models endpoint is server-gated by ext-cline-pass
(PostHog-node), while the webview independently re-checked ext-cline-pass via
PostHog-js to decide whether to show the option and keep the models. These
reads race and disagree (mid auth/identify handshake, or when PostHog
remote-config scripts are blocked by the webview CSP), so the ClinePass
option could appear with an empty model list.
Fix: make the server-gated payload the single source of truth. Onboarding
shows the ClinePass option iff the payload contains ClinePass models
(getUserTypeSelections now takes hasClinePassModels), and
getRecommendedModelsData no longer re-filters response.clinePass on the
webview flag. Removes the second racy webview PostHog read entirely.
2. Group label. The ClinePass group rendered as the raw provider id (CLINE-PASS).
Render it with the product's proper casing (ClinePass). Model ids/names are
intentionally left as-is (e.g. cline-pass/minimax-m3), since that's what the
model is called.
* fix(onboarding): gate ClinePass on reliable extension-side flag
The ext-cline-pass flag is rolled out to internal cohorts only (QA/Cline
team/ClinePass Beta), not GA. Onboarding read it via the webview posthog-js
client, which is unreliable during onboarding (CSP blocks PostHog remote
config in Nightly, and it evaluates before auth/identify resolves) -- so
eligible team members saw ClinePass with an empty list / not at all.
Read the flag from the extension-side featureFlagsService instead (the same
server-evaluated source Settings/catalog already use), plumbed into webview
state like worktreesEnabled. Onboarding now shows ClinePass iff the flag is
enabled AND the payload contains ClinePass models, so the option and the
list are always in sync.
- FeatureFlagsService.getClinePassEnabled()
- getStateToPostToWebview: clinePassEnabled
- ExtensionState type + webview default
- OnboardingView gates on state.clinePassEnabled
The remote-server JSON example omitted the `type` field. Because the
config schema's z.union lists the SSE branch before streamableHttp
(intentionally, for backward compat), an untyped remote entry silently
resolves to the deprecated legacy SSE transport — the opposite of the
docs' own "Streamable HTTP (recommended)" guidance.
Add `"type": "streamableHttp"` to the example, rename the heading to
match, and add a sentence explaining that omitting `type` defaults to
legacy SSE.
Fixes#11670
Co-authored-by: Minhkunn <minh.12072k6@gmail.com>
* Generate the model list dynamically
* Do not return known models
* Make both calls in parallel
* Remove modelsDev catch on model generation
* readd error catching
SDK migration: move apps/vscode to bun + Cline SDK
### Description
This is the integration branch that moves the VSCode extension onto the Cline SDK and the bun toolchain. Major facts:
- **`apps/vscode` now runs on the Cline SDK.** The extension consumes `@cline/core`, `@cline/llms`, and `@cline/shared` through an adapter layer in `apps/vscode/src/sdk/` (single codepath — no `CLINE_SDK` flag). The webview still talks gRPC; the adapter translates between the gRPC handlers and SDK calls.
- **`apps/vscode` is folded into the root bun workspace.** Package management and task running move from npm/node to **bun**; the extension links the local `@cline/*` packages via `workspace:*` instead of pinned published versions. **Node remains the runtime** (extension host, standalone `cline-core`, esbuild `platform: node`, prebuild ABI targets).
- **npm lockfiles deleted; root `bun.lock` is authoritative** (`apps/vscode`, `webview-ui`, and `testing-platform` per-package lockfiles removed).
- **CI updated** for the new layout: the `ext-vscode-*` workflows install once at the root with bun and build the SDK before the extension build.
- **VSCode extension version bumped to `4.0.0`.**
### Test Procedure
Validated locally before opening:
- `bun run lint` — clean.
- Typechecks across SDK packages, `@cline/cli`, `@cline/cline-hub`, plus `apps/vscode` extension + webview `tsc` — all clean.
- Extension esbuild bundle and both webviews (`apps/vscode/webview-ui`, `apps/cline-hub`) build.
- Unit suites: `apps/vscode` bun-unit (932 pass), webview-ui vitest (247 pass), and SDK package suites (llms 323, agents 41, shared 202) pass.
Watching CI here for the authoritative cross-platform signal.
### Type of Change
- [x] ✨ New feature (non-breaking change which adds functionality)
- [x] ♻️ Refactor Changes
- [x] 🏃 Workflow Changes
### Pre-flight Checklist
- [ ] Changes are limited to a single feature, bugfix or chore (split larger changes into separate PRs)
- [x] Tests are passing (`bun test`) and code is formatted and linted (`bun run format && bun run lint`)
- [x] I have reviewed contributor guidelines