@paradow/ledge 0.17.0 → 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 (38) hide show
  1. package/dist/cli/{attach-EYIX7FZN.js → attach-I6TTCGNV.js} +12 -7
  2. package/dist/cli/{bridge-6UHCD76N.js → bridge-APNFBPNE.js} +2 -2
  3. package/dist/cli/chunk-3EIRKAX7.js +165 -0
  4. package/dist/cli/chunk-3HCID6NW.js +145 -0
  5. package/dist/cli/{chunk-JQZHXVIZ.js → chunk-43D6NMYH.js} +1 -1
  6. package/dist/cli/{daemon-QEJLAIBT.js → chunk-7IQ6FV2F.js} +6044 -7227
  7. package/dist/cli/{chunk-ELLXOV4Q.js → chunk-7ZAA75HG.js} +1 -1
  8. package/dist/cli/{chunk-5ZCHFGCV.js → chunk-BVBX222F.js} +9 -7
  9. package/dist/cli/{chunk-OVJL2QTN.js → chunk-FQZ3IX6E.js} +2 -2
  10. package/dist/cli/chunk-G6K2NSQS.js +6 -0
  11. package/dist/cli/{chunk-VVK4I6B5.js → chunk-GXFU4XAX.js} +1 -1
  12. package/dist/cli/chunk-HP3G2TYJ.js +1772 -0
  13. package/dist/cli/{chunk-NC5YAEJB.js → chunk-KKNE7BFZ.js} +55 -3
  14. package/dist/cli/{chunk-36KJUV62.js → chunk-QQZALYNI.js} +38 -12
  15. package/dist/cli/{chunk-VE4LGNXX.js → chunk-TRTS24PF.js} +23 -5
  16. package/dist/cli/{chunk-Q7YNLP66.js → chunk-WCS24ICX.js} +5 -3
  17. package/dist/cli/{chunk-LAUNHDTX.js → chunk-WJ6YMZTT.js} +2 -2
  18. package/dist/cli/chunk-Y5DJ5INP.js +60 -0
  19. package/dist/cli/{chunk-AQ25HFBP.js → chunk-ZUYOA55W.js} +5 -4
  20. package/dist/cli/daemon-SKC7VKYQ.js +2240 -0
  21. package/dist/cli/handover-UXISKYPS.js +16 -0
  22. package/dist/cli/{hook-AE5HC6AS.js → hook-5UAARBWU.js} +86 -25
  23. package/dist/cli/index.js +29 -15
  24. package/dist/cli/launch-T5FJ42XS.js +34 -0
  25. package/dist/cli/{send-2OZ3YZRV.js → send-NLVR6PL2.js} +5 -5
  26. package/dist/cli/{setup-2VM4GCDJ.js → setup-EEIXRAMU.js} +4 -4
  27. package/dist/cli/{status-3VJAO6UL.js → status-2OCYHOWZ.js} +3 -3
  28. package/dist/cli/{task-PMKNYP6M.js → task-AOOWHPMN.js} +5 -5
  29. package/dist/cli/team-TVNSVYWW.js +101 -0
  30. package/dist/cli/{tui-DWA2EDC2.js → tui-MQLMUUJB.js} +866 -113
  31. package/dist/cli/{uninstall-AKUWE33D.js → uninstall-UUN7LIIT.js} +4 -4
  32. package/dist/cli/{version-WOGCIZY3.js → version-AEN2CRT2.js} +1 -1
  33. package/dist/cli/who-52MENZTT.js +11 -0
  34. package/package.json +1 -1
  35. package/dist/cli/chunk-QD27W6W5.js +0 -1474
  36. package/dist/cli/chunk-V2H7UD2N.js +0 -6
  37. package/dist/cli/launch-B4G5OFBV.js +0 -27
  38. 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-AQ25HFBP.js";
18
+ } from "./chunk-ZUYOA55W.js";
6
19
  import {
7
20
  taskOnClient
8
- } from "./chunk-5ZCHFGCV.js";
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-Q7YNLP66.js";
32
+ } from "./chunk-WCS24ICX.js";
12
33
  import {
13
34
  connect,
14
35
  sendMessageAndAwaitAck
15
- } from "./chunk-VVK4I6B5.js";
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
- CODEX_ENV_VAR,
25
- CODEX_HOOK_VAR,
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-JQZHXVIZ.js";
32
- import "./chunk-ELLXOV4Q.js";
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
- 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());
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) 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
+ }
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 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;
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,6 +12,8 @@ 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 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
15
17
  ledge tui [--notify bell|osc9|off] follow and answer the sessions in this terminal
16
18
  ledge bridge exchange Ledge messages over SSH stdio
17
19
  ledge --version print the installed version`;
@@ -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-AE5HC6AS.js");
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-QEJLAIBT.js");
38
+ const { startDaemon } = await import("./daemon-SKC7VKYQ.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-WOGCIZY3.js");
46
+ const { LEDGE_VERSION } = await import("./version-AEN2CRT2.js");
45
47
  console.log(LEDGE_VERSION);
46
48
  return 0;
47
49
  }
48
50
  case "setup": {
49
- const { runSetup } = await import("./setup-2VM4GCDJ.js");
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-AKUWE33D.js");
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-3VJAO6UL.js");
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-37TNDYVA.js");
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-2OZ3YZRV.js");
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-2OZ3YZRV.js");
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-PMKNYP6M.js");
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-DWA2EDC2.js");
107
+ const { runTui } = await import("./tui-MQLMUUJB.js");
94
108
  return runTui(rest);
95
109
  }
96
110
  case "bridge": {
97
- const { bridge } = await import("./bridge-6UHCD76N.js");
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-B4G5OFBV.js");
118
+ const { launch } = await import("./launch-T5FJ42XS.js");
105
119
  return launch(cmd, rest);
106
120
  }
107
121
  case "attach": {
108
- const { attach } = await import("./attach-EYIX7FZN.js");
122
+ const { attach } = await import("./attach-I6TTCGNV.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-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
+ };
@@ -4,11 +4,11 @@ import {
4
4
  readOnClient,
5
5
  sendMessage,
6
6
  sendOnClient
7
- } from "./chunk-AQ25HFBP.js";
8
- import "./chunk-VVK4I6B5.js";
9
- import "./chunk-VE4LGNXX.js";
10
- import "./chunk-QD27W6W5.js";
11
- import "./chunk-ELLXOV4Q.js";
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-OVJL2QTN.js";
18
- import "./chunk-LAUNHDTX.js";
19
- import "./chunk-JQZHXVIZ.js";
20
- import "./chunk-ELLXOV4Q.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-VVK4I6B5.js";
4
- import "./chunk-QD27W6W5.js";
5
- import "./chunk-ELLXOV4Q.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 = {}) {
@@ -4,11 +4,11 @@ import {
4
4
  runTask,
5
5
  taskArgs,
6
6
  taskOnClient
7
- } from "./chunk-5ZCHFGCV.js";
8
- import "./chunk-VVK4I6B5.js";
9
- import "./chunk-VE4LGNXX.js";
10
- import "./chunk-QD27W6W5.js";
11
- import "./chunk-ELLXOV4Q.js";
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
+ };