Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion src/vs/sessions/AI_CUSTOMIZATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ Core workbench registrations may expose Local, Copilot CLI, and Claude harnesses

### `ICustomizationMigrationService`

This shared workbench service computes customization migrations for an explicit chat session. File migrations include source URIs and migratable-configuration metadata for flows that need source type and storage; MCP migrations report known servers' binary harness compatibility together with discovery and policy-coverage state. The service also produces a localized, harness-specific hint summarizing available file migrations for UI consumers.
This shared workbench service computes customization migrations for an explicit chat session. File migrations include source URIs and migratable-configuration metadata for flows that need source type and storage. Its MCP migration domain owns source canonicalization, destination representability, candidate planning, pre-write revalidation, guarded execution, and typed failure reasons. MCP results also retain the full compatibility inventory, discovery state, and policy coverage. The service produces a localized, harness-specific hint summarizing available migrations for UI consumers.

`CustomizationMigrationModel` owns the editor's reactive migration lifecycle: active-session and MCP refresh inputs, async sequencing, loading/error state, candidates, and destination folders. The management editor owns only selection, rendering, confirmation, and user notifications.

### `IHarnessDescriptor`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -484,14 +484,17 @@ class WorkbenchAgentHostCustomizationService extends AbstractAgentHostCustomizat
return undefined;
}
const sessionState = this._readSessionState(sessionResource);
const workingDirectories = sessionState === undefined
? this._provisionalSessionService.getProvisionalWorkingDirectories(sessionResource)?.map(uri => uri.toString())
: sessionState.workingDirectories;
const rootState = target.connection.rootState.value;
const channel = target.backendSession.toString();
return {
customizations: sessionState?.customizations ?? [],
resourceUris: target.connection.resourceUris,
folderPickerDecision: readSessionFolderPickerDecision(sessionState?._meta),
workingDirectory: sessionState?.workingDirectories?.[0],
workingDirectories: sessionState?.workingDirectories,
workingDirectory: workingDirectories?.[0],
workingDirectories,
rootConfig: rootState && !(rootState instanceof Error) ? rootState.config : undefined,
isBundledMcpServer: (pluginUri, serverName) => this._activeClientService.isBundledMcpServer(pluginUri, serverName),
authenticate: request => target.connection.authenticate(request),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,14 +620,14 @@ function projectMcpServerConfiguration(launch: McpServerLaunch): IMcpServerConfi
command: launch.command,
args: launch.args.length > 0 ? [...launch.args] : undefined,
env: Object.keys(launch.env).length > 0 ? { ...launch.env } : undefined,
envFile: launch.envFile,
cwd: launch.cwd,
...(launch.envFile !== undefined ? { envFile: launch.envFile } : {}),
...(launch.cwd !== undefined ? { cwd: launch.cwd } : {}),
};
case McpServerTransportType.HTTP:
return {
type: McpServerType.REMOTE,
url: launch.uri.toString(),
headers: launch.headers.length > 0 ? Object.fromEntries(launch.headers) : undefined,
...(launch.headers.length > 0 ? { headers: Object.fromEntries(launch.headers) } : {}),
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ export interface IAgentHostUntitledProvisionalSessionService {
*/
get(sessionResource: URI): URI | undefined;

/** Working directories used to create the current provisional generation. */
getProvisionalWorkingDirectories(sessionResource: URI): readonly URI[] | undefined;

/**
* Initial config the editor window applies to every new Agent Host session.
* Returns `undefined` in the Agents window, where the sessions provider owns
Expand Down Expand Up @@ -373,6 +376,14 @@ export class AgentHostUntitledProvisionalSessionService extends Disposable imple
return this._generationMatchingDesiredState(entry)?.backendSession;
}

getProvisionalWorkingDirectories(sessionResource: URI): readonly URI[] | undefined {
const entry = this._entries.get(sessionResource);
if (!entry || entry.disposed) {
return undefined;
}
return this._generationMatchingDesiredState(entry)?.workingDirectories;
}

private _computeWorkingDirectories(primary: URI | undefined, provider: string): readonly URI[] | undefined {
return computeWorkingDirectories(primary, this._workspaceContextService.getWorkspace().folders.map(folder => folder.uri), this._agentHostService.rootState.value, provider);
}
Expand Down
Loading
Loading