@lore-co/cli 0.1.28 → 0.1.29
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 +44 -9
- package/dist/agents.d.ts +3 -1
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +31 -7
- package/dist/agents.js.map +1 -1
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +97 -15
- package/dist/cli.js.map +1 -1
- package/dist/command-help.d.ts +2 -1
- package/dist/command-help.d.ts.map +1 -1
- package/dist/command-help.js +33 -6
- package/dist/command-help.js.map +1 -1
- package/dist/generated-assets.d.ts +9 -4
- package/dist/generated-assets.d.ts.map +1 -1
- package/dist/generated-assets.js +5 -4
- package/dist/generated-assets.js.map +1 -1
- package/dist/recovery-cloud-workspace.d.ts +11 -0
- package/dist/recovery-cloud-workspace.d.ts.map +1 -0
- package/dist/recovery-cloud-workspace.js +113 -0
- package/dist/recovery-cloud-workspace.js.map +1 -0
- package/dist/recovery-cloud.d.ts +31 -0
- package/dist/recovery-cloud.d.ts.map +1 -0
- package/dist/recovery-cloud.js +242 -0
- package/dist/recovery-cloud.js.map +1 -0
- package/dist/recovery-codex.d.ts +5 -0
- package/dist/recovery-codex.d.ts.map +1 -0
- package/dist/recovery-codex.js +111 -0
- package/dist/recovery-codex.js.map +1 -0
- package/dist/recovery-copilot.d.ts +14 -0
- package/dist/recovery-copilot.d.ts.map +1 -0
- package/dist/recovery-copilot.js +120 -0
- package/dist/recovery-copilot.js.map +1 -0
- package/dist/recovery-desktop.d.ts +7 -0
- package/dist/recovery-desktop.d.ts.map +1 -0
- package/dist/recovery-desktop.js +179 -0
- package/dist/recovery-desktop.js.map +1 -0
- package/dist/recovery-external.d.ts +61 -0
- package/dist/recovery-external.d.ts.map +1 -0
- package/dist/recovery-external.js +98 -0
- package/dist/recovery-external.js.map +1 -0
- package/dist/recovery-hooks.d.ts +5 -0
- package/dist/recovery-hooks.d.ts.map +1 -0
- package/dist/recovery-hooks.js +115 -0
- package/dist/recovery-hooks.js.map +1 -0
- package/dist/recovery-hosts.d.ts +13 -0
- package/dist/recovery-hosts.d.ts.map +1 -0
- package/dist/recovery-hosts.js +263 -0
- package/dist/recovery-hosts.js.map +1 -0
- package/dist/recovery-polytoken.d.ts +14 -0
- package/dist/recovery-polytoken.d.ts.map +1 -0
- package/dist/recovery-polytoken.js +194 -0
- package/dist/recovery-polytoken.js.map +1 -0
- package/dist/recovery-remote.d.ts +8 -0
- package/dist/recovery-remote.d.ts.map +1 -0
- package/dist/recovery-remote.js +135 -0
- package/dist/recovery-remote.js.map +1 -0
- package/dist/recovery-state.d.ts +25 -1
- package/dist/recovery-state.d.ts.map +1 -1
- package/dist/recovery-state.js +69 -15
- package/dist/recovery-state.js.map +1 -1
- package/dist/recovery-t3.d.ts +17 -0
- package/dist/recovery-t3.d.ts.map +1 -0
- package/dist/recovery-t3.js +58 -0
- package/dist/recovery-t3.js.map +1 -0
- package/dist/recovery-transfer.d.ts +22 -0
- package/dist/recovery-transfer.d.ts.map +1 -0
- package/dist/recovery-transfer.js +228 -0
- package/dist/recovery-transfer.js.map +1 -0
- package/dist/recovery.d.ts +9 -1
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +187 -47
- package/dist/recovery.js.map +1 -1
- package/dist/self-host.d.ts +1 -1
- package/dist/self-host.js +2 -2
- package/dist/uninstall.d.ts +19 -0
- package/dist/uninstall.d.ts.map +1 -0
- package/dist/uninstall.js +128 -0
- package/dist/uninstall.js.map +1 -0
- package/dist/update.js +3 -3
- package/package.json +3 -3
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { mkdir, open, realpath, unlink } from "node:fs/promises";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { createInterface } from "node:readline/promises";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { AGENTS, findAgentExecutable } from "./agents.js";
|
|
9
|
+
import { captureRecoveryHook, createRecoveryRun, recoveryRunKey, RecoveryRunSchema, recoveryStore, recordRecoveryMetric } from "./recovery-state.js";
|
|
10
|
+
import { cliInvocation, launchRecoveredRun, recoveryRoute } from "./recovery.js";
|
|
11
|
+
import { shellQuote } from "./recovery-transfer.js";
|
|
12
|
+
import { observeCodexRecovery } from "./recovery-codex.js";
|
|
13
|
+
import { observePolytokenRecovery } from "./recovery-polytoken.js";
|
|
14
|
+
import { observeCopilotRecovery } from "./recovery-copilot.js";
|
|
15
|
+
function detached(home, args) {
|
|
16
|
+
const invocation = cliInvocation();
|
|
17
|
+
const child = spawn(invocation[0], [...invocation.slice(1), "recovery", ...args], { detached: true, stdio: "ignore", env: { ...process.env, LORE_HOME: home, BUN_OPTIONS: undefined, BUN_BE_BUN: undefined } });
|
|
18
|
+
child.once("error", () => { });
|
|
19
|
+
child.unref();
|
|
20
|
+
}
|
|
21
|
+
/** An IDE hook has no parent PTY. Start a terminal that owns the confirmation. */
|
|
22
|
+
export async function openRecoveryTerminal(home, id) {
|
|
23
|
+
z.uuid().parse(id);
|
|
24
|
+
if (process.platform !== "darwin" && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY)
|
|
25
|
+
throw new Error("Desktop recovery needs a graphical session; use the connected shell wrapper on a headless worker");
|
|
26
|
+
const folder = resolve(home, ".lore/recovery/offers");
|
|
27
|
+
await mkdir(folder, { recursive: true, mode: 0o700 });
|
|
28
|
+
const path = resolve(folder, `${id}.command`);
|
|
29
|
+
const file = await open(path, constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_NOFOLLOW, 0o700);
|
|
30
|
+
try {
|
|
31
|
+
await file.writeFile(`#!/bin/sh\nexec env -u BUN_OPTIONS -u BUN_BE_BUN PATH=${shellQuote(process.env.PATH || "/usr/bin:/bin")} LORE_HOME=${shellQuote(home)} ${[...cliInvocation(), "recovery", "offer", id].map(shellQuote).join(" ")}\n`);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
await file.close();
|
|
35
|
+
}
|
|
36
|
+
const command = process.platform === "darwin" ? "open" : "x-terminal-emulator";
|
|
37
|
+
const args = process.platform === "darwin" ? ["-a", "Terminal", path] : ["-e", "/bin/sh", path];
|
|
38
|
+
await new Promise((done, reject) => {
|
|
39
|
+
const child = spawn(command, args, { detached: true, stdio: "ignore" });
|
|
40
|
+
child.once("error", reject);
|
|
41
|
+
if (process.platform === "darwin")
|
|
42
|
+
child.once("exit", code => code === 0 ? done() : reject(new Error("Could not open the recovery terminal")));
|
|
43
|
+
else {
|
|
44
|
+
const timer = setTimeout(() => { child.unref(); done(); }, 500);
|
|
45
|
+
child.once("exit", code => { clearTimeout(timer); if (code === 0)
|
|
46
|
+
done();
|
|
47
|
+
else
|
|
48
|
+
reject(new Error("Could not open the recovery terminal")); });
|
|
49
|
+
child.once("error", () => clearTimeout(timer));
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
export async function offerDesktopRecovery(home, id, notify = openRecoveryTerminal) {
|
|
54
|
+
const store = recoveryStore(home);
|
|
55
|
+
const run = RecoveryRunSchema.parse(await store.readState(recoveryRunKey(id)));
|
|
56
|
+
if (await store.readState("disabled"))
|
|
57
|
+
throw new Error("Recovery is disabled");
|
|
58
|
+
if (!run.failure)
|
|
59
|
+
return;
|
|
60
|
+
let claim = false;
|
|
61
|
+
await store.updateState(`desktop-offer-${id}`, current => {
|
|
62
|
+
if (current && typeof current === "object" && "attempt" in current && current.attempt === run.failure.id)
|
|
63
|
+
return current;
|
|
64
|
+
claim = true;
|
|
65
|
+
return { attempt: run.failure.id };
|
|
66
|
+
});
|
|
67
|
+
if (!claim)
|
|
68
|
+
return;
|
|
69
|
+
try {
|
|
70
|
+
await notify(home, id);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
await store.deleteState(`desktop-offer-${id}`);
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export async function captureDesktopRecovery(home, agent, value) {
|
|
78
|
+
const input = z.object({ session_id: z.string().min(1).max(500), cwd: z.string(), hook_event_name: z.string() }).passthrough().safeParse(value);
|
|
79
|
+
if (!input.success)
|
|
80
|
+
return;
|
|
81
|
+
const route = await recoveryRoute(home, agent);
|
|
82
|
+
if (!route || route.agent === agent)
|
|
83
|
+
return;
|
|
84
|
+
const cwd = await realpath(input.data.cwd);
|
|
85
|
+
const key = `desktop-session-${createHash("sha256").update(JSON.stringify([agent, cwd, input.data.session_id])).digest("hex")}`;
|
|
86
|
+
const store = recoveryStore(home);
|
|
87
|
+
let saved = z.object({ id: z.uuid(), at: z.number() }).safeParse(await store.readState(key));
|
|
88
|
+
if (!saved.success || Date.now() - saved.data.at > 24 * 60 * 60 * 1000) {
|
|
89
|
+
if (input.data.hook_event_name !== "UserPromptSubmit")
|
|
90
|
+
return;
|
|
91
|
+
const run = await createRecoveryRun(home, cwd, agent, route.agent, route.remote);
|
|
92
|
+
const mapping = { id: run.id, at: Date.now() };
|
|
93
|
+
await store.writeState(key, mapping);
|
|
94
|
+
saved = { success: true, data: mapping };
|
|
95
|
+
}
|
|
96
|
+
const id = saved.data.id;
|
|
97
|
+
await captureRecoveryHook(home, id, input.data, agent);
|
|
98
|
+
const run = RecoveryRunSchema.parse(await store.readState(recoveryRunKey(id)));
|
|
99
|
+
if (agent === "codex" && input.data.hook_event_name === "UserPromptSubmit")
|
|
100
|
+
detached(home, ["watch", id, String(run.turn)]);
|
|
101
|
+
if (agent === "polytoken" && input.data.hook_event_name === "UserPromptSubmit")
|
|
102
|
+
detached(home, ["watch-polytoken", id, String(run.turn)]);
|
|
103
|
+
if (agent === "copilot-cli" && input.data.hook_event_name === "UserPromptSubmit")
|
|
104
|
+
detached(home, ["watch-copilot", id, String(run.turn)]);
|
|
105
|
+
if (run.failure)
|
|
106
|
+
await offerDesktopRecovery(home, id);
|
|
107
|
+
return id;
|
|
108
|
+
}
|
|
109
|
+
export async function runDesktopRecovery(args, home) {
|
|
110
|
+
const id = z.uuid().parse(args[1]);
|
|
111
|
+
const store = recoveryStore(home);
|
|
112
|
+
if (args[0] === "watch" || args[0] === "watch-polytoken" || args[0] === "watch-copilot") {
|
|
113
|
+
const turn = z.coerce.number().int().nonnegative().parse(args[2]);
|
|
114
|
+
const stop = args[0] === "watch-polytoken" ? observePolytokenRecovery(home, id) : args[0] === "watch-copilot" ? observeCopilotRecovery(home, id) : observeCodexRecovery(home, id, await findAgentExecutable("codex"));
|
|
115
|
+
try {
|
|
116
|
+
const deadline = Date.now() + 24 * 60 * 60 * 1000;
|
|
117
|
+
while (Date.now() < deadline) {
|
|
118
|
+
const run = RecoveryRunSchema.parse(await store.readState(recoveryRunKey(id)));
|
|
119
|
+
if (run.turn !== turn || !run.turnPending)
|
|
120
|
+
break;
|
|
121
|
+
if (run.failure) {
|
|
122
|
+
await offerDesktopRecovery(home, id);
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
await new Promise(done => setTimeout(done, 1000));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
stop();
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const run = RecoveryRunSchema.parse(await store.readState(recoveryRunKey(id)));
|
|
134
|
+
if (!run.failure || Date.now() - Date.parse(run.updatedAt) > 24 * 60 * 60 * 1000)
|
|
135
|
+
throw new Error("This recovery offer expired");
|
|
136
|
+
if (await store.readState("disabled"))
|
|
137
|
+
throw new Error("Recovery is disabled");
|
|
138
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
139
|
+
throw new Error("Recovery confirmation requires an interactive terminal");
|
|
140
|
+
await store.writeState(`attempt-${id}`, run);
|
|
141
|
+
await recordRecoveryMetric(home, id, run.failure.id, "offered");
|
|
142
|
+
const fromEditor = args[0] === "launch-accepted";
|
|
143
|
+
if (fromEditor && (run.sourceHost !== "copilot-vscode" || args[2] !== run.failure.id))
|
|
144
|
+
throw new Error("The editor offer is no longer current");
|
|
145
|
+
const prompt = fromEditor ? undefined : createInterface({ input: process.stdin, output: process.stdout });
|
|
146
|
+
let answer;
|
|
147
|
+
try {
|
|
148
|
+
answer = prompt ? await prompt.question(`${run.sourceHost ?? AGENTS[run.sourceAgent].label} stopped${run.failure.reason === "rate_limit" ? " at a usage limit" : " with an error"}.\nContinue with ${AGENTS[run.targetAgent].label}${run.targetRemote ? ` on ${run.targetRemote.host}` : " locally"}? [Y/n] `) : "yes";
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
prompt?.close();
|
|
152
|
+
await unlink(resolve(home, ".lore/recovery/offers", `${id}.command`)).catch(() => { });
|
|
153
|
+
}
|
|
154
|
+
if (!["", "y", "yes"].includes(answer.trim().toLowerCase())) {
|
|
155
|
+
await recordRecoveryMetric(home, id, run.failure.id, "declined");
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const current = RecoveryRunSchema.parse(await store.readState(recoveryRunKey(id)));
|
|
159
|
+
if (await store.readState("disabled"))
|
|
160
|
+
throw new Error("Recovery was disabled while the offer was open");
|
|
161
|
+
if (current.failure?.id !== run.failure.id)
|
|
162
|
+
throw new Error("The source has moved on; this offer is no longer current");
|
|
163
|
+
if (current.sourceHost && Date.now() - Date.parse(current.updatedAt) > 10000)
|
|
164
|
+
throw new Error("The host observer is unavailable. Reconnect the host before accepting this handoff.");
|
|
165
|
+
if (current.sourceHost)
|
|
166
|
+
await (await import("./recovery-hosts.js")).validateExternalRecovery(home, current);
|
|
167
|
+
let accepted = false;
|
|
168
|
+
await store.updateState(`desktop-accepted-${id}`, prior => {
|
|
169
|
+
if (prior && typeof prior === "object" && "attempt" in prior && prior.attempt === run.failure.id)
|
|
170
|
+
return prior;
|
|
171
|
+
accepted = true;
|
|
172
|
+
return { attempt: run.failure.id };
|
|
173
|
+
});
|
|
174
|
+
if (!accepted)
|
|
175
|
+
throw new Error("This handoff was already accepted");
|
|
176
|
+
await recordRecoveryMetric(home, id, run.failure.id, "accepted");
|
|
177
|
+
await launchRecoveredRun(home, current);
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=recovery-desktop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-desktop.js","sourceRoot":"","sources":["../src/recovery-desktop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const ExternalCheckpoint: z.ZodObject<{
|
|
3
|
+
host: z.ZodEnum<{
|
|
4
|
+
t3code: "t3code";
|
|
5
|
+
cowork: "cowork";
|
|
6
|
+
"copilot-vscode": "copilot-vscode";
|
|
7
|
+
}>;
|
|
8
|
+
sourceAgent: z.ZodEnum<{
|
|
9
|
+
claude: "claude";
|
|
10
|
+
codex: "codex";
|
|
11
|
+
opencode: "opencode";
|
|
12
|
+
devin: "devin";
|
|
13
|
+
cursor: "cursor";
|
|
14
|
+
"copilot-cli": "copilot-cli";
|
|
15
|
+
polytoken: "polytoken";
|
|
16
|
+
}>;
|
|
17
|
+
sessionId: z.ZodString;
|
|
18
|
+
turnId: z.ZodString;
|
|
19
|
+
cwd: z.ZodString;
|
|
20
|
+
goal: z.ZodString;
|
|
21
|
+
messages: z.ZodArray<z.ZodObject<{
|
|
22
|
+
role: z.ZodEnum<{
|
|
23
|
+
user: "user";
|
|
24
|
+
assistant: "assistant";
|
|
25
|
+
}>;
|
|
26
|
+
text: z.ZodString;
|
|
27
|
+
}, z.core.$strip>>;
|
|
28
|
+
state: z.ZodEnum<{
|
|
29
|
+
failed: "failed";
|
|
30
|
+
running: "running";
|
|
31
|
+
completed: "completed";
|
|
32
|
+
cancelled: "cancelled";
|
|
33
|
+
}>;
|
|
34
|
+
reason: z.ZodOptional<z.ZodEnum<{
|
|
35
|
+
rate_limit: "rate_limit";
|
|
36
|
+
agent_error: "agent_error";
|
|
37
|
+
}>>;
|
|
38
|
+
observedAt: z.ZodNumber;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
export type ExternalCheckpoint = z.infer<typeof ExternalCheckpoint>;
|
|
41
|
+
export declare const ExternalSettings: z.ZodObject<{
|
|
42
|
+
fallback: z.ZodEnum<{
|
|
43
|
+
claude: "claude";
|
|
44
|
+
codex: "codex";
|
|
45
|
+
opencode: "opencode";
|
|
46
|
+
devin: "devin";
|
|
47
|
+
cursor: "cursor";
|
|
48
|
+
"copilot-cli": "copilot-cli";
|
|
49
|
+
polytoken: "polytoken";
|
|
50
|
+
}>;
|
|
51
|
+
t3Database: z.ZodOptional<z.ZodString>;
|
|
52
|
+
coworkRoots: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
53
|
+
vscodeRoots: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
54
|
+
vscodeExtension: z.ZodOptional<z.ZodString>;
|
|
55
|
+
vscodeHookFiles: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
56
|
+
since: z.ZodNumber;
|
|
57
|
+
}, z.core.$strip>;
|
|
58
|
+
export declare function externalSessionKey(input: Pick<ExternalCheckpoint, "host" | "sessionId" | "cwd">): string;
|
|
59
|
+
/** Accept only host adapters' structured state. Text never determines failure. */
|
|
60
|
+
export declare function captureExternalRecovery(home: string, value: unknown, notify?: (home: string, id: string) => Promise<void>): Promise<string | undefined>;
|
|
61
|
+
//# sourceMappingURL=recovery-external.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-external.d.ts","sourceRoot":"","sources":["../src/recovery-external.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAS7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACpE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;iBAQ3B,CAAC;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,WAAW,GAAG,KAAK,CAAC,GAAG,MAAM,CAExG;AAGD,kFAAkF;AAClF,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkD7J"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { realpath } from "node:fs/promises";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { LAUNCHABLE_AGENTS, RECOVERY_SOURCES, findAgentExecutable } from "./agents.js";
|
|
5
|
+
import { createRecoveryRun, markRecoveryFailure, RecoveryRunSchema, recoveryRunKey, recoveryStore, recoveryMessageText } from "./recovery-state.js";
|
|
6
|
+
import { recoveryRoute } from "./recovery.js";
|
|
7
|
+
import { offerDesktopRecovery } from "./recovery-desktop.js";
|
|
8
|
+
export const ExternalCheckpoint = z.object({
|
|
9
|
+
host: z.enum(["t3code", "copilot-vscode", "cowork"]),
|
|
10
|
+
sourceAgent: z.enum(RECOVERY_SOURCES),
|
|
11
|
+
sessionId: z.string().min(1).max(500), turnId: z.string().min(1).max(500),
|
|
12
|
+
cwd: z.string().min(1), goal: z.string().min(1).max(24000),
|
|
13
|
+
messages: z.array(z.object({ role: z.enum(["user", "assistant"]), text: z.string().max(24000) })).max(20),
|
|
14
|
+
state: z.enum(["running", "completed", "failed", "cancelled"]),
|
|
15
|
+
reason: z.enum(["rate_limit", "agent_error"]).optional(),
|
|
16
|
+
observedAt: z.number(),
|
|
17
|
+
});
|
|
18
|
+
export const ExternalSettings = z.object({
|
|
19
|
+
fallback: z.enum(LAUNCHABLE_AGENTS),
|
|
20
|
+
t3Database: z.string().optional(),
|
|
21
|
+
coworkRoots: z.array(z.string()).default([]),
|
|
22
|
+
vscodeRoots: z.array(z.string()).default([]),
|
|
23
|
+
vscodeExtension: z.string().optional(),
|
|
24
|
+
vscodeHookFiles: z.array(z.string()).default([]),
|
|
25
|
+
since: z.number(),
|
|
26
|
+
});
|
|
27
|
+
export function externalSessionKey(input) {
|
|
28
|
+
return `external-${createHash("sha256").update(JSON.stringify([input.host, input.sessionId, input.cwd])).digest("hex")}`;
|
|
29
|
+
}
|
|
30
|
+
const safeText = recoveryMessageText;
|
|
31
|
+
/** Accept only host adapters' structured state. Text never determines failure. */
|
|
32
|
+
export async function captureExternalRecovery(home, value, notify) {
|
|
33
|
+
const parsed = ExternalCheckpoint.safeParse(value);
|
|
34
|
+
if (!parsed.success || Date.now() - parsed.data.observedAt > 30000 || parsed.data.observedAt > Date.now() + 5000)
|
|
35
|
+
return;
|
|
36
|
+
const store = recoveryStore(home);
|
|
37
|
+
if (await store.readState("disabled"))
|
|
38
|
+
return;
|
|
39
|
+
const settings = ExternalSettings.safeParse(await store.readState("external-settings"));
|
|
40
|
+
if (!settings.success)
|
|
41
|
+
return;
|
|
42
|
+
const input = parsed.data;
|
|
43
|
+
input.cwd = await realpath(input.cwd);
|
|
44
|
+
if (input.host === "cowork" && !settings.data.coworkRoots.includes(input.cwd))
|
|
45
|
+
return;
|
|
46
|
+
if (input.host === "copilot-vscode" && !settings.data.vscodeRoots.includes(input.cwd))
|
|
47
|
+
return;
|
|
48
|
+
const key = externalSessionKey(input);
|
|
49
|
+
const mapping = z.object({ id: z.uuid() }).safeParse(await store.readState(key));
|
|
50
|
+
let run = mapping.success ? RecoveryRunSchema.safeParse(await store.readState(recoveryRunKey(mapping.data.id))) : undefined;
|
|
51
|
+
if (run?.success && run.data.sourceAgent !== input.sourceAgent) {
|
|
52
|
+
await store.updateState(recoveryRunKey(run.data.id), current => ({ ...RecoveryRunSchema.parse(current), failure: null, turnPending: false }));
|
|
53
|
+
run = undefined;
|
|
54
|
+
}
|
|
55
|
+
if (!run?.success || Date.now() - Date.parse(run.data.startedAt) > 24 * 60 * 60 * 1000) {
|
|
56
|
+
// A resumed observer must not produce a handoff for an old completed chat.
|
|
57
|
+
if (input.state === "completed" || input.state === "cancelled")
|
|
58
|
+
return;
|
|
59
|
+
const route = await recoveryRoute(home, input.sourceAgent);
|
|
60
|
+
const fallback = route?.agent ?? settings.data.fallback;
|
|
61
|
+
if (fallback === input.sourceAgent)
|
|
62
|
+
return;
|
|
63
|
+
if (!route?.remote)
|
|
64
|
+
await findAgentExecutable(fallback);
|
|
65
|
+
const created = await createRecoveryRun(home, input.cwd, input.sourceAgent, fallback, route?.remote);
|
|
66
|
+
await store.writeState(key, { id: created.id });
|
|
67
|
+
run = { success: true, data: created };
|
|
68
|
+
}
|
|
69
|
+
const id = run.data.id;
|
|
70
|
+
await store.updateState(recoveryRunKey(id), current => {
|
|
71
|
+
const latest = RecoveryRunSchema.parse(current);
|
|
72
|
+
if (latest.sourceAgent !== input.sourceAgent)
|
|
73
|
+
return latest;
|
|
74
|
+
if (latest.supersededTurnId === input.turnId)
|
|
75
|
+
return latest;
|
|
76
|
+
if (latest.nativeTurnId !== input.turnId) {
|
|
77
|
+
latest.turn += 1;
|
|
78
|
+
latest.failure = null;
|
|
79
|
+
delete latest.supersededTurnId;
|
|
80
|
+
}
|
|
81
|
+
latest.sessionId = input.sessionId;
|
|
82
|
+
latest.nativeTurnId = input.turnId;
|
|
83
|
+
latest.goal = safeText(input.goal);
|
|
84
|
+
latest.messages = input.messages.map(m => ({ ...m, text: safeText(m.text) }));
|
|
85
|
+
latest.turnPending = input.state === "running" || input.state === "failed";
|
|
86
|
+
if (input.state !== "failed")
|
|
87
|
+
latest.failure = null;
|
|
88
|
+
latest.updatedAt = new Date().toISOString();
|
|
89
|
+
latest.sourceHost = input.host;
|
|
90
|
+
return latest;
|
|
91
|
+
});
|
|
92
|
+
if (input.state === "failed") {
|
|
93
|
+
await markRecoveryFailure(home, RecoveryRunSchema.parse(await store.readState(recoveryRunKey(id))), input.reason ?? "agent_error");
|
|
94
|
+
await offerDesktopRecovery(home, id, notify);
|
|
95
|
+
}
|
|
96
|
+
return id;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=recovery-external.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-external.js","sourceRoot":"","sources":["../src/recovery-external.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { RecoverySource } from "./agents.js";
|
|
2
|
+
/** Native event fields, never text scraped from the agent's answer or terminal. */
|
|
3
|
+
export declare function normalizeRecoveryHook(agent: RecoverySource, value: unknown, env?: NodeJS.ProcessEnv): unknown;
|
|
4
|
+
export declare function mergeNativeRecoveryHooks(agent: "cursor" | "copilot-cli" | "polytoken", value: unknown, command: string | null): unknown;
|
|
5
|
+
//# sourceMappingURL=recovery-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-hooks.d.ts","sourceRoot":"","sources":["../src/recovery-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,oBAAc,GAAG,OAAO,CAmDvG;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,GAAG,aAAa,GAAG,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CA2BvI"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
const OWNER = "--owner lore-recovery";
|
|
2
|
+
const isCore = (command) => typeof command === "string" && /--owner\s+lore(?:\s|$)/u.test(command);
|
|
3
|
+
/** Native event fields, never text scraped from the agent's answer or terminal. */
|
|
4
|
+
export function normalizeRecoveryHook(agent, value, env = process.env) {
|
|
5
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
6
|
+
return null;
|
|
7
|
+
const input = { ...value };
|
|
8
|
+
if (input.agent_id || input.isSidechain || input.parent_session_id)
|
|
9
|
+
return null;
|
|
10
|
+
if (agent === "cursor") {
|
|
11
|
+
input.session_id = input.conversation_id;
|
|
12
|
+
input.cwd ??= Array.isArray(input.workspace_roots) && input.workspace_roots.length === 1 ? input.workspace_roots[0] : undefined;
|
|
13
|
+
input.turn_id = input.generation_id;
|
|
14
|
+
if (input.hook_event_name === "beforeSubmitPrompt")
|
|
15
|
+
input.hook_event_name = "UserPromptSubmit";
|
|
16
|
+
else if (input.hook_event_name === "afterAgentResponse") {
|
|
17
|
+
input.hook_event_name = "Checkpoint";
|
|
18
|
+
input.last_assistant_message = input.text;
|
|
19
|
+
}
|
|
20
|
+
else if (input.hook_event_name === "stop") {
|
|
21
|
+
input.hook_event_name = input.status === "error" ? "StopFailure" : "Stop";
|
|
22
|
+
if (input.status === "error")
|
|
23
|
+
input.error = "agent_error";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else if (agent === "copilot-cli") {
|
|
27
|
+
input.session_id = input.sessionId;
|
|
28
|
+
input.hook_event_name ??= env.LORE_RECOVERY_EVENT;
|
|
29
|
+
if (input.hook_event_name === "userPromptSubmitted") {
|
|
30
|
+
input.hook_event_name = "UserPromptSubmit";
|
|
31
|
+
// The events journal records this same native hook timestamp before user.message.
|
|
32
|
+
if (Number.isSafeInteger(input.timestamp))
|
|
33
|
+
input.turn_id = `hook:${input.timestamp}`;
|
|
34
|
+
}
|
|
35
|
+
else if (input.hook_event_name === "agentStop") {
|
|
36
|
+
input.hook_event_name = "Stop";
|
|
37
|
+
input.last_assistant_message = input.response;
|
|
38
|
+
}
|
|
39
|
+
else if (input.hook_event_name === "errorOccurred") {
|
|
40
|
+
if (input.recoverable !== false || !["model_call", "system"].includes(input.errorContext))
|
|
41
|
+
return null;
|
|
42
|
+
input.hook_event_name = "StopFailure";
|
|
43
|
+
input.error = "agent_error";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (agent === "polytoken") {
|
|
47
|
+
input.hook_event_name ??= input.event ?? env.POLYTOKEN_HOOK_EVENT;
|
|
48
|
+
input.session_id ??= env.POLYTOKEN_SESSION_ID;
|
|
49
|
+
input.cwd ??= env.POLYTOKEN_PROJECT_DIR ?? env.POLYTOKEN_PROJECT_PATH;
|
|
50
|
+
input.turn_id ??= input.prompt_id;
|
|
51
|
+
if (input.hook_event_name === "pre_user_prompt") {
|
|
52
|
+
input.hook_event_name = "UserPromptSubmit";
|
|
53
|
+
input.prompt ??= input.user_prompt ?? input.message?.content;
|
|
54
|
+
}
|
|
55
|
+
else if (input.hook_event_name === "post_model_turn") {
|
|
56
|
+
input.hook_event_name = "Checkpoint";
|
|
57
|
+
input.last_assistant_message ??= input.assistant_message ?? input.response ?? input.text ?? input.message?.content;
|
|
58
|
+
}
|
|
59
|
+
else if (input.hook_event_name === "pre_model_turn")
|
|
60
|
+
input.hook_event_name = "Checkpoint";
|
|
61
|
+
else if (input.hook_event_name === "stop")
|
|
62
|
+
input.hook_event_name = "Stop";
|
|
63
|
+
else
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
else if (agent === "devin") {
|
|
67
|
+
input.cwd ??= env.DEVIN_PROJECT_DIR ?? process.cwd();
|
|
68
|
+
if (["PostToolUse", "PostCompaction"].includes(input.hook_event_name)) {
|
|
69
|
+
input.hook_event_name = "Checkpoint";
|
|
70
|
+
input.last_assistant_message = input.summary ?? `Tool ${String(input.tool_name ?? "result")}: ${JSON.stringify(input.tool_response ?? {})}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return input;
|
|
74
|
+
}
|
|
75
|
+
export function mergeNativeRecoveryHooks(agent, value, command) {
|
|
76
|
+
if (agent === "polytoken") {
|
|
77
|
+
if (!Array.isArray(value))
|
|
78
|
+
throw new Error("Invalid Polytoken hooks: expected an array.");
|
|
79
|
+
const hooks = value.filter(hook => typeof hook?.handler?.bash !== "string" || !hook.handler.bash.includes(OWNER));
|
|
80
|
+
if (command)
|
|
81
|
+
for (const event of ["pre_user_prompt", "pre_model_turn", "post_model_turn", "stop"]) {
|
|
82
|
+
const core = hooks.findIndex(hook => isCore(hook?.handler?.bash));
|
|
83
|
+
hooks.splice(core < 0 ? hooks.length : core, 0, { name: `Lore recovery ${event}`, event, handler: { bash: command } });
|
|
84
|
+
}
|
|
85
|
+
return hooks;
|
|
86
|
+
}
|
|
87
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
88
|
+
throw new Error(`Invalid ${agent} hooks.`);
|
|
89
|
+
const result = structuredClone(value);
|
|
90
|
+
if (result.hooks !== undefined && (!result.hooks || typeof result.hooks !== "object" || Array.isArray(result.hooks)))
|
|
91
|
+
throw new Error(`Invalid ${agent} hooks.`);
|
|
92
|
+
const hooks = result.hooks ?? {};
|
|
93
|
+
const events = agent === "cursor" ? ["beforeSubmitPrompt", "afterAgentResponse", "stop"] : ["userPromptSubmitted", "agentStop", "errorOccurred"];
|
|
94
|
+
for (const event of events) {
|
|
95
|
+
if (hooks[event] !== undefined && !Array.isArray(hooks[event]))
|
|
96
|
+
throw new Error(`Invalid ${agent} ${event} hooks.`);
|
|
97
|
+
const remaining = (hooks[event] ?? []).filter((hook) => !String(agent === "cursor" ? hook.command ?? "" : hook.bash ?? "").includes(OWNER));
|
|
98
|
+
if (command) {
|
|
99
|
+
const core = remaining.findIndex((hook) => isCore(agent === "cursor" ? hook.command : hook.bash));
|
|
100
|
+
remaining.splice(core < 0 ? remaining.length : core, 0, agent === "cursor" ? { command, timeout: 10 } : { type: "command", bash: `LORE_RECOVERY_EVENT=${event} ${command}`, timeoutSec: 10 });
|
|
101
|
+
}
|
|
102
|
+
if (remaining.length)
|
|
103
|
+
hooks[event] = remaining;
|
|
104
|
+
else
|
|
105
|
+
delete hooks[event];
|
|
106
|
+
}
|
|
107
|
+
if (Object.keys(hooks).length) {
|
|
108
|
+
result.hooks = hooks;
|
|
109
|
+
result.version ??= 1;
|
|
110
|
+
}
|
|
111
|
+
else
|
|
112
|
+
delete result.hooks;
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=recovery-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-hooks.js","sourceRoot":"","sources":["../src/recovery-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LorePaths } from "./cli.js";
|
|
2
|
+
import { type RecoveryRun } from "./recovery-state.js";
|
|
3
|
+
export declare function readOwnedJson(path: string, max?: number): Promise<any>;
|
|
4
|
+
export declare function installExternalRecovery(paths: LorePaths, hosts: readonly string[], cwd: string, fallback?: string, start?: boolean): Promise<string[]>;
|
|
5
|
+
export declare function installRecoveryMonitor(home: string, start?: boolean): Promise<void>;
|
|
6
|
+
export declare function disableExternalRecovery(home: string): Promise<void>;
|
|
7
|
+
export declare function pollExternalRecovery(home: string, notify?: (home: string, id: string) => Promise<void>): Promise<void>;
|
|
8
|
+
export declare function runExternalMonitor(home: string): Promise<void>;
|
|
9
|
+
export declare function externalCheckpointCommand(home: string): Promise<void>;
|
|
10
|
+
/** Stop offering the old saved result immediately when the editor starts a new prompt. */
|
|
11
|
+
export declare function invalidateEditorRecovery(home: string, value: unknown): Promise<void>;
|
|
12
|
+
export declare function validateExternalRecovery(home: string, run: RecoveryRun): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=recovery-hosts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-hosts.d.ts","sourceRoot":"","sources":["../src/recovery-hosts.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,OAAO,EAA0E,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAa/H,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAc,GAAG,OAAO,CAAC,GAAG,CAAC,CAOjF;AAMD,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,UAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA0CzJ;AAED,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAYtF;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBzE;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B5H;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBpE;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU3E;AAED,0FAA0F;AAC1F,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAY1F;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAW5F"}
|