@mu-crew/mu 3.8.1 → 3.10.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/AGENTS.md +2 -1
- package/README.md +1 -0
- package/dist/chunk-4PACTXAB.js +17 -0
- package/dist/chunk-4PACTXAB.js.map +1 -0
- package/dist/chunk-77GBZ2KR.js +85 -0
- package/dist/chunk-77GBZ2KR.js.map +1 -0
- package/dist/chunk-7OQNJWBY.js +391 -0
- package/dist/chunk-7OQNJWBY.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-WT7IN2OD.js +9887 -0
- package/dist/chunk-WT7IN2OD.js.map +1 -0
- package/dist/chunk-XXK7FR37.js +640 -0
- package/dist/chunk-XXK7FR37.js.map +1 -0
- package/dist/chunk-YIF3X32A.js +2792 -0
- package/dist/chunk-YIF3X32A.js.map +1 -0
- package/dist/cli-UZEMPIPW.js +6266 -0
- package/dist/cli-UZEMPIPW.js.map +1 -0
- package/dist/cli.js +37 -25280
- package/dist/cli.js.map +1 -1
- package/dist/extension/mu-pi.js +230 -138
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +543 -142
- package/dist/index.js +340 -11169
- package/dist/index.js.map +1 -1
- package/dist/tui-X2XICJTN.js +6452 -0
- package/dist/tui-X2XICJTN.js.map +1 -0
- package/dist/tui-sync-worker.js +16 -0
- package/dist/tui-sync-worker.js.map +1 -0
- package/dist/yank-T3AYQTVR.js +12 -0
- package/dist/yank-T3AYQTVR.js.map +1 -0
- package/docs/ARCHITECTURE.md +14 -6
- package/docs/VISION.md +14 -7
- package/docs/VOCABULARY.md +5 -6
- package/docs/architecture/control-socket.md +6 -2
- package/docs/architecture/mux.md +4 -2
- package/docs/architecture/ops-log.md +2 -1
- package/docs/architecture/sdk.md +3 -1
- package/docs/architecture/sync.md +32 -10
- package/docs/architecture/tui.md +18 -8
- package/docs/guide/backends.md +5 -3
- package/docs/guide/cleanup.md +8 -3
- package/docs/guide/delegate.md +3 -1
- package/docs/guide/dispatch.md +9 -3
- package/docs/guide/recovery.md +19 -8
- package/docs/guide/sql.md +11 -4
- package/docs/guide/stop-a-worker.md +3 -1
- package/docs/guide/tui.md +3 -3
- package/docs/guide/upgrade.md +8 -2
- package/docs/reference/env.md +11 -5
- package/docs/reference/naming.md +3 -4
- package/package.json +1 -1
- package/skills/mu/SKILL.md +2 -2
- package/skills/mu/recipes/drift-audit.md +5 -3
package/dist/extension/mu-pi.js
CHANGED
|
@@ -182,7 +182,6 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
182
182
|
const queue = [];
|
|
183
183
|
let queueSeq = 0;
|
|
184
184
|
const failed = /* @__PURE__ */ new Set();
|
|
185
|
-
const reserved = /* @__PURE__ */ new Set();
|
|
186
185
|
let ui;
|
|
187
186
|
let lastPending = 0;
|
|
188
187
|
const reportPending = () => {
|
|
@@ -209,7 +208,6 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
209
208
|
};
|
|
210
209
|
const forget = (name) => {
|
|
211
210
|
inflight.delete(name);
|
|
212
|
-
reserved.delete(name);
|
|
213
211
|
drain();
|
|
214
212
|
showStatus();
|
|
215
213
|
};
|
|
@@ -248,63 +246,57 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
248
246
|
}
|
|
249
247
|
};
|
|
250
248
|
const failure = (what, r) => new Error(`${what} failed (exit ${r.code}): ${(r.stderr || r.stdout).trim()}`);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
Array.isArray(agents)
|
|
256
|
-
|
|
257
|
-
if (Array.isArray(agents)) {
|
|
249
|
+
function pruneFailed() {
|
|
250
|
+
if (failed.size === 0) return;
|
|
251
|
+
void mu(["agent", "list", "-w", W, "--json"]).then((r) => {
|
|
252
|
+
const agents = json(r)?.agents;
|
|
253
|
+
if (!Array.isArray(agents)) return;
|
|
254
|
+
const taken = new Set(agents.map((a) => a.name));
|
|
258
255
|
for (const f of [...failed]) if (!taken.has(f)) failed.delete(f);
|
|
259
256
|
showStatus();
|
|
260
|
-
}
|
|
261
|
-
for (let n = 1; ; n++) {
|
|
262
|
-
const name = stem ? n === 1 ? `delegate-${stem}` : `delegate-${stem}-${n}` : `delegate-${n}`;
|
|
263
|
-
if (!taken.has(name) && !reserved.has(name)) {
|
|
264
|
-
reserved.add(name);
|
|
265
|
-
return name;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
257
|
+
});
|
|
268
258
|
}
|
|
269
|
-
async function spawn(params, cwd, signal) {
|
|
259
|
+
async function spawn(params, text, cwd, signal) {
|
|
260
|
+
signal?.throwIfAborted();
|
|
261
|
+
pruneFailed();
|
|
270
262
|
const stem = labelStem(params.label);
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (r.code !== 0 && /already exists/.test(r.stderr) && attempt < 3) {
|
|
285
|
-
reserved.delete(name);
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
if (r.code !== 0) {
|
|
289
|
-
reserved.delete(name);
|
|
290
|
-
throw failure("mu agent spawn", r);
|
|
291
|
-
}
|
|
292
|
-
const out = json(r) ?? {};
|
|
293
|
-
if (out.ctl !== "ok") {
|
|
294
|
-
reserved.delete(name);
|
|
295
|
-
throw new Error(
|
|
296
|
-
`${W}/${name} spawned but its control socket is ${String(out.ctl)}, so its answer cannot come back. Pane kept; close it with: mu agent close ${name} -w ${W}`
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
const steps = Array.isArray(out.nextSteps) ? out.nextSteps : [];
|
|
300
|
-
const attach = steps.map((s) => s).find((s) => s.intent === "Attach the pane")?.command;
|
|
301
|
-
const wsPath = out.workspace?.path;
|
|
302
|
-
return {
|
|
303
|
-
name,
|
|
304
|
-
...typeof attach === "string" ? { attach } : {},
|
|
305
|
-
...typeof wsPath === "string" ? { workspace: wsPath } : {}
|
|
306
|
-
};
|
|
263
|
+
const base = stem ? `delegate-${stem}` : "delegate-1";
|
|
264
|
+
const args = ["agent", "spawn", base, "-w", W, "--next-free", "--send", text, "--json"];
|
|
265
|
+
if (params.workspace === true) args.push("--workspace");
|
|
266
|
+
else if (cwd) args.push("--cwd", cwd);
|
|
267
|
+
if (typeof params.cli === "string" && params.cli) args.push("--cli", params.cli);
|
|
268
|
+
const r = await mu(args);
|
|
269
|
+
const out = json(r);
|
|
270
|
+
const spawned = out?.agent?.name;
|
|
271
|
+
if (typeof spawned !== "string") throw failure("mu agent spawn", r);
|
|
272
|
+
const name = spawned;
|
|
273
|
+
if (signal?.aborted) {
|
|
274
|
+
await mu(["agent", "close", name, "-w", W]);
|
|
275
|
+
signal.throwIfAborted();
|
|
307
276
|
}
|
|
277
|
+
if (out?.ctl !== "ok") {
|
|
278
|
+
throw new Error(
|
|
279
|
+
`${W}/${name} spawned but its control socket is ${String(out?.ctl)}, so its answer cannot come back. Pane kept; close it with: mu agent close ${name} -w ${W}`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
const sent = out.send;
|
|
283
|
+
if (sent?.ok !== true) {
|
|
284
|
+
const c = await mu(["agent", "close", name, "-w", W]);
|
|
285
|
+
const pane = c.code === 0 ? "Pane closed." : `Pane kept; close it with: mu agent close ${name} -w ${W}`;
|
|
286
|
+
const why = typeof sent?.message === "string" ? sent.message : (r.stderr || r.stdout).trim();
|
|
287
|
+
throw new Error(`mu agent send to ${W}/${name} failed (exit ${r.code}): ${why}. ${pane}`);
|
|
288
|
+
}
|
|
289
|
+
const steps = Array.isArray(out.nextSteps) ? out.nextSteps : [];
|
|
290
|
+
const attach = steps.map((s) => s).find((s) => s.intent === "Attach the pane")?.command;
|
|
291
|
+
const wsPath = out.workspace?.path;
|
|
292
|
+
return {
|
|
293
|
+
name,
|
|
294
|
+
// A pi just spawned has settled no run, so 0 is exact when an older
|
|
295
|
+
// extension's reply carries no runs.
|
|
296
|
+
runs: typeof sent.runs === "number" ? sent.runs : 0,
|
|
297
|
+
...typeof attach === "string" ? { attach } : {},
|
|
298
|
+
...typeof wsPath === "string" ? { workspace: wsPath } : {}
|
|
299
|
+
};
|
|
308
300
|
}
|
|
309
301
|
const recordLabel = (params, name) => typeof params.label === "string" && params.label.trim() ? params.label.trim() : name;
|
|
310
302
|
async function resolveRecord(raw) {
|
|
@@ -400,7 +392,14 @@ ${recorded}` : message,
|
|
|
400
392
|
cwd = typeof params.cwd === "string" && params.cwd ? params.cwd : ctx?.cwd ?? process.cwd();
|
|
401
393
|
if (!isDir(cwd)) throw new Error(`mu_delegate: cwd ${cwd} is not a directory`);
|
|
402
394
|
}
|
|
403
|
-
const { name, attach, workspace } = await spawn(
|
|
395
|
+
const { name, runs, attach, workspace } = await spawn(
|
|
396
|
+
params,
|
|
397
|
+
brief ? `${brief}
|
|
398
|
+
|
|
399
|
+
${task}` : task,
|
|
400
|
+
cwd,
|
|
401
|
+
signal
|
|
402
|
+
);
|
|
404
403
|
const entry = {
|
|
405
404
|
abort: new AbortController(),
|
|
406
405
|
cancelling: false,
|
|
@@ -410,43 +409,21 @@ ${recorded}` : message,
|
|
|
410
409
|
freeSlot();
|
|
411
410
|
showStatus();
|
|
412
411
|
const started = Date.now();
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
"agent",
|
|
429
|
-
"send",
|
|
430
|
-
name,
|
|
431
|
-
brief ? `${brief}
|
|
432
|
-
|
|
433
|
-
${task}` : task,
|
|
434
|
-
"-w",
|
|
435
|
-
W,
|
|
436
|
-
"--json"
|
|
437
|
-
]);
|
|
438
|
-
if (sent.code !== 0) {
|
|
439
|
-
plain.abort();
|
|
440
|
-
forget(name);
|
|
441
|
-
const c = await mu(["agent", "close", name, "-w", W]);
|
|
442
|
-
const pane = c.code === 0 ? "Pane closed." : `Pane kept; close it with: mu agent close ${name} -w ${W}`;
|
|
443
|
-
throw new Error(`${failure(`mu agent send to ${W}/${name}`, sent).message}. ${pane}`);
|
|
444
|
-
}
|
|
445
|
-
const runs = json(sent)?.runs;
|
|
446
|
-
if (typeof runs === "number") {
|
|
447
|
-
plain.abort();
|
|
448
|
-
waiting = mu(waitArgs(runs), entry.abort.signal);
|
|
449
|
-
}
|
|
412
|
+
const waiting = mu(
|
|
413
|
+
[
|
|
414
|
+
"agent",
|
|
415
|
+
"wait",
|
|
416
|
+
name,
|
|
417
|
+
"-w",
|
|
418
|
+
W,
|
|
419
|
+
"--json",
|
|
420
|
+
"--timeout",
|
|
421
|
+
String(timeoutS),
|
|
422
|
+
"--after-runs",
|
|
423
|
+
String(runs)
|
|
424
|
+
],
|
|
425
|
+
entry.abort.signal
|
|
426
|
+
);
|
|
450
427
|
const settle = async (r) => {
|
|
451
428
|
forget(name);
|
|
452
429
|
try {
|
|
@@ -501,7 +478,7 @@ ${task}` : task,
|
|
|
501
478
|
};
|
|
502
479
|
} finally {
|
|
503
480
|
freeSlot();
|
|
504
|
-
|
|
481
|
+
drain();
|
|
505
482
|
}
|
|
506
483
|
}
|
|
507
484
|
pi.registerTool({
|
|
@@ -711,25 +688,31 @@ function readSkill() {
|
|
|
711
688
|
}
|
|
712
689
|
return void 0;
|
|
713
690
|
}
|
|
691
|
+
var ENV_ASSIGN = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
692
|
+
function muArgs(words) {
|
|
693
|
+
let at = 0;
|
|
694
|
+
while (at < words.length && ENV_ASSIGN.test(words[at] ?? "")) at++;
|
|
695
|
+
const cmd = words[at];
|
|
696
|
+
if (cmd !== "mu" && !cmd?.endsWith("/mu")) return void 0;
|
|
697
|
+
return words.slice(at + 1);
|
|
698
|
+
}
|
|
714
699
|
function dispatchedWorkstreams(command) {
|
|
715
700
|
const found = /* @__PURE__ */ new Set();
|
|
716
701
|
for (const words of shellSegments(command)) {
|
|
717
|
-
const
|
|
718
|
-
if (
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
702
|
+
const args = muArgs(words);
|
|
703
|
+
if (args === void 0) continue;
|
|
704
|
+
const claim = claimOf(args);
|
|
705
|
+
if (claim !== void 0) {
|
|
706
|
+
if (claim.ws !== "scratch") found.add(claim.ws);
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
if (args[0] !== "agent" || args[1] !== "send" && args[1] !== "spawn") continue;
|
|
723
710
|
let ws = "";
|
|
724
|
-
for (let k =
|
|
725
|
-
const w =
|
|
726
|
-
if (w === "-w" || w === "--workstream") ws =
|
|
711
|
+
for (let k = 2; k < args.length; k++) {
|
|
712
|
+
const w = args[k] ?? "";
|
|
713
|
+
if (w === "-w" || w === "--workstream") ws = args[k + 1] ?? "";
|
|
727
714
|
else if (w.startsWith("--workstream=")) ws = w.slice("--workstream=".length);
|
|
728
715
|
}
|
|
729
|
-
if (ws === "" && isClaimFor) {
|
|
730
|
-
const ref = words[at + 3] ?? "";
|
|
731
|
-
if (ref.includes("/")) ws = ref.split("/")[0] ?? "";
|
|
732
|
-
}
|
|
733
716
|
if (ws !== "scratch") found.add(ws);
|
|
734
717
|
}
|
|
735
718
|
return found.size > 0 ? [...found] : void 0;
|
|
@@ -739,6 +722,8 @@ function shellSegments(command) {
|
|
|
739
722
|
const segs = [];
|
|
740
723
|
let words = [];
|
|
741
724
|
let word;
|
|
725
|
+
const heredocs = [];
|
|
726
|
+
let arithEnd = -1;
|
|
742
727
|
const endWord = () => {
|
|
743
728
|
if (word !== void 0) words.push(word);
|
|
744
729
|
word = void 0;
|
|
@@ -748,6 +733,18 @@ function shellSegments(command) {
|
|
|
748
733
|
if (words.length > 0) segs.push(words);
|
|
749
734
|
words = [];
|
|
750
735
|
};
|
|
736
|
+
const skipHeredocs = (i) => {
|
|
737
|
+
for (const h of heredocs.splice(0)) {
|
|
738
|
+
while (i < command.length) {
|
|
739
|
+
const eol = command.indexOf("\n", i + 1);
|
|
740
|
+
const end = eol < 0 ? command.length : eol;
|
|
741
|
+
const line = command.slice(i + 1, end);
|
|
742
|
+
i = end;
|
|
743
|
+
if ((h.strip ? line.replace(/^\t+/, "") : line) === h.delim) break;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
return i;
|
|
747
|
+
};
|
|
751
748
|
for (let i = 0; i < command.length; i++) {
|
|
752
749
|
const c = command[i] ?? "";
|
|
753
750
|
if (c === "'" || c === '"') {
|
|
@@ -755,11 +752,34 @@ function shellSegments(command) {
|
|
|
755
752
|
const end = close < 0 ? command.length : close;
|
|
756
753
|
word = (word ?? "") + command.slice(i + 1, end);
|
|
757
754
|
i = end;
|
|
755
|
+
} else if (c === "\\" && command[i + 1] === "\n") {
|
|
756
|
+
i++;
|
|
758
757
|
} else if (c === "\\" && i + 1 < command.length) {
|
|
759
758
|
word = (word ?? "") + command[++i];
|
|
759
|
+
} else if (c === "#" && word === void 0) {
|
|
760
|
+
const eol = command.indexOf("\n", i);
|
|
761
|
+
i = (eol < 0 ? command.length : eol) - 1;
|
|
762
|
+
} else if (c === "(" && command[i + 1] === "(" && i > arithEnd) {
|
|
763
|
+
arithEnd = arithmeticEnd(command, i);
|
|
764
|
+
word = `${word ?? ""}((`;
|
|
765
|
+
i++;
|
|
766
|
+
} else if (command.startsWith("<<<", i)) {
|
|
767
|
+
endWord();
|
|
768
|
+
i += 2;
|
|
769
|
+
} else if (c === "<" && command[i + 1] === "<" && i > arithEnd) {
|
|
770
|
+
endWord();
|
|
771
|
+
const m = /^<<(-?)[ \t]*('([^']*)'|"([^"]*)"|[^\s;&|<>()]+)/.exec(command.slice(i));
|
|
772
|
+
if (!m) {
|
|
773
|
+
i++;
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
const delim = m[3] ?? m[4] ?? (m[2] ?? "").replace(/\\/g, "");
|
|
777
|
+
heredocs.push({ delim, strip: m[1] === "-" });
|
|
778
|
+
i += m[0].length - 1;
|
|
760
779
|
} else if (c === ";" || c === "|" || c === "\n" || c === "&" && command[i + 1] === "&") {
|
|
761
780
|
if (c !== ";" && c !== "\n" && command[i + 1] === c) i++;
|
|
762
781
|
endSeg();
|
|
782
|
+
if (c === "\n" && heredocs.length > 0) i = skipHeredocs(i);
|
|
763
783
|
} else if (/\s/.test(c)) {
|
|
764
784
|
endWord();
|
|
765
785
|
} else {
|
|
@@ -769,30 +789,53 @@ function shellSegments(command) {
|
|
|
769
789
|
endSeg();
|
|
770
790
|
return segs;
|
|
771
791
|
}
|
|
792
|
+
function arithmeticEnd(command, open) {
|
|
793
|
+
let depth = 0;
|
|
794
|
+
for (let i = open + 2; i < command.length; i++) {
|
|
795
|
+
const c = command[i];
|
|
796
|
+
if (c === "'" || c === '"') {
|
|
797
|
+
const close = command.indexOf(c, i + 1);
|
|
798
|
+
if (close < 0) return -1;
|
|
799
|
+
i = close;
|
|
800
|
+
} else if (c === "\\") {
|
|
801
|
+
i++;
|
|
802
|
+
} else if (c === "(") {
|
|
803
|
+
depth++;
|
|
804
|
+
} else if (c === ")") {
|
|
805
|
+
if (depth > 0) depth--;
|
|
806
|
+
else return command[i + 1] === ")" ? i + 1 : -1;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return -1;
|
|
810
|
+
}
|
|
811
|
+
function claimOf(args) {
|
|
812
|
+
if (args[0] !== "task" || args[1] !== "claim") return void 0;
|
|
813
|
+
let ws = "";
|
|
814
|
+
let id;
|
|
815
|
+
let isFor = false;
|
|
816
|
+
for (let k = 2; k < args.length; k++) {
|
|
817
|
+
const w = args[k] ?? "";
|
|
818
|
+
const [opt, eq] = w.startsWith("--") && w.includes("=") ? w.split("=", 2) : [w, void 0];
|
|
819
|
+
if (opt === "--for" || opt === "-f") isFor = true;
|
|
820
|
+
if (opt === "-w" || opt === "--workstream") ws = eq ?? args[k + 1] ?? "";
|
|
821
|
+
if (CLAIM_VALUE_OPTS.has(opt ?? "")) {
|
|
822
|
+
if (eq === void 0) k++;
|
|
823
|
+
} else if (id === void 0 && !w.startsWith("-")) id = w;
|
|
824
|
+
}
|
|
825
|
+
if (!isFor || id === void 0) return void 0;
|
|
826
|
+
const slash = id.indexOf("/");
|
|
827
|
+
if (slash >= 0) {
|
|
828
|
+
if (ws === "") ws = id.slice(0, slash);
|
|
829
|
+
id = id.slice(slash + 1);
|
|
830
|
+
}
|
|
831
|
+
return { ws, id };
|
|
832
|
+
}
|
|
772
833
|
function dispatchedTasks(command) {
|
|
773
834
|
const out = [];
|
|
774
835
|
for (const words of shellSegments(command)) {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
let id;
|
|
779
|
-
let isFor = false;
|
|
780
|
-
for (let k = 3; k < words.length; k++) {
|
|
781
|
-
const w = words[k] ?? "";
|
|
782
|
-
const [opt, eq] = w.startsWith("--") && w.includes("=") ? w.split("=", 2) : [w, void 0];
|
|
783
|
-
if (opt === "--for" || opt === "-f") isFor = true;
|
|
784
|
-
if (opt === "-w" || opt === "--workstream") ws = eq ?? words[k + 1] ?? "";
|
|
785
|
-
if (CLAIM_VALUE_OPTS.has(opt ?? "")) {
|
|
786
|
-
if (eq === void 0) k++;
|
|
787
|
-
} else if (id === void 0 && !w.startsWith("-")) id = w;
|
|
788
|
-
}
|
|
789
|
-
if (!isFor || id === void 0) continue;
|
|
790
|
-
const slash = id.indexOf("/");
|
|
791
|
-
if (slash >= 0) {
|
|
792
|
-
if (ws === "") ws = id.slice(0, slash);
|
|
793
|
-
id = id.slice(slash + 1);
|
|
794
|
-
}
|
|
795
|
-
if (ws !== "scratch") out.push({ ws, id });
|
|
836
|
+
const args = muArgs(words);
|
|
837
|
+
const claim = args === void 0 ? void 0 : claimOf(args);
|
|
838
|
+
if (claim !== void 0 && claim.ws !== "scratch") out.push(claim);
|
|
796
839
|
}
|
|
797
840
|
return out;
|
|
798
841
|
}
|
|
@@ -826,6 +869,54 @@ function nudgeText(rule, refs) {
|
|
|
826
869
|
`${refs.length} task(s) IN_PROGRESS. Next: mu task wait ${shown} --first --on-stall exit --json${more}`
|
|
827
870
|
].join("\n");
|
|
828
871
|
}
|
|
872
|
+
function breadcrumb(run, args) {
|
|
873
|
+
void run(args).catch(() => {
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
function parallelSettle(pi) {
|
|
877
|
+
const handlers = [];
|
|
878
|
+
const api = {
|
|
879
|
+
on(event, handler) {
|
|
880
|
+
if (event === "agent_before_settle") handlers.push(handler);
|
|
881
|
+
else pi.on(event, handler);
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
let errors = [];
|
|
885
|
+
return {
|
|
886
|
+
api,
|
|
887
|
+
flush() {
|
|
888
|
+
if (handlers.length === 0) return;
|
|
889
|
+
pi.on("agent_before_settle", async (event, ctx) => {
|
|
890
|
+
errors = handlers.map(() => void 0);
|
|
891
|
+
const results = await Promise.all(
|
|
892
|
+
handlers.map(async (h, i) => {
|
|
893
|
+
try {
|
|
894
|
+
return await h(event, ctx);
|
|
895
|
+
} catch (err) {
|
|
896
|
+
errors[i] = [err];
|
|
897
|
+
return void 0;
|
|
898
|
+
}
|
|
899
|
+
})
|
|
900
|
+
);
|
|
901
|
+
const fired = results.filter((r) => r !== void 0);
|
|
902
|
+
if (fired.length === 0) return void 0;
|
|
903
|
+
const prior = event?.entries ?? [];
|
|
904
|
+
return {
|
|
905
|
+
entries: [...prior, ...fired.flatMap((r) => r.entries ?? [])],
|
|
906
|
+
...fired.some((r) => r.continue === true) ? { continue: true } : {}
|
|
907
|
+
};
|
|
908
|
+
});
|
|
909
|
+
handlers.forEach((_, i) => {
|
|
910
|
+
pi.on("agent_before_settle", () => {
|
|
911
|
+
const err = errors[i];
|
|
912
|
+
errors[i] = void 0;
|
|
913
|
+
if (err !== void 0) throw err[0];
|
|
914
|
+
return void 0;
|
|
915
|
+
});
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
}
|
|
829
920
|
function outcomeOf(event) {
|
|
830
921
|
return typeof event === "object" && event !== null ? event.outcome : void 0;
|
|
831
922
|
}
|
|
@@ -857,7 +948,7 @@ function registerNudge(pi, run = defaultRunner(), skillMd = readSkill(), nested
|
|
|
857
948
|
if (refs === void 0 || refs.length === 0) return;
|
|
858
949
|
const text = nudgeText(rule, refs);
|
|
859
950
|
const logWs = [...armed].find((w) => w !== "");
|
|
860
|
-
|
|
951
|
+
breadcrumb(run, [
|
|
861
952
|
"log",
|
|
862
953
|
...logWs ? ["-w", logWs] : [],
|
|
863
954
|
"--kind",
|
|
@@ -913,7 +1004,7 @@ function registerCloseNudge(pi, run = defaultRunner(), env = process.env, nested
|
|
|
913
1004
|
fired = true;
|
|
914
1005
|
const names = await ownedInProgress(run, me.agent, me.workstream);
|
|
915
1006
|
if (names === void 0 || names.length === 0) return;
|
|
916
|
-
|
|
1007
|
+
breadcrumb(run, [
|
|
917
1008
|
"log",
|
|
918
1009
|
"-w",
|
|
919
1010
|
me.workstream,
|
|
@@ -967,13 +1058,12 @@ function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
|
|
|
967
1058
|
if (fired || armed.size === 0 || nested() || noUI(ctx)) return;
|
|
968
1059
|
if (outcomeOf(event) !== "completed") return;
|
|
969
1060
|
fired = true;
|
|
970
|
-
const
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
}
|
|
1061
|
+
const tasks = [...armed];
|
|
1062
|
+
const refuted = await Promise.all(tasks.map(([, t]) => briefRefuted(run, t.ws, t.id)));
|
|
1063
|
+
const refs = tasks.flatMap(([ref], i) => refuted[i] === false ? [ref] : []);
|
|
974
1064
|
if (refs.length === 0) return;
|
|
975
1065
|
const logWs = [...armed.values()].find((t) => t.ws !== "")?.ws;
|
|
976
|
-
|
|
1066
|
+
breadcrumb(run, [
|
|
977
1067
|
"log",
|
|
978
1068
|
...logWs ? ["-w", logWs] : [],
|
|
979
1069
|
"--kind",
|
|
@@ -994,7 +1084,7 @@ function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
|
|
|
994
1084
|
}
|
|
995
1085
|
|
|
996
1086
|
// extension/mu-pi.ts
|
|
997
|
-
var EXT_VERSION = true ? "3.
|
|
1087
|
+
var EXT_VERSION = true ? "3.10.0" : void 0;
|
|
998
1088
|
var FRESH_COMMAND = "mu-fresh";
|
|
999
1089
|
var FRESH_TIMEOUT_MS = 3e4;
|
|
1000
1090
|
function commandName(name) {
|
|
@@ -1137,9 +1227,11 @@ function muPi(pi, run = defaultRunner()) {
|
|
|
1137
1227
|
registerDelegate(pi, run);
|
|
1138
1228
|
registerPrompts(pi);
|
|
1139
1229
|
const nested = serveCtl(pi);
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1230
|
+
const settle = parallelSettle(pi);
|
|
1231
|
+
registerNudge(settle.api, run, void 0, nested);
|
|
1232
|
+
registerCloseNudge(settle.api, run, process.env, nested);
|
|
1233
|
+
registerRefuteNudge(settle.api, run, nested);
|
|
1234
|
+
settle.flush();
|
|
1143
1235
|
}
|
|
1144
1236
|
function serveCtl(pi) {
|
|
1145
1237
|
const sock = process.env.MU_CTL_SOCK;
|