Feedback update

This commit is contained in:
Vijay Upadya
2026-08-19 12:41:36 -07:00
parent ec5cdc6326
commit 7a7d6adee8
3 changed files with 42 additions and 20 deletions
@@ -40,8 +40,6 @@ import { IWorkspaceTrustManagementService } from '../../../../../platform/worksp
import { AgentHostDownloadProgress } from '../../../../../workbench/contrib/chat/browser/agentSessions/agentHost/agentHostDownloadProgress.js';
import { IAgentCustomizationScope, IAgentHostActiveClientService } from '../../../../../workbench/contrib/chat/browser/agentSessions/agentHost/agentHostActiveClientService.js';
import { IChatWidgetService } from '../../../../../workbench/contrib/chat/browser/chat.js';
import { getCopilotCliSessionRawId, migratedCopilotCliResource } from '../../../../../workbench/contrib/chat/browser/copilotCliEventsUri.js';
import { adoptLegacyCopilotCliResource } from '../../../../../workbench/contrib/chat/browser/agentSessions/agentHost/agentHostLegacyMigration.js';
import { ChatMode } from '../../../../../workbench/contrib/chat/common/chatModes.js';
import { IChatSendRequestOptions, IChatService, type IChatModelReference } from '../../../../../workbench/contrib/chat/common/chatService/chatService.js';
import { IChatSessionFileChange, IChatSessionFileChange2, IChatSessionsService } from '../../../../../workbench/contrib/chat/common/chatSessionsService.js';
@@ -5076,24 +5074,6 @@ export abstract class BaseAgentHostSessionsProvider extends Disposable implement
this._refreshSessions();
}
/**
* Redirects a legacy extension-host Copilot CLI resource to its agent-host
* twin, adopting it on the way.
*
* Subscribing to the twin is what performs adoption: the host restores the
* session, which runs its own provenance and working-directory checks. A
* session that is not ours to adopt fails that subscribe, and the caller
* falls back to the legacy resource — the same outcome as before, so an
* external session is never worse off than it is today.
*/
async resolveSessionResource(resource: URI): Promise<URI | undefined> {
const rawId = getCopilotCliSessionRawId(migratedCopilotCliResource(resource));
if (rawId && this._sessionCache.has(rawId)) {
return migratedCopilotCliResource(resource); // already adopted; no round-trip
}
return adoptLegacyCopilotCliResource(this.connection, resource, this._logService);
}
protected async _refreshSessions(announceExistingAsAdded = false): Promise<void> {
const connection = this.connection;
if (!connection) {
@@ -28,6 +28,8 @@ import { providerAutomationStorageKey } from '../../../automations/common/automa
import { ISessionsProviderAutomations } from '../../../../services/sessions/common/sessionsProvider.js';
import { IAgentHostActiveClientService } from '../../../../../workbench/contrib/chat/browser/agentSessions/agentHost/agentHostActiveClientService.js';
import { IChatWidgetService } from '../../../../../workbench/contrib/chat/browser/chat.js';
import { getCopilotCliSessionRawId, migratedCopilotCliResource } from '../../../../../workbench/contrib/chat/browser/copilotCliEventsUri.js';
import { adoptLegacyCopilotCliResource } from '../../../../../workbench/contrib/chat/browser/agentSessions/agentHost/agentHostLegacyMigration.js';
import { IChatService } from '../../../../../workbench/contrib/chat/common/chatService/chatService.js';
import { IChatSessionsService } from '../../../../../workbench/contrib/chat/common/chatSessionsService.js';
import { ILanguageModelsService } from '../../../../../workbench/contrib/chat/common/languageModels.js';
@@ -76,6 +78,26 @@ export class LocalAgentHostSessionsProvider extends BaseAgentHostSessionsProvide
return -1;
}
/**
* Redirects a legacy extension-host Copilot CLI resource to its agent-host
* twin, adopting it on the way.
*
* Subscribing to the twin is what performs adoption: the host restores the
* session, which runs its own provenance and working-directory checks. A
* session that is not ours to adopt fails that subscribe, and the caller falls
* back to the legacy resource, so an external session is never worse off.
*
* Local-only by definition: `copilotcli:` and `agent-host-copilotcli:` name
* sessions on this machine, so a remote host must never claim or probe them.
*/
async resolveSessionResource(resource: URI): Promise<URI | undefined> {
const rawId = getCopilotCliSessionRawId(migratedCopilotCliResource(resource));
if (rawId && this._sessionCache.has(rawId)) {
return migratedCopilotCliResource(resource); // already adopted; no round-trip
}
return adoptLegacyCopilotCliResource(this.connection, resource, this._logService);
}
constructor(
@IAgentHostService private readonly _agentHostService: IAgentHostService,
@IChatSessionsService chatSessionsService: IChatSessionsService,
@@ -3247,6 +3247,26 @@ suite('SessionsManagementService', () => {
const resolved = await service.resolveSessionResource(native);
assert.deepStrictEqual({ resolved: resolved.toString(), seen }, { resolved: native.toString(), seen: [native.toString()] });
});
test('a provider that declines does not stop a later provider from claiming', async () => {
const session = legacyCliSession();
const declining = new class extends TestSessionsProvider {
constructor() { super(session); }
override readonly id = 'declining';
override getSessions(): ISession[] { return [session]; }
override resolveSessionResource(): Promise<URI | undefined> { return Promise.resolve(undefined); }
};
const claiming = new class extends TestSessionsProvider {
constructor() { super(session); }
override readonly id = LOCAL_AGENT_HOST_PROVIDER_ID;
override readonly order = 1;
override getSessions(): ISession[] { return [session]; }
override resolveSessionResource(): Promise<URI | undefined> { return Promise.resolve(twinResource); }
};
const service = createSessionsManagementService(session, disposables, [declining, claiming]).service;
assert.strictEqual((await service.resolveSessionResource(legacyResource)).toString(), twinResource.toString());
});
});
function serviceWithSessions(sessions: readonly ISession[]): ISessionsManagementService {