mirror of
https://github.com/cline/cline.git
synced 2026-10-25 10:26:36 +08:00
fix/hub-hook-error-serialization
519
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3453880297 |
fix(vscode): keep error details in production logs (#14693)
* fix(vscode): keep error details in production logs
Logger dropped every extra argument unless IS_DEV was true, and production
bundles build IS_DEV as false, so lines like 'Cline OAuth login failed:' lost
the error. Production now appends error messages (with cause chain), numbers
and booleans; strings and objects stay dropped because call sites pass OAuth
URLs, terminal and file contents and settings. Verbose mode now serializes
Errors as stacks instead of {} and survives circular arguments. The
'Opening browser' line logs only origin and path.
* fix(vscode): reduce URLs in production log output to their origin
Error messages printed in production can embed URLs with credentials in
the query, path or userinfo, such as the expanded MCP server URL in the
invalid-URL error or Bun's URL parse error echoing its input. Reduce
every URL in a production error message to its origin, log only the
origin when opening a browser, and echo the MCP server URL as entered
rather than with environment variables expanded.
* fix(vscode): redact whole URLs in log text and keep the matcher linear
Parentheses and brackets are valid URL characters, so ending a match at
them left the rest of a credential-bearing URL in the log. Match up to
whitespace, quotes or angle brackets instead, trim only trailing
sentence punctuation and unbalanced closing brackets, and bound the
scheme length so scanning stays linear on adversarial input.
* fix(vscode): move the URL redaction helper into shared
Logger lives in src/shared, which the webview build compiles too, and
there `@/` resolves to webview-ui/src, so importing `@/utils/redact-url`
broke the webview typecheck.
* refactor(vscode): drop free-text URL scrubbing from the Logger
Scrubbing URLs out of arbitrary error messages is a blocklist that can
never be complete. Give error messages the same trust as the log message
itself instead, and keep the deterministic fixes: the MCP invalid-URL
error no longer embeds expanded environment variables, and the browser
URL is logged as its origin at the one call site that logs it.
* fix(vscode): omit JSON parse error messages from production logs
V8 and Bun quote the parsed input in JSON.parse errors, and the parsed
input is often a settings file or an API response carrying credentials,
such as the remote-config provider API keys. Log only the error name.
* fix(vscode): keep the entered MCP URL out of the invalid-URL error
A URL typed with userinfo or query credentials failed validation and
was echoed in the error, which is logged in production. Omit the URL
and keep the guidance; the user just typed it and can see it in the
form. Also drop the changeset: the repo no longer uses them.
* feat(vscode): fingerprint redacted URLs in the browser-open log line
Append three hex digits of a SHA-256 over the full URL to the redacted
origin, so a log shows whether two lines with the same origin were the
same URL without revealing it.
|
||
|
|
ab4c1136a8 |
fix(vscode): stop labelling every HTTP 401-428 as an auth failure (#14919)
* fix(vscode): stop labelling every HTTP 401-428 as an auth failure ClineError.getErrorType treated any status in 401-428 as ClineErrorType.Auth, so a 404 from an OpenAI-compatible server with a stale model id, or from Gemini for a retired model, was shown as an authentication problem: for the cline provider the webview replaced the real message with the logged-out card or "(Click Retry below)". Only 401/403/407 are Auth now. 402 maps to Balance, 404/405/410 to a new NotFound class, and other 4xx fall through to the generic row, which shows the real status and message. The axios ERR_BAD_REQUEST code (set on every 4xx) only stands in for an auth failure when no status is available. ErrorRow adds model-id/base-URL guidance to a status-based NotFound, and the host's text-matched model-not-found rewrite shares the same guidance text so a message is never told twice. * fix(vscode): keep 407 off the auth row and pin message-based detection A 407 is the proxy rejecting credentials, not the provider, so the sign-in card would point at the wrong account; it now stays on the generic row, matching the SDK classifier's 401/403. Also pin that a status outside the dedicated sets still reaches the wording checks: Gemini answers an invalid key with a 400 and only the message says so. |
||
|
|
5b67631981 |
fix: child-stdin EPIPE and the SAP SDK's winston handler no longer kill the host process (#13762)
* fix: stop child-stdin EPIPE and the SAP SDK's winston handler from killing the host process
Two stacked bugs made cline-core exit with code 1 about 3s after a hook
(or MCP server) exited before draining its stdin:
- HookProcess and the SDK stdio MCP client wrote to a child's stdin with
no "error" listener. When the child dies while part of the write is
still queued (input larger than the pipe buffer), Node fails it
asynchronously with EPIPE and, unhandled, raises it as an uncaught
exception on the host process. Both writers now absorb the error and
let the existing exit handling report how the child ended.
- @sap-cloud-sdk/util (a dependency of the SAP AI Core provider) builds a
winston logger with exceptionHandlers at module load, installing a
process-wide uncaughtException listener that calls process.exit(1)
three seconds later -- overriding cline-core's own "log but survive"
handler. @jerome-benoit/sap-ai-provider bundles a second private copy
of that module, so disableExceptionLogger() cannot reach it; the
community vendor module now strips winston's process catchers by name
after the import and again after building the provider.
Regression tests cover both halves: a hook and an MCP server that exit
mid-write must fail the single operation without an uncaught exception,
and importing the community module must leave no winston catcher on the
process.
* fix(hooks): explain an undelivered input in hook failure messages
Review follow-up: the stdin "error" listener only logged. It still must
not settle the run -- a hook may legitimately ignore its input and exit
0, and the shell wrapper keeps the pipe open while the script lives, so
"close" stays the single source of truth -- but the failure is now
recorded and appended to the timeout / non-zero-exit errors so a hook
that never read its input is diagnosable from the error alone. Adds a
test that a hook ignoring a large input and exiting 0 still succeeds.
* test: type the uncaughtException probes so apps/vscode check-types passes
bun-types merges extra process listener overloads into `process`, which
made `process.off("uncaughtException", ...)` fail overload resolution
under the apps/vscode tsconfig (and with it the e2e package step). Type
the probe listeners and remove them through the plain EventEmitter type.
* fix(mcp): report the server's exit, not the broken pipe, when it dies mid-write
Review follow-up: the stdin "error" listener failed every pending request
with the EPIPE message, and it fires before "exit", so the exit handler
(which carries the exit code and stderr) never got to report. It now only
records the failure; the exit and request-timeout errors append a note
that the server stopped reading its input. The test server crashes with
exit code 3 and the test asserts the exit is what gets reported.
Also drops the changeset: changesets are no longer used in this repo.
* fix(mcp): kill a server whose stdin write failed instead of waiting out the timeout
A stdin write only fails once nothing holds the pipe's read end, so the
connection is dead either way. Killing the child lets the "exit" handler
fail pending requests immediately. A server that already exited keeps
its real exit status (the kill is a no-op); one that closed stdin but
stayed alive no longer stalls the request for the full timeout.
* fix: strip only the SAP SDK's own process catchers; give a dying MCP server its graceful window
Review follow-ups:
- community.ts removed every winston `uncaughtException`/`unhandledRejection`
listener by name, which would also take out an embedding host's own
winston exception handlers. The SAP provider is now imported lazily
(literal specifier, so bundlers still include it) inside the same
snapshot-and-diff wrapper the opencode provider already uses, so only
the listeners that import and construction added are removed. The
hygiene test installs a host listener with winston's name and asserts
it survives.
- The MCP client killed the server as soon as a stdin write failed, so a
server that closed stdin and was about to exit with its own code was
reported as SIGTERM instead. The kill now waits the existing graceful
shutdown window (250ms) and is skipped if the server exits first; a
test covers a server that exits 7 shortly after closing stdin.
* test(mcp): keep the stays-alive fixture alive and assert the client killed it
Number("") is 0, so with FAKE_MCP_EXIT_AFTER_CLOSE_MS unset the fixture
exited with code 7 at once and the stays-alive test passed without
exercising the kill. Use Number(undefined) (NaN) for the unset case and
require signal=SIGTERM so a fixture that exits on its own fails the test.
* fix(mcp): bound request failure and shutdown when a server outlives a failed stdin write
Sending a single SIGTERM and waiting for "exit" left a server that handles
SIGTERM alive, with the pending request stalled until its normal timeout.
If the server is still the current child when the graceful window ends,
the pending requests now fail with the stdin-failure message and the child
goes through disconnect()'s SIGTERM -> SIGKILL escalation. A server that
exits within the window is still reported by its own exit code.
Tests cover a stdin-closing server that honors and one that ignores
SIGTERM: the request fails within seconds and the process is gone.
* fix(llms): remove only the exit handlers the SAP import registers
The previous wrapper diffed process listeners across the async import and
construction, so it also removed host listeners registered in that
window (e.g. the CLI's abort-time unhandledRejection swap), and it had no
finally, so a rejected first construction left winston's handlers armed.
The SAP provider now loads through a small helper that attributes
"uncaughtException" registrations to the import by async context
(AsyncLocalStorage + a temporary "newListener" listener) and removes
exactly those in a finally. Construction runs after cleanup.
unhandledRejection is no longer touched: SAP never registers one.
On Bun, async context does not reach module evaluation, so nothing is
attributed; the Bun-run CLI and hub already treat uncaught exceptions as
fatal. The opencode signal-handler helper is back to exactly main's.
Tests run in fresh processes (one per file) and prove the SAP import
armed a handler: host listeners registered after loading starts survive
and SAP's are removed, on both a successful and a rejected first
construction.
|
||
|
|
afaf4f2457 | chore(vscode): release v4.1.23 | ||
|
|
5dea21ab89 |
Remove deprecated Focus Chain plumbing from the VS Code extension (#14861)
* Hide retired Focus Chain messages when loading legacy tasks * Remove deprecated Focus Chain plumbing from the extension * docs: remove retired Focus Chain telemetry events * Remove unused AgentConfigLoader from the VS Code extension (#14881) * refactor(vscode): remove unused legacy agent config loader * test(vscode): verify initialized state persists to disk * test(vscode): avoid contextual inference in storage assertion --------- Co-authored-by: Cline <noreply@cline.bot> --------- Co-authored-by: Cline <noreply@cline.bot> Co-authored-by: cline-cloud[bot] <276134852+cline-cloud[bot]@users.noreply.github.com> |
||
|
|
6354d209c8 |
docs: correct shared paths, log files, commands and tool names (#14884)
* docs: correct shared paths, log files, commands and tool names Several pages repeat the same facts about where Cline keeps its files, which commands exist and what the built-in tools are called, and many of them no longer match the shipped CLI and SDK: - Workflows live in ~/.cline/workflows/, not ~/.cline/data/workflows/. The session index is ~/.cline/data/db/sessions.db, each session has a folder of JSON files, and hub locks and logs are under ~/.cline/data/. - cline start and cline dev log do not exist; the log command is cline doctor log, and the CLI log is ~/.cline/data/logs/cline.log. - The built-in tools are run_commands, search_codebase, fetch_web_content and skills, not bash, search, fetch_web and use_skill. - CLINE_HUB_ADDRESS is read only by cline schedule; the hub port is CLINE_HUB_PORT. - No CLI 3 release reads CLINE_COMMAND_PERMISSIONS. The pages that offered it, including the PR review sample, now say the CLI has no command allow list and point to a PreToolUse hook. The unused permissionDeniedError string in the VS Code prompts goes with it. Part of #14853. Co-authored-by: Mikołaj Kondratek <19799111+mkondratek@users.noreply.github.com> Co-authored-by: Manpreet Kaur <26463231+Manpreet2298@users.noreply.github.com> Co-authored-by: Renee Huang <100229782+reneehuang1@users.noreply.github.com> * docs: qualify log, tool routing and command-approval advice - cline doctor log always opens the default log file, so say so where CLINE_LOG_PATH is described. - The editor and apply_patch choice is a default that SDK callers can replace with toolRoutingRules. - The PR review sample now warns that hooks and plugins in the checked-out pull request run with the job's environment, and says how to keep them from running before relying on a global PreToolUse hook. - The conditional-approval example no longer auto-approves git diff, which runs a configured external diff program, and notes that Git can run programs named in a repository's config. * docs: run the PR review sample with a read-only token The sample gave an auto-approved Cline run a token that can write pull requests. Split it into two jobs: `review` runs Cline with read-only permissions on a checkout of the base branch and writes review.md; `post` runs no repository or model code and posts the file with `gh pr review --comment`. Skip pull requests from forks and Dependabot, which get no secrets, and warn against `pull_request_target`. Fence the workflow with four backticks so the code block inside the prompt no longer ends it early. --------- Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> Co-authored-by: Mikołaj Kondratek <19799111+mkondratek@users.noreply.github.com> Co-authored-by: Manpreet Kaur <26463231+Manpreet2298@users.noreply.github.com> Co-authored-by: Renee Huang <100229782+reneehuang1@users.noreply.github.com> |
||
|
|
e6a3b1cf0a |
docs: state telemetry defaults and scope accurately (#14860)
* docs: state telemetry defaults and scope accurately The Enterprise and monitoring pages called Cline telemetry opt-in and anonymous, and said code never leaves the machine. Telemetry is on by default in the VS Code and JetBrains extensions, Cline Desktop and the CLI. It identifies signed-in accounts and organizations, and includes prompts for requests to the Cline and ClinePass providers. Rewrite the telemetry page around what is collected and how to turn it off in each product. Scope the remote-configuration restrictions to the products that enforce them, add a per-product support table, and tell admins to ignore the folders Cline writes into workspaces. Align the VS Code setting description and host-telemetry warning with the docs. Part of #14853 * docs: drop bold from remote-config support table rows The bold marked dashboard switch names, but nothing on the page said so, so the rows looked inconsistent. * docs: address review of the telemetry and remote-config pages State only what the telemetry setting enforces in the extensions: the lock, and that members can't turn telemetry on when the organization turns it off. Scope the support-table introduction to the controls marked Yes, since no product enforces YOLO or Kanban. Use recursive .gitignore patterns and say why: the cached settings can include prompt storage access keys, and a member may open a subfolder of a repository. Narrow the indexing card to content: Cline lists file paths to search them but doesn't index or embed file contents. * docs: say products support remote-config controls, not enforce them Organization rules and workflows reach sessions as instructions that a member can edit, so "enforces" overstated what the CLI does with them. The section heading already says "support". --------- Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> |
||
|
|
6017c502c3 |
fix(vscode): apply the user's rules when generating commit messages (#14103)
* refactor(core): select and order session rules in one place The rules section of a session's system prompt was selected in several places: `listEnabledRulesFromWatcher` (enabled only, sorted by name) for the single-workspace plugin, and an inline filter without the sort in the combined user-instruction service. Callers outside a session that need the same section had nowhere to reach it and would have grown a third copy. Add `listEnabledRulesFromRecords` / `loadRulesForSystemPromptFromRecords` next to the watcher variants, make the watcher variants delegate to them, and use the records variant in the combined service. Export the loader from `@cline/core`. Behavior change: the combined service now orders rules by name like the single-workspace path does, instead of in listing order. * fix(vscode): apply the user's rules when generating commit messages "Generate Commit Message with Cline" built its prompt from a hardcoded system prompt and never loaded `.clinerules`, so commit conventions users had written down (language, format, ticket references) were honored in chat and silently dropped by the button. `Controller.getRulesForSystemPrompt` takes the enabled rules from the user-instruction watcher the controller already runs for the workspace, through core's shared `loadRulesForSystemPromptFromRecords`, and the commit-message system prompt appends them behind a short preamble telling the model which rules are relevant to a commit message. The button sees the rule set a chat session in the workspace sees, including a rule that has `disabled: true` frontmatter being left out of both. If the rules can't be read, the base prompt is used. Known limitation: the Rules panel's on/off toggles live in extension state the SDK doesn't read, so a rule switched off there is still sent to chat and to the button alike (CLINE-3120). The new rules load is one more await before the request; the existing cancel check before `createMessage` covers it, and a test pins that. Fixes #9410 * fix(vscode): let Stop end a commit generation still waiting for rules The first generation in a workspace waits for the user-instruction watcher's initial scan of rules, skills and workflows. Stop was honored after that await (no request went out), but the generation and its SCM progress indicator stayed pending until the scan finished, which can take a while on a slow filesystem. Race the rules load against the generation's abort signal so Stop ends the generation at once. The scan carries on in the background and warms the watcher chat uses; nothing waits on it any more. * fix(core): render hub client rules through the shared selection The hub's client user-instruction proxy filtered and formatted rules inline, in listing order, while the combined service now goes through the shared `loadRulesForSystemPromptFromRecords`, which sorts by name. runtime-builder wraps the client proxy in the combined service when host plugin skills are present, even though the plugin service contributes no rules, so adding a host plugin reordered the same client rules in the session prompt. Render the hub snapshot's rules through the shared helper too. Every path that builds a session's rules section now selects and orders rules the same way; hub client sessions now get their rules sorted by name. A boundary test renders reversed names plus a disabled rule through the proxy alone and through the combined service, and expects the same output from both. |
||
|
|
2f93c1d6f7 |
docs: fix two broken README links (vscode contributing, sdk telegram) (#14826)
* docs: fix two broken README links (vscode contributing, sdk telegram) * docs: fix two broken README links (vscode contributing, sdk telegram) |
||
|
|
39ff2359f7 |
feat(llms): opt-in Langfuse tracing for BYOK providers plus env tags, metadata and environment (#14787)
* feat(llms): opt-in Langfuse tracing for BYOK providers plus env tags, metadata and environment Langfuse tracing was limited to the cline and cline-pass providers, so an operator pointing LANGFUSE_* credentials at their own instance could not trace OpenRouter or any other BYOK provider. CLINE_LANGFUSE_ALL_PROVIDERS=1 now opts third-party providers in. They are exported only through the isolated direct exporter and never through the host OTLP relay, so BYOK prompts cannot reach a collector the operator did not configure themselves. Benchmark and isolated-environment runs can label every trace from the environment: LANGFUSE_TRACING_ENVIRONMENT sets the Langfuse environment on the direct exporter, CLINE_LANGFUSE_TAGS adds comma-separated trace tags, and CLINE_LANGFUSE_METADATA adds trace metadata as a JSON object or key=value pairs. Env values merge under the runtime's own attributes, and env-only attributes propagate even when a call supplies none of its own. * docs(llms): state that Langfuse tracing covers streamed language requests only Dedicated image generation uses the AI SDK's generateImage, which takes no telemetry option and has no Langfuse integration hook, so it has never been traced for any provider. Document that scope in the resolver and the runbook rather than implying the BYOK opt-in covers it. |
||
|
|
ce74ef0914 |
fix(vscode): send Cline surface headers from commit message generation (#13593)
* fix(vscode): send Cline surface headers from commit message generation Commit message generation builds a standalone ApiHandler through `buildApiHandler` instead of going through ClineCore, and that path wired no request headers at all. The Cline gateway only serves models that are restricted to Cline product surfaces (the free models) to requests that identify themselves, so "Generate Commit Message with Cline" failed with HTTP 403 on a free model while normal chat on the same model worked. Resolve the headers through the shared `resolveProviderRequestHeaders` policy — the same one `local-runtime-bootstrap` uses for sessions — so there stays one source of truth for provider header policy, and attach them to the provider config the standalone handler is built from. The caller now resolves the host client identity first, so a request reports the same client/platform as a task from the same host. Custom provider headers stored in providers.json are layered in as well; the commit path dropped those too. A standalone request is not a task, so no session id is claimed: `sessionId` becomes optional in the resolver and `X-Task-ID` is omitted rather than sent empty. The pre-SDK extension sent `X-Task-ID: ""` from this same code path, so nothing depends on a meaningful id here. Fixes #13590 * refactor(vscode): share one client-identity mapping between sessions and standalone requests `resolveClineRequestClientContext` mapped the host identity to the SDK's client shape, including the extension-identity fallbacks, and `buildSessionConfig` built the same object inline. A commit-message request and a task are supposed to report the same client, and two copies of that mapping stop guaranteeing it the first time one is edited. Move the resolver into the session factory and have `buildSessionConfig` call it, so both paths share it by construction. The host-identity and multi-root helpers go back to private. * fix(vscode): send the core's own version and session source from standalone requests The standalone path sent the extension's version as `X-CORE-VERSION` and an inlined "vscode" source tag, while a task from the same extension sends the core package's version via `local-runtime-bootstrap`. That made the "same headers as a session" guarantee untrue for that header, and the reason given for inlining the tag (avoiding a core import) didn't hold: this module already sits behind `cline-session-factory`, which imports `@cline/core`. Import `CORE_BUILD_VERSION` and `SessionSource.VSCODE` from `@cline/core` so both paths agree by construction. The vitest `@cline/core` stub re-exports the real values from SDK source. * fix(vscode): honor a commit-generation cancel issued while the host identity resolves `performCommitMsgGeneration` flips the SCM button to its stop action and then awaits `buildApiHandlerWithHostContext()` (two host-bridge lookups) before it created this generation's `AbortController`. A cancel in that window aborted the previous controller, if any, and the request the user had just cancelled was then sent anyway. Create and install the controller before the first await, check it again right before `createMessage`, and read it through a local so a later generation can't swap the signal an earlier one checks. Two small follow-ons from the same fix: a cancelled generation no longer reports "Failed to generate commit message: This operation was aborted", and only the current generation clears the context key, so one that settles late can't flip the button back while a newer one runs. * fix(vscode): cancel a running commit generation when a new one starts Each generation now checks its own controller, but the stop action can only reach the one stored in the module slot. The Generate keybinding, unlike the SCM button and palette entry, stays live while a generation runs, so a second invocation replaced the slot and left the first generation unstoppable: Stop cancelled the newer request while the older one kept writing into the commit input. Before the per-generation controller both read the shared slot, which is why this only surfaced now. A new generation now aborts the previous one before taking the slot, so at most one runs and Stop reaches it by construction. The aborted one exits without an error and leaves the context key to the new generation. * fix(vscode): let Stop cancel every running commit generation instead of the newest Having a new generation abort the previous one made Stop reach everything, but it added a rule `main` never had, and it collided with "Generate for all repositories": a generation started mid-run aborted the bulk run's current repository, the bulk loop then moved to the next repository, and that one aborted the newer request. The latest request was lost and a repository was skipped. Track every running generation in a set instead. Each registers its controller before its first await and removes it when it settles; Stop aborts all of them, and the context key stays set while any runs. Nothing but Stop cancels a generation, so concurrent generations (the Generate keybinding stays live while one runs, the bulk loop starts one per repository) no longer cancel each other, and Stop still reaches all of them. * test(llms): assert Cline surface headers on streaming requests too The wire-level test only drove `doGenerate`, but commit-message generation calls `createMessage`, which streams. A regression that dropped the surface headers from streaming requests alone would have kept the test green while the free-model 403 came back. Run the same assertions through `doStream` (and check the request really is a streaming one) for both `cline` and `cline-pass`. |
||
|
|
07a8587479 |
fix(vscode): register the tool-approval resolver before posting state (#14643)
* fix(vscode): time out undisplayed tool approvals (#14065) * fix(vscode): drop the approval timeout, keep the resolver-ordering fix The five-minute timer denied every pending approval, including ones the user could see but had not answered yet. postStateToWebview() resolving does not mean the ask was displayed (state delivery is fire-and-forget), so the timer could not tell an undisplayed approval from a slow answer. Keep registering the resolver before the state post so Approve/Reject works while the post is in flight, and deny on a failed post only if that post's approval is still the pending one; a late failure no longer denies a later, unrelated approval. Log when an approval starts waiting so stalls can be told apart from provider stream stalls in the output channel. --------- Co-authored-by: Dang Zitou <dengzitao888@163.com> |
||
|
|
8b03864dca |
fix(core): recover oversized tool results from a session memory cache (#14712)
* fix(core): cache oversized external results without changing history
* fix(core): use volatile tool result URIs with iteration eviction
* docs(core): clarify cached result reads and truncation fallback
* docs(core): update tool result cache miss message
* fix(core): generate cache fallback agent IDs with crypto.randomUUID
* docs(core): keep cache guidance in result notices
* fix(core): preserve result recovery notices after cache eviction
* fix(core): make cached result recovery readable and text-only
* refactor(core): retain existing read_files availability and line limits
* docs(core): clarify exclusive read_files access to cache URIs
* fix(core): serialize structured cached results as multiline YAML
* fix(core): align recovery admission with persisted preview sizing
* fix(vscode): preserve cache URIs in workspace file reader
* fix(core): exclude MCP image blocks from recovery text
* fix(core): wrap long cached result lines so read_files can page single-line payloads
Cache reads go through read_files' MAX_LINE_CHARS cap, so a minified JSON
or other single-line payload was cut at 2,000 chars with no way to reach
the rest by line range. Wrap cached text at 1,000 chars on the read path
only; stored bytes stay verbatim and cache line numbers are a paging view.
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
* Revert "fix(core): wrap long cached result lines so read_files can page single-line payloads"
This reverts commit
|
||
|
|
2a83dd1a0e |
fix(desktop): provider execution, browser metadata, and MCP paths - CLINE-3283 (#14206)
* llms/core: register catalog custom providers with the gateway on the agent run path Custom providers added via Desktop's Add Provider dialog (persisted to providers.json/models.json and registered in the @cline/llms model catalog) were visible in every picker but failed at execution time with 'Unknown or disabled provider "<id>"'. The agent run path (createAgentModelFromConfig -> createGateway) only seeded builtin provider registrations, while the legacy ApiHandler path already bridged catalog collections into the gateway via resolveProviderRegistrationSync. Export that bridge from @cline/llms as resolveGatewayProviderRegistration(Sync) and apply it in createAgentModelFromConfig, mirroring the ApiHandler path. Fixes cline/cline#14180 * desktop: resolve MCP settings through one canonical resolver The sidecar carried its own homedir-based resolveMcpSettingsPath next to the shared @cline/shared/storage resolver, and the Tauri shell had a third copy. All three agree under default env, but the duplicates ignored CLINE_DIR/CLINE_DATA_DIR (and the shared resolver's HOME handling), so MCP reads/writes, the OAuth authorize command, and the 'Open MCP settings' window action could target different files. Delete the sidecar duplicate so every sidecar command uses the shared resolver, and mirror the shared resolver's precedence (CLINE_MCP_SETTINGS_PATH > CLINE_DATA_DIR > CLINE_DIR/data > ~/.cline/data) in the Rust open_mcp_settings_file path. Fixes cline/cline#14152 * refactor(desktop): resolve provider metadata in the host * Authenticate provider model source requests * Avoid iterable Headers requirement in VS Code compatibility build * Refresh source catalogs when provider credentials or endpoints change * fix(core): save provider settings when model discovery fails * fix(core): propagate provider catalog persistence failures * fix(core): restore provider settings when catalog writes fail * fix(core): serialize provider mutations and persist settings once * fix: preserve provider customizations and handle unknown auth metadata * fix(core): track discovery ownership on initial catalog refresh * fix(desktop): address provider catalog review feedback - Treat an empty source catalog as best-effort during credential saves - Prune models from source-backed entries saved before discovery ownership - Format turn failures with the submitted provider's auth metadata - Re-export ProviderLocalCli/resolveProviderLocalCli from @cline/llms for compatibility --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
f58bc118bd | chore(vscode): release v4.1.22 | ||
|
|
159951f82d |
ci(vscode): make the e2e job spend its time on the tests (#14607)
* ci(vscode): make the e2e job spend its time on the tests Windows e2e runs hit the 20-minute limit after their tests had passed: the job was saving a multi-gigabyte bun cache that only that pull request could read. The job also repeated the type check and lint that Quality Checks already runs, and downloaded Playwright browsers the tests never start. - Restore the bun cache on every run and save it only from main, right after the install, so a later test failure keeps it. - Build the extension with build:production and load it as the extension under development. The tests already ran that copy; the VSIX they also installed was never used, and packaging it ran vscode:prepublish's checks. - Install only Playwright's ffmpeg, which it records test videos with. The tests launch VS Code through Electron, not a Playwright browser. - Let runs on main finish instead of cancelling them on the next merge. - Raise the timeout to 30 minutes for the run on main that installs without a cache and saves a new one. * ci(vscode): make the e2e workflow comments match its behavior A run on main that is still waiting to start is replaced by the next merge; only a run that has started always finishes. The comments now say so, and name the directory VS Code loads the extension from. * ci(vscode): run Quality Checks when the Playwright config changes The e2e build no longer runs the type check and lint, and playwright.config.ts was the one lintable e2e input outside Quality Checks' path filter. A change to only that file could pass CI unlinted. * ci(vscode): stop caching Bun's install cache in e2e Restoring the cache and installing took about as long as an uncached `bun install` in ext-vscode-test's jobs on the same commits: 3:48-4:31 against 2:39-5:06 on Windows, and 25s against 23s on Ubuntu. With no cache to save, a run on main can be cancelled by the next merge again and the job fits main's 20-minute timeout, so concurrency and the timeout go back to main's settings. The e2e path filter also drops apps/vscode/.vscodeignore: test:e2e no longer packages a VSIX, so nothing in the job reads that file. |
||
|
|
647d8cb059 |
fix(vscode): restart an auth-failed task from a revised prompt (#14628)
When a new task fails Cline authentication before its session is created, the footer offers Retry and, since #14395, the composer lets the user submit a revised prompt. Retry sends yesButtonClicked, which askResponse turned into a restart of the original prompt. The revised prompt sends messageResponse, which askResponse treated as a follow-up and tried to resume a task with no session, so signing in and submitting the revised prompt started nothing. askResponse now restarts that task for messageResponse too, with the revised text when one was typed and the original prompt otherwise. The retry prompt is now kept with the task that showed the error and is used only by the next response to that task. A message typed after a failed edit or checkpoint restore continues the existing conversation instead of replacing it, and a task opened from history after a failed start no longer restarts the failed prompt when resumed. Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> |
||
|
|
dd261c6ca5 |
fix(vscode): look up Reset Code checkpoints when a message is edited (#14638)
* fix(vscode): look up Reset Code checkpoints when a message is edited The Windows e2e for Checkpoint settings failed two ways. Reset Code stayed disabled for a message whose checkpoint existed, and a follow-up bubble never appeared in the transcript. Reset Code availability was computed for every user message when the session went idle and pushed with every state update. It read the persisted transcript, which Core writes after it reports the turn done, so on a slow disk the last user message was missing, the message could not be mapped to its run, and "unavailable" was cached for the session. The buttons are only visible while a message is being edited, so ask then. A new checkpointExistsForMessage RPC answers for one message from the live conversation of the active session, or from the persisted transcript of a history task. The pushed map, its cache and its idle-time refresh are gone; the webview keeps the same disabled states and explanations while the answer is pending or negative. The missing bubble came from continueIdleSession, which echoed the user_feedback message at the old epoch and then bumped the epoch. A state snapshot built across that boundary carried the new epoch with a transcript copied before the echo, replaced the webview transcript wholesale, and the bubble's old-epoch copies were then dropped as stale. Bump the epoch before the echo, as the resume path already does, and rebuild a snapshot whose epoch moved while it was being assembled. The e2e test itself raced the turn end: a streamed reply is visible before the turn completes, so it opened the editor and sent the next message while the previous turn was still finishing. It now waits for the footer's Cancel button to go and the chat input to regain focus, so the input refocus cannot close the Reset Code popover and the last message starts on the rebuilt, checkpoint-enabled session instead of joining the old session's queue. * fix(vscode): read the same conversation for the Reset Code lookup and edit The checkpoint lookup read the live conversation of the active session while editMessageAndRegenerate read the persisted transcript. Between Core reporting a turn done and writing the transcript, the lookup could enable Reset Code for a message the edit then failed to find. Both now read through readCurrentMessages, as the history loader already did. While the lookup runs, the Reset Code button shows a spinner and the tooltip "Checking for a workspace checkpoint...", and does not act. Before, it claimed no checkpoint existed until the answer arrived. WorkspaceRestoreAvailability has only the webview as a consumer, so it moves out of the shared ExtensionMessage module. --------- Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> |
||
|
|
3ab7b564c1 |
feat(telemetry): label background command failures that produce no exit code (#14177)
* feat(telemetry): label background command failures that produce no exit code task.terminal_execution records a failed background (child_process) execution with an exit code only when the process ran and exited non-zero. A shell that could not be started at all — ENOENT because it is not on PATH, EACCES, EFTYPE — landed in the same success=false bucket as aborts and closed terminals with nothing to tell them apart, so a rise in "shell not found" was invisible. That matters now that the Windows working-directory lookup change (#14171) makes every bare name resolve through PATH only. The executor rejects with CommandSpawnError when spawn fails, keeping the message hosts already display and carrying the operating system code. ENOENT alone is ambiguous: spawn reports it with the same message when the executable is missing and when the working directory no longer exists, so the error checks the directory at failure time and records which path was absent. The VS Code shell tool classifies every failure into an errorCode dimension: the OS code for a spawn failure, ENOENT_CWD when the working directory had vanished instead, "aborted" for a cancelled turn, "other" otherwise; a non-zero exit keeps reporting exitCode as before. TelemetryService accepts the new dimension. * fix(telemetry): preserve termination reasons and standalone attribution * test(core): restrict detached signal assertion to POSIX |
||
|
|
dd169d48c3 |
fix(vscode): submit prompts after API errors (#14395)
* fix(vscode): submit prompts after API errors * fix(vscode): recover from unanchored API errors; keep /compact typed Most provider failures reach the error phase with no anchor message, so recovery availability now follows the footer's Retry button rather than an anchored api_req_failed ask. The composer, footer, embedded retry controls and compaction then share one decision for every error that offers Retry. A /compact (or /smol, /newtask) typed during recovery is neither compacted nor sent to the model as literal text; the draft stays in the composer, matching the disabled header button. |
||
|
|
29d66f6fbc |
fix(vscode): disable Reset Code without checkpoints (#14496)
* fix(vscode): disable Reset Code without checkpoints * fix(vscode): apply checkpoint toggles to active tasks * fix(vscode): target checkpoint settings from Reset Code * fix(vscode): use themed foreground for popovers * fix(vscode): keep history state on checkpoint host failure * fix(vscode): preserve follow-up order across rebuilds * fix(vscode): hold follow-ups for checkpoint rebuild * fix(vscode): preserve follow-ups across rebuilds * fix(vscode): isolate checkpoint transitions * fix(vscode): wire mode rebuild wait correctly * fix(vscode): coordinate rebuild task transitions * fix(vscode): repair checkpoint CI coverage * test(vscode): synchronize checkpoint rebuild e2e * fix(vscode): supersede running rebuilds on repeat requests A rebuild request for a reason that is already rebuilding used to leave the running rebuild current, so it installed the superseded setting and, for checkpoints, could replay held follow-ups under it. isCurrent() now means no newer request for the same reason has arrived. A superseded rebuild stops before replacing the session, or keeps the replacement but leaves held follow-ups to the newer rebuild, which runs next. Cancellation could never reach a running rebuild: runTaskTransition waits for the drain first. Drop the unreachable cancel path and the unused waitUntilSettled. * fix(vscode): queue follow-ups on Core during checkpoint rebuilds A follow-up typed during a turn after Checkpoints changed was parked in a private list on the config-change coordinator. Nothing displayed that list, so the message disappeared from the chat until the turn ended and the rebuild replayed it. CI's "Checkpoint settings" e2e caught this on every platform. Queue such follow-ups on Core like any other, so the webview shows them at once. The checkpoint rebuild already carries Core's queue over to the replacement session. If a newer change for the same setting arrives while the replacement is starting, the superseded rebuild re-queues the prompts instead of starting a turn, so no turn runs under the stale configuration. This removes the held-follow-up transition, the rebuild onCancel hook, and handlePendingRebuilds. * fix(vscode): keep rebuilds off sessions with queued prompts Core drains its own prompt queue the moment a turn ends. A passive rebuild that started on the "idle" status could therefore replace the session while Core was already running the queued prompt on it, and the old turn's send promise then marked the busy session idle. The queued follow-up in the checkpoint e2e lost its answer this way. Track Core's queue length on the active session and treat a session as idle for rebuilds only when it is not running and nothing is queued. A send's completion no longer marks the session idle when a newer turn began after it. With Core owning the queue there is nothing left for the rebuild to replay, so the replay code goes. A message queued during a turn runs with the settings in force when that turn ends; the setting change applies from the next message. The e2e now asserts exactly that. --------- Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> |
||
|
|
c5b7c7a776 |
fix: migrate a bare AWS profile as Bedrock profile auth and label UI credential edits as manual (#14477)
* fix(vscode): treat GUI credential edits as manual token source The provider settings manager inherits the previous entry's tokenSource when the caller does not pass one, and the settings UI write path never passed one. A migrated entry therefore kept the "migration" label on every later GUI save, so a user who re-entered credentials by hand still looked like they were running on migrated settings. Credential-bearing patches (apiKey/aws/auth) now pass an explicit "manual" source. Patches that do not touch credentials keep inheriting, so OAuth entries are not relabelled by model-only edits. * fix(core): migrate a bare AWS profile as Bedrock profile auth Legacy state grew three ways to say "use a named AWS profile": `awsAuthentication: "profile"`, the older `awsUseProfile` toggle, and, on older installs, a bare `awsProfile` value with neither flag. The provider-settings migration honoured the first two and dropped the third, writing a Bedrock entry with no profile. This is a consistency fix, not a regression fix. The legacy handler also ignored a bare profile and fell back to the default credential chain, while the legacy settings UI displayed "profile" as the selected auth mode for that state. The Next extension resolves the same state as profile auth from live settings, so VS Code already behaves that way; providers.json, which the CLI and desktop app read directly, did not. Treat a bare profile with no explicit auth choice as profile auth so the migrated entry matches what the UI shows and what VS Code does. An explicit IAM or API-key choice still wins over a stale profile. Refs cline/cline#14095. * fix(vscode): count header edits as manual credential edits Follow-up to the manual token-source change: OpenAI-compatible endpoints often carry the credential in a header (Authorization, api-key) rather than the apiKey field, so a header edit from the settings UI is a credential edit and should leave the "migration" label behind too. Refs cline/cline#14095. * fix(vscode): count only AWS auth fields as credential edits The AWS block also carries region, prompt caching, endpoint, base-model and inference-profile toggles. Editing those is not a credential edit, so it should not relabel a migrated entry as manual. Only accessKey, secretKey, sessionToken, authentication and profile (or clearing the block) count. Refs cline/cline#14095. * fix(core): backfill the profile on already-migrated Bedrock entries Migration never overwrites an existing entry, so an install that migrated before the bare-profile inference has a Bedrock entry with no profile and the fix would only reach installs that have not migrated yet. Repair such an entry from the legacy state still on disk, but only when it is untouched migration output: still tagged "migration", no authentication choice, profile, static credentials or API key, and the legacy state has a bare profile with no explicit authentication. A manually saved entry or an explicit IAM/API-key choice is left alone. Refs cline/cline#14095. * fix(core): apply the Bedrock profile repair at most once Legacy state is never deleted, so the repair re-read it on every launch and would keep restoring a profile a user had removed through a path that does not write legacy state back: a hand-edited providers.json, or another client sharing the data directory. Record the repair in providers.json and skip it once recorded. Also carry `modes` across the migration's rewrite. It was rebuilt from an empty stored object, so a migration that added a provider wiped any stored voice-input selection. Refs cline/cline#14095. * chore(vscode): drop the unused Bedrock providers.json writer `buildBedrockProviderSettings()` has no callers, and the rationale in its doc comment is wrong: it claims the session's `providerConfig` does not override the gateway registration, while `buildProviderConfig()` in local-runtime-bootstrap.ts spreads the session config last, so live settings do win over the stored entry. That comment is what sent cline/cline#14100 after a bug that was actually in the migration. Remove the function, its comment and its tests. `buildBedrockProviderConfig()`, which the session factory does call, is unchanged. Refs cline/cline#14095, cline/cline#14100. --------- Co-authored-by: zhanhuangchao <1348752764@qq.com> |
||
|
|
2ed2ef288e | test(e2e): raise dependency install timeout to 5 minutes (#14536) | ||
|
|
0271462032 |
fix(vscode): restore Zod exports in Vitest (#14504)
Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> |
||
|
|
787ad1b077 | chore(vscode): release v4.1.21 | ||
|
|
8abfde69d8 |
refactor(shared): add toPosixSeparators and reuse it in core and vscode (#14452)
Four call sites carried the same helper under different names: apps/vscode's @-mention file search (toPosixSeparators, from #14398), core's plugin-install (toPosixPath), workspace/file-indexer (toPosixRelative) and workspace/mention-enricher (inline). All split on path.sep and join with "/", so a literal backslash in a POSIX filename is left alone. Move that one implementation to @cline/shared and import it. No behavior change: every migrated site already used the path.sep form. The unconditional replace(/\\/g, "/") variants in cron-reconciler, rule-conditionals and apps/vscode/src/utils/path.ts (String.prototype .toPosix) are deliberately untouched; switching them is a POSIX behavior change to decide per site, not a refactor. |
||
|
|
8c00a0820d |
fix(vscode): stop rendering the raw tool envelope for silent commands (#14239)
* fix(vscode): stop rendering the raw tool envelope for silent commands Since #13816, a command that prints nothing reaches the chat as a ToolOperationResult with result: "". extractToolOutputText only recognized records with a non-empty result or error, so the empty result fell through to the JSON.stringify fallback and the chat rendered [{"query":"git add -A","result":"","success":true}] as the command output. Treat an empty string result as a recognized, empty output so the command row renders with no output section. * fix(vscode): preserve structured MCP output --------- Co-authored-by: Dominic Cooney <dominic.cooney@cline.bot> |
||
|
|
bb203d435c |
security: raise js-yaml floor to 4.3.2 (CVE-2026-84375, T1 in rule/skill frontmatter loader) (#14032)
bun.lock: js-yaml@4.3.1 -> 4.3.2 (the vulnerable entry is deleted, not just overridden). Root override becomes a plain top-level key ">=4.3.2 <5" per the bun-1.3 rule; apps/vscode floor ^4.3.2. Closes 2 findings on cline (CVE-2026-84375, AIKIDO-2026-641142). Produced by the VMP Automation, 2026-09-10 run Co-authored-by: TheRealSpencer <32678829+TheRealSpencer@users.noreply.github.com> |
||
|
|
7f5366556c |
fix(vscode): normalize @-mention search paths to forward slashes on Windows (#14398)
* fix(vscode): normalize @-mention search paths to forward slashes on Windows
Both @-mention search producers returned workspace-relative paths with
platform separators on Windows: the ripgrep walker via path.relative and
the host-index path via the JetBrains FilenameIndex host. Only the
open-tabs branch normalized to "/".
Downstream code assumes forward slashes. The webview picks the label over
the full path when the label differs from value.split("/").pop(), so on
Windows every nested README rendered as "/README.md"; the open-tabs
dedupe missed the same file with the other separator (#5747); and stored
mentions were not portable across OSes.
Normalize at both producers and reuse the helper for the open-tabs
branch. Two new tests cover the ripgrep and host-index branches; two
existing tests that expected "src\main.ts" on win32 now expect the
normalized form on every platform.
* fix(vscode): only rewrite the platform separator in @-mention search paths
Splitting on path.sep instead of replacing every backslash keeps POSIX
filenames that contain a literal backslash intact (review feedback).
Same approach as the SDK's workspace file-indexer. Tests now build their
inputs with path.sep, so the conversion is exercised on Windows CI and
stays a valid no-op on POSIX; a POSIX-only test covers the literal case.
|
||
|
|
636de8b2af |
fix(sdk): persist session errors across desktop and CLI navigation ENG-2524 (#14033)
* fix: persist display-only session errors across clients * fix: record terminal failures after retries and guard stale history * fix(core): exclude display-only history from compaction * cli: type manual compaction input as MessageWithMetadata The display-only filter reads `message.metadata`, which exists on MessageWithMetadata but not on Message, so `@cline/cli` typecheck failed and aborted the parallel Quality Checks run before the other packages reported. The caller already passes MessageWithMetadata, and canonicalMessages only ever returns input.messages, so widening both signatures matches the real data and also hands createSessionCompactionState the metadata its source hash expects. * test(desktop): expect formatted error message prefix |
||
|
|
254f40c4b5 | chore(vscode): release v4.1.20 | ||
|
|
cedc3c6639 |
fix(vscode): deliver run-start hook context through the hooks adapter (#14160)
* fix(hooks): deliver run-start hook context and control on next UserPromptSubmit/TaskStart/TaskResume hooks could not inject context on the next engine, and at the SDK core layers their output was discarded entirely (agent_start/agent_resume spawned detached with stdio ignored, so even cancel was dead). Legacy delivered these as <hook_context> blocks in the same turn as the user prompt. Mirrors the tool-hook contextModification shape one level up: - Contract: beforeRun now returns AgentRunStartResult, adding an appendContext channel next to stop/reason. - Runtime: run-start context is collected in callBeforeRunHooks and injected as a <hook_context source="RunStart"> user message (hidden display role) after the run's input messages, so the model sees it on the run's first request. The existing post-tool flush is extracted into a shared helper, and stale contexts are cleared at run start. A stopping hook's context is never injected. - SDK core layers (hook-file-hooks, subprocess): agent_start and agent_resume now run blocking with their control honored — cancel stops the run with the hook's message as the reason, context becomes appendContext with the existing 50KB truncation. prompt_submit stays a fire-and-forget message-added dispatch (the run input is not in the snapshot when beforeRun fires at these layers), but no longer fires for injected hook-context messages. - Extension adapter: TaskStart and UserPromptSubmit contextModification now maps to appendContext (combined across both, cancel semantics unchanged). * fix(hooks): make run-start context survive the orchestrator and harden the blocking path Review fixes on top of the run-start context injection change: - The session-runtime orchestrator's beforeRun merger returned undefined for every non-stopping result, discarding appendContext on every production path (VS Code, CLI, desktop) — only directly-constructed runtimes saw the feature. It now aggregates appendContext like its beforeModel/beforeTool siblings, with orchestrator-level tests. - Two more message-added prompt dispatchers (the CLI's and the audit logger's) were still treating injected hook-context messages as user prompts; the adapter's latestUserPrompt likewise would have fed hooks their own previous output as the prompt on the next run. All filter on the system display role now. - A blocking hook that spawned a background child sharing its stdout could hang the run forever: completion resolved on stdio close, which the grandchild holds open past the SIGKILL. The runner now settles shortly after process exit with whatever output arrived. - Run-start hooks in the subprocess layer tolerate non-JSON stdout (their output was ignored for their whole prior life), instead of raising a dispatch error on every run; timeouts still surface. - Run-start context is never inserted between a seeded trailing tool_use and its tool_result: the flush is deferred to the post-tool flush point, and the per-batch buffer reset that would have dropped the deferred context is removed (covered by a runtime test). - A stopping layer now short-circuits the layer merge, so later layers' blocking hook commands don't run for an already-cancelled turn. - Cleanup: the duplicated control mapper in hook-file-hooks collapses into stopOrContextResultFromControl (as subprocess.ts already did); the adapter's two inline stop-or-context tails use the shared mapper; the false 'input not in snapshot' rationale is corrected; the hooks README documents the blocking run-start contract and per-host timeouts. * test(vscode): e2e-verify run-start hook context injection through the live pipeline Extends the hooks e2e: the fixture UserPromptSubmit hook now records the prompt it received and returns a contextModification naming a distinctive fact, and the mock server answers the probe prompt according to whether that fact is present in the model request it received. The spec asserts, in a real VS Code window through the real adapter/orchestrator/runtime pipeline: the injected context reaches the first and second model requests; on the second turn the hook receives the real prompt rather than its own previously injected block; the raw block never renders in the transcript, live or when the task is reopened from history. The prompt assertion matches on content: the next engine hands hooks the stored form of the prompt, wrapped in user_input markup. * test(vscode): size the hook-gated e2e reply waits to the hook budget Both hooks specs waited for the model reply with Playwright's 5s expect default, but a run-start hook executes before the model call and the extension allows it up to 30s. On Windows the first prompt-sending spec pays a cold PowerShell spawn that alone can exceed 5s: the failure artifact shows the 'Hook: UserPromptSubmit Running' chip still up when the assertion expired, and the same spec had been passing at 30.1s and failing at 30.0s of wall clock - a coin flip on the deadline, not a behavior change. The reply assertions now cover the hook budget, and both specs are marked slow so two hook-gated prompts plus VS Code startup cannot exhaust the per-test timeout either. * test(vscode): make the hook-context probe turn-specific The mock answered "received" whenever the injected fact appeared anywhere in the request, and turn 1's block stays in the conversation history, so the second-turn assertion could not fail even if repeated run-start injection regressed. Require the fact in a message after the latest probe prompt. |
||
|
|
5d765e2779 |
feat(vscode): capture conversation-linked Git telemetry (#14127)
* add requestId to afterModel. add git snapshot telemetry object * update vscode session host to emit git telemetry onAfterModel * fix late observers * fix tests --------- Co-authored-by: Max Paulus 🥪 <max@cline.bot> |
||
|
|
ee46dc4bd7 | fix(vscode): preserve drafts across retry (#14312) | ||
|
|
81f9eebf72 |
fix(vscode): stream background command output from tool updates (#14136)
* fix(vscode): stream background command output from tool updates * fix(vscode): isolate streamed command output * fix(vscode): keep stale command completions isolated |
||
|
|
2ba680ce6c |
fix: load and surface .cline/rules consistently across clients (#14207)
* shared: expose workspace/global rules path helpers and search redirected Documents resolveWorkspaceRulesConfigPaths returns both supported workspace rule layouts (.clinerules and .cline/rules) so hosts can stop hardcoding one of them (#14186). resolveGlobalRulesConfigPaths returns every global rules location and now also includes OneDrive Known-Folder-Move Documents candidates: the VS Code extension resolves the real Documents folder through the OS and creates global rules there, so on Windows machines with redirected Documents the SDK resolver (used by the desktop app and CLI) never found them (#14144). * vscode: surface rules from every shared resolver location in the Rules panel The Rules panel's toggle refresh was hardcoded to the workspace .clinerules directory and the Documents global directory, so rules the SDK runtime loads from .cline/rules (and global ~/.cline/rules, ~/Cline/Rules) were applied to the model but silently missing from the panel (#14186). Synchronize toggles across every directory the shared resolver searches, combining per-directory results the same way the Cursor rules multi-location handling already does. Also drop the ambient @cline/shared/storage stub: it shadowed the real module declaration and hid every export the stub didn't re-declare; tsc resolves the real dist types fine. * desktop: classify .cline/rules workspace rules as Project in Customize view The Rules tab grouped project rules only when their path contained /.clinerules/, so rules in the .cline/rules layout were shown as Global (#14186, #14144). * fix(desktop): anchor rule scope to workspace roots and document layouts --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> |
||
|
|
27adfdb1a6 |
fix(vscode): honor Azure API version in SDK sessions and mirror it to providers.json (#13761)
* fix(vscode): honor Azure API version in SDK sessions The SDK session factory resolved bedrock/vertex/sap/ollama structured options from legacy state but never Azure's: the webview's Azure API Version and Identity fields (openai-compatible provider) only land in legacy StateManager keys, so SDK sessions hit Azure deployment URLs without ?api-version= and Azure rejects every request with "Resource not found". Resolve azureApiVersion/azureIdentity from legacy state (providers.json azure block as fallback, matching the base-URL/API-key precedence) and pass them as providerConfig.azure. Also mirror resolved values into providers.json so the CLI - which reads only providers.json - sees the same Azure configuration the extension uses; the one-shot legacy migration never updates existing entries, so this is the only ongoing sync for these fields. Fixes #13655 * test(vscode): validate the Azure mirror against the real ProviderSettingsManager The vitest '@cline/core' alias points at an in-memory stub whose saveProviderSettings validates nothing, so the mocked-manager tests could not catch a mirror payload the real ProviderSettingsSchema.parse would reject (the resolver swallows save failures). Import the real manager by relative path for one schema round-trip test, alias the @cline/shared/db subpath its import graph needs, and re-pin the provider-settings-manager mock in beforeEach so a test swapping in a real manager cannot leak it into later tests. * test(vscode): import the built @cline/core bundle instead of SDK source The real-manager test imported provider-settings-manager from SDK source by relative path, which pulled the SDK source tree into the extension's TypeScript program and failed check-types with a TS6059 cascade (files outside rootDir). Import ../../node_modules/@cline/core/dist/index.js instead: it still bypasses the vitest '@cline/core' stub alias (aliases match bare specifiers, not file paths) while typing against the package's own declarations. Also assert the mirrored azure block on the temp file itself, since the in-memory stub would satisfy the manager-level assertions too. |
||
|
|
7f75100da2 |
Add Client Type to Recommended Models requests (#14224)
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> |
||
|
|
27fe60d79f |
chore(vscode): release v4.1.19
4.1.18 was tagged but never reached the Marketplace: every publish attempt timed out on upload. Its notes carry forward under 4.1.19 together with what landed on main since, so the first version users actually receive describes everything in it. |
||
|
|
0905884ab5 |
Refresh Cline logo assets (shared, desktop, menubar) (#13965)
* feat(branding): add canonical Cline logo assets * feat(vscode): refresh extension logo surfaces * feat(web): update Hub and example branding * docs: update Mintlify branding assets * build(brand): lock asset generator tooling * chore(branding): limit logo refresh to assets and required wiring * fix(vscode): restore accessible logo names * fix(branding): retain favicon contrast in dark browser tabs * [2/3] Refresh desktop logo assets (#13966) * chore(desktop): refresh native logo assets * chore(menubar): refresh native logo assets (#13967) part of logo migration * docs: use latest adjusted navigation logo * fix(hub): keep favicon visible in dark browser tabs Point the Hub favicon at the dedicated favicon.svg and give it the same prefers-color-scheme fallback as the example app. cline-logo-filled.svg stays untouched since the sidebar renders it with dark:invert. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> --------- Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
0cf47f5851 | fix(providers): refresh CoreWeave branding and setup links (#14185) | ||
|
|
173837314b |
fix: stop Windows resolving bare program names through the workspace cwd (#14171)
* feat(shared): add disableCurrentDirectoryExecutableSearch for Windows
libuv resolves a bare program name on Windows by searching the child's
working directory before PATH, gated on the spawning process having
NoDefaultCurrentDirectoryInExePath defined. Cline spawns rg, git and
powershell with the user's workspace as cwd, so a repo shipping an rg.exe
would get it executed at index time. Expose a one-call helper that sets
Microsoft's documented opt-out, plus a Windows-only test that plants a
zero-byte cmd.exe and asserts the real one still runs.
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
* fix: stop Windows resolving bare program names through the workspace cwd
Call disableCurrentDirectoryExecutableSearch() at startup in every
process that hosts Cline core: the CLI (and the hub daemon it boots), the
desktop sidecar, the VS Code extension host, and the JetBrains cline-core
process. One environment variable covers every spawn site (file indexer,
search, simple-git, shell executor, hooks, MCP, taskkill) and is inherited
by children, which cmd.exe, libuv and Bun 1.4+ honor as well.
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
* fix: hand user-facing children the inherited NoDefaultCurrentDirectoryInExePath state
libuv reads the opt-out from the spawning process, so Cline's own protection
does not depend on children carrying it. But cmd.exe, Go, Bun 1.4 and
libuv-based children honor it as well, so letting them inherit Cline's
setting would silently change how a user's own bare program names resolve
(npm scripts running a cwd-local .bat through cmd.exe, MCP servers named
relative to cwd, hooks that spawn helpers).
disableCurrentDirectoryExecutableSearch() now latches the value the process
inherited, and withInheritedExecutableSearch() restores that state on the
child env at the spawn sites that run user-authored programs: the shell
executor, MCP stdio servers, hook subprocesses, the plugin subprocess
sandbox, and the VS Code host's HookProcess.
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
* Revert "fix: hand user-facing children the inherited NoDefaultCurrentDirectoryInExePath state"
This reverts commit
|
||
|
|
186ac22e29 |
telemetry: fire ui.panel_opened from initializeWebview on every host (#14101)
* telemetry: fire ui.panel_opened from initializeWebview on every host ui.panel_opened was only captured from VscodeWebviewProvider, so the JetBrains plugin never emitted it: the activation funnel there jumps from user.extension_activated (core spawned on project open) straight to task events, with no signal that the Cline UI was ever rendered. The webview calls the initializeWebview RPC once on mount on every host, so capture the same event there with source "webview_initialized". Existing dashboards keyed on ui.panel_opened pick up JetBrains for free; VS Code gains one extra source value on an event it already emits. * telemetry: type the ui.panel_opened source A PanelOpenedSource union on capturePanelOpened keeps the documented source list and the call sites from drifting apart. Also note that on JetBrains webview_initialized fires on every webview reload, so a crash-restart loop emits one per restart. |
||
|
|
b675eb6189 |
telemetry: report host-provided core spawn ordinal and reason as metadata (#14104)
* telemetry: report host-provided core spawn ordinal and reason as metadata Out-of-process hosts spawn cline-core and sometimes respawn it: after a crash, on a rollout fallback or demotion, or when the user restarts the agent. From core's side every spawn is just another user.extension_activated, so a core that crash-restarted three times and a user with three project windows open are indistinguishable in telemetry. Read CLINE_CORE_SPAWN_ORDINAL and CLINE_CORE_SPAWN_REASON from the spawn env, the same contract as IS_DEV and CLINE_ROLLOUT_VARIANT, and attach them as core_spawn_ordinal / core_spawn_reason metadata on both telemetry pipelines (classic TelemetryService and the SDK handle), so they land on every event. Malformed values are dropped field by field; in-process hosts set nothing and get no fields, like host_plugin_version on the CLI. The JetBrains plugin sets the env in a companion change. * telemetry: type core_spawn_reason as the shared CoreSpawnReason union Define CORE_SPAWN_REASONS / CoreSpawnReason once in @cline/shared next to TelemetryMetadata and use the union in every metadata contract (shared, classic TelemetryService, vitest stub) and in the env parser, so a programmatic setMetadata/updateMetadata cannot introduce a reason the parser's allowlist would have rejected. * telemetry: derive the classic metadata's spawn fields from CoreSpawnTelemetryMetadata Index into the parser's type instead of redeclaring both fields and their doc comment, mirroring how extension_variant defers to RolloutTelemetryMetadata. Also fix import order flagged by biome check. |
||
|
|
2198414245 | chore(vscode): release v4.1.18 | ||
|
|
36905f11cc | fix(core): refine PowerShell shell guidance (#14055) | ||
|
|
632fce5071 |
feat(llms): sampled cline-provider AI SDK tracing via the host OTLP exporter (#13974)
* fix(llms): limit Langfuse telemetry to Cline provider Refs ENG-2505 * fix(llms): include ClinePass in Langfuse telemetry Refs ENG-2505 * feat(llms): sampled cline-provider AI SDK tracing via the host OTLP exporter Enables the collector-relay tracing path: when the host telemetry service has registered an OTLP tracer provider, cline-provider streams can emit AI SDK spans without Langfuse credentials in the process. - CLINE_TRACE_SAMPLE_PERCENT (default 0 = off) gates emission; sampling is a deterministic FNV-1a hash of the task/session id, so whole tasks sample together and retries decide identically. - Metadata-only by default (recordInputs/recordOutputs false): models, tokens, timings, errors — no prompt or completion content. Content requires CLINE_TRACE_RECORD_CONTENT=true explicitly. - The direct Langfuse path (env credentials, hub/internal) is unchanged: full content, every request, provider-gated as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(telemetry): client OTLP trace pipeline for cline-provider AI SDK spans Extension side of the Langfuse collector relay: - OpenTelemetryClientProvider gains a TracerProvider: when tracesExporter is configured, spans batch-export over OTLP (grpc / http/json / http/protobuf) to the same collector endpoint as logs/metrics. register() also installs the async context manager span parenting needs. - tracesExporter plumbed through all three config sources: build constants (OTEL_TRACES_EXPORTER), runtime env (CLINE_OTEL_TRACES_EXPORTER), and remote config (openTelemetryTracesExporter) — the last is the no-release kill switch. - SDK: a host that registers a traces exporter now defaults to 100% task sampling; CLINE_TRACE_SAMPLE_PERCENT reduces it (0 disables). Env reads are literal so build-time inlining works. Metadata-only stays the default; content still requires CLINE_TRACE_RECORD_CONTENT=true. - CLI build inlines the new envs alongside the existing OTEL set. No publish workflow sets OTEL_TRACES_EXPORTER yet, so shipped builds keep tracing dark — activation is a separate one-line-per-workflow PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(llms): honor the global telemetry opt-out on the trace relay path AI SDK spans bypass the ITelemetryService wrapper that enforces the user's opt-out for events and metrics, so an opted-out user's prompts would still have traced once a host registered an OTLP exporter. resolveAiSdkTelemetry now re-checks the shared global settings file (telemetryOptOut) per stream — covering startup state and mid-session opt-outs across extension and CLI. The credentialed direct Langfuse path is unchanged: it only activates on explicit operator config. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style: biome format Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(llms): one trace export path per host — direct Langfuse declines when an OTLP tracer is registered Enablement is a per-stream boolean but export fan-out is processor-level: attaching the direct LangfuseSpanProcessor to a host-registered tracer provider ships every span twice (direct + collector relay). The direct path now declines instead of cooperating when a recording provider already owns the global slot; it only exports when it registers its own provider. A host therefore configures exactly one of LANGFUSE_* credentials or an OTLP traces exporter, and misconfiguring both is safe. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(hub): daemon-distinct trace identity for Langfuse hub coverage (#14034) The detached hub daemon already has everything needed to emit AI SDK traces: it ships in the same compiled binary as the CLI (so the publish build's OTEL_TRACES_EXPORTER / CLINE_TRACE_RECORD_CONTENT inlining reaches it), its telemetry handle flows into the hub server and the scheduled-run handlers, core's OpenTelemetryProvider registers a global tracer when the exporter is configured, and shutdown already flushes with a hard deadline. What was missing is identity: spans carry only the OTel resource, not per-event metadata, so daemon-emitted traces were indistinguishable from CLI-local ones (both service.name=cline). The daemon now declares serviceName=cline-hub-daemon (+ serviceVersion), via new optional serviceName/serviceVersion fields on the shared OpenTelemetryClientConfig. Opt-out holds for the daemon unchanged: it is a same-machine, same-user process, so the shared global settings file the per-stream gate reads is the requesting user's own (shared/cloud topologies tracked in ENG-2525). Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(llms): fail closed when the telemetry opt-out cannot be verified The relay's opt-out guard treated every settings read failure as 'no opt-out recorded', so a corrupted or unreadable settings file (including a torn read of the non-atomic writer) silently re-enabled tracing for a user who had opted out. Only a genuinely absent file (ENOENT, first run) now reads as opted in; malformed JSON and every other read failure disable the relay — consent that cannot be verified is not consent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(llms): identify the OTLP relay explicitly instead of inferring it from any recording tracer 'Some recording tracer exists' misclassified console-only tracing as the collector relay (enabling the relay decision) and — for mutable providers — newly suppressed the direct Langfuse attach that worked before the one-path guard. The hosts that build tracer providers now stamp a relay marker only when a real OTLP span processor was created (console-only providers stay unmarked), and the trace decisions key off that marker: - relay path enables only behind a marked provider; - the one-path decline fires only for marked providers — unmarked mutable providers keep the original cooperative attach behavior; - a relay decline is no longer cached, so direct Langfuse gets to retry once a relay is disposed. The marker lives on the provider instance (reached through the OTel API global), which survives bundled module duplication where a module-level registry would not. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style: organize imports Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(telemetry): own and dispose remote trace clients across config updates * fix(llms): wire per-call Langfuse telemetry and isolate direct export * refactor(telemetry): reject unsupported providers before initialization * test(desktop): raise sidecar vitest timeout above the module-graph import cost The first test in each sidecar file pays the @cline/core → @cline/llms import cost, which lands within ~100ms of the 5s default on CI runners (commands-account failed at 5009ms; context.test.ts passed at 4923ms). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: abeatrix <beatrix@cline.bot> |
||
|
|
e4f1df2c5a |
fix(core): identify shell editions and discourage redundant wrappers (#14025)
* fix(core): identify shell editions and discourage redundant wrappers * fix(shared): keep PowerShell edition export Node-only --------- Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> |
||
|
|
3d5070705c |
feat(desktop): Enable web search by default outside YOLO mode CLINE-3214 (#13957)
* feat(core): enable web search by default outside yolo * fix(core): fail closed when tool settings cannot load |
||
|
|
8ff5f22cf9 |
fix(webview): flag attached images the selected model can't use and offer a model switch (#13943)
* fix(webview): warn when an image is pasted or dropped for a text-only model Pasting or dropping an image into the chat box did not check whether the selected model accepts image input. The image was attached and shown as a thumbnail, then silently replaced by a text placeholder before the API call, so the user never learned it was ignored. The chat box now refuses the image and shows an inline hint, using the same overlay pattern as the existing dimension and unsupported-file errors. Unknown capability data fails open, matching core. * fix(model-catalog): let declared input modalities decide supportsImages The provider layer prefers a model's declared input modalities over its capability list when deciding whether image parts are sent. The adapter that produces the legacy supportsImages flag only looked at capabilities, so a model declaring text-only input without a capabilities array was reported as image-capable to the UI while the request formatter still stripped images. * fix(webview): keep unsupported images attached, badge them and offer a model switch Refusing the paste/drop was the wrong shape: it dropped user content and could not cover images attached before switching to a text-only model. Images are now attached regardless. While the selected model has no image input, each image thumbnail carries a warning badge and a notice under the composer says the images will be ignored and links to the model picker. Both are derived from the current model, so they appear and disappear as the model changes. * fix(webview): make the model-picker link in the images notice a native button An anchor with role=button and no href is focusable but ignores Enter and Space, so keyboard users could not open the model picker from the notice. * fix(webview): keep the link colour on the model-picker button in the images notice A native button inherits the notice's warning colour, which made the link blend into the sentence; use the VS Code text-link colours instead. * refactor(webview): rename imagesUnsupported to unsupportedImagesAttached The flag also requires images to be attached, so the old name read like a plain negation of modelSupportsImages. |