Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/vs/sessions/common/agentHostSessionsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ export interface IAgentHostSessionsProvider extends ISessionsProvider {
*/
getCustomizations(sessionId: string): readonly Customization[];

/**
* Returns the working directory for the session, if provided by the host.
*/
getWorkingDirectory(sessionId: string): string | undefined;

/**
* Set (or clear) the selected custom agent for a session. Optional so
* providers that don't expose custom agents can omit it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,11 @@ export abstract class BaseAgentHostSessionsProvider extends Disposable implement
return sessionState?.customizations ?? [];
}

getWorkingDirectory(sessionId: string): string | undefined {
const sessionState = this._lastSessionStates.get(sessionId);
return sessionState?.summary.workingDirectory;
}

// -- Session actions ------------------------------------------------------

async archiveSession(sessionId: string): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ function createTestCustomAgentsService(connection: MockAgentConnection, rootCust
}
return [...rootCustomizations, ...(sessionState.customizations ?? [])];
},
getWorkingDirectory(sessionResource: URI): string | undefined {
return undefined;
}
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { URI } from '../../../../base/common/uri.js';
import { Emitter, Event } from '../../../../base/common/event.js';
import { Disposable, DisposableMap } from '../../../../base/common/lifecycle.js';
import { combinedDisposable, Disposable, DisposableMap } from '../../../../base/common/lifecycle.js';
import { basename } from '../../../../base/common/resources.js';
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
import { IAgentHostCustomizationService } from '../../../../workbench/contrib/chat/browser/agentSessions/agentHost/agentHostCustomizationService.js';
Expand All @@ -14,6 +14,7 @@ import { ISessionsProvidersService } from '../../sessions/browser/sessionsProvid
import { ISessionsManagementService } from '../../sessions/common/sessionsManagement.js';
import { ISessionsProvider } from '../../sessions/common/sessionsProvider.js';
import { AgentCustomization, Customization, CustomizationType } from '../../../../platform/agentHost/common/state/sessionState.js';
import { ISession } from '../../sessions/common/session.js';

export class AgentHostCustomizationService extends Disposable implements IAgentHostCustomizationService {
declare readonly _serviceBrand: undefined;
Expand All @@ -34,37 +35,56 @@ export class AgentHostCustomizationService extends Disposable implements IAgentH
}));
}

getCustomAgents(sessionResource: URI): readonly AgentCustomization[] {
const session = this._sessionsManagementService.activeSession.get();
if (!session || session.resource.toString() !== sessionResource.toString()) {
return [];
private _getSession(sessionResource: URI): ISession | undefined {
const activeSession = this._sessionsManagementService.activeSession.get();
if (activeSession && activeSession.resource.toString() === sessionResource.toString()) {
return activeSession;
}
return this._sessionsManagementService.getSession(sessionResource);
}

private _getAHSProvider(session: ISession): IAgentHostSessionsProvider | undefined {
const provider = this._sessionsProvidersService.getProvider(session.providerId);
if (provider && isAgentHostProvider(provider)) {
this._ensureProviderListener(provider);
const agents = provider.getCustomAgents(session.sessionId);
const activeMode = session.mode.get()?.id;
const result = agents.length === 0 && activeMode ? [this._agentFromMode(activeMode)] : agents;
return result;
return provider;
}
return undefined;
}

getCustomAgents(sessionResource: URI): readonly AgentCustomization[] {
const session = this._getSession(sessionResource);
if (session) {
const provider = this._getAHSProvider(session);
if (provider) {
const agents = provider.getCustomAgents(session.sessionId);
const activeMode = session.mode.get()?.id;
return agents.length === 0 && activeMode ? [this._agentFromMode(activeMode)] : agents;
}
}
return [];
}

getCustomizations(sessionResource: URI): readonly Customization[] {
const session = this._sessionsManagementService.getSession(sessionResource);
if (!session) {
return [];
const session = this._getSession(sessionResource);
if (session) {
const provider = this._getAHSProvider(session);
if (provider) {
return provider.getCustomizations(session.sessionId);
}
}
return [];
}

const provider = this._sessionsProvidersService.getProvider(session.providerId);
if (provider && isAgentHostProvider(provider)) {
this._ensureProviderListener(provider);
return provider.getCustomizations(session.sessionId);
getWorkingDirectory(sessionResource: URI): string | undefined {
const session = this._getSession(sessionResource);
if (session) {
const provider = this._getAHSProvider(session);
if (provider) {
return provider.getWorkingDirectory(session.sessionId);
}
}

return [];
return undefined;
}


Expand All @@ -73,9 +93,15 @@ export class AgentHostCustomizationService extends Disposable implements IAgentH
return;
}

this._providerListeners.set(provider, provider.onDidChangeCustomAgents(() => {
this._onDidChangeCustomAgents.fire();
}));
// Keep both subscriptions alive under one map key so replacing the provider entry disposes both together.
this._providerListeners.set(provider, combinedDisposable(
provider.onDidChangeCustomAgents(() => {
this._onDidChangeCustomAgents.fire();
}),
provider.onDidChangeCustomizations(() => {
this._onDidChangeCustomizations.fire();
})
));
}

private _agentFromMode(uri: string): AgentCustomization {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,11 @@ export class AgentCustomizationItemProvider extends Disposable implements ICusto
}
}

const workingDirectory = this._customAgentsService.getWorkingDirectory(sessionResource);

for (const sessionCustomization of directoryCustomizations) {
const source = AICustomizationSources.local; // TODO
const groupKey = undefined; //sessionCustomization.clientId ? REMOTE_CLIENT_GROUP : REMOTE_HOST_GROUP;
const source = workingDirectory && sessionCustomization.uri.startsWith(workingDirectory) ? AICustomizationSources.local : AICustomizationSources.user;
const groupKey = sessionCustomization.clientId ? REMOTE_CLIENT_GROUP : undefined;
for (const child of this.toDirectoryItems(sessionCustomization, source, groupKey)) {
items.set(child.itemKey ?? child.uri.toString(), {
...child,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export interface IAgentHostCustomizationService {
getCustomAgents(sessionResource: URI): readonly AgentCustomization[];

getCustomizations(sessionResource: URI): readonly Customization[];

getWorkingDirectory(sessionResource: URI): string | undefined;
}

export class NullAgentHostCustomizationService implements IAgentHostCustomizationService {
Expand All @@ -42,6 +44,9 @@ export class NullAgentHostCustomizationService implements IAgentHostCustomizatio
getCustomizations(_sessionResource: URI): readonly Customization[] {
return [];
}
getWorkingDirectory(sessionResource: URI): string | undefined {
return undefined;
}
}

class WorkbenchAgentHostCustomizationService extends Disposable implements IAgentHostCustomizationService {
Expand Down Expand Up @@ -101,6 +106,11 @@ class WorkbenchAgentHostCustomizationService extends Disposable implements IAgen
return sessionState?.customizations ?? [];
}

getWorkingDirectory(sessionResource: URI): string | undefined {
const sessionState = this._readSessionState(sessionResource);
return sessionState?.summary.workingDirectory;
}

private _readSessionState(sessionResource: URI): SessionState | undefined {
const backendSession = this._resolveBackendSession(sessionResource);
const value = backendSession ? this._ensureSessionStateSubscription(sessionResource, backendSession)?.sub.value : undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ export const SYNCABLE_PROMPT_TYPES: readonly PromptsType[] = [
*/
export const SYNCABLE_STORAGE_SOURCES: readonly PromptsStorage[] = [
PromptsStorage.plugin,
PromptsStorage.extension,
PromptsStorage.user,
PromptsStorage.extension
];

export interface ILocalCustomizationFile {
Expand Down
Loading