@mu-crew/mu 3.9.0 → 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/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 -26127
- package/dist/cli.js.map +1 -1
- package/dist/extension/mu-pi.js +129 -103
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +108 -53
- package/dist/index.js +324 -11728
- 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 +9 -3
- package/docs/architecture/control-socket.md +5 -1
- package/docs/architecture/sync.md +18 -4
- package/docs/guide/dispatch.md +4 -0
- package/docs/guide/sql.md +1 -1
- package/docs/reference/env.md +2 -1
- package/package.json +1 -1
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
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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();
|
|
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
|
+
);
|
|
307
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 {
|
|
@@ -892,6 +869,54 @@ function nudgeText(rule, refs) {
|
|
|
892
869
|
`${refs.length} task(s) IN_PROGRESS. Next: mu task wait ${shown} --first --on-stall exit --json${more}`
|
|
893
870
|
].join("\n");
|
|
894
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
|
+
}
|
|
895
920
|
function outcomeOf(event) {
|
|
896
921
|
return typeof event === "object" && event !== null ? event.outcome : void 0;
|
|
897
922
|
}
|
|
@@ -923,7 +948,7 @@ function registerNudge(pi, run = defaultRunner(), skillMd = readSkill(), nested
|
|
|
923
948
|
if (refs === void 0 || refs.length === 0) return;
|
|
924
949
|
const text = nudgeText(rule, refs);
|
|
925
950
|
const logWs = [...armed].find((w) => w !== "");
|
|
926
|
-
|
|
951
|
+
breadcrumb(run, [
|
|
927
952
|
"log",
|
|
928
953
|
...logWs ? ["-w", logWs] : [],
|
|
929
954
|
"--kind",
|
|
@@ -979,7 +1004,7 @@ function registerCloseNudge(pi, run = defaultRunner(), env = process.env, nested
|
|
|
979
1004
|
fired = true;
|
|
980
1005
|
const names = await ownedInProgress(run, me.agent, me.workstream);
|
|
981
1006
|
if (names === void 0 || names.length === 0) return;
|
|
982
|
-
|
|
1007
|
+
breadcrumb(run, [
|
|
983
1008
|
"log",
|
|
984
1009
|
"-w",
|
|
985
1010
|
me.workstream,
|
|
@@ -1033,13 +1058,12 @@ function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
|
|
|
1033
1058
|
if (fired || armed.size === 0 || nested() || noUI(ctx)) return;
|
|
1034
1059
|
if (outcomeOf(event) !== "completed") return;
|
|
1035
1060
|
fired = true;
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
}
|
|
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] : []);
|
|
1040
1064
|
if (refs.length === 0) return;
|
|
1041
1065
|
const logWs = [...armed.values()].find((t) => t.ws !== "")?.ws;
|
|
1042
|
-
|
|
1066
|
+
breadcrumb(run, [
|
|
1043
1067
|
"log",
|
|
1044
1068
|
...logWs ? ["-w", logWs] : [],
|
|
1045
1069
|
"--kind",
|
|
@@ -1060,7 +1084,7 @@ function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
|
|
|
1060
1084
|
}
|
|
1061
1085
|
|
|
1062
1086
|
// extension/mu-pi.ts
|
|
1063
|
-
var EXT_VERSION = true ? "3.
|
|
1087
|
+
var EXT_VERSION = true ? "3.10.0" : void 0;
|
|
1064
1088
|
var FRESH_COMMAND = "mu-fresh";
|
|
1065
1089
|
var FRESH_TIMEOUT_MS = 3e4;
|
|
1066
1090
|
function commandName(name) {
|
|
@@ -1203,9 +1227,11 @@ function muPi(pi, run = defaultRunner()) {
|
|
|
1203
1227
|
registerDelegate(pi, run);
|
|
1204
1228
|
registerPrompts(pi);
|
|
1205
1229
|
const nested = serveCtl(pi);
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
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();
|
|
1209
1235
|
}
|
|
1210
1236
|
function serveCtl(pi) {
|
|
1211
1237
|
const sock = process.env.MU_CTL_SOCK;
|