Skip to content
Draft
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,15 +620,15 @@ 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,
transport: launch.transport === 'sse' ? 'sse' : 'http',
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