@mu-crew/mu 3.12.0 → 3.13.1
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-3BARPJLY.js +44 -0
- package/dist/{chunk-R2SVBZAB.js → chunk-45KQLMEL.js} +193 -93
- package/dist/chunk-45KQLMEL.js.map +1 -0
- package/dist/{chunk-XV7J56GD.js → chunk-G434JKV2.js} +4 -3
- package/dist/{chunk-XV7J56GD.js.map → chunk-G434JKV2.js.map} +1 -1
- package/dist/{chunk-IRPTNVJC.js → chunk-KUGUFBWH.js} +8622 -6026
- package/dist/chunk-KUGUFBWH.js.map +1 -0
- package/dist/{chunk-77GBZ2KR.js → chunk-QITLNZEM.js} +3 -1
- package/dist/{chunk-77GBZ2KR.js.map → chunk-QITLNZEM.js.map} +1 -1
- package/dist/{chunk-TEGZOXML.js → chunk-VIEYQMQA.js} +12 -10
- package/dist/chunk-VIEYQMQA.js.map +1 -0
- package/dist/{chunk-L2ABBTYG.js → chunk-WI6AWCMK.js} +3 -1
- package/dist/{chunk-L2ABBTYG.js.map → chunk-WI6AWCMK.js.map} +1 -1
- package/dist/{cli-MDCJEU74.js → cli-CKOMHBXV.js} +3581 -107
- package/dist/cli-CKOMHBXV.js.map +1 -0
- package/dist/cli.js +4 -3
- package/dist/cli.js.map +1 -1
- package/dist/devtools-LS4ZEPWM.js +3772 -0
- package/dist/devtools-LS4ZEPWM.js.map +1 -0
- package/dist/extension/mu-pi.js +206 -61
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +309 -228
- package/dist/index.js +12 -5
- package/dist/tui-LFJ5P4Y2.js +40956 -0
- package/dist/tui-LFJ5P4Y2.js.map +1 -0
- package/dist/tui-sync-worker.js +4 -3
- package/dist/tui-sync-worker.js.map +1 -1
- package/dist/yank-XDOONQSL.js +13 -0
- package/docs/ARCHITECTURE.md +4 -1
- package/docs/ROADMAP.md +43 -38
- package/docs/VISION.md +8 -0
- package/docs/VOCABULARY.md +3 -1
- package/docs/architecture/dag.md +4 -0
- package/docs/architecture/sync.md +8 -0
- package/docs/architecture/tui.md +11 -2
- package/docs/guide/delegate.md +6 -4
- package/docs/guide/recovery.md +4 -0
- package/docs/reference/env.md +2 -2
- package/package.json +2 -1
- package/skills/mu/SKILL.md +12 -2
- package/skills/mu/recipes/adversarial-review.md +3 -0
- package/skills/mu/recipes/backlog-triage.md +2 -0
- package/skills/mu/recipes/findings.md +7 -0
- package/skills/mu/recipes/long-run.md +3 -1
- package/skills/mu/recipes/loop-until-done.md +3 -1
- package/skills/mu/recipes/orchestrator-loop.md +4 -0
- package/skills/mu/recipes/ultrathink.md +3 -1
- package/skills/mu/recipes/watcher.md +6 -1
- package/dist/chunk-IRPTNVJC.js.map +0 -1
- package/dist/chunk-PZ5AY32C.js +0 -10
- package/dist/chunk-R2SVBZAB.js.map +0 -1
- package/dist/chunk-TEGZOXML.js.map +0 -1
- package/dist/cli-MDCJEU74.js.map +0 -1
- package/dist/tui-LO75XA3O.js +0 -6452
- package/dist/tui-LO75XA3O.js.map +0 -1
- package/dist/yank-T3AYQTVR.js +0 -12
- /package/dist/{chunk-PZ5AY32C.js.map → chunk-3BARPJLY.js.map} +0 -0
- /package/dist/{yank-T3AYQTVR.js.map → yank-XDOONQSL.js.map} +0 -0
package/dist/extension/mu-pi.js
CHANGED
|
@@ -75,6 +75,7 @@ function delegateStatus(running, starting = 0, queued = 0, failed = 0, pending =
|
|
|
75
75
|
var DELEGATE_TIMEOUT_S = 3600;
|
|
76
76
|
var DELEGATE_MAX_DEFAULT = 16;
|
|
77
77
|
var DELEGATE_QUEUE_FACTOR = 4;
|
|
78
|
+
var PRUNE_FAILED_MS = 3e4;
|
|
78
79
|
function delegateMax(env = process.env) {
|
|
79
80
|
const n = Number(env.MU_DELEGATE_MAX);
|
|
80
81
|
return Number.isInteger(n) && n > 0 ? n : DELEGATE_MAX_DEFAULT;
|
|
@@ -188,13 +189,26 @@ ${agent.lastText ?? ""}`;
|
|
|
188
189
|
].join("\n");
|
|
189
190
|
case "died":
|
|
190
191
|
return `${who} died${took} before answering. ${fate}${ws}${evBlock}${tailBlock}`;
|
|
192
|
+
case "blocked": {
|
|
193
|
+
const b = agent.blocked;
|
|
194
|
+
const dialog = `${b?.kind ?? "dialog"}${b?.title ? ` "${b.title}"` : ""}`;
|
|
195
|
+
const lines = [
|
|
196
|
+
`${who} is blocked on a ${dialog} dialog${took} and has NOT finished; stopped waiting, so its answer will not arrive here. ${fate}${ws}`,
|
|
197
|
+
"Answer the dialog in its pane (attach), then wait again; or close it and record the check as UNVERIFIED.",
|
|
198
|
+
...ev,
|
|
199
|
+
...look,
|
|
200
|
+
`Wait again: mu agent wait ${name} -w ${W} --json${agent.afterRuns !== void 0 ? ` --after-runs ${agent.afterRuns}` : ""}`,
|
|
201
|
+
`Close: mu agent close ${name} -w ${W}`
|
|
202
|
+
];
|
|
203
|
+
return `${lines.join("\n")}${tailBlock}`;
|
|
204
|
+
}
|
|
191
205
|
case "timeout":
|
|
192
206
|
case "pending":
|
|
193
207
|
return [
|
|
194
208
|
`${who} is still running after ${timeoutS}s; stopped waiting, so its answer will not arrive here. ${fate}${ws}`,
|
|
195
209
|
...ev,
|
|
196
210
|
...look,
|
|
197
|
-
`Wait again: mu agent wait ${name} -w ${W} --json`
|
|
211
|
+
`Wait again: mu agent wait ${name} -w ${W} --json${agent.afterRuns !== void 0 ? ` --after-runs ${agent.afterRuns}` : ""}`
|
|
198
212
|
].join("\n");
|
|
199
213
|
default:
|
|
200
214
|
return `${who}: mu agent wait gave no result. ${fate}${ws}${evBlock}${tailBlock}`;
|
|
@@ -264,12 +278,13 @@ function modelCommand(cli, model, env = process.env) {
|
|
|
264
278
|
return `${base} --model ${shellArg(model)}`;
|
|
265
279
|
}
|
|
266
280
|
function registerDelegate(pi, run = defaultRunner()) {
|
|
267
|
-
if (!delegateEnabled()) return;
|
|
281
|
+
if (!delegateEnabled()) return { answerPending: () => false };
|
|
268
282
|
const inflight = /* @__PURE__ */ new Map();
|
|
269
283
|
let starting = 0;
|
|
270
284
|
const queue = [];
|
|
271
285
|
let queueSeq = 0;
|
|
272
286
|
const failed = /* @__PURE__ */ new Set();
|
|
287
|
+
let lastPruneAt = 0;
|
|
273
288
|
const arriving = /* @__PURE__ */ new Map();
|
|
274
289
|
let deliverySeq = 0;
|
|
275
290
|
let ui;
|
|
@@ -359,6 +374,9 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
359
374
|
const failure = (what, r) => new Error(`${what} failed (exit ${r.code}): ${(r.stderr || r.stdout).trim()}`);
|
|
360
375
|
function pruneFailed() {
|
|
361
376
|
if (failed.size === 0) return;
|
|
377
|
+
const now = Date.now();
|
|
378
|
+
if (now - lastPruneAt < PRUNE_FAILED_MS) return;
|
|
379
|
+
lastPruneAt = now;
|
|
362
380
|
void mu(["agent", "list", "-w", W, "--json"]).then((r) => {
|
|
363
381
|
const agents = json(r)?.agents;
|
|
364
382
|
if (!Array.isArray(agents)) return;
|
|
@@ -394,6 +412,12 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
394
412
|
);
|
|
395
413
|
}
|
|
396
414
|
const sent = out.send;
|
|
415
|
+
if (sent?.ok !== true && sent?.error === "AgentSendIndeterminateError") {
|
|
416
|
+
const why = typeof sent.message === "string" ? sent.message : "no reply";
|
|
417
|
+
throw new Error(
|
|
418
|
+
`mu agent send to ${W}/${name}: delivery unknown (${why}). Pane kept; do NOT resend blindly. Check with: mu agent read ${name} -w ${W} -n 20 (or attach), then close it with: mu agent close ${name} -w ${W}`
|
|
419
|
+
);
|
|
420
|
+
}
|
|
397
421
|
if (sent?.ok !== true) {
|
|
398
422
|
const c = await mu(["agent", "close", name, "-w", W]);
|
|
399
423
|
const pane = c.code === 0 ? "Pane closed." : `Pane kept; close it with: mu agent close ${name} -w ${W}`;
|
|
@@ -446,30 +470,32 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
446
470
|
const outcome = agent?.outcome;
|
|
447
471
|
const tail = outcome === "done" || outcome === "timeout" || outcome === "pending" || outcome === "error" ? void 0 : (await mu(["agent", "read", name, "-n", "50", "-w", W])).stdout;
|
|
448
472
|
let pane = { closed: false, why: "keep: true" };
|
|
449
|
-
|
|
473
|
+
let closing;
|
|
474
|
+
if (outcome === "blocked") pane = { closed: false, why: "waiting on a dialog" };
|
|
475
|
+
else if (outcome !== "done" && outcome !== "empty")
|
|
450
476
|
pane = { closed: false, why: "kept as evidence" };
|
|
451
|
-
else if (!keep)
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
477
|
+
else if (!keep) closing = mu(["agent", "close", name, "-w", W]);
|
|
478
|
+
const recording = record ? writeRecord(
|
|
479
|
+
record.target,
|
|
480
|
+
name,
|
|
481
|
+
recordNote(record.label, name, outcome, agent?.lastText, extras.elapsedMs ?? 0)
|
|
482
|
+
) : void 0;
|
|
483
|
+
const [closed, recorded] = await Promise.all([closing, recording]);
|
|
484
|
+
if (closed)
|
|
485
|
+
pane = closed.code === 0 ? { closed: true } : { closed: false, why: `close refused: ${(closed.stderr || closed.stdout).trim()}` };
|
|
455
486
|
if (outcome === "error" && !pane.closed) {
|
|
456
487
|
failed.add(name);
|
|
457
488
|
showStatus();
|
|
458
489
|
}
|
|
459
490
|
if (outcome !== "done") {
|
|
460
491
|
const sessionFile = agent?.sessionFile ?? extras.sessionFile;
|
|
461
|
-
const partial = sessionFile ? partialCopy(name, sessionFile) : void 0;
|
|
492
|
+
const partial = sessionFile && outcome !== "blocked" ? partialCopy(name, sessionFile) : void 0;
|
|
462
493
|
extras = {
|
|
463
494
|
...extras,
|
|
464
495
|
...sessionFile ? { sessionFile } : {},
|
|
465
496
|
...partial ? { partial } : {}
|
|
466
497
|
};
|
|
467
498
|
}
|
|
468
|
-
const recorded = record ? await writeRecord(
|
|
469
|
-
record.target,
|
|
470
|
-
name,
|
|
471
|
-
recordNote(record.label, name, outcome, agent?.lastText, extras.elapsedMs ?? 0)
|
|
472
|
-
) : void 0;
|
|
473
499
|
const message = delegateMessage(name, agent, pane, { ...extras, ...tail ? { tail } : {} });
|
|
474
500
|
const content = recorded ? `${message}
|
|
475
501
|
|
|
@@ -868,6 +894,7 @@ ${evidence.join("\n")}`;
|
|
|
868
894
|
else process.stderr.write(`mu: ${msg}
|
|
869
895
|
`);
|
|
870
896
|
});
|
|
897
|
+
return { answerPending: () => arriving.size > 0 };
|
|
871
898
|
}
|
|
872
899
|
|
|
873
900
|
// extension/nudge.ts
|
|
@@ -881,6 +908,10 @@ var MARK_START = "<!-- mu:keep-driving -->";
|
|
|
881
908
|
var MARK_END = "<!-- /mu:keep-driving -->";
|
|
882
909
|
var WAIT_HINT_MAX = 8;
|
|
883
910
|
var notNested = () => false;
|
|
911
|
+
var noHold = () => void 0;
|
|
912
|
+
function withQueuedInput(hold) {
|
|
913
|
+
return (ctx) => ctx?.hasPendingMessages?.() ? "answer" : hold(ctx);
|
|
914
|
+
}
|
|
884
915
|
function noUI(ctx) {
|
|
885
916
|
return ctx?.hasUI === false;
|
|
886
917
|
}
|
|
@@ -1053,25 +1084,29 @@ function dispatchedTasks(command) {
|
|
|
1053
1084
|
return out;
|
|
1054
1085
|
}
|
|
1055
1086
|
async function inProgress(run, workstreams) {
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1087
|
+
const results = await Promise.all(
|
|
1088
|
+
workstreams.map(async (w) => {
|
|
1089
|
+
const r = await run([
|
|
1090
|
+
"task",
|
|
1091
|
+
"list",
|
|
1092
|
+
"--status",
|
|
1093
|
+
"IN_PROGRESS",
|
|
1094
|
+
"--json",
|
|
1095
|
+
"--sort",
|
|
1096
|
+
"recency",
|
|
1097
|
+
...w ? ["-w", w] : []
|
|
1098
|
+
]);
|
|
1099
|
+
if (r.code !== 0) return void 0;
|
|
1100
|
+
try {
|
|
1101
|
+
const items = JSON.parse(r.stdout).items ?? [];
|
|
1102
|
+
return items.flatMap((t) => t.name ? [`${t.workstreamName ?? w}/${t.name}`] : []);
|
|
1103
|
+
} catch {
|
|
1104
|
+
return void 0;
|
|
1105
|
+
}
|
|
1106
|
+
})
|
|
1107
|
+
);
|
|
1108
|
+
if (results.some((r) => r === void 0)) return void 0;
|
|
1109
|
+
return [...new Set(results.flatMap((r) => r ?? []))];
|
|
1075
1110
|
}
|
|
1076
1111
|
function nudgeText(rule, refs) {
|
|
1077
1112
|
const shown = refs.slice(0, WAIT_HINT_MAX).join(" ");
|
|
@@ -1086,7 +1121,7 @@ function breadcrumb(run, args) {
|
|
|
1086
1121
|
void run(args).catch(() => {
|
|
1087
1122
|
});
|
|
1088
1123
|
}
|
|
1089
|
-
function parallelSettle(pi) {
|
|
1124
|
+
function parallelSettle(pi, hold = noHold) {
|
|
1090
1125
|
const handlers = [];
|
|
1091
1126
|
const api = {
|
|
1092
1127
|
on(event, handler) {
|
|
@@ -1111,7 +1146,15 @@ function parallelSettle(pi) {
|
|
|
1111
1146
|
}
|
|
1112
1147
|
})
|
|
1113
1148
|
);
|
|
1114
|
-
const
|
|
1149
|
+
const late = hold(ctx);
|
|
1150
|
+
const fired = results.flatMap((r) => {
|
|
1151
|
+
if (r === void 0) return [];
|
|
1152
|
+
if (late === "answer" || late === "blocked" && r.continue === true) {
|
|
1153
|
+
r.yielded?.();
|
|
1154
|
+
return [];
|
|
1155
|
+
}
|
|
1156
|
+
return [r];
|
|
1157
|
+
});
|
|
1115
1158
|
if (fired.length === 0) return void 0;
|
|
1116
1159
|
const prior = event?.entries ?? [];
|
|
1117
1160
|
return {
|
|
@@ -1138,7 +1181,7 @@ function bashCommand(event) {
|
|
|
1138
1181
|
const e = event;
|
|
1139
1182
|
return e.toolName === "bash" && typeof e.input?.command === "string" ? e.input.command : void 0;
|
|
1140
1183
|
}
|
|
1141
|
-
function registerNudge(pi, run = defaultRunner(), skillMd = readSkill(), nested = notNested) {
|
|
1184
|
+
function registerNudge(pi, run = defaultRunner(), skillMd = readSkill(), nested = notNested, hold = noHold) {
|
|
1142
1185
|
if (!nudgeEnabled()) return;
|
|
1143
1186
|
const rule = skillMd === void 0 ? void 0 : keepDrivingRule(skillMd);
|
|
1144
1187
|
if (rule === void 0) return;
|
|
@@ -1153,12 +1196,16 @@ function registerNudge(pi, run = defaultRunner(), skillMd = readSkill(), nested
|
|
|
1153
1196
|
if (cmd === void 0) return;
|
|
1154
1197
|
for (const ws of dispatchedWorkstreams(cmd) ?? []) armed.add(ws);
|
|
1155
1198
|
});
|
|
1156
|
-
pi.on("agent_before_settle", async (event) => {
|
|
1157
|
-
if (fired || armed.size === 0 || nested()) return;
|
|
1199
|
+
pi.on("agent_before_settle", async (event, ctx) => {
|
|
1200
|
+
if (fired || armed.size === 0 || nested() || hold(ctx)) return;
|
|
1158
1201
|
if (outcomeOf(event) !== "completed") return;
|
|
1159
1202
|
fired = true;
|
|
1160
1203
|
const refs = await inProgress(run, [...armed]);
|
|
1161
1204
|
if (refs === void 0 || refs.length === 0) return;
|
|
1205
|
+
if (hold(ctx)) {
|
|
1206
|
+
fired = false;
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1162
1209
|
const text = nudgeText(rule, refs);
|
|
1163
1210
|
const logWs = [...armed].find((w) => w !== "");
|
|
1164
1211
|
breadcrumb(run, [
|
|
@@ -1172,7 +1219,10 @@ function registerNudge(pi, run = defaultRunner(), skillMd = readSkill(), nested
|
|
|
1172
1219
|
entries: [
|
|
1173
1220
|
{ type: "custom_message", customType: NUDGE_MESSAGE_TYPE, content: text, display: true }
|
|
1174
1221
|
],
|
|
1175
|
-
continue: true
|
|
1222
|
+
continue: true,
|
|
1223
|
+
yielded: () => {
|
|
1224
|
+
fired = false;
|
|
1225
|
+
}
|
|
1176
1226
|
};
|
|
1177
1227
|
});
|
|
1178
1228
|
}
|
|
@@ -1203,7 +1253,7 @@ function closeNudgeText(workstream, names) {
|
|
|
1203
1253
|
"If you are blocked or need an answer, say so in one line and stop; the orchestrator will read your pane."
|
|
1204
1254
|
].join("\n");
|
|
1205
1255
|
}
|
|
1206
|
-
function registerCloseNudge(pi, run = defaultRunner(), env = process.env, nested = notNested) {
|
|
1256
|
+
function registerCloseNudge(pi, run = defaultRunner(), env = process.env, nested = notNested, hold = noHold) {
|
|
1207
1257
|
if (!nudgeEnabled(env)) return;
|
|
1208
1258
|
const me = workerIdentity(env);
|
|
1209
1259
|
if (me === void 0) return;
|
|
@@ -1212,11 +1262,15 @@ function registerCloseNudge(pi, run = defaultRunner(), env = process.env, nested
|
|
|
1212
1262
|
fired = false;
|
|
1213
1263
|
});
|
|
1214
1264
|
pi.on("agent_before_settle", async (event, ctx) => {
|
|
1215
|
-
if (fired || nested() || noUI(ctx)) return;
|
|
1265
|
+
if (fired || nested() || noUI(ctx) || hold(ctx)) return;
|
|
1216
1266
|
if (outcomeOf(event) !== "completed") return;
|
|
1217
1267
|
fired = true;
|
|
1218
1268
|
const names = await ownedInProgress(run, me.agent, me.workstream);
|
|
1219
1269
|
if (names === void 0 || names.length === 0) return;
|
|
1270
|
+
if (hold(ctx)) {
|
|
1271
|
+
fired = false;
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1220
1274
|
breadcrumb(run, [
|
|
1221
1275
|
"log",
|
|
1222
1276
|
"-w",
|
|
@@ -1234,7 +1288,10 @@ function registerCloseNudge(pi, run = defaultRunner(), env = process.env, nested
|
|
|
1234
1288
|
display: true
|
|
1235
1289
|
}
|
|
1236
1290
|
],
|
|
1237
|
-
continue: true
|
|
1291
|
+
continue: true,
|
|
1292
|
+
yielded: () => {
|
|
1293
|
+
fired = false;
|
|
1294
|
+
}
|
|
1238
1295
|
};
|
|
1239
1296
|
});
|
|
1240
1297
|
}
|
|
@@ -1252,8 +1309,9 @@ async function briefRefuted(run, ws, id) {
|
|
|
1252
1309
|
function refuteNudgeText(refs) {
|
|
1253
1310
|
return `[mu] dispatched ${refs.join(", ")} with an unrefuted brief: refute it (delegate, record) or note REFUTE-EXEMPT: <why>`;
|
|
1254
1311
|
}
|
|
1255
|
-
function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
|
|
1312
|
+
function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested, hold = noHold) {
|
|
1256
1313
|
if (!nudgeEnabled()) return;
|
|
1314
|
+
const answerDue = (ctx) => hold(ctx) === "answer";
|
|
1257
1315
|
const armed = /* @__PURE__ */ new Map();
|
|
1258
1316
|
let fired = false;
|
|
1259
1317
|
pi.on("input", () => {
|
|
@@ -1268,13 +1326,17 @@ function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
|
|
|
1268
1326
|
}
|
|
1269
1327
|
});
|
|
1270
1328
|
pi.on("agent_before_settle", async (event, ctx) => {
|
|
1271
|
-
if (fired || armed.size === 0 || nested() || noUI(ctx)) return;
|
|
1329
|
+
if (fired || armed.size === 0 || nested() || noUI(ctx) || answerDue(ctx)) return;
|
|
1272
1330
|
if (outcomeOf(event) !== "completed") return;
|
|
1273
1331
|
fired = true;
|
|
1274
1332
|
const tasks = [...armed];
|
|
1275
1333
|
const refuted = await Promise.all(tasks.map(([, t]) => briefRefuted(run, t.ws, t.id)));
|
|
1276
1334
|
const refs = tasks.flatMap(([ref], i) => refuted[i] === false ? [ref] : []);
|
|
1277
1335
|
if (refs.length === 0) return;
|
|
1336
|
+
if (answerDue(ctx)) {
|
|
1337
|
+
fired = false;
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1278
1340
|
const logWs = [...armed.values()].find((t) => t.ws !== "")?.ws;
|
|
1279
1341
|
breadcrumb(run, [
|
|
1280
1342
|
"log",
|
|
@@ -1291,13 +1353,16 @@ function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
|
|
|
1291
1353
|
content: refuteNudgeText(refs),
|
|
1292
1354
|
display: true
|
|
1293
1355
|
}
|
|
1294
|
-
]
|
|
1356
|
+
],
|
|
1357
|
+
yielded: () => {
|
|
1358
|
+
fired = false;
|
|
1359
|
+
}
|
|
1295
1360
|
};
|
|
1296
1361
|
});
|
|
1297
1362
|
}
|
|
1298
1363
|
|
|
1299
1364
|
// extension/mu-pi.ts
|
|
1300
|
-
var EXT_VERSION = true ? "3.
|
|
1365
|
+
var EXT_VERSION = true ? "3.13.1" : void 0;
|
|
1301
1366
|
var FRESH_COMMAND = "mu-fresh";
|
|
1302
1367
|
var FRESH_TIMEOUT_MS = 3e4;
|
|
1303
1368
|
function commandName(name) {
|
|
@@ -1387,6 +1452,50 @@ function capText(text) {
|
|
|
1387
1452
|
return `${cut.replace(/\uFFFD$/, "")}
|
|
1388
1453
|
${LAST_TEXT_TRUNCATED}`;
|
|
1389
1454
|
}
|
|
1455
|
+
var UI_PROMPTS = /* @__PURE__ */ Symbol.for("mu.pi.uiPrompts");
|
|
1456
|
+
function uiPrompts() {
|
|
1457
|
+
const g = globalThis;
|
|
1458
|
+
g[UI_PROMPTS] ??= { open: [], since: 0 };
|
|
1459
|
+
return g[UI_PROMPTS];
|
|
1460
|
+
}
|
|
1461
|
+
function uiBlocked() {
|
|
1462
|
+
const u = uiPrompts();
|
|
1463
|
+
const top = u.open[u.open.length - 1];
|
|
1464
|
+
if (!top) return void 0;
|
|
1465
|
+
return {
|
|
1466
|
+
kind: top.kind,
|
|
1467
|
+
...top.title !== void 0 ? { title: top.title } : {},
|
|
1468
|
+
since: u.since
|
|
1469
|
+
};
|
|
1470
|
+
}
|
|
1471
|
+
function isUiBlocked() {
|
|
1472
|
+
return uiPrompts().open.length > 0;
|
|
1473
|
+
}
|
|
1474
|
+
function promptOf(event) {
|
|
1475
|
+
const e = typeof event === "object" && event !== null ? event : {};
|
|
1476
|
+
const kind = typeof e.kind === "string" ? e.kind : "custom";
|
|
1477
|
+
const title = typeof e.title === "string" && e.title !== "" ? e.title : void 0;
|
|
1478
|
+
return { kind, ...title !== void 0 ? { title } : {} };
|
|
1479
|
+
}
|
|
1480
|
+
function trackUiPrompts(pi, onStart = () => {
|
|
1481
|
+
}) {
|
|
1482
|
+
pi.on("ui_prompt_start", (e) => {
|
|
1483
|
+
const u = uiPrompts();
|
|
1484
|
+
if (u.open.length === 0) u.since = Date.now();
|
|
1485
|
+
u.open.push(promptOf(e));
|
|
1486
|
+
onStart();
|
|
1487
|
+
});
|
|
1488
|
+
pi.on("session_start", () => {
|
|
1489
|
+
uiPrompts().open.length = 0;
|
|
1490
|
+
});
|
|
1491
|
+
pi.on("ui_prompt_end", (e) => {
|
|
1492
|
+
const u = uiPrompts();
|
|
1493
|
+
const { kind } = promptOf(e);
|
|
1494
|
+
let i = u.open.length - 1;
|
|
1495
|
+
while (i >= 0 && u.open[i]?.kind !== kind) i--;
|
|
1496
|
+
u.open.splice(i >= 0 ? i : u.open.length - 1, 1);
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1390
1499
|
function inodeOf(path) {
|
|
1391
1500
|
try {
|
|
1392
1501
|
return statSync2(path).ino;
|
|
@@ -1437,18 +1546,24 @@ function registerPrompts(pi) {
|
|
|
1437
1546
|
});
|
|
1438
1547
|
}
|
|
1439
1548
|
function muPi(pi, run = defaultRunner()) {
|
|
1440
|
-
registerDelegate(pi, run);
|
|
1549
|
+
const delegates = registerDelegate(pi, run);
|
|
1441
1550
|
registerPrompts(pi);
|
|
1442
1551
|
const nested = serveCtl(pi);
|
|
1443
|
-
const
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1552
|
+
const hold = withQueuedInput(
|
|
1553
|
+
() => delegates.answerPending() ? "answer" : isUiBlocked() ? "blocked" : void 0
|
|
1554
|
+
);
|
|
1555
|
+
const settle = parallelSettle(pi, hold);
|
|
1556
|
+
registerNudge(settle.api, run, void 0, nested, hold);
|
|
1557
|
+
registerCloseNudge(settle.api, run, process.env, nested, hold);
|
|
1558
|
+
registerRefuteNudge(settle.api, run, nested, hold);
|
|
1447
1559
|
settle.flush();
|
|
1448
1560
|
}
|
|
1449
1561
|
function serveCtl(pi) {
|
|
1450
1562
|
const sock = process.env.MU_CTL_SOCK;
|
|
1451
|
-
if (!sock)
|
|
1563
|
+
if (!sock) {
|
|
1564
|
+
trackUiPrompts(pi);
|
|
1565
|
+
return () => false;
|
|
1566
|
+
}
|
|
1452
1567
|
const sockPath = sock;
|
|
1453
1568
|
const piVersion = detectPiVersion();
|
|
1454
1569
|
const map = sharedMap();
|
|
@@ -1471,7 +1586,15 @@ function serveCtl(pi) {
|
|
|
1471
1586
|
since: g.since,
|
|
1472
1587
|
runs: g.runs,
|
|
1473
1588
|
pending: g.ctx?.hasPendingMessages() ?? false,
|
|
1474
|
-
...sessionFileOf(g.ctx)
|
|
1589
|
+
...sessionFileOf(g.ctx),
|
|
1590
|
+
...blockedField()
|
|
1591
|
+
});
|
|
1592
|
+
const blockedField = () => {
|
|
1593
|
+
const b = uiBlocked();
|
|
1594
|
+
return b ? { blocked: b } : {};
|
|
1595
|
+
};
|
|
1596
|
+
trackUiPrompts(pi, () => {
|
|
1597
|
+
for (const w of [...g.waiters]) w("blocked");
|
|
1475
1598
|
});
|
|
1476
1599
|
const settleFresh = (r) => {
|
|
1477
1600
|
const f = g.fresh;
|
|
@@ -1513,7 +1636,7 @@ function serveCtl(pi) {
|
|
|
1513
1636
|
g.lastError = g.endError;
|
|
1514
1637
|
g.endError = void 0;
|
|
1515
1638
|
g.sessionFile = sessionFileOf(c).sessionFile;
|
|
1516
|
-
for (const w of [...g.waiters]) w();
|
|
1639
|
+
for (const w of [...g.waiters]) w("settle");
|
|
1517
1640
|
});
|
|
1518
1641
|
pi.registerCommand(FRESH_COMMAND, {
|
|
1519
1642
|
description: "mu internal: new session + the prompt mu queued (run by mu agent send --fresh)",
|
|
@@ -1643,11 +1766,19 @@ function serveCtl(pi) {
|
|
|
1643
1766
|
case "command":
|
|
1644
1767
|
return command(req);
|
|
1645
1768
|
case "wait":
|
|
1646
|
-
return wait(
|
|
1769
|
+
return wait(
|
|
1770
|
+
num(req, "afterRuns"),
|
|
1771
|
+
num(req, "timeoutMs"),
|
|
1772
|
+
conn,
|
|
1773
|
+
req.returnOnBlocked === true
|
|
1774
|
+
);
|
|
1647
1775
|
case "abort":
|
|
1648
1776
|
if (!g.ctx) return fail("no pi context yet");
|
|
1649
|
-
|
|
1650
|
-
|
|
1777
|
+
{
|
|
1778
|
+
const wasBusy = !g.ctx.isIdle();
|
|
1779
|
+
if (wasBusy) g.ctx.abort();
|
|
1780
|
+
return { v: V, ok: true, state: g.state, wasBusy };
|
|
1781
|
+
}
|
|
1651
1782
|
case "interrupt":
|
|
1652
1783
|
return interrupt(req, conn);
|
|
1653
1784
|
default:
|
|
@@ -1675,10 +1806,18 @@ function serveCtl(pi) {
|
|
|
1675
1806
|
...g.lastError !== void 0 ? { lastError: g.lastError } : {},
|
|
1676
1807
|
...g.sessionFile !== void 0 ? { sessionFile: g.sessionFile } : {}
|
|
1677
1808
|
});
|
|
1678
|
-
function wait(afterRuns, timeoutMs, conn) {
|
|
1809
|
+
function wait(afterRuns, timeoutMs, conn, onBlocked = false) {
|
|
1679
1810
|
if (afterRuns !== void 0 && g.runs > afterRuns && g.state === "idle") {
|
|
1680
|
-
return Promise.resolve({
|
|
1811
|
+
return Promise.resolve({
|
|
1812
|
+
v: V,
|
|
1813
|
+
ok: true,
|
|
1814
|
+
...status(),
|
|
1815
|
+
...settledRun(),
|
|
1816
|
+
ended: "settled"
|
|
1817
|
+
});
|
|
1681
1818
|
}
|
|
1819
|
+
const blockedReply = () => ({ v: V, ok: true, ...status(), ended: "blocked" });
|
|
1820
|
+
if (onBlocked && isUiBlocked()) return Promise.resolve(blockedReply());
|
|
1682
1821
|
return new Promise((resolve) => {
|
|
1683
1822
|
let timer;
|
|
1684
1823
|
const done = (r) => {
|
|
@@ -1687,9 +1826,13 @@ function serveCtl(pi) {
|
|
|
1687
1826
|
conn.off("close", onClose);
|
|
1688
1827
|
resolve(r);
|
|
1689
1828
|
};
|
|
1690
|
-
const waiter = () => {
|
|
1829
|
+
const waiter = (why) => {
|
|
1830
|
+
if (why === "blocked") {
|
|
1831
|
+
if (onBlocked) done(blockedReply());
|
|
1832
|
+
return;
|
|
1833
|
+
}
|
|
1691
1834
|
if (afterRuns !== void 0 && g.runs <= afterRuns) return;
|
|
1692
|
-
done({ v: V, ok: true, ...status(), ...settledRun() });
|
|
1835
|
+
done({ v: V, ok: true, ...status(), ...settledRun(), ended: "settled" });
|
|
1693
1836
|
};
|
|
1694
1837
|
const onClose = () => done(fail("client closed"));
|
|
1695
1838
|
g.waiters.add(waiter);
|
|
@@ -1811,8 +1954,10 @@ export {
|
|
|
1811
1954
|
LIVE_PROBE_MS,
|
|
1812
1955
|
commandName,
|
|
1813
1956
|
muPi as default,
|
|
1957
|
+
isUiBlocked,
|
|
1814
1958
|
lastAssistantError,
|
|
1815
1959
|
lastAssistantText,
|
|
1816
|
-
promptsDir
|
|
1960
|
+
promptsDir,
|
|
1961
|
+
uiBlocked
|
|
1817
1962
|
};
|
|
1818
1963
|
//# sourceMappingURL=mu-pi.js.map
|