@zerone-agent/open-agent-sdk 0.5.8 → 0.6.0
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/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +6 -0
- package/dist/agent.js.map +1 -1
- package/dist/engine.d.ts +19 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +89 -2
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/providers/types.d.ts +7 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/revert/index.d.ts +63 -0
- package/dist/revert/index.d.ts.map +1 -0
- package/dist/revert/index.js +125 -0
- package/dist/revert/index.js.map +1 -0
- package/dist/session.d.ts +20 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +40 -6
- package/dist/session.js.map +1 -1
- package/dist/snapshot/git-detector.d.ts +9 -0
- package/dist/snapshot/git-detector.d.ts.map +1 -0
- package/dist/snapshot/git-detector.js +26 -0
- package/dist/snapshot/git-detector.js.map +1 -0
- package/dist/snapshot/index.d.ts +76 -0
- package/dist/snapshot/index.d.ts.map +1 -0
- package/dist/snapshot/index.js +288 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/snapshot/semaphore.d.ts +11 -0
- package/dist/snapshot/semaphore.d.ts.map +1 -0
- package/dist/snapshot/semaphore.js +27 -0
- package/dist/snapshot/semaphore.js.map +1 -0
- package/dist/tools/todo-tool.d.ts +8 -18
- package/dist/tools/todo-tool.d.ts.map +1 -1
- package/dist/tools/todo-tool.js +138 -76
- package/dist/tools/todo-tool.js.map +1 -1
- package/dist/tools/todowrite.txt +25 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/compact.d.ts +5 -0
- package/dist/utils/compact.d.ts.map +1 -1
- package/dist/utils/compact.js +30 -0
- package/dist/utils/compact.js.map +1 -1
- package/dist/utils/messages.js +2 -2
- package/dist/utils/messages.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revert Service
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates conversation + file rollback using SnapshotEngine
|
|
5
|
+
* and QueryEngine snapshot/restore.
|
|
6
|
+
*
|
|
7
|
+
* Two modes:
|
|
8
|
+
* - Mode A (snapshotEngine provided): reverts files + conversation
|
|
9
|
+
* - Mode B (no snapshotEngine): reverts conversation only
|
|
10
|
+
*/
|
|
11
|
+
import type { NormalizedMessageParam } from '../providers/types.js';
|
|
12
|
+
import type { EngineSnapshot } from '../types.js';
|
|
13
|
+
import type { SnapshotEngine } from '../snapshot/index.js';
|
|
14
|
+
export interface RevertServiceOptions {
|
|
15
|
+
engine: {
|
|
16
|
+
messages: NormalizedMessageParam[];
|
|
17
|
+
snapshot: () => EngineSnapshot;
|
|
18
|
+
restore: (snap: EngineSnapshot) => void;
|
|
19
|
+
isRunning: boolean;
|
|
20
|
+
compactBoundaryId?: string;
|
|
21
|
+
};
|
|
22
|
+
snapshotEngine?: SnapshotEngine;
|
|
23
|
+
/** Snapshot of engine state taken before the current run (for restore) */
|
|
24
|
+
engineSnapshot: EngineSnapshot;
|
|
25
|
+
}
|
|
26
|
+
export interface RevertResult {
|
|
27
|
+
messageId: string;
|
|
28
|
+
changedFiles: string[];
|
|
29
|
+
diff?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare class RevertService {
|
|
32
|
+
private engine;
|
|
33
|
+
private snapshotEngine?;
|
|
34
|
+
private engineSnapshot;
|
|
35
|
+
private revertSnapshot?;
|
|
36
|
+
private revertState?;
|
|
37
|
+
constructor(opts: RevertServiceOptions);
|
|
38
|
+
/**
|
|
39
|
+
* Revert conversation and files to the state before the given message.
|
|
40
|
+
*/
|
|
41
|
+
revert(messageId: string): Promise<RevertResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Undo a revert — restore files and conversation to pre-revert state.
|
|
44
|
+
*/
|
|
45
|
+
unrevert(): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Permanently commit a revert — cleaned-up messages are gone forever.
|
|
48
|
+
*/
|
|
49
|
+
cleanup(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get current revert state (for persistence).
|
|
52
|
+
*/
|
|
53
|
+
getState(): {
|
|
54
|
+
messageId: string;
|
|
55
|
+
snapshotHash?: string;
|
|
56
|
+
} | null;
|
|
57
|
+
/**
|
|
58
|
+
* Whether a revert is currently active.
|
|
59
|
+
*/
|
|
60
|
+
isReverted(): boolean;
|
|
61
|
+
private assertNotBusy;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/revert/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,sBAAsB,CAAA;AAEvE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE;QACN,QAAQ,EAAE,sBAAsB,EAAE,CAAA;QAClC,QAAQ,EAAE,MAAM,cAAc,CAAA;QAC9B,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;QACvC,SAAS,EAAE,OAAO,CAAA;QAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAC3B,CAAA;IACD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,0EAA0E;IAC1E,cAAc,EAAE,cAAc,CAAA;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,WAAW,CAAC,CAA8C;gBAEtD,IAAI,EAAE,oBAAoB;IAMtC;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAsEtD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB/B;;OAEG;IACH,OAAO,IAAI,IAAI;IAKf;;OAEG;IACH,QAAQ,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAI/D;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB,OAAO,CAAC,aAAa;CAKtB"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revert Service
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates conversation + file rollback using SnapshotEngine
|
|
5
|
+
* and QueryEngine snapshot/restore.
|
|
6
|
+
*
|
|
7
|
+
* Two modes:
|
|
8
|
+
* - Mode A (snapshotEngine provided): reverts files + conversation
|
|
9
|
+
* - Mode B (no snapshotEngine): reverts conversation only
|
|
10
|
+
*/
|
|
11
|
+
export class RevertService {
|
|
12
|
+
engine;
|
|
13
|
+
snapshotEngine;
|
|
14
|
+
engineSnapshot;
|
|
15
|
+
revertSnapshot;
|
|
16
|
+
revertState;
|
|
17
|
+
constructor(opts) {
|
|
18
|
+
this.engine = opts.engine;
|
|
19
|
+
this.snapshotEngine = opts.snapshotEngine;
|
|
20
|
+
this.engineSnapshot = opts.engineSnapshot;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Revert conversation and files to the state before the given message.
|
|
24
|
+
*/
|
|
25
|
+
async revert(messageId) {
|
|
26
|
+
this.assertNotBusy();
|
|
27
|
+
const anchorIdx = this.engine.messages.findIndex((m) => m.id === messageId);
|
|
28
|
+
if (anchorIdx === -1) {
|
|
29
|
+
// Check if it was compacted away
|
|
30
|
+
const boundary = this.engine.compactBoundaryId;
|
|
31
|
+
if (boundary) {
|
|
32
|
+
throw new Error(`Cannot revert to message ${messageId} — it was summarized by auto-compaction. ` +
|
|
33
|
+
`Earliest available message: ${boundary}`);
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Message not found: ${messageId}`);
|
|
36
|
+
}
|
|
37
|
+
// Collect file changes from messages at or after the anchor.
|
|
38
|
+
// For each file, use the FIRST occurrence's beforeHash (the state before
|
|
39
|
+
// the file was first changed in this range). Later occurrences are skipped
|
|
40
|
+
// to avoid overwriting with newer states.
|
|
41
|
+
const entries = [];
|
|
42
|
+
const changedFiles = new Set();
|
|
43
|
+
const seenFiles = new Set();
|
|
44
|
+
for (let i = anchorIdx; i < this.engine.messages.length; i++) {
|
|
45
|
+
const msg = this.engine.messages[i];
|
|
46
|
+
if (msg._snapshot) {
|
|
47
|
+
for (const file of msg._snapshot.changedFiles) {
|
|
48
|
+
changedFiles.add(file);
|
|
49
|
+
if (!seenFiles.has(file)) {
|
|
50
|
+
seenFiles.add(file);
|
|
51
|
+
entries.push({ hash: msg._snapshot.beforeHash, path: file });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Mode A: revert files
|
|
57
|
+
let diff;
|
|
58
|
+
if (this.snapshotEngine && entries.length > 0) {
|
|
59
|
+
if (!this.revertState?.snapshotHash) {
|
|
60
|
+
const snapshotHash = await this.snapshotEngine.track();
|
|
61
|
+
this.revertState = { messageId, snapshotHash };
|
|
62
|
+
this.revertSnapshot = this.engineSnapshot;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
await this.snapshotEngine.restore(this.revertState.snapshotHash);
|
|
66
|
+
}
|
|
67
|
+
await this.snapshotEngine.revert(entries);
|
|
68
|
+
diff = await this.snapshotEngine.diff(this.revertState.snapshotHash);
|
|
69
|
+
}
|
|
70
|
+
// Revert conversation state
|
|
71
|
+
this.engine.restore(this.engineSnapshot);
|
|
72
|
+
this.engine.messages.length = anchorIdx;
|
|
73
|
+
this.revertState = {
|
|
74
|
+
messageId,
|
|
75
|
+
snapshotHash: this.revertState?.snapshotHash,
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
messageId,
|
|
79
|
+
changedFiles: Array.from(changedFiles),
|
|
80
|
+
diff,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Undo a revert — restore files and conversation to pre-revert state.
|
|
85
|
+
*/
|
|
86
|
+
async unrevert() {
|
|
87
|
+
this.assertNotBusy();
|
|
88
|
+
if (!this.revertState?.snapshotHash) {
|
|
89
|
+
throw new Error('No active revert to undo');
|
|
90
|
+
}
|
|
91
|
+
if (this.snapshotEngine) {
|
|
92
|
+
await this.snapshotEngine.restore(this.revertState.snapshotHash);
|
|
93
|
+
}
|
|
94
|
+
if (this.revertSnapshot) {
|
|
95
|
+
this.engine.restore(this.revertSnapshot);
|
|
96
|
+
}
|
|
97
|
+
this.revertState = undefined;
|
|
98
|
+
this.revertSnapshot = undefined;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Permanently commit a revert — cleaned-up messages are gone forever.
|
|
102
|
+
*/
|
|
103
|
+
cleanup() {
|
|
104
|
+
this.revertState = undefined;
|
|
105
|
+
this.revertSnapshot = undefined;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get current revert state (for persistence).
|
|
109
|
+
*/
|
|
110
|
+
getState() {
|
|
111
|
+
return this.revertState ?? null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Whether a revert is currently active.
|
|
115
|
+
*/
|
|
116
|
+
isReverted() {
|
|
117
|
+
return this.revertState !== undefined;
|
|
118
|
+
}
|
|
119
|
+
assertNotBusy() {
|
|
120
|
+
if (this.engine.isRunning) {
|
|
121
|
+
throw new Error('Cannot revert while engine is running');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/revert/index.ts"],"names":[],"mappings":"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"}
|
package/dist/session.d.ts
CHANGED
|
@@ -19,6 +19,13 @@ export interface SessionMetadata {
|
|
|
19
19
|
summary?: string;
|
|
20
20
|
lastInputTokens?: number;
|
|
21
21
|
lastOutputTokens?: number;
|
|
22
|
+
/** Revert state — present when conversation is rolled back */
|
|
23
|
+
revert?: RevertState;
|
|
24
|
+
}
|
|
25
|
+
export interface RevertState {
|
|
26
|
+
messageId: string;
|
|
27
|
+
snapshotHash?: string;
|
|
28
|
+
diff?: string;
|
|
22
29
|
}
|
|
23
30
|
/**
|
|
24
31
|
* Session data on disk.
|
|
@@ -39,10 +46,22 @@ export declare function loadSession(sessionId: string): Promise<SessionData | nu
|
|
|
39
46
|
* List all sessions.
|
|
40
47
|
*/
|
|
41
48
|
export declare function listSessions(): Promise<SessionMetadata[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Fork source specification — which session and message to fork from.
|
|
51
|
+
*/
|
|
52
|
+
export interface ForkSource {
|
|
53
|
+
sessionId: string;
|
|
54
|
+
/** Fork point: only messages up to and including this one are copied. */
|
|
55
|
+
messageId?: string;
|
|
56
|
+
}
|
|
42
57
|
/**
|
|
43
58
|
* Fork a session (create a copy with a new ID).
|
|
59
|
+
*
|
|
60
|
+
* Without messageId: full copy of all messages.
|
|
61
|
+
* With messageId: only messages up to and including that message are copied,
|
|
62
|
+
* and all message IDs are regenerated.
|
|
44
63
|
*/
|
|
45
|
-
export declare function forkSession(
|
|
64
|
+
export declare function forkSession(source: ForkSource | string, newSessionId?: string): Promise<string | null>;
|
|
46
65
|
/**
|
|
47
66
|
* Get session messages.
|
|
48
67
|
*/
|
package/dist/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAYlE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,eAAe,CAAA;IACzB,QAAQ,EAAE,sBAAsB,EAAE,CAAA;CACnC;AAiBD;;GAEG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,sBAAsB,EAAE,EAClC,QAAQ,EAAE,OAAO,CAAC,eAAe,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAUhF;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAwB/D;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,UAAU,GAAG,MAAM,EAC3B,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmCxB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAGnC;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACzB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAGjC;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACzB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACzB,OAAO,CAAC,IAAI,CAAC,CAQf"}
|
package/dist/session.js
CHANGED
|
@@ -6,6 +6,16 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { readFile, writeFile, mkdir, readdir } from 'fs/promises';
|
|
8
8
|
import { join } from 'path';
|
|
9
|
+
/**
|
|
10
|
+
* Ensure every message has a stable id.
|
|
11
|
+
*/
|
|
12
|
+
function ensureMessageIds(messages) {
|
|
13
|
+
for (const msg of messages) {
|
|
14
|
+
if (!msg.id)
|
|
15
|
+
msg.id = crypto.randomUUID();
|
|
16
|
+
}
|
|
17
|
+
return messages;
|
|
18
|
+
}
|
|
9
19
|
/**
|
|
10
20
|
* Get the sessions directory path.
|
|
11
21
|
*/
|
|
@@ -25,6 +35,7 @@ function getSessionPath(sessionId) {
|
|
|
25
35
|
export async function saveSession(sessionId, messages, metadata) {
|
|
26
36
|
const dir = getSessionPath(sessionId);
|
|
27
37
|
await mkdir(dir, { recursive: true });
|
|
38
|
+
const messagesWithIds = ensureMessageIds(messages);
|
|
28
39
|
const data = {
|
|
29
40
|
metadata: {
|
|
30
41
|
id: sessionId,
|
|
@@ -33,12 +44,12 @@ export async function saveSession(sessionId, messages, metadata) {
|
|
|
33
44
|
provider: metadata.provider,
|
|
34
45
|
createdAt: metadata.createdAt || new Date().toISOString(),
|
|
35
46
|
updatedAt: new Date().toISOString(),
|
|
36
|
-
messageCount:
|
|
47
|
+
messageCount: messagesWithIds.length,
|
|
37
48
|
summary: metadata.summary,
|
|
38
49
|
lastInputTokens: metadata.lastInputTokens,
|
|
39
50
|
lastOutputTokens: metadata.lastOutputTokens,
|
|
40
51
|
},
|
|
41
|
-
messages,
|
|
52
|
+
messages: messagesWithIds,
|
|
42
53
|
};
|
|
43
54
|
await writeFile(join(dir, 'transcript.json'), JSON.stringify(data, null, 2), 'utf-8');
|
|
44
55
|
}
|
|
@@ -49,7 +60,9 @@ export async function loadSession(sessionId) {
|
|
|
49
60
|
try {
|
|
50
61
|
const filePath = join(getSessionPath(sessionId), 'transcript.json');
|
|
51
62
|
const content = await readFile(filePath, 'utf-8');
|
|
52
|
-
|
|
63
|
+
const data = JSON.parse(content);
|
|
64
|
+
data.messages = ensureMessageIds(data.messages);
|
|
65
|
+
return data;
|
|
53
66
|
}
|
|
54
67
|
catch {
|
|
55
68
|
return null;
|
|
@@ -84,13 +97,34 @@ export async function listSessions() {
|
|
|
84
97
|
}
|
|
85
98
|
/**
|
|
86
99
|
* Fork a session (create a copy with a new ID).
|
|
100
|
+
*
|
|
101
|
+
* Without messageId: full copy of all messages.
|
|
102
|
+
* With messageId: only messages up to and including that message are copied,
|
|
103
|
+
* and all message IDs are regenerated.
|
|
87
104
|
*/
|
|
88
|
-
export async function forkSession(
|
|
105
|
+
export async function forkSession(source, newSessionId) {
|
|
106
|
+
// Accept both old signature (string) and new ({ sessionId, messageId? })
|
|
107
|
+
const sourceSessionId = typeof source === 'string' ? source : source.sessionId;
|
|
108
|
+
const forkMessageId = typeof source === 'string' ? undefined : source.messageId;
|
|
89
109
|
const data = await loadSession(sourceSessionId);
|
|
90
110
|
if (!data)
|
|
91
111
|
return null;
|
|
112
|
+
let messages = data.messages;
|
|
113
|
+
if (forkMessageId) {
|
|
114
|
+
const idx = messages.findIndex((m) => m.id === forkMessageId);
|
|
115
|
+
if (idx === -1) {
|
|
116
|
+
throw new Error(`Message not found: ${forkMessageId}`);
|
|
117
|
+
}
|
|
118
|
+
messages = messages.slice(0, idx + 1);
|
|
119
|
+
}
|
|
120
|
+
// Always regenerate IDs and strip snapshot metadata — fork starts clean
|
|
121
|
+
messages = messages.map((m) => ({
|
|
122
|
+
...m,
|
|
123
|
+
id: crypto.randomUUID(),
|
|
124
|
+
_snapshot: undefined,
|
|
125
|
+
}));
|
|
92
126
|
const forkId = newSessionId || crypto.randomUUID();
|
|
93
|
-
await saveSession(forkId,
|
|
127
|
+
await saveSession(forkId, messages, {
|
|
94
128
|
...data.metadata,
|
|
95
129
|
id: forkId,
|
|
96
130
|
createdAt: new Date().toISOString(),
|
|
@@ -112,7 +146,7 @@ export async function appendToSession(sessionId, message) {
|
|
|
112
146
|
const data = await loadSession(sessionId);
|
|
113
147
|
if (!data)
|
|
114
148
|
return;
|
|
115
|
-
data.messages.push(message);
|
|
149
|
+
data.messages.push(message.id ? message : { ...message, id: crypto.randomUUID() });
|
|
116
150
|
data.metadata.updatedAt = new Date().toISOString();
|
|
117
151
|
data.metadata.messageCount = data.messages.length;
|
|
118
152
|
await saveSession(sessionId, data.messages, data.metadata);
|
package/dist/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect if git CLI is available. Result is cached.
|
|
3
|
+
*/
|
|
4
|
+
export declare function isGitAvailable(): Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Reset the cache (for testing).
|
|
7
|
+
*/
|
|
8
|
+
export declare function resetGitCache(): void;
|
|
9
|
+
//# sourceMappingURL=git-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-detector.d.ts","sourceRoot":"","sources":["../../src/snapshot/git-detector.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CASvD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAEpC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { execFile } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
let cached = null;
|
|
5
|
+
/**
|
|
6
|
+
* Detect if git CLI is available. Result is cached.
|
|
7
|
+
*/
|
|
8
|
+
export async function isGitAvailable() {
|
|
9
|
+
if (cached !== null)
|
|
10
|
+
return cached;
|
|
11
|
+
try {
|
|
12
|
+
await execFileAsync('git', ['--version']);
|
|
13
|
+
cached = true;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
cached = false;
|
|
17
|
+
}
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Reset the cache (for testing).
|
|
22
|
+
*/
|
|
23
|
+
export function resetGitCache() {
|
|
24
|
+
cached = null;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=git-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-detector.js","sourceRoot":"","sources":["../../src/snapshot/git-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA;AAEhC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;AAEzC,IAAI,MAAM,GAAmB,IAAI,CAAA;AAEjC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAA;IAClC,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;QACzC,MAAM,GAAG,IAAI,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,KAAK,CAAA;IAChB,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,IAAI,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export interface SnapshotEngineOptions {
|
|
2
|
+
worktree: string;
|
|
3
|
+
/** Snapshot repo directory. Defaults to ~/.openagent/snapshot/<project-hash>/<worktree-hash>/ */
|
|
4
|
+
snapshotDir?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RevertEntry {
|
|
7
|
+
hash: string;
|
|
8
|
+
path: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class SnapshotEngine {
|
|
11
|
+
private worktree;
|
|
12
|
+
private _gitDir?;
|
|
13
|
+
private lock;
|
|
14
|
+
private gcTimer?;
|
|
15
|
+
private gcInterval?;
|
|
16
|
+
constructor(opts: SnapshotEngineOptions);
|
|
17
|
+
/** Snapshot repo path. Available after init(). */
|
|
18
|
+
private get gitDir();
|
|
19
|
+
/**
|
|
20
|
+
* Initialize the snapshot git repo.
|
|
21
|
+
* Creates a bare repo and syncs ignore rules from the source repo.
|
|
22
|
+
*/
|
|
23
|
+
init(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Run a git command with GIT_DIR and GIT_WORK_TREE set.
|
|
26
|
+
*/
|
|
27
|
+
private exec;
|
|
28
|
+
/**
|
|
29
|
+
* Run a git command without GIT_DIR/GIT_WORK_TREE (for init).
|
|
30
|
+
*/
|
|
31
|
+
private execRaw;
|
|
32
|
+
/**
|
|
33
|
+
* Sync ignore rules from the source repo's .git/info/exclude.
|
|
34
|
+
*/
|
|
35
|
+
private syncIgnoreRules;
|
|
36
|
+
/**
|
|
37
|
+
* Snapshot the current workspace state.
|
|
38
|
+
* Returns a tree hash that can be used to restore or revert later.
|
|
39
|
+
*/
|
|
40
|
+
track(): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Remove large untracked files from the index and add them to exclude.
|
|
43
|
+
*/
|
|
44
|
+
private filterLargeUntracked;
|
|
45
|
+
/**
|
|
46
|
+
* Restore the entire workspace to a snapshot state.
|
|
47
|
+
*/
|
|
48
|
+
restore(hash: string): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* List files changed since the given snapshot hash.
|
|
51
|
+
*/
|
|
52
|
+
patchList(fromHash: string): Promise<string[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Generate a unified diff between a snapshot and the current workspace.
|
|
55
|
+
*/
|
|
56
|
+
diff(fromHash: string): Promise<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Revert specific files to their state at a given snapshot.
|
|
59
|
+
* Files that did not exist in the snapshot are deleted.
|
|
60
|
+
*/
|
|
61
|
+
revert(entries: RevertEntry[]): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Run git gc to prune unreachable objects older than 7 days.
|
|
64
|
+
*/
|
|
65
|
+
gc(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Start periodic background gc.
|
|
68
|
+
* First run after 1 minute, then every hour.
|
|
69
|
+
*/
|
|
70
|
+
startGc(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Stop background gc. Call on engine shutdown or in test cleanup.
|
|
73
|
+
*/
|
|
74
|
+
stopGc(): void;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/snapshot/index.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,iGAAiG;IACjG,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAyCD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,OAAO,CAAC,CAAQ;IACxB,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,OAAO,CAAC,CAA+B;IAC/C,OAAO,CAAC,UAAU,CAAC,CAAgC;gBAEvC,IAAI,EAAE,qBAAqB;IAKvC,kDAAkD;IAClD,OAAO,KAAK,MAAM,GAGjB;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB3B;;OAEG;YACW,IAAI;IAWlB;;OAEG;YACW,OAAO;IAQrB;;OAEG;YACW,eAAe;IAY7B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAY9B;;OAEG;YACW,oBAAoB;IAoClC;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1C;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAYpD;;OAEG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY7C;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnD;;OAEG;IACG,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAWzB;;;OAGG;IACH,OAAO,IAAI,IAAI;IASf;;OAEG;IACH,MAAM,IAAI,IAAI;CAUf"}
|