Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion src/vs/platform/agentHost/common/agentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { ISyncedCustomization } from './agentPluginManager.js';
import { IProtectedResourceMetadata } from './state/protocol/state.js';
import type { IActionEnvelope, INotification, ISessionAction, ITerminalAction } from './state/sessionActions.js';
import type { IAgentSubscription } from './state/agentSubscription.js';
import type { ICreateTerminalParams } from './state/protocol/commands.js';
import type { ICreateTerminalParams, IResolveSessionConfigResult, ISessionConfigCompletionsResult } from './state/protocol/commands.js';
import type { IResourceCopyParams, IResourceCopyResult, IResourceDeleteParams, IResourceDeleteResult, IResourceListResult, IResourceMoveParams, IResourceMoveResult, IResourceReadResult, IResourceWriteParams, IResourceWriteResult, IStateSnapshot } from './state/sessionProtocol.js';
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';

Expand Down Expand Up @@ -99,10 +99,22 @@ export interface IAgentCreateSessionConfig {
readonly model?: string;
readonly session?: URI;
readonly workingDirectory?: URI;
readonly config?: Record<string, string>;
/** Fork from an existing session at a specific turn index. */
readonly fork?: { readonly session: URI; readonly turnIndex: number };
}

export interface IAgentResolveSessionConfigParams {
readonly provider?: AgentProvider;
readonly workingDirectory?: URI;
readonly config?: Record<string, string>;
}

export interface IAgentSessionConfigCompletionsParams extends IAgentResolveSessionConfigParams {
readonly property: string;
readonly query?: string;
}

/** Serializable attachment passed alongside a message to the agent host. */
export interface IAgentAttachment {
readonly type: AttachmentType;
Expand Down Expand Up @@ -335,6 +347,12 @@ export interface IAgent {
/** Create a new session. Returns server-owned session metadata. */
createSession(config?: IAgentCreateSessionConfig): Promise<IAgentCreateSessionResult>;

/** Resolve the dynamic configuration schema for creating a session. */
resolveSessionConfig(params: IAgentResolveSessionConfigParams): Promise<IResolveSessionConfigResult>;

/** Return dynamic completions for a session configuration property. */
sessionConfigCompletions(params: IAgentSessionConfigCompletionsParams): Promise<ISessionConfigCompletionsResult>;

/** Send a user message into an existing session. */
sendMessage(session: URI, prompt: string, attachments?: IAgentAttachment[], turnId?: string): Promise<void>;

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

/** Resolve the dynamic configuration schema for creating a session. */
resolveSessionConfig(params: IAgentResolveSessionConfigParams): Promise<IResolveSessionConfigResult>;

/** Return dynamic completions for a session configuration property. */
sessionConfigCompletions(params: IAgentSessionConfigCompletionsParams): Promise<ISessionConfigCompletionsResult>;

/** Dispose a session in the agent host, freeing SDK resources. */
disposeSession(session: URI): Promise<void>;

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

// ---- Terminal lifecycle -------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1f72258
9be2f2b
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// Generated from types/actions.ts — do not edit
// Run `npm run generate` to regenerate.

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';
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';


// ─── Root vs Session vs Terminal Action Unions ───────────────────────────────
Expand Down Expand Up @@ -57,6 +57,7 @@ export type ISessionAction =
| ISessionIsReadChangedAction
| ISessionIsDoneChangedAction
| ISessionDiffsChangedAction
| ISessionConfigChangedAction
;

/** Union of session actions that clients may dispatch. */
Expand All @@ -79,6 +80,7 @@ export type IClientSessionAction =
| ISessionTruncatedAction
| ISessionIsReadChangedAction
| ISessionIsDoneChangedAction
| ISessionConfigChangedAction
;

/** Union of session actions that only the server may produce. */
Expand Down Expand Up @@ -173,6 +175,7 @@ export const IS_CLIENT_DISPATCHABLE: { readonly [K in IStateAction['type']]: boo
[ActionType.SessionIsReadChanged]: true,
[ActionType.SessionIsDoneChanged]: true,
[ActionType.SessionDiffsChanged]: false,
[ActionType.SessionConfigChanged]: true,
[ActionType.TerminalData]: false,
[ActionType.TerminalInput]: true,
[ActionType.TerminalResized]: true,
Expand Down
23 changes: 23 additions & 0 deletions src/vs/platform/agentHost/common/state/protocol/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const enum ActionType {
SessionIsReadChanged = 'session/isReadChanged',
SessionIsDoneChanged = 'session/isDoneChanged',
SessionDiffsChanged = 'session/diffsChanged',
SessionConfigChanged = 'session/configChanged',
RootTerminalsChanged = 'root/terminalsChanged',
TerminalData = 'terminal/data',
TerminalInput = 'terminal/input',
Expand Down Expand Up @@ -663,6 +664,27 @@ export interface ISessionCustomizationToggledAction {
enabled: boolean;
}

// ─── Config Actions ──────────────────────────────────────────────────────────

/**
* Client changed a mutable config value mid-session.
*
* Only properties with `sessionMutable: true` in the config schema may be
* changed. The server validates and broadcasts the action; the reducer merges
* the new values into `state.config.values`.
*
* @category Session Actions
* @version 1
* @clientDispatchable
*/
export interface ISessionConfigChangedAction {
type: ActionType.SessionConfigChanged;
/** Session URI */
session: URI;
/** Updated config values (merged into existing config) */
config: Record<string, string>;
}

// ─── Truncation ──────────────────────────────────────────────────────────────

/**
Expand Down Expand Up @@ -1006,6 +1028,7 @@ export type IStateAction =
| ISessionIsReadChangedAction
| ISessionIsDoneChangedAction
| ISessionDiffsChangedAction
| ISessionConfigChangedAction
| ITerminalDataAction
| ITerminalInputAction
| ITerminalResizedAction
Expand Down
158 changes: 157 additions & 1 deletion src/vs/platform/agentHost/common/state/protocol/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
// allow-any-unicode-comment-file
// DO NOT EDIT -- auto-generated by scripts/sync-agent-host-protocol.ts

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

export type { ISessionConfigPropertySchema, ISessionConfigSchema } from './state.js';

// ─── initialize ──────────────────────────────────────────────────────────────

/**
Expand Down Expand Up @@ -191,6 +193,11 @@ export interface ICreateSessionParams {
* from the source session up to and including the specified turn's response.
*/
fork?: ISessionForkSource;
/**
* Agent-specific configuration values collected via `resolveSessionConfig`.
* Keys and values correspond to the schema returned by the server.
*/
config?: Record<string, string>;
}

// ─── disposeSession ──────────────────────────────────────────────────────────
Expand Down Expand Up @@ -687,3 +694,152 @@ export interface IAuthenticateParams {
*/
export interface IAuthenticateResult {
}

// ─── resolveSessionConfig ────────────────────────────────────────────────────

/**
* Iteratively resolves the session configuration schema. The client sends the
* current partial session config and any user-filled metadata values. The server
* returns a property schema describing what additional metadata is needed,
* contextual to the current selections.
*
* The client calls this command whenever the user changes a significant input
* (e.g. picks a working directory, toggles a property). Each response returns
* the full current property set (not a delta). When `ready` is `true`, the
* client may call `createSession` with the accumulated config.
*
* @category Commands
* @method resolveSessionConfig
* @direction Client → Server
* @messageType Request
* @version 1
* @example
* ```jsonc
* // Step 1: Client picks a working directory
* // Client → Server
* { "jsonrpc": "2.0", "id": 5, "method": "resolveSessionConfig",
* "params": { "workingDirectory": "file:///home/user/my-project" } }
*
* // Server → Client (git repo detected, offers worktree option)
* { "jsonrpc": "2.0", "id": 5, "result": {
* "ready": true,
* "schema": {
* "type": "object",
* "properties": {
* "target": { "type": "string", "title": "Target", "enum": ["workspace", "worktree"] }
* }
* },
* "values": {}
* }}
*
* // Step 2: User enables worktree
* // Client → Server
* { "jsonrpc": "2.0", "id": 6, "method": "resolveSessionConfig",
* "params": { "workingDirectory": "file:///home/user/my-project",
* "config": { "target": "worktree" } } }
*
* // Server → Client (now requires branch selection)
* { "jsonrpc": "2.0", "id": 6, "result": {
* "ready": false,
* "schema": {
* "type": "object",
* "properties": {
* "target": { "type": "string", "title": "Target", "enum": ["workspace", "worktree"] },
* "baseBranch": { "type": "string", "title": "Base Branch",
* "enum": ["main", "develop"],
* "enumLabels": ["main", "develop"] }
* },
* "required": ["baseBranch"]
* },
* "values": { "target": "worktree" }
* }}
* ```
*/
export interface IResolveSessionConfigParams {
/** Agent provider ID */
provider?: string;
/** Working directory for the session */
workingDirectory?: URI;
/** Current user-filled configuration values */
config?: Record<string, string>;
}

/**
* Result of the `resolveSessionConfig` command.
*/
export interface IResolveSessionConfigResult {
/** True when all required configuration is satisfied and `createSession` can be called */
ready: boolean;
/** JSON Schema describing available configuration properties given the current context */
schema: ISessionConfigSchema;
/** Current configuration values (echoed back with server-resolved defaults applied) */
values: Record<string, string>;
}

// ─── sessionConfigCompletions ────────────────────────────────────────────────

/**
* A single value item returned by `sessionConfigCompletions`.
*
* @category Commands
*/
export interface ISessionConfigValueItem {
/** The value to store in config */
value: string;
/** Human-readable display label */
label: string;
/** Optional secondary description */
description?: string;
/** Optional icon identifier */
icon?: string;
}

/**
* Queries the server for allowed values of a dynamic session config property.
*
* Used when a property in the schema returned by `resolveSessionConfig` has
* `enumDynamic: true`. The client sends a search query and receives matching
* values with display metadata.
*
* @category Commands
* @method sessionConfigCompletions
* @direction Client → Server
* @messageType Request
* @version 1
* @example
* ```jsonc
* // Client → Server (user types "ma" in branch picker)
* { "jsonrpc": "2.0", "id": 7, "method": "sessionConfigCompletions",
* "params": { "workingDirectory": "file:///home/user/my-project",
* "config": { "target": "worktree" },
* "property": "baseBranch", "query": "ma" } }
*
* // Server → Client
* { "jsonrpc": "2.0", "id": 7, "result": {
* "items": [
* { "value": "main", "label": "main", "icon": "git-branch" },
* { "value": "main-v2", "label": "main-v2", "icon": "git-branch" }
* ]
* }}
* ```
*/
export interface ISessionConfigCompletionsParams {
/** Agent provider ID */
provider?: string;
/** Working directory for the session */
workingDirectory?: URI;
/** Current user-filled configuration values (provides context for the query) */
config?: Record<string, string>;
/** Property id from the schema to query values for */
property: string;
/** Search filter text (empty or omitted returns default/recent values) */
query?: string;
}

/**
* Result of the `sessionConfigCompletions` command.
*/
export interface ISessionConfigCompletionsResult {
/** Matching value items */
items: ISessionConfigValueItem[];
}
4 changes: 3 additions & 1 deletion src/vs/platform/agentHost/common/state/protocol/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// allow-any-unicode-comment-file
// DO NOT EDIT -- auto-generated by scripts/sync-agent-host-protocol.ts

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';
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';

import type { IActionEnvelope } from './actions.js';
import type { IProtocolNotification } from './notifications.js';
Expand Down Expand Up @@ -73,6 +73,8 @@ export interface ICommandMap {
'resourceMove': { params: IResourceMoveParams; result: IResourceMoveResult };
'fetchTurns': { params: IFetchTurnsParams; result: IFetchTurnsResult };
'authenticate': { params: IAuthenticateParams; result: IAuthenticateResult };
'resolveSessionConfig': { params: IResolveSessionConfigParams; result: IResolveSessionConfigResult };
'sessionConfigCompletions': { params: ISessionConfigCompletionsParams; result: ISessionConfigCompletionsResult };
}

// ─── Notification Maps ───────────────────────────────────────────────────────
Expand Down
16 changes: 16 additions & 0 deletions src/vs/platform/agentHost/common/state/protocol/reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,22 @@ export function sessionReducer(state: ISessionState, action: ISessionAction, log
summary: { ...state.summary, diffs: action.diffs },
};

case ActionType.SessionConfigChanged:
if (!state.config) {
return state;
}
return {
...state,
config: {
...state.config,
values: { ...state.config.values, ...action.config },
},
summary: {
...state.summary,
modifiedAt: Date.now(),
},
};

case ActionType.SessionServerToolsChanged:
return { ...state, serverTools: action.tools };

Expand Down
Loading
Loading