@paradow/ledge 0.34.0 → 0.35.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 (36) hide show
  1. package/dist/cli/index.js +39003 -39
  2. package/dist/cli/{chunk-IWY7DSSO.js → reduceWorker.js} +749 -1188
  3. package/package.json +4 -1
  4. package/dist/cli/action-K42H5BDA.js +0 -27
  5. package/dist/cli/attach-KEE4A5YP.js +0 -87
  6. package/dist/cli/bridge-X327AZY4.js +0 -70
  7. package/dist/cli/chunk-25RVT5MR.js +0 -623
  8. package/dist/cli/chunk-3OJCWJAA.js +0 -144
  9. package/dist/cli/chunk-4OYVM4MT.js +0 -49
  10. package/dist/cli/chunk-4TCSADFR.js +0 -252
  11. package/dist/cli/chunk-53ISXX2R.js +0 -39
  12. package/dist/cli/chunk-54KF5RBY.js +0 -17
  13. package/dist/cli/chunk-7NHQGP6J.js +0 -95
  14. package/dist/cli/chunk-G7XPEVCG.js +0 -118
  15. package/dist/cli/chunk-KPDTYX7F.js +0 -60
  16. package/dist/cli/chunk-OLLQBK6N.js +0 -41
  17. package/dist/cli/chunk-RPH773TY.js +0 -6
  18. package/dist/cli/chunk-RX5CJ7YH.js +0 -43
  19. package/dist/cli/chunk-T547FLQN.js +0 -128
  20. package/dist/cli/chunk-U67V476Y.js +0 -35
  21. package/dist/cli/chunk-UJ2WBGLW.js +0 -305
  22. package/dist/cli/chunk-ULOMKEB6.js +0 -85
  23. package/dist/cli/chunk-V4XKKL6K.js +0 -205
  24. package/dist/cli/daemon-RO43S3S5.js +0 -11449
  25. package/dist/cli/decide-KZFYL3HY.js +0 -59
  26. package/dist/cli/handover-BWNMI2RA.js +0 -17
  27. package/dist/cli/hook-ZLWXI5EQ.js +0 -473
  28. package/dist/cli/launch-GCX7TXOH.js +0 -28
  29. package/dist/cli/send-SXZAPVRH.js +0 -19
  30. package/dist/cli/setup-TJ32FMVJ.js +0 -38
  31. package/dist/cli/status-YDVRES4E.js +0 -28
  32. package/dist/cli/task-TUSOVJK7.js +0 -19
  33. package/dist/cli/tui-TCVIRZCQ.js +0 -19348
  34. package/dist/cli/uninstall-QO7YMSLA.js +0 -162
  35. package/dist/cli/version-BAYSYWFP.js +0 -7
  36. package/dist/cli/who-6AZYSP7T.js +0 -12
@@ -1,144 +0,0 @@
1
- import {
2
- CODEX_HOOK_VAR
3
- } from "./chunk-4TCSADFR.js";
4
- import {
5
- connect,
6
- sendMessageAndAwaitAck
7
- } from "./chunk-7NHQGP6J.js";
8
-
9
- // src/cli/send.ts
10
- import { randomUUID } from "crypto";
11
- var USAGE = 'ledge send <nom> "<message>" [--summary <texte>] write to another Ledge session';
12
- var SEND_MS = 4e3;
13
- function sendUsage(args) {
14
- const positional = [];
15
- let summary;
16
- for (let i = 0; i < args.length; i++) {
17
- if (args[i] === "--summary") {
18
- summary = args[++i];
19
- if (summary === void 0) return void 0;
20
- } else positional.push(args[i]);
21
- }
22
- const [to, text] = positional;
23
- if (positional.length !== 2 || !to || !text) return void 0;
24
- return { to, text, ...summary ? { summary } : {} };
25
- }
26
- async function sendOnClient(client, args, from, ms) {
27
- const parsed = sendUsage(args);
28
- if (!parsed) return { line: USAGE, code: 1 };
29
- const { to, text, summary } = parsed;
30
- let sent = false;
31
- try {
32
- const pending = sendMessageAndAwaitAck(client, { type: "session.message", rid: randomUUID(), from, to, text, ...summary ? { summary } : {} }, ms);
33
- sent = true;
34
- const ack = await pending;
35
- if (ack.outcome === "accepted") return { line: `remis \xE0 ${to}`, code: 0 };
36
- if (ack.outcome === "queued") return { line: `${to} est occup\xE9 : il le recevra d\xE8s qu'il sera libre`, code: 0 };
37
- return { line: `refus\xE9 : ${ack.reason ?? "raison inconnue"}`, code: 1 };
38
- } catch (e) {
39
- return { line: sent ? "pas de r\xE9ponse de Ledge : le message est peut-\xEAtre d\xE9j\xE0 parti" : `refus\xE9 : ${e.message}`, code: 1 };
40
- }
41
- }
42
- async function sendMessage(args, opts = {}) {
43
- if (!sendUsage(args)) return { line: USAGE, code: 1 };
44
- const env = opts.env ?? process.env;
45
- const from = opts.from ?? (env[CODEX_HOOK_VAR] || env.LEDGE_SESSION);
46
- if (!from) return { line: "ledge send ne marche que dans une session lanc\xE9e par Ledge", code: 1 };
47
- const deadline = Date.now() + (opts.timeoutMs ?? SEND_MS);
48
- const left = () => Math.max(0, deadline - Date.now());
49
- let client;
50
- try {
51
- client = await connect({ port: opts.port, timeoutMs: left() });
52
- } catch {
53
- return { line: "daemon not running (start a session with `ledge claude`, or run `ledge daemon`)", code: 1 };
54
- }
55
- try {
56
- return await sendOnClient(client, args, from, left());
57
- } finally {
58
- await client.close();
59
- }
60
- }
61
- var READ_USAGE = "ledge read <id> print a long message whole (its id is in the pointer you received)";
62
- var MAIL_ID = /^m[0-9a-f]{6,40}$/;
63
- async function readOnClient(client, args, by, ms) {
64
- const [id] = args;
65
- if (args.length !== 1 || !id || !MAIL_ID.test(id)) return { line: READ_USAGE, code: 1 };
66
- try {
67
- client.send({ type: "message.read", id, by });
68
- const body = await client.next("message.body", ms);
69
- if (body.text === void 0) return { line: `introuvable : ${body.reason ?? "raison inconnue"}`, code: 1 };
70
- return { line: `De ${body.from} \xE0 ${body.to}, ${body.at} :
71
- ${body.text}`, code: 0 };
72
- } catch (e) {
73
- return { line: `pas de r\xE9ponse de Ledge : ${e.message}`, code: 1 };
74
- }
75
- }
76
- async function readMessage(args, opts = {}) {
77
- if (args.length !== 1 || !MAIL_ID.test(args[0])) return { line: READ_USAGE, code: 1 };
78
- const env = opts.env ?? process.env;
79
- const by = env[CODEX_HOOK_VAR] || env.LEDGE_SESSION;
80
- if (!by) return { line: "ledge read ne marche que dans une session lanc\xE9e par Ledge", code: 1 };
81
- const deadline = Date.now() + (opts.timeoutMs ?? SEND_MS);
82
- const left = () => Math.max(0, deadline - Date.now());
83
- let client;
84
- try {
85
- client = await connect({ port: opts.port, timeoutMs: left() });
86
- } catch {
87
- return { line: "daemon not running (start a session with `ledge claude`, or run `ledge daemon`)", code: 1 };
88
- }
89
- try {
90
- return await readOnClient(client, args, by, left());
91
- } finally {
92
- await client.close();
93
- }
94
- }
95
- function parseLedgeCommand(command) {
96
- command = command.replace(/[\r\n\s]+$/, "");
97
- const words = [];
98
- let word = "";
99
- let inWord = false;
100
- let quote;
101
- for (let i = 0; i < command.length; i++) {
102
- const c = command[i];
103
- if (quote === "'") {
104
- if (c === "'") quote = void 0;
105
- else word += c;
106
- continue;
107
- }
108
- if (quote === '"') {
109
- if (c === '"') quote = void 0;
110
- else if (c === "$" || c === "`") return void 0;
111
- else if (c === "\\" && '"\\$`'.includes(command[i + 1] ?? "")) word += command[++i];
112
- else word += c;
113
- continue;
114
- }
115
- if (c === "\n" || c === "\r") return void 0;
116
- if (c === " " || c === " ") {
117
- if (inWord) words.push(word);
118
- word = "";
119
- inWord = false;
120
- continue;
121
- }
122
- if (";&|<>()$`\\*?[~{".includes(c) || c === "#" && !inWord) return void 0;
123
- inWord = true;
124
- if (c === '"' || c === "'") quote = c;
125
- else word += c;
126
- }
127
- if (quote) return void 0;
128
- if (inWord) words.push(word);
129
- if (words[0] !== "ledge") return void 0;
130
- if (words[1] === "who" && words.length === 2) return { cmd: "who" };
131
- if (words[1] === "send") return { cmd: "send", args: words.slice(2) };
132
- if (words[1] === "read") return { cmd: "read", args: words.slice(2) };
133
- if (words[1] === "task") return { cmd: "task", args: words.slice(2) };
134
- if (words[1] === "handover") return { cmd: "handover", args: words.slice(2) };
135
- return void 0;
136
- }
137
-
138
- export {
139
- sendOnClient,
140
- sendMessage,
141
- readOnClient,
142
- readMessage,
143
- parseLedgeCommand
144
- };
@@ -1,49 +0,0 @@
1
- // src/imageInfo.ts
2
- var ok = (mime, width, height) => width > 0 && height > 0 ? { mime, width, height } : null;
3
- function jpeg(b) {
4
- let i = 2;
5
- while (i + 4 <= b.length) {
6
- if (b[i] !== 255) {
7
- i++;
8
- continue;
9
- }
10
- const m = b[i + 1];
11
- if (m === 255) {
12
- i++;
13
- continue;
14
- }
15
- if (m === 216 || m === 1 || m >= 208 && m <= 215) {
16
- i += 2;
17
- continue;
18
- }
19
- const len = b.readUInt16BE(i + 2);
20
- if (m >= 192 && m <= 207 && m !== 196 && m !== 200 && m !== 204) return i + 9 <= b.length ? ok("image/jpeg", b.readUInt16BE(i + 7), b.readUInt16BE(i + 5)) : null;
21
- i += 2 + len;
22
- }
23
- return null;
24
- }
25
- function webp(b) {
26
- const kind = b.toString("latin1", 12, 16);
27
- if (kind === "VP8X") return b.length >= 30 ? ok("image/webp", b.readUIntLE(24, 3) + 1, b.readUIntLE(27, 3) + 1) : null;
28
- if (kind === "VP8L") {
29
- if (b.length < 25 || b[20] !== 47) return null;
30
- const bits = b.readUInt32LE(21);
31
- return ok("image/webp", (bits & 16383) + 1, (bits >>> 14 & 16383) + 1);
32
- }
33
- if (kind === "VP8 ") return b.length >= 30 && b[23] === 157 && b[24] === 1 && b[25] === 42 ? ok("image/webp", b.readUInt16LE(26) & 16383, b.readUInt16LE(28) & 16383) : null;
34
- return null;
35
- }
36
- function imageInfo(b) {
37
- try {
38
- if (b.length >= 24 && b.readUInt32BE(0) === 2303741511 && b.readUInt32BE(4) === 218765834 && b.toString("latin1", 12, 16) === "IHDR") return ok("image/png", b.readUInt32BE(16), b.readUInt32BE(20));
39
- if (b.length >= 10 && (b.toString("latin1", 0, 6) === "GIF87a" || b.toString("latin1", 0, 6) === "GIF89a")) return ok("image/gif", b.readUInt16LE(6), b.readUInt16LE(8));
40
- if (b.length >= 4 && b[0] === 255 && b[1] === 216) return jpeg(b);
41
- if (b.length >= 16 && b.toString("latin1", 0, 4) === "RIFF" && b.toString("latin1", 8, 12) === "WEBP") return webp(b);
42
- } catch {
43
- }
44
- return null;
45
- }
46
-
47
- export {
48
- imageInfo
49
- };
@@ -1,252 +0,0 @@
1
- import {
2
- NAMES,
3
- SESSION_KEY_VAR,
4
- pickName,
5
- sessionKey
6
- } from "./chunk-IWY7DSSO.js";
7
- import {
8
- paths
9
- } from "./chunk-53ISXX2R.js";
10
-
11
- // src/daemon/transcript.ts
12
- import { appendFileSync, closeSync, fstatSync, openSync, readFileSync, readSync, statSync } from "fs";
13
- import { homedir } from "os";
14
- import { basename, join } from "path";
15
-
16
- // src/names.ts
17
- var ledgeShaped = (n, own) => n === own || NAMES.includes(n.replace(/-\d+$/, ""));
18
- function ledgeTitleRest(title, own) {
19
- if (ledgeShaped(title, own)) return "";
20
- const i = title.startsWith(`${own} - `) ? own.length : title.indexOf(" - ");
21
- return i > 0 && ledgeShaped(title.slice(0, i), own) ? title.slice(i + 3).trim() : void 0;
22
- }
23
-
24
- // src/daemon/transcript.ts
25
- var TAIL_BYTES = 512 * 1024;
26
- function tailLines(path, bytes = TAIL_BYTES) {
27
- let fd;
28
- try {
29
- fd = openSync(path, "r");
30
- } catch {
31
- return [];
32
- }
33
- try {
34
- const size = fstatSync(fd).size;
35
- const start = Math.max(0, size - bytes);
36
- const buf = Buffer.alloc(size - start);
37
- readSync(fd, buf, 0, buf.length, start);
38
- const text = buf.toString("utf8");
39
- const lines = text.split("\n");
40
- if (start > 0) lines.shift();
41
- if (!text.endsWith("\n")) lines.pop();
42
- return lines.filter((l) => l.trim());
43
- } finally {
44
- closeSync(fd);
45
- }
46
- }
47
- var texts = (blocks, kind) => (Array.isArray(blocks) ? blocks : []).filter((b) => b?.type === kind && typeof b.text === "string").map((b) => b.text.trim()).filter(Boolean).join("\n\n");
48
- function agentMessages(path, opts = {}) {
49
- const out = [];
50
- for (const line of tailLines(path, opts.bytes ?? TAIL_BYTES)) {
51
- let e;
52
- try {
53
- e = JSON.parse(line);
54
- } catch {
55
- continue;
56
- }
57
- const at = typeof e.timestamp === "string" ? e.timestamp : void 0;
58
- if (!at) continue;
59
- if (e.type === "assistant" && (opts.sidechain || e.isSidechain !== true)) {
60
- const text = texts(e.message?.content, "text");
61
- if (text && typeof e.uuid === "string") out.push({ id: e.uuid, at, text });
62
- continue;
63
- }
64
- if (e.type === "event_msg") {
65
- const p = e.payload;
66
- const item = p?.type === "item_completed" ? p.item : void 0;
67
- if (item?.type !== "AgentMessage" || typeof item.id !== "string") continue;
68
- const text = texts(item.content, "Text");
69
- if (text) out.push({ id: item.id, at, text });
70
- }
71
- }
72
- return out;
73
- }
74
- function codexPlan(path, turnId) {
75
- let plan;
76
- for (const line of tailLines(path)) {
77
- let e;
78
- try {
79
- e = JSON.parse(line);
80
- } catch {
81
- continue;
82
- }
83
- const p = e.payload;
84
- if (e.type === "event_msg" && p?.type === "item_completed" && p.turn_id === turnId && p.item?.type === "Plan" && typeof p.item.text === "string") plan = p.item.text.trim() || plan;
85
- }
86
- return plan;
87
- }
88
- var CLAUDE_DIR_MAX = 200;
89
- function claudeTranscriptPath(cwd, id, env = process.env) {
90
- const dir = cwd.replace(/[^a-zA-Z0-9]/g, "-");
91
- if (dir.length > CLAUDE_DIR_MAX) return void 0;
92
- return join(env.CLAUDE_CONFIG_DIR || join(env.HOME || homedir(), ".claude"), "projects", dir, `${id}.jsonl`);
93
- }
94
- function claudePlan(path) {
95
- let plan;
96
- for (const line of tailLines(path)) {
97
- let e;
98
- try {
99
- e = JSON.parse(line);
100
- } catch {
101
- continue;
102
- }
103
- if (e.isSidechain === true || !Array.isArray(e.message?.content)) continue;
104
- for (const b of e.message.content) {
105
- if (e.type === "assistant" && b?.type === "tool_use" && b.name === "ExitPlanMode" && typeof b.id === "string" && typeof b.input?.plan === "string" && b.input.plan.trim()) plan = { id: b.id, text: b.input.plan.trim() };
106
- else if (e.type === "user" && b?.type === "tool_result" && plan && b.tool_use_id === plan.id) plan = void 0;
107
- }
108
- }
109
- return plan?.text;
110
- }
111
- function claudeCalls(path) {
112
- const calls = [];
113
- for (const line of tailLines(path)) {
114
- let e;
115
- try {
116
- e = JSON.parse(line);
117
- } catch {
118
- continue;
119
- }
120
- if (e.isSidechain === true || !Array.isArray(e.message?.content)) continue;
121
- for (const b of e.message.content) {
122
- if (e.type === "assistant" && b?.type === "tool_use" && typeof b.id === "string" && typeof b.name === "string") calls.push({ id: b.id, name: b.name, answered: false });
123
- else if (e.type === "user" && b?.type === "tool_result") {
124
- const c = calls.find((c2) => c2.id === b.tool_use_id);
125
- if (c) c.answered = true;
126
- }
127
- }
128
- }
129
- return calls;
130
- }
131
- function claudeOpenCall(path, tool) {
132
- const last = claudeCalls(path).filter((c) => c.name === tool).at(-1);
133
- return last && !last.answered ? last.id : void 0;
134
- }
135
- function claudeToolAnswered(path, id) {
136
- return claudeCalls(path).some((c) => c.id === id && c.answered);
137
- }
138
- var LABEL_MAX = 80;
139
- function resumeLabel(name, topic) {
140
- const label = `${name} - ${topic}`.replace(/\s+/g, " ").trim();
141
- return label.length > LABEL_MAX ? `${label.slice(0, LABEL_MAX - 1)}\u2026` : label;
142
- }
143
- function lastTitle(lines) {
144
- let last;
145
- for (const line of lines) {
146
- if (!line.includes('"custom-title"')) continue;
147
- try {
148
- const e = JSON.parse(line);
149
- if (e.type === "custom-title" && typeof e.customTitle === "string") last = { customTitle: e.customTitle, ledge: e.ledge };
150
- } catch {
151
- }
152
- }
153
- return last;
154
- }
155
- var ledgeOwned = (t, name) => t.ledge === true || t.customTitle.startsWith(`${name} - `) || ledgeTitleRest(t.customTitle, name) === "";
156
- function labelTranscript(path, name, label) {
157
- try {
158
- const last = lastTitle(tailLines(path)) ?? (statSync(path).size > TAIL_BYTES ? lastTitle(readFileSync(path, "utf8").split("\n")) : void 0);
159
- if (last && (last.customTitle === label || !ledgeOwned(last, name))) return false;
160
- const fd = openSync(path, "r");
161
- let lead = "";
162
- try {
163
- const size = fstatSync(fd).size;
164
- if (size > 0) {
165
- const b = Buffer.alloc(1);
166
- readSync(fd, b, 0, 1, size - 1);
167
- if (b[0] !== 10) lead = "\n";
168
- }
169
- } finally {
170
- closeSync(fd);
171
- }
172
- appendFileSync(path, `${lead}${JSON.stringify({ type: "custom-title", customTitle: label, sessionId: basename(path, ".jsonl"), ledge: true })}
173
- `);
174
- return true;
175
- } catch (e) {
176
- return e instanceof Error ? e : new Error(String(e));
177
- }
178
- }
179
-
180
- // src/spawn.ts
181
- import { basename as basename2, join as join2 } from "path";
182
- import { randomBytes, randomUUID } from "crypto";
183
- var AGENT_BIN = { claude: "claude", codex: "codex", cursor: "cursor-agent", omp: "omp" };
184
- var CODEX_ENV_VAR = "LEDGE_CODEX_SESSION";
185
- var CODEX_HOOK_VAR = "LEDGE_CODEX_HOOK_SESSION";
186
- function agentIdArgs(tool, id) {
187
- if (tool !== "codex") return [];
188
- const key = sessionKey(id);
189
- return ["-c", `shell_environment_policy.set.${CODEX_HOOK_VAR}="${id}"`, ...key ? ["-c", `shell_environment_policy.set.${SESSION_KEY_VAR}="${key}"`] : []];
190
- }
191
- var CLAUDE_OWN_SESSION = /^(--resume|-r|--continue|-c|--session-id|--fork-session)(=|$)/;
192
- function claudeSessionId(tool, args) {
193
- return tool === "claude" && !args.some((a) => CLAUDE_OWN_SESSION.test(a)) ? randomUUID() : void 0;
194
- }
195
- function exitFile(id) {
196
- return join2(paths().dir, `exit-${id}`);
197
- }
198
- var PARENT_AGENT_VARS = [
199
- "CLAUDECODE",
200
- "CLAUDE_CODE_CHILD_SESSION",
201
- "CLAUDE_CODE_SESSION_ID",
202
- "CLAUDE_CODE_SESSION_ATTENDED",
203
- "CLAUDE_CODE_ENTRYPOINT",
204
- "CLAUDE_CODE_EXECPATH",
205
- "CLAUDE_CODE_MESSAGING_SOCKET",
206
- "CLAUDE_CODE_MESSAGING_TOKEN",
207
- "CLAUDE_PID",
208
- "CLAUDE_EFFORT"
209
- ];
210
- var PARENT_AGENT = new Set(PARENT_AGENT_VARS);
211
- function agentEnv(base, extra) {
212
- const env = {};
213
- for (const [k, v] of Object.entries(base)) if (v !== void 0 && k !== "TMUX" && !k.startsWith("TMUX_") && !PARENT_AGENT.has(k)) env[k] = v;
214
- return { ...env, ...extra };
215
- }
216
- async function spawnSession(opts) {
217
- const now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
218
- const takenIds = new Set(opts.taken.ids);
219
- let id = opts.id;
220
- if (id === void 0) do
221
- id = randomBytes(2).toString("hex");
222
- while (takenIds.has(id));
223
- const name = pickName(opts.taken.names, opts.name);
224
- const project = basename2(opts.cwd) || opts.cwd;
225
- const tmuxSession = `ledge-${id}`;
226
- const agentSessionId = opts.command ? void 0 : claudeSessionId(opts.tool, opts.args);
227
- const agent = opts.command ?? [AGENT_BIN[opts.tool], ...agentIdArgs(opts.tool, id), ...agentSessionId ? ["--session-id", agentSessionId] : [], ...opts.args];
228
- const env = opts.env ?? process.env;
229
- const transcriptPath = agentSessionId ? claudeTranscriptPath(opts.cwd, agentSessionId, env) : void 0;
230
- const command = opts.recordExit ? ["sh", "-c", '"$@"; echo $? > "$0"', exitFile(id), ...agent] : agent;
231
- const key = sessionKey(id);
232
- await opts.tmux.newSession({ name: tmuxSession, cwd: opts.cwd, env: agentEnv(env, { LEDGE_SESSION: id, ...key ? { [SESSION_KEY_VAR]: key } : {}, LEDGE_NAME: name, ...opts.tool === "codex" ? { [CODEX_ENV_VAR]: id } : {} }), unset: PARENT_AGENT_VARS, command });
233
- const at = now();
234
- return { id, name, tool: opts.tool, cwd: opts.cwd, project, title: `${name} \xB7 ${project}`, tmuxSession, state: "starting", helpers: [], startedAt: at, lastActivityAt: at, source: "launcher", ...agentSessionId ? { agentSessionId } : {}, ...transcriptPath ? { transcriptPath } : {} };
235
- }
236
-
237
- export {
238
- ledgeTitleRest,
239
- agentMessages,
240
- codexPlan,
241
- claudePlan,
242
- claudeOpenCall,
243
- claudeToolAnswered,
244
- resumeLabel,
245
- labelTranscript,
246
- CODEX_ENV_VAR,
247
- CODEX_HOOK_VAR,
248
- exitFile,
249
- PARENT_AGENT_VARS,
250
- agentEnv,
251
- spawnSession
252
- };
@@ -1,39 +0,0 @@
1
- // src/paths.ts
2
- import { homedir } from "os";
3
- import { join } from "path";
4
- import { mkdir, writeFile, readFile } from "fs/promises";
5
- var TITLE_LINES = `set -g set-titles on
6
- set -g set-titles-string "#{@ledge_title}"
7
- `;
8
- var TMUX_CONF = `set -g status off
9
- set -g mouse on
10
- set -g default-terminal "tmux-256color"
11
- set -sg escape-time 10
12
- set -g history-limit 20000
13
- set -g remain-on-exit off
14
- ${TITLE_LINES}`;
15
- function ledgeDir() {
16
- return process.env.LEDGE_HOME ?? join(homedir(), ".ledge");
17
- }
18
- function paths() {
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"), mail: join(dir, "mail.json"), tasks: join(dir, "tasks.json"), 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"), revocations: join(dir, "revocations.json"), attachments: join(dir, "attachments") };
21
- }
22
- async function ensureLedgeDir() {
23
- const p = paths();
24
- await mkdir(p.dir, { recursive: true });
25
- let conf = null;
26
- try {
27
- conf = await readFile(p.tmuxConf, "utf8");
28
- } catch {
29
- }
30
- if (conf === null) await writeFile(p.tmuxConf, TMUX_CONF);
31
- else if (!conf.includes("set-titles")) await writeFile(p.tmuxConf, `${conf.trimEnd()}
32
- ${TITLE_LINES}`);
33
- }
34
-
35
- export {
36
- ledgeDir,
37
- paths,
38
- ensureLedgeDir
39
- };
@@ -1,17 +0,0 @@
1
- import {
2
- paths
3
- } from "./chunk-53ISXX2R.js";
4
-
5
- // src/log.ts
6
- import { appendFileSync } from "fs";
7
- function log(line) {
8
- try {
9
- appendFileSync(paths().log, `${(/* @__PURE__ */ new Date()).toISOString()} | ${line}
10
- `);
11
- } catch {
12
- }
13
- }
14
-
15
- export {
16
- log
17
- };
@@ -1,95 +0,0 @@
1
- import {
2
- MESSAGE_MAX,
3
- PROTOCOL_PORT,
4
- SUMMARY_MAX,
5
- parseServerMessage,
6
- readDaemonToken
7
- } from "./chunk-IWY7DSSO.js";
8
-
9
- // src/client.ts
10
- import WebSocket from "ws";
11
- async function sendMessageAndAwaitAck(client, msg, timeoutMs) {
12
- if (msg.text.length > MESSAGE_MAX) return { type: "message.ack", rid: msg.rid, outcome: "refused", reason: `message trop long (${msg.text.length} caract\xE8res, ${MESSAGE_MAX} au plus)` };
13
- client.send(msg.summary && msg.summary.length > SUMMARY_MAX ? { ...msg, summary: msg.summary.slice(0, SUMMARY_MAX) } : msg);
14
- return client.next("message.ack", timeoutMs);
15
- }
16
- var DaemonRefusedError = class extends Error {
17
- };
18
- function connect(opts = {}) {
19
- const port = opts.port ?? PROTOCOL_PORT;
20
- const host = opts.host ?? "127.0.0.1";
21
- let token;
22
- try {
23
- token = opts.token === void 0 ? readDaemonToken() : opts.token;
24
- } catch {
25
- token = null;
26
- }
27
- const ws = new WebSocket(`ws://${host}:${port}`, token ? { headers: { authorization: `Bearer ${token}` } } : {});
28
- const queue = [];
29
- const MAX_QUEUED = 100;
30
- const waiters = [];
31
- ws.on("message", (data) => {
32
- let msg;
33
- try {
34
- msg = parseServerMessage(JSON.parse(String(data)));
35
- } catch {
36
- return;
37
- }
38
- const i = waiters.findIndex((w) => w.type === msg.type);
39
- if (i >= 0) waiters.splice(i, 1)[0].resolve(msg);
40
- else {
41
- queue.push(msg);
42
- if (queue.length > MAX_QUEUED) queue.shift();
43
- }
44
- });
45
- const client = {
46
- send: (msg) => ws.send(JSON.stringify(msg)),
47
- next(type, timeoutMs = 1500) {
48
- const i = queue.findIndex((m) => m.type === type);
49
- if (i >= 0) return Promise.resolve(queue.splice(i, 1)[0]);
50
- return new Promise((resolve, reject) => {
51
- const w = { type, resolve: (m) => {
52
- clearTimeout(t);
53
- resolve(m);
54
- } };
55
- const t = setTimeout(() => {
56
- waiters.splice(waiters.indexOf(w), 1);
57
- reject(new Error(`timeout waiting for ${type}`));
58
- }, timeoutMs);
59
- waiters.push(w);
60
- });
61
- },
62
- close: () => new Promise((res) => {
63
- if (ws.readyState === WebSocket.CLOSED) return res();
64
- ws.once("close", () => res());
65
- ws.close();
66
- })
67
- };
68
- return new Promise((resolve, reject) => {
69
- const t = setTimeout(() => {
70
- ws.terminate();
71
- reject(new Error("connect timeout"));
72
- }, opts.timeoutMs ?? 1e3);
73
- ws.once("open", () => {
74
- clearTimeout(t);
75
- resolve(client);
76
- });
77
- let settled = false;
78
- ws.once("open", () => {
79
- settled = true;
80
- });
81
- ws.on("error", (e) => {
82
- if (!settled) {
83
- settled = true;
84
- clearTimeout(t);
85
- reject(/Unexpected server response: 401/.test(e.message) ? new DaemonRefusedError("daemon refused the token") : e);
86
- }
87
- });
88
- });
89
- }
90
-
91
- export {
92
- sendMessageAndAwaitAck,
93
- DaemonRefusedError,
94
- connect
95
- };