@samjurnio_/memento 0.2.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/LICENSE +202 -0
- package/README.md +144 -0
- package/dist/adapters/antigravity.d.ts +19 -0
- package/dist/adapters/antigravity.js +463 -0
- package/dist/adapters/antigravity.js.map +1 -0
- package/dist/adapters/claude-code.d.ts +14 -0
- package/dist/adapters/claude-code.js +213 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +12 -0
- package/dist/adapters/codex.js +247 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/gemini.d.ts +10 -0
- package/dist/adapters/gemini.js +171 -0
- package/dist/adapters/gemini.js.map +1 -0
- package/dist/adapters/opencode.d.ts +3 -0
- package/dist/adapters/opencode.js +137 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/adapters/pi.d.ts +6 -0
- package/dist/adapters/pi.js +172 -0
- package/dist/adapters/pi.js.map +1 -0
- package/dist/artifacts.d.ts +25 -0
- package/dist/artifacts.js +50 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/bench-live.d.ts +28 -0
- package/dist/bench-live.js +187 -0
- package/dist/bench-live.js.map +1 -0
- package/dist/bench.d.ts +33 -0
- package/dist/bench.js +213 -0
- package/dist/bench.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +338 -0
- package/dist/cli.js.map +1 -0
- package/dist/compile.d.ts +27 -0
- package/dist/compile.js +193 -0
- package/dist/compile.js.map +1 -0
- package/dist/git.d.ts +45 -0
- package/dist/git.js +172 -0
- package/dist/git.js.map +1 -0
- package/dist/handoff.d.ts +26 -0
- package/dist/handoff.js +80 -0
- package/dist/handoff.js.map +1 -0
- package/dist/hooks.d.ts +25 -0
- package/dist/hooks.js +114 -0
- package/dist/hooks.js.map +1 -0
- package/dist/ids.d.ts +10 -0
- package/dist/ids.js +32 -0
- package/dist/ids.js.map +1 -0
- package/dist/inject/antigravity.d.ts +7 -0
- package/dist/inject/antigravity.js +391 -0
- package/dist/inject/antigravity.js.map +1 -0
- package/dist/inject/claude-code.d.ts +15 -0
- package/dist/inject/claude-code.js +53 -0
- package/dist/inject/claude-code.js.map +1 -0
- package/dist/inject/codex.d.ts +7 -0
- package/dist/inject/codex.js +307 -0
- package/dist/inject/codex.js.map +1 -0
- package/dist/inject/dispatch.d.ts +11 -0
- package/dist/inject/dispatch.js +42 -0
- package/dist/inject/dispatch.js.map +1 -0
- package/dist/inject.d.ts +22 -0
- package/dist/inject.js +47 -0
- package/dist/inject.js.map +1 -0
- package/dist/ledger.d.ts +45 -0
- package/dist/ledger.js +50 -0
- package/dist/ledger.js.map +1 -0
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.js +197 -0
- package/dist/mcp.js.map +1 -0
- package/dist/packet.d.ts +185 -0
- package/dist/packet.js +154 -0
- package/dist/packet.js.map +1 -0
- package/dist/redact.d.ts +19 -0
- package/dist/redact.js +86 -0
- package/dist/redact.js.map +1 -0
- package/dist/render.d.ts +11 -0
- package/dist/render.js +145 -0
- package/dist/render.js.map +1 -0
- package/dist/summarize.d.ts +35 -0
- package/dist/summarize.js +166 -0
- package/dist/summarize.js.map +1 -0
- package/package.json +61 -0
- package/schemas/packet.v1.schema.json +510 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { truncate, cleanUserMessage } from "../ledger.js";
|
|
5
|
+
import { extractTarget } from "./claude-code.js";
|
|
6
|
+
/**
|
|
7
|
+
* Gemini CLI adapter: normalizes a /chat-save checkpoint
|
|
8
|
+
* (~/.gemini/tmp/<project_hash>/chats/checkpoint-<tag>.json) into a ledger.
|
|
9
|
+
*
|
|
10
|
+
* Format (GenAI Content array — research-derived, NOT yet validated against
|
|
11
|
+
* a real local file; none existed on the dev machine):
|
|
12
|
+
* [{role: "user"|"model", parts: [{text} | {functionCall: {name, args}}
|
|
13
|
+
* | {functionResponse: {name, response}}]}]
|
|
14
|
+
*
|
|
15
|
+
* Caveats vs the other adapters:
|
|
16
|
+
* - No call ids: functionResponse is correlated to the oldest unmatched
|
|
17
|
+
* functionCall with the same name (synthetic callIds by arrival order).
|
|
18
|
+
* - No cwd in the format: workspace-scoped auto-discovery is impossible
|
|
19
|
+
* (the project-hash derivation is undocumented), so discovery returns the
|
|
20
|
+
* newest checkpoint across ALL projects — prefer --transcript here.
|
|
21
|
+
*/
|
|
22
|
+
const OUTCOME_MAX = 400;
|
|
23
|
+
const MESSAGE_MAX = 2000;
|
|
24
|
+
export function parseGeminiCheckpoint(json, sourcePath) {
|
|
25
|
+
const events = [];
|
|
26
|
+
let seq = 0;
|
|
27
|
+
let sawUserMessage = false;
|
|
28
|
+
let callCounter = 0;
|
|
29
|
+
// name → queue of unmatched synthetic callIds, oldest first.
|
|
30
|
+
const pendingByName = new Map();
|
|
31
|
+
const push = (event) => {
|
|
32
|
+
events.push({ ...event, seq: seq++ });
|
|
33
|
+
};
|
|
34
|
+
let contents;
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(json);
|
|
37
|
+
contents = Array.isArray(parsed)
|
|
38
|
+
? parsed
|
|
39
|
+
// Some versions wrap the array: {history: [...]} / {messages: [...]}
|
|
40
|
+
: parsed.history
|
|
41
|
+
?? parsed.messages
|
|
42
|
+
?? [];
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
contents = [];
|
|
46
|
+
}
|
|
47
|
+
for (const content of contents) {
|
|
48
|
+
if (!content || !Array.isArray(content.parts)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const role = content.role === "model" ? "model" : "user";
|
|
52
|
+
for (const part of content.parts) {
|
|
53
|
+
if (typeof part?.text === "string" && part.text.trim()) {
|
|
54
|
+
if (role === "user") {
|
|
55
|
+
const cleanedText = cleanUserMessage(part.text);
|
|
56
|
+
if (cleanedText) {
|
|
57
|
+
if (!sawUserMessage) {
|
|
58
|
+
sawUserMessage = true;
|
|
59
|
+
push({ type: "task.started", content: truncate(cleanedText, MESSAGE_MAX) });
|
|
60
|
+
}
|
|
61
|
+
push({ type: "message.user", content: truncate(cleanedText, MESSAGE_MAX) });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
push({ type: "message.assistant", content: truncate(part.text, MESSAGE_MAX) });
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (part?.functionCall?.name) {
|
|
70
|
+
const callId = `gem_${callCounter++}`;
|
|
71
|
+
const queue = pendingByName.get(part.functionCall.name) ?? [];
|
|
72
|
+
queue.push(callId);
|
|
73
|
+
pendingByName.set(part.functionCall.name, queue);
|
|
74
|
+
const tool = {
|
|
75
|
+
name: part.functionCall.name,
|
|
76
|
+
callId,
|
|
77
|
+
...(part.functionCall.args !== undefined ? { input: part.functionCall.args } : {}),
|
|
78
|
+
...(extractTarget(part.functionCall.args)
|
|
79
|
+
? { target: extractTarget(part.functionCall.args) }
|
|
80
|
+
: {}),
|
|
81
|
+
};
|
|
82
|
+
push({ type: "tool.called", tool });
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (part?.functionResponse?.name) {
|
|
86
|
+
const name = part.functionResponse.name;
|
|
87
|
+
const callId = pendingByName.get(name)?.shift();
|
|
88
|
+
const { outcome, isError } = describeResponse(part.functionResponse.response);
|
|
89
|
+
const tool = {
|
|
90
|
+
name,
|
|
91
|
+
outcome,
|
|
92
|
+
isError,
|
|
93
|
+
...(callId ? { callId } : {}),
|
|
94
|
+
};
|
|
95
|
+
push({ type: isError ? "tool.failed" : "tool.completed", tool });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
sessionId: sourcePath ? basenameNoExt(sourcePath) : "unknown",
|
|
101
|
+
agent: "gemini-cli",
|
|
102
|
+
...(sourcePath ? { sourcePath } : {}),
|
|
103
|
+
events,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function describeResponse(response) {
|
|
107
|
+
if (response === null || response === undefined) {
|
|
108
|
+
return { outcome: "(no output)", isError: false };
|
|
109
|
+
}
|
|
110
|
+
if (typeof response === "string") {
|
|
111
|
+
return { outcome: truncate(response, OUTCOME_MAX), isError: false };
|
|
112
|
+
}
|
|
113
|
+
const record = response;
|
|
114
|
+
const isError = record.error !== undefined && record.error !== null;
|
|
115
|
+
const body = record.output ?? record.content ?? record.error ?? response;
|
|
116
|
+
const text = typeof body === "string" ? body : JSON.stringify(body);
|
|
117
|
+
return { outcome: truncate(text, OUTCOME_MAX), isError };
|
|
118
|
+
}
|
|
119
|
+
function basenameNoExt(path) {
|
|
120
|
+
const base = path.split("/").pop() ?? path;
|
|
121
|
+
return base.replace(/\.json$/, "");
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Newest checkpoint across ALL Gemini projects. The checkpoint format
|
|
125
|
+
* carries no cwd and the project-hash derivation is undocumented, so this
|
|
126
|
+
* cannot be workspace-scoped — pass an explicit --transcript when precision
|
|
127
|
+
* matters.
|
|
128
|
+
*/
|
|
129
|
+
export function latestGeminiCheckpoint(home = homedir()) {
|
|
130
|
+
const root = join(home, ".gemini", "tmp");
|
|
131
|
+
const candidates = [];
|
|
132
|
+
let hashes;
|
|
133
|
+
try {
|
|
134
|
+
hashes = readdirSync(root);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
for (const hash of hashes) {
|
|
140
|
+
for (const dir of [join(root, hash, "chats"), join(root, hash)]) {
|
|
141
|
+
let entries;
|
|
142
|
+
try {
|
|
143
|
+
entries = readdirSync(dir);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
for (const name of entries) {
|
|
149
|
+
if (!name.endsWith(".json")) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const full = join(dir, name);
|
|
153
|
+
try {
|
|
154
|
+
const stat = statSync(full);
|
|
155
|
+
if (stat.isFile()) {
|
|
156
|
+
candidates.push({ path: full, mtime: stat.mtimeMs });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
candidates.sort((a, b) => b.mtime - a.mtime);
|
|
166
|
+
return candidates[0]?.path;
|
|
167
|
+
}
|
|
168
|
+
export function loadGeminiLedger(checkpointPath) {
|
|
169
|
+
return parseGeminiCheckpoint(readFileSync(checkpointPath, "utf8"), checkpointPath);
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { basename, join } from "node:path";
|
|
4
|
+
import { truncate } from "../ledger.js";
|
|
5
|
+
const MESSAGE_MAX = 4000;
|
|
6
|
+
/**
|
|
7
|
+
* opencode (github.com/sst/opencode) stores a session as many JSON files, not a
|
|
8
|
+
* single transcript:
|
|
9
|
+
* <storage>/message/<sessionID>/msg_*.json → { id, sessionID, role, time }
|
|
10
|
+
* <storage>/part/<messageID>/prt_*.json → { type: "text", text } or
|
|
11
|
+
* { type: "tool", tool, callID, state }
|
|
12
|
+
* The adapter's "path" is therefore the session's message directory; we read its
|
|
13
|
+
* messages (ordered by time.created) and each message's parts.
|
|
14
|
+
*/
|
|
15
|
+
function storageRootFor(messageDir) {
|
|
16
|
+
// <storage>/message/<sessionID> → <storage>
|
|
17
|
+
return join(messageDir, "..", "..");
|
|
18
|
+
}
|
|
19
|
+
function readJson(path) {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function partsForMessage(storageRoot, messageId) {
|
|
28
|
+
const dir = join(storageRoot, "part", messageId);
|
|
29
|
+
let files;
|
|
30
|
+
try {
|
|
31
|
+
files = readdirSync(dir).filter((f) => f.endsWith(".json")).sort();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
return files.map((f) => readJson(join(dir, f))).filter((p) => p !== undefined);
|
|
37
|
+
}
|
|
38
|
+
export function loadOpencodeLedger(messageDir) {
|
|
39
|
+
const sessionId = basename(messageDir);
|
|
40
|
+
const storageRoot = storageRootFor(messageDir);
|
|
41
|
+
let msgFiles;
|
|
42
|
+
try {
|
|
43
|
+
msgFiles = readdirSync(messageDir).filter((f) => f.endsWith(".json"));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
msgFiles = [];
|
|
47
|
+
}
|
|
48
|
+
const messages = msgFiles
|
|
49
|
+
.map((f) => readJson(join(messageDir, f)))
|
|
50
|
+
.filter((m) => m !== undefined)
|
|
51
|
+
.sort((a, b) => {
|
|
52
|
+
const ta = (a.time?.created) ?? 0;
|
|
53
|
+
const tb = (b.time?.created) ?? 0;
|
|
54
|
+
if (ta !== tb)
|
|
55
|
+
return ta - tb;
|
|
56
|
+
return String(a.id).localeCompare(String(b.id));
|
|
57
|
+
});
|
|
58
|
+
const events = [];
|
|
59
|
+
let seq = 0;
|
|
60
|
+
const push = (event) => {
|
|
61
|
+
events.push({ ...event, seq: seq++ });
|
|
62
|
+
};
|
|
63
|
+
let sawUser = false;
|
|
64
|
+
for (const msg of messages) {
|
|
65
|
+
const role = msg.role;
|
|
66
|
+
const created = msg.time?.created;
|
|
67
|
+
const at = typeof created === "number" ? { at: new Date(created).toISOString() } : {};
|
|
68
|
+
const parts = partsForMessage(storageRoot, String(msg.id));
|
|
69
|
+
for (const part of parts) {
|
|
70
|
+
if (part.type === "text" && typeof part.text === "string" && part.text.trim()) {
|
|
71
|
+
const text = truncate(part.text.trim(), MESSAGE_MAX);
|
|
72
|
+
if (role === "user") {
|
|
73
|
+
if (!sawUser) {
|
|
74
|
+
push({ type: "task.started", content: text, ...at });
|
|
75
|
+
sawUser = true;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
push({ type: "message.user", content: text, ...at });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (role === "assistant") {
|
|
82
|
+
push({ type: "message.assistant", content: text, ...at });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else if (part.type === "tool") {
|
|
86
|
+
const state = part.state ?? {};
|
|
87
|
+
const name = typeof part.tool === "string" ? part.tool : "tool";
|
|
88
|
+
const callId = typeof part.callID === "string" ? part.callID : undefined;
|
|
89
|
+
push({ type: "tool.called", tool: { name, ...(callId ? { callId } : {}), input: state.input }, ...at });
|
|
90
|
+
if (state.status && state.status !== "running" && state.status !== "pending") {
|
|
91
|
+
const isError = state.status === "error";
|
|
92
|
+
push({
|
|
93
|
+
type: isError ? "tool.failed" : "tool.completed",
|
|
94
|
+
tool: { name, ...(callId ? { callId } : {}), outcome: truncate(String(state.output ?? ""), MESSAGE_MAX), ...(isError ? { isError: true } : {}) },
|
|
95
|
+
...at,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return { sessionId, agent: "opencode", sourcePath: messageDir, events };
|
|
102
|
+
}
|
|
103
|
+
function opencodeStorage(home) {
|
|
104
|
+
return join(home, ".local", "share", "opencode", "storage");
|
|
105
|
+
}
|
|
106
|
+
export function latestOpencodeSession(_workspaceDir, home = homedir()) {
|
|
107
|
+
// opencode discovery is not workspace-scoped (sessions live in a global
|
|
108
|
+
// store); pass an explicit session message dir to target a specific one.
|
|
109
|
+
const messageRoot = join(opencodeStorage(home), "message");
|
|
110
|
+
if (!existsSync(messageRoot))
|
|
111
|
+
return undefined;
|
|
112
|
+
let sessionDirs;
|
|
113
|
+
try {
|
|
114
|
+
sessionDirs = readdirSync(messageRoot).filter((d) => d.startsWith("ses_"));
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
let best;
|
|
120
|
+
for (const d of sessionDirs) {
|
|
121
|
+
const full = join(messageRoot, d);
|
|
122
|
+
try {
|
|
123
|
+
// newest mtime across the session's message files
|
|
124
|
+
const files = readdirSync(full);
|
|
125
|
+
let m = 0;
|
|
126
|
+
for (const f of files)
|
|
127
|
+
m = Math.max(m, statSync(join(full, f)).mtimeMs);
|
|
128
|
+
if (!best || m > best.mtime)
|
|
129
|
+
best = { path: full, mtime: m };
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return best?.path;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/adapters/opencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Ledger } from "../ledger.js";
|
|
2
|
+
export declare function parsePiSession(jsonl: string, sourcePath?: string): Ledger;
|
|
3
|
+
/** Fill tool.completed names from the tool.called that shares its callId. */
|
|
4
|
+
export declare function resolvePiToolNames(ledger: Ledger): Ledger;
|
|
5
|
+
export declare function latestPiSession(workspaceDir: string, home?: string): string | undefined;
|
|
6
|
+
export declare function loadPiLedger(sessionPath: string): Ledger;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { basename, join } from "node:path";
|
|
4
|
+
import { truncate } from "../ledger.js";
|
|
5
|
+
const MESSAGE_MAX = 4000;
|
|
6
|
+
const DISCOVERY_SCAN_LIMIT = 50;
|
|
7
|
+
/**
|
|
8
|
+
* Pi (github.com/earendil-works/pi) persists a session as JSONL of SessionEntry
|
|
9
|
+
* objects. Message entries are `{ type: "message", message: Message }` where a
|
|
10
|
+
* Message is one of:
|
|
11
|
+
* - { role: "user", content: string | Part[] }
|
|
12
|
+
* - { role: "assistant", content: Part[] } (text, thinking, and toolCall parts)
|
|
13
|
+
* - { role: "toolResult", toolCallId, content: Part[] }
|
|
14
|
+
* Text parts are `{ type: "text", text }`; tool calls are parts on the assistant
|
|
15
|
+
* message carrying a name + arguments + id.
|
|
16
|
+
*/
|
|
17
|
+
function partsToText(content) {
|
|
18
|
+
if (typeof content === "string")
|
|
19
|
+
return content;
|
|
20
|
+
if (!Array.isArray(content))
|
|
21
|
+
return "";
|
|
22
|
+
return content
|
|
23
|
+
.filter((p) => p && typeof p === "object" && typeof p.text === "string")
|
|
24
|
+
.map((p) => p.text)
|
|
25
|
+
.join("\n")
|
|
26
|
+
.trim();
|
|
27
|
+
}
|
|
28
|
+
function isToolCallPart(part) {
|
|
29
|
+
if (!part || typeof part !== "object")
|
|
30
|
+
return false;
|
|
31
|
+
const p = part;
|
|
32
|
+
return (p.type === "toolCall" || p.type === "tool_call" || p.type === "tool-call") && typeof p.name === "string";
|
|
33
|
+
}
|
|
34
|
+
export function parsePiSession(jsonl, sourcePath) {
|
|
35
|
+
const events = [];
|
|
36
|
+
let seq = 0;
|
|
37
|
+
const push = (event) => {
|
|
38
|
+
events.push({ ...event, seq: seq++ });
|
|
39
|
+
};
|
|
40
|
+
let sessionId = sourcePath ? basename(sourcePath).replace(/\.jsonl$/, "") : "pi-session";
|
|
41
|
+
let cwd;
|
|
42
|
+
let sawUser = false;
|
|
43
|
+
for (const line of jsonl.split("\n")) {
|
|
44
|
+
const t = line.trim();
|
|
45
|
+
if (!t)
|
|
46
|
+
continue;
|
|
47
|
+
let entry;
|
|
48
|
+
try {
|
|
49
|
+
entry = JSON.parse(t);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (typeof entry.sessionId === "string")
|
|
55
|
+
sessionId = entry.sessionId;
|
|
56
|
+
if (typeof entry.cwd === "string")
|
|
57
|
+
cwd = entry.cwd;
|
|
58
|
+
if (entry.type !== "message" || !entry.message)
|
|
59
|
+
continue;
|
|
60
|
+
const msg = entry.message;
|
|
61
|
+
const at = typeof entry.timestamp === "string" ? { at: entry.timestamp } : {};
|
|
62
|
+
if (msg.role === "user") {
|
|
63
|
+
const text = partsToText(msg.content);
|
|
64
|
+
if (!text)
|
|
65
|
+
continue;
|
|
66
|
+
if (!sawUser) {
|
|
67
|
+
push({ type: "task.started", content: truncate(text, MESSAGE_MAX), ...at });
|
|
68
|
+
sawUser = true;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
push({ type: "message.user", content: truncate(text, MESSAGE_MAX), ...at });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (msg.role === "assistant") {
|
|
75
|
+
const parts = Array.isArray(msg.content) ? msg.content : [];
|
|
76
|
+
const text = partsToText(parts);
|
|
77
|
+
if (text)
|
|
78
|
+
push({ type: "message.assistant", content: truncate(text, MESSAGE_MAX), ...at });
|
|
79
|
+
for (const part of parts) {
|
|
80
|
+
if (isToolCallPart(part)) {
|
|
81
|
+
push({
|
|
82
|
+
type: "tool.called",
|
|
83
|
+
tool: {
|
|
84
|
+
name: part.name ?? "tool",
|
|
85
|
+
...(part.id ? { callId: part.id } : {}),
|
|
86
|
+
input: part.arguments ?? part.input,
|
|
87
|
+
},
|
|
88
|
+
...at,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (msg.role === "toolResult") {
|
|
94
|
+
const outcome = partsToText(msg.content);
|
|
95
|
+
push({
|
|
96
|
+
type: "tool.completed",
|
|
97
|
+
tool: { name: "", ...(msg.toolCallId ? { callId: msg.toolCallId } : {}), outcome: truncate(outcome, MESSAGE_MAX) },
|
|
98
|
+
...at,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
sessionId,
|
|
104
|
+
agent: "pi",
|
|
105
|
+
...(sourcePath ? { sourcePath } : {}),
|
|
106
|
+
...(cwd ? { cwd } : {}),
|
|
107
|
+
events,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** Fill tool.completed names from the tool.called that shares its callId. */
|
|
111
|
+
export function resolvePiToolNames(ledger) {
|
|
112
|
+
const nameById = new Map();
|
|
113
|
+
for (const event of ledger.events) {
|
|
114
|
+
if (event.type === "tool.called" && event.tool?.callId) {
|
|
115
|
+
nameById.set(event.tool.callId, event.tool.name);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
for (const event of ledger.events) {
|
|
119
|
+
if (event.type === "tool.completed" && event.tool && !event.tool.name && event.tool.callId) {
|
|
120
|
+
const name = nameById.get(event.tool.callId);
|
|
121
|
+
if (name)
|
|
122
|
+
event.tool.name = name;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return ledger;
|
|
126
|
+
}
|
|
127
|
+
function piSessionsDir(home) {
|
|
128
|
+
const agentDir = process.env.PI_CODING_AGENT_DIR ?? join(home, ".pi", "agent");
|
|
129
|
+
return join(agentDir, "sessions");
|
|
130
|
+
}
|
|
131
|
+
export function latestPiSession(workspaceDir, home = homedir()) {
|
|
132
|
+
const dir = piSessionsDir(home);
|
|
133
|
+
let entries;
|
|
134
|
+
try {
|
|
135
|
+
entries = readdirSync(dir);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
const candidates = entries
|
|
141
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
142
|
+
.map((f) => {
|
|
143
|
+
const full = join(dir, f);
|
|
144
|
+
try {
|
|
145
|
+
return { path: full, mtime: statSync(full).mtimeMs };
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
.filter((c) => c !== undefined)
|
|
152
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
153
|
+
// Prefer a session whose recorded cwd matches the workspace; else newest.
|
|
154
|
+
for (const candidate of candidates.slice(0, DISCOVERY_SCAN_LIMIT)) {
|
|
155
|
+
const ledger = parsePiSession(readFileSafe(candidate.path), candidate.path);
|
|
156
|
+
if (ledger.cwd && ledger.cwd === workspaceDir)
|
|
157
|
+
return candidate.path;
|
|
158
|
+
}
|
|
159
|
+
return candidates[0]?.path;
|
|
160
|
+
}
|
|
161
|
+
function readFileSafe(path) {
|
|
162
|
+
try {
|
|
163
|
+
return readFileSync(path, "utf8");
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return "";
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export function loadPiLedger(sessionPath) {
|
|
170
|
+
return resolvePiToolNames(parsePiSession(readFileSync(sessionPath, "utf8"), sessionPath));
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=pi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.js","sourceRoot":"","sources":["../../src/adapters/pi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAC,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAC,OAAO,EAAC,MAAM,SAAS,CAAC;AAChC,OAAO,EAAC,QAAQ,EAAE,IAAI,EAAC,MAAM,WAAW,CAAC;AACzC,OAAO,EAAgC,QAAQ,EAAC,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,GAAG,IAAI,CAAC;AACzB,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC;;;;;;;;;GASG;AAEH,SAAS,WAAW,CAAC,OAAgB;IACjC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,OAAO;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAQ,CAAsB,CAAC,IAAI,KAAK,QAAQ,CAAC;SAC7F,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAoB,CAAC,IAAI,CAAC;SACtC,IAAI,CAAC,IAAI,CAAC;SACV,IAAI,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,IAAa;IACjC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACpD,MAAM,CAAC,GAAG,IAAwC,CAAC;IACnD,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;AACrH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,UAAmB;IAC7D,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,MAAM,IAAI,GAAG,CAAC,KAA+B,EAAQ,EAAE;QACnD,MAAM,CAAC,IAAI,CAAC,EAAC,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAC,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,IAAI,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IACzF,IAAI,GAAuB,CAAC;IAC5B,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,KAA+I,CAAC;QACpJ,IAAI,CAAC;YACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACL,SAAS;QACb,CAAC;QAED,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;YAAE,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QACrE,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;YAAE,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QACnD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,SAAS;QAEzD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC;QAC1B,MAAM,EAAE,GAAG,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAC,EAAE,EAAE,KAAK,CAAC,SAAS,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE5E,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,IAAI,CAAC,OAAO,EAAE,CAAC;gBACX,IAAI,CAAC,EAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,EAAE,EAAC,CAAC,CAAC;gBAC1E,OAAO,GAAG,IAAI,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,EAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,EAAE,EAAC,CAAC,CAAC;YAC9E,CAAC;QACL,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAChC,IAAI,IAAI;gBAAE,IAAI,CAAC,EAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,EAAE,EAAC,CAAC,CAAC;YACzF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACvB,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;oBACvB,IAAI,CAAC;wBACD,IAAI,EAAE,aAAa;wBACnB,IAAI,EAAE;4BACF,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,MAAM;4BACzB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;4BACrC,KAAK,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK;yBACtC;wBACD,GAAG,EAAE;qBACR,CAAC,CAAC;gBACP,CAAC;YACL,CAAC;QACL,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACzC,IAAI,CAAC;gBACD,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,EAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,EAAC;gBAC9G,GAAG,EAAE;aACR,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO;QACH,SAAS;QACT,KAAK,EAAE,IAAI;QACX,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAC,UAAU,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAC,GAAG,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,MAAM;KACT,CAAC;AACN,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YACrD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;IACL,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACzF,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACrC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC/E,OAAO,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,OAAe,OAAO,EAAE;IAC1E,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACD,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,MAAM,UAAU,GAAG,OAAO;SACrB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACP,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC;YACD,OAAO,EAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,SAAS,CAAC;QACrB,CAAC;IACL,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAsC,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;SAClE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAEvC,0EAA0E;IAC1E,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,EAAE,CAAC;QAChE,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5E,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,KAAK,YAAY;YAAE,OAAO,SAAS,CAAC,IAAI,CAAC;IACzE,CAAC;IACD,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;AAC/B,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAC9B,IAAI,CAAC;QACD,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC5C,OAAO,kBAAkB,CAAC,cAAc,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;AAC9F,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Packet } from "./packet.js";
|
|
2
|
+
export interface WrittenArtifacts {
|
|
3
|
+
jsonPath: string;
|
|
4
|
+
markdownPath: string;
|
|
5
|
+
}
|
|
6
|
+
/** Write the canonical packet + markdown twin under <workspace>/.memento/. */
|
|
7
|
+
export declare function writePacketArtifacts(workspaceDir: string, packet: Packet): WrittenArtifacts;
|
|
8
|
+
/**
|
|
9
|
+
* Read the workspace's current packet. Missing → undefined; present but
|
|
10
|
+
* unparseable/invalid → throws (a corrupt packet must be surfaced to whoever
|
|
11
|
+
* is about to resume from it, not silently ignored).
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadPacket(workspaceDir: string): Packet | undefined;
|
|
14
|
+
export interface ChainLink {
|
|
15
|
+
taskId: string;
|
|
16
|
+
parent: string;
|
|
17
|
+
seq: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Packet-chain continuity (spec §5.1/§8.1): when a packet already exists in
|
|
21
|
+
* the workspace, the next compile continues its chain — same taskId, parent
|
|
22
|
+
* pointing at the previous packet, seq incremented. An unreadable or invalid
|
|
23
|
+
* prior packet starts a fresh chain rather than failing the compile.
|
|
24
|
+
*/
|
|
25
|
+
export declare function chainFromPrior(workspaceDir: string): ChainLink | undefined;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { PacketSchema } from "./packet.js";
|
|
4
|
+
import { renderMarkdown } from "./render.js";
|
|
5
|
+
/** Write the canonical packet + markdown twin under <workspace>/.memento/. */
|
|
6
|
+
export function writePacketArtifacts(workspaceDir, packet) {
|
|
7
|
+
const dir = join(workspaceDir, ".memento");
|
|
8
|
+
mkdirSync(dir, { recursive: true });
|
|
9
|
+
const jsonPath = join(dir, "handoff.json");
|
|
10
|
+
const markdownPath = join(dir, "HANDOFF.md");
|
|
11
|
+
writeFileSync(jsonPath, `${JSON.stringify(packet, null, 2)}\n`);
|
|
12
|
+
writeFileSync(markdownPath, `${renderMarkdown(packet)}\n`);
|
|
13
|
+
return { jsonPath, markdownPath };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Read the workspace's current packet. Missing → undefined; present but
|
|
17
|
+
* unparseable/invalid → throws (a corrupt packet must be surfaced to whoever
|
|
18
|
+
* is about to resume from it, not silently ignored).
|
|
19
|
+
*/
|
|
20
|
+
export function loadPacket(workspaceDir) {
|
|
21
|
+
const path = join(workspaceDir, ".memento", "handoff.json");
|
|
22
|
+
if (!existsSync(path)) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
return PacketSchema.parse(JSON.parse(readFileSync(path, "utf8")));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Packet-chain continuity (spec §5.1/§8.1): when a packet already exists in
|
|
29
|
+
* the workspace, the next compile continues its chain — same taskId, parent
|
|
30
|
+
* pointing at the previous packet, seq incremented. An unreadable or invalid
|
|
31
|
+
* prior packet starts a fresh chain rather than failing the compile.
|
|
32
|
+
*/
|
|
33
|
+
export function chainFromPrior(workspaceDir) {
|
|
34
|
+
const path = join(workspaceDir, ".memento", "handoff.json");
|
|
35
|
+
if (!existsSync(path)) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const prior = PacketSchema.parse(JSON.parse(readFileSync(path, "utf8")));
|
|
40
|
+
return {
|
|
41
|
+
taskId: prior.packet.taskId,
|
|
42
|
+
parent: prior.packet.id,
|
|
43
|
+
seq: prior.packet.seq + 1,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAC,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAC/B,OAAO,EAAC,YAAY,EAAc,MAAM,aAAa,CAAC;AACtD,OAAO,EAAC,cAAc,EAAC,MAAM,aAAa,CAAC;AAO3C,8EAA8E;AAC9E,MAAM,UAAU,oBAAoB,CAAC,YAAoB,EAAE,MAAc;IACrE,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC3C,SAAS,CAAC,GAAG,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAElC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAE7C,aAAa,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAChE,aAAa,CAAC,YAAY,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3D,OAAO,EAAC,QAAQ,EAAE,YAAY,EAAC,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,YAAoB;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;IAE5D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC;AAQD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,YAAoB;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;IAE5D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAEzE,OAAO;YACH,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;YAC3B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;YACvB,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;SAC5B,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,SAAS,CAAC;IACrB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface LiveCheck {
|
|
2
|
+
name: string;
|
|
3
|
+
pass: boolean;
|
|
4
|
+
detail?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface LiveArmResult {
|
|
7
|
+
arm: "packet" | "baseline";
|
|
8
|
+
checks: LiveCheck[];
|
|
9
|
+
passed: number;
|
|
10
|
+
total: number;
|
|
11
|
+
output: string;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
}
|
|
14
|
+
export interface LiveBenchReport {
|
|
15
|
+
version: string;
|
|
16
|
+
ranAt: string;
|
|
17
|
+
executor: string;
|
|
18
|
+
arms: LiveArmResult[];
|
|
19
|
+
}
|
|
20
|
+
export type Executor = (prompt: string, cwd: string) => Promise<string>;
|
|
21
|
+
export declare function shellExecutor(command: string, timeoutMs?: number): Executor;
|
|
22
|
+
export interface RunLiveBenchOptions {
|
|
23
|
+
executor: Executor;
|
|
24
|
+
executorLabel: string;
|
|
25
|
+
baseline?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function runLiveBench(options: RunLiveBenchOptions): Promise<LiveBenchReport>;
|
|
28
|
+
export declare function formatLiveBenchReport(report: LiveBenchReport): string;
|