mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-18 14:19:42 +01:00
Merge pull request #309237 from microsoft/roblou/agent-host-session-cwd
Fix agent host session working directories
This commit is contained in:
Generated
+33
-33
@@ -11,8 +11,8 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sandbox-runtime": "0.0.42",
|
||||
"@github/copilot": "^1.0.11",
|
||||
"@github/copilot-sdk": "^0.2.0",
|
||||
"@github/copilot": "^1.0.24",
|
||||
"@github/copilot-sdk": "^0.2.2",
|
||||
"@microsoft/1ds-core-js": "^3.2.13",
|
||||
"@microsoft/1ds-post-js": "^3.2.13",
|
||||
"@microsoft/dev-tunnels-connections": "^1.3.41",
|
||||
@@ -1072,26 +1072,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.11.tgz",
|
||||
"integrity": "sha512-cptVopko/tNKEXyBP174yBjHQBEwg6CqaKN2S0M3J+5LEB8u31bLL75ioOPd+5vubqBrA0liyTdcHeZ8UTRbmg==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.24.tgz",
|
||||
"integrity": "sha512-/nZ2GwhaGq0HeI3W+6LE0JGw25/bipC6tYVa+oQ5tIvAafBazuNt10CXkeaor+u9oBWLZtPbdTyAzE2tjy9NpQ==",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"bin": {
|
||||
"copilot": "npm-loader.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@github/copilot-darwin-arm64": "1.0.11",
|
||||
"@github/copilot-darwin-x64": "1.0.11",
|
||||
"@github/copilot-linux-arm64": "1.0.11",
|
||||
"@github/copilot-linux-x64": "1.0.11",
|
||||
"@github/copilot-win32-arm64": "1.0.11",
|
||||
"@github/copilot-win32-x64": "1.0.11"
|
||||
"@github/copilot-darwin-arm64": "1.0.24",
|
||||
"@github/copilot-darwin-x64": "1.0.24",
|
||||
"@github/copilot-linux-arm64": "1.0.24",
|
||||
"@github/copilot-linux-x64": "1.0.24",
|
||||
"@github/copilot-win32-arm64": "1.0.24",
|
||||
"@github/copilot-win32-x64": "1.0.24"
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-darwin-arm64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.11.tgz",
|
||||
"integrity": "sha512-wdKimjtbsVeXqMqQSnGpGBPFEYHljxXNuWeH8EIJTNRgFpAsimcivsFgql3Twq4YOp0AxfsH36icG4IEen30mA==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.24.tgz",
|
||||
"integrity": "sha512-lejn6KV+09rZEICX3nRx9a58DQFQ2kK3NJ3EICfVLngUCWIUmwn1BLezjeTQc9YNasHltA1hulvfsWqX+VjlMw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1105,9 +1105,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-darwin-x64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.11.tgz",
|
||||
"integrity": "sha512-VeuPv8rzBVGBB8uDwMEhcHBpldoKaq26yZ5YQm+G9Ka5QIF+1DMah8ZNRMVsTeNKkb1ji9G8vcuCsaPbnG3fKg==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.24.tgz",
|
||||
"integrity": "sha512-r2F3keTvr4Bunz3V+waRAvsHgqsVQGyIZFBebsNPWxBX1eh3IXgtBqxCR7vXTFyZonQ8VaiJH3YYEfAhyKsk9g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1121,9 +1121,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-linux-arm64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.11.tgz",
|
||||
"integrity": "sha512-/d8p6RlFYKj1Va2hekFIcYNMHWagcEkaxgcllUNXSyQLnmEtXUkaWtz62VKGWE+n/UMkEwCB6vI2xEwPTlUNBQ==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.24.tgz",
|
||||
"integrity": "sha512-B3oANXKKKLhnKYozXa/W+DxfCQAHJCs0QKR5rBwNrwJbf656twNgALSxWTSJk+1rEP6MrHCswUAcwjwZL7Q+FQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1137,9 +1137,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-linux-x64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.11.tgz",
|
||||
"integrity": "sha512-UujTRO3xkPFC1CybchBbCnaTEAG6JrH0etIst07JvfekMWgvRxbiCHQPpDPSzBCPiBcGu0gba0/IT+vUCORuIw==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.24.tgz",
|
||||
"integrity": "sha512-NGTldizY54B+4Sfhu/GWoEQNMwqqUNgMwbSgBshFv+Hqy1EwuvNWKVov1Y0Vzhp4qAHc6ZxBk/OPIW8Ato9FUg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1153,12 +1153,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-sdk": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-sdk/-/copilot-sdk-0.2.0.tgz",
|
||||
"integrity": "sha512-fCEpD9W9xqcaCAJmatyNQ1PkET9P9liK2P4Vk0raDFoMXcvpIdqewa5JQeKtWCBUsN/HCz7ExkkFP8peQuo+DA==",
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-sdk/-/copilot-sdk-0.2.2.tgz",
|
||||
"integrity": "sha512-VZCqS08YlUM90bUKJ7VLeIxgTTEHtfXBo84T1IUMNvXRREX2csjPH6Z+CPw3S2468RcCLvzBXcc9LtJJTLIWFw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@github/copilot": "^1.0.10",
|
||||
"@github/copilot": "^1.0.21",
|
||||
"vscode-jsonrpc": "^8.2.1",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
@@ -1176,9 +1176,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-win32-arm64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.11.tgz",
|
||||
"integrity": "sha512-EOW8HUM+EmnHEZEa+iUMl4pP1+2eZUk2XCbynYiMehwX9sidc4BxEHp2RuxADSzFPTieQEWzgjQmHWrtet8pQg==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.24.tgz",
|
||||
"integrity": "sha512-/pd/kgef7/HIIg1SQq4q8fext39pDSC44jHB10KkhfgG1WaDFhQbc/aSSMQfxeldkRbQh6VANp8WtGQdwtMCBA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1192,9 +1192,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-win32-x64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.11.tgz",
|
||||
"integrity": "sha512-fKGkSNamzs3h9AbmswNvPYJBORCb2Y8CbusijU3C7fT3ohvqnHJwKo5iHhJXLOKZNOpFZgq9YKha410u9sIs6Q==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.24.tgz",
|
||||
"integrity": "sha512-RDvOiSvyEJwELqErwANJTrdRuMIHkwPE4QK7Le7WsmaSKxiuS4H1Pa8Yxnd2FWrMsCHEbase23GJlymbnGYLXQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
||||
+2
-2
@@ -88,8 +88,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sandbox-runtime": "0.0.42",
|
||||
"@github/copilot": "^1.0.11",
|
||||
"@github/copilot-sdk": "^0.2.0",
|
||||
"@github/copilot": "^1.0.24",
|
||||
"@github/copilot-sdk": "^0.2.2",
|
||||
"@microsoft/1ds-core-js": "^3.2.13",
|
||||
"@microsoft/1ds-post-js": "^3.2.13",
|
||||
"@microsoft/dev-tunnels-connections": "^1.3.41",
|
||||
|
||||
Generated
+33
-33
@@ -9,8 +9,8 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sandbox-runtime": "0.0.42",
|
||||
"@github/copilot": "^1.0.11",
|
||||
"@github/copilot-sdk": "^0.2.0",
|
||||
"@github/copilot": "^1.0.24",
|
||||
"@github/copilot-sdk": "^0.2.2",
|
||||
"@microsoft/1ds-core-js": "^3.2.13",
|
||||
"@microsoft/1ds-post-js": "^3.2.13",
|
||||
"@parcel/watcher": "^2.5.6",
|
||||
@@ -83,26 +83,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.11.tgz",
|
||||
"integrity": "sha512-cptVopko/tNKEXyBP174yBjHQBEwg6CqaKN2S0M3J+5LEB8u31bLL75ioOPd+5vubqBrA0liyTdcHeZ8UTRbmg==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.24.tgz",
|
||||
"integrity": "sha512-/nZ2GwhaGq0HeI3W+6LE0JGw25/bipC6tYVa+oQ5tIvAafBazuNt10CXkeaor+u9oBWLZtPbdTyAzE2tjy9NpQ==",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"bin": {
|
||||
"copilot": "npm-loader.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@github/copilot-darwin-arm64": "1.0.11",
|
||||
"@github/copilot-darwin-x64": "1.0.11",
|
||||
"@github/copilot-linux-arm64": "1.0.11",
|
||||
"@github/copilot-linux-x64": "1.0.11",
|
||||
"@github/copilot-win32-arm64": "1.0.11",
|
||||
"@github/copilot-win32-x64": "1.0.11"
|
||||
"@github/copilot-darwin-arm64": "1.0.24",
|
||||
"@github/copilot-darwin-x64": "1.0.24",
|
||||
"@github/copilot-linux-arm64": "1.0.24",
|
||||
"@github/copilot-linux-x64": "1.0.24",
|
||||
"@github/copilot-win32-arm64": "1.0.24",
|
||||
"@github/copilot-win32-x64": "1.0.24"
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-darwin-arm64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.11.tgz",
|
||||
"integrity": "sha512-wdKimjtbsVeXqMqQSnGpGBPFEYHljxXNuWeH8EIJTNRgFpAsimcivsFgql3Twq4YOp0AxfsH36icG4IEen30mA==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.24.tgz",
|
||||
"integrity": "sha512-lejn6KV+09rZEICX3nRx9a58DQFQ2kK3NJ3EICfVLngUCWIUmwn1BLezjeTQc9YNasHltA1hulvfsWqX+VjlMw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -116,9 +116,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-darwin-x64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.11.tgz",
|
||||
"integrity": "sha512-VeuPv8rzBVGBB8uDwMEhcHBpldoKaq26yZ5YQm+G9Ka5QIF+1DMah8ZNRMVsTeNKkb1ji9G8vcuCsaPbnG3fKg==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.24.tgz",
|
||||
"integrity": "sha512-r2F3keTvr4Bunz3V+waRAvsHgqsVQGyIZFBebsNPWxBX1eh3IXgtBqxCR7vXTFyZonQ8VaiJH3YYEfAhyKsk9g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -132,9 +132,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-linux-arm64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.11.tgz",
|
||||
"integrity": "sha512-/d8p6RlFYKj1Va2hekFIcYNMHWagcEkaxgcllUNXSyQLnmEtXUkaWtz62VKGWE+n/UMkEwCB6vI2xEwPTlUNBQ==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.24.tgz",
|
||||
"integrity": "sha512-B3oANXKKKLhnKYozXa/W+DxfCQAHJCs0QKR5rBwNrwJbf656twNgALSxWTSJk+1rEP6MrHCswUAcwjwZL7Q+FQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -148,9 +148,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-linux-x64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.11.tgz",
|
||||
"integrity": "sha512-UujTRO3xkPFC1CybchBbCnaTEAG6JrH0etIst07JvfekMWgvRxbiCHQPpDPSzBCPiBcGu0gba0/IT+vUCORuIw==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.24.tgz",
|
||||
"integrity": "sha512-NGTldizY54B+4Sfhu/GWoEQNMwqqUNgMwbSgBshFv+Hqy1EwuvNWKVov1Y0Vzhp4qAHc6ZxBk/OPIW8Ato9FUg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -164,12 +164,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-sdk": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-sdk/-/copilot-sdk-0.2.0.tgz",
|
||||
"integrity": "sha512-fCEpD9W9xqcaCAJmatyNQ1PkET9P9liK2P4Vk0raDFoMXcvpIdqewa5JQeKtWCBUsN/HCz7ExkkFP8peQuo+DA==",
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-sdk/-/copilot-sdk-0.2.2.tgz",
|
||||
"integrity": "sha512-VZCqS08YlUM90bUKJ7VLeIxgTTEHtfXBo84T1IUMNvXRREX2csjPH6Z+CPw3S2468RcCLvzBXcc9LtJJTLIWFw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@github/copilot": "^1.0.10",
|
||||
"@github/copilot": "^1.0.21",
|
||||
"vscode-jsonrpc": "^8.2.1",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
@@ -187,9 +187,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-win32-arm64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.11.tgz",
|
||||
"integrity": "sha512-EOW8HUM+EmnHEZEa+iUMl4pP1+2eZUk2XCbynYiMehwX9sidc4BxEHp2RuxADSzFPTieQEWzgjQmHWrtet8pQg==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.24.tgz",
|
||||
"integrity": "sha512-/pd/kgef7/HIIg1SQq4q8fext39pDSC44jHB10KkhfgG1WaDFhQbc/aSSMQfxeldkRbQh6VANp8WtGQdwtMCBA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -203,9 +203,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@github/copilot-win32-x64": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.11.tgz",
|
||||
"integrity": "sha512-fKGkSNamzs3h9AbmswNvPYJBORCb2Y8CbusijU3C7fT3ohvqnHJwKo5iHhJXLOKZNOpFZgq9YKha410u9sIs6Q==",
|
||||
"version": "1.0.24",
|
||||
"resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.24.tgz",
|
||||
"integrity": "sha512-RDvOiSvyEJwELqErwANJTrdRuMIHkwPE4QK7Le7WsmaSKxiuS4H1Pa8Yxnd2FWrMsCHEbase23GJlymbnGYLXQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sandbox-runtime": "0.0.42",
|
||||
"@github/copilot": "^1.0.11",
|
||||
"@github/copilot-sdk": "^0.2.0",
|
||||
"@github/copilot": "^1.0.24",
|
||||
"@github/copilot-sdk": "^0.2.2",
|
||||
"@microsoft/1ds-core-js": "^3.2.13",
|
||||
"@microsoft/1ds-post-js": "^3.2.13",
|
||||
"@parcel/watcher": "^2.5.6",
|
||||
|
||||
@@ -467,6 +467,11 @@ export class CopilotAgent extends Disposable implements IAgent {
|
||||
const parsedPlugins = await this._plugins.getAppliedPlugins();
|
||||
|
||||
const sessionUri = AgentSession.uri(this.id, sessionId);
|
||||
const sessionMetadata = await client.getSessionMetadata(sessionId).catch(err => {
|
||||
this._logService.warn(`[Copilot:${sessionId}] getSessionMetadata failed`, err);
|
||||
return undefined;
|
||||
});
|
||||
const workingDirectory = typeof sessionMetadata?.context?.cwd === 'string' ? URI.file(sessionMetadata.context.cwd) : undefined;
|
||||
const shellManager = this._instantiationService.createInstance(ShellManager, sessionUri);
|
||||
const sessionConfig = this._buildSessionConfig(parsedPlugins, shellManager);
|
||||
|
||||
@@ -475,6 +480,7 @@ export class CopilotAgent extends Disposable implements IAgent {
|
||||
try {
|
||||
const raw = await client.resumeSession(sessionId, {
|
||||
...config,
|
||||
workingDirectory: workingDirectory?.fsPath,
|
||||
});
|
||||
return new CopilotSessionWrapper(raw);
|
||||
} catch (err) {
|
||||
@@ -499,7 +505,7 @@ export class CopilotAgent extends Disposable implements IAgent {
|
||||
}
|
||||
};
|
||||
|
||||
const agentSession = this._createAgentSession(factory, undefined, sessionId, shellManager);
|
||||
const agentSession = this._createAgentSession(factory, workingDirectory, sessionId, shellManager);
|
||||
this._plugins.setAppliedPlugins(agentSession, parsedPlugins);
|
||||
await agentSession.initializeSession();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { AgentHostEnabledSettingId } from '../../../../platform/agentHost/common
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../../workbench/common/contributions.js';
|
||||
import { IAgentHostSessionWorkingDirectoryResolver } from '../../../../workbench/contrib/chat/browser/agentSessions/agentHost/agentHostSessionWorkingDirectoryResolver.js';
|
||||
import { ISessionsProvidersService } from '../../../services/sessions/browser/sessionsProvidersService.js';
|
||||
import { LocalAgentHostSessionsProvider } from './localAgentHostSessionsProvider.js';
|
||||
|
||||
@@ -29,6 +30,7 @@ class LocalAgentHostContribution extends Disposable implements IWorkbenchContrib
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@ISessionsProvidersService sessionsProvidersService: ISessionsProvidersService,
|
||||
@IAgentHostSessionWorkingDirectoryResolver workingDirectoryResolver: IAgentHostSessionWorkingDirectoryResolver,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -38,6 +40,12 @@ class LocalAgentHostContribution extends Disposable implements IWorkbenchContrib
|
||||
|
||||
const provider = this._register(instantiationService.createInstance(LocalAgentHostSessionsProvider));
|
||||
this._register(sessionsProvidersService.registerProvider(provider));
|
||||
for (const sessionType of provider.sessionTypes) {
|
||||
this._register(workingDirectoryResolver.registerResolver(sessionType.id, sessionResource => {
|
||||
const repository = provider.getSessionByResource(sessionResource)?.workspace.get()?.repositories[0];
|
||||
return repository?.workingDirectory ?? repository?.uri;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -283,6 +283,25 @@ export class LocalAgentHostSessionsProvider extends Disposable implements ISessi
|
||||
return sessions;
|
||||
}
|
||||
|
||||
getSessionByResource(resource: URI): ISession | undefined {
|
||||
if (this._currentNewSession?.resource.toString() === resource.toString()) {
|
||||
return this._currentNewSession;
|
||||
}
|
||||
|
||||
if (this._pendingSession?.resource.toString() === resource.toString()) {
|
||||
return this._pendingSession;
|
||||
}
|
||||
|
||||
this._ensureSessionCache();
|
||||
for (const cached of this._sessionCache.values()) {
|
||||
if (cached.resource.toString() === resource.toString()) {
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// -- Session Lifecycle --
|
||||
|
||||
createNewSession(workspace: ISessionWorkspace): ISession {
|
||||
|
||||
+23
@@ -306,6 +306,29 @@ suite('LocalAgentHostSessionsProvider', () => {
|
||||
assert.strictEqual(session.sessionType, provider.sessionTypes[0].id);
|
||||
});
|
||||
|
||||
test('getSessionByResource resolves current new session without listing it', () => {
|
||||
const provider = createProvider(disposables, agentHost);
|
||||
const workspace = {
|
||||
label: 'my-project',
|
||||
icon: { id: 'folder' },
|
||||
repositories: [{ uri: URI.parse('file:///home/user/project'), workingDirectory: undefined, detail: undefined, baseBranchName: undefined, baseBranchProtected: undefined }],
|
||||
requiresWorkspaceTrust: true,
|
||||
};
|
||||
|
||||
const session = provider.createNewSession(workspace);
|
||||
const resolved = provider.getSessionByResource(session.resource);
|
||||
|
||||
assert.deepStrictEqual({
|
||||
listedSessions: provider.getSessions().length,
|
||||
resolvedResource: resolved?.resource.toString(),
|
||||
resolvedWorkspaceLabel: resolved?.workspace.get()?.label,
|
||||
}, {
|
||||
listedSessions: 0,
|
||||
resolvedResource: session.resource.toString(),
|
||||
resolvedWorkspaceLabel: 'my-project',
|
||||
});
|
||||
});
|
||||
|
||||
test('createNewSession throws when no repository URI', () => {
|
||||
const provider = createProvider(disposables, agentHost);
|
||||
const workspace = { label: 'empty', icon: { id: 'folder' }, repositories: [], requiresWorkspaceTrust: false };
|
||||
|
||||
@@ -39,7 +39,6 @@ import { createRemoteAgentHarnessDescriptor, RemoteAgentCustomizationItemProvide
|
||||
import { RemoteAgentHostSessionsProvider } from './remoteAgentHostSessionsProvider.js';
|
||||
import { SyncedCustomizationBundler } from './syncedCustomizationBundler.js';
|
||||
import { ISSHRemoteAgentHostService } from '../../../../platform/agentHost/common/sshRemoteAgentHost.js';
|
||||
import { ISessionsManagementService } from '../../../services/sessions/common/sessionsManagement.js';
|
||||
|
||||
/** Per-connection state bundle, disposed when a connection is removed. */
|
||||
class ConnectionState extends Disposable {
|
||||
@@ -86,7 +85,6 @@ export class RemoteAgentHostContribution extends Disposable implements IWorkbenc
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IAuthenticationService private readonly _authenticationService: IAuthenticationService,
|
||||
@IDefaultAccountService private readonly _defaultAccountService: IDefaultAccountService,
|
||||
@ISessionsManagementService private readonly _sessionsManagementService: ISessionsManagementService,
|
||||
@ISessionsProvidersService private readonly _sessionsProvidersService: ISessionsProvidersService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@IAgentHostFileSystemService private readonly _agentHostFileSystemService: IAgentHostFileSystemService,
|
||||
@@ -339,6 +337,7 @@ export class RemoteAgentHostContribution extends Disposable implements IWorkbenc
|
||||
connState.store.add(agentStore);
|
||||
|
||||
const sanitized = agentHostAuthority(address);
|
||||
const providerId = `agenthost-${sanitized}`;
|
||||
const sessionType = `remote-${sanitized}-${agent.provider}`;
|
||||
const agentId = sessionType;
|
||||
const vendor = sessionType;
|
||||
@@ -349,17 +348,20 @@ export class RemoteAgentHostContribution extends Disposable implements IWorkbenc
|
||||
const sessionWorkingDirs = new Map<string, URI>();
|
||||
agentStore.add(toDisposable(() => sessionWorkingDirs.clear()));
|
||||
|
||||
// Capture the working directory from the active session for new sessions
|
||||
const resolveWorkingDirectory = (resourceKey: string): URI | undefined => {
|
||||
// Capture the working directory from the session that is being created.
|
||||
const resolveWorkingDirectory = (sessionResource: URI): URI | undefined => {
|
||||
const resourceKey = sessionResource.toString();
|
||||
const cached = sessionWorkingDirs.get(resourceKey);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const activeSession = this._sessionsManagementService.activeSession.get();
|
||||
const repoUri = activeSession?.workspace.get()?.repositories[0]?.uri;
|
||||
if (repoUri) {
|
||||
sessionWorkingDirs.set(resourceKey, repoUri);
|
||||
return repoUri;
|
||||
const provider = this._sessionsProvidersService.getProvider<RemoteAgentHostSessionsProvider>(providerId);
|
||||
const session = provider?.getSessionByResource(sessionResource);
|
||||
const repository = session?.workspace.get()?.repositories[0];
|
||||
const workingDirectory = repository?.workingDirectory ?? repository?.uri;
|
||||
if (workingDirectory) {
|
||||
sessionWorkingDirs.set(resourceKey, workingDirectory);
|
||||
return workingDirectory;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@@ -370,6 +370,25 @@ export class RemoteAgentHostSessionsProvider extends Disposable implements ISess
|
||||
return sessions;
|
||||
}
|
||||
|
||||
getSessionByResource(resource: URI): ISession | undefined {
|
||||
if (this._currentNewSession?.resource.toString() === resource.toString()) {
|
||||
return this._chatToSession(this._currentNewSession);
|
||||
}
|
||||
|
||||
if (this._pendingSession?.resource.toString() === resource.toString()) {
|
||||
return this._pendingSession;
|
||||
}
|
||||
|
||||
this._ensureSessionCache();
|
||||
for (const cached of this._sessionCache.values()) {
|
||||
if (cached.resource.toString() === resource.toString()) {
|
||||
return this._chatToSession(cached);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// -- Session Lifecycle --
|
||||
|
||||
private _currentNewSession: IChatData | undefined;
|
||||
|
||||
+23
@@ -369,6 +369,29 @@ suite('RemoteAgentHostSessionsProvider', () => {
|
||||
assert.strictEqual(session.sessionType, provider.sessionTypes[0].id);
|
||||
});
|
||||
|
||||
test('getSessionByResource resolves current new session without listing it', () => {
|
||||
const provider = createProvider(disposables, connection);
|
||||
const workspace = {
|
||||
label: 'my-project',
|
||||
icon: { id: 'remote' },
|
||||
repositories: [{ uri: URI.parse('vscode-agent-host://auth/home/user/project'), workingDirectory: undefined, detail: undefined, baseBranchName: undefined, baseBranchProtected: undefined }],
|
||||
requiresWorkspaceTrust: false,
|
||||
};
|
||||
|
||||
const session = provider.createNewSession(workspace);
|
||||
const resolved = provider.getSessionByResource(session.resource);
|
||||
|
||||
assert.deepStrictEqual({
|
||||
listedSessions: provider.getSessions().length,
|
||||
resolvedResource: resolved?.resource.toString(),
|
||||
resolvedWorkspaceLabel: resolved?.workspace.get()?.label,
|
||||
}, {
|
||||
listedSessions: 0,
|
||||
resolvedResource: session.resource.toString(),
|
||||
resolvedWorkspaceLabel: 'my-project',
|
||||
});
|
||||
});
|
||||
|
||||
test('createNewSession throws when no repository URI', () => {
|
||||
const provider = createProvider(disposables, connection);
|
||||
const workspace = { label: 'empty', icon: { id: 'remote' }, repositories: [], requiresWorkspaceTrust: false };
|
||||
|
||||
+7
-4
@@ -37,6 +37,7 @@ import { IChatAgentData, IChatAgentImplementation, IChatAgentRequest, IChatAgent
|
||||
import { ToolInvocationPresentation } from '../../../common/tools/languageModelToolsService.js';
|
||||
import { getAgentHostIcon } from '../agentSessions.js';
|
||||
import { AgentHostEditingSession } from './agentHostEditingSession.js';
|
||||
import { IAgentHostSessionWorkingDirectoryResolver } from './agentHostSessionWorkingDirectoryResolver.js';
|
||||
import { IAgentHostTerminalService } from '../../../../terminal/browser/agentHostTerminalService.js';
|
||||
import { activeTurnToProgress, completedToolCallToEditParts, completedToolCallToSerialized, finalizeToolInvocation, getTerminalContentUri, toolCallStateToInvocation, turnsToHistory, updateRunningToolSpecificData, type IToolCallFileEdit } from './stateToProgressAdapter.js';
|
||||
import { getToolKind } from '../../../../../../platform/agentHost/common/state/sessionReducers.js';
|
||||
@@ -237,9 +238,10 @@ export interface IAgentHostSessionHandlerConfig {
|
||||
readonly extensionDisplayName?: string;
|
||||
/**
|
||||
* Optional callback to resolve a working directory for a new session.
|
||||
* If not provided, falls back to the first workspace folder.
|
||||
* If not provided or unresolved, session resource resolvers are consulted before
|
||||
* falling back to the first workspace folder.
|
||||
*/
|
||||
readonly resolveWorkingDirectory?: (resourceKey: string) => URI | undefined;
|
||||
readonly resolveWorkingDirectory?: (sessionResource: URI) => URI | undefined;
|
||||
/**
|
||||
* Optional callback invoked when the server rejects an operation because
|
||||
* authentication is required. Should trigger interactive authentication
|
||||
@@ -286,6 +288,7 @@ export class AgentHostSessionHandler extends Disposable implements IChatSessionC
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@ITerminalChatService private readonly _terminalChatService: ITerminalChatService,
|
||||
@IAgentHostTerminalService private readonly _agentHostTerminalService: IAgentHostTerminalService,
|
||||
@IAgentHostSessionWorkingDirectoryResolver private readonly _workingDirectoryResolver: IAgentHostSessionWorkingDirectoryResolver,
|
||||
) {
|
||||
super();
|
||||
this._config = config;
|
||||
@@ -1798,8 +1801,8 @@ export class AgentHostSessionHandler extends Disposable implements IChatSessionC
|
||||
/** Creates a new backend session and subscribes to its state. */
|
||||
private async _createAndSubscribe(sessionResource: URI, modelId?: string, fork?: { session: URI; turnIndex: number }): Promise<URI> {
|
||||
const rawModelId = this._extractRawModelId(modelId);
|
||||
const resourceKey = sessionResource.path.substring(1);
|
||||
const workingDirectory = this._config.resolveWorkingDirectory?.(resourceKey)
|
||||
const workingDirectory = this._config.resolveWorkingDirectory?.(sessionResource)
|
||||
?? this._workingDirectoryResolver.resolve(sessionResource)
|
||||
?? this._workspaceContextService.getWorkspace().folders[0]?.uri;
|
||||
|
||||
this._logService.trace(`[AgentHost] Creating new session, model=${rawModelId ?? '(default)'}, provider=${this._config.provider}${fork ? `, fork from ${fork.session.toString()} at index ${fork.turnIndex}` : ''}`);
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable, toDisposable } from '../../../../../../base/common/lifecycle.js';
|
||||
import { URI } from '../../../../../../base/common/uri.js';
|
||||
import { createDecorator } from '../../../../../../platform/instantiation/common/instantiation.js';
|
||||
import { InstantiationType, registerSingleton } from '../../../../../../platform/instantiation/common/extensions.js';
|
||||
|
||||
export const IAgentHostSessionWorkingDirectoryResolver = createDecorator<IAgentHostSessionWorkingDirectoryResolver>('agentHostSessionWorkingDirectoryResolver');
|
||||
|
||||
export interface IAgentHostSessionWorkingDirectoryResolver {
|
||||
readonly _serviceBrand: undefined;
|
||||
registerResolver(sessionType: string, resolver: (sessionResource: URI) => URI | undefined): IDisposable;
|
||||
resolve(sessionResource: URI): URI | undefined;
|
||||
}
|
||||
|
||||
class AgentHostSessionWorkingDirectoryResolver implements IAgentHostSessionWorkingDirectoryResolver {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private readonly _resolvers = new Map<string, (sessionResource: URI) => URI | undefined>();
|
||||
|
||||
registerResolver(sessionType: string, resolver: (sessionResource: URI) => URI | undefined): IDisposable {
|
||||
this._resolvers.set(sessionType, resolver);
|
||||
return toDisposable(() => {
|
||||
if (this._resolvers.get(sessionType) === resolver) {
|
||||
this._resolvers.delete(sessionType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
resolve(sessionResource: URI): URI | undefined {
|
||||
return this._resolvers.get(sessionResource.scheme)?.(sessionResource);
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IAgentHostSessionWorkingDirectoryResolver, AgentHostSessionWorkingDirectoryResolver, InstantiationType.Delayed);
|
||||
+30
-1
@@ -47,6 +47,7 @@ import { IStorageService, InMemoryStorageService } from '../../../../../../platf
|
||||
import { IAgentSubscription } from '../../../../../../platform/agentHost/common/state/agentSubscription.js';
|
||||
import { ITerminalChatService } from '../../../../terminal/browser/terminal.js';
|
||||
import { IAgentHostTerminalService } from '../../../../terminal/browser/agentHostTerminalService.js';
|
||||
import { IAgentHostSessionWorkingDirectoryResolver } from '../../../browser/agentSessions/agentHost/agentHostSessionWorkingDirectoryResolver.js';
|
||||
|
||||
// ---- Mock agent host service ------------------------------------------------
|
||||
|
||||
@@ -259,7 +260,7 @@ class MockChatAgentService extends mock<IChatAgentService>() {
|
||||
|
||||
// ---- Helpers ----------------------------------------------------------------
|
||||
|
||||
function createTestServices(disposables: DisposableStore) {
|
||||
function createTestServices(disposables: DisposableStore, workingDirectoryResolver?: { resolve(sessionResource: URI): URI | undefined }) {
|
||||
const instantiationService = disposables.add(new TestInstantiationService());
|
||||
|
||||
const agentHostService = new MockAgentHostService();
|
||||
@@ -313,6 +314,10 @@ function createTestServices(disposables: DisposableStore) {
|
||||
instantiationService.stub(IAgentHostTerminalService, {
|
||||
reviveTerminal: async () => undefined!,
|
||||
});
|
||||
instantiationService.stub(IAgentHostSessionWorkingDirectoryResolver, {
|
||||
registerResolver: () => toDisposable(() => { }),
|
||||
resolve: sessionResource => workingDirectoryResolver?.resolve(sessionResource),
|
||||
});
|
||||
|
||||
return { instantiationService, agentHostService, chatAgentService };
|
||||
}
|
||||
@@ -1605,6 +1610,30 @@ suite('AgentHostChatContribution', () => {
|
||||
assert.strictEqual(agentHostService.createSessionCalls[0].workingDirectory?.toString(), URI.file('/custom/working/dir').toString());
|
||||
}));
|
||||
|
||||
test('handler uses registered working directory resolver', () => runWithFakedTimers({ useFakeTimers: true }, async () => {
|
||||
const resolvedWorkingDirectory = URI.file('/resolved/working/dir');
|
||||
const { instantiationService, agentHostService } = createTestServices(disposables, {
|
||||
resolve: () => resolvedWorkingDirectory,
|
||||
});
|
||||
|
||||
const handler = disposables.add(instantiationService.createInstance(AgentHostSessionHandler, {
|
||||
provider: 'copilot' as const,
|
||||
agentId: 'workdir-resolver-test',
|
||||
sessionType: 'workdir-resolver-test',
|
||||
fullName: 'Test',
|
||||
description: 'test',
|
||||
connection: agentHostService,
|
||||
connectionAuthority: 'local',
|
||||
}));
|
||||
|
||||
const { turnPromise, session, turnId, fire } = await startTurn(handler, agentHostService, disposables);
|
||||
fire({ type: 'session/turnComplete', session, turnId } as ISessionAction);
|
||||
await turnPromise;
|
||||
|
||||
assert.strictEqual(agentHostService.createSessionCalls.length, 1);
|
||||
assert.strictEqual(agentHostService.createSessionCalls[0].workingDirectory?.toString(), resolvedWorkingDirectory.toString());
|
||||
}));
|
||||
|
||||
test('handler passes vscode-agent-host URI as-is to createSession', () => runWithFakedTimers({ useFakeTimers: true }, async () => {
|
||||
const { instantiationService, agentHostService } = createTestServices(disposables);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user