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
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,6 @@ export interface IChatSessionMetadataStore {
storeForkedSessionMetadata(sourceSessionId: string, targetSessionId: string, customTitle: string): Promise<void>;
setSessionOrigin(sessionId: string): Promise<void>;
getSessionOrigin(sessionId: string): Promise<'vscode' | 'other'>;
setSessionParentId(sessionId: string, parentSessionId: string): Promise<void>;
getSessionParentId(sessionId: string): Promise<string | undefined>;
Comment thread
lszomoru marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,12 @@ export class MockChatSessionMetadataStore implements IChatSessionMetadataStore {
async getSessionOrigin(sessionId: string): Promise<'vscode' | 'other'> {
return this._sessionOrigins.get(sessionId) ?? 'vscode';
}

setSessionParentId(_sessionId: string, _parentSessionId: string): Promise<void> {
return Promise.resolve();
}

getSessionParentId(_sessionId: string): Promise<string | undefined> {
return Promise.resolve(undefined);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export type ISessionOptions = {
debugTargetSessionIds?: readonly string[];
mcpServerMappings?: McpServerMappings;
additionalWorkspaces?: IWorkspaceInfo[];
sessionParentId?: string;
}
export type IGetSessionOptions = ISessionOptions & { sessionId: string };
export type ICreateSessionOptions = ISessionOptions & { sessionId?: string };
Expand Down Expand Up @@ -567,7 +568,15 @@ export class CopilotCLISessionService extends Disposable implements ICopilotCLIS

const session = this.createCopilotSession(sdkSession, options.workspace, options.agent?.name, sessionManager);
session.object.add(mcpGateway);

// Set origin
void this._chatSessionMetadataStore.setSessionOrigin(session.object.sessionId);

// Set session parent id
if (options.sessionParentId) {
void this._chatSessionMetadataStore.setSessionParentId(session.object.sessionId, options.sessionParentId);
Comment thread
lszomoru marked this conversation as resolved.
}

return session;
}
catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,16 @@ export class ChatSessionMetadataStore extends Disposable implements IChatSession
return 'other';
}

public async setSessionParentId(sessionId: string, parentSessionId: string): Promise<void> {
await this._intialize.value;
await this.updateMetadataFields(sessionId, { parentSessionId });
}

public async getSessionParentId(sessionId: string): Promise<string | undefined> {
const metadata = await this.getSessionMetadata(sessionId, false);
return metadata?.parentSessionId;
}

private async getSessionMetadata(sessionId: string, createMetadataFileIfNotFound = true): Promise<ChatSessionMetadataFile | undefined> {
if (isUntitledSessionId(sessionId)) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,10 @@ export class CopilotCLIChatSessionContentProvider extends Disposable implements
workingDirectory: vscode.Uri | undefined,
): Promise<{ readonly [key: string]: unknown }> {
if (worktreeProperties) {
const sessionParentId = await this._metadataStore.getSessionParentId(sessionId);

return {
sessionParentId,
autoCommit: worktreeProperties.autoCommit !== false,
baseCommit: worktreeProperties?.baseCommit,
baseBranchName: worktreeProperties.version === 2
Expand Down Expand Up @@ -451,7 +454,8 @@ export class CopilotCLIChatSessionContentProvider extends Disposable implements
} satisfies { readonly [key: string]: unknown };
}

const [sessionRequestDetails, repositoryProperties] = await Promise.all([
const [sessionParentId, sessionRequestDetails, repositoryProperties] = await Promise.all([
this._metadataStore.getSessionParentId(sessionId),
this._metadataStore.getRequestDetails(sessionId),
this._metadataStore.getRepositoryProperties(sessionId)
]);
Expand All @@ -470,6 +474,7 @@ export class CopilotCLIChatSessionContentProvider extends Disposable implements
: undefined;

return {
sessionParentId,
isolationMode: IsolationMode.Workspace,
repositoryPath: repositoryProperties?.repositoryPath,
branchName: repositoryProperties?.branchName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const REPOSITORY_OPTION_ID = 'repository';
const _sessionWorktreeIsolationCache = new Map<string, boolean>();
const BRANCH_OPTION_ID = 'branch';
const ISOLATION_OPTION_ID = 'isolation';
const PARENT_SESSION_OPTION_ID = 'parentSessionId';
const LAST_USED_ISOLATION_OPTION_KEY = 'github.copilot.cli.lastUsedIsolationOption';
const OPEN_REPOSITORY_COMMAND_ID = 'github.copilot.cli.sessions.openRepository';
const OPEN_IN_COPILOT_CLI_COMMAND_ID = 'github.copilot.cli.openInCopilotCLI';
Expand Down Expand Up @@ -308,9 +309,12 @@ export class CopilotCLIChatSessionItemProvider extends Disposable implements vsc
// repository state which we are passing along through the metadata
worktreeProperties = await this.worktreeManager.getWorktreeProperties(session.id);

const sessionParentId = await this.chatSessionMetadataStore.getSessionParentId(session.id);

if (worktreeProperties) {
// Worktree
metadata = {
sessionParentId,
autoCommit: worktreeProperties.autoCommit !== false,
baseCommit: worktreeProperties?.baseCommit,
baseBranchName: worktreeProperties.version === 2
Expand Down Expand Up @@ -373,6 +377,7 @@ export class CopilotCLIChatSessionItemProvider extends Disposable implements vsc
: undefined;

metadata = {
sessionParentId,
isolationMode: IsolationMode.Workspace,
repositoryPath: repositoryProperties?.repositoryPath,
branchName: repositoryProperties?.branchName,
Expand Down Expand Up @@ -1267,6 +1272,7 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
let { chatSessionContext } = context;
const disposables = new DisposableStore();
let sessionId: string | undefined = undefined;
let sessionParentId: string | undefined = undefined;
let sdkSessionId: string | undefined = undefined;
try {

Expand All @@ -1284,6 +1290,8 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
_sessionBranch.set(sessionId, value);
} else if (opt.optionId === ISOLATION_OPTION_ID && value) {
_sessionIsolation.set(sessionId, value as IsolationMode);
} else if (opt.optionId === PARENT_SESSION_OPTION_ID && value) {
sessionParentId = value;
}
Comment thread
lszomoru marked this conversation as resolved.
}
}
Expand Down Expand Up @@ -1369,7 +1377,7 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
};
const newBranch = (isUntitled && request.prompt && this.branchNameGenerator) ? this.branchNameGenerator.generateBranchName(fakeContext, token) : undefined;

const sessionResult = await this.getOrCreateSession(request, chatSessionContext, stream, { model, agent, newBranch }, disposables, token);
const sessionResult = await this.getOrCreateSession(request, chatSessionContext, stream, { model, agent, newBranch, sessionParentId }, disposables, token);
const session = sessionResult.session;
if (session) {
disposables.add(session);
Expand Down Expand Up @@ -1729,7 +1737,7 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
}
}

private async getOrCreateSession(request: vscode.ChatRequest, chatSessionContext: vscode.ChatSessionContext, stream: vscode.ChatResponseStream, options: { model: { model: string; reasoningEffort?: string } | undefined; agent: SweCustomAgent | undefined; newBranch?: Promise<string | undefined> }, disposables: DisposableStore, token: vscode.CancellationToken): Promise<{ session: IReference<ICopilotCLISession> | undefined; trusted: boolean }> {
private async getOrCreateSession(request: vscode.ChatRequest, chatSessionContext: vscode.ChatSessionContext, stream: vscode.ChatResponseStream, options: { model: { model: string; reasoningEffort?: string } | undefined; agent: SweCustomAgent | undefined; newBranch?: Promise<string | undefined>; sessionParentId?: string }, disposables: DisposableStore, token: vscode.CancellationToken): Promise<{ session: IReference<ICopilotCLISession> | undefined; trusted: boolean }> {
const { resource } = chatSessionContext.chatSessionItem;
const existingSessionId = this.sessionItemProvider.untitledSessionIdMapping.get(SessionIdForCLI.parse(resource));
const id = existingSessionId ?? SessionIdForCLI.parse(resource);
Expand All @@ -1747,7 +1755,7 @@ export class CopilotCLIChatSessionParticipant extends Disposable {
const debugTargetSessionIds = extractDebugTargetSessionIds(request.references);
const mcpServerMappings = buildMcpServerMappings(request.tools);
const session = isNewSession ?
await this.sessionService.createSession({ model: model?.model, reasoningEffort: model?.reasoningEffort, workspace: workspaceInfo, agent, debugTargetSessionIds, mcpServerMappings }, token) :
await this.sessionService.createSession({ model: model?.model, reasoningEffort: model?.reasoningEffort, workspace: workspaceInfo, agent, debugTargetSessionIds, mcpServerMappings, sessionParentId: options.sessionParentId }, token) :
await this.sessionService.getSession({ sessionId: id, model: model?.model, reasoningEffort: model?.reasoningEffort, workspace: workspaceInfo, agent, debugTargetSessionIds, mcpServerMappings }, token);
this.sessionItemProvider.notifySessionsChange();
// TODO @DonJayamanne We need to refresh to add this new session, but we need a label.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ function createProvider() {
const metadataStore = new class extends mock<IChatSessionMetadataStore>() {
override getRequestDetails = vi.fn(async () => []);
override getRepositoryProperties = vi.fn(async () => undefined);
override getSessionParentId = vi.fn(async () => undefined);
};
const gitService = new TestGitService();
const folderRepositoryManager = new TestFolderRepositoryManager();
Expand Down
Loading