Skip to content

chat: start cloud sandbox sessions from a draft participant like the cloud agent - #341697

Merged
Osvaldo Ortega (osortega) merged 10 commits into
mainfrom
osortega/cloud-sandbox-transcript-progress
Oct 15, 2026
Merged

Osvaldo Ortega (osortega) merged 10 commits into
mainfrom
osortega/cloud-sandbox-transcript-progress

Conversation

@osortega

@osortega Osvaldo Ortega (osortega) commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Follows #341695 (merged).

Problem

Sending a cloud sandbox draft went through IChatSessionItemController.newChatSessionItem. Provisioning progress was shown in a notification, the chat input stayed "in progress" with an empty transcript until the real session loaded, failures ended up in notifications instead of the thread, and until the agent named the session it showed up as a GUID in the editor header, the sessions list and recorded history.

Approach

The Copilot cloud agent already solves this without new platform machinery: a chat participant serves the draft's first turn (stream.progress for the steps) and, once the task exists, commits the draft to the real session (onDidCommitChatSessionItem), which swaps the editor/view, transfers state and migrates queued requests. This PR gives the core cloud sandbox contribution the same shape:

  • commitChatSession (new, chatSessions/chatSessionCommit.ts): the commit logic that MainThreadChatSessions.$onDidCommitChatSessionItem applied for extension providers, extracted into a ServicesAccessor function so core providers can commit a draft too. MainThreadChatSessions now just resolves the session type and delegates; no behavior change for extension providers.

  • Cloud sandbox contribution: drops newChatSessionItem/IProgressService and registers a dynamic participant for the cloud-sandbox draft type (the chat widget already locks a draft to the participant named after its type). Its invoke:

    1. provisions the sandbox, reporting each step as one in-place progressMessage (shimmer) in the draft's transcript — "Creating Cloud Session for owner/repo: Setting up cloud container / Connecting to cloud container / Cloning repository…"; the draft's input is blocked meanwhile so a follow-up can't be queued against a session that doesn't exist yet;
    2. confirms the draft's mode/approval picks with the host (unchanged);
    3. aliases the draft's options to the new session and commits the draft to the environment's session via commitChatSession;
    4. re-sends the turn on the committed session with the draft's mode, model and attachments (agentIdSilent = the environment's session type), where the environment's Agent Host handler runs it exactly as any later turn.

    Cancellation (stop button) and errors now surface on the draft turn in the thread.

Nothing changes on the wire: the same Mission Control task creation and rename the Agents window already performs, and the same AHP createSession + turn dispatch as any other turn. The handoff is client-side orchestration only.

Titles

  • The new session is seeded and its Mission Control task named after the first line of the prompt, as the Agents window does, so lists show the prompt instead of Mission Control's default name until the agent titles the session. A transient rename failure does not block the first turn.
  • The host session itself is not renamed, so the agent's generated title still arrives and replaces the prompt (in the Agents window a client rename suppresses it). Editor-created sandboxes therefore end up auto-titled; worth keeping in mind if we want the two windows to match.
  • Until the agent names a session, the sandbox host reports the session id as its title. That is recognized in one place, isCloudSandboxPlaceholderTitle (cloudSandboxAgentHost.ts), and applied through the connection customization hook isSessionTitlePlaceholder for the live handler, by the session list (which keeps the label it already shows) and for recorded history. This is a compensation, not a design: AHP's SessionMetadata.title has no "untitled" meaning and VS Code's own agent host publishes an empty title. The rule can go once the sandbox host does the same or the protocol defines the untitled case.

Tests

editorCloudSandboxContribution.test.ts drives the registered participant instead of newChatSessionItem and covers: provisioning + alias + commit + re-send ordering with the draft's picks and attachments; a new session listed under its prompt until the agent names it, never under an id; the task rename (transient failure continues, not-found fails); cancellation before and during commit; follow-ups blocked while provisioning; a rejected re-send recorded on the committed session; non-draft resources, no-repository drafts, host config confirmation and connection failures. cloudSandboxSessionHandler.test.ts and agentHostChatContribution.test.ts cover the placeholder title for recorded history and the live handler.

Testing locally

Quit Code OSS, npm run build-fast -- --client-only, ./scripts/code.sh, open a GitHub repo, start a new Cloud session from the session type picker and send a prompt. Progress shows in the transcript; the thread switches to the real session when the sandbox is ready, listed under the prompt until the agent titles it.

@osortega
Osvaldo Ortega (osortega) force-pushed the osortega/cloud-sandbox-transcript-progress branch from b3c8920 to 1edfb56 Compare October 15, 2026 07:28
Base automatically changed from osortega/accepted-firefly to main October 15, 2026 15:57
@osortega
Osvaldo Ortega (osortega) requested a balanced review from Copilot October 15, 2026 15:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Follow-up messages retain the draft-agent lock, and repository searches exclude accessible collaborator repositories.

2 open findings
What changed in this PR

Moves cloud sandbox provisioning progress into the chat transcript and corrects first-send agent routing, alongside the stacked repository-picker changes.

Changes:

  • Adds transcript progress and cancellation through the chat sessions service.
  • Re-keys silent agent selection when a draft materializes.
  • Moves repository discovery into the renderer and expands regression coverage.
File Description
src/​vs/​workbench/​contrib/​chat/​test/​common/​mockChatSessionsService.ts Mocks preparation progress.
src/​vs/​workbench/​contrib/​chat/​test/​common/​chatService/​chatService.test.ts Tests cross-type first-send routing.
src/​vs/​workbench/​contrib/​chat/​test/​browser/​widget/​chatWidget.test.ts Tests progress-aware empty state.
src/​vs/​workbench/​contrib/​chat/​test/​browser/​remoteAgentHost/​editorCloudSandboxContribution.test.ts Tests provisioning progress, cancellation, and picker integration.
src/​vs/​workbench/​contrib/​chat/​test/​browser/​remoteAgentHost/​cloudSandboxRepositoryPicker.test.ts Tests repository searches and authentication failures.
src/​vs/​workbench/​contrib/​chat/​common/​chatSessionsService.ts Defines preparation progress APIs.
src/​vs/​workbench/​contrib/​chat/​common/​chatService/​chatServiceImpl.ts Re-keys silent agents during materialization.
src/​vs/​workbench/​contrib/​chat/​browser/​widget/​chatWidget.ts Displays preparation progress in the transcript.
src/​vs/​workbench/​contrib/​chat/​browser/​remoteAgentHost/​editorCloudSandboxContribution.ts Publishes provisioning progress and integrates repository picking.
src/​vs/​workbench/​contrib/​chat/​browser/​remoteAgentHost/​cloudSandboxRepositoryPicker.ts Implements renderer-side GitHub repository discovery.
src/​vs/​workbench/​contrib/​chat/​browser/​chatSessions/​chatSessions.contribution.ts Stores and broadcasts preparation progress.
src/​vs/​workbench/​contrib/​chat/​browser/​chat.shared.contribution.ts Normalizes null picker options from RPC.
src/​vs/​workbench/​contrib/​chat/​browser/​agentSessions/​repositoryPicker.ts Supports normalized local filtering.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Base: a32a8413 Current: 712d2e41

No screenshot changes.

@osortega
Osvaldo Ortega (osortega) force-pushed the osortega/cloud-sandbox-transcript-progress branch from c65659d to ca51afc Compare October 15, 2026 17:44
@osortega Osvaldo Ortega (osortega) changed the title chat: show cloud sandbox creation progress in the chat transcript chat: start cloud sandbox sessions from a draft participant like the cloud agent Oct 15, 2026
@osortega
Osvaldo Ortega (osortega) force-pushed the osortega/cloud-sandbox-transcript-progress branch from ca51afc to 51fbcec Compare October 15, 2026 18:51
…cloud agent

Sending a cloud sandbox draft used to go through `newChatSessionItem`, which
reported provisioning in a notification and left the chat input spinning until
the real session loaded. The Copilot cloud agent instead serves the draft's
first turn with a chat participant and commits the draft to the real session
once it exists, so the same chat machinery (editor swap, state transfer, queued
request migration, `onDidCommitSession`) is reused here:

- `commitChatSession` is the commit logic that `mainThreadChatSessions` applied
  for extension providers, extracted so core providers can commit a draft too.
- The cloud sandbox contribution registers a participant for the `cloud-sandbox`
  draft type. Its first turn provisions the sandbox while updating a single
  shimmering progress line in the transcript, commits the draft to the
  environment's session and re-sends the turn there with the draft's mode,
  model and attachments, where the environment's Agent Host handler runs it.
  Errors and cancellation surface on the draft turn instead of a notification.
…ession

A fresh sandbox session is titled after its id by the host, so the chat editor
showed a UUID once the session's state arrived. The Agents window already
ignores that stand-in (`isSessionTitlePlaceholder`); the remote agent host
handler now does the same through a connection customization the cloud sandbox
contribution supplies, so the chat keeps its current title until the agent
names the session.
…agent names it

The sessions list labelled a new repo-less sandbox with the Mission Control
task id, flipped to the task's name ("New remote session") once discovery ran,
and then to the session id once the host listed the session. Seed the entry
with the task name discovery will report, and keep the listed label when the
host reports the session id as the title, as the Agents window does.
…nts window

Drop the seeded "New remote session" label: the Agents window titles a new
cloud session's placeholder after the first line of the prompt and names the
Mission Control task the same way (`setInitialSessionTitle`), so neither the
task id nor Mission Control's default name is ever shown. Provisioning now seeds
the list entry with that prompt-derived title and the editor renames the task
to it before the first turn, tolerating a transient Mission Control failure the
same way. The host still auto-titles the session; that title replaces the
prompt when it arrives.
Keeps the placeholder handling for default-chat titles that came with it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…while naming the task

`renameTask` rethrows transport errors unwrapped, so the `instanceof
CloudSandboxRequestError` guard treated them as permanent and failed creation
after the sandbox was already connected. Only cancellation and non-retryable
HTTP failures abort now.
- Block the draft's input while its sandbox is provisioned, as the Agents
  window keeps its placeholder read-only: a follow-up queued on the draft would
  be dropped when the environment's first turn hydrates the host's empty queue
  over the migrated one.
- Stop before re-sending when the draft was cancelled while being committed.
- Forward images the widget expanded from directory attachments; they only
  exist on the resolved request, not in the attached context.
- Record a rejected re-send on the committed session, since the draft that
  would have shown the error is already replaced.
The host reports the session id as the title of an untitled session; define that once, with why it exists and when it can go, instead of three private copies.
@osortega
Osvaldo Ortega (osortega) merged commit 5c76d51 into main Oct 15, 2026
58 of 59 checks passed
@osortega
Osvaldo Ortega (osortega) deleted the osortega/cloud-sandbox-transcript-progress branch October 15, 2026 23:58
@vs-code-engineering vs-code-engineering Bot added this to the 1.143.0 milestone Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants