* fix(hub): hydrate tool results in session message mapping
Map historical tool call/use and tool result blocks into webview tool events, including same-message results and following user result messages. Add tests to verify hydrated outputs and block ordering so restored sessions render completed tool interactions correctly.
* feedback
* Fix basic compaction first-prompt truncation
Issue: shallow sessions on high-output models such as OpenRouter MiniMax M3 could auto-compact immediately and reduce the initial task prompt to only the leading <user_input> wrapper. Harbor still passed the full task into Cline and session metadata retained it, but the model conversation could receive a truncated first message and respond that the request was empty or cut off.
Root cause: the output-runway target used maxInputTokens - maxTokens for every basic compaction. For MiniMax M3, maxTokens is nearly maxInputTokens, producing a tiny target. Basic compaction then used its last-resort first-user truncation path, and raw messages still contain the user_input envelope, so prefix truncation preserved the wrapper instead of the actionable task.
Fix: only use the output-runway target after the transcript has at least five user-assistant pairs, so early/shallow tasks use the normal trigger-based target. Also prevent first-user truncation unless that first user message alone exceeds the trigger budget, preserving normal first-turn prompts while still allowing genuinely oversized prompts to be reduced. Added regression tests for the MiniMax-style shallow prompt case and the oversized-first-prompt escape hatch.
* Fix compaction budget for huge-output models
Avoid collapsing context-derived input budgets when a model reports an output limit nearly equal to its context window, such as MiniMax M3. In those cases, treating context-output as the input budget causes auto-compaction to trigger on normal-sized prompts.
Only use contextWindow - maxTokens when the derived value remains at least half of the context window. Also simplify long-conversation basic compaction targeting to maxInputTokens * 0.5 instead of applying the default target ratio to maxInputTokens - maxTokens.
Adds regression coverage for MiniMax-style context-only metadata so an 18k-token prompt does not compact against an incorrectly collapsed 12k input budget.
* Guard compaction estimator against cumulative metrics
* Address basic compaction target review comments
#11986 (Forcefully enable ClinePass on the CLI) hardcoded isClinePassEnabled: true in session-runtime.ts, provider-catalog.ts, and main.ts and removed the ext-cline-pass feature-flag check, but left the corresponding tests asserting the old flag-driven / disabled behavior. They fail on main (and every branch that merges it).
- session-runtime.test.ts: expect getLastUsedProviderSettings called with isClinePassEnabled: true.
- provider-catalog.test.ts: drop the obsolete getBooleanFlagEnabled('ext-cline-pass') assertion (source no longer reads the flag) and its now-unused mock; keep the isClinePassEnabled: true expectation.
- main.test.ts: the ClinePass flag is no longer read during startup, so getBooleanFlagEnabled is never called. Re-target the 'seed identity before flags' ordering assertion at refreshCliFeatureFlagsInBackground (which is still invoked after seeding), and wire that mock through featureFlagMocks.
The vscode test (Extension Integration Tests) job is red on main: the updateAutoApprovalSettings suite (added in #11929) is vitest-native but was being collected and run by the Mocha @vscode/test-cli runner, where vitest-only matchers (toHaveBeenCalledWith / toHaveBeenCalledOnce / not.toHaveBeenCalled) are not registered, failing with 'is not a function'.
build-tests.js already excludes bun:test-owned tests from the Node-based out/ tree (single source of truth for the runner split). Extend that same mechanism to also exclude vitest-owned tests (files importing from 'vitest'), so neither bun nor vitest suites are ever compiled into the mocha out/ tree. Verified locally: detection catches the state suite (123 non-mocha test files total) while preserving the existing 60 bun __tests__ exclusions. No coverage lost — these suites run under test:vitest / bun.
* docs: add MiniMax M3, Qwen3.7 Max, Qwen3.7 Plus models to ClinePass page
* more updates
* explicitly direct to personal org
* making the clinepass page more detailed
* updates to cline provider wording
* docs: document ClinePass API usage
* chore: discard McpHub change from PR
* docs: simplify ClinePass model slug table
* updates
* nit
* docs: add MiniMax M3, Qwen3.7 Max, Qwen3.7 Plus models to ClinePass page
* more updates
* explicitly direct to personal org
* making the clinepass page more detailed
* updates to cline provider wording
Align resolved workspace versions in bun.lock with the v0.0.54 package
bumps. bun pm pack substitutes workspace:* deps using the version
recorded in bun.lock, so a stale lock made packed inter-package deps
resolve to 0.0.53, failing check-publish and the node smoke test (which
then pulled the old published @cline/shared from npm).
* Add an intermediate step before going to model selection
* fix type issues
* use allSettled
* fix(cli): serialize ClinePass subscription checks
* fix(cli): handle missing ClinePass plan as unsubscribed
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
PR #11928 added an `instanceof Error` branch to extractErrorMessage to
preserve transport-error wrappers (e.g. "fetch failed: SocketError: ...
(UND_ERR_SOCKET)"), but that branch regressed two cases:
- Generic SDK wrappers like "No output generated. Check the stream for
errors." were prepended to the real cause instead of being dropped.
- Errors carrying structured detail on responseBody/detail/error fields
surfaced the bland top-level .message ("Bad Request") instead of the
detail ("Instructions are required").
The Error branch now drops known generic wrappers in favor of the cause
and extracts structured detail from the error's own fields, while keeping
the transport-wrapper concat behavior #11928 intended.
* Improve compaction token budgeting
Use MessageWithMetadata.metrics input/output token counts when estimating message size for compaction, falling back to the existing chars/3 heuristic only when metrics are unavailable. This makes trigger decisions and post-compaction accounting use provider-reported token usage instead of relying only on serialized character estimates.
When an explicit compaction maxInputTokens budget is configured and the model exposes maxTokens, reserve half of the model output budget before triggering compaction. This gives the next provider request room for completion tokens and reduces edge cases where the local context estimate passes but the provider rejects the prompt as exceeding its limit.
Keep explicit reserveTokens and thresholdRatio overrides intact, and add regression coverage for metric-based token estimation, fallback estimation, and output-token-aware trigger budgeting.
* new target tokens and trigger tokens value
* fixes
* use imports and add unit test
* resolveMaxInputTokens
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
The standalone AgentRuntime({ providerId, modelId }) constructor built the gateway model in resolveRuntimeConfig and returned { ...rest, model } without deriving messageModelInfo. The prebuilt-model path preserves it, and core sessions populate it via buildMessageModelInfo, but standalone SDK callers lost it -- so assistant-message modelInfo and model-tagged telemetry (reasoning tokens, action-follow-through) emitted without provider/model dimensions.
Derive messageModelInfo as { id: modelId, provider: providerId } in that path (family omitted; it is optional and unavailable here). An explicit caller-provided messageModelInfo still wins. Adds provider-form tests covering both the derived and explicit-override cases.
The bun run version catalog regen dropped the xiaomi mimo-v2-omni,
mimo-v2-pro, and mimo-v2-flash models from the live data. mimo-v2-omni
is the xiaomi provider's defaultModelId in builtins.ts, so shipping the
refreshed catalog would point the default at a missing model and broke
the provider-ids test. Revert the catalog to the pre-release state and
ship v0.0.53 as a pure SDK code release; the catalog will refresh in a
later release once upstream data is stable.
* refactor(vscode): use string type for api provider in proto
Replace the ApiProvider proto enum with plain string fields across\nmodels.proto and state.proto, and drop the enum<->string conversion\nmappings in api-configuration-conversion.ts. Updates ApiOptions and\nOpenAICompatible settings components accordingly.
* fix custom provider render
* format
* id
* remove extension providers file
* uses includes
* fix(ci): harden ext-vscode stable release workflow
- Resolve previous tag to the latest vX.Y.Z ancestor instead of the most
recent reachable tag. The nightly workflow now pushes a nightly-main-*
annotated tag on every main commit, so git describe was resolving the
release notes' Full Changelog compare link to a nightly tag rather than
the prior release tag.
- Extract the changelog section by exact version heading (and fail if it
is missing) instead of always taking the first ## [ block, so a stale
top entry can no longer ship as the release notes for a different
version.
- Add a pre-publish Verify Changelog Entry gate so a release cannot be
published unless CHANGELOG.md leads with the version being released.
- Add a Verify Marketplace Tokens gate so a missing VSCE_PAT/OVSX_PAT
fails fast before packaging rather than mid-publish.
- In existing-tag mode, require the tag to point at the tested SHA so the
published artifact always matches what CI verified.
- Add a concurrency group keyed on the tag to prevent duplicate
concurrent publishes of the same release.
* fix(ci): validate stable release metadata before publish
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
The bun migration relocated apps/vscode/webview-ui overrides to the root
package.json, including vite ^7.1.11. As a workspace-wide override this
forced vite 7 onto apps/cline-hub/src/webview, which targets vite 8 and
uses rolldownOptions in its vite.config.ts. That broke `bun run -F
@cline/cli build` (cline-hub build:webview) with TS2769 on rolldownOptions.
Removing the global override lets each workspace resolve its declared
vite: webview-ui stays on vite 7.3.5, cline-hub resolves vite 8.0.16.
Both webviews build and the webview-ui vitest suite (247 tests) passes.
* fix(vscode): keep model metadata out of provider settings
* fix(vscode): prune stale provider model metadata
* docs(vscode): explain provider metadata pruning
Several vitest suites lazily await import() their subject inside the first
test (so vi.mock factories apply first). That import pulls in heavy workspace
packages (@cline/core, @cline/llms, @cline/shared), and on loaded CI runners
the first test in a file intermittently exceeds the 5s default timeout and
fails the nightly (observed in catalog.test.ts, now resolveModelInfo.test.ts).
Set a global 20s testTimeout so import cost attributed to the first test does
not cause flakes.
#11720 (feature flag resolution on startup) added a
controller.invalidateProviderListings() call to AuthService.sendAuthStatusUpdate
but did not update the test's mock controllers, which only stubbed
postStateToWebview. The new call threw on the mocks, so the throw happened
before postStateToWebview ran (failing the 'polls feature flags' test) and
caused subscribeToAuthStatusUpdate to delete the handler in its catch block
(failing the 'removes subscription on cleanup' test). Add the now-required
invalidateProviderListings stub to the mock controllers.
api-configuration-conversion.test.ts is picked up by both the vitest
runner and the mocha-based vscode-test integration runner (.vscode-test.mjs
globs src/shared/**/*.test.js). vitest's jest-compat matcher toMatchObject
does not exist in the mocha runtime, so the test passed under vitest but
threw "toMatchObject is not a function" in the integration suite, failing
the nightly publish. Assert the two provider fields with toBe, which works
under both runners.
The first test in catalog.test.ts paid the cost of dynamically importing
./catalog (which pulls in @cline/core, @cline/llms and @cline/shared)
inside its own 5s test timeout, intermittently failing CI/nightly runs.
Warm the import once in beforeAll so the cost falls outside any per-test
clock.
Restore the webview feature-flag hook needed by the ClinePass onboarding/settings UI, but implement it against the existing posthog singleton instead of posthog-js/react so tests do not pull in a second React copy.
Make ClinePass settings follow the SDK provider-catalog pattern: render the Cline account card, resolve models with useProviderModels("cline-pass"), and persist selections with useProviderConfig/useProviderModelSelection for providerId="cline-pass". Remove the stale origin/main props that tried to drive the SDK-era ClineModelPicker, which is intentionally Cline-provider specific.
ClinePass remains hidden by the ext-cline-pass flag in settings/onboarding, and its model info hides token usage costs because billing is subscription-based.
Resolve type-check and test breakages from rebasing the ClinePass
feature (origin/main) onto the SDK migration branch:
- provider-keys: re-add cline-pass to ProviderKeyMap and
NON_SDK_PROVIDER_DEFAULTS (removed by the 'remove unused code'
commit which predated ClinePass), so getProviderModelIdKey and
getProviderDefaultModelId handle the cline-pass provider.
- provider-id: register 'cline-pass' in KNOWN_API_PROVIDERS so the
Record<ApiProvider, true> constraint is satisfied.
- refreshClineRecommendedModels: add optional 'clinePass' field to
ClineRecommendedModelsData so the RPC handler can map it into the
proto response without a type error.
- refreshClineRecommendedModelsRpc: guard models.clinePass with ?? []
for the same reason.
- handleClinePassProviderSelection: pass undefined (not null) to
accountService.switchAccount to match the SDK signature.
- provider-keys.test: remove a duplicate closing brace left by the
conflict resolution.
- Biome formatting (asNeeded semicolons) applied by check-types.
* fix(vscode): store MCP OAuth in shared settings file like the CLI (ENG-2108)
VSCode stored MCP OAuth tokens in a single mcpOAuthSecrets secrets blob
keyed by sha256(name:url), while the CLI/SDK store per-server oauth state in
cline_mcp_settings.json. The two never interoperated (CLI auth was invisible to
VSCode), and VSCode's read-whole-blob/write-whole-blob through StateManager's
non-refreshing cache meant concurrent windows clobbered each other's tokens.
- Store MCP OAuth state in the shared settings file in @cline/core's format.
- Reads are fresh from disk; writes are scoped read-modify-write of one
server's oauth key via updateMcpServerOAuthState (now atomic temp+rename).
- Replace the vscode:// callback flow with HTTP-based token collection via
authorizeMcpServerOAuth (same local loopback flow the CLI uses).
- Reconnect an unauthenticated server when its tokens appear (e.g. CLI auth).
- One-time migration of legacy mcpOAuthSecrets tokens into the shared file.
- Remove McpOAuthRedirectResolver, mcpOAuthFlow, completeOAuth, and the
mcp-auth URI callback route.
* feat(vscode): add --instances/--random-port to MCP OAuth test server
Lets you start several independent test servers, each on its own OS-assigned
random port, so you can add multiple streamableHttp MCP servers to Cline at
once and exercise concurrent OAuth flows. baseUrl now reflects the actually
bound port so discovery metadata and redirect URIs stay correct under random
ports.
* fix(vscode): stop MCP OAuth handshake writes from livelocking the settings watcher (ENG-2108)
Now that codeVerifier/clientInformation live in the shared settings file, the
MCP SDK's per-connect-attempt saveCodeVerifier() writes were tripping the
settings watcher, which re-entered updateServerConnections -> connectToServer
-> another write, looping forever. It was especially bad with two+
unauthenticated servers, where each server's verifier churn re-triggered the
other (visible as a flickering, ever-changing codeVerifier nonce).
The watcher now compares a connection-relevant fingerprint (full per-server
config minus the oauth block, plus a boolean for whether an access token
exists) and skips writes that only churn OAuth-handshake fields. A token
appearing/disappearing still changes the fingerprint, so CLI/other-window
authorization continues to trigger a reconnect via serverGainedOAuthTokens.
* feat(vscode): print paste-ready MCP settings fragment from OAuth test server
On startup the test server now emits an mcpServers JSON fragment (nested
transport shape, matching cline_mcp_settings.json) alongside the banner, so you
can paste it straight into the settings file instead of hand-writing it. With
--instances the entries get distinct names (oauth-test-1, ...), each carrying
its actual bound port.
* fix(vscode): atomic MCP settings writes + fingerprint gate; drop timer guards (CLINE-2097)
Deleting one MCP server could empty the whole list. Root cause: settings
writes were non-atomic (fs.writeFile), so chokidar (and any other process)
could read a transient empty/torn file mid-write and reconcile to zero servers.
The previous fix only masked this with a per-process isUpdatingClineSettings
boolean cleared on a 300ms timer — it did nothing for the CLI or other windows
and was racy.
Replace both timer guards (isUpdatingClineSettings, isUpdatingFromRemoteConfig)
with two deterministic, process-agnostic mechanisms:
- writeSettingsFile(): atomic temp-file + rename for every settings write, so
any reader always sees a complete file. Holds for any number of concurrent
writers (CLI, multiple windows, SDK OAuth handshake).
- content fingerprint: the watcher reconciles only when the connection-relevant
view changed. writeSettingsFile pre-seeds the fingerprint so our own write is
a no-op, while a genuine change from any other process is still processed.
Because reconcile is idempotent and reads are never torn, a missed
suppression is at worst a redundant reconnect, never data loss.
All RPC writers (toggle disabled, autoApprove x2, timeout, add, delete) and the
remote-config sync now go through writeSettingsFile. Removes all setTimeout(.,
300) flag juggling.
* feat(vscode): add a non-guessable 'frozzle' tool to the MCP OAuth test server
The MCP OAuth test server now serves tools/list + tools/call exposing a
'frozzle' tool whose output cannot be derived without calling it (reverse the
string and swap each letter's case, wrapped in guillemets). This gives an eval
a reliable end-to-end signal that the OAuth-authenticated MCP round-trip really
happened: a correct 'frozzle <text>' answer can't be hallucinated. The
transform is easy to verify at a glance and invertible. Adds frozzle.test.ts.
* fix(sdk): drop lingering OAuth callback sockets on close so deny->approve re-auth works (ENG-2108)
The local OAuth callback server's close() called Server.close(), which only
stops accepting new connections and lets existing keep-alive sockets linger.
The browser / global-fetch connection pool keeps such a socket to the fixed
callback port (1456) alive. So after the user denied an MCP OAuth request and
retried, the retry's approve callback could be delivered over the pooled socket
to the FIRST (already-settled) server. That server's settle() was a no-op, so
waitForCallback() never resolved, finishAuth()/token exchange never ran, and no
token was saved — the server stayed unauthenticated (the deny->approve repro).
Call server.closeAllConnections() in close() so no pooled socket outlives the
server. Adds a regression test driving a keep-alive agent across close().
* fix(vscode): actually reconnect MCP server when toggled back on (ENG-2108)
toggleServerDisabledRPC only flipped the in-memory disabled flag and set status
to 'connecting', but never rebuilt the connection. A disabled server's
connection has no live transport/client, so re-enabling left it stuck on the
yellow 'connecting' indicator forever and never re-advertised its tools to the
agent.
Tear down and rebuild the connection through deleteConnection + connectToServer
(which opens a real transport when enabled, or a disconnected stub when
disabled), then notifyWebviewOfServerChanges so the SDK session's tool list is
refreshed. OAuth state is preserved (deleteConnection doesn't clear it). Adds
McpHub.toggleServerDisabledRPC.test.ts.
* fix(vscode): reload MCP tools silently without chat spam (ENG-2108)
Restarting the SDK session to pick up MCP tool changes appended visible chat
messages ('MCP tools changed - reloading...' and 'MCP tools reloaded
successfully...') plus a completion_result banner. Toggling several servers
piled up many of these. Tool reloading should be transparent.
Emit only the session status transitions (running -> idle) via
emitSessionEvents([], ...) instead of appendAndEmit, so no chat messages or
completion banner are shown. Genuine reload failures still surface an error
message. Updates sdk-mcp-coordinator.test.ts accordingly.
* docs(mcp): clean up comments to describe current behavior
Revise comments across the MCP OAuth and settings code to document the code as
it stands, dropping references to prior implementations, task IDs, and
before/after narration. Also reflow the auth-server regression test to the
repository's formatter. No behavior change.
* fix(vscode): atomic fallback write in remote MCP sync; document sync OAuth I/O
Make the no-McpHub branch of syncRemoteMcpServersToSettings write via an
atomic temp-file + rename so a concurrent reader never observes a torn or
empty settings file, matching every other settings write.
Document why the OAuth state read-modify-write in McpOAuthManager is
synchronous: it serializes this process's shared-file updates without a
Promise queue, which we prefer over async I/O for reliability of the
cross-process settings file.
* fix(mcp): serialize settings read-modify-writes
* docs(vscode): clarify MCP settings create race
* fix(vscode): create MCP settings atomically
* fix(cli): keep clearing missing MCP OAuth state a no-op
* fix(vscode): avoid yielding while holding MCP settings lock (#11596)
* fix(mcp): async lock acquisition for VSCode MCP settings/OAuth writes
Add updateMcpSettingsFile/updateMcpServerOAuthStateAsync to @cline/core that
yield the event loop while acquiring the cross-process settings lock instead of
blocking it with Atomics.wait. The critical section stays synchronous and the
mutator stays pure, so the lock is never held across an await and serialization
is preserved without an in-process queue.
Route the VSCode extension host's OAuth state writes (McpOAuthManager) through
the async variant so a connection-time OAuth callback can no longer freeze the
extension host event loop or deadlock against an in-flight updateMcpSettingsFile
whose lock-releasing continuation needs the loop.
Unify the sync and async acquisition paths on a shared reentrancy guard
(activeLocks) so a nested settings update on the same file fails fast instead of
self-deadlocking.
Tests: contended async serialization asserting zero Atomics.wait calls, async
stale-lock reclaim, reentrancy fail-fast, and uncontended run+release.
* fix(mcp): bootstrap missing settings file inside the lock; tidy docs
Creating the MCP settings file now happens in one place: the locked
read-modify-write helpers. A missing file reads as an empty settings object, so
the first write to a fresh path (e.g. a fresh-install `cline mcp add`) creates
it inside the lock instead of throwing ENOENT. The SDK (updateMcpSettingsFile /
updateMcpSettingsFileSync) and the VSCode lock helper share this contract, so
callers no longer need to pre-create the file. Add regression tests for the
SDK, the CLI wizard addServer(), and the VSCode helper on a missing path.
Also flag the synchronous SDK entry points (updateMcpSettingsFileSync,
updateMcpServerOAuthState) as preferring their async siblings, with a TODO to
delete them once all callers migrate, and tighten the lock-helper doc comments
to describe current behavior.
* fix(vscode): finish npm->bun migration in dev tooling, tasks, and docs
The npm->bun migration (#11632) updated package scripts, .vscodeignore and .vscode-test.mjs but left a trail of npm/npx/node invocations in editor configs, dev scripts, and docs. Following the breadcrumbs from 'npm run protos':
- .vscode/launch.json: standalone-core debug uses 'bun <file>.ts' (was npx tsx); Open Storybook uses 'bun run' (was npm run).
- .vscode/tasks.json: all task commands use 'bun run' (was npm run).
- scripts/run-extension-host.sh and .claude/hooks/claude-code-for-web-setup.sh: 'bun run' (was npm run).
- debug-harness/server.ts: shebang 'bun'; build steps use 'bun run protos', 'bun esbuild.mjs', 'bunx vite build' (were npm/node/npx).
- dev script shebangs (test-hostbridge-server, test-standalone-core-api-server, testing-platform-orchestrator, interactive-playwright): '#!/usr/bin/env bun' (was npx tsx).
- WebviewProvider HMR hint, e2e README, copilot-instructions, PR template, mcp-oauth-test-server docs, generate-state-proto message, tsconfig.test comment, state-keys test comment: bun.
Left untouched (correct per .clinerules/bun-and-node): Node-runtime invocations (node build.mjs), prebuild-install --target=<node>, vsce, 'npm install -g cline' (user CLI install), and App.stories.tsx mock chat fixtures.
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Co-authored-by: Cline Agent <cline-agent@users.noreply.github.com>
* chore(vscode): migrate package management & build from npm/node to bun
Fold apps/vscode (+ webview-ui, testing-platform) into the root bun
workspace so the extension consumes the local @cline/* SDK packages via
workspace symlinks instead of pinned published versions, eliminating the
SDK vendoring cycle. Node remains the runtime (extension host, standalone
cline-core, esbuild platform:node, prebuild-install ABI target).
- root: drop "!apps/vscode", add nested members, relocate overrides to
root, add trustedDependencies [better-sqlite3, grpc-tools]
- apps/vscode: @cline/* -> workspace:*, scripts -> bun/bunx,
npm-run-all -> bun --parallel, drop cross-env; keep esbuild + vite;
declare previously-hoisted phantom deps (nice-grpc-common, playwright)
- package-standalone.mjs: npm install -> bun install (isolated dist dir)
- CI: setup-bun + single root bun install --frozen-lockfile, build:sdk
before extension build, better-sqlite3 binary + zero-test guards;
publish workflows intentionally keep setup-node for vsce/ovsx
- docs/comments: curated pass (keep-list vs rewrite-list), add
apps/vscode/docs/bun-migration-notes.md guard doc
- delete npm lockfiles (root bun.lock authoritative)
Deferred to follow-up PRs: test-runner migration to bun test (Phase 4)
and devDep cleanup (Phase 6).
* test(vscode): add bun test foundation for the vitest-native unit suites
Phase 4a of the test-runner migration. Adds a bun test runner that
reaches full parity (582 pass / 0 fail / 50 files) with the existing
vitest SDK-adapter + model-catalog suite, without touching the
@vscode/test-cli integration tests or the webview vitest suite.
- bunfig.toml: [test] preload
- src/test/bun-test-preload.ts: mock.module() shadows `vscode` and
`@cline/core` with their unit-test stubs (bun's onResolve plugin hook
does not intercept host/symlinked specifiers); seeds real @cline/core
export names as undefined to satisfy bun's strict ESM named-import
linking; full vitest->bun:test shim (vi.fn/mocked/spyOn, describe/it/
expect/before*/after*)
- scripts/run-bun-tests.ts: mirrors vitest.config.ts include[] exactly and
runs with --parallel for per-file mock isolation (bun test's single-process
default lets mock.module clobber across files)
- test:bun script
* test(vscode): migrate node-side unit suite from mocha to bun test
Phase 4b of the test-runner migration. The standalone mocha unit runner
(.mocharc spec: __tests__/* + test/services/**) was already broken under
bun (mocha was a phantom dependency — only @types/mocha/ts-node were
declared, npm hoisted mocha transitively). Migrate it to `bun test`.
- codemod 77 files: import { ... } from "mocha" -> "bun:test", renaming
before->beforeAll / after->afterAll at imports and call-sites; chai,
should and sinon kept as libraries (they work under bun test)
- convert sinon.stub() on ESM namespace exports to mock.module()/spyOn
(bun loads real ESM: "ES Modules cannot be stubbed")
- scripts/run-bun-unit-tests.ts: runs the .mocharc spec set with one
isolated `bun test` process per file (Bun.spawn + concurrency pool),
restoring vitest-forks module-registry isolation (bun's single-process
default lets mock.module leak across files)
- scripts/codemod-mocha-{to-bun,this}.ts: one-shot migration tooling
- test:unit now runs the bun unit runner; CI calls bun + a non-zero
pass-count guard instead of `bunx nyc ... mocha`
- tsconfig: add root node_modules/@types to typeRoots so `bun:test`
types resolve under tsc; cast loose os.userInfo mocks in shell.test
Result: unit suite 58 files / 880 pass / 0 fail; vitest set still
582/0. @vscode/test-cli integration tests and webview vitest unchanged.
* chore(vscode): remove dead mocha-runner deps and artifacts
Phase 6 cleanup after the bun test migration. The standalone mocha unit
runner is gone (replaced by scripts/run-bun-unit-tests.ts), so its
config and now-unused devDependencies are removed.
- remove dead files: .mocharc.json, tsconfig.unit-test.json,
src/test/requires.ts, .nycrc.unit.json
- remove unused devDeps: @types/mocha, @types/proxyquire, ts-node,
tsconfig-paths, cross-env, npm-run-all, nyc, proxyquire, husky
(root owns the husky hook; chai/should/sinon stay — used as libs)
- install:all -> single root `bun install` (workspace covers webview-ui)
- drop .mocharc.json / .nycrc*.json from CI paths-filters and
.vscodeignore; add bunfig.toml to the filters
Verified: check-types clean, unit 880/0, vitest 582/0.
* fix(vscode): import bun:test globals in tests that relied on ambient @types/mocha
CI Quality Checks (clean `bun install` without @types/mocha) surfaced
TS2582/TS2304 "Cannot find name 'describe'/'it'/'beforeEach'" in test
files that used the global mocha/jest test functions without importing
them. The Phase 4b codemod only rewrote files that imported from
"mocha"; these used ambient globals, so they were missed (and passed
locally because a stale @types/mocha lingered in node_modules).
Add explicit `bun:test` imports (before->beforeAll, after->afterAll in
TelemetryService.test.ts). chai/sinon stay as libraries.
Verified against a clean tree (no @types/mocha): check-types 0 errors,
unit suite 58 files / 880 pass / 0 fail.
* style(vscode): biome-format migrated test files + codemod scripts
The mocha->bun:test codemod and manual import edits left formatting that
didn't match biome (the CI `format` check, which validates files changed
since main, flagged them). Also narrow setup.ts's bun:test import to the
actually-used beforeEach/afterEach (describe/it only appear in a JSDoc
example), fixing a noUnusedImports lint error.
ci:check-all (check-types + lint + format) now passes locally.
* fix(webview-ui): declare phantom deps + pin React 18 types under bun workspace
Folding webview-ui into the bun workspace changed its install topology
from an isolated npm flat tree to the shared hoisted store, surfacing
two classes of pre-existing latent issues that npm hoisting had masked:
1. Phantom dependencies: src imports `marked`, `unist`, `unist-util-visit`
and `@heroui/theme` directly but never declared them. Declared them
(marked ^15, unist-util-visit ^5, @types/unist ^3, @heroui/theme 2.4.26).
2. React types: @testing-library/react's optional peer pulls @types/react@19
into a resolvable location; tsc mixed it with the toolkit's React 18
types (React 19 dropped Component.refs), breaking 452 JSX usages. Pin
react/react-dom type resolution to webview-ui's React 18 copy via
tsconfig paths.
build:webview (tsc -b && vite build) and ci:check-all now pass.
* fix(vscode): restore @types/mocha for integration build + add bun:test types
The @vscode/test-cli integration runner still uses mocha, and
tsconfig.test.json compiles all src/**/*.test.ts (including bun-migrated
files) to out/. So:
- restore @types/mocha (integration compile needs the mocha ambient types)
- add `bun` to tsconfig.test.json types + root @types to both tsconfig
typeRoots so `bun:test` resolves under tsc for the migrated tests
* fix(vscode): declare glob — phantom dep used by package-standalone.mjs
scripts/package-standalone.mjs imports `glob` but it was never declared
(resolved transitively under npm's flat hoist). Under the bun workspace
store it's unresolvable, failing postcompile-standalone with
ERR_MODULE_NOT_FOUND. Declare glob ^11 (modern named-export API).
compile-standalone now produces dist-standalone/standalone.zip.
* fix(ci): strip ANSI before vitest zero-test guard grep
The vitest summary line colorizes the count ("Tests <ansi>582 passed"),
so the count isn't adjacent to the "Tests" label in raw bytes and the
guard regex failed even though 582 tests passed. Strip ANSI escapes
before matching.
* fix(vscode): declare minimist — phantom dep in testing-platform-orchestrator
scripts/testing-platform-orchestrator.ts imports `minimist` (undeclared,
resolved transitively under npm hoist). Declare it so the testing-platform
integration job runs under the bun workspace store.
* fix(vscode): restore tsconfig-paths for integration runner; tp-orchestrator uses bun
Phase 6 over-removed tsconfig-paths: test-setup.js (loaded by the
@vscode/test-cli mocha integration runner) requires it to resolve @/
aliases in the compiled out/ tree — the extension host test runner failed
with "Cannot find module 'tsconfig-paths'". Restore it. Also switch the
testing-platform spawn from `npx ts-node index.ts` to `bun index.ts`
(bun runs TS natively; avoids the removed ts-node).
* fix(vscode): route tests by bun:test import marker; integration runner stays mocha
The mocha->bun codemod swept up tests that the Node-based @vscode/test-cli
integration runner compiles/runs, which cannot load the `bun:test` builtin
(and some need the real VSCode host). Establish a single source of truth:
a *.test.ts is bun-runner-owned IFF it imports "bun:test".
- run-bun-unit-tests.ts: discover files by the bun:test import marker
(not fixed globs), so every migrated file runs under bun.
- build-tests.js: generate a tsconfig that excludes all bun:test files
from the integration compile (json5-parsed), so out/ never contains
bun:test; gitignore the generated config.
- .vscode-test.mjs: exclude the bun unit dirs from the runner globs.
- revert host-dependent tests (hostbridge/*, extension, terminal,
FileContextTracker host bits) and 3 files with sinon-on-ESM/behavioral
issues (ClineIgnoreController, mentions, TelemetryService) back to
mocha; they run on @vscode/test-cli as before.
Verified: check-types 0 errors; compile-tests 0 bun:test in out/;
bun unit 65 files/962 pass/0 fail; vitest 582/0.
* fix(vscode): declare mocha — phantom dep for @vscode/test-cli integration runner
The @vscode/test-cli extension host loads `mocha` at runtime to run the
integration suite, but only @types/mocha was declared (npm hoisted the
mocha package transitively; bun's store does not expose it). The host
failed with "Cannot find module 'mocha'". Declare mocha ^11.7.4 (matches
@vscode/test-cli's own range).
* fix(vscode): robust Windows protoc-gen-ts_proto plugin resolution under bun
build-proto.mjs hardcoded node_modules/.bin/protoc-gen-ts_proto.cmd for
Windows, but bun's workspace store places/extensions the bin shim
differently (hoist + .cmd/.bunx), so Windows protos failed with
"protoc-gen-ts_proto: The system cannot find the file specified". Probe
the local + root .bin with known shim extensions instead. Also update
the testing-platform usage string (ts-node -> bun).
* fix(vscode): generate node .cmd wrapper for ts-proto plugin on Windows
The previous probe found bun's `.bunx` shim, but protoc cannot exec it
("%1 is not a valid Win32 application"). Instead, on Windows generate a
small .cmd wrapper that runs the resolved protoc-gen-ts_proto JS via
`node`, which protoc can execute regardless of package manager. POSIX
path (direct JS bin) is unchanged.
* fix(vscode): package VSIX with --no-dependencies (bundled) to stop monorepo traversal
Under the bun workspace, @cline/* are workspace:* symlinks pointing to
../../../../sdk/packages/*. vsce, walking the dependency tree, followed
them out of apps/vscode and packaged the whole monorepo (../, ~84MB incl.
root node_modules and .env), which crashed vsce's secret scanner and
failed all e2e jobs.
The extension is fully esbuild-bundled into dist/extension.js, so vsce
should not walk node_modules at all. Add --no-dependencies to every
vsce/ovsx package/publish path (e2e build, marketplace, nightly), and
tighten .vscodeignore to drop nested node_modules and dev-only inputs
(scripts, proto, testing-platform, bunfig, esbuild.mjs, etc.).
Result: VSIX is 39 files / ~7 MB and the secret scan passes.
* docs(vscode): tighten bun/node comments and consolidate into a clinerule
- add .clinerules/bun-and-node.md (eternal-now: bun=tooling, node=runtime,
keep-list, and the bun:test-vs-mocha test routing rule); remove the
apps/vscode/docs/bun-migration-notes.md migration doc and point
.clinerules/general.md at the rule (single-line bullet matching the file).
- fix the hotfix-release note: there is no infra step that regenerates the
lockfile; a CHANGELOG+version bump leaves bun.lock consistent (workspace
versions aren't pinned) and publish runs --frozen-lockfile.
- reframe runner/preload comments to describe the code as-is (drop
"migrated off mocha"/codemod history); add a TODO on the bun-test preload
to migrate suites off the vitest `vi` shim to native bun:test and delete it.
- remove the one-shot mocha->bun codemod scripts.
* fix(debug-harness): pin debugee VSCode version so bundled Playwright can drive it
The harness downloaded "stable" VSCode (currently 1.125 / Electron 42),
which the bundled Playwright cannot drive — `_electron.launch()` hangs
until its 60s timeout (Electron started and a window appeared, but the
launch handshake never completed). Default to a known-good version
(1.103.0, matching the e2e CI matrix) and allow override via
VSCODE_TEST_VERSION.
* fix(webview): render under bun workspace — dedupe React, drop stale codicons link
The webview mounted but crashed before rendering (blank sidebar; e2e
"Login to Cline" never visible) with "Cannot read properties of null
(reading 'useRef')" — the classic two-React-copies / null hook dispatcher.
Under the bun workspace, sibling packages pull react@19 into the shared
store and a transitive webview dep resolved a second React instance into
the vite bundle. Add resolve.dedupe + pin react/react-dom to webview-ui's
own React 18 copy.
Also drop the separate `<link>` to node_modules/@vscode/codicons in the
webview HTML: the webview's index.css already @imports codicons, so the
font is bundled into the build assets. Under bun that node_modules path
is a symlink to the root store (outside the webview localResourceRoots)
and isn't packaged with --no-dependencies, so the link 404'd; the bundle
covers it. Re-scope the .vscodeignore nested-node_modules exclude so it
no longer shadows the codicons re-include.
* fix(debug-harness): disable GPU so the debugee renders in headless/VM envs
On headless/VM GPU stacks the debugee Electron's GPU process crash-loops
("Exiting GPU process during initialization" / CreateCommandBuffer
kTransientFailure), killing the window before Playwright finishes
attaching and tripping the 60s launch timeout. Force software rendering
(--disable-gpu and friends) for a stable harness launch.
* fix(debug-harness): survive launch failures; configurable, longer launch timeout
The harness crashed (whole bun process exited) whenever VSCode launch
failed/timed out: Playwright emits a late unhandled rejection on the dead
CDP transport after we've already handled the launch error, and the
default behavior takes the HTTP server down with it — forcing a full
restart just to retry.
- Add process-level unhandledRejection/uncaughtException guards so stray
async errors are logged and the server keeps serving (retry via `launch`).
- On launch failure, close the orphaned Electron so a retry isn't blocked.
- Make the _electron.launch timeout configurable (--launch-timeout) and
raise the default to 120s for cold launches; document VSCODE_TEST_VERSION.
* fix(ci): address review feedback — vsix --no-dependencies, drop stale coverage path, Windows shell
- ext-vscode-publish-stable.yml: add --no-dependencies to the release-artifact
`vsce package` (Max's catch). Without it, vsce follows the @cline/* workspace
symlinks out of the package and bloats the .vsix with the whole monorepo.
- ext-vscode-test.yml: drop the stale apps/vscode/coverage-unit/lcov.info upload
path (Max's catch). That file was produced by the removed nyc unit-coverage
step (.nycrc.unit.json); nothing generates it now.
- ext-vscode-test-e2e.yml: the better-sqlite3 assert step ran under the Windows
runner's default pwsh and failed to parse the POSIX test. Pin it to `shell: bash`
(Git Bash ships on windows-latest); the non-e2e job already defaults to bash.
---------
Co-authored-by: Cline Agent <cline-agent@users.noreply.github.com>
* remove inline no-usable-provider sign-in banner; rely on inference-time errors
The "Sign in to Cline or set up a provider" banner gated chat input on a
parallel provider-usability heuristic that mis-detected BYOK setups
(Bedrock profile/IAM, Vertex ADC) and its sign-in button discarded the
device code. Remove the component and the hasUsableProvider plumbing.
Auth/config problems now surface at inference time, where handling
already exists:
- cline provider without a token -> emitClineAuthError -> ErrorRow
renders the Sign in button with the device-code display
- any other misconfigured provider -> say:"error" row
Also deletes the now-dead sdk/provider-usability module and adds a test
that failed session start emits a plain chat error.
* restore debug-harness server deleted in 0bfbfb944
Commit 0bfbfb944 ("delete unused files") removed src/dev/debug-harness/server.ts
as dead code, but it is a dev tool launched directly via
`npx tsx src/dev/debug-harness/server.ts` (see its README and
.clinerules/debug-harness.md) — no static import graph reaches it, which
is why the unused-file analysis flagged it. The README, the .clinerules
docs, and the CLINE_CAPTURE_BROWSER / __clineHandleUri hooks in
extension.ts and utils/env.ts that exist solely for this harness all
survived the deletion, leaving them dangling.
Restored verbatim from 0bfbfb944~1; verified it boots and listens on
:19229.
* fix: thread proxy/CA-aware fetch into the SDK inference path
The main agent loop did not receive the host's proxy/CA-aware fetch, so
on JetBrains and the CLI inference over a corporate proxy or to a
self-signed/private-CA endpoint failed with "unable to get local issuer
certificate". This regressed at the SDK cutover: the pre-SDK CLI
(2.18.0) constructed provider clients with a proxy-aware fetch directly,
while the SDK agent loop fell back to bare global fetch (CLINE-2353).
Two layers:
- App (cline-session-factory.ts): always build CoreSessionConfig.
providerConfig and carry the proxy-aware fetch from @/shared/net, not
just for Bedrock. In VSCode this fetch is global fetch, so behavior is
unchanged there; in the standalone (JetBrains) build it is undici with
EnvHttpProxyAgent.
- SDK (handler-factory.ts): forward providerConfig.fetch into
createGateway both as the top-level fallback fetch and per provider, so
the gateway's provider clients use it. Passing undefined is a no-op
(registry resolves config?.fetch ?? defaults?.fetch ?? fallbackFetch),
so other SDK consumers are unaffected.
The SDK change covers every host that supplies a fetch; the app change
covers VSCode and JetBrains. The CLI builds its session config through a
separate path (apps/cli) that does not yet wire a proxy-aware fetch, so
CLINE-2353 on the CLI surface is addressed in a follow-up.
Adds a handler-factory unit test asserting the host fetch is forwarded
to createGateway at both the top level and per provider.
* fix: deterministically install proxy dispatcher in standalone core
The proxy/CA-aware undici dispatcher is installed as a side effect of
loading @/shared/net (it calls setGlobalDispatcher with EnvHttpProxyAgent
in the standalone build). The standalone entry cline-core.ts did not
import that module, so the dispatcher was only installed incidentally
when some other transitively-imported module happened to pull it in. A
future change to the import graph could silently drop proxy/CA support on
JetBrains.
Import @/shared/net for its side effect, first, so the install is
deterministic and runs before any network use (CLINE-2353).
Standalone-only hardening; VSCode uses global fetch and is unaffected.
* fix(vscode): suppress duplicate tool row when a mode change clears a pending approval
Switching plan/act while a tool approval was pending duplicated the
approval row in chat. clearPending resolved the pending approval as
denied, which unblocks the core; the core then emits the denied tool
call's content_start/content_end events before the mode coordinator's
abort lands. The interactive deny paths record the denial in the
message translator state so those events are suppressed, but
clearPending skipped that step, so the translator rendered the events
as a fresh say:tool row next to the still-visible approval ask.
clearPending now records the denial through recordDeniedToolApproval
before resolving, mirroring resolvePendingToolApproval. This covers all
clearPending callers: mode changes, task cancel, and task clear.
* refactor(vscode): trim the clearPending denial fix to its minimal shape
Keep clearPending's original structure, only inserting the denial
recording before the resolve. Drop the end-to-end suppression test:
translator suppression for recorded denials is already covered by
message-translator-approval-denial.test.ts, and the clearPending
recording is covered by the extended unit assertion.
* fix(webview): restore aggressive pin-to-bottom auto scroll in chat view
The auto-scroll effect only fired on groupedMessages.length changes, but in
the SDK-migrated extension new content can appear in the chat without the
message list length changing:
- The Thinking placeholder row is driven by turnState alone (e.g. the plan
to act switch auto-continues the task with no new message), and it was
appended to the rendered list inside MessagesArea where the scroll hook
never saw it.
- New tool messages merge into the trailing tool group, and the thinking
placeholder gets swapped for a real reasoning row at constant length.
Fixes:
- Lift the thinking placeholder computation out of MessagesArea into a new
useDisplayedGroupedMessages hook so ChatView feeds the same list to both
Virtuoso and useScrollBehavior; the placeholder appearing now pins to
bottom like a real message.
- Key the pin effect on the tail message ts (skipping the placeholder) in
addition to list length, covering in-place tail changes.
- Re-engage auto scroll when turnState.phase transitions into streaming. In
the old extension every turn start was accompanied by a user send/button
click that reset disableAutoScrollRef; turnState-driven turn starts like
plan to act auto-continue have no webview-side action, so handle it in
the scroll hook.
* refactor(webview): replace scroll fix with minimal single-file version
Same three behaviors as the previous commit (pin when the thinking
placeholder appears, pin on in-place tail changes, re-engage auto scroll
when a turn starts streaming) but implemented as two small effects in
MessagesArea, which already has both the rendered list and scrollBehavior
in scope. Reverts the useDisplayedGroupedMessages hook extraction and the
ChatView/useScrollBehavior changes; net diff vs the base branch is now
one file.
* test(vscode): exercise full SDK structured edit flow in diff.test.ts e2e (ENG-2042)
The SDK runtime executes structured (OpenAI-format) tool calls instead of parsing XML-style tool syntax out of assistant text. Teach the e2e mock server to stream an editor tool call for edit_request (arguments split across deltas to exercise fragment reassembly), answer the SDK's follow-up tool-result request (role:'tool' message) with turn-ending completion text, and remove the classic XML-era EDIT_REQUEST/REPLACE_REQUEST responses.
diff.test.ts now covers the full approval flow: approval ask row -> Save -> editor tool writes the file -> completion text, verifying the edit on disk and restoring the git-tracked fixture afterwards. The old 'test.ts: Original <-> Cline's Changes' diff-tab assertions are unreachable under the SDK executor architecture (the editor executor writes via Node fs and does not route through DiffViewProvider); this behavioral difference is documented in the test file.
* test(vscode): address review feedback on diff.test.ts e2e
- Scope the mock server's tool-result follow-up detection to edit_request conversations so tool results from other (future) scenarios don't mis-route to EDIT_REQUEST_COMPLETE.
- Move the fixture readFileSync inside the try block and guard the finally restore, so a failed read doesn't bypass cleanup attribution or write undefined back to the fixture.
* docs(vscode): rephrase diff e2e comments to describe current behavior
Comments described historical behavior (XML-style tool-call parsing that predates the SDK runtime), which is confusing to readers of the current code. Rephrase them to describe the code as it exists now.
* test(vscode): rename diff.test.ts to file-edit.test.ts and drop duplicated preamble
The test no longer touches a diff editor (the SDK editor executor writes files directly after approval), so the 'Diff Editor' name was misleading. Rename the file and describe block to match what it asserts: the file-edit approval flow.
Drop the first half of the test (send hello, wait, New Task, check history), which duplicated chat.test.ts, and the mock server's 500ms delay that existed only to support an 'API Request...' visibility assertion that no longer exists.
* fix(vscode): persist skill disable to SKILL.md frontmatter so the model honors it (ENG-1995)
The VS Code skill toggle only updated extension state (globalSkillsToggles /
localSkillsToggles), but the SDK builds the model's skill list and the `skills`
tool from each SKILL.md's frontmatter `disabled` flag. As a result, disabling a
skill in the sidebar left it fully available to the model, including in new
tasks.
toggleSkill now also writes the `disabled` flag to the skill's SKILL.md
frontmatter (no-op for remote skills, which have no backing file), via new
helpers updateSkillMarkdownDisabledState / setSkillDisabledInFrontmatter in
skills.ts. Adds unit tests for both helpers.
* fix(vscode): don't rewrite skills with malformed frontmatter (ENG-1995)
parseYamlFrontmatter fails open on invalid YAML, returning the full original
document as the body. updateSkillMarkdownDisabledState would then prepend a
second `---` block on a disable, corrupting the file. Bail out and leave the
file untouched when frontmatter fails to parse. Adds tests for the malformed
disable/enable cases.
Addresses Greptile review feedback on #11294.
* test(vscode): assert malformed-skill fixture is actually invalid YAML (ENG-1995)
Add a guard test that parseYamlFrontmatter reports hadFrontmatter and a
parseError for the shared malformed fixture, so the two "leave file untouched"
tests can't silently pass via a different code path if the fixture ever became
valid YAML.
Addresses Greptile review feedback on #11294.
* fix(vscode): resolve @cline/shared/storage subpath in mocha unit-test compile
The CommonJS mocha unit-test runner uses classic "node" moduleResolution,
which does not read the `exports` subpath maps in @cline/* package
manifests, so `@cline/shared/storage` (imported by
src/sdk/telemetry-settings-sync.ts) failed with TS2307 when test files
transitively reach the SDK adapter. Mirror the explicit paths mapping
already added to tsconfig.test.json for the integration-test compile.
* fix(vscode): restore E2E mock auth in SDK auth service so e2e tests can sign in
The SDK migration replaced classic AuthService (which swapped in
AuthServiceMock under E2E_TEST) with sdk/auth-service.ts, losing the
mock path. "Login to Cline" then invoked the real SDK OAuth flow and
opened a native browser dialog the Playwright tests cannot interact
with, so helper.signin() never authenticated and chat.test.ts +
diff.test.ts failed on every platform (the failures also reproduce on
the base branch).
- auth-service.ts: under E2E_TEST=true (and CLINE_ENVIRONMENT=local),
exchange the well-known test code with the local mock API server and
persist credentials to providers.json — no browser. Replaces classic
AuthServiceMock (see origin/main src/services/auth/AuthServiceMock.ts).
- chat.test.ts/diff.test.ts: wait for the mock turn to complete before
clicking New Task; SDK history is persisted at turn end, so navigating
mid-turn races the write and Recent never shows.
- diff.test.ts: the footer Start New Task button only appears for
attempt_completion turns under SDK TurnState; use the header New Task
button like chat.test.ts.
* fix(vscode): enforce stop-before-start ordering for same-id session restarts
The app reuses the taskId as the sessionId whenever it replaces or
resumes a session (mode/MCP rebuilds, follow-up resume, history
restore), but the old session's stop ran fire-and-forget, and core
cleanup is keyed by sessionId across multiple awaits. A stop still in
flight when the same-id replacement started could tear down the live
successor: late sessions-map deletes, a late 'ended' emission, or a
stalled status write landing on the replacement.
Adopt the sequencing invariant the CLI has always used: never start a
same-id session while its stop is in flight. SdkSessionLifecycle tracks
in-flight stops in a pendingStops map keyed by sessionId, and
startNewSession awaits the pending stop for a reused id before starting
(with a log line so a wedged stop is diagnosable). Fresh-id starts
never wait. fireAndForgetSend additionally captures the ActiveSession
by object identity at send time so a send settling after a same-id
replacement cannot flip the successor's run state.
* fix(vscode): auto-continue the task when switching from plan to act
In plan mode, the model's switch_to_act_mode tool call flipped the toggle
but ended the run as aborted: the beforeModel stop hook fired after
turn-started, leaving a dangling api_req_started spinner rendered as
'API Request Cancelled', and nothing continued the task after the
act-mode rebuild. Manually toggling after a presented plan had the same
dead end.
The tool now declares lifecycle.completesRun so the run ends cleanly
after the tool result, and the queued mode change rebuilds the session
and auto-continues with a hidden continuation prompt. A manual plan to
act toggle auto-continues only when the agent is idle after presenting
its plan (not running and awaiting_followup; a pending ask_question
blocks mid-run so it cannot false-positive). Composer content rides
along: typed text becomes the continuation, attachments are forwarded
and echoed, attachment-only toggles count as consumed. The RPC reports
consumption only after the send was actually handed to the session, and
the webview then clears only the exact submitted content, so failures
and racing input never lose composer state. Failures before the send
undo the optimistic running flip, report an error phase, and roll the
mode back when the session was never replaced.
Hidden prompts (the act continuation and the pre-existing task
resumption prompt) shifted editMessageAndRegenerate's visible-to-SDK
user message ordinal mapping; the new sdk-user-message-mapping module
skips them in their persisted user_input-wrapped shape, counts
attachment-only messages (which have visible bubbles), ignores
tool-result rows, and attachment-only resumes now echo a bubble to keep
both transcripts aligned. Follow-ups sent during a rebuild wait on
waitForPendingRebuild instead of resuming a parallel session that the
rebuild would kill.
The plan-mode system prompt and tool description require explicit user
approval in a message sent after the plan was presented, preventing the
model from self-escalating to act mode.
* fix(vscode): move the turn phase to error when a task resume fails
askResponse optimistically sets the turn phase to streaming before
delegating to the followup coordinator, but the coordinator's resume
catch only posted an error row, leaving the footer stuck on
Thinking/Cancel. Resume failures (auth errors, session start errors)
now report back via onResumeFailed so the controller can set the phase
to error.
* fix(webview): use themed components and reasoning selector in generic provider settings
The catalog-backed GenericProviderSettings path (deepseek, gemini, mistral,
and other migrated providers) rendered its model picker with raw unstyled
HTML select/input/button elements, unlike every other provider which uses
the VS Code webview-ui-toolkit components. Swap ModelPickerWithManualEntry
to VSCodeDropdown/VSCodeOption/VSCodeTextField/VSCodeButton, reusing the
DropdownContainer and re-init key workaround from common/ModelSelector.
Also render ReasoningEffortSelector in GenericProviderSettings when the
selected model's catalog info has supportsReasoning, persisting the effort
through the provider config reasoning patch, matching ClineModelPicker.
This is driven by the catalog capability flag rather than provider id.
* fix(webview): re-sync custom model id field after async config hydration
The controlled customModelId state was initialized once at mount, but the
provider config and model catalog both hydrate asynchronously, so the lazy
initializer could capture a placeholder value and leave the custom model
text field stale once the committed selection loaded. Sync the field via an
effect keyed on the committed model id and its in-list status, depending on
derived values rather than the models object whose identity can change
every render while the catalog loads.
* fix(vscode): expand remote workflow/skill slash commands before send
The SDK-backed extension sent `/workflow` text to the model verbatim, so
remote-config workflows never ran. Expansion is host-driven (the agent loop
never auto-expands), and the controller's pre-send path did none — matching
the CLI's `buildUserInputMessage`, resolve slash commands via a
controller-owned UserInstructionConfigService that watches the workspace
(including `.cline/remote-config/`), refreshed after each remote-config sync.
Fixes ENG-2036.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(vscode): guard instruction watcher against post-dispose race
Reject in ensureUserInstructionService when the controller is already
disposed so a slash-command resolution that yielded across dispose() can't
resurrect a file watcher that nothing will stop. Also log the post-expansion
length handed to parseMentions. Addresses Greptile review.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
When a provider returns a model-not-found error (e.g. Anthropic's HTTP 404
for a retired model such as claude-3-haiku-20240307), the SDK strips the
status and delivers only the terse body, which collapses to the bare label
"model: <id>". reshapeErrorForWebview fell through to returning that raw
string, so ErrorRow rendered a label-like fragment in red with no hint that
the model is gone or how to recover.
Detect these in the plain-text branch of reshapeErrorForWebview and rewrite
them into a sentence that names the model and tells the user to switch models
in API Configuration settings, then retry. The model switch is framed as a
precondition rather than a parallel option so users don't loop on Retry.
Detection is text-based because the HTTP status is unavailable at this point.
The keyword match is anchored to the word "model" with a not-found signal in
the same sentence, so unrelated errors that merely mention a model (plan
gating, deprecated features) are left untouched. Adds tests for the bare
label form, a generic "does not exist" form, and two negative cases (plan
gating and an auth error mentioning a model) that must pass through unchanged.
The CommonJS integration-test tsconfig (moduleResolution: node) and the
vitest config did not resolve the @cline/shared/storage exports subpath
imported by src/sdk/SdkController.ts, breaking 'compile-tests' (TS2307)
and 3 vitest SDK suites. Add explicit path/alias mappings to the built
dist so both resolve without changing module emit. Compile-time/test-only;
emitted JS still uses the real package specifier.
The inline "Sign in to Cline or add an API key" gate appeared and disabled
chat for Amazon Bedrock users who configured AWS Credentials (access key +
secret), an AWS profile, or relied on the default AWS credential chain, even
though the provider was fully usable (issue #11270).
hasUsableProvider() decided Bedrock usability solely via resolveApiKey(),
which maps bedrock -> awsBedrockApiKey. Bedrock's three non-API-key auth
modes leave that field empty, so buildBedrockProviderConfig() would build a
working session while the gate reported the provider unusable. The Cline
login state is irrelevant here: the gate is computed for the active-mode
provider, and the "Sign in to Cline" button is just one of two generic
remedies, which is what made the symptom look like a logged-out state.
Add a Bedrock branch that classifies usability per auth mode, reusing
resolveBedrockAuthentication() so the gate and the session builder agree on
what each mode means:
- api-key: usable only when awsBedrockApiKey is non-blank (unchanged, now
also rejects whitespace-only keys)
- profile / iam / default credential chain: usable, deferring credential
resolution to request time (mirrors buildBedrockProviderConfig and the
existing keyless-provider philosophy)
Manually verified on a real setup across all four auth modes: pre-fix the
gate blocked chat for access-key and profile auth; post-fix the gate clears
and chat works. API-key mode was never gated incorrectly.
Tests: add Bedrock coverage for every auth mode, including api-key with a
blank and with an unset key (both not usable), the SigV4 repro, profile
(explicit/inferred/awsUseProfile), the bare credential-chain config, and
plan-mode resolution plus plan/act isolation.
Allow user feedback messages in the VS Code extension to be edited inline and regenerated from that point. Adds a TaskService RPC, truncates persisted SDK history before the selected visible user prompt, and starts a new session with the edited prompt. Also ensures the regenerated active task appears in extension history while SDK history catches up.
cf25cd66a ("make extension plan mode more similar to CLI") removed the
file-level ACT_MODE_CONTINUATION_PROMPT constant and stopped passing the
autoContinue / continuationPrompt options when rebuilding a session for
a mode change, but left the corresponding block inside
rebuildSessionForMode in place. The block still references the deleted
constant, so tsc fails on the SDK migration branch with TS2304: Cannot
find name "ACT_MODE_CONTINUATION_PROMPT".
No caller passes options to rebuildSessionForMode anymore, so the block
is dead. Drop the block and narrow the signature to take only newMode.
Existing tests already invoke rebuildSessionForMode(<mode>) with no
second argument and assert that fireAndForgetSend is not called on a
mode rebuild, so they keep passing.
* fix(terminal): surface standalone terminal spawn diagnostics
Add Logger calls at every chokepoint of the standalone terminal pipeline
so the (currently silent) failure modes around JetBrains-hosted
cline-core become debuggable from cline-core-service.log.
Lines added, all using the existing Logger facility (no new
dependencies, no behavioral changes):
* StandaloneTerminalProcess.run() now logs:
- `[StandaloneTerminalProcess] run() entered: shell=… cwd=… args=…`
on entry, before the try block;
- `[StandaloneTerminalProcess] spawned pid=… for shell=…` right
after child_process.spawn returns;
- `[StandaloneTerminalProcess] close: code=… signal=… fullOutputLen=…`
inside the `close` handler (the `fullOutputLen` reveals when the
child exits 0 with empty pipes — the symptom in issue #10948);
- `[StandaloneTerminalProcess] child error: …` in the `error`
handler;
- `[StandaloneTerminalProcess] spawn threw synchronously: …` in
the outer catch.
* StandaloneTerminalManager.runCommand() now logs entry
(`[StandaloneTerminalManager] runCommand terminalId=…: <cmd>`) and
attaches a `.catch` to the previously fire-and-forget
`process.run(…)` Promise so an unhandled rejection surfaces as
`[StandaloneTerminalManager] process.run rejected for terminal …`
instead of disappearing.
* CommandExecutor.execute() extends the existing "Executing command
in … terminal" line with `mode=<terminalExecutionMode>` and
`managerCtor=<manager.constructor.name>`, so it's possible to
confirm whether the `vscodeTerminal` path is in fact backed by a
`StandaloneTerminalManager` on JetBrains (it is — see
notes/issue-10948-…md).
* CommandOrchestrator.orchestrateCommandExecution() logs the
`process.once("completed")` event with `exitCode`/`signal`/
`terminalType`, the "resolved completed" return branch with the
line/byte totals, and emits a `WARN` on the silent "still running"
fall-through. The last one matters because the original repro
reported "Command executed successfully (exit code 0)" with empty
output — the WARN makes that branch loud the next time it fires.
These logs are what made the two distinct bugs in #10948 visible
(see the 2026-05-28 update in
notes/issue-10948-terminal-output-investigation-2026-05-27.md). They
stay in to keep the next regression debuggable.
Refs: cline/cline#10948
* fix(terminal): keep Windows child stdio attached to parent pipes
The non-cmd Windows branch in StandaloneTerminalProcess.run() spawned
the shell (powershell.exe in practice) with `detached: true` and no
`windowsHide`. When cline-core is launched by the JetBrains plugin it
has no console of its own, so Windows CreateProcess allocates a NEW
console for the detached child and the child's stdio routes to that
new console instead of the pipe handles the parent created. From the
parent's point of view the pipes immediately EOF, `close` fires with
`code=0`, and `fullOutput` is 0 bytes — exactly the symptom reported
in cline/cline#10948 ("Command executed successfully (exit code 0)"
with no output and no filesystem effect).
This bug applies to every command the agent runs through the
standalone terminal path on Windows, not just the
double-wrapped-PowerShell cases (verified by re-running a clean
`dir <file>` after the diagnostics from the previous commit landed:
`run() entered` and `spawned pid=<num>` both fired, then `close: code=0
fullOutputLen=0`).
Fix:
* `detached: process.platform !== "win32"` — keep the existing
POSIX behavior (a separate process group helps `tree-kill`), but
drop it on Windows where `tree-kill` walks the PID tree with
`taskkill /T` and doesn't need a process group.
* `windowsHide: true` — matches every other `child_process.spawn`
call site in cline-core (git, MCP, hooks, browser) and flips on
`CREATE_NO_WINDOW`, keeping the child attached to our pipes
without popping a console window.
Verified on Windows 11 + IntelliJ IDEA 2026.1 + Cline plugin
1.1.59-Internal: `dir <path>`-style probes now produce a non-zero
`fullOutputLen` in the close log, and the captured output bytes
match what would have been visible interactively. PowerShell
double-wrapping (the other half of #10948) is handled in a
follow-up commit.
Refs: cline/cline#10948
* fix(terminal): harden PowerShell command wrapping for standalone shell
`StandaloneTerminalProcess.getShellArgs()` blindly wrapped every
PowerShell command as `["-Command", command]`. That has two
end-user-visible failure modes on Windows, both observed in
cline/cline#10948:
1. The agent's `run_commands` tool call sometimes arrives already
prefixed with `powershell -Command "…"`. We then spawned
`powershell.exe -Command 'powershell -Command "…"'`, and the
outer shell shredded the inner single/double-quote pairs while
re-parsing its `-Command` argument. The inner pwsh saw
quote-empty `Test-Path` calls, fell through to the `else` branch
and reported "File not found" — to ITS stdout, which the outer
inherited but the file deletion the LLM intended never ran.
2. The user's `$PROFILE` script ran on every spawn, leaking
non-deterministic noise (e.g.
`%windir%\System32\REG.exe : The module '%windir%' could not be
loaded`) into the captured output and confusing the agent.
3. Bonus: the POSIX branch used `["-l", "-c", command]`. The `-l`
re-sources login files on every command, which is slow and lets
greeter scripts leak into output.
4. Bonus: the cmd branch used `["/c", command]`. `/d` skips
AutoRun, `/s` makes the embedded-quote handling deterministic.
Fix:
* PowerShell branch returns
`["-NoProfile", "-NonInteractive", "-Command", unwrap(command)]`.
`-NoProfile` suppresses (1) the spurious profile noise that
contaminated the captured output, and `-NonInteractive` ensures
the child doesn't deadlock waiting on a prompt no one will answer.
* `unwrapPowerShell(command)` strips a leading
`powershell|pwsh [.exe] -Command|-c "…"` (or single-quoted)
wrapper that the LLM sometimes emits, fixing the double-pass
argument-quoting destruction. If the command does not match the
exact wrapper shape it is returned verbatim — worst case is "no
change", preserving pre-fix behavior.
* cmd branch returns `["/d", "/s", "/c", command]`, matching the
canonical helper in cline/sdk/packages/shared/src/parse/shell.ts.
* POSIX branch returns `["-c", command]`, dropping the unhelpful
`-l`. Also matches the SDK helper.
Verified on Windows 11 + IntelliJ IDEA 2026.1 + Cline plugin
1.1.59-Internal in combination with the previous "keep Windows
child stdio attached" commit: `Remove-Item CHANGELOG.md` now
deletes the file, the agent's verification `Get-ChildItem CHANGELOG*`
returns nothing, and the profile-load REG.exe error no longer leaks
into captured output.
Refs: cline/cline#10948
* refactor(terminal): tone down standalone terminal diagnostics
The diagnostics added while chasing #10948 were intentionally loud so the
two bugs were visible. Now that the fixes are in, reduce them to a normal
operating posture:
* Demote fine-grained traces to `debug`: the per-spawn `spawning …` and
`spawned pid=…` lines, `StandaloneTerminalManager.runCommand`, and the
orchestrator's `resolved completed` summary.
* Drop the orchestrator's `completed event` line entirely — the
`resolved completed` debug line already carries exit code, signal, and
line/byte totals.
* Stop echoing the full command in the manager line and stop echoing the
args vector in the spawn line. The command is still logged once at
`info` by CommandExecutor (unchanged, pre-existing), so we go back from
three command echoes to one. Commands routinely embed secrets
(Authorization headers, tokens), so fewer copies on disk is better.
Kept loud on purpose:
* `info` on `close: code=… fullOutputLen=…` — the single line that proves
the Windows stdio-capture fix and the most useful per-command signal.
* `warn` on `resolved without completion event` — the silent-success
canary for the #10948 failure mode.
* `error` on child error / synchronous spawn failure / unhandled
process.run rejection.
Refs: cline/cline#10948
* fix(terminal): tighten PowerShell unwrap regex and extract to a pure module
Two review follow-ups for the #10948 shell-arg handling:
1. The wrapper-strip regex used a greedy `([\s\S]*)` body, so a command
like `powershell -Command "foo" "bar"` would match with the body
captured as `foo" "bar`, silently rewriting a command into something
different. Replace the body with a tempered match `((?:(?!\1).)*)`
that cannot contain the captured delimiter, so anything other than
exactly one quoted token is returned verbatim. Worst case is now
"no change" rather than an incorrect rewrite. The legitimate
double-wrapped case from #10948 (outer ", inner ') still unwraps.
2. `getShellArgs` and `unwrapPowerShell` were private methods on
StandaloneTerminalProcess, untestable without spawning a process.
Move them to a pure `shellArgs.ts` module. `getShellArgs` now takes
an injectable `platform` (defaulting to `process.platform`) purely so
the win32-vs-posix branch is testable; behavior is unchanged. This
also gives us a single local seam to later consolidate onto the
canonical `@cline/shared` helper (tracked as a follow-up).
No behavioral change beyond the regex correctness fix.
Refs: cline/cline#10948
* test(terminal): cover shell-arg construction and PowerShell unwrap
Add mocha unit tests (matching the repo's node:assert/strict + __tests__/
convention so the existing mocharc spec globs pick them up) for the newly
extracted shellArgs module:
* unwrapPowerShell: double-quote and single-quote wrappers, powershell.exe
-c form, the #10948 nested-quote repro (inner quotes preserved),
non-wrapped passthrough, and the two regressions the tightened regex
must reject (`… "foo" "bar"` and a command that merely mentions
powershell mid-string).
* getShellArgs: PowerShell -> -NoProfile -NonInteractive -Command (with
unwrap), cmd -> /d /s /c, POSIX -> -c. The injectable platform arg lets
these run on any CI host.
This closes the M1 review finding (the regex was the riskiest line in the
change and had zero coverage) and exercises the cmd/POSIX flag changes
called out in M2.
Refs: cline/cline#10948
* docs(terminal): drop issue references and clarify windowsHide comment
Remove inline issue-number references from source comments and a test
name; that context belongs in the commit history, not the code. Also add
a one-line note that windowsHide is a no-op on non-Windows platforms,
since it is set unconditionally while the surrounding comment is
Windows-specific.
No behavior change.
* refactor(terminal): drop warn on the non-completion return path
The orchestrator's final fall-through return is a normal, expected path:
the process resolved via `continue` without a `completed` event (e.g. a
terminal mode without shell integration, or proceed-while-running flows).
Logging it at `warn` cries wolf on healthy runs, so remove it. The
genuine failure mode this was meant to catch surfaces through the
`close`/error logs and the result string itself.
* fix(terminal): address review feedback on standalone spawn paths
Three follow-ups from code review:
* StandaloneTerminalManager.runCommand: the unawaited process.run()
.catch only logged. run() emits "error" for failures it catches, but a
rejection escaping without an "error" event would leave the outer
promise (resolved via the "continue"/"error" events) pending forever,
stalling the caller. Re-emit "error" from the catch so both paths stay
consistent. Cannot trigger today (no await outside run()'s try/catch)
but the guard exists precisely for future rejections.
* shellArgs POSIX branch: document that dropping the login flag (`-l`)
is intentional and relies on the child inheriting the parent's PATH via
process.env, with a note that a GUI-launched IDE without a login PATH
is the edge case to watch.
* StandaloneTerminalProcess cmd.exe branch: add windowsHide:true. The
console-allocation/window-pop problem is not exclusive to the non-cmd
branch; a console-less parent could pop a window for cmd.exe too.
No-op on non-Windows.
compile-tests runs 'tsc -p tsconfig.test.json' (module: commonjs) over all
src/**/*.test.ts for the VS Code integration runner. The new src/sdk vitest
suites use top-level 'await import(...)' (after vi.mock), which is invalid
under CommonJS and fails with TS1378. The integration runner never runs
src/sdk anyway (.vscode-test.mjs only globs core/test/utils/shared/
integrations/hosts/services); these run via 'npm run test:vitest'. Exclude
src/sdk/**/*.test.ts from the integration compile.
The rebase dropped '--config-path ./biome.jsonc' from the lint/format/
postprotos scripts and removed the '!!**/.vscode-test' ignore from
biome.jsonc. Without the explicit config path, biome auto-discovered the
root biome.json instead of apps/vscode/biome.jsonc, applying the wrong
rule severities (449 errors at error level for rules that are off/info in
the nested config). Restore both to match origin/main and apply the
pending buf format fix to models.proto.
The command row reflects an executing state while a command runs. The
message translator includes the command-output marker on the running
command row so the webview renders it as executing; the row is finalized
with output and a completed flag when the command ends.
Also remove the unused onChange parameter from the foreground run_commands
path: the SDK runtime does not pass it, so it had no effect. Foreground
command output is surfaced to the chat at completion, not incrementally.
Fixes CLINE-2298 and CLINE-2162
The footer Approve/Reject buttons stayed disabled when a second consecutive
approval ask arrived. The button configs are shared singletons (e.g.
BUTTON_CONFIGS.tool_approve), so two identical asks return the same object
reference and the effect that reset the processing latch never re-ran.
Key the processing latch on the ask identity (anchored turn timestamp plus the
button labels) rather than the config object reference, using a ref-based latch
so each new ask re-enables the buttons. Adds a regression test.
Test plan:
1. Ask the agent to generate two requests to ls /tmp at once
2. Approve (or reject) the first request
3. Check that the buttons for the second request are enabled
Run Cline inference through the VS Code Language Model API (vscode.lm), enabling
models contributed by any extension that registers a language model chat
provider with VS Code. GitHub Copilot is the most common such vendor, but the
implementation is vendor-agnostic — it selects models via
vscode.lm.selectChatModels and has no Copilot-specific logic.
- VsCodeLmHandler implements the Cline SDK ApiHandler and is registered with the
SDK handler registry; the model selector travels as a vendor/family[/version/id]
string in modelId and is parsed back here. Selector segments are
percent-encoded so values containing slashes round-trip intact.
- Native tool calling: tool definitions are passed to sendRequest and tool calls
are surfaced as tool-call chunks; tool results round-trip as
LanguageModelToolResultPart, with structured tool output serialized to text and
a trailing user message appended when a turn ends on tool results so models can
read the output.
- Gated to VS Code: registration is conditioned on the vscode.lm API being
present, and the provider is hidden in the UI on hosts without it (JetBrains).
Depends on @cline/{shared,llms,agents,core} 0.0.42-nightly.1780514867, the first
published SDK build with the custom-registered-handler routing this provider
needs.
Both packages are imported directly from source but were never declared in
apps/vscode/package.json, so they only resolved transitively. On a clean
install this broke:
- @grpc/proto-loader — imported by scripts/proto-utils.mjs,
src/standalone/utils.ts and src/standalone/hostbridge-client.ts; its absence
made `npm run protos` (and therefore the whole build) fail on a fresh checkout.
- @opentelemetry/api-logs — imported by the OpenTelemetry telemetry providers;
its absence produced TS2307 "Cannot find module" errors under tsc.
Versions are pinned to align with the existing dependency families already
declared in this package (@grpc/grpc-js ^1.9.x → proto-loader ^0.7.13;
the @opentelemetry/* 0.56.x line → api-logs ^0.56.0). The npm and bun
lockfiles are updated accordingly (the api-logs change also dedupes several
previously-nested copies to a single hoisted entry).
Omnibus squash of the 10 oldest SDK-migration commits (authored 2026-05-27
through 2026-06-02), collapsed during the 2026-06-09 rebase onto origin/main.
Squashed commits:
- sdk migration: squashed pre-2026-05-27 work
- sdk migration: squashed 06-05-2026 -- instead of listHistory, use host.get(sessionId) instead
- updat gitignore
- fix xai provider
- fix(vscode): forward Bedrock region + AWS auth to the SDK gateway
- fix(vscode): keep in-progress MCP OAuth flow across reconnects
- fix(vscode): wire auto compact into SDK sessions (#11197)
- fix(vscode): compact Codex OAuth before input cap (#11194)
- fix unauthed user flow
- fix(llms): strip Cerebras reasoning history (#11214)
* Improve OpenRouter sticky session routing
OpenRouter prompt caching was getting weaker cache hit rates because requests did not include a stable session_id. Without that identifier, OpenRouter can route consecutive turns away from the same upstream cache context even when cache_control is present, causing more fresh input billing.
Propagate explicit runtime sessionId metadata from agents into model requests without synthesizing fallback session or conversation ids. Add provider metadata for sticky sessions so OpenRouter maps metadata.sessionId to the JSON body session_id field, while keeping the mechanism extensible for header-based providers.
Apply sticky-session metadata in the AI SDK provider fetch wrapper, preserving explicit wire values when callers already set them. Move trimNonEmpty and omitUndefinedValues into @cline/shared for reuse, and cover the JSON-body, header, and no-fallback paths with tests.
* Tighten sticky session fetch body handling
Treat init.body null as an explicit no-body override so the sticky-session wrapper does not inspect or parse a Request body that the caller has intentionally overridden.
Model fetch body text by source, which removes the unreachable JSON-body injection branch and makes the Request rewrite path explicit. Also type the provider fetch mocks so sticky-session assertions compile cleanly in editors.
* merges model-handle default metadata with per-request metadata
* feat(hub): add connector configure path and share catalog via @cline/shared
Add connector.channels/configure/delete_config Hub commands that persist
connector settings to disk without starting connector processes or calling
provider auth APIs. This means settings (including tokens) are saved as-is
without verification; callers are responsible for supplying valid values.
Shared catalog and platform definitions:
- Move ConnectorCatalogEntry, CONNECTOR_CATALOG, listConnectorCatalog, and
all ConnectorPlatformDef/FieldDef/SecurityDef types + CONNECTOR_PLATFORMS
into sdk/packages/shared/src/connectors/platforms.ts
- Export everything from @cline/shared index so CLI and Hub use the same
definitions without duplication
- Reduce apps/cli/src/connectors/catalog.ts and
apps/cli/src/wizards/connect/platforms.ts to thin re-export shims that
preserve existing CLI import paths
New Hub connector handlers (sdk/packages/core):
- connector-handlers.ts: handles connector.channels (list available/active/
configured), connector.configure (validate fields and write settings.json
under ~/.cline/data/connectors/), connector.delete_config (remove entry
and clean up empty file)
- Settings are stored as ConnectorSettingsFile (version 1) at
~/.cline/data/connectors/settings.json; reads are lenient/defensive
- Wire handlers into hub-server-transport.ts dispatch switch
- connector-handlers.test.ts: unit tests for configure, channels, and
delete_config covering field validation, conditional fields, security
constraints, and settings round-trips
Hub WebSocket auth helpers (hub-websocket-server.ts):
- Extract isLocalHubHostName / isLocalHubOrigin as named, tested exports
- Allow unauthenticated WebSocket upgrades from local origins (localhost,
127.0.0.1, ::1) so the Hub UI can connect without an auth token
- hub-websocket-server.test.ts: extend tests to cover new local-origin logic
Add connector.channels, connector.configure, connector.delete_config to
HubCommandName union in sdk/packages/shared/src/hub.ts
* apply feedback
* export connector settings json path
* apply feedback from robin
* fix(hub-ui): Use development mode conditionally for connector
Refactor connector CLI launch logic to conditionally apply Bun-specific
flags (`--conditions=development`) only when running under Bun or Node
runtimes with access to the source entrypoint. When running from a
compiled binary (e.g., packaged Cline app), use the execPath directly
without Bun flags.
- Extract `buildCliConnectCommand` function to encapsulate launcher
and args resolution logic based on runtime detection
- Use `withResolvedClineBuildEnv` for environment variable setup
- Export `__test__` object to enable unit testing of internal logic
- Add tests covering Bun source entrypoint and compiled binary cases
* address feedback
* Optimize Cline Hub webview bundle
Issue:
The Cline Hub webview build emitted Vite's large chunk warning. The main entry bundle was over 2 MB minified, and the build output included many Shiki language/theme chunks plus eagerly bundled Streamdown math/Mermaid support that the hub did not need on startup.
Changes:
- Split heavyweight Cline Hub views behind React.lazy/Suspense so settings, customization, and chat code do not all land in the initial app shell.
- Replace root Shiki highlighter usage with shiki/core and lazily loaded, explicitly supported languages/themes.
- Route Streamdown through a local HubStreamdown wrapper that uses the local CodeBlock renderer and keeps Mermaid as a lazy diagram plugin.
- Remove unused Streamdown math/code/Mermaid packages, add direct lazy Mermaid support, and add targeted Rolldown chunk groups for Mermaid parser/layout/markup assets.
Before/after bundle measurements:
| Metric | Before | After |
| --- | ---: | ---: |
| Total generated JS | 24,356 KiB | 5,800 KiB |
| Total generated JS gzip | 4,805.5 KiB | 1,434.6 KiB |
| Main entry chunk | 2,044.02 kB | 373.88 kB |
| Main entry gzip | 617.25 kB | 117.83 kB |
Verification:
- bun -F @cline/cline-hub build:webview
- bun biome check apps/cline-hub/src/webview/vite.config.ts apps/cline-hub/src/webview/src/App.tsx apps/cline-hub/src/webview/src/components/ai-elements/code-block.tsx apps/cline-hub/src/webview/src/components/ai-elements/message.tsx apps/cline-hub/src/webview/src/components/ai-elements/reasoning.tsx apps/cline-hub/src/webview/src/components/ai-elements/streamdown.tsx apps/cline-hub/src/webview/package.json
* address feedback
* fix(sdk): resolve Cline Z.ai model metadata aliases
* fix(sdk): preserve Cline model alias overrides
* test(sdk): update Cline provider model list expectation
* fix(sdk): default-on tool result truncation, name fallback, tool_use budget accounting
- Truncate every tool result (MCP/custom tools included), not just an allowlist
- Resolve tool names from tool_result.name when the paired tool_use is gone
- Count tool_use.input strings toward the aggregate provider request budget
- Protect any binary carrier block ({type, data}) from truncation, not just images
- Don't let failSession cleanup errors mask the original turn error
* fix(sdk): tighten MessageBuilder limits with named options and env overrides
Folds #11474 into the default-on truncation branch and addresses review
feedback from both PRs:
- per-result tool cap drops to 8k chars; MessageBuilderOptions constructor
with CLINE_MESSAGE_BUILDER_* env overrides for A/B testing
- env parsing is positive-only so '=0' cannot silently disable a limit
(greptile on #11474)
- aggregate budget stays at 6MB: budget truncation rewrites mid-transcript
bytes and breaks provider prefix caching, so it must stay a rare overflow
valve rather than the steady state (johnwschoi on #11474)
- user file attachments get a dedicated 50k cap instead of inheriting the
aggressive tool-result cap (codex on #11474)
- isBinaryContentLike restricted to known binary block types so textual
{type, data} payloads can no longer dodge every cap (codex/greptile)
- tool_use.input strings become last-resort budget truncation candidates,
making the aggregate budget reclaimable when oversized model-generated
arguments carry the overflow (robinnewhouse/greptile)
* fix(sdk): constrain binary tool result truncation
* style(sdk): remove disallowed comment formatting
* Revert "style(sdk): remove disallowed comment formatting"
This reverts commit 9d8b66726d.
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* Add Cline Pass provider to VS Code extension
* Fix the model picker
* ClinePass specific options
* Add feature flag to the api options
* Extend flag usage
* fix type error
* Use the right model info
* Fix tests
* Hide price info for clinePass models
* feat(onboarding): add Cline Pass as optional user-type in signup flow
Surface Cline Pass as a recommended-but-optional onboarding choice gated
behind the ext-cline-pass feature flag, alongside Free / Frontier / BYOK.
When selected, signup provisions the cline-pass provider and ClinePass
model fields; price info is hidden since cost is covered by the
subscription. Falls back cleanly to the existing flow when the flag is
off. Adds unit tests for the new helpers.
* feat(onboarding): nudge + Cline Pass subscribe link in signup flow
Strengthen the Cline Pass onboarding option with a 'Recommended' copy
nudge (text + ordering, no badge/paid-default), and add an additive
subscribe affordance on the post-signup 'Almost there!' step that links
to {appBaseUrl}/dashboard/plan. Client-only: reuses existing appBaseUrl
from useClineAuth and the existing dashboard subscribe page; no backend
change. Shown only when the user selects Cline Pass; existing flow and
other user-types are unchanged.
* refactor(onboarding): redirect Cline Pass signup to subscription page
Replace the manual 'Get Cline Pass' callout with an automatic redirect:
after a Cline Pass user completes account creation, open the dashboard
subscription signup page (/onboarding/individual-plan) in the browser.
Keep the free option first and default-selected, with Cline Pass shown
second and labeled '(Recommended)'.
* chore(onboarding): tighten inline comments
* fix(onboarding): constrain Cline Pass selection and clear stale subscribe redirect
Addresses review findings:
- Never save a non-Cline-Pass model id under the cline-pass provider:
Cline Pass selection no longer falls back to a free model when the
Cline Pass list is empty, the generic model search is hidden for Cline
Pass, finishOnboarding guards on a cline-pass/ id, and the CTA is
disabled (with an empty state) when no Cline Pass model is available.
- Clear the pending subscription redirect when the user backs out, signs
in, or navigates away from Cline Pass, and re-check userType in the
redirect effect so a late auth update can't force the paid flow.
* fix(onboarding): add userType to handleFooterAction deps
The signup handler reads userType (to set the pending Cline Pass
subscribe flag); make that dependency explicit rather than relying on
the transitive finishOnboarding dependency.
* fix(onboarding): gate Cline Pass model data by feature flag
* fix(onboarding): address Greptile review on Cline Pass signup
- Log when the Cline Pass provider write is skipped due to an unexpected
(non cline-pass/) model id, so the otherwise-silent no-op is observable.
- Open the subscription page for already-authenticated users by invoking
the redirect helper directly after accountLoginClicked resolves, not
only via the auth effect (which never re-runs when clineUser is
unchanged).
* fix(onboarding): preserve ClinePass selection through login + one-word branding
- handleAuthCallback no longer forces the provider back to 'cline' on
login when the user picked Cline Pass during onboarding; it preserves a
'cline-pass' selection per mode. Only 'cline-pass' configs are affected
(which require the ext-cline-pass flag), so all other logins are
unchanged.
- Open the subscription page solely from the clineUser auth effect; the
signup action no longer also calls it directly (prevents the login
browser and subscribe page opening at once / dead-ends for already-
authenticated users). Signup flow is otherwise untouched.
- Rename user-facing 'Cline Pass' to one-word 'ClinePass' (card titles,
step title, empty state) and the model group label to 'clinepass'.
* chore(onboarding): normalize ClinePass branding in comments, trim verbose comments
* fix(merge): resolve ApiOptions redeclare + apply biome semicolon formatting
- Remove duplicate CLINE_PASS_FEATURE_FLAG const in ApiOptions.tsx (the
shared import from constants/featureFlags supersedes main's local const).
- Apply biome format (semicolons) to onboarding/controller files so they
match main's current style and pass Quality Checks.
* fix: restore clean no-semicolon formatting, keep only real ClinePass changes
The previous merge-recovery commit ran a local biome that incorrectly added
semicolons across entire files, bloating the diff by ~2000 LOC. Restore the
files to their clean pre-format state (matching main's asNeeded style) so the
diff reflects only the actual ClinePass onboarding changes (~420 LOC). Keeps
the handleAuthCallback provider-preservation fix and the ApiOptions duplicate
const removal.
* chore(onboarding): trim redundant inline comments
* chore: match main in refreshClineRecommendedModels (drop snake_case cline_pass handling)
* chore: trim featureFlags.ts comment
* fix(onboarding): open ClinePass subscribe page from App, not OnboardingView
handleAuthCallback marks the welcome view completed (unmounting OnboardingView)
before it pushes the auth-status update that sets clineUser. The redirect effect
lived in OnboardingView, so the pending-subscribe intent was lost on unmount and
the subscription page never opened for new ClinePass users.
Move the pending intent to a module-level store (clinePassSubscribe.ts) and run
the redirect from an effect in App, which outlives the onboarding unmount.
---------
Co-authored-by: BarreiroT <tomasmbarreiroi@gmail.com>
* Make sections expandable and add ClinePass
* fix label
* Map clinePass models to clinePass and the rest to cline
* gate the models behind the feature flag
* Do not allow custom model on cline pass
* Do not show the count on the mode list
* fix clinepass model list
* fix focus when expanding a section
* update the model data when the provider doesn't match
* Add ClinePass to the onboarding screen
* Fix the auth flow not starting
* Hide option behind a feature flag
* Update icon
* Remove unrelated changes
* Hide the custom model id
* fix model names
* remove custom model id option
* fix tests
* Fix names
* Display the clinepass models in the onboarding
* Throw a specific error when the user isn't subscribed
* properly render the error message
* fix error detection
* refactor
* Update the ResponseErrorHandler type
* re-add trailing slash
* Clear organization on ClinePass selection on the VSCode extension
* Disable remote config if ClinePass is selected
* Disable remote config if ClinePass is selected
* Revert formatting changes
* fix issue
Update the Fireworks model registry in apps/vscode/src/shared/api.ts:
- Add accounts/fireworks/models/glm-5p2: new general-purpose model with
a 1,048,576-token context window (131,072 output).
- Add accounts/fireworks/routers/kimi-k2p6-fast: standardizes the
Kimi K2.6 router on the `-fast` naming convention used for /routers.
The existing kimi-k2p6-turbo entry is retained for now to avoid
breaking user workflows; the turbo variant is expected to be removed
in a future release once the fast variant is the only one served.
- Correct the cache-read price for accounts/fireworks/models/deepseek-v4-flash
from 0.03 to 0.028 to match the published rate.
Pricing sourced from https://docs.fireworks.ai/serverless/pricing.
* Add Cline Pass provider to VS Code extension
* Fix the model picker
* ClinePass specific options
* Add feature flag to the api options
* Extend flag usage
* fix type error
* Use the right model info
* Fix tests
* Hide price info for clinePass models
* Add friendly Cline Pass entitlement error UI
When a Cline Pass model returns a 403 ENTITLEMENT_ERROR (user not subscribed to the required model plan), the chat dumped the raw serialized error JSON and pointlessly auto-retried it.
- Add ClineErrorType.Entitlement, classified before the generic 403/auth path.
- Skip auto-retry (and the retries-exhausted message) for entitlement errors.
- Render a dedicated EntitlementError card: friendly headline, env-aware 'Get Cline Pass' subscribe link (clineUser.appBaseUrl, falling back to production), and a Retry button; backend detail is shown as muted support text.
- Add unit/component tests and a Storybook story.
* Scope entitlement to individual case; fix path-prefixed subscribe URL
- ClineError: only classify the individual 'not subscribed' ENTITLEMENT_ERROR as Entitlement (checks message and details.message). Org-account variant falls through to generic handling rather than showing a misleading 'Get Cline Pass' card.
- EntitlementError: build the subscribe URL with a relative path against a trailing-slash-normalized base so path-prefixed self-hosted/proxy app URLs (e.g. https://proxy.example.com/cline/app) are preserved instead of resetting to origin.
- Tests: add org-exclusion case, path-prefixed URL case, and assert the retry askResponse payload (yesButtonClicked).
* Trim redundant inline comments
* Add provider test: pre-stream 403 entitlement error classifies correctly
Documents and locks in that a 403 ENTITLEMENT_ERROR (which rejects completions.create before streaming, as an OpenAI SDK APIError) propagates through ClineHandler with the code intact so ClineError classifies it as Entitlement. Confirms the error does not rely on the mid-stream chunk.error path.
* Guard subscribe URL build against malformed appBaseUrl
Wrap new URL() in try/catch so an invalid appBaseUrl from the auth context omits the subscribe link instead of throwing TypeError and crashing the EntitlementError card mid-render. Addresses Greptile review feedback; adds a malformed-URL test.
* test: trim entitlement error UI coverage
* Use one-word 'ClinePass' in user-facing copy
Renames the display text in the entitlement card (headline, helper, button) and related tests/story/comments from 'Cline Pass' to 'ClinePass'. Also normalizes EntitlementError.test.tsx formatting to the webview Biome style.
* fix: skip subagent retries for ClinePass entitlement errors
---------
Co-authored-by: BarreiroT <tomasmbarreiroi@gmail.com>
Co-authored-by: Tomás Barreiro <52393857+BarreiroT@users.noreply.github.com>
* Add Cline Pass provider to VS Code extension
* Fix the model picker
* ClinePass specific options
* Add feature flag to the api options
* Extend flag usage
* fix type error
* Use the right model info
* Fix tests
* Hide price info for clinePass models
* refactor
* remove redundancy
* fix syncModeConfigurations
* Make sections expandable and add ClinePass
* fix label
* Map clinePass models to clinePass and the rest to cline
* gate the models behind the feature flag
* Do not allow custom model on cline pass
* Do not show the count on the mode list
* fix clinepass model list
* fix focus when expanding a section
* update the model data when the provider doesn't match
* Add ClinePass to the onboarding screen
* Fix the auth flow not starting
* Hide option behind a feature flag
* Update icon
* Remove unrelated changes
* Hide the custom model id
* fix model names
* remove custom model id option
* fix tests
* Fix names
* Display the clinepass models in the onboarding
* feat(cli): add cline skill command aliasing the open skills CLI
Adds a 'cline skill' command that forwards to Vercel's open skills CLI
via 'npx -y skills@latest <args>', giving parity with 'cline plugin
install' and 'cline mcp' without reimplementing skill installation.
install/add/i default to '--agent cline' (unless the user passes their
own -a/--agent) so installs land in a directory Cline already scans;
use/list/remove pass through verbatim.
* fix(cli): scope skill update to cline
* Make sections expandable and add ClinePass
* fix label
* Map clinePass models to clinePass and the rest to cline
* gate the models behind the feature flag
* Do not allow custom model on cline pass
* Do not show the count on the mode list
* fix clinepass model list
* fix focus when expanding a section
* update the model data when the provider doesn't match
* Update sdk/packages/core/src/services/llms/cline-recommended-models.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* style: format Cline recommended models fallback
* Build models
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
The VS Code extension's Fireworks model list is out of date compared to the current active models available on the Fireworks platform. This commit updates the registry to match the current model lineup, ensuring users can select from the latest available models.
Changes:
- Add Kimi K2.7 Code (accounts/fireworks/models/kimi-k2p7-code)
- Add Kimi K2.7 Code Fast (accounts/fireworks/routers/kimi-k2p7-code-fast)
- Add Qwen 3.7 Plus (accounts/fireworks/models/qwen3p7-plus)
- Add MiniMax M3 (accounts/fireworks/models/minimax-m3)
- Remove deprecated Kimi K2.5 (accounts/fireworks/models/kimi-k2p5)
- Remove deprecated MiniMax M2.5 (accounts/fireworks/models/minimax-m2p5)
- Remove deprecated Qwen 3.6 Plus (accounts/fireworks/models/qwen3p6-plus)
The default model remains accounts/fireworks/models/kimi-k2p6.
Files:
- apps/vscode/src/shared/api.ts
* fix(sdk): search output cap + bash executor fixes (follow-up to #11480)
Slimmed from the original revision: the aggregate per-call output budget
is deferred to its own follow-up PR. What remains:
- cap search_codebase output at 48k chars per query with a middle-cut
notice teaching the model to narrow the pattern (robinnewhouse's
finding on #11480 — search was the last uncapped tool)
- rename bash executor maxOutputBytes -> maxOutputChars; the limit was
always enforced in characters. Deprecated alias retained; stale
@default annotation fixed
- flush the rolling collector's StringDecoder at end-of-stream so
trailing incomplete multibyte sequences are not silently dropped
(greptile's finding on #11480)
- decouple output-limits comments from MessageBuilder's specific
backstop value; the durable invariant is that truncation notices live
in the preserved head/tail of an entry
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/ygz2qho62ub6o8v1zhjvdktt
* test(sdk): cover search output cap
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* Centralize OAuth management to the SDK
* Update mock
* Cleanup TUI cline-account logic
* clean save credentails
* Remove unused code
* Reduce mocks
* use normalizeStoredAccessToken
* Add Cline Pass
* Properly read storageProviderId
* Use the name for the model generation
* Use the model for the capabilities lookup
* Fix capability discovery
* Fix getLastUsedProviderSettings
* remove the provider id from the resolveWithSingleFlight return
* Fix tests
* Remove the entry.name check
* Execute model API calls separetely
* Hide Cline Pass pricing
* update model list
* Unselect the org when selecting Cline Pass
* deduplicate onProviderChange calls
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* Centralize OAuth management to the SDK
* Update mock
* Cleanup TUI cline-account logic
* clean save credentails
* Remove unused code
* Reduce mocks
* use normalizeStoredAccessToken
* Add Cline Pass
* Properly read storageProviderId
* Use the name for the model generation
* Use the model for the capabilities lookup
* Fix capability discovery
* Fix getLastUsedProviderSettings
* remove the provider id from the resolveWithSingleFlight return
* Fix tests
* Remove the entry.name check
* Execute model API calls separetely
* Hide Cline Pass pricing
* Display cline-pass only if the feature flag is enabled
* unselect cline pass when the feature flag is off
* Store and read feature flag cache
* Add comment
* Do not return userId
* fix tests
* Revert unrelated changes
* Centralize OAuth management to the SDK
* Update mock
* Cleanup TUI cline-account logic
* clean save credentails
* Remove unused code
* Reduce mocks
* use normalizeStoredAccessToken
* Add Cline Pass
* Properly read storageProviderId
* Use the name for the model generation
* Use the model for the capabilities lookup
* Fix capability discovery
* Fix getLastUsedProviderSettings
* remove the provider id from the resolveWithSingleFlight return
* Fix tests
* Remove the entry.name check
* Execute model API calls separetely
* Hide Cline Pass pricing
* update model list
* Address PR feedback
* revert unrelated changes
* Update comment
* Update check
Tool outputs previously entered conversation history nearly unbounded
(1MB command output, whole-file reads up to 10MB) and were re-sent on
every subsequent request. Evals showed single observations of 350KB-3.2MB
dominating token spend versus opencode's 50KB-bounded observations.
- run_commands: combined stdout/stderr capped at 48,000 chars with
head+tail sampling (middle elided with a notice reporting total size),
since failures usually live at the end of build/test output. Failing
commands carry the notice in stderr errors too. Streams decode through
StringDecoder so multibyte chars split across chunks stay intact.
- read_files: whole-file and oversized-range reads windowed to 2,000
lines / 48,000 chars with a notice reporting total line count and how
to paginate via start_line/end_line. Per-line cap of 2,000 chars
defangs minified files. In-window ranged reads are byte-for-byte
unchanged; the 10MB stat guard stays.
- Shared constants live in executors/output-limits.ts, sized below
MessageBuilder's 50,000 per-string backstop so source notices survive
provider-request truncation intact. Tool descriptions document the
windowing so the model pages or filters instead of retrying.
Companion to #11463/#11465: those bound provider requests at build time;
this bounds what enters history at the source and gives the model a
recovery path.
* Introduce PostHog as a Feature Flag provider
* Set-up auth after login
* Update the context when something changes in the CLI
* Make the distinctId not be optional
* Dispose of the feature flag service
* Remove the distinctId from the options
* get rid of isSharedClient
* Remove timeoutMs from the posthog options
* Rename functions to not refer cli
* Change the PostHogFeatureFlagsProvider API
* Add the FeatureFlagService to the SDK
* Fix comments
* Dispose of the telemetry service
* Dispose of the feature flag service
* Address PR feedback
* Stop the polling early if a new one is triggered with another user id
* Address PR feedback
* Dispose of the feature flag service
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* test(sdk): add regression tests for structured ToolOperationResult truncation
MessageBuilder tests only covered string and {type:
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/mrbt2b39jfn370scr4g0ivzo"text"} tool-result
content, not the structured ToolOperationResult[] shape the default tools
(run_commands, read_files, search_codebase) actually emit. Those entries
are plain {query, result, success} objects with no type discriminator, so
the token-bloat path they create was unprotected by tests.
Adds regression tests using the real structured shape: huge result, huge
query, huge read_files payload, aggregate budget across multiple results,
mutation safety, and provider-formatted AI SDK payload size. Assertions
are on actual serialized payload sizes, not transcript shape.
The new tests fail at this commit by design; the following commit makes
them pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(sdk): truncate structured ToolOperationResult strings in MessageBuilder
The runtime stores structured tool outputs (ToolOperationResult[] from
run_commands/read_files/search_codebase) directly as the tool_result
content array (agentPartToContentBlock casts the array straight through).
Those entries have no type discriminator, so MessageBuilder's per-result
truncation, aggregate byte counting, and budget truncation all skipped
them — multi-megabyte command outputs and file reads were JSON-serialized
in full into every subsequent provider request.
MessageBuilder now deep-truncates nested strings inside structured
entries (middle truncation, preserving head and tail), counts them
against the aggregate text budget, collects them as budget-truncation
candidates, and deep-clones them before mutation so the original
conversation history stays untouched. Image blocks are skipped so base64
payloads survive intact.
Real-inference A/B on openrouter:minimax/minimax-m2.7 with realistic
structured payloads: 58.7% overall input-token reduction (82.6% on a
single huge command output) with identical answer correctness.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/mrbt2b39jfn370scr4g0ivzo
* fix(sdk): include fetch_web_content in MessageBuilder truncation targets
Review feedback: fetch_web_content also returns ToolOperationResult[] and
its executor allows responses up to 5MB, but the tool was missing from
TARGET_TOOL_NAMES, so a single web fetch could still bloat every
subsequent provider request. Adds the tool to the truncation target set
with a regression test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/mrbt2b39jfn370scr4g0ivzo
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The run_commands tool result's query field repeated the entire executed
command, which already exists verbatim in the assistant tool-call input.
For large generated-file commands (e.g. cat <<EOF heredocs) this
duplicated thousands of chars of source text into every subsequent
provider request.
Bound the provider-facing echo to a 200-char preview plus a truncation
note pointing at the tool call input. Short commands pass through
unchanged. Applies to both createBashTool and createWindowsShellTool,
on success and error paths.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/og840mbjqaog4zita8m0262m
The SDK 0.50.1 upgrade widened convertToOpenAiMessages to take
Anthropic.Messages.MessageParam[], which left the ClineStorageMessage
import referenced only in comments. tsc does not flag unused imports in
this config, but biome lint does, and it blocked the 3.89.2 publish.
VS Code 1.123.0 bumped its bundled runtime from Node 22 to Node 24
(Electron 39 to 42). The Anthropic provider broke on the updated editor
because the old SDK (<=0.41.x) shipped a legacy runtime built on
node-fetch and an internal _shims layer that does not work under Node 24.
0.50.1 is the first SDK release rewritten on top of the platform's native
fetch: it has zero runtime dependencies (no node-fetch, no _shims), which
removes the incompatibility. This is the actual fix; the earlier 0.40.1
bump did not change the runtime architecture.
The 0.50.1 type changes are minimal:
- Usage gained a required server_tool_use field, so fabricated Usage
objects in the gemini/o1/openai/vscode-lm transforms set it to null.
- ContentBlockParam widened, so Anthropic.MessageParam is no longer
structurally assignable to ClineStorageMessage. Handled by narrowing
the two transform helpers that only ever receive Cline history
(sanitizeAnthropicMessages, convertAnthropicMessageToGemini), typing
getSavedApiConversationHistory as the Cline history it reads, and
narrowing ContextManager's loosely-typed truncated output back to
ClineStorageMessage at the two provider/hook boundaries.
VS Code 1.123.0 bumped its bundled runtime from Node 22 to Node 24
(Electron 39 to 42). The extension passes VS Code's globalThis.fetch to
every provider SDK, but @anthropic-ai/sdk was pinned at 0.37.0, which
predates the SDK's native-fetch rewrite and relies on legacy _shims
runtime detection that breaks under Node 24. The modern OpenAI and Gemini
SDKs are unaffected, which is why only the Anthropic provider broke after
users updated VS Code.
Bump to ^0.40.1, the first release with the native-fetch rewrite that
restores Node 24 compatibility, while staying short of the latest line's
larger breaking surface.
The only code change the bump requires is narrowing the image source type:
ImageBlockParam.source widened from a base64-only type to
Base64ImageSource | URLImageSource. Add a getBase64ImageSource/
getImageDataUrl helper in shared/messages/content.ts and route the
provider transforms through it. Cline only ever produces base64 image
sources, so behavior is unchanged; the helper emits the same data URL the
inline code did.
* feat: Enforce a production singleton Cline Hub
This PR changes local Hub startup/discovery so production uses one stable daemon per user machine instead of silently creating additional hubs on random ports.
Replace resolveSharedHubOwnerContext with resolveProductionHubOwnerContext
across doctor and hub server lifecycle management to scope hub discovery
to the production owner.
Additionally:
- Preserve and propagate auth tokens when retiring incompatible hubs
- Throw a clear error when a compatible hub is already running but its
discovery record is missing, guiding users to run 'cline doctor fix'
- Gate port fallback behind an explicit allowPortFallback override
- Update tests to mock the new production hub owner context
* patches
* fix
* hasExplicitPort
* Restored daemon cron startup, made discovery auth tokens required again, and fixed graceful hub stop/restart paths to use the selected production/shared owner context.
* clean up
* patches
* fix Polynomial regular expression
* test
* fix: require explicit hub port fallback in production
* fix(cli): stop pgrep from parsing the hub daemon marker as an option
pgrep treats the "--cline-hub-daemon" pattern as an unknown long option
and exits 2, so doctor never found stale daemons from compiled-binary
installs, which are exactly the processes 'cline doctor fix' is told to
clean up. Pass "--" before the pattern to end option parsing.
* fix(hub): retire legacy shared-owner hubs on production startup
Pre-singleton production builds tracked the local hub under the shared
owner discovery path and spawned daemons on random fallback ports. The
production owner context never reads that path, so upgrades would leave
those daemons running indefinitely with no way to reuse or stop them.
Retire the recorded legacy hub (its record carries the auth token and
pid needed for a graceful stop) and clear the legacy record before
resolving the production hub.
* refactor(hub): simplify stale discovery clearing, share capability list
shouldClearStaleHubDiscovery was only ever called with
discoveredVerified=false (the true assignment sits on a return path),
so the expected-hub probe and compatibility check had no effect and the
condition reduced to "a discovery record exists and was not reused".
Replace it with a plain conditional and drop the tests that exercised
unreachable states.
Also move the hub capability list into a typed HUB_CAPABILITIES
constant in @cline/shared next to HubCapabilityName so the server
cannot drift from the type.
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* fix(cli): suppress flickering console windows on Windows by setting windowsHide on child processes
On Windows, child_process.spawn/execFile default to windowsHide: false,
so console-subsystem children (powershell, rg, git, node, npm) can
allocate a new visible console window - guaranteed when detached: true
is used. In the CLI this caused constant short-lived window flashes
from run_commands, the git status bar polling, ripgrep searches and
indexing, clipboard helpers, and hook/plugin node subprocesses.
Set windowsHide: true (CREATE_NO_WINDOW; a no-op on non-Windows) on all
remaining spawn/spawnSync/execFile call sites in the SDK core, CLI,
Cline Hub, and example plugins, matching the pattern already used by
the MCP client, checkpoint-hooks, and StandaloneTerminalProcess.
* Update apps/cli/src/commands/kanban.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix(llms): avoid disabled reasoning for fable 5
* fix(llms): route fable reasoning by family
* Revert "fix(llms): route fable reasoning by family"
This reverts commit 6dd4e5dcf5.
* fix(llms): match claude fable reasoning workaround broadly
* fix(core): configured agent support as subagent tools
Introduce configured agent config parsing and tool creation for
subagents. Agent configs are defined via YAML frontmatter files
specifying name, description, tools, skills, model, and system prompt.
- Add `configured-agent-config` for loading and parsing agent
definitions from search paths
- Add configured agent tool factory that wraps delegated agents as
named subagent tools with policy and approval support
* patch
* patches
* fixes
* Infinite loop when YAML block is a non-object fix
* apply feedback
Forwarded host requestToolApproval into configured subagents.
Used the resolved workspace config root for configured-agent skills discovery.
Split configured-agent skill loading from root-session skills enablement.
Added host lifecycle/event plumbing for configured subagents via shared subagent callbacks.
Made UserInstructionConfigService.createSkillsExecutor optional and guarded its use.
* threaded
* test(core): cover configured subagent skill isolation (#11396)
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
The Fable 5 PR (#11385) made claude-fable-5 the newest anthropic model,
which sorts first in the generated catalog. Legacy provider migration
defaults to the first catalog model, so the migrated default changed from
claude-opus-4-8 to claude-fable-5. Update the test expectation to match.
* Improve bug report form: rename surface dropdown, add IDE/CLI diagnostics
Rename the 'Plugin Type' dropdown to 'Cline Surface' since CLI is not a plugin; the option values keep each choice unambiguous.
Add an 'IDE / CLI Diagnostics' field with per-surface copy-paste steps for About info (VSCode Help/About, JetBrains Help/About Copy button) and a CLI exception using 'cline --version'. System Information is left as-is; minor overlap is acceptable.
* Update repo-label-issues workflow for renamed Cline Surface field
The auto-labeler matches the rendered '### Plugin Type' heading. Since the form label was renamed to 'Cline Surface', update the three regexes so JetBrains/VS Code/CLI labels keep applying.
* doc(sdk): add host logger support in plugin examples
Add examples to use the exposed `ctx.logger` to plugins via the `setup` second argument for
diagnostics. Wire logging into the agents-squad example to record setup,
subagent starts, follow-ups, and async failures, with a `logPluginError`
helper that falls back to severity-tagged logs. Update README with
logger usage guidance and examples.
* patches
* fix: empty SDK message content replay for Bedrock CLINE-2373
This fixes SDK message formatting when persisted conversation history contains an empty user or assistant message, such as after an interrupted task is resumed.
Instead of dropping the message turn, the SDK now preserves it and inserts a text content block:
ERROR: EMPTY CONTENT
This prevents providers like Amazon Bedrock from rejecting replayed history with empty content arrays while avoiding message removal that could affect provider turn ordering.
* Exported EMPTY_CONTENT_TEXT from @cline/shared so core/shared use one constant
* fix(cli): connector thread session routing & stale hub session
Fix connector thread session routing and stale hub session recovery
**PR Description**
This fixes connector messages from separate chat threads being routed into the wrong active runtime session.
**Issue**
In Slack, if a user sent a message in a different thread while another thread was still processing, the new message could be treated as a steer message for the active task. Users could also see errors like:
```text
Slack bridge error: session not found: 1780596180501_ms45m
```
when a connector thread had a persisted session id that no longer existed in the hub, such as after a hub restart.
**Cause**
Connector conversation bindings and active turn queues were using participant identity as the primary key in several paths. That allowed messages from the same user in different chat threads to resolve to the same connector session/active turn.
Separately, persisted connector `sessionId` values were trusted without checking whether the hub still had that runtime session. After a hub restart, the connector could try to send input to a stale session id.
**Fix**
- Store connector conversation bindings by thread id instead of participant key.
- Key connector active turn queues by thread id across Slack, Discord, Telegram, Google Chat, Linear, and WhatsApp adapters.
- Only treat a follow-up as a steer message when the active turn belongs to the same thread.
- Keep participant key/label as metadata instead of using it as the conversation binding key.
- Validate a persisted session id with the hub before reusing it.
- If the persisted session is missing, clear it from thread state and start a fresh runtime session.
- Update schedule delivery metadata to target thread ids while preserving participant metadata.
- Add regression coverage for cross-thread active sessions and stale persisted session ids.
**Verification**
```bash
bun -F @cline/cli typecheck
bunx vitest run apps/cli/src/connectors/connector-host.test.ts apps/cli/src/connectors/thread-bindings.test.ts apps/cli/src/connectors/adapters/slack.test.ts apps/cli/src/connectors/adapters/telegram.test.ts apps/cli/src/connectors/adapters/discord.test.ts apps/cli/src/connectors/adapters/gchat.test.ts apps/cli/src/connectors/adapters/linear.test.ts apps/cli/src/connectors/adapters/whatsapp.test.ts
```
* patches
deleteServerRPC and addRemoteServer wrote cline_mcp_settings.json without
setting isUpdatingClineSettings, so the chokidar settings watcher was not
suppressed during the plugin's own write. The watcher is configured with
atomic: true and awaitWriteFinish (stabilityThreshold 100ms); on Windows it
races the non-atomic writeFile, reads a transient/empty file, and
readAndValidateMcpSettingsFile() returns { mcpServers: {} }. updateServerConnections({})
then tears down every in-memory connection, so deleting one MCP server emptied
the whole list in the UI after navigating away and back (CLINE-2097).
Wrap both methods in the same guard the sibling RPCs already use
(toggleServerDisabledRPC, toggleToolAutoApproveRPC, updateServerTimeoutRPC):
set isUpdatingClineSettings = true before the write and clear it on a 300ms
timer in finally, so the delayed watcher "change" event is skipped. addRemoteServer
had the same latent omission and is fixed in the same change.
Known tradeoff (pre-existing, unchanged by this fix): the guard is a single
shared boolean cleared by uncoordinated 300ms timers, so two settings writes
within 300ms can clear the flag early. Because awaitWriteFinish only emits once
the file is stable, the worst case there is a redundant reconnect, not the
empty-list data loss this fixes. A deterministic guard (per-op token or
content-compare-and-skip in the watcher) is out of scope for this targeted fix.
Adds McpHub.deleteServerRPC.test.ts covering the user-visible symptom (delete
one of two servers -> remaining server still returned/persisted, list not empty)
and the guard contract (flag set during write, cleared after 300ms, cleared on
the not-found error path).
* docs(cli): release the SDK before the CLI in the publish-cli skill
Add a Step 0 to the publish-cli skill that gates a CLI release on an SDK
release when the SDK changed since its last release, and relocate the
publish-cli skill to the repo root.
Why release the SDK alongside the CLI: the CLI bundles the SDK source via
workspace:*, so the CLI always ships the latest SDK code, but the hub
daemon stamps a buildId that defaults to the @cline/core version and a
running hub is only respawned when that buildId changes. Bumping the SDK
version forces a stale hub to be retired and respawned with the new code.
It also keeps SDK releases on a regular cadence in step with the CLI.
Step 0 covers detecting unreleased sdk/packages changes, bumping the
shared SDK version + llms CHANGELOG, committing to main, kicking off
sdk-publish.yml on the latest channel, and waiting for it before cutting
the CLI release. Also fixes the now-stale working-directory note (commands
run from the repo root, not sdk/) and updates the DEVELOPMENT.md path.
* chore: move opentui skill to repo root
Relocate the opentui TUI skill from apps/cli to the repo root, matching
the real-dir + symlink convention used by the other root skills (real dir
in .agents/skills, symlink from .claude/skills).
* docs(sdk): reformat the SDK changelog and move it to sdk/CHANGELOG.md
The changelog covers all SDK packages (they share one version and release
together), so move it from sdk/packages/llms/ to the SDK root, parallel to
apps/cli/CHANGELOG.md. Reformat to match the CLI changelog: a titled
header with flat, version-only sections, newest on top, no dates, and no
Next Release bucket. The unreleased entry that bucket held is captured
from commits when the next SDK release is drafted. Update the publish-cli
skill to draft SDK notes from commits and prepend a ## <version> section
at sdk/CHANGELOG.md.
* fix(slack): normalize channel mentions to original post thread
Route top-level Slack channel mentions to the originating post thread so
replies land in the correct conversation. Add `resolveSlackChannelMentionThread`
to rewrite non-DM mention threads using the message's `thread_ts`/`ts` and
channel, while preserving DM threads and already-correct threads.
Includes unit tests covering normalization, no-op, and DM cases.
* thread id
* feat: update Fireworks model registry to improve Cline UX for Fireworks API users
The VS Code extension's Fireworks model list was significantly out of
date compared to the current active models available on the Fireworks
platform. This commit updates the registry to match the current model
lineup, ensuring users can select from the latest available models.
Changes:
- Default model: accounts/fireworks/models/kimi-k2p6 (was kimi-k2p5)
- SDK default: accounts/fireworks/models/kimi-k2p6 (was minimax-m2p5)
Removed 6 stale/phantom models no longer available:
- qwen3-vl-30b-a3b-thinking
- qwen3-vl-30b-a3b-instruct
- deepseek-v3p2
- glm-4p7
- glm-5
- minimax-m2p1
Added 9 missing models:
- accounts/fireworks/models/kimi-k2p6
- accounts/fireworks/routers/kimi-k2p6-turbo
- accounts/fireworks/models/deepseek-v4-flash
- accounts/fireworks/models/deepseek-v4-pro
- accounts/fireworks/models/glm-5p1
- accounts/fireworks/routers/glm-5p1-fast
- accounts/fireworks/models/minimax-m2p7
- accounts/fireworks/models/qwen3p6-plus
- accounts/fireworks/models/gpt-oss-20b
Fixed metadata for 3 overlapping models:
- kimi-k2p5: contextWindow 262144 → 256000, maxTokens 16384 → 256000
- minimax-m2p5: maxTokens 16384 → 196608
- gpt-oss-120b: maxTokens 16384 → 32768, cacheReadsPrice 0.01 → 0.015
All models now have cacheWritesPrice: 0 because Fireworks does not
charge a separate rate for prompt cache writes (cache writes are
billed at the standard input rate, matching the SDK catalog).
Three models remain in the UI but are scheduled for deprecation on
June 17 and will be removed then:
- accounts/fireworks/models/kimi-k2p5
- accounts/fireworks/models/minimax-m2p5
- accounts/fireworks/models/qwen3p6-plus
Files:
- apps/vscode/src/shared/api.ts
- apps/vscode/webview-ui/src/components/settings/__tests__/APIOptions.spec.tsx
- sdk/packages/llms/src/providers/builtins.ts
* fix: update qwen3p6-plus context window and maxTokens
* fix(cli): recover stale interactive sessions and suppress shutdown hook races
This fixes the CLI/TUI regression introduced between `3.0.14` and `3.0.15` where the interactive CLI could enter a broken state after stopping and restarting Cline Hub, then attempting to cancel a request with Escape.
The affected release window was:
- `49e8c1b32` / `v3.0.14`: known-good baseline
- `c33c3176e` / `v3.0.15`: release containing the regression
- `fad8271f4 feat: Cline Hub web app (#10969)`: relevant behavior change in the window
The Hub web app change introduced new Hub-backed runtime/session lifecycle behavior. After Ctrl+C or Hub shutdown, the CLI could still retain an `activeSessionId` that no longer existed in the Hub/runtime process. On the next interactive send, the CLI attempted to reuse that stale session and received `session not found`. Because cancellation also targeted the stale session, Escape stopped working and OpenTUI ended up receiving failures during input handling, which made the TUI look corrupted.
The same lifecycle issue also explains the Ctrl+C errors:
```text
error: hook dispatch failed: Hub connection closed (code=1006, reason=Connection ended)
error: WebSocket connection to 'ws://127.0.0.1:50168/hub' failed: Failed to connect
```
Those were caused by late hook dispatches racing against Hub shutdown. The CLI was still trying to send hook events over a Hub WebSocket that had already closed.
**What changed**
- Added missing-session recovery in the interactive runtime.
- Detects `session not found` / stale session errors.
- Reads any recoverable messages from the missing session.
- Clears the stale active session state.
- Starts a new interactive runtime session.
- Retries the current turn once against the fresh session.
- Made hook dispatch shutdown-aware.
- Runtime hooks now mark themselves as shutting down before session disposal.
- Hook dispatches are skipped once shutdown begins.
- Dispatch failures during shutdown are suppressed, since the Hub transport closing is expected at that point.
- Reordered CLI cleanup.
- Hooks are shut down before stopping/disposing runtime sessions.
- This prevents abort/stop lifecycle events from trying to dispatch over a closing Hub connection.
**Regression coverage**
Added tests for:
- Recovering from a disappeared active interactive session and retrying against a new session.
- Ensuring hook events are not dispatched after shutdown begins.
**Verification**
Passed:
```text
bunx vitest run apps/cli/src/utils/hooks.test.ts apps/cli/src/runtime/interactive/session-runtime.test.ts
bun -F @cline/cli typecheck
bun -F @cline/cli test:unit
bun -F @cline/cli test:e2e:cli:tui
git diff --check
```
* SessionNotFoundError
* fix(core): preserve stale session errors in hub runs
* clean up
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* feat(cli): add Slack socket mode support
Add socket mode as an alternative to webhook mode for Slack
connector, allowing connections without a public URL.
- Introduce `--connection` flag to select webhook or socket mode
- Add `--app-token` option for socket mode authentication
- Make signing secret and base URL conditional on webhook mode
- Add `parseSlackConnectionMode` with validation and tests
- Update CLI platform definition to support hybrid connection type
- Update README docs with socket mode usage examples
* use base-url and remove connection flag
* isSocketMode
* fix(core): use union schema for read files tool input validation
Move the normalizeReadFileRequests helper logic directly into the
read_files tool executor, replacing the legacy helper with inline
validation against ReadFilesInputUnionSchema. This ensures invalid
union inputs are rejected before reaching the executor.
Update tests to reflect validation behavior and add coverage for
rejecting invalid union inputs.
* add new schema support
* feat(llms,core): route custom registered handlers through the agent runtime
Expose the handler-registry helpers (hasRegisteredHandler, getRegisteredHandler,
getRegisteredHandlerAsync, isRegisteredHandlerAsync) from @cline/llms, and have
core's createAgentModelFromConfig consult the registry: when a handler is
registered for a provider, build it via createHandler and adapt its ApiHandler
surface onto the AgentModel contract (the inverse of the gateway's
toApiStreamChunk).
This lets hosts register provider handlers that need host-only dependencies
(e.g. a vscode.lm-backed handler) and have them used by the main agent loop,
not just standalone createHandler callers.
* fix(core): resolve registered handlers lazily and avoid double finish
Address review feedback:
- createAgentModelFromConfig built the handler eagerly with the sync
createHandler, which throws for providers registered via registerAsyncHandler.
The adapter now accepts a handler factory and resolves it on the first stream
via createHandlerAsync, supporting both sync- and async-registered handlers.
- Guard the adapter's catch-block finish with sawFinish so a handler that emits
an explicit done chunk and then throws does not produce two finish events.
* fix(core): preserve thought signatures and finish-reason semantics in adapter
Further review feedback on the ApiHandler -> AgentModel adapter:
- Reasoning and tool-call thought signatures are now surfaced under
metadata.thoughtSignature (the key downstream adapters read), instead of being
stored as metadata.signature / dropped.
- A done chunk whose incompleteReason indicates max output tokens now maps to
finish{reason:"max-tokens"} rather than "stop".
- A turn that ends with tool calls (no explicit done) now terminates as
finish{reason:"tool-calls"}, matching the gateway/AI-SDK adapters.
* Apply remaining changes
* fix(core): report lazy handler-factory rejection as a finish(error) event
The lazy handler resolution (await source()) ran outside the adapter's
try/catch, so a rejecting factory (e.g. when the host API is unavailable at
stream time) escaped as a raw generator exception instead of a terminal
finish{reason:"error"} event. Move the resolution inside the try block so all
failure paths converge on the same terminal finish.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
- user's who are signed in with oauth in old extension were not properly
migrating their token. this commit handles that
Co-authored-by: Max Paulus 🥪 <max@cline.bot>
* docs(sdk): add custom model provider plugin example
Add an OpenRouter-backed example plugin demonstrating the providers
capability and registerProvider. It registers an OpenAI-compatible
provider plus its model catalog with the gateway so the agent can run
inference against an endpoint Cline does not bundle.
Registers under a distinct id (openrouter-plugin) to avoid colliding
with the built-in openrouter provider.
* docs(sdk): drop redundant provider section from plugin examples readme
* docs(sdk): drop provider demo line from plugin examples readme
* fix: support plugin model providers
* docs: remove provider plugin demo
* docs: address provider example review
* Move the apps to the root dir
* Update all references from sdk/apps/ to apps/
* Update dependencies
* Install bun types
* Fix types
* Fix types
* Fix linter
* Ingore apps from vscode
* Fix security warning
* Fix windows install
* Enable windows dev mode
* Revert "Enable windows dev mode"
This reverts commit a46c99282e.
* Revert "Ingore apps from vscode"
This reverts commit 47f7b265d2.
* Revert "Fix windows install"
This reverts commit 1dabba1556.
* update the repo root
* fix root dir
* fix path
* fix other path
* Fix unrelated changes
* fix: address apps move follow-up blockers (#11228)
* fix: update root app command paths
* fix: include moved apps in root checks
* fix: clean up moved app path references
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
- Fold provider/model setup into a single `cline` run; drop the auth command
- Remove the /yolo on step from the Telegram setup
- Present scheduling as two clear options (Telegram chat vs terminal with
delivery flags)
- Clarify how to find the schedule id before triggering a test run
* docs(cli): add supply-chain scan alerts sample
Walkthrough for scheduling the Cline CLI to run Perplexity's Bumblebee
scanner and deliver compromise alerts to Telegram. Covers installing the
CLI, cloning/building Bumblebee and how it stays read-only, the Telegram
connector, and creating a scheduled scan that texts a clean/alert verdict.
* docs(cli): drop unsupported --delivery-thread from supply-chain sample
* feat(cli): bundle and serve Cline Hub dashboard with cline dashboard
Add the @cline/cline-hub workspace dependency to the CLI and build the
Hub webview as part of CLI packaging. Copy the generated dashboard assets
into platform-specific CLI distributions so the dashboard is available in
built artifacts.
Refactor the Cline Hub server startup into an exported function so the CLI
can start and stop the dashboard server programmatically.
* fix(cli): resolve dashboard webview in wrapper installs
Detect the platform-specific CLI package from the published wrapper layout
and use its bundled cline-hub webview assets when no explicit dist path is
set. Add test coverage for resolving assets via CLINE_WRAPPER_PATH.
* patches
* patch
* fix server detachHub on stop
Imported detachHub.
Changed ClineHubDashboardServer.stop to () => Promise<void>.
Made stop() idempotent with a stopped guard.
Clears the health interval.
Calls server.stop(true).
Always calls await detachHub(ctx) in a finally, so hub client teardown still happens if the HTTP server stop throws.
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* fix(plugin-sandbox): expose CLINE_PLUGIN_IMPORT_TIMEOUT_MS env override
The hardcoded 4000 ms importTimeoutMs default is too tight on Windows
cold-start; the plugin-sandbox tests already use 30_000 ms for the same
reason. This patch lets hosts raise the ceiling via env var without
touching code or adding a CLI flag, with explicit options.importTimeoutMs
still taking precedence.
Precedence: options.importTimeoutMs > env var > 4000.
Refs: #11065
* fix(plugin-sandbox): tighten env parsing + use vi.stubEnv (PR feedback)
- Number.parseInt accepts trailing garbage ("4000ms" -> 4000); switch
to Number() + Number.isInteger() so malformed env values fall back
to the default instead of silently consuming the numeric prefix.
- Replace manual process.env save/restore in the regression test with
the idiomatic vi.stubEnv() / vi.unstubAllEnvs() pattern.
Per Greptile review on #11084.
* docs(sdk): add env-blocker plugin example
Adds a beforeTool hook plugin that deterministically blocks the agent
from reading .env secret files via read_files, editor, or run_commands
(e.g. cat .env), while leaving .env.example/.sample/.template readable.
Demonstrates moving a security policy out of an AGENTS.md rule (a
suggestion the model can ignore) and into the execution path.
* docs(sdk): install env-blocker globally in usage examples
A secret-protection guard is most useful applied to every project, so
drop the --cwd . project-scoped install in favor of the global default.
* docs(sdk): trim env-blocker usage docs
* docs(sdk): limit env-blocker to read paths only
It is a read blocker, so only guard read_files and run_commands.
Drop the editor case (and with it the symmetric apply_patch concern),
keeping the example focused and simple.
* docs(sdk): rename env-blocker helpers for readability
collectPaths -> extractFilePaths, collectCommands -> extractShellCommands
so the beforeTool call sites read clearly at a glance.
* docs(sdk): rename commandTouchesEnv to commandReadsEnv
* docs(sdk): drop console.error from env-blocker hook
VS Code 1.122.0 migrated its bundled ripgrep from `@vscode/ripgrep` to
`@vscode/ripgrep-universal`, which ships per-platform/arch subdirectories
(`node_modules/@vscode/ripgrep-universal/bin/<platform>-<arch>/{rg|rg.exe}`)
instead of the previous flat `node_modules/@vscode/ripgrep/bin/{rg|rg.exe}`.
The migration commit (microsoft/vscode@bf19e5ca / @c4471e24) landed on
`release/1.122` and ships in stable 1.122.0+. Microsoft hit the identical
bug in their own sandbox engines and patched it in microsoft/vscode#317978;
our `getBinaryLocation` was still on the retired layout.
Symptom: on VS Code 1.122.x, all four `checkPath` probes in extension.ts
miss, `getBinaryLocation("rg")` throws `Could not find ripgrep binary`,
and `searchFiles` returns `{results: [], errorReason: "unknown"}`. The
@-mention picker shows "No results found" immediately, regardless of
workspace or query.
Telemetry confirmed the regression bisects cleanly to the VS Code
version boundary, not any Cline release — `mention_failed` events with
`errorType=unknown` jumped from ~300/week on 1.121.0 to ~100k/week on
1.122.0/1, while JetBrains versions (which don't use this code path)
stayed flat. Every historical Cline version is affected when the user
is on 1.122+.
Fix: probe the new `@vscode/ripgrep-universal/bin/<platform>-<arch>/`
layout first (both regular and `.asar.unpacked` variants), then fall
through to the four legacy probes so users on ≤1.121.x keep working.
`<platform>-<arch>` is `${process.platform}-${process.arch}`, matching
the directory naming Microsoft documented in #317978
(darwin-arm64, darwin-x64, linux-x64, linux-arm64, linux-arm,
linux-ia32, win32-x64, win32-arm64, win32-ia32, etc.).
This also closes the residual #11105 reports that survived #11166:
Yufeng's PR moved the failure mode from `unknown` to
`ripgrep_spawn_failed` (bare `rg`/`rg.exe` on PATH fallback) but didn't
restore actual functionality for users on 1.122.x — they got
spawn-ENOENT instead of file-not-found. With this patch the bundled
binary resolves correctly and ripgrep runs as before.
Refs: https://github.com/cline/cline/issues/11105
Refs: https://github.com/cline/cline/issues/11142
Refs: https://github.com/microsoft/vscode/pull/317978
* feat(plugin): support rule contributions in sandbox
Add plugin rule registration to the sandbox descriptor and handler state so
plugins can contribute static or dynamic rule content.
Update plugin installation to omit peer dependencies and use
legacy-peer-deps to avoid peer resolution failures during isolated installs.
* feat(cli): support participant mute targets in Discord
Resolve /mute and /unmute targets from Discord user mentions and raw
user IDs so a specific participant can be muted within a thread.
Update Discord system rules to guide agents toward thread-level and
participant-level mute commands, and add tests for target parsing.
* Update sdk/apps/cli/src/utils/chat-commands.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix(cli): normalize addressed bot command suffixes
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* fix(cli): clear connector sessions on hub shutdown
* fix: stop Discord connector after repeated errors
Added error tracking to Discord connector to prevent spam:
- Tracks errors by message within a 1-minute window
- After 3 identical errors, shuts down connector instead of posting
- Prevents repeated error messages flooding Discord channels
- Logs shutdown reason for debugging
* fix: address Greptile feedback
1. Error tracker now per-thread (includes thread.id in key)
- Prevents cross-thread error aggregation
- One thread having errors will not kill the whole connector
2. Use fixed time window instead of sliding window
- Track firstSeen timestamp, not just lastSeen
- Prevents indefinite spam from errors every 61s
- Window properly resets after ERROR_WINDOW_MS from first error
3. Remove redundant delete in clearBindingSessionIds
- binding.state.sessionId already deleted in earlier block
- Cleanup was misleading/unnecessary
* feat: Cline Hub web app
Add a Cline Hub app for monitoring connected clients, viewing and driving sessions, streaming assistant output, and restarting the local hub. Document local, LAN, and tunnel usage with room-secret gating, ignore generated Cline cache/config data, and update lockfile entries.
* feat: Cline Hub UI
* feat: provider config schema
* run command update
* Use Workspace versions
* fix: rename routines to schedules
* feat(schedule): add routine summary and update support
Include last execution data in routine schedule overviews and cache the
summary state in the UI to reduce unnecessary reloads.
Add support for updating routine schedules from the hub server, validate
required fields, and trigger schedules asynchronously after confirming they
exist.
* UI for Connectors
* Fix UI switch for telemetryOptOut
* Expands Recent Sessions UI - allow title update
* feat: Cline Hub routes
* Add "health" and "version" routes
* Refactor server.ts nto 17 focused modules
* Provider Model list search box
* Extensions -> Customizations
* fix: restore discord connector catalog
* fix
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* feat(cli): support participant mute targets in Discord
Resolve /mute and /unmute targets from Discord user mentions and raw
user IDs so a specific participant can be muted within a thread.
Update Discord system rules to guide agents toward thread-level and
participant-level mute commands, and add tests for target parsing.
* patches
* update prompt
* fix(cli): stabilize core tests on Windows
Avoid several Windows-specific failure modes in the core CLI test suite.
Vitest already runs test files inside worker pools. The workspace file indexer was lazily spawning a nested worker from a transformed TypeScript module via import.meta.url, which is fragile on Windows and can cause Vitest to report only a generic worker fork crash. Disable that worker path under VITEST and use the deterministic fallback indexer for tests.
Quote process.execPath in bash executor shell-string tests. Windows Node/Bun paths commonly contain spaces, so unquoted command strings can fail under PowerShell or cmd even though they work on Unix paths.
Make detached hub probing defensive by routing probeHubServer calls through a safe wrapper, so rejected or malformed probe results are treated as unreachable instead of destabilizing startup/prewarm flows.
Also clear CLINE_RUN_AS_HUB_DAEMON in daemon test setup so tests do not inherit daemon-mode state from the surrounding CLI environment except where explicitly set.
Validation: bunx vitest run --config vitest.config.ts src/hub/daemon/index.test.ts src/services/workspace/file-indexer.test.ts src/services/workspace/mention-enricher.test.ts src/extensions/tools/executors/bash.test.ts --reporter=dot
Validation: bun run typecheck
Validation: bun run test:unit
* patch
* fix(cli): bind discord sessions to individual message authors
Resolve Discord participants from normalized message author data and persist
participant-specific thread state in bindings. Restore or create sessions per
participant so different Discord users do not accidentally share chat state.
Also add coverage for bot author handling and owner user configuration.
* patches
* fix(cli): steer active connector sessions across turn keys
Detect active connector turns by session ID when the current turn key
does not match, so replies steer the existing runtime session instead of
starting a duplicate session.
Also treat queued runtime turns as a non-error completion and log the
queued state for connector transports.
* fix(cli): steer active connector sessions across turn keys
Detect active connector turns by session ID when the current turn key
does not match, so replies steer the existing runtime session instead of
starting a duplicate session.
Also treat queued runtime turns as a non-error completion and log the
queued state for connector transports.
* add /idel
* fix(cli): bind discord sessions to individual message authors
Resolve Discord participants from normalized message author data and persist
participant-specific thread state in bindings. Restore or create sessions per
participant so different Discord users do not accidentally share chat state.
Also add coverage for bot author handling and owner user configuration.
* patches
Eve Killaby (@candieduniverse) has left Cline; transfer her /.github/ codeowner slot to @dominiccooney so .github changes still have four code owners able to approve.
Add claude-opus-4-8 (200k) and claude-opus-4-8:1m model variants across the
Anthropic, Claude Code, Bedrock, and Vertex catalogs, mirroring the Opus 4.7
setup (same pricing, 1M tiers, global endpoint, adaptive thinking).
- Wire the OpenRouter/Vercel AI Gateway 1m suffix handling and Cline/OpenRouter
model refresh derivation for anthropic/claude-opus-4.8
- Register 4.8 in adaptive thinking detection so it uses the reasoning-effort
selector path
- Bump the Claude Code "opus" alias to 4.8
- Add context window switchers in the Cline and OpenRouter model pickers
- Add provider tests for the new model ids
* ci: gate ext-jb-test-integration auto-trigger on PR author association
Extend the existing MEMBER/OWNER/COLLABORATOR allow-list (already used
for the /test-jetbrains comment path) to pull_request_target [opened,
reopened] as well, so the same trust model applies regardless of how
the workflow is triggered. PRs from non-trusted authors no longer
auto-trigger; a maintainer can still opt them in via /test-jetbrains.
* ci: replace hardcoded app-id with CLINE_JETBRAINS_WORKFLOW_ID var
Matches the convention already in use in cline/intellij-plugin and lets us change the App ID without touching workflow code.
* Update .github/workflows/ext-jb-test-integration.yml
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* ci: rename CLINE_JETBRAINS_WORKFLOW_KEY to CLINE_JETBRAINS_APP_KEY
The secret holds a GitHub App private key. Matches the rename of the matching app-id var in the previous commit.
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Single-file plugins can only import Node builtins and @cline/*. As soon
as a plugin needs an npm dep it has to ship as a package. Adds one
sentence each to the writing-plugins guide (with dependencies in the
example package.json) and plugin-install (noting pluginPaths accepts a
package directory for fast iteration).
@@ -9,12 +9,13 @@ Use this skill when the user asks to release the CLI, publish `cline`, bump the
The CLI is npm-only. Do not add alternate distribution or signing steps.
> Working directory: this skill lives in the SDK sub-monorepo. Run `cd sdk` (from the repo root) before any of the shell commands below. Paths in commands and instructions (e.g. `apps/cli/package.json`, `bun release cli`) are written relative to `sdk/`.
> Working directory: run every command below from the repository root. Paths and scripts (e.g. `apps/cli/package.json`, `sdk/packages/`, `bun release cli`, `bun run version`) are written relative to the repo root.
The skill should guide the user through one release preparation flow, then offer the publish path options. The two normal publish paths are GitHub Actions and local publishing from an authenticated machine.
## Release contract
- SDK prerequisite: the CLI depends on the SDK via `workspace:*` (`@cline/core`, `@cline/shared`, and friends). If the SDK changed since its last release, release the SDK first and wait for it to finish publishing before releasing the CLI. See "Step 0: Release the SDK first if it changed" below.
- Version source: `apps/cli/package.json`.
- Main release tag: `cli-vX.Y.Z`, where `X.Y.Z` matches `apps/cli/package.json`.
@@ -30,8 +31,93 @@ The skill should guide the user through one release preparation flow, then offer
- Always ask before pushing commits or tags.
- Do not amend commits unless explicitly requested.
## Step 0: Release the SDK first if it changed
Do this before anything else in the Workflow below.
The CLI builds and ships against the SDK source in the monorepo (`workspace:*` for `@cline/core`, `@cline/shared`, and the rest), so a CLI release always contains the latest SDK code whether or not the SDK was released. The build and tests use that source too, not anything from npm. Releasing the SDK alongside the CLI is still worth doing for two reasons:
- Hub freshness. The hub daemon lives in `@cline/core` and stamps a `buildId` that defaults to the `@cline/core` package version (`resolveHubBuildId` in `sdk/packages/core/src/hub/discovery/index.ts`). A running hub is only retired and respawned when that `buildId` changes (`isCompatibleHubRecord` / `retireIncompatibleHub` in `sdk/packages/core/src/hub/daemon/index.ts`). So if the SDK code changed but the version did not, a user who upgrades the CLI keeps talking to their already-running hub, which is still executing the old SDK code. Bumping the SDK version makes the new CLI's `buildId` differ, so the stale hub is detected as incompatible and respawned with the fresh code.
- Release hygiene. We want regular SDK releases; cutting one whenever we cut a CLI release keeps the published SDK in step with what the CLI ships.
So when the SDK has changed, release it first (which bumps the `@cline/core` version), then cut the CLI release on top of that bump. Leave the CLI's SDK dependency as `workspace:*` — the fix is to release the SDK, not to pin the CLI.
1. Check for unreleased SDK changes.
```sh
git fetch origin --tags
git tag --list 'sdk/sdk/v*' 'sdk-v*' --sort=-v:refname | head -1
`sdk/<pkg>/v*` tags are created by the `sdk-publish.yml` workflow; `sdk-v*` tags are created by the local `bun release sdk` helper. Use whichever is newest as the baseline.
If `git log` prints no commits, the SDK is already up to date. Skip the rest of Step 0 and continue with the Workflow below.
If it prints commits, sanity-check the diff (ignore entries that are only the previous version-bump commit's lockfile or generated files), then release the SDK.
2. Decide the SDK version bump.
All SDK packages share one version, read from `sdk/packages/llms/package.json`. Ask whether this is patch, minor, major, or an explicit version. Patch is the default. Do not guess if the user has not made it clear.
3. Draft the SDK release notes and update the changelog.
Draft user-facing notes from the SDK commits found in step 1, translating commit messages into user-facing language (same approach as the CLI release notes below). Prepend a new `## <version>` section with those notes to the top of `sdk/CHANGELOG.md`, using the header format `## <version>` with no date — the same flat, newest-on-top format as `apps/cli/CHANGELOG.md`. This is the SDK changelog (all SDK packages share one version) and it is maintained by hand; the `sdk-publish.yml` workflow does not read it.
4. Bump versions and regenerate.
```sh
bun run version <version>
```
This bumps every SDK `package.json` to the new version, regenerates the lockfile and the generated model catalog, formats, and builds. Review the result.
5. Commit and push the bump to `main`.
The `sdk-publish.yml` workflow publishes the version that is committed on `main` and tags that commit, so the bump must land on `main` before the workflow runs.
```sh
git add -A
git commit -m "chore(sdk): release v<version>"
```
Ask before pushing:
```sh
git push origin HEAD
```
6. Trigger the SDK publish workflow on the `latest` channel.
```sh
gh workflow run sdk-publish.yml -f channel=latest -f confirm_publish=publish
gh run list --workflow=sdk-publish.yml --limit=1 --json databaseId,url,status,createdAt --jq '.[0]'
```
The workflow runs the SDK tests, publishes `@cline/shared`, `@cline/llms`, `@cline/agents`, `@cline/core`, and `@cline/sdk` to npm with the `latest` dist-tag in dependency order, and pushes `sdk/<pkg>/v<version>` git tags.
7. Wait for the SDK workflow to succeed before starting the CLI release.
```sh
gh run watch <run-id> --exit-status
```
Do not start the CLI release until this run has finished successfully. The CLI does not install the SDK from npm, but cutting the CLI release on top of a clean, completed SDK release keeps the two in step: the CLI release commit then sits on top of the `@cline/core` version bump, so the shipped CLI carries the new version that forces a running hub to respawn with the new code, and you are not building a CLI release on top of an SDK release that failed midway.
After the SDK release succeeds, pull `main` so the CLI release is prepared on top of the SDK version bump:
```sh
git checkout main && git pull --ff-only
```
Then continue with the Workflow below.
For a local SDK publish from an authenticated machine instead of the workflow, `bun release sdk <version>` exists, but prefer the `sdk-publish.yml` workflow for normal releases so the CLI release can gate on a single GitHub Actions run.
## Workflow
Complete Step 0 first. Only proceed once the SDK is released (or you confirmed no SDK release was needed).
1. Gather context.
```sh
@@ -46,10 +132,10 @@ Find the latest CLI tag. If there is no `cli-v*` tag, use the first relevant CLI
If the release includes broader SDK changes that affect the CLI, also inspect commits outside `apps/cli`.
The `sdk/packages` commits matter here even though the SDK was released separately in Step 0: the CLI bundles the SDK, so SDK changes ship in this CLI release too. Read those commits and fold anything user-relevant to the CLI into the release notes (provider/model updates, behavior changes, fixes the CLI inherits). Skip SDK changes that are purely internal or have no CLI-visible effect.
This repo uses **bun** for package management and task running, and **Node** as
the execution runtime. Both are correct at the same time; the distinction is the
source of most confusion, so keep it straight before editing scripts, configs,
docs, or comments.
## Use bun for tooling
-`bun install` (never `npm install` / `npm ci`)
-`bun run <script>` (never `npm run <script>`)
-`bunx <bin>` (never `npx <bin>`)
-`bun <file>.ts` to run a TS entrypoint directly (no `ts-node` / `tsx`)
-`bun esbuild.mjs` to drive the build (esbuild/vite are still the bundlers)
-`bun run --parallel ...` for parallel tasks
The root `bun.lock` is the single lockfile for the whole workspace, including
`apps/vscode`, `webview-ui`, and `testing-platform`. There are no per-package npm
lockfiles.
## Node is the runtime — do NOT rewrite these to bun
The build product runs on Node: the VS Code extension host loads
`dist/extension.js` as CommonJS under Node, and the standalone `cline-core` is a
Node process. The following are Node runtime/ABI references and are correct as-is:
| Reference | Why it is Node |
|-----------|----------------|
| esbuild `platform: "node"` / `target: "node..."` | The bundle targets the Node runtime (extension host, standalone core). |
| `TARGET_NODE_VERSION` (`scripts/package-standalone.mjs`) | Pins the Node ABI of the bundled standalone runtime (matches the JetBrains-packaged Node). |
| `prebuild-install --target=<node version>` | Downloads native `.node` binaries for that Node ABI. |
| `NODE_PATH=... node cline-core.js` | The standalone core is launched by Node, not bun. |
All via `POST localhost:19229/api` with `{"method":"...", "params":{...}}`:
- **`launch`** / **`shutdown`** — lifecycle
- **`ui.screenshot`** — screenshot to `/tmp/cline-debug/`; returns `{path}` — **use `read_file` on the path to examine, do NOT `open` the file** (Preview.app covers the VSCode window)
- **`web.evaluate`** `{expression}` — eval in webview
- **`web.post_message`** `{message}` — send postMessage to extension host via exposed vsCodeApi
- **`wait_for_pause`** `{timeout?}` — block until breakpoint hit
- **`ui.locator`** `{role?, testId?, text?, frame?}` — Playwright locator (auto-retries on stale sidebar frame)
- **`ui.react_input`** `{text, selector?, clear?, submit?}` — set React textarea value via `execCommand('insertText')`; works reliably across multiple tasks
- **⚠️ Dismiss promotional overlays FIRST**: On fresh launches, full-screen promo overlays block the sidebar. **Dismiss immediately after `ui.open_sidebar`**, before any other interaction or screenshot. May need to run twice:
- **Screenshots — don't open the file**: `ui.screenshot` and `ui.sidebar_screenshot` save PNGs to `/tmp/cline-debug/` and return the `{path}`. Use `read_file` on that path to examine screenshots. Running `open <path>` launches Preview.app on macOS which covers the VSCode window.
- **Scripts count = 0 after launch**: CDP connects after extension host starts, so scripts parsed during startup aren't tracked. Breakpoints still work via sourcemap resolution.
- **Port 9230**: Extension host inspector. If another VSCode instance uses this port, the harness will fail to connect. Kill other debug instances first.
- **macOS only** for now (Playwright Electron launch behavior).
- **Webview CDP**: `connect_webview` may fail depending on Electron version. `web.evaluate` still works via Playwright's `frame.evaluate()` fallback.
- **Sourcemap paths**: esbuild outputs relative paths like `../src/extension.ts` in the sourcemap. The resolver handles this, but if a file isn't found, use `ext.source_files` to see exact paths.
- **OAuth with fake codes**: Browser capture intercepts the URL but doesn't provide a valid auth code. For real OAuth testing, open the captured URL in a browser. For unit testing, mock the token exchange.
See `src/dev/debug-harness/README.md` for full API reference.
@@ -13,11 +13,56 @@ This file is the secret sauce for working effectively in this codebase. It captu
**What NOT to add:** Stuff you can figure out from reading a few files, obvious patterns, or standard practices. This file should be high-signal, not comprehensive.
## Miscellaneous
- This is a VS Code extension—check `package.json` for available scripts before trying to verify builds (e.g., `npm run compile`, not `npm run build`).
- The whole repo (including `apps/vscode`) uses **bun** for package management and task running. Emit `bun run X` / `bun install` / `bunx <bin>` / `bun file.ts`, never npm/npx. Node remains the *runtime* (VS Code's extension host and the standalone cline-core are Node), so Node-runtime tokens are legitimate and must not be "fixed" to bun — see @.clinerules/bun-and-node.md for the keep-list vs rewrite-list.
- Avoid provider-specific string matching / hardcoded provider branches when fixing provider/config plumbing. Prefer provider metadata, shared catalog/defaults, explicit protocol/client capabilities, or centralized normalization utilities that apply by data shape rather than `providerId === "..."`. If a provider exception seems necessary, stop and explain why instead of adding ad-hoc string matching.
- This is a VS Code extension—check `package.json` for available scripts before trying to verify builds (e.g., `bun run compile`, not `bun run build`).
- When creating PRs, contributors should not create changelog-entry files. Maintainers handle release versioning and changelog curation during the release process.
- When adding new feature flags, see this PR as a reference https://github.com/cline/cline/pull/7566
- Additional instructions about making requests: @.clinerules/network.md
## Searching the Codebase — Avoiding Build Output
Several directories contain build output or generated code that produces
noisy or unusable results with `search_files` / `grep`:
| Directory | What it is | Why it's a problem |
|-----------|-----------|-------------------|
| `out/` | esbuild bundle output | Mirrors `src/` structure as minified JS — every search gets duplicate hits on single-line files |
| `dist/` | Packaged extension | Entire extension bundled into one minified `extension.js` (~1 long line) |
When adding a new provider (e.g., "openai-codex"), you must update the proto conversion layer in THREE places or the provider will silently reset to Anthropic:
1.`proto/cline/models.proto` - Add to the `ApiProvider` enum (e.g., `OPENAI_CODEX = 40;`)
2.`convertApiProviderToProto()` in `src/shared/proto-conversions/models/api-configuration-conversion.ts` - Add case mapping string to proto enum
3.`convertProtoToApiProvider()` in the same file - Add case mapping proto enum back to string
**Why this matters:** Without these, the provider string hits the `default` case and returns `ANTHROPIC`. The webview, provider list, and handler all work fine, but the state silently resets when it round-trips through proto serialization. No error is thrown.
**Other files to update when adding a provider:**
-`src/shared/api.ts` - Add to `ApiProvider` union type, define models
-`src/shared/providers/providers.json` - Add to provider list for dropdown
-`src/core/api/index.ts` - Register handler in `createHandlerForProvider()`
-`webview-ui/src/components/settings/utils/providerUtils.ts` - Add cases in `getModelsForProvider()` and `normalizeApiConfiguration()`
-`webview-ui/src/utils/validate.ts` - Add validation case
## Responses API Providers (OpenAI Codex, OpenAI Native)
Providers using OpenAI's Responses API require native tool calling. XML tools don't work with the Responses API.
**Symptoms of broken native tool calling:**
- Tools get called multiple times (e.g., `ask_followup_question` asks the same question twice)
- Tool arguments get duplicated or malformed
- The model responds but tools aren't recognized
**Root causes to check:**
1.**Provider missing from `isNextGenModelProvider()`** in `src/utils/model-utils.ts`. The native variant matchers (e.g., `native-gpt-5/config.ts`) call this function. If your provider isn't in the list, the matcher returns false and falls back to XML tools.
2.**Model missing `apiFormat: ApiFormat.OPENAI_RESPONSES`** in its model info (`src/shared/api.ts`). This property signals that the model requires native tool calling. The task runner in `src/core/task/index.ts` checks this and forces `enableNativeToolCalls: true` regardless of user settings.
**When adding a new Responses API provider:**
1. Add provider to `isNextGenModelProvider()` list in `src/utils/model-utils.ts`
2. Set `apiFormat: ApiFormat.OPENAI_RESPONSES` on all models that use the Responses API
3. The variant matcher and task runner will handle the rest automatically
## Adding Tools to System Prompt
This is tricky—multiple prompt variants and configs. **Always search for existing similar tools first and follow their pattern.** Look at the full chain from prompt definition → variant configs → handler → UI before implementing.
1.**Add to `ClineDefaultTool` enum** in `src/shared/tools.ts`
2.**Tool definition** in `src/core/prompts/system-prompt/tools/` (create file like `generate_explanation.ts`)
- Define variants for each `ModelFamily` (generic, next-gen, xs, etc.)
- **Fallback behavior**: If a variant isn't defined for a model family, `ClineToolSet.getToolByNameWithFallback()` automatically falls back to GENERIC. So you only need to export `[GENERIC]` unless the tool needs model-specific behavior.
3.**Register in `src/core/prompts/system-prompt/tools/init.ts`** - Import and spread into `allToolVariants`
4.**Add to variant configs** - Each model family has its own config in `src/core/prompts/system-prompt/variants/*/config.ts`. Add your tool's enum to the `.tools()` list:
**How overrides work:** Variants can override components via `componentOverrides` in their `config.ts`, or provide a custom template in `template.ts` (e.g., `next-gen/template.ts` exports `rules_template`). If no override, the shared component from `components/` is used.
**Example: Adding a rule to RULES section**
1. Check if variant overrides rules: look for `rules_template` in `variants/*/template.ts` or `componentOverrides.RULES` in `config.ts`
2. If shared: modify `components/rules.ts`
3. If overridden: modify that variant's template
4. XS variant is special—has heavily condensed inline content in `template.ts`
**After any changes, regenerate snapshots:**
```bash
UPDATE_SNAPSHOTS=true npm run test:unit
```
Snapshots live in `__tests__/__snapshots__/`. Tests validate across model families and context variations (browser, MCP, focus chain).
Adding a new key to global state requires updates in multiple places. Missing any step causes silent failures.
Required steps:
1. Type definition in `src/shared/storage/state-keys.ts` - Add to `GlobalState` or `Settings` interface
2. Read from globalState in `src/core/storage/utils/state-helpers.ts`:
- Add `const myKey = context.globalState.get<GlobalStateAndSettings["myKey"]>("myKey")` in `readGlobalStateFromDisk()`
- Add to the return object: `myKey: myKey ?? defaultValue,`
3. StateManager handles read/write via `setGlobalState()`/`getGlobalStateKey()` after initialization
2. Add any default value or transform in `src/shared/storage/state-keys.ts` if the key needs one
3. Read and write the value through `StateManager` (`setGlobalState()` / `getGlobalStateKey()`) after initialization
Common mistake: Adding only the return value without the `context.globalState.get()` call. This compiles but the value is always `undefined` on load.
Persistent state is file-backed through `StateManager`; do not add new runtime reads or writes against VS Code `ExtensionContext` storage. That storage is only a legacy migration source.
Settings plumbing gotcha: if a key is user-toggleable from settings, wire both controller update paths:
- `src/core/controller/state/updateSettings.ts` for webview `updateSetting(...)`
@@ -153,28 +109,26 @@ Settings plumbing gotcha: if a key is user-toggleable from settings, wire both c
Missing one path causes a toggle to appear to change in one surface while the backend state stays unchanged.
Webview toggle gotcha: settings changes must also round-trip back in state payloads.
- Add the field to `UpdateSettingsRequest` in `proto/cline/state.proto` (for webview update requests), then run `npm run protos`
- Add the field to `UpdateSettingsRequest` in `proto/cline/state.proto` (for webview update requests), then run `bun run protos`
- Include the key in `Controller.getStateToPostToWebview()` (`src/core/controller/index.ts`)
- Ensure `ExtensionState` and webview defaults include the key (`src/shared/ExtensionMessage.ts`, `webview-ui/src/context/ExtensionStateContext.tsx`)
If this round-trip wiring is missing, the backend value can update but the toggle in webview appears stuck or reverts.
## StateManager Cache vs Direct globalState Access
StateManager uses an in-memory cache populated during `StateManager.initialize(context)` in `common.ts`. For most state, use `controller.stateManager.setGlobalState()`/`getGlobalStateKey()`.
StateManager uses an in-memory cache populated during `StateManager.initialize()` from file-backed storage. For most state, use `controller.stateManager.setGlobalState()`/`getGlobalStateKey()`.
Exception: State needed immediately at extension startup (before cache is ready)
Exception: host migration code may read legacy VS Code storage before file-backed storage is initialized.
When Window A sets state and immediately opens Window B, the new window's StateManager cache is populated from `context.globalState` during initialization. If you need to read state in Window B right at startup (e.g., in `common.ts` during `initialize()`), read directly from `context.globalState.get()` instead of StateManager's cache.
Example pattern (see `lastShownAnnouncementId` and `worktreeAutoOpenPath`):
const value = controller.stateManager.getGlobalStateKey("myKey")
```
This is only needed for cross-window state read during the brief startup window before StateManager cache is fully usable. Normal state access after initialization should use StateManager.
Use `context.globalState` only in VS Code migration code that copies legacy ExtensionContext values into the shared file-backed stores.
## ChatRow Cancelled/Interrupted States
When a ChatRow displays a loading/in-progress state (spinner), you must handle what happens when the task is cancelled. This is non-obvious because cancellation doesn't update the message content—you have to infer it from context.
**See also:** `BrowserSessionRow.tsx` uses similar pattern with `isLastApiReqInterrupted` and `isLastMessageResume`.
**Backend side:** When streaming is cancelled, clean up properly (close tabs, clear comments, etc.) by checking `taskState.abort` after the streaming function returns.
## Debug Harness: clear inherited VSCode/Electron env vars before launching
The debug harness (`apps/vscode/src/dev/debug-harness/server.ts`) launches a child
VSCode via Playwright's `_electron.launch({ env: { ...process.env, ... } })`. If you
run the harness from a process that was itself spawned by VSCode (e.g. the Cline
extension host, an integrated terminal, or an agent running inside VSCode), the
parent's VSCode/Electron env vars leak into the child and break the launch.
The fatal one is **`ELECTRON_RUN_AS_NODE=1`**: it makes the child VSCode binary run
as plain Node, so it rejects every VSCode CLI flag. Symptom:
```
.../Visual Studio Code.app/Contents/MacOS/Code: bad option: --extensionDevelopmentPath=...
Error: Process failed to launch! (Playwright _electron.launch)
```
This is NOT the macOS Playwright flakiness mentioned in the harness README — it's
env inheritance. Fix: strip the inherited vars before starting the harness:
@@ -42,7 +42,7 @@ Here, we use the common `StringRequest` and `KeyValuePair` types.
After editing a `.proto` file, regenerate the TypeScript code. From the project root, run:
```bash
npm run protos
bun run protos
```
This command compiles all `.proto` files and outputs the generated code to `src/generated/` and `src/shared/`. Do not edit these generated files manually.
@@ -91,7 +91,7 @@ On the main branch, create a commit that updates:
3. No changelog-entry file cleanup is needed. Contributors do not create changelog-entry files in this repo.
**Skip running `npm run install:all`** - release automation handles lockfile consistency as needed.
**No dependency install is needed.** A CHANGELOG + `version` bump does not change any dependency, and `bun.lock` does not pin workspace-package versions, so the lockfile stays consistent. The publish workflow runs `bun install --frozen-lockfile`, which would *fail* on an out-of-sync lock — so only run `bun install` here if you actually change dependencies (then commit the updated `bun.lock`).
Commit with message format: `v{VERSION} Release Notes (hotfix)`
**Important:** All bug reports must be reproducible using Claude Sonnet 4.5. Cline uses complex prompts so less capable models may not work as expected.
- type:dropdown
id:plugin-type
id:cline-surface
attributes:
label:Plugin Type
description:Which plugin are you reporting a bug for?
label:Cline Surface
description:Which Cline surface are you reporting a bug for?
Paste the "About" diagnostics for your Cline surface. This captures the IDE build, runtime, and host details we need.
- VSCode Extension: open `Help → About` (Windows/Linux) or `Code → About Visual Studio Code` (macOS), then copy the info.
- JetBrains Plugin: open `Help → About` (Windows/Linux) or `<IDE name> → About` (macOS), then click `Copy` to grab build, runtime, OS, memory, and cores.
- CLI: there is no About dialog. Run `cline --version` and paste the output.
placeholder:Paste the copied About info or `cline --version` output here.
- Adding enums (e.g. `ClineSay`) → also update `src/shared/proto-conversions/cline-message.ts`.
@@ -38,13 +38,13 @@ For Responses API providers: add to `isNextGenModelProvider()` in `src/utils/mod
4. Whitelist in `src/core/prompts/system-prompt/variants/*/config.ts` for each model family.
5. Handler in `src/core/task/tools/handlers/`, wire in `ToolExecutor.ts`.
6. If tool has UI: add `ClineSay` enum in proto → `ExtensionMessage.ts` → `cline-message.ts` → `ChatRow.tsx`.
7. Regenerate snapshots: `UPDATE_SNAPSHOTS=true npm run test:unit`.
7. Regenerate snapshots: `UPDATE_SNAPSHOTS=true bun run test:unit`.
## Modifying System Prompt
Modular: `components/` (shared) + `variants/` (model-specific) + `templates/` (`{{PLACEHOLDER}}`). Variants override components via `componentOverrides` in `config.ts` or custom `template.ts`. XS variant is heavily condensed inline. Always regenerate snapshots after changes.
## Global State Keys (silent failure risk)
Adding a key requires: type in `src/shared/storage/state-keys.ts`, read via `context.globalState.get()` in `src/core/storage/utils/state-helpers.ts``readGlobalStateFromDisk()`, and add to return object. Missing the `.get()` call compiles fine but value is always `undefined`.
Adding a key requires updating the typed storage definitions in `src/shared/storage/state-keys.ts`; runtime reads and writes should go through `StateManager`, not VS Code `ExtensionContext` storage. Persistent state is file-backed so it works across VS Code, CLI, and JetBrains hosts.
"rule":"Any new tool handler added to packages/agents/src or packages/core/src that performs a user-visible action (writes files, executes commands, modifies state, calls external APIs) must include a call to captureToolUsage() from packages/core/src/services/telemetry/core-events.ts, or emit a task.tool_used event via telemetry.capture(). Pure read-only helpers and getters are exempt. When in doubt, prefer instrumentation.",
"rule":"New session start, end, or state-transition code paths in packages/core/src must call the appropriate typed helper from packages/core/src/services/telemetry/core-events.ts (captureTaskCreated, captureTaskCompleted, captureConversationTurnEvent, captureTokenUsage, etc.). Do not inline raw telemetry.capture() calls for session lifecycle events — always use the typed helper, which guarantees a consistent payload shape.",
"scope":[
"packages/core/src/cline-core/**",
"packages/core/src/runtime/**"
"sdk/packages/core/src/cline-core/**",
"sdk/packages/core/src/runtime/**"
],
"severity":"high"
},
@@ -22,8 +25,8 @@
"id":"sdk-no-raw-event-strings",
"rule":"All telemetry event name strings must be sourced from CORE_TELEMETRY_EVENTS in packages/core/src/services/telemetry/core-events.ts. If a PR introduces a string literal in a telemetry.capture(), telemetry.captureRequired(), or recordCounter()/recordHistogram()/recordGauge() call that does not reference CORE_TELEMETRY_EVENTS, flag it. New events must be added to CORE_TELEMETRY_EVENTS first, with a typed capture helper created alongside them.",
"scope":[
"packages/core/src/**",
"packages/agents/src/**",
"sdk/packages/core/src/**",
"sdk/packages/agents/src/**",
"apps/cli/src/**",
"apps/vscode/src/**"
],
@@ -32,13 +35,17 @@
{
"id":"sdk-auth-telemetry-completeness",
"rule":"Any new OAuth or authentication provider added under packages/core/src/auth must emit all four lifecycle events using the typed helpers from core-events.ts: captureAuthStarted (at flow entry), captureAuthSucceeded + identifyAccount (on token success), captureAuthFailed (on error), and captureAuthLoggedOut (on token invalidation or explicit logout). Flag PRs that introduce a new auth flow file without all four. Cross-reference packages/core/src/auth/cline.ts and packages/core/src/auth/codex.ts as canonical examples.",
"scope":["packages/core/src/auth/**"],
"scope":[
"sdk/packages/core/src/auth/**"
],
"severity":"high"
},
{
"id":"sdk-telemetry-doc-update",
"rule":"Any PR that adds new event constants to CORE_TELEMETRY_EVENTS in packages/core/src/services/telemetry/core-events.ts, adds new capture* helper functions, or changes the payload shape of an existing event must update the Event Catalog section in DOC.md. Flag PRs that modify core-events.ts without a corresponding change to DOC.md.",
"description":"Single source of truth for all telemetry event names (CORE_TELEMETRY_EVENTS) and their typed capture helper functions. Every PR touching telemetry must be evaluated against this catalog. New events must be defined here first."
"description":"OpenTelemetry-backed provider that wires logs/metrics/traces exporters. Contains createConfiguredTelemetryService and createConfiguredTelemetryHandle, the canonical factories every host should use."
},
{
@@ -21,11 +21,11 @@
"description":"Public API and event documentation. The Event Catalog and 'Activation funnel' sections must be kept in sync with core-events.ts. Host integration rules (CLI dir ordering, hub daemon metadata forwarding) are documented here."
},
{
"path":"ARCHITECTURE.md",
"path":"sdk/ARCHITECTURE.md",
"description":"Architecture reference. Telemetry design decisions, completion semantics (submit_and_exit anchoring), and hub-daemon telemetry forwarding are documented here. Use as ground truth for design intent."
},
{
"path":"AGENTS.md",
"path":"sdk/AGENTS.md",
"description":"Package boundary rules. Telemetry runtime services live in @cline/core; @cline/agents must not own stateful telemetry. Use to evaluate whether a telemetry change is being made in the correct package."
- Add the SDK-backed VS Code extension runtime. Cline now runs tasks through the shared Cline SDK session layer for agent turns, tools, Plan/Act mode coordination, MCP, checkpoints, telemetry, provider changes, compaction, mistake limits, and task history.
- Add ClinePass to the VS Code extension, including onboarding, provider selection, signup and subscription handoff, live model lists, entitlement and organization error states, out-of-credit prompts, and clearer ClinePass auth/error handling.
- Add the Customize marketplace for discovering and managing Skills, MCP servers, and Plugins from the extension, including installed/marketplace tabs, search and filtering, install/uninstall flows, enable/disable controls, and support for plugin-bundled skills.
- Cline Plugins: Plugins let you extend Cline with custom tools, workflows, skills, and MCP-powered capabilities tailored to your team or project. Install them from the new Customize marketplace to add specialized behavior, connect external services, and package reusable automations—so Cline can do more than code: it can adapt to the way you work.
- Add queued prompts in chat. Messages submitted while Cline is already working are now queued, shown while the current turn streams, and can be cancelled before they run.
- Add edit-and-regenerate support for previous user messages, with clearer Reset Chat and Reset Code actions.
- Add generic SDK provider settings and model-catalog support so more providers can share the same model picker, reasoning controls, dynamic model IDs, provider config persistence, and custom model handling.
- Add additional SDK-backed provider exposure and model/provider updates, including ClinePass models, refreshed Cline catalog data, Fireworks GLM 5.2, Kimi K2.6 Fast, Kimi K2.7 Code, Qwen 3.7 Plus, MiniMax M3 updates, SAP AI Core wiring, LiteLLM model fetching, Codex OAuth credentials, and OpenAI-compatible model settings.
- Add MCP support for plugins and shared marketplace install/uninstall plumbing used by the VS Code extension.
### Changed
- Migrate the VS Code extension from the legacy task implementation to the shared Cline SDK and move the extension build/package workflow to Bun.
- Rework Plan/Act mode handling through SDK coordinators, including closer CLI parity and automatic continuation when switching from Plan to Act.
- Rework provider and model configuration around `providers.json`, the model catalog, and SDK session config so settings are preserved consistently across provider switches and active sessions can restart when the selected provider changes.
- Simplify provider settings UI by replacing many provider-specific views with shared generic settings components and consistent reasoning selectors.
- Simplify terminal execution through the SDK run-commands path, including clearer non-interactive command guidance and safer structured command formatting.
- Migrate legacy MCP files and formats into the shared settings file and protect MCP settings writes with safer locking/atomic updates.
- Refresh the MCP hub automatically after marketplace installs so newly installed servers are available without a manual restart.
- Reorganize MCP/Skills/Plugins entry points under Customize, hide workflows from the Customize menu, wrap Customize tabs on narrow screens, and allow the MCP Marketplace tab to be disabled remotely while installed MCP servers remain accessible.
- Simplify auto-approval settings. Command auto-approval is now disabled by default for safer new and reset configurations, and the auto-approval UI has been streamlined.
- Update task history handling for the SDK migration, including legacy task history visibility, metadata preservation on resume, and corrected deletion behavior.
- Route compacting and mistake-limit behavior through the SDK so the Compact button and mistake tracking affect the active SDK session.
- Remove the legacy Explain Changes feature as part of the SDK migration cleanup.
- Temporarily disable subagents in the VS Code extension while the SDK-backed experience is stabilized.
### Fixed
- Fix marketplace edge cases, including refreshing MCP servers after marketplace installs, disabling the MCP Marketplace tab from remote config, hiding workflows from Customize, surfacing plugin-bundled skills, and uninstalling shared marketplace entries.
- Fix chat submission during active turns by queuing user messages instead of dropping or racing them, showing pending/queued states promptly, rendering direct user messages immediately, and removing delayed send behavior.
- Fix editing previous user messages so Escape cancels editing locally and reset action labels are clearer.
- Fix terminal reliability, including standalone Windows output capture, hardened PowerShell command handling, running-state display for in-progress commands, raw structured command preservation, single-quote handling, cwd setup timeouts, failing-command stdout capture, heredoc coalescing, and removal of duplicated command echoes in tool results.
- Fix SDK tool-result and provider-message budgeting by truncating large tool outputs by default, capping assistant text, limiting bash/file-read/search output ingestion, bounding media budgets, batching outdated-read rewrites to preserve provider prefix caches, and normalizing JSON-like tool inputs by schema.
- Fix login and feature-flag resolution by using the correct user/account identity on startup and simplifying the login UX.
## [3.89.2]
### Fixed
- Complete the fix for the Anthropic provider on VS Code 1.123 and later by upgrading the bundled Anthropic SDK to a release compatible with the Node 24 runtime.
- Update the Vertex AI provider to a compatible Anthropic Vertex SDK release so it works with the upgraded Anthropic SDK.
## [3.89.1]
### Fixed
- Restore the Anthropic provider on VS Code 1.123 and later, where the updated Node 24 runtime broke the bundled Anthropic SDK.
- Handle the DeepSeek V4 reasoning format.
## [3.89.0]
### Added
- Add Claude Fable 5 model support.
### Fixed
- Fix MiniMax M3 thinking controls across gateways.
### Changed
- Clean up the Codex model list.
## [3.88.1]
### Added
- Add a debug section in settings for Cline testers.
### Fixed
- Include the walkthrough markdown files in the VS Code extension package so the first-run walkthrough steps load correctly.
## [3.88.0]
### Added
- Add the latest Fireworks AI serverless models and update the default Fireworks model to Kimi K2.6.
### Fixed
- Fix MCP server delete/add flows so settings writes do not cause the MCP server list to be emptied by the file watcher.
- Remove stale Fireworks AI models and correct Fireworks model metadata and cache pricing.
### Changed
- Always use the upstream Cline recommended models endpoint instead of gating it behind a feature flag.
## [3.87.0]
### Added
- Add MiniMax M3 model support.
### Fixed
- Update VS Code extension dependencies to resolve security issues in `@xmldom/xmldom`, `basic-ftp`, `axios`, `undici`, and other direct/transitive packages.
## [3.86.2]
### Fixed
- Fix `@` file mentions and workspace file search on VS Code 1.122+ by resolving the new bundled `@vscode/ripgrep-universal` per-platform binary layout before falling back to legacy ripgrep paths.
## [3.86.1]
### Fixed
- Fix `@` file mentions failing to find files in some environments (notably VS Code Remote SSH, and after certain VS Code updates) by keeping the file-search fallback alive when the workspace index or bundled ripgrep binary is unavailable.
## [3.86.0]
### Added
- Add Claude Opus 4.8 provider support, including 1M-context variants where available.
- Add Moonshot Kimi K2.6 model support.
### Fixed
- Show prompt-cache support for Qwen 3.7 Max in the Cline provider.
- Fix the VS Code nightly publish workflow startup permissions.
### Changed
- Move the VS Code extension project into `apps/vscode`.
## [3.85.0]
### Added
- Add GPT-5.5 support to SAP AI Core.
- Add DeepSeek V4 Flash and Pro models.
- Add Gemini 3.5 Flash to Gemini and Vertex providers.
- Add `/lg-task` URI webhook integration for LG dashboard flows.
### Fixed
- Fix Vertex AI global endpoint handling for Claude models.
- Route Poolside Laguna models through next-gen prompts and native tool calling.
Chat with your agent from any messaging platform: Telegram, Slack, Discord, Google Chat, WhatsApp, and Linear. Each conversation thread maps to an agent session with full context. Set up access control to restrict who can interact with your agent.
- Recover missing interactive sessions when reading messages
- Format structured commands in history export
- Add the subscription promo code when linking to the dashboard subscription page
- Add Tencent TokenHub as a provider (from SDK v0.0.55)
- Fix first-prompt truncation on high-output models (e.g. MiniMax M3) that could immediately auto-compact and cut the initial task down to just the input wrapper (from SDK v0.0.55)
- Use a curated default when migrating legacy provider settings (from SDK v0.0.55)
- Advertise run commands as shell strings (from SDK v0.0.55)
- Refresh the bundled model catalog with the latest provider models (from SDK v0.0.55)
## 3.0.34
- Fixed the ClinePass upgrade notice appearing immediately after completing onboarding.
- Improved the wording of the ClinePass onboarding step.
- Streamlined the Cline provider picker by merging the subscription and usage/billing options into one and removing the credits link.
## 3.0.33
- Show a ClinePass subscription URL as a fallback during onboarding so you can still subscribe if the subscription screen can't open automatically
- Hide the ClinePass promo for users who already have a ClinePass subscription
- Use an adaptive plan accent color for ClinePass prompts so they fit the active theme
## 3.0.32
- Improved the ClinePass onboarding experience
- Added an intermediate step before going to ClinePass model selection
- Made the ClinePass subscription screen selectable
- Promoted ClinePass in the startup notice
- Used "ClinePass" as one word consistently and refined the provider UI copy
- More accurate context compaction and clearer error messages (from SDK v0.0.54)
## 3.0.31
- Show when request cost is covered by your Cline subscription
- Prompt to switch to ClinePass when you run out of credits, and list ClinePass features in the not-subscribed message
- Added an option to open the subscription page from the ClinePass options
- Added marketplace uninstall support and surfaced plugin-bundled skills
- Require quoted prompts for one-shot mode
- Capped MCP tool names at 64 characters for OpenAI-compatible providers
- Updated coupon code
## 3.0.30
- Added a token count to the status bar, shown alongside cost
- Added organization-specific error messages
- Added SAP AI Core provider support
- Refreshed the model catalog with the latest provider models
- Preserved OpenRouter reasoning-disable behavior and improved OpenRouter prompt caching
- Routed LiteLLM model fetches through the SDK and stopped unrelated models from appearing in the LiteLLM model list
- Updated ClinePass models live, restored ClinePass models in onboarding, and improved ClinePass error messages
- Threaded proxy/CA-aware networking into the inference path
- Persisted Bedrock settings to providers.json
- Normalized JSON-like tool inputs by schema for more reliable tool calls
- Fixed an "ERROR: EMPTY CONTENT" message that could appear when an error occurred
- Fixed a packaging issue (createRequire) that could break the CLI at runtime
## 3.0.29
- Costs are now hidden for Cline free models
- Fixed Z.ai model metadata resolution for Z.ai models accessed through the Cline provider
- Reverted the model-name-only display change from v3.0.28; the model picker, selector, and status bar return to their previous display behavior
## 3.0.28
- Added a ClinePass onboarding flow with selectable ClinePass models, plus improved ClinePass error handling
- Added hub primitive catalogs and refreshed the hub dashboard design with a dedicated customizations breakout
- Auto-approve toggles now apply immediately when changed
- Feature flags now resolve using your user ID on startup
- Fixed Cline model display names so they resolve by model name
- Truncate large tool results by default (including MCP and custom tool output) to keep requests within context budget
- Hardened parallel tool-call guidance for faster, more reliable multi-tool execution
## 3.0.27
- Added a `cline skill` command to install and manage skills, matching `cline plugin install` and `cline mcp` (installs default to the Cline agent directory)
- Added a prefilled MCP install wizard command for quicker MCP server setup
- Improved error handling and messaging when plugin MCP OAuth authorization fails
- The CLI now rejects unknown commands and unquoted multi-word input with a clear error instead of silently treating bad arguments as a prompt
## 3.0.26
- Reverted the expandable model picker sections and ClinePass models, restoring the previous model-selection UI
## 3.0.25
- Added ClinePass support, with selectable ClinePass models in the model picker
- Made model picker sections expandable
- Added MCP server support to plugins, including authorizing plugin MCP OAuth during install
- Encouraged parallel tool calls for faster task execution
- Capped tool output for bash commands and file reads to keep large output within context limits
- Allowed ranged reads on large files
- Fixed apply_patch to fail when a hunk is skipped
- Fixed run_commands to return captured stdout on failure and handle split heredocs
- Fixed search tools to treat zero results as success
- Fixed disabled-reasoning handling for StepFun flash
- Fixed history resume rendering isolation
- Fixed the Hugging Face URL
- Fixed Cline OAuth token formatting in provider config
## 3.0.24
- Plugin commands can now submit prompts to the agent
- Added support for overriding the API base URL
- Open the verification URL automatically when starting device authentication
- Enforced a single shared Cline Hub, so a stale hub is respawned after an upgrade
- Suppressed flickering console windows on Windows
- Fixed truncation of structured tool operation result strings so oversized tool output stays within limits
- Stopped echoing the full command text in run_commands tool results
## 3.0.23
- Fixed Vertex AI GCP settings configuration
- Fixed the Azure Foundry API version
- Added support for configured agents as subagent tools
- Centralized OAuth management into the SDK
- Fixed an error caused by disabled reasoning on Fable 5
## 3.0.22
- Added support for the Claude Fable 5 model
- Fixed MiniMax M3 thinking controls so they route correctly across gateways
## 3.0.21
- Added a global auto-update setting that controls automatic updates on CLI startup
- Added a Cline credits refill link
- Fixed scrolling for inline ask-question responses
- Fixed connector thread session routing and stale hub session handling
- Added support for Vertex AI Application Default Credentials (ADC) with tool use
- Fixed empty message content replay for Bedrock
- Cleaned up the OpenAI Codex model list
## 3.0.20
- Installed plugin wrappers are now named from their source (npm package name, git repo, remote filename, official slug, or local directory) instead of an opaque hash, making installed plugins easier to identify.
## 3.0.19
- Fixed CLI auto-update to use `npm update` so updates apply reliably, while preserving the installed release channel (e.g. nightly).
## 3.0.18
- Fix Slack channel mentions so replies post in the original message's thread.
- Fix the abort indicator to clear immediately when a task is cancelled.
- Sync the Fireworks AI model registry and refresh the bundled model catalog with current platform offerings.
- Bump the bundled SDK to v0.0.43, which forces a running Cline Hub to restart so it picks up the latest SDK code.
## 3.0.17
- Fix a regression introduced in 3.0.15 where the interactive CLI could get stuck after stopping and restarting Cline Hub and then pressing Escape to cancel a request. The CLI now detects stale or missing sessions, recovers any pending messages, and starts a fresh session instead of failing with "session not found".
- Fix Ctrl+C and Hub shutdown races that surfaced as "hook dispatch failed" and WebSocket connection errors from late hook events racing against Hub shutdown.
- Fix the Hub daemon being shut down prematurely when a runtime request was aborted, so the daemon now stays alive.
- Improve the Telegram connector with a new `--allowed-user-id` flag to restrict which Telegram users are authorized to interact with the agent.
## 3.0.16
- Install official Cline plugins by slug off the new github.com/cline/plugins collection.
- Uninstall plugins using `cline plugin uninstall <plugin>` or in the TUI.
- Plugins can now bundle skills, and plugin skills are grouped together in settings.
- Add Slack socket mode support.
- Allow a custom base URL for Anthropic vendor-type providers.
- Fix OAuth token migration for users signed in through the old extension.
- Use a union schema for read-files tool input validation.
- Add a `CLINE_PLUGIN_IMPORT_TIMEOUT_MS` env override to control the plugin import timeout.
## 3.0.15
- Add Cline Hub, a web app for monitoring connected clients, viewing and driving sessions, streaming assistant output, and restarting the local hub, with local, LAN, and tunnel usage gated by a room secret.
- Support global AGENTS rules so agent rules can be applied across all sessions, not just per-project.
- Let plugins contribute static or dynamic rule content when installed in the sandbox.
- Bind Discord sessions to individual message authors so different Discord users no longer share chat state in a thread.
- Support participant mute targets in Discord: resolve `/mute` and `/unmute` from user mentions or raw user IDs to mute a specific participant in a thread.
- Make OAuth URLs clickable in the TUI.
- Refresh the bundled model catalog, adding Claude Opus 4.8, Moonshot Kimi K2.6, and Qwen3.7 Max (with cache support).
- Discover SDK skill directories that are symlinked, including handling circular symlinks.
- Steer active connector sessions across turn keys by matching on session ID, so replies continue the existing session instead of starting a duplicate.
- Stop the Discord connector after repeated identical errors (per thread, within a time window) to prevent error messages from flooding a channel.
- Fix Discord connector registration and reply fallback handling.
- Fix SAP AI Core to use the AI SDK community provider.
- Log ACP output as diagnostics instead of errors so normal output no longer appears as errors.
## 3.0.14
- Fix OTEL telemetry variable bundling so telemetry is correctly enabled in compiled CLI builds: guard against environments where `process.env` is undefined and remove optional chaining so bundlers can inline the values at build time.
## 3.0.13
- Show a loading dialog while resuming a session from history so the TUI no longer appears frozen during the load.
@@ -416,7 +416,7 @@ Then attach VS Code or Chrome DevTools to `ws://127.0.0.1:6499`.
## Publishing
The CLI is published as the `cline` wrapper package on npm with platform-specific binaries under `@cline/cli-*`. The release flow lives in the `publish-cli` skill (`sdk/apps/cli/.cline/skills/publish-cli/SKILL.md`).
The CLI is published as the `cline` wrapper package on npm with platform-specific binaries under `@cline/cli-*`. The release flow lives in the `publish-cli` skill (`.cline/skills/publish-cli/SKILL.md` at the repo root).
Open the add-server wizard with the name, transport, and command or URL already filled in with `cline mcp install` (`cline mcp add` also works). Stdio servers use everything after `--` as the command and arguments:
Because this command opens the wizard, it requires a TTY.
### Connectors
Bridge a chat surface into RPC-backed Cline sessions. Each conversation thread maps to a session with full context. Supported platforms: Telegram, Slack, Google Chat, WhatsApp, and Linear.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.