Add agent-host skill buttons to changes view#311815
Draft
roblourens wants to merge 28 commits intomainfrom
Draft
Add agent-host skill buttons to changes view#311815roblourens wants to merge 28 commits intomainfrom
roblourens wants to merge 28 commits intomainfrom
Conversation
Mirrors the Copilot CLI extension's commit/merge/PR buttons for agent-host sessions in the Agents app. Buttons are contributed to the ChatEditingSessionApplySubmenu so they render as a dropdown alongside the existing apply-to-parent-repo actions. Also adds a typed ISessionGitState accessor under the protocol-level ISessionMeta bag so clients can read git state (branch, ahead/behind, PR-related affordances) without parsing raw _meta. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pp-pull-request-skills-issue # Conflicts: # src/vs/sessions/contrib/agentHost/browser/localAgentHostSessionsProvider.ts # src/vs/sessions/contrib/remoteAgentHost/browser/remoteAgentHostSessionsProvider.ts
Contributor
There was a problem hiding this comment.
Pull request overview
Adds Agents-app (“sessions window”) equivalents of the Copilot CLI extension’s commit/merge/PR actions for agent-host sessions, and plumbs a typed git-state payload through the agent-host session metadata so the UI can drive correct affordances (branch, ahead/behind, PR gating).
Changes:
- Introduces agent-host skill buttons contributed to
ChatEditingSessionApplySubmenu, and styles them appropriately in the Changes view. - Adds protocol-level
_meta(ISessionMeta) and a typed_meta.git(ISessionGitState) accessor path; overlays git state into session summaries on the agent-host side. - Updates workspace/session list metadata propagation and adds unit tests for customization resolution, git parsing/state, and menu/context-key wiring.
Show a summary per file
| File | Description |
|---|---|
| src/vs/workbench/contrib/chat/test/browser/agentSessions/resolveCustomizationRefs.test.ts | New unit tests for resolving customization refs (plugin vs bundled files, built-ins). |
| src/vs/workbench/contrib/chat/test/browser/agentSessions/agentHostChatContribution.test.ts | Stubs IPromptsService and tests propagation of git state into session item metadata. |
| src/vs/workbench/contrib/chat/browser/chatSessions/chatSessions.contribution.ts | Exports resolvePromptSlashCommand for reuse by Sessions-window skill buttons. |
| src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentHostSessionListController.ts | Carries _meta through and maps _meta.git into IChatSessionItem.metadata keys used by Changes view. |
| src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentHostChatContribution.ts | Collects built-in skills via IPromptsService.findAgentSkills and factors resolveCustomizationRefs for testing. |
| src/vs/sessions/contrib/remoteAgentHost/browser/remoteAgentHostSessionsProvider.ts | Extends workspace builder signature to accept ISessionGitState. |
| src/vs/sessions/contrib/changes/browser/changesView.ts | Applies button styling/badge behavior to agent-host skill actions. |
| src/vs/sessions/contrib/agentHost/test/browser/agentHostSkillButtons.test.ts | New tests for context key binding and menu registrations for skill buttons. |
| src/vs/sessions/contrib/agentHost/browser/localAgentHostSessionsProvider.ts | Extends workspace builder signature to accept ISessionGitState. |
| src/vs/sessions/contrib/agentHost/browser/localAgentHost.contribution.ts | Ensures agent-host skill buttons are registered in Sessions window. |
| src/vs/sessions/contrib/agentHost/browser/baseAgentHostSessionsProvider.ts | Threads readSessionGitState(metadata._meta) into workspace construction and adapter options. |
| src/vs/sessions/contrib/agentHost/browser/agentHostSkillButtons.ts | New action/menu contributions that run built-in skills by sending /<skill> prompts via IChatService. |
| src/vs/sessions/common/agentHostSessionWorkspace.ts | Includes base-branch info in workspace identity and stores base-branch fields on repository entries. |
| src/vs/platform/agentHost/test/node/copilotGitProject.test.ts | Updates test git-service stub to satisfy new getSessionGitState API. |
| src/vs/platform/agentHost/test/node/copilotAgent.test.ts | Updates test git-service stub to satisfy new getSessionGitState API. |
| src/vs/platform/agentHost/test/node/agentService.test.ts | Adds tests verifying git state overlay into _meta.git during listSessions. |
| src/vs/platform/agentHost/test/node/agentHostGitService.test.ts | Adds unit tests for git parsing helpers and on-disk tests for getSessionGitState (skipped if git missing). |
| src/vs/platform/agentHost/node/agentService.ts | Overlays computed git state into _meta during listSessions; propagates _meta when restoring sessions. |
| src/vs/platform/agentHost/node/agentHostMain.ts | Wires a single AgentHostGitService instance into AgentService and DI. |
| src/vs/platform/agentHost/node/agentHostGitService.ts | Adds getSessionGitState with short TTL caching plus parsing helpers for status/remotes/default branch. |
| src/vs/platform/agentHost/common/state/sessionState.ts | Adds _meta.git well-known key + ISessionGitState interface and read/write helpers. |
| src/vs/platform/agentHost/common/state/protocol/state.ts | Introduces ISessionMeta and optional ISessionSummary._meta. |
| src/vs/platform/agentHost/common/agentService.ts | Mirrors _meta?: ISessionMeta onto IAgentSessionMetadata. |
| src/vs/platform/agentHost/browser/remoteAgentHostProtocolClient.ts | Propagates _meta from protocol session summaries into metadata objects. |
| extensions/copilot/package.json | Suppresses Copilot CLI extension’s session buttons when sessions.isAgentHostSession is true. |
Copilot's findings
- Files reviewed: 25/25 changed files
- Comments generated: 3
Going through IChatService.sendRequest directly bypassed widget-owned view most importantly the tool confirmation rendering wired upstate in IChatWidget._acceptInput. It also let us pass the wrong agentIdSilent (the shared logical sessionType 'copilotcli' instead of the per-host chat-session contribution type 'agent-host-copilotcli'), which routed clicks to the EH copilotcli extension rather than the active local/remote agent-host session. Look up the chat widget by session resource and call acceptInput, which handles slash-command parsing, locked-agent resolution, instructions, and tool confirmation UI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Base:
|
…agent id Removes the standalone Commit it has no equivalent in the EHbutton copilotcli extension's contributions to the apply submenu (which only exposes commitAndSync, gated to workspace-isolation), so its presence made Commit appear as the dropdown's primary action for agent-host sessions where Merge wasn't applicable. Reverts the dispatch back to IChatService.sendRequest with agentIdSilent (matching the pattern in chatSessions.contribution.ts's openSessionWithPrompt action). Going through the chat widget required a mounted IChatWidget for the session, which isn't available when only the Changes view is clicks were silently bailing on the no-widgetopen guard. The agent id correctness fix from the previous attempt is preserved: pass session.resource.scheme (e.g. agent-host-copilotcli), not the shared logical sessionType (copilotcli). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
From #311751 Co-authored-by: Copilot <copilot@github.com>
…request-skills-issue Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pp-pull-request-skills-issue
Without this capability, the chat input's slash command completion provider returns null when an agent is locked (which agent-host sessions always have), suppressing all '/' slash commands including bundled built-in skills like /create-pr. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the store returned by ensureNoDisposablesAreLeakedInTestSuite() instead of a separate DisposableStore to avoid the afterEach leak check flagging the store itself. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These two registerWorkbenchContribution2 calls landed on origin/main in f3d5d14 (#311954, 'agentHost: settings followups') after our last merge from origin/main. Without them the Agents app never instantiates AgentHostContribution, so authentication never runs and the local agent host stays in the loading state forever. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mirrors the capability set on the chat session contribution in 1ce51eb. The chat input uses the contribution's capability for slash-command completions, but the chat request parser (ChatRequestParser.tryToParseSlashCommand) reads it off the agent itself when an agent is forced via agentIdSilent. Without it, the parser sees a usedAgent with no matching subcommand and bails before producing a ChatRequestSlashPromptPart, so /merge / /create-pr render as plain text instead of a styled slash-command both for skillchip buttons and for users typing the command directly. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pp-pull-request-skills-issue Conflicts were caused by upstream renaming protocol types to drop the I- prefix (#311983). Resolutions: - Adopt the new (no-I) names everywhere protocol types are referenced. - Rename our newly-added 'ISessionMeta' -> 'SessionMeta' to match the same convention; preserve '_meta' / 'SessionMeta' / 'ISessionGitState' / 'readSessionGitState' / 'withSessionGitState' additions, plus the 'resolveCustomizationRefs' helper extraction. - In the local/remote agent host providers, merge upstream's 'description' computation into our 'buildWorkspace' callbacks (which still need to thread 'gitState' through to support the skill buttons). Type-check passes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pure parser tests (parseGitStatusV2, parseHasGitHubRemote, parseDefaultBranchRef, getBranchCompletions) stay in agentHostGitService.test.ts and remain hermetic. The cases that initialise temp git repos and spawn real git move into agentHostGitService.integrationTest.ts and are picked up by scripts/test-integration.sh via the **/*.integrationTest.js glob. Mirrors the git extension's split between unit-style parser tests in git.test.ts and on-disk smoke tests in smoke.test.ts. Also includes a leftover ICustomizationRef -> CustomizationRef rename in resolveCustomizationRefs.test.ts that should have landed with the origin/main merge. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…verride
MockAgent.listSessions() does not infer workingDirectory from
resolvedWorkingDirectory (that field is only consumed by
resolveSessionConfig). Without an explicit override the session metadata
has no workingDirectory, so AgentService.listSessions skips the git
overlay and the test asserted undefined !== { git: ... }.
Set agent.sessionMetadataOverrides = { workingDirectory } so the
listSessions code path actually receives a working directory and invokes
the mock git service.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the agent-host server-side git state probe from `listSessions` (which ran for every session on every refresh) into `createSession` / `restoreSession` (runs once when a session is opened). The result is merged into `summary._meta.git` via a new `AgentHostStateManager.setSessionMeta` method which marks the summary dirty and lets the existing `SessionSummaryChanged` notification fan it out to clients. `_flushSummaryNotifications` now also propagates `_meta` deltas. On the client, `AgentHostSessionAdapter` retains the project / working-directory it was constructed with, exposes a `setMeta` method that rebuilds the `workspace` observable when `_meta` changes, and `_handleSessionSummaryChanged` invokes it. List rendering is otherwise unchanged. Tests: rewrote the two `agentService.test.ts` tests that previously asserted overlay-in-listSessions behaviour to instead drive `createSession` and assert that `_meta.git` lands on the summary. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nState._meta SessionSummary is returned for every session in listSessions and is meant to be cheap to compute. Git state (branch, ahead/behind, etc.) is only consumed by the changesViewModel and the skill buttons, both of which only run for opened sessions, so it belongs on the lazy per-URI SessionState subscription rather than the eager summary. Protocol additions (vendored, will be upstreamed separately): - Add SessionMetaChanged action (server-only, full-replacement semantics matching SessionDiffsChanged) to the action enum, StateAction union, IS_CLIENT_DISPATCHABLE map, and version registry. - Add _meta?: SessionMeta to SessionState. - Remove _meta?: SessionMeta from SessionSummary. Server side: - AgentHostStateManager.setSessionMeta now dispatches a SessionMetaChanged action via dispatchServerAction so the change flows through the action envelope (and thus to all live subscribers) rather than mutating the summary. - Drop _meta change-detection from _flushSummaryNotifications. - AgentService._attachGitState reads state._meta instead of state.summary._meta. - AgentService.listSessions drops the summary._meta overlay. - AgentService.restoreSession dispatches SessionMetaChanged after restoreSession instead of seeding _meta on the summary literal. - remoteAgentHostProtocolClient.listSessions stops forwarding s._meta. Client side: - BaseAgentHostSessionsProvider's state subscription handler now also syncs cached.setMeta(state._meta), so opening a session causes its git state to flow to the adapter via the action envelope. - BaseAgentHostSessionsProvider.getSessionByResource triggers _ensureSessionStateSubscription so the wire subscription is open when the chat editor mounts. The subscription is reference-counted with the chat session handler's, so this is essentially free. - BaseAgentHostSessionsProvider._handleSessionSummaryChanged drops the changes._meta branch (no longer flows through summary). - AgentHostSessionListController._buildMetadata drops the git fields and the meta parameter; the list never read them anyway. The repo tag falls back to workingDirectoryPath. Tests: - agentService.test.ts: assert on state._meta (via stateManager) instead of summary._meta. - agentHostChatContribution.test.ts: rewrite the list-controller git metadata test to assert that git fields are no longer surfaced in list metadata (now per-session state, not summary).
…pp-pull-request-skills-issue # Conflicts: # extensions/copilot/package.json # src/vs/platform/agentHost/common/state/protocol/action-origin.generated.ts # src/vs/sessions/contrib/changes/browser/changesView.ts
Pulls in upstream changes: - SessionMeta interface removed; `_meta` now typed as `Record<string, unknown>` directly - SessionMetaChangedAction `meta` field renamed to `_meta` - New SessionActivityChangedAction (not yet consumed) Adapt VS Code side: - Define a local `SessionMeta` type alias in sessionState.ts (kept for ergonomics in our git-state helpers) - Update agentHostStateManager.setSessionMeta to dispatch with the renamed `_meta` field Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pp-pull-request-skills-issue # Conflicts: # src/vs/platform/agentHost/node/agentHostStateManager.ts
…den validation, bound cache - Add git state fields to ISessionRepository (hasGitHubRemote, upstreamBranchName, incomingChanges, outgoingChanges, uncommittedChanges) - buildAgentHostSessionWorkspace: populate all ISessionGitState fields into the repository; update agentHostSessionWorkspaceKey to include them so downstream observables react when git state changes - changesViewModel: fix activeSessionHasGitRepositoryObs to check workspace.repositories for agent-host sessions (which don't set metadata.repositoryPath); fall back to workspaceRepository for hasGitHubRemote, incomingChanges, outgoingChanges, this wires the buttons to actually appearuncommittedChanges - agentHostSkillButtons: use localize2 / ILocalizedString so Action2.title.original is always the stable English string, not the locale-translated value - readSessionGitState: reject arrays, validate each field's type individually so partial state still propagates; never trust raw cast - agentHostGitService: add _pruneGitStateCache (TTL eviction + LRU cap at 256) called before every new insertion so the map stays bounded SessionMetaChanged / _applySessionMetaFromState / setMeta) - agentHostSessionWorkspace: import ISessionGitState as import type Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the TTL cache from AgentHostGitService.getSessionGitState _computeSessionGitState now runs unconditionally each time it's called, keeping the implementation simple. Add IAgentSideEffectsOptions.onTurnComplete callback, invoked from the idle-event handler in _handleAgentProgress. This fires only for top-level sessions (subagent events are short-circuited earlier), so we get exactly one git probe per real turn. AgentService wires onTurnComplete to _attachGitState using the session's stored workingDirectory, so the toolbar buttons reflect post-turn branch/remote/change state without a session reload. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Drop `baseBranchProtected` from `ISessionGitState` (it was never populated by the agent host's git it's a VS Code policy concept,probe not git data). Instead, the agent-host providers now read VS Code's `git.branchProtection` setting, match the base branch against those glob patterns, and write the result into `ISessionRepository` when building the workspace. The view model continues to read `baseBranchProtected` from the session metadata (Copilot Chat) or the workspace repository (agent uniform across providers, no policy logic in the view.host) (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The git-state cache was removed; `getSessionGitState` no longer returns the same promise reference across calls. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The provider constructors now require IConfigurationService for branch protection pattern reads. Test instantiation services need to provide it. (Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pp-pull-request-skills-issue # Conflicts: # src/vs/sessions/contrib/remoteAgentHost/browser/remoteAgentHostSessionsProvider.ts
Agent-host worktree branches are typically created without an upstream tracking ref, so 'git status -b --porcelain=v2' doesn't emit ahead/behind counts. That meant outgoingChanges came back undefined for committed-but- unpushed work, hiding the 'Create PR' button. Fall back to 'git rev-list --count <baseBranch>..HEAD' to count commits relative to the base branch, which matches what the user actually cares about for PR-creation. Adds an integration test covering the no-upstream case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The local agent-host harness collects every built-in skill bundled under 'vs/sessions/skills/' and ships them as part of the active client's customizations, so the toolbar buttons (/create-pr, /merge, /update-pr, ...) just work for any agent-host session. The remote harness was only syncing the user's manually selected entries, so on a remote agent host those buttons would invoke skills the agent doesn't know about. Extract the built-in collector into a shared 'collectBuiltinSkillFiles' helper and reuse the existing 'resolveCustomizationRefs' pipeline from the remote contribution. Both harnesses now produce the same single synthetic plugin ref containing the bundled skills (plus whatever the user has selected). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds skill buttons (Merge Changes, Create Pull Request, Create Draft Pull Request, Update Pull Request) for agent-host sessions in the Agents app changes view.
What this does
ChatEditingSessionApplySubmenuso they appear in the same dropdown as the existing apply-to-parent-repo actions, gated on context keys (HasGitRepository,HasGitHubRemote, etc.)!sessions.isAgentHostSessionwhen clause) to avoid duplicatesISessionGitStateas a typed accessor over the protocol-level_metabag, so clients can read git state (branch name, ahead/behind counts, PR-related affordances) without parsing raw unknown dataProtocol changes
SessionSummary._metatoSessionState._meta(lazy, only computed when a session is opened) via the newSessionMetaChangedAHP actionagent-host-protocolfiles to84e5779:SessionMetainterface removed in favour ofRecord<string, unknown>directly; action field renamed frommeta→_meta; newSessionActivityChangedActionadded (not yet consumed on the VS Code side)Known issues / follow-up needed
whenclauses depend on context keys derived fromIAgentSession.metadata, but the agent-host list controller doesn't yet bridgestate._meta.gitinto that metadata pipeline — so the buttons may not appear until that wiring is addedlistSessions()overlay doesn't propagate_meta, which can cause git affordances to flicker off after a turn completes(Written by Copilot)