@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.
Files changed (28) hide show
  1. package/dist/cli/{attach-UWADG6NX.js → attach-3U4A44ZE.js} +22 -9
  2. package/dist/cli/{bridge-53ZTDSST.js → bridge-7JT6P53L.js} +2 -2
  3. package/dist/cli/{chunk-A7YEHYLY.js → chunk-2P2SUT7A.js} +2 -2
  4. package/dist/cli/{chunk-YUSY3E47.js → chunk-5DDBCJX2.js} +1 -1
  5. package/dist/cli/{chunk-VY45MACP.js → chunk-5LVPB3ET.js} +436 -135
  6. package/dist/cli/{chunk-XIO4OIHR.js → chunk-6A7JPTHV.js} +2 -2
  7. package/dist/cli/{chunk-ZNRXLDSH.js → chunk-D3JQV5AA.js} +6 -6
  8. package/dist/cli/{chunk-ZEHTNFPV.js → chunk-FPW7MF5X.js} +2 -2
  9. package/dist/cli/{chunk-FRGNPUDO.js → chunk-IIXALRFM.js} +2 -2
  10. package/dist/cli/{chunk-XXFUYME7.js → chunk-PFDZ6VYG.js} +1 -1
  11. package/dist/cli/{chunk-FGOFRWIB.js → chunk-QBJEUZYW.js} +1 -1
  12. package/dist/cli/chunk-QUUZSAPI.js +6 -0
  13. package/dist/cli/{chunk-X34LPKG7.js → chunk-ULWVO3TH.js} +4 -3
  14. package/dist/cli/{chunk-QAEH5TJB.js → chunk-UWANRALT.js} +93 -4
  15. package/dist/cli/{daemon-LV7V2VP5.js → daemon-KHGAO6BC.js} +3340 -323
  16. package/dist/cli/{hook-OLZ2I4GM.js → hook-R6OWCFAQ.js} +8 -8
  17. package/dist/cli/index.js +11 -11
  18. package/dist/cli/{launch-ZGICGFVU.js → launch-PPTQEWYD.js} +7 -7
  19. package/dist/cli/send-74LTIRSN.js +14 -0
  20. package/dist/cli/{setup-TULNBDFB.js → setup-FPQK3NA7.js} +4 -4
  21. package/dist/cli/{status-LLITXNOW.js → status-QLTB6T3U.js} +3 -3
  22. package/dist/cli/{uninstall-OFSLCP4T.js → uninstall-QC5WEWDH.js} +4 -4
  23. package/dist/cli/{version-BGEWDJNC.js → version-AELAEF6T.js} +1 -1
  24. package/dist/cli/who-5F6CHRA3.js +11 -0
  25. package/package.json +2 -1
  26. package/dist/cli/chunk-DKL4DFNI.js +0 -6
  27. package/dist/cli/send-VV25P46X.js +0 -14
  28. package/dist/cli/who-K6VK7EXV.js +0 -11
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-ZEHTNFPV.js";
3
+ } from "./chunk-FPW7MF5X.js";
4
4
  import {
5
5
  ensureLedgeDir,
6
6
  paths
7
- } from "./chunk-FGOFRWIB.js";
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-XXFUYME7.js";
4
+ } from "./chunk-PFDZ6VYG.js";
5
5
  import {
6
6
  exitFile,
7
7
  spawnSession
8
- } from "./chunk-X34LPKG7.js";
8
+ } from "./chunk-ULWVO3TH.js";
9
9
  import {
10
10
  PROTOCOL_PORT
11
- } from "./chunk-VY45MACP.js";
11
+ } from "./chunk-5LVPB3ET.js";
12
12
  import {
13
13
  realTmux
14
- } from "./chunk-ZEHTNFPV.js";
14
+ } from "./chunk-FPW7MF5X.js";
15
15
  import {
16
16
  log
17
- } from "./chunk-YUSY3E47.js";
17
+ } from "./chunk-5DDBCJX2.js";
18
18
  import {
19
19
  ensureLedgeDir
20
- } from "./chunk-FGOFRWIB.js";
20
+ } from "./chunk-QBJEUZYW.js";
21
21
 
22
22
  // src/cli/launch.ts
23
23
  import { spawn } from "child_process";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  log
3
- } from "./chunk-YUSY3E47.js";
3
+ } from "./chunk-5DDBCJX2.js";
4
4
  import {
5
5
  paths
6
- } from "./chunk-FGOFRWIB.js";
6
+ } from "./chunk-QBJEUZYW.js";
7
7
 
8
8
  // src/tmux.ts
9
9
  import { execFile } from "child_process";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  connect
3
- } from "./chunk-XXFUYME7.js";
3
+ } from "./chunk-PFDZ6VYG.js";
4
4
  import {
5
5
  isArchived
6
- } from "./chunk-VY45MACP.js";
6
+ } from "./chunk-5LVPB3ET.js";
7
7
 
8
8
  // src/cli/who.ts
9
9
  import { basename } from "path";
@@ -4,7 +4,7 @@ import {
4
4
  SUMMARY_MAX,
5
5
  parseServerMessage,
6
6
  readDaemonToken
7
- } from "./chunk-VY45MACP.js";
7
+ } from "./chunk-5LVPB3ET.js";
8
8
 
9
9
  // src/client.ts
10
10
  import WebSocket from "ws";
@@ -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();
@@ -0,0 +1,6 @@
1
+ // src/version.ts
2
+ var LEDGE_VERSION = true ? "0.14.0" : "0.0.0-dev";
3
+
4
+ export {
5
+ LEDGE_VERSION
6
+ };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pickName
3
- } from "./chunk-VY45MACP.js";
3
+ } from "./chunk-5LVPB3ET.js";
4
4
  import {
5
5
  paths
6
- } from "./chunk-FGOFRWIB.js";
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-VY45MACP.js";
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
- if (s.pending?.source === "hook") return s;
291
- if (hooksReportPrompts(s) && lastHookAt && Date.parse(at) - Date.parse(lastHookAt) < HOOK_PRIORITY_MS) return s;
292
- let pending = mergePending(s.pending, pendingFor(ev));
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,