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 { URI } from '../../../base/common/uri.js';
7
>
import { createDecorator } from '../../instantiation/common/instantiation.js';
8
>
9
>
export const IAgentHostCheckpointService = createDecorator<IAgentHostCheckpointService>('agentHostCheckpointService');
10
>
11
>
/**
12
>
* `session_metadata` key under which the per-session baseline (turn/0)
13
>
* checkpoint ref is stored.
14
>
*/
15
>
export const META_CHECKPOINT_BASE_REF = 'checkpoint.baseRef';
16
>
17
>
/**
18
>
* Returns the canonical name for a per-turn checkpoint ref.
19
>
* Distinct from the chat extension's `refs/sessions/...` so the two can
20
>
* coexist safely in the same repository.
21
>
*/
22
>
export function buildCheckpointRefName(sanitizedSessionId: string, turnNumber: number): string {
23
return `refs/agents/${sanitizedSessionId}/checkpoints/turn/${turnNumber}`;
24
}
26
>
/**
27
>
* Captures per-turn git **checkpoint refs** for Agent Host sessions so
28
>
* end-of-turn diffs reflect the entire working-tree delta (including
29
>
* terminal-tool edits that are invisible to the FileEditTracker pipeline).
30
>
*
31
>
* Each checkpoint is a parentless or parent-chained commit (commit-tree)
32
>
* pointing at a tree captured via the temp-index trick, anchored under
33
>
* `refs/agents/<sid>/checkpoints/turn/<N>`. The session-private ref
34
>
* namespace means the commits stay reachable for the lifetime of the
35
>
* session and survive process restarts (refs live on disk in
36
>
* `<repo>/.git/refs/`), while never appearing as branches/tags to the
37
>
* user. Cleanup is driven by `ISessionDataService.onWillDeleteSessionData`
38
>
* — the service deletes every ref it created for the destroyed session
39
>
* before the data directory is removed.
40
>
*/
41
>
export interface IAgentHostCheckpointService {
42
>
readonly _serviceBrand: undefined;
43
>
44
>
/**
45
>
* Captures the session's baseline (turn/0) checkpoint. Idempotent: if
46
>
* a baseline already exists for the session, returns the existing ref.
47
>
* Returns `undefined` when the working directory is not a git work tree
48
>
* (folder-isolation against a non-git folder) or when checkpoint
49
>
* capture fails.
50
>
*
51
>
* Called once per session, immediately after the session's working
52
>
* directory has been resolved and any worktree metadata has been
53
>
* persisted (e.g. `CopilotAgent._materializeProvisional`).
54
>
*/
55
>
captureBaseline(sessionUri: URI, workingDirectory: URI | undefined): Promise<string | undefined>;
56
>
57
>
/**
58
>
* Captures an end-of-turn checkpoint, chained to the previous turn's
59
>
* checkpoint (or the baseline for turn 1). Persists the ref against
60
>
* the turn via `ISessionDatabase.setTurnCheckpointRef`. Returns
61
>
* `undefined` when the session is not git-backed, the baseline is
62
>
* missing, or capture fails.
63
>
*
64
>
* If the captured tree OID matches the parent's tree OID (no-op turn)
65
>
* the parent ref is recorded against the turn rather than creating a
66
>
* redundant commit / new ref.
67
>
*
68
>
* Called from `AgentSideEffects` when a `ChatTurnComplete` action
69
>
* fires, BEFORE the changeset service's `onTurnComplete` hook so the
70
>
* per-turn changeset compute can pick up the new refs.
71
>
*/
72
>
captureTurnCheckpoint(sessionUri: URI, turnId: string): Promise<string | undefined>;
73
>
74
>
/**
75
>
* Returns the `{ parent, current }` checkpoint refs for a turn, or
76
>
* `undefined` when either is missing. Used by the changeset service
77
>
* to decide whether to take the git-diff fast path for per-turn diffs.
78
>
*/
79
>
getTurnCheckpointPair(sessionUri: URI, turnId: string): Promise<{ parent: string; current: string } | undefined>;
80
>
81
>
/**
82
>
* Returns the session's baseline checkpoint ref, or `undefined` when
83
>
* the baseline was never captured (non-git-backed session, or capture
84
>
* failed). Used by the changeset service to resolve compare-turns
85
>
* URIs whose `originalTurnId` is the `BASELINE_TURN_ID` sentinel.
86
>
*/
87
>
getBaselineCheckpointRef(sessionUri: URI): Promise<string | undefined>;
88
>
89
>
/**
90
>
* Deletes every checkpoint ref this service created for the session
91
>
* (baseline + all turn refs), reading the precise list from the
92
>
* session database. Tolerates missing refs.
93
>
*
94
>
* Called from a subscriber to `ISessionDataService.onWillDeleteSessionData`
95
>
* before the session's data directory is removed.
96
>
*/
97
>
disposeSessionData(sessionUri: URI): Promise<void>;
98
>
}
99
>
100
>
/**
101
>
* A no-op implementation of {@link IAgentHostCheckpointService} used as a
102
>
* fallback in test fixtures that don't exercise checkpoint capture, and
103
>
* as the default value for the optional `_checkpointService` parameter
104
>
* on `AgentService` so existing test callsites keep compiling without
105
>
* forced fixture updates.
106
>
*/
107
>
export const NULL_CHECKPOINT_SERVICE: IAgentHostCheckpointService = {
108
>
_serviceBrand: undefined,
109
>
captureBaseline: async () => undefined,
110
>
captureTurnCheckpoint: async () => undefined,
111
>
getTurnCheckpointPair: async () => undefined,
112
>
getBaselineCheckpointRef: async () => undefined,
113
>
disposeSessionData: async () => { },
114
>
};