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 @@ -32,7 +32,7 @@ import { diffsEqual, diffsToChanges, mapProtocolStatus } from './agentHostDiffs.
import { buildMutableConfigSchema, IAgentHostSessionsProvider, resolvedConfigsEqual } from '../../../common/agentHostSessionsProvider.js';
import { agentHostSessionWorkspaceKey } from '../../../common/agentHostSessionWorkspace.js';
import { isSessionConfigComplete } from '../../../common/sessionConfig.js';
import { IChat, IGitHubInfo, ISession, ISessionType, ISessionWorkspace, ISessionWorkspaceBrowseAction, SessionStatus, toSessionId } from '../../../services/sessions/common/session.js';
import { IChat, IGitHubInfo, ISession, ISessionChangeset, ISessionType, ISessionWorkspace, ISessionWorkspaceBrowseAction, SessionStatus, toSessionId } from '../../../services/sessions/common/session.js';
import { ISendRequestOptions, ISessionChangeEvent } from '../../../services/sessions/common/sessionsProvider.js';

// ============================================================================
Expand Down Expand Up @@ -74,6 +74,7 @@ export class AgentHostSessionAdapter implements ISession {
readonly updatedAt: ISettableObservable<Date>;
readonly status: ISettableObservable<SessionStatus>;
readonly changes = observableValue<readonly (IChatSessionFileChange | IChatSessionFileChange2)[]>('changes', []);
readonly changesets = observableValue<readonly ISessionChangeset[]>('changesets', []);
readonly modelId: ISettableObservable<string | undefined>;
modelSelection: ModelSelection | undefined;
readonly mode = observableValue<{ readonly id: string; readonly kind: string } | undefined>('mode', undefined);
Expand Down Expand Up @@ -162,6 +163,7 @@ export class AgentHostSessionAdapter implements ISession {
updatedAt: this.updatedAt,
status: this.status,
changes: this.changes,
changesets: this.changesets,
modelId: this.modelId,
mode: this.mode,
isArchived: this.isArchived,
Expand Down Expand Up @@ -381,6 +383,7 @@ class NewSession extends Disposable {
this._status = observableValue<SessionStatus>(this, SessionStatus.Untitled);
const title = observableValue<string>(this, '');
const updatedAt = observableValue(this, new Date());
const changesets = observableValue<readonly ISessionChangeset[]>(this, []);
const changes = observableValue<readonly (IChatSessionFileChange | IChatSessionFileChange2)[]>(this, []);
this._modelId = observableValue<string | undefined>(this, undefined);
const mode = observableValue<{ readonly id: string; readonly kind: string } | undefined>(this, undefined);
Expand All @@ -394,6 +397,7 @@ class NewSession extends Disposable {
const mainChat: IChat = {
resource, createdAt, title, updatedAt,
status: this._status,
changesets,
changes,
modelId: this._modelId,
mode, isArchived, isRead, description, lastTurnEnd,
Expand All @@ -411,6 +415,7 @@ class NewSession extends Disposable {
title,
updatedAt,
status: this._status,
changesets,
changes,
modelId: this._modelId,
mode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ function makeActiveSession(providerId: string): IActiveSession {
title: observableValue('t', 'Test'),
updatedAt: observableValue('u', new Date()),
status: observableValue('s', 0),
changesets: observableValue('cs', []),
changes: observableValue('c', []),
modelId: observableValue('m', undefined),
mode: observableValue('mo', undefined),
Expand All @@ -50,6 +51,7 @@ function makeActiveSession(providerId: string): IActiveSession {
title: chat.title,
updatedAt: chat.updatedAt,
status: chat.status,
changesets: chat.changesets,
changes: chat.changes,
modelId: chat.modelId,
mode: chat.mode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function makeSession(opts: { repository?: URI; worktree?: URI } = {}): ISession
title: observableValue('title', 'session'),
updatedAt: observableValue('updatedAt', new Date()),
status: observableValue('status', SessionStatus.Untitled),
changesets: observableValue('changesets', []),
changes: observableValue('changes', []),
modelId: observableValue('modelId', undefined),
mode: observableValue('mode', undefined),
Expand All @@ -60,6 +61,7 @@ function makeSession(opts: { repository?: URI; worktree?: URI } = {}): ISession
title: chat.title,
updatedAt: chat.updatedAt,
status: chat.status,
changesets: chat.changesets,
changes: chat.changes,
modelId: chat.modelId,
mode: chat.mode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { AgentSessionProviders, AgentSessionTarget } from '../../../../workbench
import { IChatService, IChatSendRequestOptions } from '../../../../workbench/contrib/chat/common/chatService/chatService.js';
import { IChatResponseModel } from '../../../../workbench/contrib/chat/common/model/chatModel.js';
import { ChatSessionStatus, IChatSessionsService, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, SessionType } from '../../../../workbench/contrib/chat/common/chatSessionsService.js';
import { ISession, IChat, ISessionRepository, ISessionWorkspace, SessionStatus, GITHUB_REMOTE_FILE_SCHEME, IGitHubInfo, CopilotCLISessionType, CopilotCloudSessionType, ClaudeCodeSessionType, ISessionType, ISessionWorkspaceBrowseAction, ISessionFileChange, toSessionId, SESSION_WORKSPACE_GROUP_LOCAL } from '../../../services/sessions/common/session.js';
import { ISession, IChat, ISessionRepository, ISessionWorkspace, SessionStatus, GITHUB_REMOTE_FILE_SCHEME, IGitHubInfo, CopilotCLISessionType, CopilotCloudSessionType, ClaudeCodeSessionType, ISessionType, ISessionWorkspaceBrowseAction, ISessionFileChange, toSessionId, SESSION_WORKSPACE_GROUP_LOCAL, ISessionChangeset } from '../../../services/sessions/common/session.js';
import { ChatAgentLocation, ChatConfiguration, ChatModeKind, ChatPermissionLevel, isChatPermissionLevel } from '../../../../workbench/contrib/chat/common/constants.js';
import { basename, dirname, isEqual } from '../../../../base/common/resources.js';
import { ISendRequestOptions, ISessionChangeEvent, ISessionsProvider } from '../../../services/sessions/common/sessionsProvider.js';
Expand Down Expand Up @@ -71,6 +71,8 @@ export interface ICopilotChatSession {
readonly updatedAt: IObservable<Date>;
/** Current session status. */
readonly status: IObservable<SessionStatus>;
/** File changesets produced by the session. */
readonly changesets: IObservable<readonly ISessionChangeset[]>;
/** File changes produced by the session. */
readonly changes: IObservable<readonly ISessionFileChange[]>;
/** Currently selected model identifier. */
Expand Down Expand Up @@ -180,6 +182,9 @@ class CopilotCLISession extends Disposable implements ICopilotChatSession {
private readonly _loading = observableValue(this, true);
readonly loading: IObservable<boolean> = this._loading;

private readonly _changesets: ReturnType<typeof observableValue<readonly ISessionChangeset[]>>;
readonly changesets: IObservable<readonly ISessionChangeset[]>;

private readonly _changes: ReturnType<typeof observableValue<readonly ISessionFileChange[]>>;
readonly changes: IObservable<readonly ISessionFileChange[]>;

Expand Down Expand Up @@ -259,6 +264,9 @@ class CopilotCLISession extends Disposable implements ICopilotChatSession {
this._description = observableValue(this, undefined);
this.description = this._description;

this._changesets = observableValue<readonly ISessionChangeset[]>(this, []);
this.changesets = this._changesets;

Comment thread
lszomoru marked this conversation as resolved.
this._changes = observableValue<readonly ISessionFileChange[]>(this, []);
this.changes = this._changes;
}
Expand Down Expand Up @@ -416,6 +424,7 @@ class CopilotCLISession extends Disposable implements ICopilotChatSession {
this._title.set(session.title.get(), undefined);
this._status.set(session.status.get(), undefined);
this._updatedAt.set(session.updatedAt.get(), undefined);
this._changesets.set(session.changesets.get(), undefined);
this._changes.set(session.changes.get(), undefined);
this._description.set(session.description.get(), undefined);
}
Expand Down Expand Up @@ -463,6 +472,7 @@ export class RemoteNewSession extends Disposable implements ICopilotChatSession
private readonly _workspaceData = observableValue<ISessionWorkspace | undefined>(this, undefined);
readonly workspace: IObservable<ISessionWorkspace | undefined> = this._workspaceData;

readonly changesets: IObservable<readonly ISessionChangeset[]> = observableValue<readonly ISessionChangeset[]>(this, []);
readonly changes: IObservable<readonly ISessionFileChange[]> = observableValue<readonly ISessionFileChange[]>(this, []);

private readonly _modelIdObservable = observableValue<string | undefined>(this, undefined);
Expand Down Expand Up @@ -705,6 +715,7 @@ class ClaudeCodeNewSession extends Disposable implements ICopilotChatSession {
private readonly _workspaceData = observableValue<ISessionWorkspace | undefined>(this, undefined);
readonly workspace: IObservable<ISessionWorkspace | undefined> = this._workspaceData;

readonly changesets: IObservable<readonly ISessionChangeset[]> = observableValue<readonly ISessionChangeset[]>(this, []);
readonly changes: IObservable<readonly ISessionFileChange[]> = observableValue<readonly ISessionFileChange[]>(this, []);

private readonly _modelIdObservable = observableValue<string | undefined>(this, undefined);
Expand Down Expand Up @@ -844,6 +855,9 @@ class AgentSessionAdapter implements ICopilotChatSession {
private readonly _status: ReturnType<typeof observableValue<SessionStatus>>;
readonly status: IObservable<SessionStatus>;

private readonly _changesets: ReturnType<typeof observableValue<readonly ISessionChangeset[]>>;
readonly changesets: IObservable<readonly ISessionChangeset[]>;

private readonly _changes: ReturnType<typeof observableValue<readonly ISessionFileChange[]>>;
readonly changes: IObservable<readonly ISessionFileChange[]>;

Expand Down Expand Up @@ -896,6 +910,9 @@ class AgentSessionAdapter implements ICopilotChatSession {
this._status = observableValue(this, toSessionStatus(session.status));
this.status = this._status;

this._changesets = observableValue<readonly ISessionChangeset[]>(this, this._extractChangesets(session));
this.changesets = this._changesets;

this._changes = observableValue<readonly ISessionFileChange[]>(this, this._extractChanges(session));
this.changes = this._changes;

Expand Down Expand Up @@ -1094,6 +1111,10 @@ class AgentSessionAdapter implements ICopilotChatSession {
return undefined;
}

private _extractChangesets(session: IAgentSession): readonly ISessionChangeset[] {
return [];
}

private _extractChanges(session: IAgentSession): readonly ISessionFileChange[] {
if (!session.changes) {
return [];
Expand Down Expand Up @@ -2593,6 +2614,7 @@ export class CopilotChatSessionsProvider extends Disposable implements ISessions
title: primaryChat.title,
updatedAt: chatsObs.map((chats, reader) => this._latestDate(chats, c => c.updatedAt.read(reader))!),
status: chatsObs.map((chats, reader) => this._aggregateStatus(chats, reader)),
changesets: primaryChat.changesets,
changes: primaryChat.changes,
modelId: primaryChat.modelId,
mode: primaryChat.mode,
Expand Down Expand Up @@ -2623,6 +2645,7 @@ export class CopilotChatSessionsProvider extends Disposable implements ISessions
title: chat.title,
updatedAt: chat.updatedAt,
status: chat.status,
changesets: chat.changesets,
changes: chat.changes,
modelId: chat.modelId,
mode: chat.mode,
Expand All @@ -2645,6 +2668,7 @@ export class CopilotChatSessionsProvider extends Disposable implements ISessions
title: chat.title,
updatedAt: chat.updatedAt,
status: chat.status,
changesets: chat.changesets,
changes: chat.changes,
modelId: chat.modelId,
mode: chat.mode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/tes
import { mock } from '../../../../../base/test/common/mock.js';
import { GitHubPullRequestPollingContribution } from '../../browser/github.contribution.js';
import { IGitHubService } from '../../browser/githubService.js';
import { IChat, IGitHubInfo, ISession, ISessionCapabilities, ISessionFileChange, ISessionWorkspace, SessionStatus } from '../../../../services/sessions/common/session.js';
import { IChat, IGitHubInfo, ISession, ISessionCapabilities, ISessionChangeset, ISessionFileChange, ISessionWorkspace, SessionStatus } from '../../../../services/sessions/common/session.js';
import { IActiveSession, ISessionsChangeEvent, ISessionsManagementService } from '../../../../services/sessions/common/sessionsManagement.js';

suite('GitHubPullRequestPollingContribution', () => {
Expand Down Expand Up @@ -152,6 +152,7 @@ class TestSession implements ISession {
readonly title: ReturnType<typeof observableValue<string>>;
readonly updatedAt: ReturnType<typeof observableValue<Date>>;
readonly status: ReturnType<typeof observableValue<SessionStatus>>;
readonly changesets: ReturnType<typeof observableValue<readonly ISessionChangeset[]>>;
readonly changes: ReturnType<typeof observableValue<readonly ISessionFileChange[]>>;
readonly workspace: ReturnType<typeof observableValue<ISessionWorkspace | undefined>>;
readonly modelId: ReturnType<typeof observableValue<string | undefined>>;
Expand All @@ -172,6 +173,7 @@ class TestSession implements ISession {
this.title = observableValue<string>(`test.title.${id}`, id);
this.updatedAt = observableValue<Date>(`test.updatedAt.${id}`, new Date(0));
this.status = observableValue<SessionStatus>(`test.status.${id}`, SessionStatus.Completed);
this.changesets = observableValue<readonly ISessionChangeset[]>(`test.changesets.${id}`, []);
this.changes = observableValue<readonly ISessionFileChange[]>(`test.changes.${id}`, []);
this.workspace = observableValue<ISessionWorkspace | undefined>(`test.workspace.${id}`, undefined);
this.modelId = observableValue<string | undefined>(`test.modelId.${id}`, undefined);
Expand All @@ -188,6 +190,7 @@ class TestSession implements ISession {
title: this.title,
updatedAt: this.updatedAt,
status: this.status,
changesets: this.changesets,
changes: this.changes,
modelId: this.modelId,
mode: this.mode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function createSession(id: string, opts: {
title: observableValue(`title-${id}`, id),
updatedAt: observableValue(`updatedAt-${id}`, updatedAt),
status: observableValue(`status-${id}`, SessionStatus.Completed),
changesets: observableValue(`changesets-${id}`, []),
changes: observableValue(`changes-${id}`, []),
modelId: observableValue(`modelId-${id}`, undefined),
mode: observableValue(`mode-${id}`, undefined),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function createSession(id: string): ISession {
title: observableValue(`title-${id}`, id),
updatedAt: observableValue(`updatedAt-${id}`, new Date()),
status: observableValue(`status-${id}`, SessionStatus.Completed),
changesets: observableValue(`changesets-${id}`, []),
changes: observableValue(`changes-${id}`, []),
modelId: observableValue(`modelId-${id}`, undefined),
mode: observableValue(`mode-${id}`, undefined),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ function makeAgentSession(opts: {
title: observableValue('test.title', 'Test Session'),
updatedAt: observableValue('test.updatedAt', new Date()),
status: observableValue('test.status', 0),
changesets: observableValue('test.changesets', []),
changes: observableValue('test.changes', []),
modelId: observableValue('test.modelId', undefined),
mode: observableValue('test.mode', undefined),
Expand All @@ -83,6 +84,7 @@ function makeAgentSession(opts: {
title: chat.title,
updatedAt: chat.updatedAt,
status: chat.status,
changesets: chat.changesets,
changes: chat.changes,
modelId: chat.modelId,
mode: chat.mode,
Expand Down Expand Up @@ -113,6 +115,7 @@ function makeNonAgentSession(opts: { repository?: URI; worktree?: URI; providerT
title: observableValue('test.title', 'Test Session'),
updatedAt: observableValue('test.updatedAt', new Date()),
status: observableValue('test.status', 0),
changesets: observableValue('test.changesets', []),
changes: observableValue('test.changes', []),
modelId: observableValue('test.modelId', undefined),
mode: observableValue('test.mode', undefined),
Expand All @@ -132,6 +135,7 @@ function makeNonAgentSession(opts: { repository?: URI; worktree?: URI; providerT
title: chat.title,
updatedAt: chat.updatedAt,
status: chat.status,
changesets: chat.changesets,
changes: chat.changes,
modelId: chat.modelId,
mode: chat.mode,
Expand Down
17 changes: 17 additions & 0 deletions src/vs/sessions/services/sessions/common/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,19 @@ export interface IGitHubInfo {

export type ISessionFileChange = IChatSessionFileChange | IChatSessionFileChange2;

export interface ISessionChangeset {
/** Unique identifier for the changeset. */
readonly id: string;
/** Display label for the changeset. */
readonly label: string;
/** Optional description for the changeset. */
readonly description?: string;
/** Whether the changeset is enabled. */
readonly enabled: IObservable<boolean>;
/** File changes associated with this changeset. */
readonly changes: IObservable<readonly ISessionFileChange[]>;
}

/**
* A single chat within a session, produced by the sessions management layer.
*/
Expand All @@ -169,6 +182,8 @@ export interface IChat {
readonly status: IObservable<SessionStatus>;
/** File changes produced by the chat. */
readonly changes: IObservable<readonly ISessionFileChange[]>;
/** Changesets produced by the chat. */
readonly changesets: IObservable<readonly ISessionChangeset[]>;
/** Currently selected model identifier. */
readonly modelId: IObservable<string | undefined>;
/** Currently selected mode identifier and kind. */
Expand Down Expand Up @@ -213,6 +228,8 @@ export interface ISession {
readonly status: IObservable<SessionStatus>;
/** File changes produced by the session. */
readonly changes: IObservable<readonly ISessionFileChange[]>;
/** Changesets produced by the session. */
readonly changesets: IObservable<readonly ISessionChangeset[]>;
/** Currently selected model identifier. */
readonly modelId: IObservable<string | undefined>;
/** Currently selected mode identifier and kind. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const stubChat: IChat = {
title: constObservable('Chat'),
updatedAt: constObservable(new Date()),
status: constObservable(0),
changesets: constObservable([]),
changes: constObservable([]),
modelId: constObservable(undefined),
mode: constObservable(undefined),
Expand All @@ -37,6 +38,7 @@ function stubSession(overrides: Partial<ISession> & Pick<ISession, 'sessionId' |
title: constObservable('Test'),
updatedAt: constObservable(new Date()),
status: constObservable(0),
changesets: constObservable([]),
changes: constObservable([]),
modelId: constObservable(undefined),
mode: constObservable(undefined),
Expand Down
Loading