mirror of
https://github.com/cline/cline.git
synced 2026-10-25 18:33:44 +08:00
* 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>