mirror of
https://github.com/cline/cline.git
synced 2026-10-25 18:33:44 +08:00
bee/installer-script
546
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2895a16927 | fix(core): load embedded plugin and dashboard resources | ||
|
|
7e8d22c789 | fix(vscode): settle pending questions before posting state (#14839) | ||
|
|
41e75efc53 |
fix(vscode): honor disabled rule toggles in SDK sessions (#14605)
* fix(vscode): persist rule toggle state for SDK loader * fix(vscode): confine rule toggle frontmatter writes and preserve authored YAML - Only write rule documents the SDK loader actually reads (.md, .markdown, .txt, or the bare .clinerules file) that resolve, through symlinks, to a regular file inside the scope's rules root (global Rules dir or the workspace .clinerules). Anything else keeps the extension-state toggle only. - Edit the top-level `disabled` entry line by line instead of re-dumping the YAML block, so comments, key order, quoting, CRLF line endings and a UTF-8 BOM survive a toggle. Re-parse before writing and leave the file untouched if the result would not parse. Skills share the helper and get the same. - Reconcile extension state with frontmatter on rules refresh: toggles turned off before this fix are written to the file so SDK sessions honor them, and a file disabled by hand wins over a stale enabled toggle. * fix(vscode): write rule toggles into every rule root the panel scans Rebase adjustment: since the rules panel now scans both .clinerules and .cline/rules plus every global location the shared resolver knows, the frontmatter write and the state<->frontmatter reconcile take the same directory lists instead of the two hardcoded roots. * fix(vscode): make rule files authoritative for toggles after a one-time back-fill - Match the SDK's disabled precedence: a boolean `disabled` wins, `enabled: false` only counts when `disabled` is absent. - Recognize quoted frontmatter keys when editing the disabled line. - Return written/skipped/failed from the frontmatter write; on failure the toggle handler reverts the state toggle and returns the reverted map so the panel keeps showing what the SDK loads. - Back-fill state toggles into frontmatter once, behind a new global state flag; afterwards the file is the source of truth for the panel in both directions, so removing `disabled` from a file re-enables the rule. - Only write files the SDK loader reads: direct children of a rule root, or the single legacy .clinerules file. * fix(vscode): back-fill rule toggles per workspace and accept uppercase YAML booleans - The one-time back-fill marker is now keyed per scope (global, and one entry per workspace path), so a workspace opened after another one was migrated still gets its pre-fix off toggles written into its rule files instead of having them flipped on by the file-wins reconcile. - The enabled: false matcher accepts False and FALSE, which both YAML parsers in play read as boolean false, so re-enabling removes those lines too. * fix(vscode): keep the workspace back-fill marker in workspace state Each window holds its own copy of global state and the last writer wins per key, so two windows migrating different workspaces could erase each other's marker in the shared record. The global marker is a plain flag again and the workspace marker moves to workspace state, keyed by workspace path, which is per window and never shared. * fix(vscode): report a rule toggle as failed when the file could not be edited safely The frontmatter helper returns the document unchanged both when it already carries the requested state and when it cannot be edited safely (malformed YAML, or an edit that would not re-parse). The write wrapper treated both as success, so the toggle handler kept the new state while the SDK kept loading the old one. An unchanged document now counts as written only if it parses and already matches the requested state; otherwise the handler reverts. * fix(vscode): retry a failed rule back-fill and keep comments after inline disabled values - A back-fill write that fails (read-only file, malformed frontmatter) keeps the off toggle and leaves the scope's migration marker unset, so the next refresh retries instead of treating the unwritten file as re-enabled. - An entry with an inline scalar value is a single line, so an indented comment after `disabled: true` is no longer removed with it. * fix(vscode): track the rule back-fill per rule instead of per scope A scope-wide migration marker forced a choice between two failure modes: mark the scope done after a failed back-fill (the unwritten rule turns on), or keep the whole scope pending (a rule the user re-enabled by hand gets back-filled again). Each rule now records whether its file is authoritative. A rule joins that set when state and file agree, when the file disables it, when its back-fill succeeds, or when the toggle handler writes it; only a rule whose back-fill failed stays pending and is retried on the next refresh. The global set lives in global state and the workspace set in workspace state, replacing the unreleased scope markers. Also handle an inline disabled value that continues on later lines (a flow collection or a split quoted string) by taking lines until the entry parses. * fix(vscode): keep global rule authority records in their own settings file Every window caches global state and persists its whole snapshot, so a window that started before another one back-filled a global rule kept no record of it. After the user re-enabled that rule by editing its file, refreshing the stale window back-filled it again. The global records now live in settings/cline-rules-frontmatter-authority.json, re-read on every refresh and merged on every write, so windows only ever add to them. Records for deleted rule files are dropped on write. Workspace records stay in workspace state, which is a separate file per workspace. * fix(vscode): make the rule file the only source of truth for rule toggles Drop the one-time back-fill of toggles saved before the toggle wrote frontmatter. Telling such a toggle apart from a rule the user re-enabled by editing its file needs per-rule history, and every place to keep it (scope flags, global state, workspace state, a settings file) failed across multiple windows, crashes, or hand edits. The Rules panel now shows what the frontmatter says on every refresh, and the toggle writes it. A rule switched off before this fix shows as on after upgrading, which is what the SDK has been loading, and is switched off once more. Removes the per-rule authority records, the authority settings file, and the localClineRulesFrontmatterAuthoritative workspace key. The multi-layout refresh test now marks its disabled fixtures in frontmatter. * fix(vscode): verify the requested state before reporting a toggle write The rule and skill write paths trusted the frontmatter editor's output. An edit that left a disabling flag the editor did not recognize (for example a legacy `enabled: false` whose value is on the next line) was written and reported as success, so the panel showed the rule or skill as on while the SDK still excluded it. Both paths now re-parse the edited document and treat anything not in the requested state as a failure, so the rule toggle handler reverts and the skill write reports false without writing. * fix(vscode): edit rule and skill frontmatter by YAML source range The line-based editor guessed entry boundaries from line shapes. It missed a legacy `enabled: false` whose value sits on the next line, matched `disabled:` lines inside multi-line string values (changing unrelated metadata while still producing valid YAML), and dropped comments on and around the flag. The editor now parses the frontmatter with the SDK loader's YAML parser and splices only the source ranges of the top-level `disabled` and `enabled` entries. Disabling sets an existing value or appends `disabled: true`. Enabling removes those entries, or flips the value in place when the entry carries a comment so the comment survives. Anything the SDK would reject (invalid YAML, duplicate keys, non-boolean flags) is left untouched, and an edit is discarded unless every other value is unchanged and the result is in the requested state. The Rules panel reads state with the same parser. Declares `yaml` (already a workspace dependency through @cline/core) as a direct dependency of apps/vscode. * test(vscode): mock @cline/core before it is loaded in the bun harness The preload imported the real @cline/core to read its export names and then mocked it. Mocking an already-loaded module makes bun re-link the graph, and that re-link leaves a slice of @cline/shared's source-tree exports undefined (stripUtf8Bom among them) for everything under sdk/packages/core, which resolves @cline/shared to shared/src through core's tsconfig paths. Any real SDK function the stub re-exports then threw when called from a test. The export names now come from a child process, cached on the built package's mtime, the mock is registered first, and the stub and @cline/llms are imported after it. * fix(vscode): let the SDK parser decide a rule's enabled state The extension kept its own copy of the SDK's rules for reading a rule file's enabled state, and every review round found a case where the copy and the SDK disagreed: flag precedence, uppercase booleans, non-boolean values, and now frontmatter that is not a mapping, which the SDK loads as having no metadata but the copy treated as unloadable. A rule starting with a markdown divider line could not be switched off. The Rules panel, both write paths, and the editor now ask parseRuleConfigFromMarkdown / parseSkillConfigFromMarkdown from @cline/core, so they cannot disagree with what the SDK loads, now or after the SDK changes. The editor still parses the block as a YAML document, but only to locate the source ranges it edits. A file with non-mapping frontmatter is disabled by adding a disabled: true block above it, and re-enabling restores it exactly. A comment-only block gets the flag appended inside it. A file the SDK does not load at all (unparseable frontmatter, non-boolean flag, empty body) now shows as off in the panel, since nothing from it reaches the model; switching it on fails and reverts, with the reason logged. The bun test stub re-exports the two parsers from the SDK source. --------- Co-authored-by: 33modeling <33modeling@gmail.com> |
||
|
|
9857d19fc4 |
fix(vscode): keep the session's mode in sync when Plan/Act is toggled during a session start (#15026)
* test(vscode): cover Plan/Act toggles that race a session start A toggle that lands while a session is being started or replaced sees no active session, flips only the setting, and leaves the session running with the other mode's tools. These tests reproduce that and fail on main. * fix(vscode): keep the session's mode in sync when Plan/Act is toggled during a session start Starting or replacing a session detaches the outgoing one before the new one is active. A toggle in that window saw no session, flipped only the setting, and the session that finished starting kept the other mode's tools, so the UI showed Act while every write was blocked as plan mode. - Sessions record the mode they were built for. - The toggle decides under the rebuild lock, after waiting for session starts that run outside it (new task, edited message, checkpoint restore). - The toggle and the rebuild compare against the session's mode rather than the setting, which also fixes the stale mode notice the late rebuild left. * test(vscode): release session-start waiters when the start fails Cover a waiter that is already in place when a tracked start rejects. The previous check only waited after the rejection, so an implementation that rejected existing waiters would still have passed. |
||
|
|
dc3d7a58c9 |
fix(vscode): keep keyboard focus when revealing the terminal for a command (#15061)
* fix(vscode): keep keyboard focus when revealing the terminal for a command Every foreground run_commands execution called terminal.show() with no argument, which makes VS Code move keyboard focus into the terminal. A user typing in the chat input while Cline starts a command had the rest of their keystrokes land in the shell, corrupting the running command. Pass preserveFocus=true at both reveal sites (the per-command reveal in runCommand and the pre-cd reveal of a reused terminal). The terminal panel is still revealed, which is all shell-integration initialization needs. * test(vscode): stub the command process in the reveal-only terminal test The reveal test fed the process a never-ending stream, so its VS Code shell-execution and terminal-close listeners outlived the test. Stub run() instead; the test only checks the reveal call. |
||
|
|
731f48462b |
Support MCP Resources [NO-OP] (#15165)
* Support MCP Resources * Small fixes * Address PR comments * remove CreateMcpToolsOptions mcpApps option |
||
|
|
44b388b998 |
chore(vscode): fix integration test runner on macOS (#15088)
* chore(vscode): fix integration test runner on macOS Bump @vscode/test-electron to 3.1.0, which resolves the macOS executable from Info.plist. VS Code 1.110+ renamed Contents/MacOS/Electron to Code and dropped the compatibility symlink, so 2.5.2 failed every run with `spawn .../Contents/MacOS/Electron ENOENT`. Also pass a short --user-data-dir on macOS. VS Code puts its IPC socket in the user data dir, and the default .vscode-test/user-data overflows the 103-char unix socket limit from deep checkouts such as worktrees (`listen EINVAL ... 1.14-main.sock`). Linux and Windows keep the default. * test(vscode): drop the macOS E2E executable fallback @vscode/test-electron 3.1.0 resolves the macOS executable from the app bundle's Info.plist for both Stable and Insiders, so downloadAndUnzipVSCode now returns Contents/MacOS/Code directly and the Code / Code - Insiders fallback never runs. |
||
|
|
01b8a9724d | chore(vscode): release v4.1.25 | ||
|
|
9098d603cc |
feat(webview): name the host editor in Cloud sessions copy (#15133)
* feat(webview): name the host editor in Cloud sessions copy The Cloud sessions copy said "your editor". Name the editor the user is actually in instead: "VS Code", "Cursor", "PyCharm" and so on. The extension already gets the product name from the host bridge (getHostVersion's platform); fetch it once and pass it to the webview as hostName. The webview shortens it the way users say it (drops the JetBrains edition, "Visual Studio Code" -> "VS Code") and falls back to "your editor" when the host is unknown. * fix: read the host name from HostRegistryInfo instead of a bridge call HostRegistryInfo already holds getHostVersion's platform from startup, so building webview state no longer waits on the host bridge. The tooltip test now asserts the visible text instead of reusing the function it tests. * fix(webview): fall back to "your IDE" when the host is unknown |
||
|
|
1faa00fa25 |
fix(webview): use editor-neutral wording in Cloud sessions copy (#15123)
The webview is shared with the JetBrains plugin, where "after you close VS Code" is wrong. Say "your editor" instead in the onboarding/GitHub cards, the Run task hint and the cloud auto-approve tooltip. |
||
|
|
cd01a92faa | security: dependency floor lifts for open Dependabot advisories (#15132) | ||
|
|
3834735da2 | fix(webview): keep the Run task card above the Auto-approve bar in JetBrains (#15120) | ||
|
|
2ffa920b0e |
fix: add /v1 to host-only OpenAI Compatible base URLs once, on VS Code and JetBrains (#15108)
* fix(vscode): migrate host-only OpenAI Compatible base URLs to /v1 once
Earlier extension builds sent requests for a host-only OpenAI Compatible base
URL to <host>/v1. #15057 now uses the URL as entered, so persist the /v1 for
existing users once instead of retrying requests at runtime.
* Revert "fix(vscode): migrate host-only OpenAI Compatible base URLs to /v1 once"
This reverts commit
|
||
|
|
0474213f6c |
fix(vscode): keep Auto Compact and its strategy together in Feature settings (#15109)
The Cloud toggle was appended to the agent toggle list, which renders before the Auto Compact Strategy dropdown, so it split Auto Compact from its strategy. Render the Cloud row after Web Search instead. |
||
|
|
adc7b15535 |
fix(vscode): include attachments in ask_question answers (#15059)
* fix(vscode): include attachments in ask_question answers Answer a pending ask_question with the user's images and attached files in the tool result itself, as the pre-SDK extension did, instead of dropping them. The SDK's AskQuestionExecutor may now return text and image blocks (the same shape read_file returns), and the answer bubble shows the attachments. * fix(vscode): let cancel settle an ask_question answer while attachments load Cancelling the task while an answer's attached files were still being extracted could not release the question, so the old run (and anything waiting for it to stop) stalled until extraction finished. Keep the claimed resolver reachable so clearPending settles it immediately. |
||
|
|
868464e4f3 |
fix(vscode): don't append default path to OpenAI Compatible base URL (#15057)
* fix(vscode): don't append default path to OpenAI Compatible base URL normalizeSdkBaseUrl inherited the SDK default path (/v1) for URLs with no path, turning https://abc.com into https://abc.com/v1. OpenAI Compatible endpoints are user-supplied and were passed verbatim by the legacy client, so skip default-path inheritance for this provider. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix(vscode): reword base URL comment per review Co-authored-by: Mikołaj Kondratek <19799111+mkondratek@users.noreply.github.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: Mikołaj Kondratek <19799111+mkondratek@users.noreply.github.com> |
||
|
|
1932d5dc37 |
feat(vscode): Cline Cloud sessions - run tasks in a hosted sandbox from the extension (#13799)
* feat(sdk): support header-authenticated remote Hub connections Ports the NodeHubClient resolveConnectionHeaders option from #13519 so a client can authenticate a remote proxy's WebSocket upgrade with HTTP headers (refreshed on every reconnect), and threads it through HubRuntimeHost and RemoteRuntimeHost so ClineCore remote runtimes can reach Cline Cloud sandboxes. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * feat(vscode): cloud session runtime, control-plane client and history integration Adds the extension-host side of Cline Cloud sessions: - CloudSessionsService: REST client for GitHub App status/repos/branches and the outer session records (create/list/status/delete/rename/history) - CloudSessionHost: an SdkSessionHost over RemoteRuntimeHost that dials the sandbox Hub through the api.cline.bot proxy with the account token, maps outer/inner ids and re-emits events so the existing chat pipeline is reused - SdkCloudSessionCoordinator: starts/reopens cloud tasks, keeps sandbox connections alive to track running/finished status, notifies on completion and projects cloud sessions into task history - CloudService proto + handlers, NewTaskRequest execution target, history cloud fields/filter, ext-cloud-sessions feature flag Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * feat(vscode): cloud sessions UI — home task-target panel, running strip, history and account - Home screen: Local | Cloud chooser above the composer with GitHub repo and branch pickers (prefilled from the workspace's origin remote and branch) and an onboarding card that walks through connecting GitHub, polling until done - Running-in-the-cloud strip and cloud status pills in Recent/History, plus a Cloud Only history filter - Task header cloud badge (repo @ branch, opens the dashboard); cloud tasks render inline diffs, hide checkpoint/restore and only attach images - Account view: Cline Cloud card with GitHub connection status Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * fix(vscode): cloud task fixes found in manual testing - claim the task-view generation after clearTask (which bumps it), so cloud task start/open is not treated as superseded and left on Thinking - track completion from the agent done event and keep completed/failed over the trailing idle status so History shows Done instead of Cloud - stop the branch picker from re-querying on every render - readable popover text in the repo/branch pickers; hide cost chips on cloud rows Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * docs(vscode): cloud sessions follow-ups and test stub for org switch reset Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * fix(vscode): make cloud sessions Act-only Match the desktop app and the cloud dashboard: cloud sessions are created in Act mode regardless of the selected mode, no per-turn mode is sent, the host refuses Plan/Act toggles while a cloud session is active, and the webview pins the toggle to Act (disabled, with a tooltip) while a cloud task is shown or about to start. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * test(vscode): add local cloud session boundary * fix(vscode): preserve cloud outcomes and stale-work ownership * fix(vscode): drain cloud cleanup before account changes * fix(vscode): build cloud sandbox config through the Cline path * docs(vscode): clarify cloud proxy rollout boundary * fix(vscode): close cloud picker when leaving chat * fix(vscode): wait for cloud session before opening dashboard * fix(vscode): keep account history in document flow * fix(vscode): report available cloud task usage * fix(vscode): cancel cloud tasks during provisioning * fix(vscode): make cloud model billing explicit * fix(vscode): hide local approvals for cloud tasks * fix(vscode): resolve cloud prompt before session adoption * fix(vscode): seed local cloud development profile * fix(vscode): sanitize local cloud fixture errors * fix(vscode): handle cloud state before hydration * fix(core): honor proxies for remote Hub WebSockets * fix(vscode): preserve cloud task IDs * fix(vscode): explain cloud auto-approval * test: repair cloud and proxy CI fixtures * fix(vscode): resolve cloud status after restart * fix(vscode): resolve flags for restored accounts * fix(vscode): keep cloud tasks in the cloud and in Act mode * test(vscode): let the local cloud fixture delay model replies CLINE_LOCAL_CLOUD_MODEL_DELAY_MS holds the scripted reply so cancellation and navigation can be exercised while a cloud task is still thinking. * fix(vscode): cancel a cloud task that is still provisioning Cancelling during "Starting a cloud sandbox..." did not stop the start: - Cancel arriving while initTask awaited remote config found no pending start, so the sandbox went on to provision, connect and run the prompt behind a "Resume Task" view, and the user paid for a sandbox they had cancelled. initTask now claims the cloud start before its first await. - Cancel arriving during the readiness poll took effect only after the sandbox came up. createSession accepts an abort signal that stops the poll, so the unused record is deleted as soon as the control plane answers. - clearTask (New Task) now cancels a pending cloud start too; a provisioning task has no SDK session for the task controller to end. The local cloud fixture reports `ready` like the hosted control plane and accepts CLINE_LOCAL_CLOUD_PROVISION_DELAY_MS to hold new sandboxes in `provisioning`, so this window is reproducible. The cloud Vitest config restores the Zod namespace export the same way vitest.config.ts does. * fix(vscode): keep cloud status displays truthful and hosts open while in use A status check that resolved a cloud task as idle or finished closed the host while openCloudTask could still be reading messages or attaching the session on that same host. Entries now count the openCloudTask calls using them, and neither status resolution nor the idle sweep disposes a host that is pinned or belongs to the displayed task. Cancelling a cloud start while remote config was still loading left the turn phase at streaming after the view had returned home. initTask no longer sets the phase for cloud starts; the coordinator sets it once the start is still current and its task view is installed. useResolvedCloudStatuses kept a resolved status after history reported a newer one, so a task resolved as running stayed "Working" after it completed. The hook now returns statuses only for tasks history still reports as unknown, and the running strip lists a task only while its effective status is active or unconfirmed. An unknown status showed a spinner labelled "Checking" for as long as connections kept failing. It is now shown as Unconfirmed with a static icon; only provisioning and running animate. * test(core): run the proxy tunnel fixture with a real Node executable When Bun runs vitest it reports its own Node-compatible shim as process.execPath and places it first on PATH. That runtime ignores NODE_EXTRA_CA_CERTS, so the spawned fixture failed TLS verification on the Windows CI runner. The test now looks past the shim for an installed Node and is skipped when none is available. * fix(vscode): remember cloud task status across restarts After a restart every cloud row in History showed "Unconfirmed" and joined the running strip until a socket to each sandbox re-learned its status, and the first status a socket reported bumped the row's timestamp to now, reordering History (CLINE-3307, CLINE-3424, CLINE-3418). The coordinator now writes the last settled status it confirmed over a live connection to global state (`cloudSessionStatuses`, keyed by session id with the observation time) and reads it back when it first sees a record. The remembered status is trusted only while the control plane's `updatedAt` is no later than the observation plus a one-minute grace, because the control plane touches `updatedAt` when a client connects; a later touch means another client may have run the agent, so the row falls back to unknown and is resolved live as before. Active statuses are never remembered. Ids the account no longer lists are pruned on every list refresh. A connection that only learns the current status no longer counts as activity; the row's timestamp moves only when the status changes while connected or the user sends a follow-up. * fix(vscode): settle account switches without blocking History * fix(vscode): refresh stale cloud outcomes without restarting * test(vscode): wait for cloud run cleanup before removing sandbox * fix(vscode): reserve switch errors for account transitions * refactor(vscode): remove unused cloud accessors and refresh notes * test(vscode): seed expired sessions and a 402 model reply in the cloud fixture The loopback fixture only ever served live sandboxes, so the read-only expired path and the out-of-credits path could not be exercised without a day's wait or real spend. CLINE_LOCAL_CLOUD_SEED_EXPIRED=1 seeds two Personal sessions whose sandboxes are gone: one with an archived transcript, one that answers /history with the control plane's 404 "no history captured". Their WebSocket upgrade returns 410 like the real proxy and /status reports "expired". CLINE_LOCAL_CLOUD_INSUFFICIENT_CREDITS=1 makes every scripted model reply the hosted API's 402 insufficient_credits body. * fix(vscode): explain expired cloud sessions instead of showing an error Opening a cloud task whose sandbox the control plane retired showed a red error row and, when no transcript had been archived, a synthetic Done row above it. QA read this as data loss (CLINE-3322). The row is now an informational notice that says the sandbox was retired after 24 idle hours and names the repository to start a new cloud task on. It tells three cases apart: the archived conversation is shown above it; no conversation was archived (the control plane answered 404); or the archive could not be loaded right now, with the error. An empty transcript is no longer rendered, so no Done row appears. The History pill reads Archived with a tooltip explaining the retirement. * fix(vscode): show the out-of-credits card for cloud task failures A cloud turn that failed on the Cline API's 402 insufficient_credits reply ended with Retry / Start New Task and no explanation (CLINE-3376). A Hub-hosted session does not forward the agent's "error" event; the client learns of the failure only from run.failed, which the runtime host turns into done(reason: "error") with the failure message as its text. The translator recorded the error outcome for that event but rendered nothing. done(reason: "error") now renders the same api_req_started and api_req_failed rows as an "error" event, once per turn, so ErrorRow shows the Buy Credits card (or the plain error) for cloud tasks as it does for local ones. Both paths share one helper. * fix(vscode): explain cloud sessions deleted or retired since History loaded Opening a cloud task deleted from the dashboard showed "Could not connect to this cloud session: Unexpected server response: 404" and left the row in History (CLINE-3377). The Hub client reports only the HTTP status of the refused upgrade. A failed connection now asks the control plane for the session's status. A deleted session shows a notice and leaves History; a session retired since the list was fetched opens as expired, with its archived conversation if one exists. Other failures keep the connection error. The loopback fixture now answers an unknown session's upgrade with 404, as the hosted proxy does, instead of 401. * fix(vscode): only suggest cloud branches that exist on GitHub The cloud branch picker was prefilled with the workspace's checked-out branch even when it had never been pushed. The sandbox clones from GitHub, so the session then failed to start (CLIENTS-109). The workspace default is now the remote branch the checkout corresponds to: its upstream on origin when one is configured, otherwise the same name when origin has it. A local-only branch yields no suggestion and the picker falls back to the repository's default branch. Branches listed from the GitHub API were already remote. * fix(vscode): accumulate streamed text for cloud tasks A cloud task's reply flickered chunk by chunk and only appeared whole when the message finished (CLIENTS-111). The translator showed each content_start's `accumulated` text, falling back to the chunk alone. A local session sends the running total, but a Hub-hosted session forwards assistant.delta as a bare chunk, so each update replaced the last. The translator now keeps the running total itself when `accumulated` is absent, and clears it with the other per-block streaming state. * fix(vscode): show the cloud model in the composer while Cloud is selected With Cloud selected, or a cloud task open, the composer footer still showed the local provider and model, e.g. anthropic:claude-opus, although the sandbox runs a Cline model (CLIENTS-116). The extension now reports cloudModelId in state: the model the displayed cloud task runs on, else the one a new cloud task would start with. The start path and the label share one function, so they cannot disagree. The composer shows it as cline:<model> whenever it pins the mode to Act for Cloud. * fix(vscode): release the retained host of a deleted cloud session When a session opened from History turns out to have been deleted, its entry leaves the registry. A connection retained from an earlier status check stayed open with nothing to watch; dispose it with the entry. * fix(vscode): keep expired-session and cloud-model displays truthful An archived cloud transcript was rendered with the final turn marked completed, so the last reply of a task that was still running when its sandbox retired showed as a green Done box. Retirement is not completion; the final reply now stays a plain text row. An archive that exists but holds no messages rendered nothing yet the notice pointed at "the conversation above", and the History tooltip promised a readable conversation for every Archived row. An empty archive now reads as none, and the tooltip says to open the session to see whether one was saved. With a non-Cline local provider the composer showed the cached or fallback recommendation while the start path refreshed the list first and could pick a different model. The start now uses the model shown when the user submitted, snapshotted before any await, and the composer warms the recommendation cache once so the label moves from the fallback to the live recommendation before the next submit. * fix(vscode): confirm an account switch overtaken by its own auth update switchOrganization confirmed a switch by re-reading the organizations and treating an answer overtaken by a newer read as no answer. The extension's auth refresh after the PUT starts such a newer read, so a switch that succeeded returned false and the ClinePass switch control asked the user to retry it. Every read now returns the server's answer; only the newest read still writes context state. * fix(core): connect header-authenticated Hub sockets under Bun The desktop sidecar runs the cloud session controller under Bun. Since a2cefba05 the header-authenticated Hub client imported the npm `ws` package through a `node-ws` alias so a proxy agent could be attached. Under Bun 1.3.13, the toolchain this branch was pinned to, Bun's node:http client never emits `upgrade`, so the npm `ws` treats the 101 as an ordinary response and connect() fails with "Unexpected server response: 101". Cloud sessions in the desktop app could not connect. Import `ws` directly again. Bun substitutes its own client, which reads the proxy URL and Proxy-Authorization from the same `agent` option that Node's `ws` uses, so one socket shape tunnels on both runtimes and the `node-ws` dependency and its @ts-expect-error go away. The tunnel test now runs the fixture under Bun as well as Node. Bun's TLS client does not read NODE_EXTRA_CA_CERTS, so the Bun leg tunnels a plain ws:// destination; it still checks the CONNECT, the upgrade and where the credentials land. With the `node-ws` import the Bun leg fails on 1.3.13 and the Node leg passes, which is the gap that let this ship. * fix(vscode): retry the cloud model recommendation after a failed fetch The composer shows the model a new cloud task will run on. When the local provider is not Cline that is the top recommendation, warmed once by the coordinator. A fetch that failed returned the built-in fallback without caching it, but the coordinator kept its warm-up handle, so it never asked again and the fallback stayed in the composer and in new sandboxes until the extension restarted. Release the handle when a fetch settles without filling the cache, so the next state post retries. * fix(vscode): stop the recommendation warm-up from polling a failing endpoint The warm-up posted state after every fetch, including one that returned the built-in fallback. That post reads the model again, which starts the next fetch, so a recommendation endpoint that keeps failing was polled without bound while Cloud was selected with a non-Cline provider. Post state only when the fetch filled the cache. A failed fetch still releases the handle, so the next read the user causes retries. * fix(vscode): disable the composer while a cloud sandbox is provisioning The composer allows sending during the streaming phase so follow-ups can queue on a running task, and a cloud start sets that phase while the sandbox is still provisioning. There is no session to queue on yet, so askResponse hit the expired-session guard and answered "This cloud session is no longer running" while the sandbox kept starting, dropping the message. The displayed cloud task now reports status provisioning while its start is pending, and the composer keeps submit disabled on that status so the draft stays in place until the sandbox is running. * fix(vscode): re-enable the composer after a failed cloud start The failure path posts state while the start is still pending, so the composer kept seeing "provisioning" and stayed disabled. Post state once more after the pending start is cleared. The askResponse guard, still reachable through the extension API while the composer is disabled, now says the sandbox is starting instead of that the session is gone. * style(vscode): wrap two JSX lines the CI formatter rejects Biome 2.4.5 on main wraps these attributes; the branch's Quality Checks failed on them after the rebase onto that formatter version. * test(vscode): pin the composer's provisioning status through a failed start The displayed cloud task reports provisioning while its start is pending, and the last state post after a failed start no longer carries it, so the composer re-enables without waiting for an unrelated refresh. * fix(vscode): keep a draft typed while a cloud task is provisioning handleSendMessage cleared the composer a second time after its RPC resolved. Every send path already clears the draft before the RPC, so the second clear only ever removed text the user typed while the RPC was pending. A local newTask resolves too quickly to notice; a cloud newTask resolves only after the sandbox is provisioned, so the draft the disabled composer was holding for the user vanished when the sandbox came up. * fix(vscode): follow main's rename of the sign-in retry field #14628 replaced pendingClineAuthRetryPrompt with pendingClineAuthRetry. The cloud coordinator's clearTask callback and the cloud branch of initTask still cleared the old field, which no longer exists. * fix(vscode): tear down cloud sessions when ClinePass switches the account Selecting the ClinePass provider switches the active account to Personal by calling switchAccount directly. The Account view's organization switch runs the same call inside resetCloudSessions, which detaches the displayed cloud task and its authenticated hosts and drains pending cleanup before the account changes. Without that, an organization cloud task stayed on screen after the account became Personal, and a still-pending DELETE could use the new account's credentials. Route the ClinePass switch through the same reset, and only when an organization is active: every API configuration update passes through this path, and the reset would otherwise clear a displayed cloud task for a model change that switches nothing. * fix(vscode): page History's Cloud Only filter after filtering The Cloud Only filter ran on a page already cut from the merged local-and-cloud list, and hasMore was computed from that page. With more than a page of newer local tasks the first page came back empty while cloud tasks existed further down, and hasMore said there was nothing more. When Cloud Only is on, list the whole history, filter, then apply offset, limit and hasMore to the filtered records. * fix(vscode): stop reporting a model change the cloud sandbox never made CloudSessionHost.updateSessionModel called an optional method that RemoteRuntimeHost does not have, then recorded the new model anyway. Choosing a different local model while a cloud task was displayed made the composer name that model while the sandbox kept running on the one it was started with. The Hub protocol has no command to change a running session's model, so drop the method. The lifecycle already treats a host without it as unable to switch, and the composer keeps naming the model the sandbox was started on. * fix(vscode): hide a cloud task's cost until the sandbox reports usage The task header decided whether to show the cost badge from the local provider's cost display setting. For a cloud task with no usage yet that showed $0.0000, which reads as a confirmed zero for a charge that is not known. Cloud tasks now show the badge only when the sandbox has reported usage; local tasks keep the provider-based decision. * fix(vscode): do not offer to open a cloud task's files in the local editor Cloud edits render through DiffEditRow, whose file name and open icon call openFileRelativePath. The path is relative to the sandbox's /workspace, so clicking opened an unrelated local file or failed. The row now takes canOpenFile; ChatRow passes false for cloud tasks, which drops the click action and the open icon and leaves the path as plain text. * fix(vscode): keep the cloud repository and branch choice truthful Two ways the stored cloud target could name something the current account cannot start a sandbox on: - The repository selection persists across account changes. When the new account has no accessible repositories the panel showed onboarding, but the old URL stayed stored, so the composer still treated the target as ready to submit. Clear the stored repository once the account's list is known and does not contain it. - The workspace branch was persisted from the local remote-tracking ref without checking GitHub. A branch deleted on GitHub but not pruned locally was suggested and submitted, and provisioning failed. Start on the repository's default branch and ask GitHub for the workspace branch by name; the unfiltered branch list is paginated, so its first page cannot decide. Suggest the branch only if GitHub returns it and the default branch is still selected, so a branch the user has since chosen stays. * fix(vscode): reconcile retained cloud connections with the account's list Two ways a cloud session's record and its connection could disagree: - A list refresh kept any entry that still had a host, so a task deleted from the dashboard stayed in History with an open authenticated connection, and a 401 cleared the entries without closing their hosts. An entry whose record has left the list, or every entry on a 401, is now dropped and its host closed. The displayed task is the exception in both cases: its host stays so that opening it can explain a deletion, and so that signing in again after a 401 leaves a task that can continue. - When a sandbox retires after History was listed, its WebSocket rejects with 410 while /status may answer 200 with status "expired". The probe treated every successful /status as "not expired", so the task opened to a connection error instead of the retirement notice. A 200 that says expired now counts as retirement, like a 410. * fix(vscode): subscribe monitored cloud tasks to their Hub event stream The Hub streams a session's events only to clients subscribed to it, and the runtime host subscribes when it first sends a command for that session. A connection opened only to resolve a History row's status sent none: it listed sessions, read the status, and then waited on an event stream that was never opened. A turn finished by another client left the row on Running and the completion notification never fired. Listing the task's pending prompts after discovery sends that first command and opens the stream. * test(vscode): keep the local cloud fixture alive when a client drops its socket An extension host that reloads or exits closes its bridged WebSocket without a close frame. The bridge attached no "error" listener to either side, so ws raised an unhandled error and the fixture process exited, taking every sandbox with it. Terminate the failed socket instead. * Own the account boundary in switchAccount Four paths changed the active account (the Account view, ClinePass selection and two remote-config paths) and only one of them tore down the previous account's cloud task and connections first. Each caller had to remember to wrap the switch, and two did not. switchAccount now runs every change inside a boundary the controller installs once (the cloud coordinator's reset), and serialises switches: one requested while another is in flight waits for it and then decides against the account as it is then. A caller that read a stale account cannot skip a needed switch or repeat one that just happened, so the ClinePass gate and the Account view's pending-switch map are gone. * Resolve the cloud task target in the extension The task-target panel computed the whole stored target from five effects (account repositories, workspace remote, GitHub branch check, repository click, Local/Cloud click), each writing the result back. Any two could interleave and the later write won: a branch check that landed after the user clicked Local flipped the target back to Cloud. The extension now stores only what the user chose, one field per choice (Local/Cloud, a repository, a branch), and resolves the rest on every state post: the stored repository if this account can reach it, else the workspace's, else the first; the user's branch, else the workspace branch once GitHub confirms it exists, else the default. Nothing derived is written, so no lookup can override a click, and a repository chosen under another account is never submitted. Failed lookups retry after 30 seconds; the GitHub connection is cached per account and shared with the Account view. The webview panel renders the resolved view and sends each click as one choice. * test(vscode): keep the cloud fixture alive when the Hub socket fails early The fixture's session proxy attached its error handler to the upstream Hub socket only after "open". An error during the handshake was unhandled and exited the fixture process, which the extension then saw as "Timed out connecting to hub after 8000ms". Attach the handler at construction for both sides of the bridge. * Refresh aged cloud-target inputs and always restore the server account The task-target resolver cached repositories and the workspace checkout for as long as the account and directory stayed the same. Repository access changes in the browser and the checkout changes in the terminal, and neither notifies the extension, so the picker could keep offering a revoked repository or suggesting the previous branch. A loaded input now ages out (repositories after 60 s, the checkout after 10 s): a read past that returns the cached answer and reloads behind it. switchAccount skipped the request when the cached account already matched. The server's active account is shared by every client on the login, so another client may have moved it. The request is now always sent; only the cloud teardown is gated on the cached account changing. * Retry a failed cloud start instead of declaring the session gone A cloud task whose sandbox never came up shows "Failed to start the cloud session" with Retry / Start New Task, but Retry appended "This cloud session is no longer running" and the footer then stayed disabled: the webview holds its recovery claim until the turn phase advances, and the refusal never advanced it. The coordinator now hands the failed input to the controller, which keeps it as the same pending start retry a "Sign in to Cline" error uses. Retry runs the cloud task again on the same repository and branch; a prompt typed into the composer starts one with that prompt. Refusing a response to a session that is gone sets the turn phase, so the footer releases its claim either way. The task-header tooltip no longer doubles its full stop when the task has no repository. The local cloud fixture starts a sandbox's Hub when the session becomes ready rather than on the first socket upgrade, so a cold start cannot outlast the client's connect timeout. * test(vscode): let the cloud fixture refuse session sockets CLINE_LOCAL_CLOUD_REFUSE_SOCKETS=1 answers every session socket upgrade with 503, so a cloud start fails after its sandbox is ready and the footer's Retry path can be exercised by hand. * Replace the carried-forward transcript when the new epoch's snapshot lands Retrying a failed cloud start appended the new attempt below the old one instead of replacing it. The new task's first partials reach the webview before the debounced state snapshot of the new epoch; the reducer deliberately carries the old rows forward on a lone newer-epoch partial, but then treated the snapshot as same-epoch and merged, so the old rows were never removed. The replica now remembers that it carried rows forward, and the first snapshot at that epoch replaces them while keeping the newer-epoch partials already held. A prompt typed after a failed start also left its optimistic bubble below the new task row: the bubble is user_feedback, but a restart is confirmed by a task row. Any user-authored row with the same text and attachments now confirms the bubble. * test(vscode): keep the cloud scope fixture complete Supply the failed-start callback required by the cloud retry path and assert that the coordinator hands it the failed task and original input. Check the fixture keys against the options interface before casting its partial service doubles, so a new required option fails typechecking. * fix(vscode): send Cancel to the task on screen, not a cloud start left behind (#14794) A cloud start stays pending after the user opens another task from History. Cancel always cancelled that pending start first, so cancelling a running task (cloud or local) cleared its view instead, and a cloud turn kept running in its sandbox. Only cancel the pending start when its own view, or no task, is on screen. * fix(vscode): delete cloud sandboxes left provisioning by a reload or quit (#14791) * fix(vscode): delete cloud sandboxes left provisioning by a reload or quit A terminating extension host cannot reach the network (VS Code's fetch resolves proxies through the window it is detaching from), so the cleanup DELETE a reload or quit triggers during provisioning never leaves the process and the sandbox is orphaned. Record each provisioning sandbox in a per-extension-host file under the Cline data directory until its task starts or its cleanup is confirmed, and let the next extension host delete records whose owner has exited. * fix(vscode): recover abandoned cloud starts only when it is safe Address review of the abandoned-start journal: - Keep a record until the control plane confirms the sandbox is gone. A 401, 429 or 5xx no longer erases it; only a successful DELETE or a 404 under the account and endpoint that started it settles it. - Keep a record until the sandbox has started the first turn, not just until the send was queued. Recovery connects to a sandbox before deleting it and leaves one that already holds a conversation, in case the host exited after the turn was accepted but before recording that. - Name each journal by pid and extension-host lifetime and refresh it while it has records, so an earlier lifetime of this pid, or a pid reused by another process, reads as abandoned instead of being skipped or overwritten. - Run recovery as one scope operation of the account that started the sandboxes: an account change waits for a DELETE in flight and stops the rest, nothing runs after disposal, and reset and dispose cancel the recheck timer. * fix(vscode): never recover a cloud start that may still be live - A sandbox's saved transcript stays empty until the first turn's iteration ends, so recovery could delete a task whose first turn was running. Treat any Hub session status other than idle as a turn the sandbox has taken. - Drop the journal heartbeat. A missed refresh does not prove the owner exited (it may be paused in a debugger or asleep), so a journal whose pid is alive is never taken; a pid reused by another process only delays recovery until that process exits. - Bound the sandbox inspection with a timeout and stop awaiting its detach, so an unresponsive sandbox cannot hold the account scope. * refactor(vscode): simplify abandoned cloud start recovery Drop the record right before the first prompt is sent instead of waiting for the sandbox to report turn acceptance. A surviving record then means the prompt never left the extension host, so its sandbox holds no user work and recovery can just DELETE it. This removes the turn-acceptance tracking in CloudSessionHost and the sandbox inspection (connect, status check, transcript read, timeout) that recovery needed to tell an orphan from a live task. Also fail the start when the record cannot be written, so its normal cleanup DELETE runs while the host can still reach the network, and treat only ESRCH as proof that a journal's owner has exited. * fix(vscode): fail a cloud start whose pending record cannot be dropped Recovery deletes any recorded sandbox without inspecting it, so the record must be gone before the first prompt is sent. If dropping it fails, fail the start instead of sending; its normal cleanup then deletes the sandbox. After a confirmed deletion a leftover record is harmless, so that path only logs. * fix(vscode): preserve provisioning tasks opened from History (#14793) Keep a pending cloud start alive when its own History row is opened, reject older selections, and relist its sandbox when startup settles. Carry the task-view fence across clearTask instead of claiming again. Retain abandoned-start journaling from the target branch and verify its record survives own-row reopening until immediately before the first send. * fix(vscode): keep a failed cloud start's images when Retry is clicked The webview's Retry response omits images, which protobuf decodes as an empty list, so `images ?? retry.images` dropped the attachments and the retried sandbox ran on the text prompt alone. Fall back to the failed start's images unless the response actually carries some. * fix(vscode): stop sending the account token into cloud sandboxes (#14970) * fix(vscode): keep cloud sessions out of Delete All History (#14967) * fix(vscode): keep cloud sessions out of Delete All History * fix(vscode): report the actual Delete All History count * fix(vscode): cancel a provisioning cloud start when the account changes (#14968) * fix(vscode): forget a remembered cloud status once the agent runs again (#14969) * fix(vscode): forget a remembered cloud status once the agent runs again * test(vscode): cover forgetting a remembered status on connect * feat(vscode): resume suspended cloud sandboxes and use the SDK's cloud client (#14973) * test(vscode): let the local cloud fixture suspend and resume sandboxes * fix(vscode): resume suspended cloud sandboxes instead of treating them as unknown * fix(vscode): reopen cloud tasks whose last turn failed * refactor(vscode): talk to the cloud control plane through the SDK's CloudSessionApi * feat(vscode): show cloud provisioning progress and dashboard renames * refactor(core): export the cloud session system prompt * feat(vscode): give cloud sandboxes the SDK's shared prompt and work-branch rules * perf(vscode): keep the local model catalog out of cloud session.create * docs(vscode): update cloud session follow-ups for the SDK alignment * fix(vscode): reconnect from scratch after resuming a suspended sandbox * fix(vscode): link an organization to its own GitHub connect page * test(vscode): only auto-suspend resumable fixture sandboxes * fix(vscode): show the resume notice when a suspended cloud task is opened from History showTaskWithId only dismisses the History view after the open completes, which for a suspended sandbox is after the whole resume. The notice the coordinator posts stayed covered and History sat unchanged for the duration. Bring the chat view forward right after the notice is posted. * fix(vscode): keep the UI on the server's account after a slow switch (#14971) * fix(vscode): keep the UI on the server's account after a slow switch * fix(vscode): retract a switch error only from the newest account read * feat(vscode): opt-in Cloud toggle in Settings behind ext-cloud-sessions (#15018) * feat(vscode): add opt-in Cloud toggle in Settings behind the ext-cloud-sessions flag * fix(vscode): refresh History when the Cloud toggle changes * fix(vscode): close four cloud-session gaps found in review and QA - A cancelled cloud start left a ghost STARTING row in History. A list during provisioning adds an entry for the new record before the start holds one, and cleanupUnusedSession only dropped the caller's entry. It now drops the entry by session id and invalidates History after the DELETE settles. - A failed DELETE left entry.host pointing at a disposed host, so a reopened task stopped reporting status. The host is cleared before disposal. - Switching repositories left the previous repository's branches selectable while the new list loaded, so a stale branch could be saved against the new repository. The list is cleared and the picker disabled until it loads. - Attached files were silently dropped from a cloud start. The composer now refuses the send and says why. - compile-tests could not resolve @cline/core/cloud under classic node resolution; tsconfig.test.json maps the subpath to the built declarations. * docs(vscode): track cloud session follow-ups as GitHub issues instead of a checked-in file * merge: preserve latest VS Code cloud updates with reviewed fixes * Saoudrizwan/cloud greptile fixes 26ac (#15073) * test(vscode): stub @cline/core/cloud for the CommonJS integration host * fix(vscode): keep the open cloud task's model visible when Cloud is turned off * fix(vscode): restore a cloud runtime the Hub lost after a turn reports it missing --------- Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Cline Agent <cline-agent@users.noreply.github.com> Co-authored-by: Dominic Cooney <dominic.cooney@cline.bot> Co-authored-by: Dominic Cooney <dominiccooney@users.noreply.github.com> Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> Co-authored-by: Dominic Coon <dominic@cline.bot> Co-authored-by: John Choi <john.choi@cline.bot> |
||
|
|
26cea2fa8b |
fix: stop undici's 5-minute idle timeout killing local model requests (#15024)
* fix(lmstudio): disable undici's idle-body timeout so slow local generations aren't killed mid-stream * fix(lmstudio): compose the bodyTimeout override onto the active dispatcher instead of replacing it * fix(vscode): disable undici idle timeouts for local model providers Node's fetch applies undici's default 300s headersTimeout/bodyTimeout, each measuring time since the last byte received. Local servers (LM Studio, Ollama) legitimately go silent for longer while processing a large prompt (headers arrive immediately, then no body bytes until the first token), so long requests died mid-task with 'terminated: BodyTimeoutError (UND_ERR_BODY_TIMEOUT)' even though the server was still generating. Route LM Studio and Ollama inference through a fetch bound to an EnvHttpProxyAgent with headersTimeout/bodyTimeout disabled. This calls undici's own fetch rather than global fetch because VS Code's http.fetchAdditionalSupport patch replaces caller-supplied dispatchers with its own default-timeout Agent. Cancellation stays with each request's AbortSignal. Fixes #13464 Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * fix(vscode): disable undici idle timeouts for providers that may run a local model Combine the two earlier drafts: dispatch through undici's own fetch so the override survives VS Code's global fetch wrapper, and keep the env-var proxy agent so JetBrains proxy support is unchanged. Widen the provider set from LM Studio and Ollama to also cover OpenAI Compatible and LiteLLM, which telemetry shows carry most of the UND_ERR_BODY_TIMEOUT failures. The net test now exercises real undici fetch against a local server that flushes headers and then stays silent, with a short-timeout control to prove the silence is long enough to trip the default timer. * test(vscode): keep the idle-timeout net test off any machine-level proxy * chore: drop the changeset file, the repo no longer uses changesets * fix(vscode): only skip idle timeouts when the base URL is on the local network OpenAI Compatible and LiteLLM often point at remote corporate gateways. On VS Code, fetchWithoutIdleTimeouts bypasses the host's proxy handling (http.proxy, OS/PAC proxy, proxyStrictSSL), so routing those through it would break proxied setups. Gate on the base URL as well: loopback, private/link-local/CGNAT ranges, single-label hosts and .local/.internal names get the idle-timeout-free fetch; remote gateways keep the proxy-aware fetch and its dead-connection cap. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * fix(vscode): keep loopback direct in fetchWithoutIdleTimeouts, cover 0.0.0.0 and mapped IPv4 EnvHttpProxyAgent sends loopback through http_proxy whenever no_proxy is unset, which VS Code's own resolver never does. Pick a plain Agent for loopback hosts and the env-var proxy agent for everything else, both with idle timeouts off. The local-network gate now also accepts 0.0.0.0 and IPv4-mapped IPv6 addresses, which Ollama and LM Studio print when bound to all interfaces. The net test now runs with HTTP_PROXY set and NO_PROXY unset against a recording CONNECT proxy: loopback never touches it, an unroutable host goes through it, and neither path has an idle timeout. * fix(vscode): match loopback by address so IPv4-mapped IPv6 stays direct The URL parser rewrites [::ffff:127.0.0.1] to [::ffff:7f00:1], which a string match on "127." misses. Use a BlockList, which checks mapped addresses against the IPv4 rules, for the loopback bypass and drop the now-redundant unwrapping in the local-network gate. --------- Co-authored-by: lizhe <marshal_li_b@163.com> Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
ed469c753a | chore(vscode): release v4.1.24 | ||
|
|
c606894cb1 |
Revert "fix(vscode): preserve attachments in pending question responses (#14986)" (#15058)
This reverts commit
|
||
|
|
f8997dac23 |
fix(vscode): preserve attachments in pending question responses (#14986)
* fix: preserve attachments in VS Code question responses * fix(vscode): preserve pending question response ordering * fix(core): preserve display text in Hub submitted prompt events |
||
|
|
12a4c6bfe2 |
feat(core): load plugins in the hub process and surface plugin errors (#14957)
* feat(core): load plugins in the hub process and surface plugin errors
Plugins now load in-process through one registry per process instead of a
node/bun subprocess. The compiled CLI and the hub it starts no longer need a
runtime on PATH, and plugins can use the Bun global under the Bun-built hub.
The subprocess sandbox stays available with CLINE_PLUGIN_MODE=sandbox.
The registry wraps import, setup, every hook, tool, and command call with
timeouts and error capture, and tracks loading/ready/degraded/failed/disabled
per plugin with the last error's phase, message, stack, and counts. A failing
plugin no longer silently drops its tools:
- session.create takes a `plugins` policy shaped like toolPolicies, and its
reply and session.created event carry `pluginIssues`
- failures after start (setup and hooks run on the first turn) reach each
affected session as a status notice
- the hub answers plugins.list/status/reload and broadcasts
plugin.status_changed; `cline hub plugins [--reload]` wraps them
- the daemon marks a plugin failed instead of shutting down when an uncaught
error's stack points into it
- the CLI prints a warning naming the plugin and error, and
`cline config tools --json` lists failed plugins as plugin_failure entries
Setup and tool contexts gain cwd and emitEvent; __clinePluginHost keeps
working as a shim. Compiled binaries fall back to jiti/static when babel is
not on disk next to them.
* fix(core): give each session its own copy of every plugin module
Plugins written for the per-session sandbox keep state at module level. The
cline-monitor plugin, for example, builds one plugin object per import and
throws "Create a separate monitor plugin handle for each session" on a second
setup(). Sharing one imported copy across hub sessions broke it on the
second session.
The registry now hands each session its own copy: the first session claims
the copy imported at startup, and later ones re-evaluate the module while
reusing jiti's transform cache (about 180ms for cline-monitor instead of
2.8s with no cache).
A setup() failure now costs only the session it happened in: other sessions
keep their copies, the next session tries again, and a successful setup
returns the status to ready. Import failures, attributed uncaught errors, and
repeated hook/tool failures still turn the plugin off for every session.
* docs(sdk): document the plugin hooks that exist and how hook failures behave
The Hook Stages list (snake_case stages such as tool_call_before) and the
Hook Policies table (mode, retries, queueLimit, maxConcurrency) described no
code: plugin hooks are the seven runtime hooks, and there is no per-hook
policy object. Replace both with the real hooks, what each can return, and
how hookErrorMode and the 3-second hook timeout apply.
* fix(core): report failed plugins as failed in settings
Settings marked a plugin "failed" only when the plugin tool report had no
entry for it. The report now lists failed plugins with their state, so they
showed as "available" (desktop Extensions page and other core settings
hosts). Use the reported state, and fill loadError with the failing phase
and message so the reason is visible.
Also tell only the calling session about a per-session setup failure;
other sessions' copies still work. Keep the hub log line's own message
instead of letting the plugin error text overwrite it.
* fix(core): address plugin registry review findings
Reload and generations: each session copy records the generation (import)
it came from. A reload starts a new generation without invalidating older
copies, so running sessions keep working. Failures and blocking are counted
per generation, so a broken reload cannot turn off copies that still work,
and an old copy's failures cannot change the current status. A stray error
attributed by stack turns off every live generation, since a stack cannot
tell copies of one file apart.
Sandbox mode: the hub daemon no longer preloads plugins in sandbox mode,
and tool listing and MCP settings sync inspect plugins through the sandbox.
The session plugin policy now applies in sandbox mode: paths whose file
name the policy turns off never reach the sandbox, and plugins matched only
by their exported name are dropped after import.
Calls: commands, rule content, and message builders go through the same
guarded path as hooks and tools (timeout, error capture, failure count), and
calls into a copy that is turned off, failed setup, or whose session ended
are refused. A failing rule contributes no text and a failing message
builder leaves messages unchanged.
Cleanup: ctx.onDispose registers per-session cleanup. Timers a copy creates
while its own code runs, including at import, are tracked and cleared when
the session releases the copy; host callbacks given to plugins run outside
that scope so host timers are never cleared with them. Release runs on
session stop and dispose, and now also when building the session runtime
fails. The automation-events example uses ctx.onDispose.
Registrations: automation event types are validated while setup runs. If
the host still rejects a registration on commit, the copy's setup is
recorded as failed and the error is rethrown so the partial registrations
are discarded.
Also: forward importTimeoutMs, hookTimeoutMs, and contributionTimeoutMs to
the in-process registry per session; key the plugin tool inspection cache on
registry status; keep the module copy imported by preload for the first
session; report settings-disabled plugins a session would use as issues
with reason "settings".
* fix(core): keep this bindings and route import-time plugin events
- Timer tracking forwards the runtime's this (the timer handle in Node and
Bun) to plugin callbacks.
- Plugin methods keep their receiver: rule content, message builders,
command handlers, and setup() are called on their own objects, including
setup() in the existing in-process loader.
- Each plugin copy owns one async scope from import onward. Claiming the
copy for a session fills in that scope's session id and event callback,
so events emitted by work the module started at import reach the session.
- Each generation tracks its own health, so an older copy's first failure
after a reload is reported to its sessions even though the status shows
the reloaded generation.
* fix(core): bind plugin changes to sessions started afterwards
Plugins are bound to a session when it starts; added, edited, or reloaded
plugins reach only sessions started afterwards. Change detection used the
entry file's mtime and size, which missed edits to files the entry imports
(common for package plugins) and same-size edits within one clock tick, so
the next new session could claim a stale preloaded copy.
Detect changes with a content fingerprint of the entry file and every file
it reaches through relative static imports, for the registry, the plugin
tool inspection cache, and the plugin command service. Add a bootstrap test
that a session started before a plugin is added or changed keeps its
original tools even when its setup runs afterwards, and a registry test for
a change outside the entry file.
* fix(core): include side-effect imports in plugin change fingerprints
The fingerprint only followed `from`, `import()`, and `require()`
specifiers, so a fix to a file the entry imports only for side effects
(`import "./setup.js"`) left the fingerprint unchanged and new sessions kept
getting the failed entry.
Scan statement-level side-effect imports for the fingerprint only. They are
kept out of the dependency preflight, where a loose match on text inside a
string (`'run import "x" first'`) would reject a valid plugin.
* fix(core): retry failed plugin imports on a backoff
Change detection follows static and side-effect relative imports, but a
broken import can also be fixed where no fingerprint sees it: a dynamically
imported file, a file behind a block comment, or a dependency installed in
node_modules. Such plugins stayed failed until an explicit reload.
Retry a plugin whose import failed when a session starts, at most every 30
seconds, even if no change was detected. A broken plugin costs at most one
extra import attempt per 30 seconds, bounded by the import timeout.
Replace the SHA-1 fingerprint with a non-cryptographic checksum; it only has
to notice edits to plugin source.
* feat(desktop): show plugin failures in the chat
Plugin failures reached the desktop webview only as core logs written to the
devtools console. Show them as status lines in the chat:
- session start returns `pluginWarnings` for plugins the session asked for
but could not load, and the webview adds one status line per warning
- plugin notices that arrive later on the session stream (setup and hooks
run on the first turn) carry `metadata.pluginIssue`; the webview adds
those as status lines too, while other core logs stay out of the
transcript
* fix(desktop): keep plugin warnings when saved history reloads
Finishing a turn replaces the live transcript with saved history, which
never contains plugin warnings (they come from the start reply and stream
notices), so the explanation of a missing plugin disappeared after the first
turn. Carry the session's live plugin-warning lines into canonical history
at their original position by time.
* refactor(core): simplify the in-process plugin registry (#14999)
* refactor(core): simplify the plugin registry
Drop the pieces added in review rounds that cost more than they buy:
- Global timer tracking. It monkeypatched setTimeout/setInterval/
setImmediate and their clear* counterparts on globalThis for the whole
host process (the hub, the CLI, and the shared VS Code extension host),
and attributed timers by async scope, so a host callback invoked from
inside a plugin call had its timers cancelled when the session released
its plugin copy. Plugins stop what they start in ctx.onDispose, which
stays.
- Plugin generations and per-generation health. Blocking and consecutive
failures are counted per plugin again; a re-import (reload or source
change) resets them. Running sessions keep their copies callable unless
the plugin is turned off, so a broken reload fails closed for them.
- Automatic retry of failed imports on a 30 s backoff, and the side-effect
import scan in the change fingerprint. plugins.reload covers changes the
fingerprint cannot see.
- The duplicated registerAutomationEventType validation; the commit
try/catch already records a host-rejected registration as a setup
failure.
* refactor(core): do not apply the session plugin policy in sandbox mode
The sandbox is an opt-in escape hatch and the per-session policy is new;
filtering sandbox results by file-derived and exported names added two
passes nobody needs yet. The policy is documented as in-process only.
* revert(desktop): drop the live plugin-warning merge into saved history
Reverts
|
||
|
|
ff255c08a9 |
feat(vscode): show dedicated ai& provider settings (#14611)
* feat(vscode): show dedicated ai& provider settings Selecting ai& in the extension showed the generic OpenAI-compatible form (base URL, model ID, custom headers, Azure options). Register aiand as a known provider so it gets the standard API key + model picker form, backed by the SDK builtin (fixed base URL https://api.aiand.com/v1, catalog models, default zai-org/glm-5.3). * chore: drop unused changeset file |
||
|
|
62f690d6ca |
fix: load and watch symlinked rule files (#14912)
* fix: load symlinked rule files from config directories
* fix(core): automatically reload symlinked instruction targets
* fix(core): drop symlink target watching, keep link-path loading
Review feedback on #14912: reading rules through the link path already
fixes the reported bug, and each new session re-reads the rules. Watching
wherever links point is a larger change than the bug needs and carried
loose ends (directory links in the target path, a readlink per file on
every refresh).
- revert the target-directory watching, chain walk and broken-link
retention from
|
||
|
|
bf71bf7cd9 |
Default to the first Cline recommended model (Sonnet 5.5 fallback) across CLI, extension, and desktop (#14959)
* Default to the first Cline recommended model (Sonnet 5.5 fallback) across CLI, extension, and desktop - @cline/shared: CLINE_DEFAULT_MODEL_ID is now the anthropic/claude-sonnet-5.5 fallback - @cline/llms: the cline provider's defaultModelId prefers GENERATED_CLINE_RECOMMENDED_MODELS.recommended[0] - CLI: resolve the provider's SDK default before falling back to the first catalog entry; drop the hardcoded sonnet-4.6 fallback - VS Code: openRouterDefaultModelId -> anthropic/claude-sonnet-5.5; cline provider falls through to the SDK default Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Default the SDK openrouter provider to anthropic/claude-sonnet-5.5 The VS Code extension's OpenRouter model field is populated from this SDK default via resolveModelInfo, so the extension-side openRouterDefaultModelId constant alone did not change the fresh-install selection. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Desktop: adopt the provider catalog default model once the catalog loads A fresh install booted on CLINE_DEFAULT_MODEL_ID and kept it when the user skipped onboarding, so the chat bar never picked up the Cline provider's recommended-list default. Swap the bootstrap fallback for the catalog default unless a model was already remembered for that provider. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Scope the recommended-model default to the Cline providers Only cline/cline-pass declare a curated default; other manifests may expose a placeholder like "default" (ollama, lmstudio), so the CLI keeps falling back to the first catalog entry for them. The desktop bootstrap swap now also applies only to new Cline chats, never to hydrated sessions. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Test both branches of the cline default model selection Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Simplify: drop the desktop bootstrap swap and connector catalog lookup The desktop app keeps CLINE_DEFAULT_MODEL_ID as its pre-onboarding default (onboarding already stores the provider's recommended default), and the connector only swaps its hardcoded literal for the shared constant. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * CLI: only the cline provider uses the SDK default before the catalog cline-pass's manifest default is just the first bundled model, not a curated pick, so it keeps the live catalog's own ordering. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Connectors: prefer the provider's declared default over the Cline fallback Non-Cline connector sessions with no saved model were handed a Claude id. Use the provider manifest default when it is a real model, skipping the "default" placeholder that catalog-less local providers expose. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> --------- Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
2f4e36e86f | fix(vscode): preserve prose spacing when deleting slash commands (#14883) | ||
|
|
93e5e455e6 |
chore: remove the dead subscribeToRelinquishControl stream (#14974)
Its only sender, sendRelinquishControlEvent, was removed as unused in
|
||
|
|
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) |