Skip to content

Commit ebfbb71

Browse files
authored
Agents - scaffold Changesets model (#313577)
* Agents - scaffold Changesets model * Pull request feedback
1 parent a0afc4c commit ebfbb71

10 files changed

Lines changed: 64 additions & 3 deletions

File tree

src/vs/sessions/contrib/agentHost/browser/baseAgentHostSessionsProvider.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { diffsEqual, diffsToChanges, mapProtocolStatus } from './agentHostDiffs.
3232
import { buildMutableConfigSchema, IAgentHostSessionsProvider, resolvedConfigsEqual } from '../../../common/agentHostSessionsProvider.js';
3333
import { agentHostSessionWorkspaceKey } from '../../../common/agentHostSessionWorkspace.js';
3434
import { isSessionConfigComplete } from '../../../common/sessionConfig.js';
35-
import { IChat, IGitHubInfo, ISession, ISessionType, ISessionWorkspace, ISessionWorkspaceBrowseAction, SessionStatus, toSessionId } from '../../../services/sessions/common/session.js';
35+
import { IChat, IGitHubInfo, ISession, ISessionChangeset, ISessionType, ISessionWorkspace, ISessionWorkspaceBrowseAction, SessionStatus, toSessionId } from '../../../services/sessions/common/session.js';
3636
import { ISendRequestOptions, ISessionChangeEvent } from '../../../services/sessions/common/sessionsProvider.js';
3737

3838
// ============================================================================
@@ -74,6 +74,7 @@ export class AgentHostSessionAdapter implements ISession {
7474
readonly updatedAt: ISettableObservable<Date>;
7575
readonly status: ISettableObservable<SessionStatus>;
7676
readonly changes = observableValue<readonly (IChatSessionFileChange | IChatSessionFileChange2)[]>('changes', []);
77+
readonly changesets = observableValue<readonly ISessionChangeset[]>('changesets', []);
7778
readonly modelId: ISettableObservable<string | undefined>;
7879
modelSelection: ModelSelection | undefined;
7980
readonly mode = observableValue<{ readonly id: string; readonly kind: string } | undefined>('mode', undefined);
@@ -162,6 +163,7 @@ export class AgentHostSessionAdapter implements ISession {
162163
updatedAt: this.updatedAt,
163164
status: this.status,
164165
changes: this.changes,
166+
changesets: this.changesets,
165167
modelId: this.modelId,
166168
mode: this.mode,
167169
isArchived: this.isArchived,
@@ -381,6 +383,7 @@ class NewSession extends Disposable {
381383
this._status = observableValue<SessionStatus>(this, SessionStatus.Untitled);
382384
const title = observableValue<string>(this, '');
383385
const updatedAt = observableValue(this, new Date());
386+
const changesets = observableValue<readonly ISessionChangeset[]>(this, []);
384387
const changes = observableValue<readonly (IChatSessionFileChange | IChatSessionFileChange2)[]>(this, []);
385388
this._modelId = observableValue<string | undefined>(this, undefined);
386389
const mode = observableValue<{ readonly id: string; readonly kind: string } | undefined>(this, undefined);
@@ -394,6 +397,7 @@ class NewSession extends Disposable {
394397
const mainChat: IChat = {
395398
resource, createdAt, title, updatedAt,
396399
status: this._status,
400+
changesets,
397401
changes,
398402
modelId: this._modelId,
399403
mode, isArchived, isRead, description, lastTurnEnd,
@@ -411,6 +415,7 @@ class NewSession extends Disposable {
411415
title,
412416
updatedAt,
413417
status: this._status,
418+
changesets,
414419
changes,
415420
modelId: this._modelId,
416421
mode,

src/vs/sessions/contrib/agentHost/test/browser/agentHostSkillButtons.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ function makeActiveSession(providerId: string): IActiveSession {
3131
title: observableValue('t', 'Test'),
3232
updatedAt: observableValue('u', new Date()),
3333
status: observableValue('s', 0),
34+
changesets: observableValue('cs', []),
3435
changes: observableValue('c', []),
3536
modelId: observableValue('m', undefined),
3637
mode: observableValue('mo', undefined),
@@ -50,6 +51,7 @@ function makeActiveSession(providerId: string): IActiveSession {
5051
title: chat.title,
5152
updatedAt: chat.updatedAt,
5253
status: chat.status,
54+
changesets: chat.changesets,
5355
changes: chat.changes,
5456
modelId: chat.modelId,
5557
mode: chat.mode,

src/vs/sessions/contrib/chat/test/browser/sessionsConfigurationService.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ function makeSession(opts: { repository?: URI; worktree?: URI } = {}): ISession
4141
title: observableValue('title', 'session'),
4242
updatedAt: observableValue('updatedAt', new Date()),
4343
status: observableValue('status', SessionStatus.Untitled),
44+
changesets: observableValue('changesets', []),
4445
changes: observableValue('changes', []),
4546
modelId: observableValue('modelId', undefined),
4647
mode: observableValue('mode', undefined),
@@ -60,6 +61,7 @@ function makeSession(opts: { repository?: URI; worktree?: URI } = {}): ISession
6061
title: chat.title,
6162
updatedAt: chat.updatedAt,
6263
status: chat.status,
64+
changesets: chat.changesets,
6365
changes: chat.changes,
6466
modelId: chat.modelId,
6567
mode: chat.mode,

src/vs/sessions/contrib/copilotChatSessions/browser/copilotChatSessionsProvider.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { AgentSessionProviders, AgentSessionTarget } from '../../../../workbench
2323
import { IChatService, IChatSendRequestOptions } from '../../../../workbench/contrib/chat/common/chatService/chatService.js';
2424
import { IChatResponseModel } from '../../../../workbench/contrib/chat/common/model/chatModel.js';
2525
import { ChatSessionStatus, IChatSessionsService, IChatSessionProviderOptionGroup, IChatSessionProviderOptionItem, SessionType } from '../../../../workbench/contrib/chat/common/chatSessionsService.js';
26-
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';
26+
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';
2727
import { ChatAgentLocation, ChatConfiguration, ChatModeKind, ChatPermissionLevel, isChatPermissionLevel } from '../../../../workbench/contrib/chat/common/constants.js';
2828
import { basename, dirname, isEqual } from '../../../../base/common/resources.js';
2929
import { ISendRequestOptions, ISessionChangeEvent, ISessionsProvider } from '../../../services/sessions/common/sessionsProvider.js';
@@ -71,6 +71,8 @@ export interface ICopilotChatSession {
7171
readonly updatedAt: IObservable<Date>;
7272
/** Current session status. */
7373
readonly status: IObservable<SessionStatus>;
74+
/** File changesets produced by the session. */
75+
readonly changesets: IObservable<readonly ISessionChangeset[]>;
7476
/** File changes produced by the session. */
7577
readonly changes: IObservable<readonly ISessionFileChange[]>;
7678
/** Currently selected model identifier. */
@@ -180,6 +182,9 @@ class CopilotCLISession extends Disposable implements ICopilotChatSession {
180182
private readonly _loading = observableValue(this, true);
181183
readonly loading: IObservable<boolean> = this._loading;
182184

185+
private readonly _changesets: ReturnType<typeof observableValue<readonly ISessionChangeset[]>>;
186+
readonly changesets: IObservable<readonly ISessionChangeset[]>;
187+
183188
private readonly _changes: ReturnType<typeof observableValue<readonly ISessionFileChange[]>>;
184189
readonly changes: IObservable<readonly ISessionFileChange[]>;
185190

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

267+
this._changesets = observableValue<readonly ISessionChangeset[]>(this, []);
268+
this.changesets = this._changesets;
269+
262270
this._changes = observableValue<readonly ISessionFileChange[]>(this, []);
263271
this.changes = this._changes;
264272
}
@@ -416,6 +424,7 @@ class CopilotCLISession extends Disposable implements ICopilotChatSession {
416424
this._title.set(session.title.get(), undefined);
417425
this._status.set(session.status.get(), undefined);
418426
this._updatedAt.set(session.updatedAt.get(), undefined);
427+
this._changesets.set(session.changesets.get(), undefined);
419428
this._changes.set(session.changes.get(), undefined);
420429
this._description.set(session.description.get(), undefined);
421430
}
@@ -463,6 +472,7 @@ export class RemoteNewSession extends Disposable implements ICopilotChatSession
463472
private readonly _workspaceData = observableValue<ISessionWorkspace | undefined>(this, undefined);
464473
readonly workspace: IObservable<ISessionWorkspace | undefined> = this._workspaceData;
465474

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

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

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

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

858+
private readonly _changesets: ReturnType<typeof observableValue<readonly ISessionChangeset[]>>;
859+
readonly changesets: IObservable<readonly ISessionChangeset[]>;
860+
847861
private readonly _changes: ReturnType<typeof observableValue<readonly ISessionFileChange[]>>;
848862
readonly changes: IObservable<readonly ISessionFileChange[]>;
849863

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

913+
this._changesets = observableValue<readonly ISessionChangeset[]>(this, this._extractChangesets(session));
914+
this.changesets = this._changesets;
915+
899916
this._changes = observableValue<readonly ISessionFileChange[]>(this, this._extractChanges(session));
900917
this.changes = this._changes;
901918

@@ -1094,6 +1111,10 @@ class AgentSessionAdapter implements ICopilotChatSession {
10941111
return undefined;
10951112
}
10961113

1114+
private _extractChangesets(session: IAgentSession): readonly ISessionChangeset[] {
1115+
return [];
1116+
}
1117+
10971118
private _extractChanges(session: IAgentSession): readonly ISessionFileChange[] {
10981119
if (!session.changes) {
10991120
return [];
@@ -2593,6 +2614,7 @@ export class CopilotChatSessionsProvider extends Disposable implements ISessions
25932614
title: primaryChat.title,
25942615
updatedAt: chatsObs.map((chats, reader) => this._latestDate(chats, c => c.updatedAt.read(reader))!),
25952616
status: chatsObs.map((chats, reader) => this._aggregateStatus(chats, reader)),
2617+
changesets: primaryChat.changesets,
25962618
changes: primaryChat.changes,
25972619
modelId: primaryChat.modelId,
25982620
mode: primaryChat.mode,
@@ -2623,6 +2645,7 @@ export class CopilotChatSessionsProvider extends Disposable implements ISessions
26232645
title: chat.title,
26242646
updatedAt: chat.updatedAt,
26252647
status: chat.status,
2648+
changesets: chat.changesets,
26262649
changes: chat.changes,
26272650
modelId: chat.modelId,
26282651
mode: chat.mode,
@@ -2645,6 +2668,7 @@ export class CopilotChatSessionsProvider extends Disposable implements ISessions
26452668
title: chat.title,
26462669
updatedAt: chat.updatedAt,
26472670
status: chat.status,
2671+
changesets: chat.changesets,
26482672
changes: chat.changes,
26492673
modelId: chat.modelId,
26502674
mode: chat.mode,

src/vs/sessions/contrib/github/test/browser/githubContribution.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/tes
1515
import { mock } from '../../../../../base/test/common/mock.js';
1616
import { GitHubPullRequestPollingContribution } from '../../browser/github.contribution.js';
1717
import { IGitHubService } from '../../browser/githubService.js';
18-
import { IChat, IGitHubInfo, ISession, ISessionCapabilities, ISessionFileChange, ISessionWorkspace, SessionStatus } from '../../../../services/sessions/common/session.js';
18+
import { IChat, IGitHubInfo, ISession, ISessionCapabilities, ISessionChangeset, ISessionFileChange, ISessionWorkspace, SessionStatus } from '../../../../services/sessions/common/session.js';
1919
import { IActiveSession, ISessionsChangeEvent, ISessionsManagementService } from '../../../../services/sessions/common/sessionsManagement.js';
2020

2121
suite('GitHubPullRequestPollingContribution', () => {
@@ -152,6 +152,7 @@ class TestSession implements ISession {
152152
readonly title: ReturnType<typeof observableValue<string>>;
153153
readonly updatedAt: ReturnType<typeof observableValue<Date>>;
154154
readonly status: ReturnType<typeof observableValue<SessionStatus>>;
155+
readonly changesets: ReturnType<typeof observableValue<readonly ISessionChangeset[]>>;
155156
readonly changes: ReturnType<typeof observableValue<readonly ISessionFileChange[]>>;
156157
readonly workspace: ReturnType<typeof observableValue<ISessionWorkspace | undefined>>;
157158
readonly modelId: ReturnType<typeof observableValue<string | undefined>>;
@@ -172,6 +173,7 @@ class TestSession implements ISession {
172173
this.title = observableValue<string>(`test.title.${id}`, id);
173174
this.updatedAt = observableValue<Date>(`test.updatedAt.${id}`, new Date(0));
174175
this.status = observableValue<SessionStatus>(`test.status.${id}`, SessionStatus.Completed);
176+
this.changesets = observableValue<readonly ISessionChangeset[]>(`test.changesets.${id}`, []);
175177
this.changes = observableValue<readonly ISessionFileChange[]>(`test.changes.${id}`, []);
176178
this.workspace = observableValue<ISessionWorkspace | undefined>(`test.workspace.${id}`, undefined);
177179
this.modelId = observableValue<string | undefined>(`test.modelId.${id}`, undefined);
@@ -188,6 +190,7 @@ class TestSession implements ISession {
188190
title: this.title,
189191
updatedAt: this.updatedAt,
190192
status: this.status,
193+
changesets: this.changesets,
191194
changes: this.changes,
192195
modelId: this.modelId,
193196
mode: this.mode,

src/vs/sessions/contrib/sessions/test/browser/sessionsList.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ function createSession(id: string, opts: {
3535
title: observableValue(`title-${id}`, id),
3636
updatedAt: observableValue(`updatedAt-${id}`, updatedAt),
3737
status: observableValue(`status-${id}`, SessionStatus.Completed),
38+
changesets: observableValue(`changesets-${id}`, []),
3839
changes: observableValue(`changes-${id}`, []),
3940
modelId: observableValue(`modelId-${id}`, undefined),
4041
mode: observableValue(`mode-${id}`, undefined),

src/vs/sessions/contrib/sessions/test/browser/sessionsListModelService.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ function createSession(id: string): ISession {
2828
title: observableValue(`title-${id}`, id),
2929
updatedAt: observableValue(`updatedAt-${id}`, new Date()),
3030
status: observableValue(`status-${id}`, SessionStatus.Completed),
31+
changesets: observableValue(`changesets-${id}`, []),
3132
changes: observableValue(`changes-${id}`, []),
3233
modelId: observableValue(`modelId-${id}`, undefined),
3334
mode: observableValue(`mode-${id}`, undefined),

src/vs/sessions/contrib/terminal/test/browser/sessionsTerminalContribution.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ function makeAgentSession(opts: {
6464
title: observableValue('test.title', 'Test Session'),
6565
updatedAt: observableValue('test.updatedAt', new Date()),
6666
status: observableValue('test.status', 0),
67+
changesets: observableValue('test.changesets', []),
6768
changes: observableValue('test.changes', []),
6869
modelId: observableValue('test.modelId', undefined),
6970
mode: observableValue('test.mode', undefined),
@@ -83,6 +84,7 @@ function makeAgentSession(opts: {
8384
title: chat.title,
8485
updatedAt: chat.updatedAt,
8586
status: chat.status,
87+
changesets: chat.changesets,
8688
changes: chat.changes,
8789
modelId: chat.modelId,
8890
mode: chat.mode,
@@ -113,6 +115,7 @@ function makeNonAgentSession(opts: { repository?: URI; worktree?: URI; providerT
113115
title: observableValue('test.title', 'Test Session'),
114116
updatedAt: observableValue('test.updatedAt', new Date()),
115117
status: observableValue('test.status', 0),
118+
changesets: observableValue('test.changesets', []),
116119
changes: observableValue('test.changes', []),
117120
modelId: observableValue('test.modelId', undefined),
118121
mode: observableValue('test.mode', undefined),
@@ -132,6 +135,7 @@ function makeNonAgentSession(opts: { repository?: URI; worktree?: URI; providerT
132135
title: chat.title,
133136
updatedAt: chat.updatedAt,
134137
status: chat.status,
138+
changesets: chat.changesets,
135139
changes: chat.changes,
136140
modelId: chat.modelId,
137141
mode: chat.mode,

src/vs/sessions/services/sessions/common/session.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,19 @@ export interface IGitHubInfo {
150150

151151
export type ISessionFileChange = IChatSessionFileChange | IChatSessionFileChange2;
152152

153+
export interface ISessionChangeset {
154+
/** Unique identifier for the changeset. */
155+
readonly id: string;
156+
/** Display label for the changeset. */
157+
readonly label: string;
158+
/** Optional description for the changeset. */
159+
readonly description?: string;
160+
/** Whether the changeset is enabled. */
161+
readonly enabled: IObservable<boolean>;
162+
/** File changes associated with this changeset. */
163+
readonly changes: IObservable<readonly ISessionFileChange[]>;
164+
}
165+
153166
/**
154167
* A single chat within a session, produced by the sessions management layer.
155168
*/
@@ -169,6 +182,8 @@ export interface IChat {
169182
readonly status: IObservable<SessionStatus>;
170183
/** File changes produced by the chat. */
171184
readonly changes: IObservable<readonly ISessionFileChange[]>;
185+
/** Changesets produced by the chat. */
186+
readonly changesets: IObservable<readonly ISessionChangeset[]>;
172187
/** Currently selected model identifier. */
173188
readonly modelId: IObservable<string | undefined>;
174189
/** Currently selected mode identifier and kind. */
@@ -213,6 +228,8 @@ export interface ISession {
213228
readonly status: IObservable<SessionStatus>;
214229
/** File changes produced by the session. */
215230
readonly changes: IObservable<readonly ISessionFileChange[]>;
231+
/** Changesets produced by the session. */
232+
readonly changesets: IObservable<readonly ISessionChangeset[]>;
216233
/** Currently selected model identifier. */
217234
readonly modelId: IObservable<string | undefined>;
218235
/** Currently selected mode identifier and kind. */

src/vs/sessions/services/sessions/test/browser/sessionsManagementService.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const stubChat: IChat = {
1818
title: constObservable('Chat'),
1919
updatedAt: constObservable(new Date()),
2020
status: constObservable(0),
21+
changesets: constObservable([]),
2122
changes: constObservable([]),
2223
modelId: constObservable(undefined),
2324
mode: constObservable(undefined),
@@ -37,6 +38,7 @@ function stubSession(overrides: Partial<ISession> & Pick<ISession, 'sessionId' |
3738
title: constObservable('Test'),
3839
updatedAt: constObservable(new Date()),
3940
status: constObservable(0),
41+
changesets: constObservable([]),
4042
changes: constObservable([]),
4143
modelId: constObservable(undefined),
4244
mode: constObservable(undefined),

0 commit comments

Comments
 (0)