@paradow/ledge 0.12.1 → 0.14.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/cli/{attach-UWADG6NX.js → attach-3U4A44ZE.js} +22 -9
- package/dist/cli/{bridge-53ZTDSST.js → bridge-7JT6P53L.js} +2 -2
- package/dist/cli/{chunk-A7YEHYLY.js → chunk-2P2SUT7A.js} +2 -2
- package/dist/cli/{chunk-YUSY3E47.js → chunk-5DDBCJX2.js} +1 -1
- package/dist/cli/{chunk-VY45MACP.js → chunk-5LVPB3ET.js} +436 -135
- package/dist/cli/{chunk-XIO4OIHR.js → chunk-6A7JPTHV.js} +2 -2
- package/dist/cli/{chunk-ZNRXLDSH.js → chunk-D3JQV5AA.js} +6 -6
- package/dist/cli/{chunk-ZEHTNFPV.js → chunk-FPW7MF5X.js} +2 -2
- package/dist/cli/{chunk-FRGNPUDO.js → chunk-IIXALRFM.js} +2 -2
- package/dist/cli/{chunk-XXFUYME7.js → chunk-PFDZ6VYG.js} +1 -1
- package/dist/cli/{chunk-FGOFRWIB.js → chunk-QBJEUZYW.js} +1 -1
- package/dist/cli/chunk-QUUZSAPI.js +6 -0
- package/dist/cli/{chunk-X34LPKG7.js → chunk-ULWVO3TH.js} +4 -3
- package/dist/cli/{chunk-QAEH5TJB.js → chunk-UWANRALT.js} +93 -4
- package/dist/cli/{daemon-LV7V2VP5.js → daemon-KHGAO6BC.js} +3340 -323
- package/dist/cli/{hook-OLZ2I4GM.js → hook-R6OWCFAQ.js} +8 -8
- package/dist/cli/index.js +11 -11
- package/dist/cli/{launch-ZGICGFVU.js → launch-PPTQEWYD.js} +7 -7
- package/dist/cli/send-74LTIRSN.js +14 -0
- package/dist/cli/{setup-TULNBDFB.js → setup-FPQK3NA7.js} +4 -4
- package/dist/cli/{status-LLITXNOW.js → status-QLTB6T3U.js} +3 -3
- package/dist/cli/{uninstall-OFSLCP4T.js → uninstall-QC5WEWDH.js} +4 -4
- package/dist/cli/{version-BGEWDJNC.js → version-AELAEF6T.js} +1 -1
- package/dist/cli/who-5F6CHRA3.js +11 -0
- package/package.json +2 -1
- package/dist/cli/chunk-DKL4DFNI.js +0 -6
- package/dist/cli/send-VV25P46X.js +0 -14
- package/dist/cli/who-K6VK7EXV.js +0 -11
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
run
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FPW7MF5X.js";
|
|
4
4
|
import {
|
|
5
5
|
ensureLedgeDir,
|
|
6
6
|
paths
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QBJEUZYW.js";
|
|
8
8
|
|
|
9
9
|
// src/cli/setup.ts
|
|
10
10
|
import { readFile as readFile2, writeFile, mkdir, rename, realpath, rm, stat, lstat, readlink, symlink, unlink } from "fs/promises";
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DaemonRefusedError,
|
|
3
3
|
connect
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PFDZ6VYG.js";
|
|
5
5
|
import {
|
|
6
6
|
exitFile,
|
|
7
7
|
spawnSession
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-ULWVO3TH.js";
|
|
9
9
|
import {
|
|
10
10
|
PROTOCOL_PORT
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-5LVPB3ET.js";
|
|
12
12
|
import {
|
|
13
13
|
realTmux
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-FPW7MF5X.js";
|
|
15
15
|
import {
|
|
16
16
|
log
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-5DDBCJX2.js";
|
|
18
18
|
import {
|
|
19
19
|
ensureLedgeDir
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-QBJEUZYW.js";
|
|
21
21
|
|
|
22
22
|
// src/cli/launch.ts
|
|
23
23
|
import { spawn } from "child_process";
|
|
@@ -17,7 +17,7 @@ function ledgeDir() {
|
|
|
17
17
|
}
|
|
18
18
|
function paths() {
|
|
19
19
|
const dir = ledgeDir();
|
|
20
|
-
return { dir, tmuxConf: join(dir, "tmux.conf"), journal: join(dir, "sessions.json"), log: join(dir, "daemon.log"), pid: join(dir, "daemon.pid"), history: join(dir, "history"), machines: join(dir, "machines.json"), projects: join(dir, "projects.json"), island: join(dir, "island.json"), token: join(dir, "token") };
|
|
20
|
+
return { dir, tmuxConf: join(dir, "tmux.conf"), journal: join(dir, "sessions.json"), log: join(dir, "daemon.log"), pid: join(dir, "daemon.pid"), history: join(dir, "history"), machines: join(dir, "machines.json"), projects: join(dir, "projects.json"), island: join(dir, "island.json"), token: join(dir, "token"), mobile: join(dir, "mobile.json"), mobileSession: join(dir, "mobile-session.json"), mobileKey: join(dir, "mobile-key"), devices: join(dir, "devices.json") };
|
|
21
21
|
}
|
|
22
22
|
async function ensureLedgeDir() {
|
|
23
23
|
const p = paths();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pickName
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5LVPB3ET.js";
|
|
4
4
|
import {
|
|
5
5
|
paths
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QBJEUZYW.js";
|
|
7
7
|
|
|
8
8
|
// src/daemon/transcript.ts
|
|
9
9
|
import { closeSync, fstatSync, openSync, readSync } from "fs";
|
|
@@ -126,7 +126,7 @@ function claudeToolAnswered(path, id) {
|
|
|
126
126
|
// src/spawn.ts
|
|
127
127
|
import { basename, join as join2 } from "path";
|
|
128
128
|
import { randomBytes, randomUUID } from "crypto";
|
|
129
|
-
var AGENT_BIN = { claude: "claude", codex: "codex", cursor: "cursor-agent" };
|
|
129
|
+
var AGENT_BIN = { claude: "claude", codex: "codex", cursor: "cursor-agent", omp: "omp" };
|
|
130
130
|
var CODEX_ENV_VAR = "LEDGE_CODEX_SESSION";
|
|
131
131
|
var CODEX_HOOK_VAR = "LEDGE_CODEX_HOOK_SESSION";
|
|
132
132
|
function agentIdArgs(tool, id) {
|
|
@@ -190,6 +190,7 @@ export {
|
|
|
190
190
|
CODEX_ENV_VAR,
|
|
191
191
|
CODEX_HOOK_VAR,
|
|
192
192
|
exitFile,
|
|
193
|
+
PARENT_AGENT_VARS,
|
|
193
194
|
agentEnv,
|
|
194
195
|
spawnSession
|
|
195
196
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cleanTopic,
|
|
3
3
|
sessionTitle
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5LVPB3ET.js";
|
|
5
5
|
|
|
6
6
|
// src/daemon/crossSession.ts
|
|
7
7
|
var FIRST_LINE = /^Another Claude session sent a message:\s*\n/;
|
|
@@ -80,6 +80,70 @@ function notice(text) {
|
|
|
80
80
|
return { kind: "other", text };
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
// src/adapters/types.ts
|
|
84
|
+
var Refusal = class extends Error {
|
|
85
|
+
constructor(message, code) {
|
|
86
|
+
super(message);
|
|
87
|
+
this.code = code;
|
|
88
|
+
this.name = "Refusal";
|
|
89
|
+
}
|
|
90
|
+
code;
|
|
91
|
+
};
|
|
92
|
+
var NO_ALWAYS = 'no "always" option in this dialog, answer in the terminal';
|
|
93
|
+
var NO_NOTE = "no place for a note in this dialog, answer in the terminal";
|
|
94
|
+
var STALE = "the request changed, look again";
|
|
95
|
+
function assertDialogIs(pending, shown) {
|
|
96
|
+
if (shown === null) return;
|
|
97
|
+
const want = pending.kind === "diff" ? "permission" : pending.kind;
|
|
98
|
+
if (shown !== want) throw new Refusal(STALE, "stale");
|
|
99
|
+
}
|
|
100
|
+
var UNCHECKED = "the request on screen cannot be checked, answer in the terminal";
|
|
101
|
+
var COMMAND_TOOLS = /* @__PURE__ */ new Set(["Bash", "shell", "Shell"]);
|
|
102
|
+
var compact = (t) => t.replace(/\s+/g, "");
|
|
103
|
+
function sameQuestion(shown, asked) {
|
|
104
|
+
const screen = compact(shown), want = compact(asked);
|
|
105
|
+
return !want || screen === want || !!screen && (want.startsWith(screen) || screen.startsWith(want));
|
|
106
|
+
}
|
|
107
|
+
var EDGE = 4;
|
|
108
|
+
var WIDE = /[\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\ufe30-\ufe4f\uff00-\uff60\uffe0-\uffe6\u{1f300}-\u{1faff}\u{20000}-\u{3fffd}]/u;
|
|
109
|
+
var columns = (text) => [...text].reduce((n, c) => n + (WIDE.test(c) ? 2 : 1), 0);
|
|
110
|
+
function shownCommand(raw) {
|
|
111
|
+
const lines = raw.map((l) => l.trimEnd());
|
|
112
|
+
while (lines.length && !lines.at(-1).trim()) lines.pop();
|
|
113
|
+
while (lines.length && !lines[0].trim()) lines.shift();
|
|
114
|
+
return { lines: lines.map((l) => l.trim()), ends: lines.map(columns) };
|
|
115
|
+
}
|
|
116
|
+
function commandMismatch({ lines, ends }, asked, width) {
|
|
117
|
+
if (!lines.length || lines.at(-1).endsWith("\u2026") || lines.length > 1 && !width) return UNCHECKED;
|
|
118
|
+
const edge = (width ?? 0) - EDGE;
|
|
119
|
+
const a = asked.trim();
|
|
120
|
+
let at = 0;
|
|
121
|
+
for (let i = 0; i < lines.length; i++) {
|
|
122
|
+
if (!a.startsWith(lines[i], at)) return STALE;
|
|
123
|
+
at += lines[i].length;
|
|
124
|
+
if (i === lines.length - 1) break;
|
|
125
|
+
if (ends[i] + 1 + columns(lines[i + 1].split(/\s/)[0]) <= edge) {
|
|
126
|
+
const nl = /^[ \t]*\n[ \t]*/.exec(a.slice(at));
|
|
127
|
+
if (!nl) return STALE;
|
|
128
|
+
at += nl[0].length;
|
|
129
|
+
} else if (a[at] === " ") at++;
|
|
130
|
+
else if (ends[i] < edge) return STALE;
|
|
131
|
+
}
|
|
132
|
+
return at === a.length ? null : STALE;
|
|
133
|
+
}
|
|
134
|
+
function dialogMismatch(shown, pending, width) {
|
|
135
|
+
if (!shown) return UNCHECKED;
|
|
136
|
+
if (shown.kind !== (pending.kind === "diff" ? "permission" : pending.kind)) return STALE;
|
|
137
|
+
if (pending.kind === "question") return sameQuestion(shown.text, pending.text) ? null : STALE;
|
|
138
|
+
if (pending.source === "pane") return shown.text === pending.text ? null : STALE;
|
|
139
|
+
if (pending.tool !== void 0 && COMMAND_TOOLS.has(pending.tool)) return shown.command ? commandMismatch(shown.command, pending.text, width) : UNCHECKED;
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
function bottomLines(pane, n = 5) {
|
|
143
|
+
return pane.split("\n").filter((l) => l.trim() !== "").slice(-n).join("\n");
|
|
144
|
+
}
|
|
145
|
+
var flatten = (text) => text.replace(/\s*[\r\n]+\s*/g, " ").trim();
|
|
146
|
+
|
|
83
147
|
// src/daemon/state.ts
|
|
84
148
|
var HOOK_PRIORITY_MS = 2e3;
|
|
85
149
|
var hooksReportPrompts = (s) => s.tool === "claude";
|
|
@@ -101,6 +165,9 @@ function pendingFor(ev) {
|
|
|
101
165
|
if (ev.name === "Notification" && ev.kind === "permission") {
|
|
102
166
|
return { kind: "permission", text: ev.text ?? "", source: "hook" };
|
|
103
167
|
}
|
|
168
|
+
if (ev.name === "NativeRequest") {
|
|
169
|
+
return { kind: "question", text: ev.text ?? "", ...ev.options?.length ? { options: ev.options } : {}, ...ev.questions ? { questions: ev.questions } : {}, ...ev.requestId ? { requestId: ev.requestId } : {}, source: "rpc", tool: "omp" };
|
|
170
|
+
}
|
|
104
171
|
if (ev.name === "PanePrompt") {
|
|
105
172
|
return { kind: ev.kind ?? "permission", text: ev.text ?? "", ...ev.body ? { body: ev.body } : {}, options: ev.options, ...details(ev), source: "pane" };
|
|
106
173
|
}
|
|
@@ -287,14 +354,26 @@ function reduceEvent(s, ev) {
|
|
|
287
354
|
return { ...s, state: rest, pending: void 0, lastHookAt: at, lastActivityAt: at };
|
|
288
355
|
}
|
|
289
356
|
case "PanePrompt": {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
357
|
+
const incoming = pendingFor(ev);
|
|
358
|
+
const moved = s.pending?.source === "hook" && s.pending.kind === "question" && incoming.kind === "question" && !sameQuestion(incoming.text, s.pending.text);
|
|
359
|
+
if (s.pending?.source === "hook" && !moved) return s;
|
|
360
|
+
if (!moved && hooksReportPrompts(s) && lastHookAt && Date.parse(at) - Date.parse(lastHookAt) < HOOK_PRIORITY_MS) return s;
|
|
361
|
+
let pending = moved ? { ...incoming, ...s.pending.helperId ? { helperId: s.pending.helperId } : {} } : mergePending(s.pending, incoming);
|
|
293
362
|
if (pending.kind === "plan" && !pending.body && s.tool === "codex" && s.lastReply) pending = { ...pending, body: s.lastReply.text };
|
|
294
363
|
if (s.pending && samePending(s.pending, pending)) return s;
|
|
295
364
|
const state = pending.kind === "question" ? "waiting_input" : "waiting_permission";
|
|
296
365
|
return { ...s, state, pending, lastActivityAt: at };
|
|
297
366
|
}
|
|
367
|
+
case "QueueUpdate": {
|
|
368
|
+
const { queue: _q, ...rest } = s;
|
|
369
|
+
return ev.queue?.length ? { ...rest, queue: ev.queue } : s.queue ? rest : s;
|
|
370
|
+
}
|
|
371
|
+
case "AgentMessage":
|
|
372
|
+
return s.lastActivityAt === at ? s : { ...s, lastActivityAt: at };
|
|
373
|
+
case "NativeRequest": {
|
|
374
|
+
if (s.pending) return s;
|
|
375
|
+
return { ...s, state: "waiting_input", pending: pendingFor(ev), lastActivityAt: at };
|
|
376
|
+
}
|
|
298
377
|
case "SessionStart":
|
|
299
378
|
case "UserPromptSubmit":
|
|
300
379
|
case "PreToolUse":
|
|
@@ -302,6 +381,7 @@ function reduceEvent(s, ev) {
|
|
|
302
381
|
case "Notification": {
|
|
303
382
|
const notice2 = ev.name === "UserPromptSubmit" && !!ev.text && !!crossSessionNotices(ev.text);
|
|
304
383
|
if (ev.name === "UserPromptSubmit" && ev.text && !s.topic && !notice2 && !crossSession(ev.text)) s = withTopic(s, ev.text, "prompt");
|
|
384
|
+
if (s.pending?.source === "rpc" && ev.name === "PreToolUse") return { ...s, lastHookAt: at, lastActivityAt: at };
|
|
305
385
|
const incoming = pendingFor(ev);
|
|
306
386
|
if (incoming) {
|
|
307
387
|
if (ev.name === "Notification" && s.pending) return { ...s, lastHookAt: at, lastActivityAt: at };
|
|
@@ -409,6 +489,15 @@ export {
|
|
|
409
489
|
formatLedgeMessage,
|
|
410
490
|
ledgeMessages,
|
|
411
491
|
crossSessionNotices,
|
|
492
|
+
Refusal,
|
|
493
|
+
NO_ALWAYS,
|
|
494
|
+
NO_NOTE,
|
|
495
|
+
STALE,
|
|
496
|
+
assertDialogIs,
|
|
497
|
+
shownCommand,
|
|
498
|
+
dialogMismatch,
|
|
499
|
+
bottomLines,
|
|
500
|
+
flatten,
|
|
412
501
|
QUESTION_TOOLS,
|
|
413
502
|
pendingTool,
|
|
414
503
|
answeredBy,
|