@mu-crew/mu 3.11.2 → 3.11.3

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/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  defaultStateDir
4
- } from "./chunk-4PACTXAB.js";
4
+ } from "./chunk-L2ABBTYG.js";
5
5
  import "./chunk-PZ5AY32C.js";
6
6
 
7
7
  // src/main.ts
@@ -47,6 +47,6 @@ function enableCompileCacheIn(dir, enable = nodeEnable ?? null) {
47
47
 
48
48
  // src/main.ts
49
49
  enableCompileCacheIn(join(defaultStateDir(), "compile-cache"));
50
- var { runCli } = await import("./cli-GRAPF5VC.js");
50
+ var { runCli } = await import("./cli-GJIO7GWD.js");
51
51
  await runCli(process.argv);
52
52
  //# sourceMappingURL=cli.js.map
@@ -3,7 +3,7 @@ import {
3
3
  chmodSync,
4
4
  existsSync as existsSync3,
5
5
  linkSync,
6
- mkdirSync,
6
+ mkdirSync as mkdirSync2,
7
7
  readdirSync,
8
8
  readFileSync as readFileSync2,
9
9
  realpathSync,
@@ -11,7 +11,7 @@ import {
11
11
  statSync as statSync2
12
12
  } from "fs";
13
13
  import { connect, createServer } from "net";
14
- import { dirname, join as join3 } from "path";
14
+ import { dirname, join as join4 } from "path";
15
15
  import { fileURLToPath as fileURLToPath2 } from "url";
16
16
 
17
17
  // src/ctl/protocol.ts
@@ -44,9 +44,19 @@ var LineDecoder = class {
44
44
 
45
45
  // extension/delegate.ts
46
46
  import { execFile } from "child_process";
47
- import { existsSync, statSync } from "fs";
48
- import { delimiter, join } from "path";
47
+ import { existsSync, mkdirSync, statSync, writeFileSync } from "fs";
48
+ import { delimiter, join as join2 } from "path";
49
49
  import { fileURLToPath } from "url";
50
+
51
+ // src/state-dir.ts
52
+ import { homedir } from "os";
53
+ import { isAbsolute, join } from "path";
54
+ function defaultCacheDir() {
55
+ const xdg = process.env.XDG_CACHE_HOME;
56
+ return join(xdg !== void 0 && isAbsolute(xdg) ? xdg : join(homedir(), ".cache"), "mu");
57
+ }
58
+
59
+ // extension/delegate.ts
50
60
  var DELEGATE_TOOL = "mu_delegate";
51
61
  var DELEGATE_CANCEL_TOOL = "mu_delegate_cancel";
52
62
  var DELEGATE_MESSAGE_TYPE = "mu-delegate";
@@ -84,7 +94,7 @@ function isDir(p) {
84
94
  }
85
95
  }
86
96
  function onPath(bin, env) {
87
- return (env.PATH ?? "").split(delimiter).some((d) => d !== "" && existsSync(join(d, bin)));
97
+ return (env.PATH ?? "").split(delimiter).some((d) => d !== "" && existsSync(join2(d, bin)));
88
98
  }
89
99
  function defaultRunner() {
90
100
  let cli;
@@ -154,6 +164,29 @@ ${agent.lastText ?? ""}`;
154
164
  return `${who}: mu agent wait gave no result. ${fate}${ws}${tailBlock}`;
155
165
  }
156
166
  }
167
+ function droppedAnswersDir() {
168
+ return join2(defaultCacheDir(), "delegate-answers");
169
+ }
170
+ function droppedNote(dropped) {
171
+ const n = dropped.length;
172
+ const lines = dropped.map((d) => {
173
+ const how = [
174
+ d.outcome ?? "no result",
175
+ d.elapsedMs !== void 0 ? formatElapsed(d.elapsedMs) : void 0
176
+ ].filter((x) => x !== void 0).join(", ");
177
+ const where = [
178
+ d.copy ? `answer: ${d.copy}` : void 0,
179
+ d.sessionFile ? `session: ${d.sessionFile}` : void 0
180
+ ].filter((x) => x !== void 0);
181
+ if (where.length === 0) where.push(`read: mu agent read ${d.name} -n 50 -w ${W}`);
182
+ return `- ${W}/${d.name} (${how}) ${where.join(" \xB7 ")}`;
183
+ });
184
+ return [
185
+ `The interrupt dropped ${n} delegate answer${n === 1 ? "" : "s"} before ${n === 1 ? "it" : "they"} arrived:`,
186
+ ...lines,
187
+ "The answer file holds the message that would have arrived; in a session file the answer is the last assistant message."
188
+ ].join("\n");
189
+ }
157
190
  var RECORD_NOTE_MAX = 4e3;
158
191
  var RECORD_FALLBACK_TAIL = 1500;
159
192
  var VERDICT_LINE = /^[\s>*_`-]*VERDICT:/;
@@ -227,6 +260,23 @@ function registerDelegate(pi, run = defaultRunner()) {
227
260
  const track = (ctx) => {
228
261
  if (ctx?.hasUI !== false && ctx?.ui) ui = ctx.ui;
229
262
  };
263
+ const markQueued = (delivery) => {
264
+ const a = arriving.get(delivery);
265
+ if (a) a.queued = true;
266
+ };
267
+ const saveCopy = (name, content) => {
268
+ try {
269
+ const dir = droppedAnswersDir();
270
+ mkdirSync(dir, { recursive: true });
271
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
272
+ const path = join2(dir, `${stamp}_${name}.md`);
273
+ writeFileSync(path, `${content}
274
+ `);
275
+ return path;
276
+ } catch {
277
+ return void 0;
278
+ }
279
+ };
230
280
  const forget = (name) => {
231
281
  inflight.delete(name);
232
282
  drain();
@@ -371,12 +421,21 @@ function registerDelegate(pi, run = defaultRunner()) {
371
421
  recordNote(record.label, name, outcome, agent?.lastText, extras.elapsedMs ?? 0)
372
422
  ) : void 0;
373
423
  const message = delegateMessage(name, agent, pane, { ...extras, ...tail ? { tail } : {} });
424
+ const content = recorded ? `${message}
425
+
426
+ ${recorded}` : message;
427
+ const a = arriving.get(delivery);
428
+ if (a)
429
+ Object.assign(a, {
430
+ content,
431
+ ...outcome ? { outcome } : {},
432
+ ...extras.elapsedMs !== void 0 ? { elapsedMs: extras.elapsedMs } : {},
433
+ ...agent?.sessionFile ? { sessionFile: agent.sessionFile } : {}
434
+ });
374
435
  await pi.sendMessage(
375
436
  {
376
437
  customType: DELEGATE_MESSAGE_TYPE,
377
- content: recorded ? `${message}
378
-
379
- ${recorded}` : message,
438
+ content,
380
439
  display: true,
381
440
  details: {
382
441
  name,
@@ -451,7 +510,7 @@ ${task}` : task,
451
510
  );
452
511
  const settle = async (r) => {
453
512
  const delivery = ++deliverySeq;
454
- arriving.set(delivery, false);
513
+ arriving.set(delivery, { queued: false, name });
455
514
  forget(name);
456
515
  try {
457
516
  await deliver(
@@ -468,22 +527,28 @@ ${task}` : task,
468
527
  delivery,
469
528
  entry.record
470
529
  );
471
- if (arriving.has(delivery)) arriving.set(delivery, true);
530
+ markQueued(delivery);
472
531
  } catch (e) {
532
+ const content = `Delegate ${W}/${name} settled, but delivering its answer failed: ${e instanceof Error ? e.message : String(e)}. Read it with: mu agent read ${name} -n 50 -w ${W}`;
533
+ const a = arriving.get(delivery);
534
+ if (a) a.content = content;
473
535
  await Promise.resolve(
474
536
  pi.sendMessage(
475
537
  {
476
538
  customType: DELEGATE_MESSAGE_TYPE,
477
- content: `Delegate ${W}/${name} settled, but delivering its answer failed: ${e instanceof Error ? e.message : String(e)}. Read it with: mu agent read ${name} -n 50 -w ${W}`,
539
+ content,
478
540
  display: true,
479
541
  details: { name, workstream: W, outcome: null, closed: false, delivery }
480
542
  },
481
543
  { deliverAs: "followUp", triggerTurn: true }
482
544
  )
483
- ).catch(() => {
484
- arriving.delete(delivery);
485
- showStatus();
486
- });
545
+ ).then(
546
+ () => markQueued(delivery),
547
+ () => {
548
+ arriving.delete(delivery);
549
+ showStatus();
550
+ }
551
+ );
487
552
  }
488
553
  };
489
554
  void waiting.then(async (r) => {
@@ -686,13 +751,32 @@ ${task}` : task,
686
751
  });
687
752
  pi.on("agent_settled", (e) => {
688
753
  if (e.aborted !== true) return;
689
- let dropped = false;
690
- for (const [id, queued] of arriving)
691
- if (queued) {
692
- arriving.delete(id);
693
- dropped = true;
694
- }
695
- if (dropped) showStatus();
754
+ const dropped = [];
755
+ for (const [id, a] of arriving) {
756
+ if (!a.queued) continue;
757
+ arriving.delete(id);
758
+ dropped.push({
759
+ name: a.name,
760
+ ...a.outcome ? { outcome: a.outcome } : {},
761
+ ...a.elapsedMs !== void 0 ? { elapsedMs: a.elapsedMs } : {},
762
+ ...a.sessionFile ? { sessionFile: a.sessionFile } : {},
763
+ ...a.content ? { copy: saveCopy(a.name, a.content) } : {}
764
+ });
765
+ }
766
+ if (dropped.length === 0) return;
767
+ showStatus();
768
+ void Promise.resolve(
769
+ pi.sendMessage(
770
+ {
771
+ customType: DELEGATE_MESSAGE_TYPE,
772
+ content: droppedNote(dropped),
773
+ display: true,
774
+ details: { dropped }
775
+ },
776
+ { triggerTurn: false }
777
+ )
778
+ ).catch(() => {
779
+ });
696
780
  });
697
781
  pi.on("session_shutdown", (_e, ctx) => {
698
782
  if (arriving.size > 0) {
@@ -722,7 +806,7 @@ ${task}` : task,
722
806
 
723
807
  // extension/nudge.ts
724
808
  import { existsSync as existsSync2, readFileSync } from "fs";
725
- import { join as join2 } from "path";
809
+ import { join as join3 } from "path";
726
810
  var NUDGE_MESSAGE_TYPE = "mu-keep-driving";
727
811
  var NUDGE_LOG_KIND = "nudge";
728
812
  var CLOSE_NUDGE_MESSAGE_TYPE = "mu-close-task";
@@ -746,7 +830,7 @@ function keepDrivingRule(skillMd) {
746
830
  }
747
831
  function readSkill() {
748
832
  for (const up of ["..", "../.."]) {
749
- const p = join2(import.meta.dirname ?? "", up, "skills", "mu", "SKILL.md");
833
+ const p = join3(import.meta.dirname ?? "", up, "skills", "mu", "SKILL.md");
750
834
  if (existsSync2(p)) return readFileSync(p, "utf8");
751
835
  }
752
836
  return void 0;
@@ -1147,7 +1231,7 @@ function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
1147
1231
  }
1148
1232
 
1149
1233
  // extension/mu-pi.ts
1150
- var EXT_VERSION = true ? "3.11.2" : void 0;
1234
+ var EXT_VERSION = true ? "3.11.3" : void 0;
1151
1235
  var FRESH_COMMAND = "mu-fresh";
1152
1236
  var FRESH_TIMEOUT_MS = 3e4;
1153
1237
  function commandName(name) {
@@ -1167,7 +1251,7 @@ function detectPiVersion() {
1167
1251
  if (!entry) return void 0;
1168
1252
  let dir = dirname(realpathSync(entry));
1169
1253
  for (let i = 0; i < 6; i++) {
1170
- const pkgPath = join3(dir, "package.json");
1254
+ const pkgPath = join4(dir, "package.json");
1171
1255
  if (existsSync3(pkgPath)) {
1172
1256
  const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
1173
1257
  if (typeof pkg === "object" && pkg !== null) {
@@ -1273,8 +1357,8 @@ function promptsDir(from = import.meta.url) {
1273
1357
  return void 0;
1274
1358
  }
1275
1359
  for (const up of ["..", "../.."]) {
1276
- const d = join3(here, up, "prompts");
1277
- if (existsSync3(join3(d, "ultrathink.md"))) return d;
1360
+ const d = join4(here, up, "prompts");
1361
+ if (existsSync3(join4(d, "ultrathink.md"))) return d;
1278
1362
  }
1279
1363
  return void 0;
1280
1364
  }
@@ -1282,7 +1366,7 @@ function registerPrompts(pi) {
1282
1366
  pi.on("resources_discover", () => {
1283
1367
  const d = promptsDir();
1284
1368
  if (!d) return {};
1285
- const paths = readdirSync(d).filter((f) => f.endsWith(".md")).sort().map((f) => join3(d, f));
1369
+ const paths = readdirSync(d).filter((f) => f.endsWith(".md")).sort().map((f) => join4(d, f));
1286
1370
  return { promptPaths: paths };
1287
1371
  });
1288
1372
  }
@@ -1353,6 +1437,11 @@ function serveCtl(pi) {
1353
1437
  g.endText = void 0;
1354
1438
  g.lastError = g.endError;
1355
1439
  g.endError = void 0;
1440
+ try {
1441
+ g.sessionFile = c.sessionManager?.getSessionFile();
1442
+ } catch {
1443
+ g.sessionFile = void 0;
1444
+ }
1356
1445
  for (const w of [...g.waiters]) w();
1357
1446
  });
1358
1447
  pi.registerCommand(FRESH_COMMAND, {
@@ -1512,7 +1601,8 @@ function serveCtl(pi) {
1512
1601
  }
1513
1602
  const settledRun = () => ({
1514
1603
  lastText: g.lastText,
1515
- ...g.lastError !== void 0 ? { lastError: g.lastError } : {}
1604
+ ...g.lastError !== void 0 ? { lastError: g.lastError } : {},
1605
+ ...g.sessionFile !== void 0 ? { sessionFile: g.sessionFile } : {}
1516
1606
  });
1517
1607
  function wait(afterRuns, timeoutMs, conn) {
1518
1608
  if (afterRuns !== void 0 && g.runs > afterRuns && g.state === "idle") {
@@ -1570,7 +1660,7 @@ function serveCtl(pi) {
1570
1660
  });
1571
1661
  }
1572
1662
  async function bind() {
1573
- mkdirSync(dirname(sockPath), { recursive: true, mode: 448 });
1663
+ mkdirSync2(dirname(sockPath), { recursive: true, mode: 448 });
1574
1664
  if (await socketIsLive(sockPath)) {
1575
1665
  g.nested = true;
1576
1666
  process.stderr.write(
@@ -1580,7 +1670,7 @@ function serveCtl(pi) {
1580
1670
  return;
1581
1671
  }
1582
1672
  rmSync(sockPath, { force: true });
1583
- const tmp = join3(dirname(sockPath), `.${process.pid.toString(36)}${(++bindSeq).toString(36)}`);
1673
+ const tmp = join4(dirname(sockPath), `.${process.pid.toString(36)}${(++bindSeq).toString(36)}`);
1584
1674
  rmSync(tmp, { force: true });
1585
1675
  const s = createServer(onConnection);
1586
1676
  await new Promise((resolve, reject) => {