agentHostLocalTurns.ts ×12

Frontier kind: Code frontier

unlabeled · c_5bb93883c6e4

508 tests · 14360 LOC · 53 files · introduces 0 tests · 78 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
12 ranges78 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1380 ranges14360 lines · 53 files · Browse complete extent
All tests (intent)
508 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.

1 file ranked by introduced lines: 78 introduced LOC across 12 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/agentHost/node/agentHostLocalTurns.ts 78 introduced LOC · 12 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- agentHostLocalTurns.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import type { IReference } from '../../../base/common/lifecycle.js';
7 > import { URI } from '../../../base/common/uri.js';
8 > import { ILogService } from '../../log/common/log.js';
9 > import type { ILocalTurnRecord, ISessionDatabase, ISessionDataService } from '../common/sessionDataService.js';
10 > import type { Turn } from '../common/state/sessionState.js';
11 >
12 > /**
13 > * Tracks host-injected ("local") turns — completed protocol turns the agent SDK
14 > * never saw, such as the `/rename` acknowledgement or a `!command` terminal run.
15 > *
16 > * These turns exist only in the agent host: they are never forwarded to the
17 > * agent SDK, so they are absent from the SDK transcript that
18 > * {@link AgentService} replays on restore. This registry persists them (so they
19 > * survive reload) and remembers, for each, the id of the preceding concrete
20 > * (SDK-backed) turn — the *anchor* — so that fork/truncate operations targeting
21 > * a local turn can be redirected to the concrete SDK message before it.
22 > *
23 > * Everything is scoped to a **chat** (its channel URI): a session's default
24 > * chat and each of its peer chats are handled identically. Persistence lives in
25 > * the owning session's database (one per session, shared across its chats),
26 > * discriminated by {@link ILocalTurnRecord.chatUri}.
27 > */
28 > export class AgentHostLocalTurns {
29 >
30 > /** chat URI → (localTurnId → { anchorTurnId, seq }). */
31 > private readonly _byChat = new Map<string, Map<string, { readonly anchorTurnId: string | undefined; readonly seq: number }>>();
32 > /** session URI → highest `seq` assigned so far (seq is session-global for stable ordering). */
33 > private readonly _seqBySession = new Map<string, number>();
34 >
35 > constructor(
36 private readonly _sessionDataService: ISessionDataService,
37 private readonly _logService: ILogService,
38 ) { }
40 > /** Whether `turnId` is a known host-injected local turn in `chat`. */
41 > isLocal(chat: string, turnId: string): boolean {
42 return this._byChat.get(chat)?.has(turnId) ?? false;
43 }
45 > /** All known local turn ids for `chat`. */
46 > getLocalTurnIds(chat: string): string[] {
47 const map = this._byChat.get(chat);
48 return map ? [...map.keys()] : [];
49 }
51 > /**
52 > * Resolves `turnId` to the concrete (SDK-backed) turn a fork/truncate should
53 > * operate on within `chat`. For a local turn this is its anchor (the
54 > * preceding real turn, or `undefined` when it precedes any real turn); for a
55 > * concrete turn it is the turn itself.
56 > */
57 > resolveConcreteTurnId(chat: string, turnId: string): string | undefined {
58 const entry = this._byChat.get(chat)?.get(turnId);
59 return entry ? entry.anchorTurnId : turnId;
60 }
62 > /**
63 > * Persist a local turn and remember it in memory. `anchorTurnId` is the id
64 > * of the preceding concrete turn in `chat` (or `undefined` when there is
65 > * none). `session` identifies the database to persist into.
66 > */
67 > record(session: string, chat: string, turn: Turn, anchorTurnId: string | undefined): void {
68 const seq = (this._seqBySession.get(session) ?? 0) + 1;
69 this._noteInMemory(session, chat, turn.id, anchorTurnId, seq);
80 }).finally(() => ref.dispose());
81 }
83 > /**
84 > * Loads persisted local turns for `session`, populating the in-memory index
85 > * (keyed by each record's chat), and returns the records for `chat` in
86 > * `seq` order so the caller can interleave them into that chat's SDK-derived
87 > * turns during restore.
88 > */
89 > async loadForChat(session: string, chat: string): Promise<ILocalTurnRecord[]> {
90 const records = await this._load(session);
91 return records.filter(r => r.chatUri === chat);
92 }
94 > /** Note a local turn in memory only (used by fork seeding). */
95 > noteInMemory(session: string, chat: string, turnId: string, anchorTurnId: string | undefined, seq: number): void {
96 this._noteInMemory(session, chat, turnId, anchorTurnId, seq);
97 }
99 > /** Delete the given local turns from memory and the session database. */
100 > deleteLocals(session: string, turnIds: readonly string[]): void {
101 if (turnIds.length === 0) {
102 return;
119 }).finally(() => ref.dispose());
120 }
122 > /** Drop all in-memory state for a chat. */
123 > forgetChat(chat: string): void {
124 this._byChat.delete(chat);
125 }
127 > private async _load(session: string): Promise<ILocalTurnRecord[]> {
128 const ref = this._sessionDataService.tryOpenDatabase?.(URI.parse(session));
129 if (!ref) {
149 }
150 }
152 > private _noteInMemory(session: string, chat: string, turnId: string, anchorTurnId: string | undefined, seq: number): void {
153 let map = this._byChat.get(chat);
154 if (!map) {
159 this._seqBySession.set(session, Math.max(this._seqBySession.get(session) ?? 0, seq));
160 }