@posthog/agent 2.3.398 → 2.3.403
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -14
- package/dist/agent.js +1 -7
- package/dist/agent.js.map +1 -1
- package/dist/handoff-checkpoint.d.ts +0 -2
- package/dist/handoff-checkpoint.js +38 -53
- package/dist/handoff-checkpoint.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/posthog-api.js +1 -5
- package/dist/posthog-api.js.map +1 -1
- package/dist/resume.d.ts +5 -6
- package/dist/resume.js +2 -41
- package/dist/resume.js.map +1 -1
- package/dist/server/agent-server.d.ts +1 -2
- package/dist/server/agent-server.js +103 -768
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +101 -766
- package/dist/server/bin.cjs.map +1 -1
- package/dist/types.d.ts +2 -13
- package/dist/types.js.map +1 -1
- package/package.json +3 -7
- package/src/acp-extensions.ts +0 -3
- package/src/handoff-checkpoint.test.ts +3 -17
- package/src/handoff-checkpoint.ts +15 -45
- package/src/resume.ts +5 -11
- package/src/sagas/resume-saga.test.ts +27 -77
- package/src/sagas/resume-saga.ts +3 -44
- package/src/sagas/test-fixtures.ts +17 -76
- package/src/server/agent-server.ts +22 -103
- package/src/test/fixtures/api.ts +2 -15
- package/src/types.ts +0 -16
- package/dist/tree-tracker.d.ts +0 -68
- package/dist/tree-tracker.js +0 -6431
- package/dist/tree-tracker.js.map +0 -1
- package/src/sagas/apply-snapshot-saga.test.ts +0 -690
- package/src/sagas/apply-snapshot-saga.ts +0 -100
- package/src/sagas/capture-tree-saga.test.ts +0 -892
- package/src/sagas/capture-tree-saga.ts +0 -150
- package/src/tree-tracker.ts +0 -173
|
@@ -5,11 +5,10 @@ import { tmpdir } from "node:os";
|
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import type { SagaLogger } from "@posthog/shared";
|
|
8
|
-
import * as tar from "tar";
|
|
9
8
|
import { vi } from "vitest";
|
|
10
9
|
import { POSTHOG_NOTIFICATIONS } from "../acp-extensions";
|
|
11
10
|
import type { PostHogAPIClient } from "../posthog-api";
|
|
12
|
-
import type { StoredNotification, TaskRun
|
|
11
|
+
import type { GitCheckpointEvent, StoredNotification, TaskRun } from "../types";
|
|
13
12
|
|
|
14
13
|
const execFileAsync = promisify(execFile);
|
|
15
14
|
|
|
@@ -128,7 +127,7 @@ export function createMockApiClient(
|
|
|
128
127
|
return {
|
|
129
128
|
uploadTaskArtifacts: vi
|
|
130
129
|
.fn()
|
|
131
|
-
.mockResolvedValue([{ storage_path: "gs://bucket/
|
|
130
|
+
.mockResolvedValue([{ storage_path: "gs://bucket/handoff/test.pack" }]),
|
|
132
131
|
downloadArtifact: vi.fn(),
|
|
133
132
|
getTaskRun: vi.fn(),
|
|
134
133
|
fetchTaskRunLogs: vi.fn(),
|
|
@@ -136,69 +135,6 @@ export function createMockApiClient(
|
|
|
136
135
|
} as unknown as PostHogAPIClient;
|
|
137
136
|
}
|
|
138
137
|
|
|
139
|
-
export interface ArchiveFile {
|
|
140
|
-
path: string;
|
|
141
|
-
content: string;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export interface ArchiveSymlink {
|
|
145
|
-
path: string;
|
|
146
|
-
target: string;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export async function createArchiveBuffer(
|
|
150
|
-
files: Array<ArchiveFile>,
|
|
151
|
-
symlinks: Array<ArchiveSymlink> = [],
|
|
152
|
-
): Promise<Buffer> {
|
|
153
|
-
const { symlink } = await import("node:fs/promises");
|
|
154
|
-
const tmpDir = join(
|
|
155
|
-
tmpdir(),
|
|
156
|
-
`archive-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
157
|
-
);
|
|
158
|
-
await mkdir(tmpDir, { recursive: true });
|
|
159
|
-
|
|
160
|
-
const filesToArchive =
|
|
161
|
-
files.length > 0 ? files : [{ path: ".empty", content: "" }];
|
|
162
|
-
|
|
163
|
-
for (const file of filesToArchive) {
|
|
164
|
-
const fullPath = join(tmpDir, file.path);
|
|
165
|
-
await mkdir(join(fullPath, ".."), { recursive: true });
|
|
166
|
-
await writeFile(fullPath, file.content);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const symlinkPaths: string[] = [];
|
|
170
|
-
for (const link of symlinks) {
|
|
171
|
-
const fullPath = join(tmpDir, link.path);
|
|
172
|
-
await mkdir(join(fullPath, ".."), { recursive: true });
|
|
173
|
-
await symlink(link.target, fullPath);
|
|
174
|
-
symlinkPaths.push(link.path);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const archivePath = join(tmpDir, "archive.tar.gz");
|
|
178
|
-
await tar.create({ gzip: true, file: archivePath, cwd: tmpDir }, [
|
|
179
|
-
...filesToArchive.map((f) => f.path),
|
|
180
|
-
...symlinkPaths,
|
|
181
|
-
]);
|
|
182
|
-
|
|
183
|
-
const content = await readFile(archivePath);
|
|
184
|
-
await rm(tmpDir, { recursive: true, force: true });
|
|
185
|
-
|
|
186
|
-
return Buffer.from(content.toString("base64"));
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export function createSnapshot(
|
|
190
|
-
overrides: Partial<TreeSnapshot> = {},
|
|
191
|
-
): TreeSnapshot {
|
|
192
|
-
return {
|
|
193
|
-
treeHash: "test-tree-hash",
|
|
194
|
-
baseCommit: null,
|
|
195
|
-
archiveUrl: "gs://bucket/trees/test.tar.gz",
|
|
196
|
-
changes: [],
|
|
197
|
-
timestamp: new Date().toISOString(),
|
|
198
|
-
...overrides,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
138
|
export function createTaskRun(overrides: Partial<TaskRun> = {}): TaskRun {
|
|
203
139
|
return {
|
|
204
140
|
id: "run-1",
|
|
@@ -290,17 +226,22 @@ export function createToolResult(
|
|
|
290
226
|
});
|
|
291
227
|
}
|
|
292
228
|
|
|
293
|
-
export function
|
|
294
|
-
|
|
295
|
-
archiveUrl?: string,
|
|
296
|
-
options: { interrupted?: boolean; device?: { type: "local" | "cloud" } } = {},
|
|
229
|
+
export function createGitCheckpointNotification(
|
|
230
|
+
overrides: Partial<GitCheckpointEvent> = {},
|
|
297
231
|
): StoredNotification {
|
|
298
|
-
return createNotification(POSTHOG_NOTIFICATIONS.
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
232
|
+
return createNotification(POSTHOG_NOTIFICATIONS.GIT_CHECKPOINT, {
|
|
233
|
+
checkpointId: "checkpoint-1",
|
|
234
|
+
commit: "commit-1",
|
|
235
|
+
checkpointRef: "refs/posthog-code-checkpoint/checkpoint-1",
|
|
236
|
+
headRef: "refs/posthog-code-handoff/head/checkpoint-1",
|
|
237
|
+
head: "head-1",
|
|
238
|
+
branch: "main",
|
|
239
|
+
indexTree: "index-tree-1",
|
|
240
|
+
worktreeTree: "worktree-tree-1",
|
|
303
241
|
timestamp: new Date().toISOString(),
|
|
304
|
-
|
|
242
|
+
upstreamRemote: "origin",
|
|
243
|
+
upstreamMergeRef: "refs/heads/main",
|
|
244
|
+
remoteUrl: "git@github.com:posthog/posthog.git",
|
|
245
|
+
...overrides,
|
|
305
246
|
});
|
|
306
247
|
}
|
|
@@ -35,7 +35,6 @@ import {
|
|
|
35
35
|
resumeFromLog,
|
|
36
36
|
} from "../resume";
|
|
37
37
|
import { SessionLogWriter } from "../session-log-writer";
|
|
38
|
-
import { TreeTracker } from "../tree-tracker";
|
|
39
38
|
import type {
|
|
40
39
|
AgentMode,
|
|
41
40
|
DeviceInfo,
|
|
@@ -44,7 +43,6 @@ import type {
|
|
|
44
43
|
LogLevel,
|
|
45
44
|
TaskRun,
|
|
46
45
|
TaskRunArtifact,
|
|
47
|
-
TreeSnapshotEvent,
|
|
48
46
|
} from "../types";
|
|
49
47
|
import { resourceLink } from "../utils/acp-content";
|
|
50
48
|
import { AsyncMutex } from "../utils/async-mutex";
|
|
@@ -184,7 +182,6 @@ interface ActiveSession {
|
|
|
184
182
|
acpSessionId: string;
|
|
185
183
|
acpConnection: InProcessAcpConnection;
|
|
186
184
|
clientConnection: ClientSideConnection;
|
|
187
|
-
treeTracker: TreeTracker | null;
|
|
188
185
|
sseController: SseController | null;
|
|
189
186
|
deviceInfo: DeviceInfo;
|
|
190
187
|
logWriter: SessionLogWriter;
|
|
@@ -494,7 +491,6 @@ export class AgentServer {
|
|
|
494
491
|
});
|
|
495
492
|
this.logger.debug("Resume state loaded", {
|
|
496
493
|
conversationTurns: this.resumeState.conversation.length,
|
|
497
|
-
hasSnapshot: !!this.resumeState.latestSnapshot,
|
|
498
494
|
hasGitCheckpoint: !!this.resumeState.latestGitCheckpoint,
|
|
499
495
|
gitCheckpointBranch:
|
|
500
496
|
this.resumeState.latestGitCheckpoint?.branch ?? null,
|
|
@@ -823,16 +819,6 @@ export class AgentServer {
|
|
|
823
819
|
userAgent: `posthog/cloud.hog.dev; version: ${this.config.version ?? packageJson.version}`,
|
|
824
820
|
});
|
|
825
821
|
|
|
826
|
-
const treeTracker = this.config.repositoryPath
|
|
827
|
-
? new TreeTracker({
|
|
828
|
-
repositoryPath: this.config.repositoryPath,
|
|
829
|
-
taskId: payload.task_id,
|
|
830
|
-
runId: payload.run_id,
|
|
831
|
-
apiClient: posthogAPI,
|
|
832
|
-
logger: new Logger({ debug: true, prefix: "[TreeTracker]" }),
|
|
833
|
-
})
|
|
834
|
-
: null;
|
|
835
|
-
|
|
836
822
|
const logWriter = new SessionLogWriter({
|
|
837
823
|
posthogAPI,
|
|
838
824
|
logger: new Logger({ debug: true, prefix: "[SessionLogWriter]" }),
|
|
@@ -948,7 +934,6 @@ export class AgentServer {
|
|
|
948
934
|
acpSessionId,
|
|
949
935
|
acpConnection,
|
|
950
936
|
clientConnection,
|
|
951
|
-
treeTracker,
|
|
952
937
|
sseController,
|
|
953
938
|
deviceInfo,
|
|
954
939
|
logWriter,
|
|
@@ -1128,36 +1113,7 @@ export class AgentServer {
|
|
|
1128
1113
|
this.resumeState.conversation,
|
|
1129
1114
|
);
|
|
1130
1115
|
|
|
1131
|
-
let
|
|
1132
|
-
if (
|
|
1133
|
-
this.resumeState.latestSnapshot?.archiveUrl &&
|
|
1134
|
-
this.config.repositoryPath &&
|
|
1135
|
-
this.posthogAPI
|
|
1136
|
-
) {
|
|
1137
|
-
try {
|
|
1138
|
-
const treeTracker = new TreeTracker({
|
|
1139
|
-
repositoryPath: this.config.repositoryPath,
|
|
1140
|
-
taskId: payload.task_id,
|
|
1141
|
-
runId: payload.run_id,
|
|
1142
|
-
apiClient: this.posthogAPI,
|
|
1143
|
-
logger: this.logger.child("TreeTracker"),
|
|
1144
|
-
});
|
|
1145
|
-
await treeTracker.applyTreeSnapshot(this.resumeState.latestSnapshot);
|
|
1146
|
-
treeTracker.setLastTreeHash(this.resumeState.latestSnapshot.treeHash);
|
|
1147
|
-
snapshotApplied = true;
|
|
1148
|
-
this.logger.info("Tree snapshot applied", {
|
|
1149
|
-
treeHash: this.resumeState.latestSnapshot.treeHash,
|
|
1150
|
-
changes: this.resumeState.latestSnapshot.changes?.length ?? 0,
|
|
1151
|
-
hasArchiveUrl: !!this.resumeState.latestSnapshot.archiveUrl,
|
|
1152
|
-
});
|
|
1153
|
-
} catch (error) {
|
|
1154
|
-
this.logger.warn("Failed to apply tree snapshot", {
|
|
1155
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1156
|
-
treeHash: this.resumeState.latestSnapshot.treeHash,
|
|
1157
|
-
});
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1116
|
+
let checkpointApplied = false;
|
|
1161
1117
|
if (
|
|
1162
1118
|
this.resumeState.latestGitCheckpoint &&
|
|
1163
1119
|
this.config.repositoryPath &&
|
|
@@ -1174,6 +1130,7 @@ export class AgentServer {
|
|
|
1174
1130
|
const metrics = await checkpointTracker.applyFromHandoff(
|
|
1175
1131
|
this.resumeState.latestGitCheckpoint,
|
|
1176
1132
|
);
|
|
1133
|
+
checkpointApplied = true;
|
|
1177
1134
|
this.logger.info("Git checkpoint applied", {
|
|
1178
1135
|
branch: this.resumeState.latestGitCheckpoint.branch,
|
|
1179
1136
|
head: this.resumeState.latestGitCheckpoint.head,
|
|
@@ -1191,9 +1148,9 @@ export class AgentServer {
|
|
|
1191
1148
|
|
|
1192
1149
|
const pendingUserPrompt = await this.getPendingUserPrompt(taskRun);
|
|
1193
1150
|
|
|
1194
|
-
const sandboxContext =
|
|
1195
|
-
? `The workspace environment (all files, packages, and code changes) has been fully restored from
|
|
1196
|
-
: `The workspace
|
|
1151
|
+
const sandboxContext = checkpointApplied
|
|
1152
|
+
? `The workspace environment (all files, packages, and code changes) has been fully restored from the latest checkpoint.`
|
|
1153
|
+
: `The workspace from the previous session was not restored from a checkpoint, so you are starting with a fresh environment. Your conversation history is fully preserved below.`;
|
|
1197
1154
|
|
|
1198
1155
|
let resumePromptBlocks: ContentBlock[];
|
|
1199
1156
|
if (pendingUserPrompt?.length) {
|
|
@@ -1230,7 +1187,7 @@ export class AgentServer {
|
|
|
1230
1187
|
conversationTurns: this.resumeState.conversation.length,
|
|
1231
1188
|
promptLength: promptBlocksToText(resumePromptBlocks).length,
|
|
1232
1189
|
hasPendingUserMessage: !!pendingUserPrompt?.length,
|
|
1233
|
-
|
|
1190
|
+
checkpointApplied,
|
|
1234
1191
|
hasGitCheckpoint: !!this.resumeState.latestGitCheckpoint,
|
|
1235
1192
|
gitCheckpointBranch:
|
|
1236
1193
|
this.resumeState.latestGitCheckpoint?.branch ?? null,
|
|
@@ -1933,7 +1890,8 @@ ${attributionInstructions}
|
|
|
1933
1890
|
}
|
|
1934
1891
|
|
|
1935
1892
|
// session/update notifications flow through the tapped stream (like local transport)
|
|
1936
|
-
//
|
|
1893
|
+
// Capture checkpoints for file-changing tools so cloud resumes restore
|
|
1894
|
+
// from git checkpoints rather than tree snapshots.
|
|
1937
1895
|
if (params.update?.sessionUpdate === "tool_call_update") {
|
|
1938
1896
|
const meta = (params.update?._meta as Record<string, unknown>)
|
|
1939
1897
|
?.claudeCode as Record<string, unknown> | undefined;
|
|
@@ -1943,10 +1901,14 @@ ${attributionInstructions}
|
|
|
1943
1901
|
| undefined;
|
|
1944
1902
|
|
|
1945
1903
|
if (
|
|
1946
|
-
(toolName === "Write" ||
|
|
1904
|
+
(toolName === "Write" ||
|
|
1905
|
+
toolName === "Edit" ||
|
|
1906
|
+
toolName === "MultiEdit" ||
|
|
1907
|
+
toolName === "Delete" ||
|
|
1908
|
+
toolName === "Move") &&
|
|
1947
1909
|
toolResponse?.filePath
|
|
1948
1910
|
) {
|
|
1949
|
-
await this.
|
|
1911
|
+
await this.captureCheckpointState();
|
|
1950
1912
|
}
|
|
1951
1913
|
|
|
1952
1914
|
if (
|
|
@@ -2168,15 +2130,9 @@ ${attributionInstructions}
|
|
|
2168
2130
|
this.logger.debug("Cleaning up session");
|
|
2169
2131
|
|
|
2170
2132
|
try {
|
|
2171
|
-
await this.
|
|
2172
|
-
} catch (error) {
|
|
2173
|
-
this.logger.error("Failed to capture handoff checkpoint", error);
|
|
2174
|
-
}
|
|
2175
|
-
|
|
2176
|
-
try {
|
|
2177
|
-
await this.captureTreeState();
|
|
2133
|
+
await this.captureCheckpointState(this.session.pendingHandoffGitState);
|
|
2178
2134
|
} catch (error) {
|
|
2179
|
-
this.logger.error("Failed to capture final
|
|
2135
|
+
this.logger.error("Failed to capture final checkpoint state", error);
|
|
2180
2136
|
}
|
|
2181
2137
|
|
|
2182
2138
|
try {
|
|
@@ -2212,50 +2168,15 @@ ${attributionInstructions}
|
|
|
2212
2168
|
this.session = null;
|
|
2213
2169
|
}
|
|
2214
2170
|
|
|
2215
|
-
private async
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
const snapshot = await this.session.treeTracker.captureTree({});
|
|
2220
|
-
if (snapshot) {
|
|
2221
|
-
const snapshotWithDevice: TreeSnapshotEvent = {
|
|
2222
|
-
...snapshot,
|
|
2223
|
-
device: this.session.deviceInfo,
|
|
2224
|
-
};
|
|
2225
|
-
|
|
2226
|
-
const notification = {
|
|
2227
|
-
jsonrpc: "2.0" as const,
|
|
2228
|
-
method: POSTHOG_NOTIFICATIONS.TREE_SNAPSHOT,
|
|
2229
|
-
params: snapshotWithDevice,
|
|
2230
|
-
};
|
|
2231
|
-
|
|
2232
|
-
this.broadcastEvent({
|
|
2233
|
-
type: "notification",
|
|
2234
|
-
timestamp: new Date().toISOString(),
|
|
2235
|
-
notification,
|
|
2236
|
-
});
|
|
2237
|
-
|
|
2238
|
-
// Persist full snapshot (including archiveUrl) so resume can restore files.
|
|
2239
|
-
// archiveUrl is a pre-signed S3 URL that expires — if the user resumes
|
|
2240
|
-
// after expiry, ApplySnapshotSaga fails gracefully and the agent continues
|
|
2241
|
-
// with conversation context but a fresh sandbox (snapshotApplied=false).
|
|
2242
|
-
this.session.logWriter.appendRawLine(
|
|
2243
|
-
this.session.payload.run_id,
|
|
2244
|
-
JSON.stringify(notification),
|
|
2245
|
-
);
|
|
2246
|
-
}
|
|
2247
|
-
} catch (error) {
|
|
2248
|
-
this.logger.error("Failed to capture tree state", error);
|
|
2249
|
-
}
|
|
2250
|
-
}
|
|
2251
|
-
|
|
2252
|
-
private async captureHandoffCheckpoint(): Promise<void> {
|
|
2253
|
-
if (!this.session?.treeTracker || !this.session.pendingHandoffGitState) {
|
|
2171
|
+
private async captureCheckpointState(
|
|
2172
|
+
localGitState?: HandoffLocalGitState,
|
|
2173
|
+
): Promise<void> {
|
|
2174
|
+
if (!this.session || !this.config.repositoryPath) {
|
|
2254
2175
|
return;
|
|
2255
2176
|
}
|
|
2256
2177
|
if (!this.posthogAPI) {
|
|
2257
2178
|
this.logger.warn(
|
|
2258
|
-
"Skipping
|
|
2179
|
+
"Skipping checkpoint capture: PostHog API client is not configured",
|
|
2259
2180
|
);
|
|
2260
2181
|
return;
|
|
2261
2182
|
}
|
|
@@ -2268,9 +2189,7 @@ ${attributionInstructions}
|
|
|
2268
2189
|
logger: this.logger.child("HandoffCheckpoint"),
|
|
2269
2190
|
});
|
|
2270
2191
|
|
|
2271
|
-
const checkpoint = await tracker.captureForHandoff(
|
|
2272
|
-
this.session.pendingHandoffGitState,
|
|
2273
|
-
);
|
|
2192
|
+
const checkpoint = await tracker.captureForHandoff(localGitState);
|
|
2274
2193
|
if (!checkpoint) return;
|
|
2275
2194
|
|
|
2276
2195
|
const checkpointWithDevice: GitCheckpointEvent = {
|
package/src/test/fixtures/api.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { join } from "node:path";
|
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import { vi } from "vitest";
|
|
8
8
|
import type { PostHogAPIClient } from "../../posthog-api";
|
|
9
|
-
import type { TaskRun
|
|
9
|
+
import type { TaskRun } from "../../types";
|
|
10
10
|
|
|
11
11
|
const execFileAsync = promisify(execFile);
|
|
12
12
|
|
|
@@ -70,7 +70,7 @@ export function createMockApiClient(
|
|
|
70
70
|
return {
|
|
71
71
|
uploadTaskArtifacts: vi
|
|
72
72
|
.fn()
|
|
73
|
-
.mockResolvedValue([{ storage_path: "gs://bucket/
|
|
73
|
+
.mockResolvedValue([{ storage_path: "gs://bucket/handoff/test.pack" }]),
|
|
74
74
|
downloadArtifact: vi.fn(),
|
|
75
75
|
getTaskRun: vi.fn(),
|
|
76
76
|
fetchTaskRunLogs: vi.fn(),
|
|
@@ -97,16 +97,3 @@ export function createTaskRun(overrides: Partial<TaskRun> = {}): TaskRun {
|
|
|
97
97
|
...overrides,
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
-
|
|
101
|
-
export function createSnapshot(
|
|
102
|
-
overrides: Partial<TreeSnapshot> = {},
|
|
103
|
-
): TreeSnapshot {
|
|
104
|
-
return {
|
|
105
|
-
treeHash: "test-tree-hash",
|
|
106
|
-
baseCommit: null,
|
|
107
|
-
archiveUrl: "gs://bucket/trees/test.tar.gz",
|
|
108
|
-
changes: [],
|
|
109
|
-
timestamp: new Date().toISOString(),
|
|
110
|
-
...overrides,
|
|
111
|
-
};
|
|
112
|
-
}
|
package/src/types.ts
CHANGED
|
@@ -61,7 +61,6 @@ export type ArtifactType =
|
|
|
61
61
|
| "reference"
|
|
62
62
|
| "output"
|
|
63
63
|
| "artifact"
|
|
64
|
-
| "tree_snapshot"
|
|
65
64
|
| "user_attachment";
|
|
66
65
|
|
|
67
66
|
export interface TaskRunArtifact {
|
|
@@ -187,21 +186,6 @@ export interface FileChange {
|
|
|
187
186
|
status: FileStatus;
|
|
188
187
|
}
|
|
189
188
|
|
|
190
|
-
// Tree snapshot - what TreeTracker captures
|
|
191
|
-
export interface TreeSnapshot {
|
|
192
|
-
treeHash: string;
|
|
193
|
-
baseCommit: string | null;
|
|
194
|
-
archiveUrl?: string;
|
|
195
|
-
changes: FileChange[];
|
|
196
|
-
timestamp: string;
|
|
197
|
-
interrupted?: boolean;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Tree snapshot event - includes device info when sent as notification
|
|
201
|
-
export interface TreeSnapshotEvent extends TreeSnapshot {
|
|
202
|
-
device?: DeviceInfo;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
189
|
export type HandoffLocalGitState = GitHandoffLocalGitState;
|
|
206
190
|
|
|
207
191
|
export interface GitCheckpoint extends GitHandoffCheckpoint {
|
package/dist/tree-tracker.d.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { PostHogAPIClient } from './posthog-api.js';
|
|
2
|
-
import { TreeSnapshot } from './types.js';
|
|
3
|
-
import { L as Logger } from './logger-RC7sPv0S.js';
|
|
4
|
-
import '@posthog/git/handoff';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* TreeTracker - Git tree-based state capture for cloud/local sync
|
|
8
|
-
*
|
|
9
|
-
* Captures the entire working state as a git tree hash + archive:
|
|
10
|
-
* - Atomic state snapshots (no partial syncs)
|
|
11
|
-
* - Efficient delta detection using git's diffing
|
|
12
|
-
* - Simpler resume logic (restore tree, continue)
|
|
13
|
-
*
|
|
14
|
-
* Uses Saga pattern for atomic operations with automatic rollback on failure.
|
|
15
|
-
* Uses a temporary git index to avoid modifying the user's staging area.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
interface TreeTrackerConfig {
|
|
19
|
-
repositoryPath: string;
|
|
20
|
-
taskId: string;
|
|
21
|
-
runId: string;
|
|
22
|
-
apiClient?: PostHogAPIClient;
|
|
23
|
-
logger?: Logger;
|
|
24
|
-
}
|
|
25
|
-
declare class TreeTracker {
|
|
26
|
-
private repositoryPath;
|
|
27
|
-
private taskId;
|
|
28
|
-
private runId;
|
|
29
|
-
private apiClient?;
|
|
30
|
-
private logger;
|
|
31
|
-
private lastTreeHash;
|
|
32
|
-
constructor(config: TreeTrackerConfig);
|
|
33
|
-
/**
|
|
34
|
-
* Capture current working tree state as a snapshot.
|
|
35
|
-
* Uses a temporary index to avoid modifying user's staging area.
|
|
36
|
-
* Uses Saga pattern for atomic operation with automatic cleanup on failure.
|
|
37
|
-
*/
|
|
38
|
-
captureTree(options?: {
|
|
39
|
-
interrupted?: boolean;
|
|
40
|
-
}): Promise<TreeSnapshot | null>;
|
|
41
|
-
/**
|
|
42
|
-
* Download and apply a tree snapshot.
|
|
43
|
-
* Uses Saga pattern for atomic operation with rollback on failure.
|
|
44
|
-
*/
|
|
45
|
-
applyTreeSnapshot(snapshot: TreeSnapshot): Promise<void>;
|
|
46
|
-
/**
|
|
47
|
-
* Get the last captured tree hash.
|
|
48
|
-
*/
|
|
49
|
-
getLastTreeHash(): string | null;
|
|
50
|
-
/**
|
|
51
|
-
* Set the last tree hash (used when resuming).
|
|
52
|
-
*/
|
|
53
|
-
setLastTreeHash(hash: string | null): void;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Check if a commit is available on any remote branch.
|
|
57
|
-
* Used to validate that cloud can fetch the base commit during handoff.
|
|
58
|
-
*/
|
|
59
|
-
declare function isCommitOnRemote(commit: string, cwd: string): Promise<boolean>;
|
|
60
|
-
/**
|
|
61
|
-
* Validate that a snapshot can be handed off to cloud execution.
|
|
62
|
-
* Cloud needs to be able to fetch the baseCommit from a remote.
|
|
63
|
-
*
|
|
64
|
-
* @throws Error if the snapshot cannot be restored on cloud
|
|
65
|
-
*/
|
|
66
|
-
declare function validateForCloudHandoff(snapshot: TreeSnapshot, repositoryPath: string): Promise<void>;
|
|
67
|
-
|
|
68
|
-
export { TreeSnapshot, TreeTracker, type TreeTrackerConfig, isCommitOnRemote, validateForCloudHandoff };
|