@paradow/ledge 0.16.1 → 0.18.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/README.md +2 -0
- package/dist/cli/{attach-5H727FCW.js → attach-I6TTCGNV.js} +12 -7
- package/dist/cli/{bridge-LXMOQN6Q.js → bridge-APNFBPNE.js} +2 -2
- package/dist/cli/chunk-3EIRKAX7.js +165 -0
- package/dist/cli/chunk-3HCID6NW.js +145 -0
- package/dist/cli/{chunk-BNKPXSUY.js → chunk-43D6NMYH.js} +1 -1
- package/dist/cli/{daemon-DKH63BGV.js → chunk-7IQ6FV2F.js} +6117 -6985
- package/dist/cli/{chunk-R5462SQM.js → chunk-7ZAA75HG.js} +2 -1
- package/dist/cli/chunk-BVBX222F.js +117 -0
- package/dist/cli/{chunk-S4ANPQGA.js → chunk-FQZ3IX6E.js} +2 -2
- package/dist/cli/chunk-G6K2NSQS.js +6 -0
- package/dist/cli/{chunk-DEXDXDO4.js → chunk-GXFU4XAX.js} +1 -1
- package/dist/cli/chunk-HP3G2TYJ.js +1772 -0
- package/dist/cli/{chunk-DBSCO3HI.js → chunk-KKNE7BFZ.js} +108 -7
- package/dist/cli/{chunk-MQICEVKR.js → chunk-QQZALYNI.js} +38 -12
- package/dist/cli/{chunk-H36JD4E3.js → chunk-TRTS24PF.js} +23 -5
- package/dist/cli/{chunk-TB47EHML.js → chunk-WCS24ICX.js} +5 -3
- package/dist/cli/{chunk-2H5FJH4Q.js → chunk-WJ6YMZTT.js} +2 -2
- package/dist/cli/chunk-Y5DJ5INP.js +60 -0
- package/dist/cli/{chunk-QJVODYJ5.js → chunk-ZUYOA55W.js} +43 -4
- package/dist/cli/daemon-SKC7VKYQ.js +2240 -0
- package/dist/cli/handover-UXISKYPS.js +16 -0
- package/dist/cli/{hook-LY2YTK5U.js → hook-5UAARBWU.js} +93 -29
- package/dist/cli/index.js +45 -12
- package/dist/cli/launch-T5FJ42XS.js +34 -0
- package/dist/cli/send-NLVR6PL2.js +18 -0
- package/dist/cli/{setup-3N2EOJXS.js → setup-EEIXRAMU.js} +4 -4
- package/dist/cli/{status-ZQSYXILE.js → status-2OCYHOWZ.js} +3 -3
- package/dist/cli/task-AOOWHPMN.js +18 -0
- package/dist/cli/team-TVNSVYWW.js +101 -0
- package/dist/cli/tui-MQLMUUJB.js +4314 -0
- package/dist/cli/{uninstall-W2OMKU3B.js → uninstall-UUN7LIIT.js} +4 -4
- package/dist/cli/{version-6BMBIXHN.js → version-AEN2CRT2.js} +1 -1
- package/dist/cli/who-52MENZTT.js +11 -0
- package/package.json +7 -1
- package/dist/cli/chunk-J4ICZEGP.js +0 -6
- package/dist/cli/chunk-Q5WWH7FG.js +0 -1423
- package/dist/cli/launch-UQEFFPBN.js +0 -27
- package/dist/cli/send-EY63XQXI.js +0 -14
- package/dist/cli/who-VGIMGQNS.js +0 -11
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HANDOVER_USAGE,
|
|
3
|
+
handoverArgs,
|
|
4
|
+
handoverOnClient,
|
|
5
|
+
runHandover
|
|
6
|
+
} from "./chunk-Y5DJ5INP.js";
|
|
7
|
+
import "./chunk-TRTS24PF.js";
|
|
8
|
+
import "./chunk-GXFU4XAX.js";
|
|
9
|
+
import "./chunk-HP3G2TYJ.js";
|
|
10
|
+
import "./chunk-7ZAA75HG.js";
|
|
11
|
+
export {
|
|
12
|
+
HANDOVER_USAGE,
|
|
13
|
+
handoverArgs,
|
|
14
|
+
handoverOnClient,
|
|
15
|
+
runHandover
|
|
16
|
+
};
|
|
@@ -1,35 +1,49 @@
|
|
|
1
|
-
import {
|
|
2
|
-
parseLedgeCommand,
|
|
3
|
-
sendOnClient
|
|
4
|
-
} from "./chunk-QJVODYJ5.js";
|
|
5
|
-
import {
|
|
6
|
-
formatWho
|
|
7
|
-
} from "./chunk-TB47EHML.js";
|
|
8
|
-
import {
|
|
9
|
-
connect,
|
|
10
|
-
sendMessageAndAwaitAck
|
|
11
|
-
} from "./chunk-DEXDXDO4.js";
|
|
12
1
|
import {
|
|
13
2
|
QUESTION_TOOLS,
|
|
14
3
|
gitInfo,
|
|
15
4
|
messageNote,
|
|
16
5
|
readPeers,
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
resolveRoleAddress,
|
|
7
|
+
resolveTarget,
|
|
8
|
+
seatContext,
|
|
9
|
+
teammates
|
|
10
|
+
} from "./chunk-KKNE7BFZ.js";
|
|
11
|
+
import {
|
|
12
|
+
findRole
|
|
13
|
+
} from "./chunk-3HCID6NW.js";
|
|
14
|
+
import {
|
|
15
|
+
parseLedgeCommand,
|
|
16
|
+
readOnClient,
|
|
17
|
+
sendOnClient
|
|
18
|
+
} from "./chunk-ZUYOA55W.js";
|
|
19
|
+
import {
|
|
20
|
+
taskOnClient
|
|
21
|
+
} from "./chunk-BVBX222F.js";
|
|
22
|
+
import {
|
|
23
|
+
handoverOnClient
|
|
24
|
+
} from "./chunk-Y5DJ5INP.js";
|
|
19
25
|
import {
|
|
20
26
|
CODEX_ENV_VAR,
|
|
21
27
|
CODEX_HOOK_VAR,
|
|
22
28
|
codexPlan
|
|
23
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-TRTS24PF.js";
|
|
24
30
|
import {
|
|
25
|
-
|
|
26
|
-
} from "./chunk-
|
|
31
|
+
formatWho
|
|
32
|
+
} from "./chunk-WCS24ICX.js";
|
|
33
|
+
import {
|
|
34
|
+
connect,
|
|
35
|
+
sendMessageAndAwaitAck
|
|
36
|
+
} from "./chunk-GXFU4XAX.js";
|
|
37
|
+
import {
|
|
38
|
+
taskClosed
|
|
39
|
+
} from "./chunk-HP3G2TYJ.js";
|
|
27
40
|
import {
|
|
28
41
|
log
|
|
29
|
-
} from "./chunk-
|
|
30
|
-
import "./chunk-
|
|
42
|
+
} from "./chunk-43D6NMYH.js";
|
|
43
|
+
import "./chunk-7ZAA75HG.js";
|
|
31
44
|
|
|
32
45
|
// src/cli/hook.ts
|
|
46
|
+
import { randomUUID } from "crypto";
|
|
33
47
|
import { readFileSync, openSync, fstatSync, readSync, closeSync } from "fs";
|
|
34
48
|
import { basename, join } from "path";
|
|
35
49
|
var str = (v) => typeof v === "string" ? v : void 0;
|
|
@@ -315,15 +329,32 @@ function mapCursorEvent(eventName, p, at, launched, transcript) {
|
|
|
315
329
|
return null;
|
|
316
330
|
}
|
|
317
331
|
}
|
|
332
|
+
var TASKS_TOLD = 10;
|
|
333
|
+
var TASK_STATE = { open: "ouverte", taken: "prise", done: "termin\xE9e", refused: "refus\xE9e", dropped: "abandonn\xE9e" };
|
|
334
|
+
function tasksContext(tasks) {
|
|
335
|
+
if (!tasks.length) return void 0;
|
|
336
|
+
const shown = tasks.slice(0, TASKS_TOLD);
|
|
337
|
+
return [
|
|
338
|
+
"Tes t\xE2ches en cours (elles sont gard\xE9es par Ledge, pas dans ta conversation) :",
|
|
339
|
+
...shown.map((t) => `- ${t.id} \xB7 ${TASK_STATE[t.state]} \xB7 \xAB ${t.title} \xBB \xB7 confi\xE9e par ${t.giverName}`),
|
|
340
|
+
...tasks.length > shown.length ? [`- et ${tasks.length - shown.length} autre(s) : ledge task list`] : [],
|
|
341
|
+
"Relis-en une avec `ledge task show <id>` avant de reprendre."
|
|
342
|
+
].join("\n");
|
|
343
|
+
}
|
|
318
344
|
function identityContext(s) {
|
|
319
345
|
const where = [`projet ${s.repo ?? s.project}`, ...s.branch ? [`branche ${s.branch}`] : [], ...s.worktree ? [`worktree ${basename(s.cwd) || s.cwd}`] : []].join(", ");
|
|
320
346
|
return [
|
|
321
347
|
`Tu es ${s.name}, ${where} : une session lanc\xE9e par Ledge (${s.tool}). Les autres sessions Ledge te connaissent sous le nom ${s.name}.`,
|
|
322
348
|
"Pour voir les autres sessions (nom, outil, \xE9tat, projet, branche, sujet), lance `ledge who`.",
|
|
323
|
-
s.tool === "claude" ? "Pour \xE9crire \xE0 une autre session Ledge, Claude ou Codex, utilise son nom Ledge (donn\xE9 par `ledge who`) comme adresse SendMessage : Ledge le transmet. `ListAgents` montre les noms internes de Claude, pas les noms Ledge." : "Pour \xE9crire \xE0 une autre session Ledge, lance `ledge send <nom> \"<message>\"` (seul, sans && ni |). Ledge ex\xE9cute lui-m\xEAme `ledge send` et `ledge who` : leur r\xE9sultat t'arrive comme \xAB Command blocked by PreToolUse hook: \u2026 \xBB, c'est la r\xE9ponse, pas une erreur."
|
|
349
|
+
s.tool === "claude" ? "Pour \xE9crire \xE0 une autre session Ledge, Claude ou Codex, utilise son nom Ledge (donn\xE9 par `ledge who`) comme adresse SendMessage : Ledge le transmet. `ListAgents` montre les noms internes de Claude, pas les noms Ledge." : "Pour \xE9crire \xE0 une autre session Ledge, lance `ledge send <nom> \"<message>\"` (seul, sans && ni |). Ledge ex\xE9cute lui-m\xEAme `ledge send`, `ledge read`, `ledge task` et `ledge who` : leur r\xE9sultat t'arrive comme \xAB Command blocked by PreToolUse hook: \u2026 \xBB, c'est la r\xE9ponse, pas une erreur.",
|
|
350
|
+
"Un long message d'une autre session t'arrive en aper\xE7u avec son id : lance `ledge read <id>` pour le lire en entier. Une `<ledge-notice>` te dit qu'un de tes messages n'a pas pu \xEAtre remis.",
|
|
351
|
+
'Un message sert \xE0 pr\xE9venir ; pour confier un travail qui ne doit pas se perdre, lance plut\xF4t `ledge task give <nom> "<titre>" "<d\xE9tail>"` (`ledge task` pour le reste). Une `<ledge-task>` t\'en confie une, ou te dit comment une des tiennes a fini : quand on t\'en confie une, prends-la (`ledge task take <id>`) et termine-la toujours (`ledge task done <id> "<r\xE9sultat>"`, ou `refuse`).',
|
|
352
|
+
...s.seat ? [s.seat] : [],
|
|
353
|
+
...s.relieves ? [`Tu as pris la rel\xE8ve de ${s.relieves.name}, dont le contexte \xE9tait plein : relis son bilan avec \`ledge handover show\`.`] : [],
|
|
354
|
+
...s.tasks ? [tasksContext(s.tasks) ?? ""].filter(Boolean) : []
|
|
324
355
|
].join("\n");
|
|
325
356
|
}
|
|
326
|
-
async function identity(agent, cwd, known, deadline) {
|
|
357
|
+
async function identity(agent, cwd, known, deadline, live = { sessions: [], teams: [] }) {
|
|
327
358
|
const name = known?.name ?? process.env.LEDGE_NAME;
|
|
328
359
|
const dir = known?.cwd ?? cwd;
|
|
329
360
|
if (!name || !dir) return void 0;
|
|
@@ -335,9 +366,23 @@ async function identity(agent, cwd, known, deadline) {
|
|
|
335
366
|
project: known?.project ?? (basename(dir) || dir),
|
|
336
367
|
...known?.repo ?? git?.repo ? { repo: known?.repo ?? git.repo } : {},
|
|
337
368
|
...known?.branch ?? git?.branch ? { branch: known?.branch ?? git.branch } : {},
|
|
338
|
-
...known?.worktree ?? git?.worktree ? { worktree: true } : {}
|
|
369
|
+
...known?.worktree ?? git?.worktree ? { worktree: true } : {},
|
|
370
|
+
...seatOf(known, dir, live)
|
|
339
371
|
};
|
|
340
372
|
}
|
|
373
|
+
function seatOf(known, dir, live) {
|
|
374
|
+
const roleId = known?.role ?? process.env.LEDGE_ROLE;
|
|
375
|
+
if (!roleId) return {};
|
|
376
|
+
let role;
|
|
377
|
+
try {
|
|
378
|
+
role = findRole(roleId, dir);
|
|
379
|
+
} catch {
|
|
380
|
+
role = void 0;
|
|
381
|
+
}
|
|
382
|
+
const team = known?.team ? live.teams.find((t) => t.id === known.team && t.state !== "dissolved") : void 0;
|
|
383
|
+
const seat = seatContext({ ...role ? { role } : {}, roleId, roleLabel: known?.roleLabel, ...team ? { team: { name: team.name, members: teammates(team, live.sessions).filter((m) => m.name !== known?.name) } } : {} });
|
|
384
|
+
return seat ? { seat } : {};
|
|
385
|
+
}
|
|
341
386
|
var SEND_MESSAGE_MS = 1500;
|
|
342
387
|
var deny = (reason) => JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: reason } });
|
|
343
388
|
async function relayMessage(client, from, toolUseId, input, deadline) {
|
|
@@ -347,7 +392,14 @@ async function relayMessage(client, from, toolUseId, input, deadline) {
|
|
|
347
392
|
const snapshot = await client.next("snapshot", left());
|
|
348
393
|
const sender = snapshot.sessions.find((s) => s.id === from);
|
|
349
394
|
if (sender?.source !== "launcher") return void 0;
|
|
350
|
-
|
|
395
|
+
let address = to;
|
|
396
|
+
if (to.startsWith("@")) {
|
|
397
|
+
const teams = sender.team ? (await client.next("teams", left()).catch(() => void 0))?.teams ?? [] : [];
|
|
398
|
+
const role = resolveRoleAddress(to, from, snapshot.sessions, teams);
|
|
399
|
+
if ("reason" in role) return deny(`Ledge n'a pas pu transmettre le message \xE0 ${to} : ${role.reason}`);
|
|
400
|
+
address = role.to;
|
|
401
|
+
}
|
|
402
|
+
const r = resolveTarget(address, snapshot.sessions, readPeers());
|
|
351
403
|
if (r.outcome === "unknown") return void 0;
|
|
352
404
|
if (r.outcome === "refused") return deny(`Ledge n'a pas pu transmettre le message \xE0 ${to} : ${r.reason}`);
|
|
353
405
|
if (r.outcome === "native") {
|
|
@@ -357,9 +409,8 @@ async function relayMessage(client, from, toolUseId, input, deadline) {
|
|
|
357
409
|
return JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow", updatedInput } });
|
|
358
410
|
}
|
|
359
411
|
const tool = r.target.tool;
|
|
360
|
-
if (tool !== "codex" && input.message.length > MESSAGE_MAX) return void 0;
|
|
361
412
|
const summary = str(input.summary);
|
|
362
|
-
const ack = await sendMessageAndAwaitAck(client, { type: "session.message", rid: toolUseId, from, to, text: input.message, ...summary ? { summary } : {}, intercept: true }, left());
|
|
413
|
+
const ack = await sendMessageAndAwaitAck(client, { type: "session.message", rid: toolUseId, from, to: address, text: input.message, ...summary ? { summary } : {}, intercept: true }, left());
|
|
363
414
|
const target = `${to} (${tool})`;
|
|
364
415
|
const reason = ack.outcome === "accepted" ? `Message transmis par Ledge \xE0 ${target} : il le re\xE7oit maintenant.` : ack.outcome === "queued" ? `Message transmis par Ledge \xE0 ${target} : il le recevra d\xE8s qu'il sera libre.` : ack.outcome === "refused" ? `Ledge n'a pas pu transmettre le message \xE0 ${to} : ${ack.reason ?? "raison inconnue"}` : void 0;
|
|
365
416
|
return reason ? deny(reason) : void 0;
|
|
@@ -368,9 +419,10 @@ async function runLedgeCommand(client, cmd, from, deadline) {
|
|
|
368
419
|
const left = () => Math.max(0, deadline - Date.now());
|
|
369
420
|
let line;
|
|
370
421
|
if (cmd.cmd === "who") line = formatWho((await client.next("snapshot", left())).sessions, from);
|
|
371
|
-
else
|
|
372
|
-
|
|
373
|
-
|
|
422
|
+
else if (cmd.cmd === "read") line = (await readOnClient(client, cmd.args, from, left())).line;
|
|
423
|
+
else if (cmd.cmd === "task") line = (await taskOnClient(client, cmd.args, from, left())).line;
|
|
424
|
+
else if (cmd.cmd === "handover") line = (await handoverOnClient(client, cmd.args, from, left())).line;
|
|
425
|
+
else line = (await sendOnClient(client, cmd.args, from, left())).line;
|
|
374
426
|
return deny(line);
|
|
375
427
|
}
|
|
376
428
|
async function runHook(eventName, stdin, opts = {}) {
|
|
@@ -383,8 +435,10 @@ async function runHook(eventName, stdin, opts = {}) {
|
|
|
383
435
|
let mapped = null;
|
|
384
436
|
let identify = false;
|
|
385
437
|
let known;
|
|
438
|
+
let live = { sessions: [], teams: [] };
|
|
386
439
|
let deadline = Date.now() + (opts.timeoutMs ?? 100);
|
|
387
440
|
let relayed;
|
|
441
|
+
let held = [];
|
|
388
442
|
try {
|
|
389
443
|
const payload = JSON.parse(stdin || "{}");
|
|
390
444
|
mapped = agent === "cursor" ? mapCursorHook(eventName, payload, (/* @__PURE__ */ new Date()).toISOString()) : mapHook(agent, eventName, payload, (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -401,7 +455,15 @@ async function runHook(eventName, stdin, opts = {}) {
|
|
|
401
455
|
deadline = Date.now() + timeoutMs;
|
|
402
456
|
const client = await connect({ port: opts.port, timeoutMs });
|
|
403
457
|
client.send({ type: "session.event", id: mapped.id, event: mapped.event, agent: mapped.agent, ...mapped.cwd ? { cwd: mapped.cwd } : {} });
|
|
404
|
-
if (identify)
|
|
458
|
+
if (identify) {
|
|
459
|
+
const snapshot = await client.next("snapshot", Math.max(0, deadline - Date.now())).catch(() => void 0);
|
|
460
|
+
known = snapshot?.sessions.find((s) => s.id === mapped.id);
|
|
461
|
+
const teamList = known?.team ? (await client.next("teams", Math.max(0, deadline - Date.now())).catch(() => void 0))?.teams : void 0;
|
|
462
|
+
live = { sessions: snapshot?.sessions ?? [], teams: teamList ?? [] };
|
|
463
|
+
client.send({ type: "task.cmd", rid: randomUUID(), by: mapped.id, op: "list" });
|
|
464
|
+
const listed = await client.next("task.result", Math.max(0, deadline - Date.now())).catch(() => void 0);
|
|
465
|
+
held = (listed?.tasks ?? []).filter((t) => t.owner === mapped.id && !taskClosed(t));
|
|
466
|
+
}
|
|
405
467
|
if (intercept) relayed = await relayMessage(client, mapped.id, str(payload.tool_use_id), input, deadline);
|
|
406
468
|
if (command) relayed = await runLedgeCommand(client, command, mapped.id, deadline);
|
|
407
469
|
await Promise.race([client.close(), new Promise((r) => setTimeout(r, Math.max(0, deadline - Date.now())))]);
|
|
@@ -410,7 +472,8 @@ async function runHook(eventName, stdin, opts = {}) {
|
|
|
410
472
|
}
|
|
411
473
|
if (relayed) return relayed;
|
|
412
474
|
if (!identify || !mapped) return void 0;
|
|
413
|
-
const
|
|
475
|
+
const found = await identity(agent, mapped.cwd, known, deadline, live);
|
|
476
|
+
const who = found ? { ...found, ...held.length ? { tasks: held } : {}, ...known?.relieves ? { relieves: known.relieves } : {} } : void 0;
|
|
414
477
|
return who ? JSON.stringify({ hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: identityContext(who) } }) : void 0;
|
|
415
478
|
}
|
|
416
479
|
export {
|
|
@@ -424,6 +487,7 @@ export {
|
|
|
424
487
|
mapHook,
|
|
425
488
|
readTranscript,
|
|
426
489
|
runHook,
|
|
490
|
+
tasksContext,
|
|
427
491
|
toolOutput,
|
|
428
492
|
trimInput,
|
|
429
493
|
underCodexDaemon
|
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
|
-
var USAGE = `ledge <claude|codex|cursor> [--name <bot>] [-- agent args] start an agent in a tracked session
|
|
4
|
+
var USAGE = `ledge <claude|codex|cursor> [--name <bot>] [--role <id>] [-- agent args] start an agent in a tracked session (--role: .ledge/roles/<id>.md)
|
|
5
5
|
ledge attach [--read-only] <id> put this terminal on a running session
|
|
6
6
|
ledge daemon run the daemon in the foreground
|
|
7
7
|
ledge hook [codex|cursor] <Event> receive a hook (reads JSON on stdin)
|
|
@@ -10,6 +10,11 @@ ledge uninstall [--purge] remove hooks, servi
|
|
|
10
10
|
ledge status list sessions
|
|
11
11
|
ledge who list the live sessions (name, tool, state, project, branch, topic)
|
|
12
12
|
ledge send <nom> "<message>" [--summary <texte>] write to another Ledge session
|
|
13
|
+
ledge read <id> print a long message whole (the id is in its pointer)
|
|
14
|
+
ledge task <give|list|show|take|done|refuse|pass> \u2026 give another session work, take it, close it (ledge task: details)
|
|
15
|
+
ledge handover "<bilan>" | show the relief brief, when Ledge asks for it; show: read your predecessor's
|
|
16
|
+
ledge team <up|list> \u2026 start a team from a template, list templates, roles and live teams
|
|
17
|
+
ledge tui [--notify bell|osc9|off] follow and answer the sessions in this terminal
|
|
13
18
|
ledge bridge exchange Ledge messages over SSH stdio
|
|
14
19
|
ledge --version print the installed version`;
|
|
15
20
|
async function hookMain(args) {
|
|
@@ -18,7 +23,7 @@ async function hookMain(args) {
|
|
|
18
23
|
try {
|
|
19
24
|
const chunks = [];
|
|
20
25
|
for await (const c of process.stdin) chunks.push(c);
|
|
21
|
-
const { runHook } = await import("./hook-
|
|
26
|
+
const { runHook } = await import("./hook-5UAARBWU.js");
|
|
22
27
|
const out = await runHook(event, Buffer.concat(chunks).toString("utf8"), { tool });
|
|
23
28
|
if (out) process.stdout.write(`${out}
|
|
24
29
|
`);
|
|
@@ -30,7 +35,7 @@ async function main(argv) {
|
|
|
30
35
|
const [cmd, ...rest] = argv;
|
|
31
36
|
switch (cmd) {
|
|
32
37
|
case "daemon": {
|
|
33
|
-
const { startDaemon } = await import("./daemon-
|
|
38
|
+
const { startDaemon } = await import("./daemon-SKC7VKYQ.js");
|
|
34
39
|
await startDaemon();
|
|
35
40
|
await new Promise(() => {
|
|
36
41
|
});
|
|
@@ -38,17 +43,17 @@ async function main(argv) {
|
|
|
38
43
|
}
|
|
39
44
|
case "--version":
|
|
40
45
|
case "version": {
|
|
41
|
-
const { LEDGE_VERSION } = await import("./version-
|
|
46
|
+
const { LEDGE_VERSION } = await import("./version-AEN2CRT2.js");
|
|
42
47
|
console.log(LEDGE_VERSION);
|
|
43
48
|
return 0;
|
|
44
49
|
}
|
|
45
50
|
case "setup": {
|
|
46
|
-
const { runSetup } = await import("./setup-
|
|
51
|
+
const { runSetup } = await import("./setup-EEIXRAMU.js");
|
|
47
52
|
for (const l of await runSetup()) console.log(l);
|
|
48
53
|
return 0;
|
|
49
54
|
}
|
|
50
55
|
case "uninstall": {
|
|
51
|
-
const { runUninstall, uninstallArgs } = await import("./uninstall-
|
|
56
|
+
const { runUninstall, uninstallArgs } = await import("./uninstall-UUN7LIIT.js");
|
|
52
57
|
const args = uninstallArgs(rest);
|
|
53
58
|
if (!args) {
|
|
54
59
|
console.log(USAGE);
|
|
@@ -59,34 +64,62 @@ async function main(argv) {
|
|
|
59
64
|
return r.ok ? 0 : 1;
|
|
60
65
|
}
|
|
61
66
|
case "status": {
|
|
62
|
-
const { printStatus } = await import("./status-
|
|
67
|
+
const { printStatus } = await import("./status-2OCYHOWZ.js");
|
|
63
68
|
console.log(await printStatus());
|
|
64
69
|
return 0;
|
|
65
70
|
}
|
|
66
71
|
case "who": {
|
|
67
|
-
const { printWho } = await import("./who-
|
|
72
|
+
const { printWho } = await import("./who-52MENZTT.js");
|
|
68
73
|
console.log(await printWho());
|
|
69
74
|
return 0;
|
|
70
75
|
}
|
|
71
76
|
case "send": {
|
|
72
|
-
const { sendMessage } = await import("./send-
|
|
77
|
+
const { sendMessage } = await import("./send-NLVR6PL2.js");
|
|
73
78
|
const r = await sendMessage(rest);
|
|
74
79
|
console.log(r.line);
|
|
75
80
|
return r.code;
|
|
76
81
|
}
|
|
82
|
+
case "read": {
|
|
83
|
+
const { readMessage } = await import("./send-NLVR6PL2.js");
|
|
84
|
+
const r = await readMessage(rest);
|
|
85
|
+
console.log(r.line);
|
|
86
|
+
return r.code;
|
|
87
|
+
}
|
|
88
|
+
case "task": {
|
|
89
|
+
const { runTask } = await import("./task-AOOWHPMN.js");
|
|
90
|
+
const r = await runTask(rest);
|
|
91
|
+
console.log(r.line);
|
|
92
|
+
return r.code;
|
|
93
|
+
}
|
|
94
|
+
case "handover": {
|
|
95
|
+
const { runHandover } = await import("./handover-UXISKYPS.js");
|
|
96
|
+
const r = await runHandover(rest);
|
|
97
|
+
console.log(r.line);
|
|
98
|
+
return r.code;
|
|
99
|
+
}
|
|
100
|
+
case "team": {
|
|
101
|
+
const { runTeam } = await import("./team-TVNSVYWW.js");
|
|
102
|
+
const r = await runTeam(rest);
|
|
103
|
+
console.log(r.line);
|
|
104
|
+
return r.code;
|
|
105
|
+
}
|
|
106
|
+
case "tui": {
|
|
107
|
+
const { runTui } = await import("./tui-MQLMUUJB.js");
|
|
108
|
+
return runTui(rest);
|
|
109
|
+
}
|
|
77
110
|
case "bridge": {
|
|
78
|
-
const { bridge } = await import("./bridge-
|
|
111
|
+
const { bridge } = await import("./bridge-APNFBPNE.js");
|
|
79
112
|
await bridge();
|
|
80
113
|
return 0;
|
|
81
114
|
}
|
|
82
115
|
case "claude":
|
|
83
116
|
case "codex":
|
|
84
117
|
case "cursor": {
|
|
85
|
-
const { launch } = await import("./launch-
|
|
118
|
+
const { launch } = await import("./launch-T5FJ42XS.js");
|
|
86
119
|
return launch(cmd, rest);
|
|
87
120
|
}
|
|
88
121
|
case "attach": {
|
|
89
|
-
const { attach } = await import("./attach-
|
|
122
|
+
const { attach } = await import("./attach-I6TTCGNV.js");
|
|
90
123
|
return attach(rest.find((a) => !a.startsWith("--")) ?? "", { readOnly: rest.includes("--read-only") });
|
|
91
124
|
}
|
|
92
125
|
default:
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DaemonError,
|
|
3
|
+
attachEnv,
|
|
4
|
+
createSession,
|
|
5
|
+
ensureDaemon,
|
|
6
|
+
launch,
|
|
7
|
+
parseLaunchArgs,
|
|
8
|
+
roleArgs
|
|
9
|
+
} from "./chunk-QQZALYNI.js";
|
|
10
|
+
import "./chunk-7IQ6FV2F.js";
|
|
11
|
+
import "./chunk-3EIRKAX7.js";
|
|
12
|
+
import "./chunk-OLLQBK6N.js";
|
|
13
|
+
import "./chunk-KKNE7BFZ.js";
|
|
14
|
+
import "./chunk-3HCID6NW.js";
|
|
15
|
+
import {
|
|
16
|
+
agentEnv,
|
|
17
|
+
exitFile
|
|
18
|
+
} from "./chunk-TRTS24PF.js";
|
|
19
|
+
import "./chunk-GXFU4XAX.js";
|
|
20
|
+
import "./chunk-HP3G2TYJ.js";
|
|
21
|
+
import "./chunk-WJ6YMZTT.js";
|
|
22
|
+
import "./chunk-43D6NMYH.js";
|
|
23
|
+
import "./chunk-7ZAA75HG.js";
|
|
24
|
+
export {
|
|
25
|
+
DaemonError,
|
|
26
|
+
agentEnv,
|
|
27
|
+
attachEnv,
|
|
28
|
+
createSession,
|
|
29
|
+
ensureDaemon,
|
|
30
|
+
exitFile,
|
|
31
|
+
launch,
|
|
32
|
+
parseLaunchArgs,
|
|
33
|
+
roleArgs
|
|
34
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseLedgeCommand,
|
|
3
|
+
readMessage,
|
|
4
|
+
readOnClient,
|
|
5
|
+
sendMessage,
|
|
6
|
+
sendOnClient
|
|
7
|
+
} from "./chunk-ZUYOA55W.js";
|
|
8
|
+
import "./chunk-TRTS24PF.js";
|
|
9
|
+
import "./chunk-GXFU4XAX.js";
|
|
10
|
+
import "./chunk-HP3G2TYJ.js";
|
|
11
|
+
import "./chunk-7ZAA75HG.js";
|
|
12
|
+
export {
|
|
13
|
+
parseLedgeCommand,
|
|
14
|
+
readMessage,
|
|
15
|
+
readOnClient,
|
|
16
|
+
sendMessage,
|
|
17
|
+
sendOnClient
|
|
18
|
+
};
|
|
@@ -14,10 +14,10 @@ import {
|
|
|
14
14
|
stopDetachedDaemon,
|
|
15
15
|
systemdUnit,
|
|
16
16
|
writeBin
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-FQZ3IX6E.js";
|
|
18
|
+
import "./chunk-WJ6YMZTT.js";
|
|
19
|
+
import "./chunk-43D6NMYH.js";
|
|
20
|
+
import "./chunk-7ZAA75HG.js";
|
|
21
21
|
export {
|
|
22
22
|
BIN_MARK,
|
|
23
23
|
CLAUDE_EVENTS,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
connect
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-GXFU4XAX.js";
|
|
4
|
+
import "./chunk-HP3G2TYJ.js";
|
|
5
|
+
import "./chunk-7ZAA75HG.js";
|
|
6
6
|
|
|
7
7
|
// src/cli/status.ts
|
|
8
8
|
async function printStatus(opts = {}) {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TASK_USAGE,
|
|
3
|
+
formatTask,
|
|
4
|
+
runTask,
|
|
5
|
+
taskArgs,
|
|
6
|
+
taskOnClient
|
|
7
|
+
} from "./chunk-BVBX222F.js";
|
|
8
|
+
import "./chunk-TRTS24PF.js";
|
|
9
|
+
import "./chunk-GXFU4XAX.js";
|
|
10
|
+
import "./chunk-HP3G2TYJ.js";
|
|
11
|
+
import "./chunk-7ZAA75HG.js";
|
|
12
|
+
export {
|
|
13
|
+
TASK_USAGE,
|
|
14
|
+
formatTask,
|
|
15
|
+
runTask,
|
|
16
|
+
taskArgs,
|
|
17
|
+
taskOnClient
|
|
18
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listDefinitions
|
|
3
|
+
} from "./chunk-3EIRKAX7.js";
|
|
4
|
+
import "./chunk-3HCID6NW.js";
|
|
5
|
+
import {
|
|
6
|
+
connect
|
|
7
|
+
} from "./chunk-GXFU4XAX.js";
|
|
8
|
+
import "./chunk-HP3G2TYJ.js";
|
|
9
|
+
import "./chunk-43D6NMYH.js";
|
|
10
|
+
import "./chunk-7ZAA75HG.js";
|
|
11
|
+
|
|
12
|
+
// src/cli/team.ts
|
|
13
|
+
import { randomUUID } from "crypto";
|
|
14
|
+
import { resolve } from "path";
|
|
15
|
+
var TEAM_USAGE = `ledge team up <mod\xE8le> [--cwd <dossier>] [--name <nom>] lancer une \xE9quipe d'apr\xE8s .ledge/teams/<mod\xE8le>.yaml
|
|
16
|
+
ledge team list [--cwd <dossier>] les mod\xE8les, les r\xF4les et les \xE9quipes en cours`;
|
|
17
|
+
var UP_MS = 6e4;
|
|
18
|
+
var DAEMON_DOWN = "daemon not running (start a session with `ledge claude`, or run `ledge daemon`)";
|
|
19
|
+
function teamArgs(args) {
|
|
20
|
+
const [op, ...rest] = args;
|
|
21
|
+
const positional = [];
|
|
22
|
+
let cwd;
|
|
23
|
+
let name;
|
|
24
|
+
for (let i = 0; i < rest.length; i++) {
|
|
25
|
+
if (rest[i] === "--cwd") {
|
|
26
|
+
cwd = rest[++i];
|
|
27
|
+
if (!cwd) return void 0;
|
|
28
|
+
} else if (rest[i] === "--name") {
|
|
29
|
+
name = rest[++i];
|
|
30
|
+
if (!name) return void 0;
|
|
31
|
+
} else positional.push(rest[i]);
|
|
32
|
+
}
|
|
33
|
+
if (op === "up" && positional.length === 1) return { op, template: positional[0], ...cwd ? { cwd } : {}, ...name ? { name } : {} };
|
|
34
|
+
if (op === "list" && positional.length === 0 && !name) return { op, ...cwd ? { cwd } : {} };
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
var STATE = { active: "active", resting: "au repos", dissolved: "dissoute" };
|
|
38
|
+
function formatTeam(t, sessions) {
|
|
39
|
+
const byId = new Map(sessions.map((s) => [s.id, s]));
|
|
40
|
+
return [`${t.id} ${t.name} ${STATE[t.state]} ${t.cwd}`, ...t.seats.map((seat) => {
|
|
41
|
+
const s = seat.sessionId ? byId.get(seat.sessionId) : void 0;
|
|
42
|
+
return ` @${seat.role.padEnd(12)} ${s ? `${s.name} (${s.tool}, ${s.state})` : "libre"}`;
|
|
43
|
+
})].join("\n");
|
|
44
|
+
}
|
|
45
|
+
async function runTeam(args, opts = {}) {
|
|
46
|
+
const parsed = teamArgs(args);
|
|
47
|
+
if (!parsed) return { line: TEAM_USAGE, code: args.length ? 1 : 0 };
|
|
48
|
+
const cwd = resolve(opts.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
49
|
+
if (parsed.op === "list") {
|
|
50
|
+
const defs = listDefinitions(cwd);
|
|
51
|
+
const lines = [
|
|
52
|
+
"MOD\xC8LES",
|
|
53
|
+
...defs.templates.length ? defs.templates.map((t) => ` ${t.id.padEnd(16)} ${t.name} \xB7 ${t.seats.map((s) => `@${s.role}`).join(" ")} (${t.source})`) : [" aucun (~/.ledge/teams/<id>.yaml)"],
|
|
54
|
+
"",
|
|
55
|
+
"R\xD4LES",
|
|
56
|
+
...defs.roles.length ? defs.roles.map((r) => ` @${r.id.padEnd(15)} ${r.label}${r.tool ? ` \xB7 ${r.tool}` : ""}${r.autonomy && r.autonomy !== "ask" ? ` \xB7 autonomie ${r.autonomy}` : ""} (${r.source})`) : [" aucun (~/.ledge/roles/<id>.md)"],
|
|
57
|
+
...defs.problems.length ? ["", "IGNOR\xC9S", ...defs.problems.map((p) => ` ${p.path} : ${p.reason}`)] : []
|
|
58
|
+
];
|
|
59
|
+
let client2;
|
|
60
|
+
try {
|
|
61
|
+
client2 = await connect({ port: opts.port, timeoutMs: 800 });
|
|
62
|
+
} catch {
|
|
63
|
+
return { line: [...lines, "", "\xC9QUIPES", ` ${DAEMON_DOWN}`].join("\n"), code: 0 };
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const snapshot = await client2.next("snapshot");
|
|
67
|
+
const teams = (await client2.next("teams").catch(() => ({ teams: [] }))).teams.filter((t) => t.state !== "dissolved");
|
|
68
|
+
return { line: [...lines, "", "\xC9QUIPES", ...teams.length ? teams.map((t) => formatTeam(t, snapshot.sessions)) : [" aucune"]].join("\n"), code: 0 };
|
|
69
|
+
} finally {
|
|
70
|
+
await client2.close();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
let client;
|
|
74
|
+
try {
|
|
75
|
+
client = await connect({ port: opts.port, timeoutMs: 1500 });
|
|
76
|
+
} catch {
|
|
77
|
+
return { line: DAEMON_DOWN, code: 1 };
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const rid = randomUUID();
|
|
81
|
+
client.send({ type: "team.launch", rid, cwd, template: parsed.template, ...parsed.name ? { name: parsed.name } : {} });
|
|
82
|
+
const r = await Promise.race([client.next("team.launched", UP_MS), client.next("team.failed", UP_MS)]);
|
|
83
|
+
const snapshot = await client.next("snapshot", 500).catch(() => void 0);
|
|
84
|
+
if (r.type === "team.failed") return { line: `refus\xE9 : ${r.reason}${r.team ? `
|
|
85
|
+
${formatTeam(r.team, snapshot?.sessions ?? [])}` : ""}`, code: 1 };
|
|
86
|
+
client.send({ type: "snapshot.request" });
|
|
87
|
+
const fresh = await client.next("snapshot", 1500).catch(() => snapshot);
|
|
88
|
+
return { line: `\xE9quipe ${r.team.name} lanc\xE9e
|
|
89
|
+
${formatTeam(r.team, fresh?.sessions ?? [])}`, code: 0 };
|
|
90
|
+
} catch (e) {
|
|
91
|
+
return { line: `pas de r\xE9ponse de Ledge : ${e.message}`, code: 1 };
|
|
92
|
+
} finally {
|
|
93
|
+
await client.close();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export {
|
|
97
|
+
TEAM_USAGE,
|
|
98
|
+
formatTeam,
|
|
99
|
+
runTeam,
|
|
100
|
+
teamArgs
|
|
101
|
+
};
|