agentService.ts ×13

Frontier kind: Code frontier

unlabeled · c_5d74820aacff

44 tests · 50524 LOC · 290 files · introduces 0 tests · 142 LOC · 5 files

Introduces — evidence that enters the hierarchy at this concept

Code
31 ranges142 lines · 5 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
5285 ranges50524 lines · 290 files · Browse complete extent
All tests (intent)
44 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

5 files ranked by introduced lines: 142 introduced LOC across 31 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/agentHost/node/agentService.ts 80 introduced LOC · 13 ranges

Open complete file

2419 throw new ProtocolError(AHP_SESSION_NOT_FOUND, `Session not found on backend: ${sessionStr}`);
2420 }
2422 > const defaultChatUri = URI.parse(buildDefaultChatUri(sessionStr));
2423 > let turns: readonly Turn[];
2424 > try {
2425 > turns = await this._getChatMessages(agent, defaultChatUri);
2426 > } catch (err) {
2427 if (err instanceof ProtocolError) {
2428 throw err;
2431 throw new ProtocolError(JSON_RPC_INTERNAL_ERROR, `Failed to restore session ${sessionStr}: ${message}`);
2432 }
2434 > // Check for persisted metadata in the session database
2435 > let title = meta.summary ?? 'Session';
2436 let isRead: boolean | undefined;
2437 let isArchived: boolean | undefined;
2443 const ref = this._sessionDataService.tryOpenDatabase?.(session);
2444 if (ref) {
2445 > try { agentService.ts
2446 > const db = await ref;
2447 > if (db) {
2448 try {
2449 const m = await db.object.getMetadataObject({
2516 }
2517 }
2518 > } catch { agentService.ts
2519 // Best-effort: fall back to agent-provided metadata
2520 }
2521 > } agentService.ts
2522 >
2523 > // Encode isRead/isArchived as status bitmask flags
2524 > let status: SessionStatus = SessionStatus.Idle;
2525 > if (isRead) {
2526 status |= SessionStatus.IsRead;
2527 }
2528 > if (isArchived) { agentService.ts
2529 status |= SessionStatus.IsArchived;
2530 }
2532 > const summary: SessionSummary = {
2533 > resource: sessionStr,
2534 > provider: agent.id,
2535 > title,
2536 > status,
2537 > createdAt: new Date(meta.startTime).toISOString(),
2538 > modifiedAt: new Date(meta.modifiedTime).toISOString(),
2539 ...(meta.project ? { project: { uri: meta.project.uri.toString(), displayName: meta.project.displayName } } : {}),
2540 changes: meta.changes ?? changes,
2547 this._readPersistedChatTitle(session, defaultChatUri),
2548 ]);
2549 > const mergedTurns = await this._interleaveLocalTurns(sessionStr, defaultChatUri.toString(), turns); agentService.ts
2550 > this._stateManager.restoreSession(summary, mergedTurns, { draft: defaultDraft, defaultChatTitle });
2551 >
2552 > const promises: Promise<unknown>[] = [];
2553 > // Eagerly register subagent child sessions discovered in the event log
2554 > // so the client's per-subagent subscriptions resolve from in-memory
2555 > // state (hitting `restoreSubagent skipped existing`) instead of each
2556 > // re-fetching and re-reconstructing the full parent event log. The
2557 > // agent serves these from the same reconstruction it already produced
2558 > // for the parent turns above, so this adds no extra event-log reads.
2559 > promises.push((async () => {
2560 > if (agent.getSubagentSessions) {
2561 try {
2562 const children = await agent.getSubagentSessions(session);
2568 }
2569 }
2570 > })()); agentService.ts
2571 >
2572 > // Restore any additional (non-default) peer chats the provider has
2573 > // persisted for this session, seeding each with its own history and
2574 > // persisted title so they reappear after a process restart.
2575 > promises.push(this._restorePeerChats(agent, session));
2576 >
2577 > // Register the static changeset URIs and reseed them from any
2578 > // persisted file lists in the batched metadata read. The catalogue
2579 > // itself is seeded on `state.changesets` synchronously by the
2580 > // `setSessionChangesets` call above. The coordinator drains any
2581 > // uncommitted refresh deferred by an earlier `addSubscriber` —
2582 > // `addSubscriber`'s 0→1 trigger may have fired for
2583 > // `<session>/changeset/uncommitted` before this restore ran (e.g.
2584 > // active-session autorun subscribing in parallel with the
2585 > // chat-view); now that `summary.workingDirectory` is populated,
2586 > // re-triggering the refresh dispatches to the compute path.
2587 this._changesetCoordinator.onSessionRestored(sessionStr, changesetMetadata ?? {});
2588
2592 this._stateManager.setSessionMeta(sessionStr, meta._meta);
2593 }
2595 > // Resolve the session config so clients (e.g. the running-session
2596 > // auto-approve picker) can render session-mutable properties for
2597 > // sessions that were not created in the current process lifetime.
2598 > // Overlay any values the user previously selected (persisted via
2599 > // `SessionConfigChanged`) on top of the provider's resolved defaults.
2600 > const [restoredConfig, restoredCustomizations] = await Promise.all([
2601 > this._resolveCreatedSessionConfig(agent, {
2602 > workingDirectory: meta.workingDirectory,
2603 > config: persistedConfigValues,
2604 > }),
2605 > agent.getSessionCustomizations
2606 ? agent.getSessionCustomizations(session).catch(err => {
2607 this._logService.error('[AgentService] restoreSession: failed to resolve session customizations', err);
2611 ...promises
2612 ]);
2613 > if (restoredConfig) { agentService.ts
2614 this._stateManager.setSessionConfig(sessionStr, restoredConfig);
2615 }
2616 > // Seed restored session customizations into state so the very first agentService.ts
2617 > // snapshot after selecting an existing session contains effective
2618 > // instructions/agents without waiting for a follow-up republish.
2619 if (restoredCustomizations && restoredCustomizations.length > 0) {
2620 this._stateManager.setSessionCustomizations(sessionStr, restoredCustomizations);
2621 }
2623 > this._logService.info(`[AgentService] Restored session ${sessionStr} with ${turns.length} turns`);
2624 >
2625 > // Refresh the git state for the session.
2626 > void this._gitStateService.refreshSessionGitState(sessionStr, meta.workingDirectory);
2627 >
2628 > // Check for a GitHub pull request associated with the session's branch.
2629 > void this._gitStateService.attachSessionGitHubPullRequest(sessionStr);
2630 }
2631
src/vs/platform/agentHost/node/agentHostChangesetService.ts 33 introduced LOC · 10 ranges

Open complete file

118 * failure with a specific session/changeset slot. Never throws.
119 */
120 > function tryParsePersistedDiffs(raw: string | undefined, sessionUri: string, kind: string, log: ILogService): ISessionFileDiff[] | undefined { agentHostChangesetService.ts
121 > if (!raw) {
122 > return undefined;
123 > }
124 try {
125 return JSON.parse(raw) as ISessionFileDiff[];
128 return undefined;
129 }
131
132 export class AgentHostChangesetService extends Disposable implements IAgentHostChangesetService {
196
197 parsePersistedStaticChangesets(sessionUri: ProtocolURI, metadata: IPersistedChangesetMetadata): IRestoredChangesetDiffs {
198 > const persistedBranch = tryParsePersistedDiffs(metadata.branchRaw, sessionUri, 'branch', this._logService); agentHostChangesetService.ts
199 >
200 > // Legacy `diffs` is the migration fallback for the session-wide
201 > // changeset only — it never carried uncommitted state.
202 > const persistedSession = tryParsePersistedDiffs(metadata.sessionRaw, sessionUri, 'session', this._logService)
203 > ?? tryParsePersistedDiffs(metadata.legacyRaw, sessionUri, 'session (legacy)', this._logService);
204 >
205 > return { branch: persistedBranch, session: persistedSession };
206 > }
207
208 applyPersistedStaticChangesets(sessionUri: ProtocolURI, diffs: IRestoredChangesetDiffs): void {
209 > // `seedIfEmpty`: only reseed persisted diffs when the matching live agentHostChangesetService.ts
210 > // changeset state is absent or empty. Live state (e.g. from a prior
211 > // refresh in this lifetime) is always more authoritative than a
212 > // potentially-stale persisted blob; without this guard a fresh
213 > // `restorePersistedStaticChangesets` call would clobber it.
214 > this._seedIfEmpty(sessionUri, 'branch', diffs.branch);
215 > this._seedIfEmpty(sessionUri, 'session', diffs.session);
216 > }
217
218 restorePersistedStaticChangesets(sessionUri: ProtocolURI, metadata: IPersistedChangesetMetadata): IRestoredChangesetDiffs {
219 > const parsed = this.parsePersistedStaticChangesets(sessionUri, metadata); agentHostChangesetService.ts
220 > this.applyPersistedStaticChangesets(sessionUri, parsed);
221 > return parsed;
222 > }
223
224 persistChangesSummary(sessionUri: ProtocolURI, summary: ChangesSummary): void {
300
301 private _seedIfEmpty(session: ProtocolURI, kind: StaticChangesetKind, diffs: readonly ISessionFileDiff[] | undefined): void {
302 > if (!diffs) { agentHostChangesetService.ts
303 > return;
304 > }
305 const existing = this._stateManager.getChangesetState(staticChangesetUri(session, kind));
306 > if (existing && existing.files.length > 0) { agentHostChangesetService.ts
307 return;
308 }
309 this.restoreStaticChangeset(session, kind, diffs);
311
312 refreshChangesetCatalog(session: ProtocolURI): void {
src/vs/platform/agentHost/node/agentHostGitStateService.ts 14 introduced LOC · 6 ranges

Open complete file

45
46 async attachSessionGitHubPullRequest(sessionKey: string): Promise<void> {
47 > const state = this._stateManager.getSessionState(sessionKey); agentHostGitStateService.ts
48 > if (!state) {
49 return;
50 }
52 > // New session
53 > if (state.lifecycle !== SessionLifecycle.Ready) {
54 return;
55 }
57 > // GitHub state
58 > const gitHubState = readSessionGitHubState(this._stateManager.getSessionState(sessionKey)?._meta);
59 > if (!gitHubState?.owner || !gitHubState?.repo || gitHubState?.pullRequestUrl) {
60 > return;
61 > }
62
63 // Git state
64 const gitState = readSessionGitState(state._meta);
65 > if (!gitState?.branchName || (gitState.branchName === gitState.baseBranchName)) { agentHostGitStateService.ts
66 return;
67 }
80 const pr = await this._octoKitService.findPullRequestByHeadBranch(
81 gitHubState.owner, gitHubState.repo, gitState.branchName, authToken, signal);
82 > if (!pr?.url) { agentHostGitStateService.ts
83 return;
84 }
92 this._logService.warn(`[AgentHostGitStateService][attachSessionGitHubPullRequest] Failed to find pull request for ${sessionKey}`, error);
93 }
95
96 async refreshSessionGitState(sessionKey: string, workingDirectory: URI | undefined): Promise<void> {
src/vs/platform/agentHost/node/agentHostChangesetCoordinator.ts 13 introduced LOC · 1 range

Open complete file

77 */
78 onSessionRestored(sessionStr: string, metadata: IChangesetSessionMetadata): void {
79 > this._changesets.refreshChangesetCatalog(sessionStr); agentHostChangesetCoordinator.ts
80 > this._changesets.registerStaticChangesets(sessionStr);
81 > this._changesets.restorePersistedStaticChangesets(sessionStr, {
82 > branchRaw: metadata[META_CHANGESET_BRANCH],
83 > sessionRaw: metadata[META_CHANGESET_SESSION],
84 > legacyRaw: metadata[META_LEGACY_DIFFS],
85 > });
86 > // `addSubscriber`'s 0→1 trigger may have fired before the session
87 > // state existed; now that `summary.workingDirectory` is populated,
88 > // drain the deferred refresh.
89 > this._changesets.onWorkingDirectoryAvailable(sessionStr);
90 > this._changesetFileMonitor.onSessionRestored(sessionStr);
91 > }
92
93 /**
src/vs/platform/agentHost/node/agentHostChangesetFileMonitorCoordinator.ts 2 introduced LOC · 1 range

Open complete file