@paradow/ledge 0.13.0 → 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-PJHKOS4N.js → attach-3U4A44ZE.js} +7 -7
  2. package/dist/cli/{bridge-VQZCDSQE.js → bridge-7JT6P53L.js} +2 -2
  3. package/dist/cli/{chunk-FXI2EE52.js → chunk-2P2SUT7A.js} +2 -2
  4. package/dist/cli/{chunk-YUSY3E47.js → chunk-5DDBCJX2.js} +1 -1
  5. package/dist/cli/{chunk-PPRB4XIX.js → chunk-5LVPB3ET.js} +392 -141
  6. package/dist/cli/{chunk-XIO4OIHR.js → chunk-6A7JPTHV.js} +2 -2
  7. package/dist/cli/{chunk-ZSKCV73V.js → chunk-D3JQV5AA.js} +6 -6
  8. package/dist/cli/{chunk-ZEHTNFPV.js → chunk-FPW7MF5X.js} +2 -2
  9. package/dist/cli/{chunk-7XZNRFWJ.js → chunk-IIXALRFM.js} +2 -2
  10. package/dist/cli/{chunk-SVVQ5KPJ.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-5XFBRTKO.js → chunk-ULWVO3TH.js} +2 -2
  14. package/dist/cli/{chunk-IOASI5FF.js → chunk-UWANRALT.js} +79 -4
  15. package/dist/cli/{daemon-ZUDRXUCP.js → daemon-KHGAO6BC.js} +2123 -187
  16. package/dist/cli/{hook-KKJLIOOM.js → hook-R6OWCFAQ.js} +8 -8
  17. package/dist/cli/index.js +11 -11
  18. package/dist/cli/{launch-4CBL5ZRR.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-R7IOK5KL.js → status-QLTB6T3U.js} +3 -3
  22. package/dist/cli/{uninstall-OFSLCP4T.js → uninstall-QC5WEWDH.js} +4 -4
  23. package/dist/cli/{version-JOFQUAE4.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-LMQADKT7.js +0 -6
  27. package/dist/cli/send-6EGRHCRO.js +0 -14
  28. package/dist/cli/who-NVF6ZMSP.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-SVVQ5KPJ.js";
4
+ } from "./chunk-PFDZ6VYG.js";
5
5
  import {
6
6
  exitFile,
7
7
  spawnSession
8
- } from "./chunk-5XFBRTKO.js";
8
+ } from "./chunk-ULWVO3TH.js";
9
9
  import {
10
10
  PROTOCOL_PORT
11
- } from "./chunk-PPRB4XIX.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-SVVQ5KPJ.js";
3
+ } from "./chunk-PFDZ6VYG.js";
4
4
  import {
5
5
  isArchived
6
- } from "./chunk-PPRB4XIX.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-PPRB4XIX.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-PPRB4XIX.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";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cleanTopic,
3
3
  sessionTitle
4
- } from "./chunk-PPRB4XIX.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";
@@ -290,9 +354,11 @@ function reduceEvent(s, ev) {
290
354
  return { ...s, state: rest, pending: void 0, lastHookAt: at, lastActivityAt: at };
291
355
  }
292
356
  case "PanePrompt": {
293
- if (s.pending?.source === "hook") return s;
294
- if (hooksReportPrompts(s) && lastHookAt && Date.parse(at) - Date.parse(lastHookAt) < HOOK_PRIORITY_MS) return s;
295
- 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);
296
362
  if (pending.kind === "plan" && !pending.body && s.tool === "codex" && s.lastReply) pending = { ...pending, body: s.lastReply.text };
297
363
  if (s.pending && samePending(s.pending, pending)) return s;
298
364
  const state = pending.kind === "question" ? "waiting_input" : "waiting_permission";
@@ -423,6 +489,15 @@ export {
423
489
  formatLedgeMessage,
424
490
  ledgeMessages,
425
491
  crossSessionNotices,
492
+ Refusal,
493
+ NO_ALWAYS,
494
+ NO_NOTE,
495
+ STALE,
496
+ assertDialogIs,
497
+ shownCommand,
498
+ dialogMismatch,
499
+ bottomLines,
500
+ flatten,
426
501
  QUESTION_TOOLS,
427
502
  pendingTool,
428
503
  answeredBy,