Skip to content

Commit a8b52bf

Browse files
committed
Add Agent Host session configuration flow
(Written by Copilot)
1 parent f69bfc0 commit a8b52bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1644
-140
lines changed

src/vs/platform/agentHost/common/agentService.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type { ISyncedCustomization } from './agentPluginManager.js';
1212
import { IProtectedResourceMetadata } from './state/protocol/state.js';
1313
import type { IActionEnvelope, INotification, ISessionAction, ITerminalAction } from './state/sessionActions.js';
1414
import type { IAgentSubscription } from './state/agentSubscription.js';
15-
import type { ICreateTerminalParams } from './state/protocol/commands.js';
15+
import type { ICreateTerminalParams, IResolveSessionConfigResult, ISessionConfigCompletionsResult } from './state/protocol/commands.js';
1616
import type { IResourceCopyParams, IResourceCopyResult, IResourceDeleteParams, IResourceDeleteResult, IResourceListResult, IResourceMoveParams, IResourceMoveResult, IResourceReadResult, IResourceWriteParams, IResourceWriteResult, IStateSnapshot } from './state/sessionProtocol.js';
1717
import { AttachmentType, ComponentToState, SessionStatus, StateComponents, type ICustomizationRef, type IPendingMessage, type IRootState, type ISessionInputAnswer, type ISessionInputRequest, type IToolCallResult, type PolicyState, type StringOrMarkdown, SessionInputResponseKind } from './state/sessionState.js';
1818

@@ -99,10 +99,22 @@ export interface IAgentCreateSessionConfig {
9999
readonly model?: string;
100100
readonly session?: URI;
101101
readonly workingDirectory?: URI;
102+
readonly config?: Record<string, string>;
102103
/** Fork from an existing session at a specific turn index. */
103104
readonly fork?: { readonly session: URI; readonly turnIndex: number };
104105
}
105106

107+
export interface IAgentResolveSessionConfigParams {
108+
readonly provider?: AgentProvider;
109+
readonly workingDirectory?: URI;
110+
readonly config?: Record<string, string>;
111+
}
112+
113+
export interface IAgentSessionConfigCompletionsParams extends IAgentResolveSessionConfigParams {
114+
readonly property: string;
115+
readonly query?: string;
116+
}
117+
106118
/** Serializable attachment passed alongside a message to the agent host. */
107119
export interface IAgentAttachment {
108120
readonly type: AttachmentType;
@@ -335,6 +347,12 @@ export interface IAgent {
335347
/** Create a new session. Returns server-owned session metadata. */
336348
createSession(config?: IAgentCreateSessionConfig): Promise<IAgentCreateSessionResult>;
337349

350+
/** Resolve the dynamic configuration schema for creating a session. */
351+
resolveSessionConfig(params: IAgentResolveSessionConfigParams): Promise<IResolveSessionConfigResult>;
352+
353+
/** Return dynamic completions for a session configuration property. */
354+
sessionConfigCompletions(params: IAgentSessionConfigCompletionsParams): Promise<ISessionConfigCompletionsResult>;
355+
338356
/** Send a user message into an existing session. */
339357
sendMessage(session: URI, prompt: string, attachments?: IAgentAttachment[], turnId?: string): Promise<void>;
340358

@@ -452,6 +470,12 @@ export interface IAgentService {
452470
/** Create a new session. Returns the session URI. */
453471
createSession(config?: IAgentCreateSessionConfig): Promise<URI>;
454472

473+
/** Resolve the dynamic configuration schema for creating a session. */
474+
resolveSessionConfig(params: IAgentResolveSessionConfigParams): Promise<IResolveSessionConfigResult>;
475+
476+
/** Return dynamic completions for a session configuration property. */
477+
sessionConfigCompletions(params: IAgentSessionConfigCompletionsParams): Promise<ISessionConfigCompletionsResult>;
478+
455479
/** Dispose a session in the agent host, freeing SDK resources. */
456480
disposeSession(session: URI): Promise<void>;
457481

@@ -557,6 +581,8 @@ export interface IAgentConnection {
557581
authenticate(params: IAuthenticateParams): Promise<IAuthenticateResult>;
558582
listSessions(): Promise<IAgentSessionMetadata[]>;
559583
createSession(config?: IAgentCreateSessionConfig): Promise<URI>;
584+
resolveSessionConfig(params: IAgentResolveSessionConfigParams): Promise<IResolveSessionConfigResult>;
585+
sessionConfigCompletions(params: IAgentSessionConfigCompletionsParams): Promise<ISessionConfigCompletionsResult>;
560586
disposeSession(session: URI): Promise<void>;
561587

562588
// ---- Terminal lifecycle -------------------------------------------------
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1f72258
1+
cd9331d

src/vs/platform/agentHost/common/state/protocol/action-origin.generated.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// Generated from types/actions.ts — do not edit
1010
// Run `npm run generate` to regenerate.
1111

12-
import { ActionType, type IStateAction, type IRootAgentsChangedAction, type IRootActiveSessionsChangedAction, type IRootTerminalsChangedAction, type ISessionReadyAction, type ISessionCreationFailedAction, type ISessionTurnStartedAction, type ISessionDeltaAction, type ISessionResponsePartAction, type ISessionToolCallStartAction, type ISessionToolCallDeltaAction, type ISessionToolCallReadyAction, type ISessionToolCallConfirmedAction, type ISessionToolCallCompleteAction, type ISessionToolCallResultConfirmedAction, type ISessionToolCallContentChangedAction, type ISessionTurnCompleteAction, type ISessionTurnCancelledAction, type ISessionErrorAction, type ISessionTitleChangedAction, type ISessionUsageAction, type ISessionReasoningAction, type ISessionModelChangedAction, type ISessionServerToolsChangedAction, type ISessionActiveClientChangedAction, type ISessionActiveClientToolsChangedAction, type ISessionPendingMessageSetAction, type ISessionPendingMessageRemovedAction, type ISessionQueuedMessagesReorderedAction, type ISessionInputRequestedAction, type ISessionInputAnswerChangedAction, type ISessionInputCompletedAction, type ISessionCustomizationsChangedAction, type ISessionCustomizationToggledAction, type ISessionTruncatedAction, type ISessionIsReadChangedAction, type ISessionIsDoneChangedAction, type ISessionDiffsChangedAction, type ITerminalDataAction, type ITerminalInputAction, type ITerminalResizedAction, type ITerminalClaimedAction, type ITerminalTitleChangedAction, type ITerminalCwdChangedAction, type ITerminalExitedAction, type ITerminalClearedAction } from './actions.js';
12+
import { ActionType, type IStateAction, type IRootAgentsChangedAction, type IRootActiveSessionsChangedAction, type IRootTerminalsChangedAction, type ISessionReadyAction, type ISessionCreationFailedAction, type ISessionTurnStartedAction, type ISessionDeltaAction, type ISessionResponsePartAction, type ISessionToolCallStartAction, type ISessionToolCallDeltaAction, type ISessionToolCallReadyAction, type ISessionToolCallConfirmedAction, type ISessionToolCallCompleteAction, type ISessionToolCallResultConfirmedAction, type ISessionToolCallContentChangedAction, type ISessionTurnCompleteAction, type ISessionTurnCancelledAction, type ISessionErrorAction, type ISessionTitleChangedAction, type ISessionUsageAction, type ISessionReasoningAction, type ISessionModelChangedAction, type ISessionServerToolsChangedAction, type ISessionActiveClientChangedAction, type ISessionActiveClientToolsChangedAction, type ISessionPendingMessageSetAction, type ISessionPendingMessageRemovedAction, type ISessionQueuedMessagesReorderedAction, type ISessionInputRequestedAction, type ISessionInputAnswerChangedAction, type ISessionInputCompletedAction, type ISessionCustomizationsChangedAction, type ISessionCustomizationToggledAction, type ISessionTruncatedAction, type ISessionIsReadChangedAction, type ISessionIsDoneChangedAction, type ISessionDiffsChangedAction, type ISessionConfigChangedAction, type ITerminalDataAction, type ITerminalInputAction, type ITerminalResizedAction, type ITerminalClaimedAction, type ITerminalTitleChangedAction, type ITerminalCwdChangedAction, type ITerminalExitedAction, type ITerminalClearedAction } from './actions.js';
1313

1414

1515
// ─── Root vs Session vs Terminal Action Unions ───────────────────────────────
@@ -57,6 +57,7 @@ export type ISessionAction =
5757
| ISessionIsReadChangedAction
5858
| ISessionIsDoneChangedAction
5959
| ISessionDiffsChangedAction
60+
| ISessionConfigChangedAction
6061
;
6162

6263
/** Union of session actions that clients may dispatch. */
@@ -79,6 +80,7 @@ export type IClientSessionAction =
7980
| ISessionTruncatedAction
8081
| ISessionIsReadChangedAction
8182
| ISessionIsDoneChangedAction
83+
| ISessionConfigChangedAction
8284
;
8385

8486
/** Union of session actions that only the server may produce. */
@@ -173,6 +175,7 @@ export const IS_CLIENT_DISPATCHABLE: { readonly [K in IStateAction['type']]: boo
173175
[ActionType.SessionIsReadChanged]: true,
174176
[ActionType.SessionIsDoneChanged]: true,
175177
[ActionType.SessionDiffsChanged]: false,
178+
[ActionType.SessionConfigChanged]: true,
176179
[ActionType.TerminalData]: false,
177180
[ActionType.TerminalInput]: true,
178181
[ActionType.TerminalResized]: true,

src/vs/platform/agentHost/common/state/protocol/actions.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export const enum ActionType {
5353
SessionIsReadChanged = 'session/isReadChanged',
5454
SessionIsDoneChanged = 'session/isDoneChanged',
5555
SessionDiffsChanged = 'session/diffsChanged',
56+
SessionConfigChanged = 'session/configChanged',
5657
RootTerminalsChanged = 'root/terminalsChanged',
5758
TerminalData = 'terminal/data',
5859
TerminalInput = 'terminal/input',
@@ -663,6 +664,27 @@ export interface ISessionCustomizationToggledAction {
663664
enabled: boolean;
664665
}
665666

667+
// ─── Config Actions ──────────────────────────────────────────────────────────
668+
669+
/**
670+
* Client changed a mutable config value mid-session.
671+
*
672+
* Only properties with `sessionMutable: true` in the config schema may be
673+
* changed. The server validates and broadcasts the action; the reducer merges
674+
* the new values into `state.config.values`.
675+
*
676+
* @category Session Actions
677+
* @version 1
678+
* @clientDispatchable
679+
*/
680+
export interface ISessionConfigChangedAction {
681+
type: ActionType.SessionConfigChanged;
682+
/** Session URI */
683+
session: URI;
684+
/** Updated config values (merged into existing config) */
685+
config: Record<string, string>;
686+
}
687+
666688
// ─── Truncation ──────────────────────────────────────────────────────────────
667689

668690
/**
@@ -1006,6 +1028,7 @@ export type IStateAction =
10061028
| ISessionIsReadChangedAction
10071029
| ISessionIsDoneChangedAction
10081030
| ISessionDiffsChangedAction
1031+
| ISessionConfigChangedAction
10091032
| ITerminalDataAction
10101033
| ITerminalInputAction
10111034
| ITerminalResizedAction

src/vs/platform/agentHost/common/state/protocol/commands.ts

Lines changed: 157 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
// allow-any-unicode-comment-file
77
// DO NOT EDIT -- auto-generated by scripts/sync-agent-host-protocol.ts
88

9-
import type { URI, ISnapshot, ISessionSummary, ITurn, ITerminalClaim } from './state.js';
9+
import type { URI, ISnapshot, ISessionConfigSchema, ISessionSummary, ITurn, ITerminalClaim } from './state.js';
1010
import type { IActionEnvelope, IStateAction } from './actions.js';
1111

12+
export type { ISessionConfigPropertySchema, ISessionConfigSchema } from './state.js';
13+
1214
// ─── initialize ──────────────────────────────────────────────────────────────
1315

1416
/**
@@ -191,6 +193,11 @@ export interface ICreateSessionParams {
191193
* from the source session up to and including the specified turn's response.
192194
*/
193195
fork?: ISessionForkSource;
196+
/**
197+
* Agent-specific configuration values collected via `resolveSessionConfig`.
198+
* Keys and values correspond to the schema returned by the server.
199+
*/
200+
config?: Record<string, string>;
194201
}
195202

196203
// ─── disposeSession ──────────────────────────────────────────────────────────
@@ -687,3 +694,152 @@ export interface IAuthenticateParams {
687694
*/
688695
export interface IAuthenticateResult {
689696
}
697+
698+
// ─── resolveSessionConfig ────────────────────────────────────────────────────
699+
700+
/**
701+
* Iteratively resolves the session configuration schema. The client sends the
702+
* current partial session config and any user-filled metadata values. The server
703+
* returns a property schema describing what additional metadata is needed,
704+
* contextual to the current selections.
705+
*
706+
* The client calls this command whenever the user changes a significant input
707+
* (e.g. picks a working directory, toggles a property). Each response returns
708+
* the full current property set (not a delta). When `ready` is `true`, the
709+
* client may call `createSession` with the accumulated config.
710+
*
711+
* @category Commands
712+
* @method resolveSessionConfig
713+
* @direction Client → Server
714+
* @messageType Request
715+
* @version 1
716+
* @example
717+
* ```jsonc
718+
* // Step 1: Client picks a working directory
719+
* // Client → Server
720+
* { "jsonrpc": "2.0", "id": 5, "method": "resolveSessionConfig",
721+
* "params": { "workingDirectory": "file:///home/user/my-project" } }
722+
*
723+
* // Server → Client (git repo detected, offers worktree option)
724+
* { "jsonrpc": "2.0", "id": 5, "result": {
725+
* "ready": true,
726+
* "schema": {
727+
* "type": "object",
728+
* "properties": {
729+
* "target": { "type": "string", "title": "Target", "enum": ["workspace", "worktree"] }
730+
* }
731+
* },
732+
* "values": {}
733+
* }}
734+
*
735+
* // Step 2: User enables worktree
736+
* // Client → Server
737+
* { "jsonrpc": "2.0", "id": 6, "method": "resolveSessionConfig",
738+
* "params": { "workingDirectory": "file:///home/user/my-project",
739+
* "config": { "target": "worktree" } } }
740+
*
741+
* // Server → Client (now requires branch selection)
742+
* { "jsonrpc": "2.0", "id": 6, "result": {
743+
* "ready": false,
744+
* "schema": {
745+
* "type": "object",
746+
* "properties": {
747+
* "target": { "type": "string", "title": "Target", "enum": ["workspace", "worktree"] },
748+
* "baseBranch": { "type": "string", "title": "Base Branch",
749+
* "enum": ["main", "develop"],
750+
* "enumLabels": ["main", "develop"] }
751+
* },
752+
* "required": ["baseBranch"]
753+
* },
754+
* "values": { "target": "worktree" }
755+
* }}
756+
* ```
757+
*/
758+
export interface IResolveSessionConfigParams {
759+
/** Agent provider ID */
760+
provider?: string;
761+
/** Working directory for the session */
762+
workingDirectory?: URI;
763+
/** Current user-filled configuration values */
764+
config?: Record<string, string>;
765+
}
766+
767+
/**
768+
* Result of the `resolveSessionConfig` command.
769+
*/
770+
export interface IResolveSessionConfigResult {
771+
/** True when all required configuration is satisfied and `createSession` can be called */
772+
ready: boolean;
773+
/** JSON Schema describing available configuration properties given the current context */
774+
schema: ISessionConfigSchema;
775+
/** Current configuration values (echoed back with server-resolved defaults applied) */
776+
values: Record<string, string>;
777+
}
778+
779+
// ─── sessionConfigCompletions ────────────────────────────────────────────────
780+
781+
/**
782+
* A single value item returned by `sessionConfigCompletions`.
783+
*
784+
* @category Commands
785+
*/
786+
export interface ISessionConfigValueItem {
787+
/** The value to store in config */
788+
value: string;
789+
/** Human-readable display label */
790+
label: string;
791+
/** Optional secondary description */
792+
description?: string;
793+
/** Optional icon identifier */
794+
icon?: string;
795+
}
796+
797+
/**
798+
* Queries the server for allowed values of a dynamic session config property.
799+
*
800+
* Used when a property in the schema returned by `resolveSessionConfig` has
801+
* `enumDynamic: true`. The client sends a search query and receives matching
802+
* values with display metadata.
803+
*
804+
* @category Commands
805+
* @method sessionConfigCompletions
806+
* @direction Client → Server
807+
* @messageType Request
808+
* @version 1
809+
* @example
810+
* ```jsonc
811+
* // Client → Server (user types "ma" in branch picker)
812+
* { "jsonrpc": "2.0", "id": 7, "method": "sessionConfigCompletions",
813+
* "params": { "workingDirectory": "file:///home/user/my-project",
814+
* "config": { "target": "worktree" },
815+
* "property": "baseBranch", "query": "ma" } }
816+
*
817+
* // Server → Client
818+
* { "jsonrpc": "2.0", "id": 7, "result": {
819+
* "items": [
820+
* { "value": "main", "label": "main", "icon": "git-branch" },
821+
* { "value": "main-v2", "label": "main-v2", "icon": "git-branch" }
822+
* ]
823+
* }}
824+
* ```
825+
*/
826+
export interface ISessionConfigCompletionsParams {
827+
/** Agent provider ID */
828+
provider?: string;
829+
/** Working directory for the session */
830+
workingDirectory?: URI;
831+
/** Current user-filled configuration values (provides context for the query) */
832+
config?: Record<string, string>;
833+
/** Property id from the schema to query values for */
834+
property: string;
835+
/** Search filter text (empty or omitted returns default/recent values) */
836+
query?: string;
837+
}
838+
839+
/**
840+
* Result of the `sessionConfigCompletions` command.
841+
*/
842+
export interface ISessionConfigCompletionsResult {
843+
/** Matching value items */
844+
items: ISessionConfigValueItem[];
845+
}

src/vs/platform/agentHost/common/state/protocol/messages.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// allow-any-unicode-comment-file
77
// DO NOT EDIT -- auto-generated by scripts/sync-agent-host-protocol.ts
88

9-
import type { IInitializeParams, IInitializeResult, IReconnectParams, IReconnectResult, ISubscribeParams, ISubscribeResult, ICreateSessionParams, IDisposeSessionParams, ICreateTerminalParams, IDisposeTerminalParams, IListSessionsParams, IListSessionsResult, IResourceReadParams, IResourceReadResult, IResourceWriteParams, IResourceWriteResult, IResourceListParams, IResourceListResult, IResourceCopyParams, IResourceCopyResult, IResourceDeleteParams, IResourceDeleteResult, IResourceMoveParams, IResourceMoveResult, IFetchTurnsParams, IFetchTurnsResult, IUnsubscribeParams, IDispatchActionParams, IAuthenticateParams, IAuthenticateResult } from './commands.js';
9+
import type { IInitializeParams, IInitializeResult, IReconnectParams, IReconnectResult, ISubscribeParams, ISubscribeResult, ICreateSessionParams, IDisposeSessionParams, ICreateTerminalParams, IDisposeTerminalParams, IListSessionsParams, IListSessionsResult, IResourceReadParams, IResourceReadResult, IResourceWriteParams, IResourceWriteResult, IResourceListParams, IResourceListResult, IResourceCopyParams, IResourceCopyResult, IResourceDeleteParams, IResourceDeleteResult, IResourceMoveParams, IResourceMoveResult, IFetchTurnsParams, IFetchTurnsResult, IUnsubscribeParams, IDispatchActionParams, IAuthenticateParams, IAuthenticateResult, IResolveSessionConfigParams, IResolveSessionConfigResult, ISessionConfigCompletionsParams, ISessionConfigCompletionsResult } from './commands.js';
1010

1111
import type { IActionEnvelope } from './actions.js';
1212
import type { IProtocolNotification } from './notifications.js';
@@ -73,6 +73,8 @@ export interface ICommandMap {
7373
'resourceMove': { params: IResourceMoveParams; result: IResourceMoveResult };
7474
'fetchTurns': { params: IFetchTurnsParams; result: IFetchTurnsResult };
7575
'authenticate': { params: IAuthenticateParams; result: IAuthenticateResult };
76+
'resolveSessionConfig': { params: IResolveSessionConfigParams; result: IResolveSessionConfigResult };
77+
'sessionConfigCompletions': { params: ISessionConfigCompletionsParams; result: ISessionConfigCompletionsResult };
7678
}
7779

7880
// ─── Notification Maps ───────────────────────────────────────────────────────

src/vs/platform/agentHost/common/state/protocol/reducers.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,22 @@ export function sessionReducer(state: ISessionState, action: ISessionAction, log
541541
summary: { ...state.summary, diffs: action.diffs },
542542
};
543543

544+
case ActionType.SessionConfigChanged:
545+
if (!state.config) {
546+
return state;
547+
}
548+
return {
549+
...state,
550+
config: {
551+
...state.config,
552+
values: { ...state.config.values, ...action.config },
553+
},
554+
summary: {
555+
...state.summary,
556+
modifiedAt: Date.now(),
557+
},
558+
};
559+
544560
case ActionType.SessionServerToolsChanged:
545561
return { ...state, serverTools: action.tools };
546562

0 commit comments

Comments
 (0)