Use URI for workingDirectory across agent host layer (#306117)

* Use URI for workingDirectory across agent host layer

- Change IAgentCreateSessionConfig.workingDirectory and
  IAgentSessionMetadata.workingDirectory from string to URI
- Convert file paths to URI at SDK boundary (CopilotAgent)
- Convert protocol strings to agenthost:// URIs at protocol client boundary
- Convert agenthost:// URIs back to file:// at protocol client on outgoing
- Update resolveWorkingDirectory callback to return URI
- Use extUriBiasedIgnorePathCase.isEqualOrParent for path containment
- Use generateUuid() instead of crypto.randomUUID()
- Add CopilotAgentSession tests and SessionWrapperFactory pattern
- Register all event subscription disposables properly

(Written by Copilot)

* Tweak

* Fix test
This commit is contained in:
Rob Lourens
2026-03-29 12:56:06 -07:00
committed by GitHub
parent 9a6bf81db5
commit 0dad7e0453
15 changed files with 46 additions and 46 deletions

View File

@@ -430,7 +430,7 @@ suite('AgentSideEffects', () => {
});
test('preserves workingDirectory from agent metadata', async () => {
agent.sessionMetadataOverrides = { workingDirectory: '/home/user/project' };
agent.sessionMetadataOverrides = { workingDirectory: URI.file('/home/user/project') };
const session = await agent.createSession();
const sessions = await agent.listSessions();
const sessionResource = sessions[0].session.toString();
@@ -444,7 +444,7 @@ suite('AgentSideEffects', () => {
const state = stateManager.getSessionState(sessionResource);
assert.ok(state);
assert.strictEqual(state!.summary.workingDirectory, '/home/user/project');
assert.strictEqual(state!.summary.workingDirectory, URI.file('/home/user/project').toString());
});
});

View File

@@ -81,7 +81,7 @@ function createMockSessionDataService(): ISessionDataService {
};
}
async function createAgentSession(disposables: DisposableStore, options?: { workingDirectory?: string }): Promise<{
async function createAgentSession(disposables: DisposableStore, options?: { workingDirectory?: URI }): Promise<{
session: CopilotAgentSession;
mockSession: MockCopilotSession;
progressEvents: IAgentProgressEvent[];
@@ -129,7 +129,7 @@ suite('CopilotAgentSession', () => {
suite('permission handling', () => {
test('auto-approves read inside working directory', async () => {
const { session } = await createAgentSession(disposables, { workingDirectory: '/workspace' });
const { session } = await createAgentSession(disposables, { workingDirectory: URI.file('/workspace') });
const result = await session.handlePermissionRequest({
kind: 'read',
path: '/workspace/src/file.ts',
@@ -139,7 +139,7 @@ suite('CopilotAgentSession', () => {
});
test('does not auto-approve read outside working directory', async () => {
const { session, progressEvents } = await createAgentSession(disposables, { workingDirectory: '/workspace' });
const { session, progressEvents } = await createAgentSession(disposables, { workingDirectory: URI.file('/workspace') });
// Kick off permission request but don't await — it will block
const resultPromise = session.handlePermissionRequest({