Skip to content

Commit df4d69e

Browse files
joshspicerCopilot
andauthored
sessions: sync customizations harness with AHP session resource scheme (#315127)
The customizations editor harness selector wasn't switching to the AHP remote when an AHP session was selected, because all three sync points looked up the harness by `session.sessionType`. For AHP sessions `sessionType` is the agent provider name (e.g. `copilotcli`) and is shared across all hosts, so the lookup always matched the local CLI harness rather than the per-host AHP harness: - Local AHP harness id: `agent-host-${provider}` - Remote AHP harness id: `remote-${authority}-${provider}` Both of those equal `session.resource.scheme`. Add a `findHarnessIdForSession` helper that prefers the resource scheme and falls back to `sessionType` for harnesses whose id matches it directly, and use it from all three sync points: - ActiveSessionHarnessSyncContribution autorun - CustomizationLinkViewItem.run (sidebar customization links) - AICustomizationShortcutsWidget._openWelcomePage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 5c9093d commit df4d69e

2 files changed

Lines changed: 42 additions & 14 deletions

File tree

‎src/vs/sessions/contrib/sessions/browser/aiCustomizationShortcutsWidget.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { defaultButtonStyles } from '../../../../platform/theme/browser/defaultS
1919
import { IMcpService } from '../../../../workbench/contrib/mcp/common/mcpTypes.js';
2020
import { IAICustomizationItemsModel } from '../../../../workbench/contrib/chat/browser/aiCustomization/aiCustomizationItemsModel.js';
2121
import { ICustomizationHarnessService } from '../../../../workbench/contrib/chat/common/customizationHarnessService.js';
22-
import { CUSTOMIZATION_ITEMS, SESSIONS_CUSTOMIZATIONS_SIDEBAR_MODE_SETTING, SessionsCustomizationsSidebarMode } from './customizationsToolbar.contribution.js';
22+
import { CUSTOMIZATION_ITEMS, findHarnessIdForSession, SESSIONS_CUSTOMIZATIONS_SIDEBAR_MODE_SETTING, SessionsCustomizationsSidebarMode } from './customizationsToolbar.contribution.js';
2323
import { Menus } from '../../../browser/menus.js';
2424
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
2525
import { IEditorService } from '../../../../workbench/services/editor/common/editorService.js';
@@ -167,9 +167,9 @@ export class AICustomizationShortcutsWidget extends Disposable {
167167
}
168168

169169
private async _openWelcomePage(): Promise<void> {
170-
const activeSessionType = this.sessionsManagementService.activeSession.get()?.sessionType;
171-
if (activeSessionType && this.harnessService.findHarnessById(activeSessionType)) {
172-
this.harnessService.setActiveHarness(activeSessionType);
170+
const harnessId = findHarnessIdForSession(this.sessionsManagementService.activeSession.get(), this.harnessService);
171+
if (harnessId) {
172+
this.harnessService.setActiveHarness(harnessId);
173173
}
174174

175175
const input = AICustomizationManagementEditorInput.getOrCreate();

‎src/vs/sessions/contrib/sessions/browser/customizationsToolbar.contribution.ts‎

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { defaultButtonStyles } from '../../../../platform/theme/browser/defaultS
2828
import { IEditorService } from '../../../../workbench/services/editor/common/editorService.js';
2929
import { AICustomizationManagementSection } from '../../../../workbench/contrib/chat/common/aiCustomizationWorkspaceService.js';
3030
import { ICustomizationHarnessService } from '../../../../workbench/contrib/chat/common/customizationHarnessService.js';
31+
import { ISession } from '../../../services/sessions/common/session.js';
3132
import { ISessionsManagementService } from '../../../services/sessions/common/sessionsManagement.js';
3233
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
3334
import { Registry } from '../../../../platform/registry/common/platform.js';
@@ -287,9 +288,9 @@ export class CustomizationsToolbarContribution extends Disposable implements IWo
287288
const harnessService = accessor.get(ICustomizationHarnessService);
288289
const sessionsManagementService = accessor.get(ISessionsManagementService);
289290
const configurationService = accessor.get(IConfigurationService);
290-
const activeSessionType = sessionsManagementService.activeSession.get()?.sessionType;
291-
if (activeSessionType && harnessService.findHarnessById(activeSessionType)) {
292-
harnessService.setActiveHarness(activeSessionType);
291+
const harnessId = findHarnessIdForSession(sessionsManagementService.activeSession.get(), harnessService);
292+
if (harnessId) {
293+
harnessService.setActiveHarness(harnessId);
293294
}
294295
const input = AICustomizationManagementEditorInput.getOrCreate();
295296
const pane = await editorService.openEditor(input, { pinned: true });
@@ -310,11 +311,37 @@ export class CustomizationsToolbarContribution extends Disposable implements IWo
310311

311312
registerWorkbenchContribution2(CustomizationsToolbarContribution.ID, CustomizationsToolbarContribution, WorkbenchPhase.AfterRestored);
312313

314+
/**
315+
* Returns the harness id that matches a given session, or `undefined` if no
316+
* harness is registered for it.
317+
*
318+
* The session's `resource.scheme` is the per-host harness id (e.g. local AHP
319+
* uses `agent-host-${provider}` and remote AHP uses `remote-${authority}-${provider}`),
320+
* while {@link ISession.sessionType} is the agent provider name shared across
321+
* hosts (e.g. `copilotcli`). Lookup therefore prefers the resource scheme so
322+
* that an AHP remote session selects its remote harness rather than the local
323+
* harness with the same `sessionType`. The `sessionType` is kept as a fallback
324+
* for harnesses whose id matches it directly.
325+
*/
326+
export function findHarnessIdForSession(session: ISession | undefined, harnessService: ICustomizationHarnessService): string | undefined {
327+
if (!session) {
328+
return undefined;
329+
}
330+
const schemeId = session.resource.scheme;
331+
if (harnessService.findHarnessById(schemeId)) {
332+
return schemeId;
333+
}
334+
if (harnessService.findHarnessById(session.sessionType)) {
335+
return session.sessionType;
336+
}
337+
return undefined;
338+
}
339+
313340
/**
314341
* Keeps the active customization harness in sync with the currently active
315-
* session's `sessionType`. This drives the customizations sidebar (counts,
316-
* filtering) and the customizations editor so they reflect the harness that
317-
* matches the session the user is interacting with.
342+
* session. This drives the customizations sidebar (counts, filtering) and the
343+
* customizations editor so they reflect the harness that matches the session
344+
* the user is interacting with.
318345
*
319346
* This covers two cases identically:
320347
* - opening / navigating into an existing session
@@ -332,16 +359,17 @@ export class ActiveSessionHarnessSyncContribution extends Disposable implements
332359
super();
333360

334361
this._register(autorun(reader => {
335-
const sessionType = sessionsManagementService.activeSession.read(reader)?.sessionType;
336-
if (!sessionType) {
362+
const session = sessionsManagementService.activeSession.read(reader);
363+
if (!session) {
337364
return;
338365
}
339366
// Re-read available harnesses so we re-run when an external harness
340367
// (e.g. agent host, CLI) registers asynchronously after the session
341368
// has already been selected.
342369
harnessService.availableHarnesses.read(reader);
343-
if (harnessService.findHarnessById(sessionType)) {
344-
harnessService.setActiveHarness(sessionType);
370+
const harnessId = findHarnessIdForSession(session, harnessService);
371+
if (harnessId) {
372+
harnessService.setActiveHarness(harnessId);
345373
}
346374
}));
347375
}

0 commit comments

Comments
 (0)