@paradow/ledge 0.17.0 → 0.19.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 +7 -1
- package/assets/ledge.ico +0 -0
- package/dist/cli/{attach-EYIX7FZN.js → attach-3BKQSEWC.js} +12 -7
- package/dist/cli/{bridge-6UHCD76N.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-JQZHXVIZ.js → chunk-43D6NMYH.js} +1 -1
- package/dist/cli/chunk-4RD7OJ2J.js +6 -0
- package/dist/cli/{chunk-ELLXOV4Q.js → chunk-7ZAA75HG.js} +1 -1
- package/dist/cli/{chunk-5ZCHFGCV.js → chunk-BVBX222F.js} +9 -7
- package/dist/cli/{chunk-OVJL2QTN.js → chunk-FQZ3IX6E.js} +2 -2
- package/dist/cli/{chunk-VVK4I6B5.js → chunk-GXFU4XAX.js} +1 -1
- package/dist/cli/chunk-HP3G2TYJ.js +1772 -0
- package/dist/cli/{chunk-NC5YAEJB.js → chunk-KKNE7BFZ.js} +55 -3
- package/dist/cli/{chunk-36KJUV62.js → chunk-LOOOHYZR.js} +38 -12
- package/dist/cli/{chunk-VE4LGNXX.js → chunk-TRTS24PF.js} +23 -5
- package/dist/cli/{chunk-Q7YNLP66.js → chunk-WCS24ICX.js} +5 -3
- package/dist/cli/{chunk-LAUNHDTX.js → chunk-WJ6YMZTT.js} +2 -2
- package/dist/cli/{daemon-QEJLAIBT.js → chunk-WP77O5LC.js} +6045 -7228
- package/dist/cli/chunk-Y5DJ5INP.js +60 -0
- package/dist/cli/{chunk-AQ25HFBP.js → chunk-ZUYOA55W.js} +5 -4
- package/dist/cli/daemon-66EUIZ3J.js +2240 -0
- package/dist/cli/handover-UXISKYPS.js +16 -0
- package/dist/cli/{hook-AE5HC6AS.js → hook-5UAARBWU.js} +86 -25
- package/dist/cli/index.js +30 -16
- package/dist/cli/launch-YQYCDZ7N.js +34 -0
- package/dist/cli/{send-2OZ3YZRV.js → send-NLVR6PL2.js} +5 -5
- package/dist/cli/{setup-2VM4GCDJ.js → setup-EEIXRAMU.js} +4 -4
- package/dist/cli/{status-3VJAO6UL.js → status-2OCYHOWZ.js} +3 -3
- package/dist/cli/{task-PMKNYP6M.js → task-AOOWHPMN.js} +5 -5
- package/dist/cli/team-TVNSVYWW.js +101 -0
- package/dist/cli/{tui-DWA2EDC2.js → tui-6JY7IS4D.js} +985 -125
- package/dist/cli/{uninstall-AKUWE33D.js → uninstall-UUN7LIIT.js} +4 -4
- package/dist/cli/{version-WOGCIZY3.js → version-XSEI3V2C.js} +1 -1
- package/dist/cli/who-52MENZTT.js +11 -0
- package/package.json +2 -2
- package/dist/cli/chunk-QD27W6W5.js +0 -1474
- package/dist/cli/chunk-V2H7UD2N.js +0 -6
- package/dist/cli/launch-B4G5OFBV.js +0 -27
- package/dist/cli/who-37TNDYVA.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,37 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
QUESTION_TOOLS,
|
|
3
|
+
gitInfo,
|
|
4
|
+
messageNote,
|
|
5
|
+
readPeers,
|
|
6
|
+
resolveRoleAddress,
|
|
7
|
+
resolveTarget,
|
|
8
|
+
seatContext,
|
|
9
|
+
teammates
|
|
10
|
+
} from "./chunk-KKNE7BFZ.js";
|
|
11
|
+
import {
|
|
12
|
+
findRole
|
|
13
|
+
} from "./chunk-3HCID6NW.js";
|
|
1
14
|
import {
|
|
2
15
|
parseLedgeCommand,
|
|
3
16
|
readOnClient,
|
|
4
17
|
sendOnClient
|
|
5
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ZUYOA55W.js";
|
|
6
19
|
import {
|
|
7
20
|
taskOnClient
|
|
8
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-BVBX222F.js";
|
|
22
|
+
import {
|
|
23
|
+
handoverOnClient
|
|
24
|
+
} from "./chunk-Y5DJ5INP.js";
|
|
25
|
+
import {
|
|
26
|
+
CODEX_ENV_VAR,
|
|
27
|
+
CODEX_HOOK_VAR,
|
|
28
|
+
codexPlan
|
|
29
|
+
} from "./chunk-TRTS24PF.js";
|
|
9
30
|
import {
|
|
10
31
|
formatWho
|
|
11
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-WCS24ICX.js";
|
|
12
33
|
import {
|
|
13
34
|
connect,
|
|
14
35
|
sendMessageAndAwaitAck
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import {
|
|
17
|
-
QUESTION_TOOLS,
|
|
18
|
-
gitInfo,
|
|
19
|
-
messageNote,
|
|
20
|
-
readPeers,
|
|
21
|
-
resolveTarget
|
|
22
|
-
} from "./chunk-NC5YAEJB.js";
|
|
36
|
+
} from "./chunk-GXFU4XAX.js";
|
|
23
37
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
codexPlan
|
|
27
|
-
} from "./chunk-VE4LGNXX.js";
|
|
28
|
-
import "./chunk-QD27W6W5.js";
|
|
38
|
+
taskClosed
|
|
39
|
+
} from "./chunk-HP3G2TYJ.js";
|
|
29
40
|
import {
|
|
30
41
|
log
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-
|
|
42
|
+
} from "./chunk-43D6NMYH.js";
|
|
43
|
+
import "./chunk-7ZAA75HG.js";
|
|
33
44
|
|
|
34
45
|
// src/cli/hook.ts
|
|
46
|
+
import { randomUUID } from "crypto";
|
|
35
47
|
import { readFileSync, openSync, fstatSync, readSync, closeSync } from "fs";
|
|
36
48
|
import { basename, join } from "path";
|
|
37
49
|
var str = (v) => typeof v === "string" ? v : void 0;
|
|
@@ -317,6 +329,18 @@ function mapCursorEvent(eventName, p, at, launched, transcript) {
|
|
|
317
329
|
return null;
|
|
318
330
|
}
|
|
319
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
|
+
}
|
|
320
344
|
function identityContext(s) {
|
|
321
345
|
const where = [`projet ${s.repo ?? s.project}`, ...s.branch ? [`branche ${s.branch}`] : [], ...s.worktree ? [`worktree ${basename(s.cwd) || s.cwd}`] : []].join(", ");
|
|
322
346
|
return [
|
|
@@ -324,10 +348,13 @@ function identityContext(s) {
|
|
|
324
348
|
"Pour voir les autres sessions (nom, outil, \xE9tat, projet, branche, sujet), lance `ledge who`.",
|
|
325
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.",
|
|
326
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.",
|
|
327
|
-
'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`).'
|
|
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) : []
|
|
328
355
|
].join("\n");
|
|
329
356
|
}
|
|
330
|
-
async function identity(agent, cwd, known, deadline) {
|
|
357
|
+
async function identity(agent, cwd, known, deadline, live = { sessions: [], teams: [] }) {
|
|
331
358
|
const name = known?.name ?? process.env.LEDGE_NAME;
|
|
332
359
|
const dir = known?.cwd ?? cwd;
|
|
333
360
|
if (!name || !dir) return void 0;
|
|
@@ -339,9 +366,23 @@ async function identity(agent, cwd, known, deadline) {
|
|
|
339
366
|
project: known?.project ?? (basename(dir) || dir),
|
|
340
367
|
...known?.repo ?? git?.repo ? { repo: known?.repo ?? git.repo } : {},
|
|
341
368
|
...known?.branch ?? git?.branch ? { branch: known?.branch ?? git.branch } : {},
|
|
342
|
-
...known?.worktree ?? git?.worktree ? { worktree: true } : {}
|
|
369
|
+
...known?.worktree ?? git?.worktree ? { worktree: true } : {},
|
|
370
|
+
...seatOf(known, dir, live)
|
|
343
371
|
};
|
|
344
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
|
+
}
|
|
345
386
|
var SEND_MESSAGE_MS = 1500;
|
|
346
387
|
var deny = (reason) => JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: reason } });
|
|
347
388
|
async function relayMessage(client, from, toolUseId, input, deadline) {
|
|
@@ -351,7 +392,14 @@ async function relayMessage(client, from, toolUseId, input, deadline) {
|
|
|
351
392
|
const snapshot = await client.next("snapshot", left());
|
|
352
393
|
const sender = snapshot.sessions.find((s) => s.id === from);
|
|
353
394
|
if (sender?.source !== "launcher") return void 0;
|
|
354
|
-
|
|
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());
|
|
355
403
|
if (r.outcome === "unknown") return void 0;
|
|
356
404
|
if (r.outcome === "refused") return deny(`Ledge n'a pas pu transmettre le message \xE0 ${to} : ${r.reason}`);
|
|
357
405
|
if (r.outcome === "native") {
|
|
@@ -362,7 +410,7 @@ async function relayMessage(client, from, toolUseId, input, deadline) {
|
|
|
362
410
|
}
|
|
363
411
|
const tool = r.target.tool;
|
|
364
412
|
const summary = str(input.summary);
|
|
365
|
-
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());
|
|
366
414
|
const target = `${to} (${tool})`;
|
|
367
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;
|
|
368
416
|
return reason ? deny(reason) : void 0;
|
|
@@ -373,6 +421,7 @@ async function runLedgeCommand(client, cmd, from, deadline) {
|
|
|
373
421
|
if (cmd.cmd === "who") line = formatWho((await client.next("snapshot", left())).sessions, from);
|
|
374
422
|
else if (cmd.cmd === "read") line = (await readOnClient(client, cmd.args, from, left())).line;
|
|
375
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;
|
|
376
425
|
else line = (await sendOnClient(client, cmd.args, from, left())).line;
|
|
377
426
|
return deny(line);
|
|
378
427
|
}
|
|
@@ -386,8 +435,10 @@ async function runHook(eventName, stdin, opts = {}) {
|
|
|
386
435
|
let mapped = null;
|
|
387
436
|
let identify = false;
|
|
388
437
|
let known;
|
|
438
|
+
let live = { sessions: [], teams: [] };
|
|
389
439
|
let deadline = Date.now() + (opts.timeoutMs ?? 100);
|
|
390
440
|
let relayed;
|
|
441
|
+
let held = [];
|
|
391
442
|
try {
|
|
392
443
|
const payload = JSON.parse(stdin || "{}");
|
|
393
444
|
mapped = agent === "cursor" ? mapCursorHook(eventName, payload, (/* @__PURE__ */ new Date()).toISOString()) : mapHook(agent, eventName, payload, (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -404,7 +455,15 @@ async function runHook(eventName, stdin, opts = {}) {
|
|
|
404
455
|
deadline = Date.now() + timeoutMs;
|
|
405
456
|
const client = await connect({ port: opts.port, timeoutMs });
|
|
406
457
|
client.send({ type: "session.event", id: mapped.id, event: mapped.event, agent: mapped.agent, ...mapped.cwd ? { cwd: mapped.cwd } : {} });
|
|
407
|
-
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
|
+
}
|
|
408
467
|
if (intercept) relayed = await relayMessage(client, mapped.id, str(payload.tool_use_id), input, deadline);
|
|
409
468
|
if (command) relayed = await runLedgeCommand(client, command, mapped.id, deadline);
|
|
410
469
|
await Promise.race([client.close(), new Promise((r) => setTimeout(r, Math.max(0, deadline - Date.now())))]);
|
|
@@ -413,7 +472,8 @@ async function runHook(eventName, stdin, opts = {}) {
|
|
|
413
472
|
}
|
|
414
473
|
if (relayed) return relayed;
|
|
415
474
|
if (!identify || !mapped) return void 0;
|
|
416
|
-
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;
|
|
417
477
|
return who ? JSON.stringify({ hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: identityContext(who) } }) : void 0;
|
|
418
478
|
}
|
|
419
479
|
export {
|
|
@@ -427,6 +487,7 @@ export {
|
|
|
427
487
|
mapHook,
|
|
428
488
|
readTranscript,
|
|
429
489
|
runHook,
|
|
490
|
+
tasksContext,
|
|
430
491
|
toolOutput,
|
|
431
492
|
trimInput,
|
|
432
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)
|
|
@@ -12,7 +12,9 @@ ledge who list the live sessi
|
|
|
12
12
|
ledge send <nom> "<message>" [--summary <texte>] write to another Ledge session
|
|
13
13
|
ledge read <id> print a long message whole (the id is in its pointer)
|
|
14
14
|
ledge task <give|list|show|take|done|refuse|pass> \u2026 give another session work, take it, close it (ledge task: details)
|
|
15
|
-
ledge
|
|
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] [--here] follow and answer the sessions (in a Ledge tab of Windows Terminal unless --here)
|
|
16
18
|
ledge bridge exchange Ledge messages over SSH stdio
|
|
17
19
|
ledge --version print the installed version`;
|
|
18
20
|
async function hookMain(args) {
|
|
@@ -21,7 +23,7 @@ async function hookMain(args) {
|
|
|
21
23
|
try {
|
|
22
24
|
const chunks = [];
|
|
23
25
|
for await (const c of process.stdin) chunks.push(c);
|
|
24
|
-
const { runHook } = await import("./hook-
|
|
26
|
+
const { runHook } = await import("./hook-5UAARBWU.js");
|
|
25
27
|
const out = await runHook(event, Buffer.concat(chunks).toString("utf8"), { tool });
|
|
26
28
|
if (out) process.stdout.write(`${out}
|
|
27
29
|
`);
|
|
@@ -33,7 +35,7 @@ async function main(argv) {
|
|
|
33
35
|
const [cmd, ...rest] = argv;
|
|
34
36
|
switch (cmd) {
|
|
35
37
|
case "daemon": {
|
|
36
|
-
const { startDaemon } = await import("./daemon-
|
|
38
|
+
const { startDaemon } = await import("./daemon-66EUIZ3J.js");
|
|
37
39
|
await startDaemon();
|
|
38
40
|
await new Promise(() => {
|
|
39
41
|
});
|
|
@@ -41,17 +43,17 @@ async function main(argv) {
|
|
|
41
43
|
}
|
|
42
44
|
case "--version":
|
|
43
45
|
case "version": {
|
|
44
|
-
const { LEDGE_VERSION } = await import("./version-
|
|
46
|
+
const { LEDGE_VERSION } = await import("./version-XSEI3V2C.js");
|
|
45
47
|
console.log(LEDGE_VERSION);
|
|
46
48
|
return 0;
|
|
47
49
|
}
|
|
48
50
|
case "setup": {
|
|
49
|
-
const { runSetup } = await import("./setup-
|
|
51
|
+
const { runSetup } = await import("./setup-EEIXRAMU.js");
|
|
50
52
|
for (const l of await runSetup()) console.log(l);
|
|
51
53
|
return 0;
|
|
52
54
|
}
|
|
53
55
|
case "uninstall": {
|
|
54
|
-
const { runUninstall, uninstallArgs } = await import("./uninstall-
|
|
56
|
+
const { runUninstall, uninstallArgs } = await import("./uninstall-UUN7LIIT.js");
|
|
55
57
|
const args = uninstallArgs(rest);
|
|
56
58
|
if (!args) {
|
|
57
59
|
console.log(USAGE);
|
|
@@ -62,50 +64,62 @@ async function main(argv) {
|
|
|
62
64
|
return r.ok ? 0 : 1;
|
|
63
65
|
}
|
|
64
66
|
case "status": {
|
|
65
|
-
const { printStatus } = await import("./status-
|
|
67
|
+
const { printStatus } = await import("./status-2OCYHOWZ.js");
|
|
66
68
|
console.log(await printStatus());
|
|
67
69
|
return 0;
|
|
68
70
|
}
|
|
69
71
|
case "who": {
|
|
70
|
-
const { printWho } = await import("./who-
|
|
72
|
+
const { printWho } = await import("./who-52MENZTT.js");
|
|
71
73
|
console.log(await printWho());
|
|
72
74
|
return 0;
|
|
73
75
|
}
|
|
74
76
|
case "send": {
|
|
75
|
-
const { sendMessage } = await import("./send-
|
|
77
|
+
const { sendMessage } = await import("./send-NLVR6PL2.js");
|
|
76
78
|
const r = await sendMessage(rest);
|
|
77
79
|
console.log(r.line);
|
|
78
80
|
return r.code;
|
|
79
81
|
}
|
|
80
82
|
case "read": {
|
|
81
|
-
const { readMessage } = await import("./send-
|
|
83
|
+
const { readMessage } = await import("./send-NLVR6PL2.js");
|
|
82
84
|
const r = await readMessage(rest);
|
|
83
85
|
console.log(r.line);
|
|
84
86
|
return r.code;
|
|
85
87
|
}
|
|
86
88
|
case "task": {
|
|
87
|
-
const { runTask } = await import("./task-
|
|
89
|
+
const { runTask } = await import("./task-AOOWHPMN.js");
|
|
88
90
|
const r = await runTask(rest);
|
|
89
91
|
console.log(r.line);
|
|
90
92
|
return r.code;
|
|
91
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
|
+
}
|
|
92
106
|
case "tui": {
|
|
93
|
-
const { runTui } = await import("./tui-
|
|
107
|
+
const { runTui } = await import("./tui-6JY7IS4D.js");
|
|
94
108
|
return runTui(rest);
|
|
95
109
|
}
|
|
96
110
|
case "bridge": {
|
|
97
|
-
const { bridge } = await import("./bridge-
|
|
111
|
+
const { bridge } = await import("./bridge-APNFBPNE.js");
|
|
98
112
|
await bridge();
|
|
99
113
|
return 0;
|
|
100
114
|
}
|
|
101
115
|
case "claude":
|
|
102
116
|
case "codex":
|
|
103
117
|
case "cursor": {
|
|
104
|
-
const { launch } = await import("./launch-
|
|
118
|
+
const { launch } = await import("./launch-YQYCDZ7N.js");
|
|
105
119
|
return launch(cmd, rest);
|
|
106
120
|
}
|
|
107
121
|
case "attach": {
|
|
108
|
-
const { attach } = await import("./attach-
|
|
122
|
+
const { attach } = await import("./attach-3BKQSEWC.js");
|
|
109
123
|
return attach(rest.find((a) => !a.startsWith("--")) ?? "", { readOnly: rest.includes("--read-only") });
|
|
110
124
|
}
|
|
111
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-LOOOHYZR.js";
|
|
10
|
+
import "./chunk-WP77O5LC.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
|
+
};
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
readOnClient,
|
|
5
5
|
sendMessage,
|
|
6
6
|
sendOnClient
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
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
12
|
export {
|
|
13
13
|
parseLedgeCommand,
|
|
14
14
|
readMessage,
|
|
@@ -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 = {}) {
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
runTask,
|
|
5
5
|
taskArgs,
|
|
6
6
|
taskOnClient
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
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
12
|
export {
|
|
13
13
|
TASK_USAGE,
|
|
14
14
|
formatTask,
|
|
@@ -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
|
+
};
|