@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.
Files changed (40) hide show
  1. package/README.md +2 -0
  2. package/dist/cli/{attach-5H727FCW.js → attach-I6TTCGNV.js} +12 -7
  3. package/dist/cli/{bridge-LXMOQN6Q.js → bridge-APNFBPNE.js} +2 -2
  4. package/dist/cli/chunk-3EIRKAX7.js +165 -0
  5. package/dist/cli/chunk-3HCID6NW.js +145 -0
  6. package/dist/cli/{chunk-BNKPXSUY.js → chunk-43D6NMYH.js} +1 -1
  7. package/dist/cli/{daemon-DKH63BGV.js → chunk-7IQ6FV2F.js} +6117 -6985
  8. package/dist/cli/{chunk-R5462SQM.js → chunk-7ZAA75HG.js} +2 -1
  9. package/dist/cli/chunk-BVBX222F.js +117 -0
  10. package/dist/cli/{chunk-S4ANPQGA.js → chunk-FQZ3IX6E.js} +2 -2
  11. package/dist/cli/chunk-G6K2NSQS.js +6 -0
  12. package/dist/cli/{chunk-DEXDXDO4.js → chunk-GXFU4XAX.js} +1 -1
  13. package/dist/cli/chunk-HP3G2TYJ.js +1772 -0
  14. package/dist/cli/{chunk-DBSCO3HI.js → chunk-KKNE7BFZ.js} +108 -7
  15. package/dist/cli/{chunk-MQICEVKR.js → chunk-QQZALYNI.js} +38 -12
  16. package/dist/cli/{chunk-H36JD4E3.js → chunk-TRTS24PF.js} +23 -5
  17. package/dist/cli/{chunk-TB47EHML.js → chunk-WCS24ICX.js} +5 -3
  18. package/dist/cli/{chunk-2H5FJH4Q.js → chunk-WJ6YMZTT.js} +2 -2
  19. package/dist/cli/chunk-Y5DJ5INP.js +60 -0
  20. package/dist/cli/{chunk-QJVODYJ5.js → chunk-ZUYOA55W.js} +43 -4
  21. package/dist/cli/daemon-SKC7VKYQ.js +2240 -0
  22. package/dist/cli/handover-UXISKYPS.js +16 -0
  23. package/dist/cli/{hook-LY2YTK5U.js → hook-5UAARBWU.js} +93 -29
  24. package/dist/cli/index.js +45 -12
  25. package/dist/cli/launch-T5FJ42XS.js +34 -0
  26. package/dist/cli/send-NLVR6PL2.js +18 -0
  27. package/dist/cli/{setup-3N2EOJXS.js → setup-EEIXRAMU.js} +4 -4
  28. package/dist/cli/{status-ZQSYXILE.js → status-2OCYHOWZ.js} +3 -3
  29. package/dist/cli/task-AOOWHPMN.js +18 -0
  30. package/dist/cli/team-TVNSVYWW.js +101 -0
  31. package/dist/cli/tui-MQLMUUJB.js +4314 -0
  32. package/dist/cli/{uninstall-W2OMKU3B.js → uninstall-UUN7LIIT.js} +4 -4
  33. package/dist/cli/{version-6BMBIXHN.js → version-AEN2CRT2.js} +1 -1
  34. package/dist/cli/who-52MENZTT.js +11 -0
  35. package/package.json +7 -1
  36. package/dist/cli/chunk-J4ICZEGP.js +0 -6
  37. package/dist/cli/chunk-Q5WWH7FG.js +0 -1423
  38. package/dist/cli/launch-UQEFFPBN.js +0 -27
  39. package/dist/cli/send-EY63XQXI.js +0 -14
  40. 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
- resolveTarget
18
- } from "./chunk-DBSCO3HI.js";
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-H36JD4E3.js";
29
+ } from "./chunk-TRTS24PF.js";
24
30
  import {
25
- MESSAGE_MAX
26
- } from "./chunk-Q5WWH7FG.js";
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-BNKPXSUY.js";
30
- import "./chunk-R5462SQM.js";
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
- const r = resolveTarget(to, snapshot.sessions, readPeers());
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
- line = (await sendOnClient(client, cmd.args, from, left())).line;
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) known = (await client.next("snapshot", Math.max(0, deadline - Date.now())).catch(() => void 0))?.sessions.find((s) => s.id === mapped.id);
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 who = await identity(agent, mapped.cwd, known, deadline);
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-LY2YTK5U.js");
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-DKH63BGV.js");
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-6BMBIXHN.js");
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-3N2EOJXS.js");
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-W2OMKU3B.js");
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-ZQSYXILE.js");
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-VGIMGQNS.js");
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-EY63XQXI.js");
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-LXMOQN6Q.js");
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-UQEFFPBN.js");
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-5H727FCW.js");
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-S4ANPQGA.js";
18
- import "./chunk-2H5FJH4Q.js";
19
- import "./chunk-BNKPXSUY.js";
20
- import "./chunk-R5462SQM.js";
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-DEXDXDO4.js";
4
- import "./chunk-Q5WWH7FG.js";
5
- import "./chunk-R5462SQM.js";
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
+ };