@mu-crew/mu 3.11.3 → 3.12.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-F7ZBF6I7.js → chunk-IRPTNVJC.js} +3 -2
- package/dist/chunk-IRPTNVJC.js.map +1 -0
- package/dist/{chunk-3L5KO3PX.js → chunk-TEGZOXML.js} +2 -2
- package/dist/{chunk-LEORAGKV.js → chunk-XV7J56GD.js} +2 -2
- package/dist/{cli-GJIO7GWD.js → cli-MDCJEU74.js} +6 -5
- package/dist/cli-MDCJEU74.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/extension/mu-pi.js +91 -20
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -2
- package/dist/{tui-WHCLVCYE.js → tui-LO75XA3O.js} +3 -3
- package/docs/architecture/control-socket.md +1 -1
- package/docs/guide/delegate.md +5 -0
- package/docs/reference/naming.md +1 -1
- package/package.json +1 -1
- package/dist/chunk-F7ZBF6I7.js.map +0 -1
- package/dist/cli-GJIO7GWD.js.map +0 -1
- /package/dist/{chunk-3L5KO3PX.js.map → chunk-TEGZOXML.js.map} +0 -0
- /package/dist/{chunk-LEORAGKV.js.map → chunk-XV7J56GD.js.map} +0 -0
- /package/dist/{tui-WHCLVCYE.js.map → tui-LO75XA3O.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -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-
|
|
50
|
+
var { runCli } = await import("./cli-MDCJEU74.js");
|
|
51
51
|
await runCli(process.argv);
|
|
52
52
|
//# sourceMappingURL=cli.js.map
|
package/dist/extension/mu-pi.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
linkSync,
|
|
6
6
|
mkdirSync as mkdirSync2,
|
|
7
7
|
readdirSync,
|
|
8
|
-
readFileSync as
|
|
8
|
+
readFileSync as readFileSync3,
|
|
9
9
|
realpathSync,
|
|
10
10
|
rmSync,
|
|
11
11
|
statSync as statSync2
|
|
@@ -44,7 +44,7 @@ var LineDecoder = class {
|
|
|
44
44
|
|
|
45
45
|
// extension/delegate.ts
|
|
46
46
|
import { execFile } from "child_process";
|
|
47
|
-
import { existsSync, mkdirSync, statSync, writeFileSync } from "fs";
|
|
47
|
+
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
48
48
|
import { delimiter, join as join2 } from "path";
|
|
49
49
|
import { fileURLToPath } from "url";
|
|
50
50
|
|
|
@@ -116,6 +116,37 @@ function defaultRunner() {
|
|
|
116
116
|
);
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
|
+
function lastAssistantTextIn(sessionFile) {
|
|
120
|
+
let raw;
|
|
121
|
+
try {
|
|
122
|
+
raw = readFileSync(sessionFile, "utf8");
|
|
123
|
+
} catch {
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
const lines = raw.split("\n");
|
|
127
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
128
|
+
const line = lines[i];
|
|
129
|
+
if (!line?.includes('"assistant"')) continue;
|
|
130
|
+
try {
|
|
131
|
+
const e = JSON.parse(line);
|
|
132
|
+
if (e.message?.role !== "assistant") continue;
|
|
133
|
+
const c = e.message.content;
|
|
134
|
+
const text = typeof c === "string" ? c : Array.isArray(c) ? c.map((p) => {
|
|
135
|
+
const q = p;
|
|
136
|
+
return q.type === "text" && typeof q.text === "string" ? q.text : "";
|
|
137
|
+
}).join("") : "";
|
|
138
|
+
if (text.trim()) return text;
|
|
139
|
+
} catch {
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return void 0;
|
|
143
|
+
}
|
|
144
|
+
function evidenceLines(x) {
|
|
145
|
+
return [
|
|
146
|
+
x.partial ? `Partial answer so far: ${x.partial}` : void 0,
|
|
147
|
+
x.sessionFile ? `Session: ${x.sessionFile}` : void 0
|
|
148
|
+
].filter((v) => v !== void 0);
|
|
149
|
+
}
|
|
119
150
|
function formatElapsed(ms) {
|
|
120
151
|
const t = Math.max(0, Math.round(ms / 1e3));
|
|
121
152
|
if (t < 60) return `${t}s`;
|
|
@@ -137,31 +168,36 @@ function delegateMessage(name, agent, pane, x = {}) {
|
|
|
137
168
|
Pane tail:
|
|
138
169
|
${x.tail.trimEnd()}` : "";
|
|
139
170
|
const ws = x.workspace ? ` Workspace: ${x.workspace}` : "";
|
|
171
|
+
const ev = evidenceLines(x);
|
|
172
|
+
const evBlock = ev.length > 0 ? `
|
|
173
|
+
${ev.join("\n")}` : "";
|
|
140
174
|
switch (agent?.outcome) {
|
|
141
175
|
case "done":
|
|
142
176
|
return `${who} finished${took}. ${fate}${ws}
|
|
143
177
|
|
|
144
178
|
${agent.lastText ?? ""}`;
|
|
145
179
|
case "empty":
|
|
146
|
-
return `${who} finished${took} without a text answer. ${fate}${ws}${tailBlock}`;
|
|
180
|
+
return `${who} finished${took} without a text answer. ${fate}${ws}${evBlock}${tailBlock}`;
|
|
147
181
|
case "error":
|
|
148
182
|
return [
|
|
149
183
|
`${who} stopped on an API error${took}, after pi's own retries: ${(agent.lastError ?? "unknown error").replace(/[.\s]+$/, "")}. ${fate}${ws}`,
|
|
150
184
|
"Decide: re-issue the call, or record the check as UNVERIFIED.",
|
|
185
|
+
...ev,
|
|
151
186
|
...look,
|
|
152
187
|
`Close: mu agent close ${name} -w ${W}`
|
|
153
188
|
].join("\n");
|
|
154
189
|
case "died":
|
|
155
|
-
return `${who} died${took} before answering. ${fate}${ws}${tailBlock}`;
|
|
190
|
+
return `${who} died${took} before answering. ${fate}${ws}${evBlock}${tailBlock}`;
|
|
156
191
|
case "timeout":
|
|
157
192
|
case "pending":
|
|
158
193
|
return [
|
|
159
194
|
`${who} is still running after ${timeoutS}s; stopped waiting, so its answer will not arrive here. ${fate}${ws}`,
|
|
195
|
+
...ev,
|
|
160
196
|
...look,
|
|
161
197
|
`Wait again: mu agent wait ${name} -w ${W} --json`
|
|
162
198
|
].join("\n");
|
|
163
199
|
default:
|
|
164
|
-
return `${who}: mu agent wait gave no result. ${fate}${ws}${tailBlock}`;
|
|
200
|
+
return `${who}: mu agent wait gave no result. ${fate}${ws}${evBlock}${tailBlock}`;
|
|
165
201
|
}
|
|
166
202
|
}
|
|
167
203
|
function droppedAnswersDir() {
|
|
@@ -264,12 +300,12 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
264
300
|
const a = arriving.get(delivery);
|
|
265
301
|
if (a) a.queued = true;
|
|
266
302
|
};
|
|
267
|
-
const saveCopy = (name, content) => {
|
|
303
|
+
const saveCopy = (name, content, kind = "") => {
|
|
268
304
|
try {
|
|
269
305
|
const dir = droppedAnswersDir();
|
|
270
306
|
mkdirSync(dir, { recursive: true });
|
|
271
307
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
272
|
-
const path = join2(dir, `${stamp}_${name}.md`);
|
|
308
|
+
const path = join2(dir, `${stamp}_${name}${kind}.md`);
|
|
273
309
|
writeFileSync(path, `${content}
|
|
274
310
|
`);
|
|
275
311
|
return path;
|
|
@@ -277,6 +313,10 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
277
313
|
return void 0;
|
|
278
314
|
}
|
|
279
315
|
};
|
|
316
|
+
const partialCopy = (name, sessionFile) => {
|
|
317
|
+
const text = lastAssistantTextIn(sessionFile);
|
|
318
|
+
return text ? saveCopy(name, text, ".partial") : void 0;
|
|
319
|
+
};
|
|
280
320
|
const forget = (name) => {
|
|
281
321
|
inflight.delete(name);
|
|
282
322
|
drain();
|
|
@@ -369,7 +409,8 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
369
409
|
// extension's reply carries no runs.
|
|
370
410
|
runs: typeof sent.runs === "number" ? sent.runs : 0,
|
|
371
411
|
...typeof attach === "string" ? { attach } : {},
|
|
372
|
-
...typeof wsPath === "string" ? { workspace: wsPath } : {}
|
|
412
|
+
...typeof wsPath === "string" ? { workspace: wsPath } : {},
|
|
413
|
+
...typeof sent.sessionFile === "string" ? { sessionFile: sent.sessionFile } : {}
|
|
373
414
|
};
|
|
374
415
|
}
|
|
375
416
|
const recordLabel = (params, name) => typeof params.label === "string" && params.label.trim() ? params.label.trim() : name;
|
|
@@ -415,6 +456,15 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
415
456
|
failed.add(name);
|
|
416
457
|
showStatus();
|
|
417
458
|
}
|
|
459
|
+
if (outcome !== "done") {
|
|
460
|
+
const sessionFile = agent?.sessionFile ?? extras.sessionFile;
|
|
461
|
+
const partial = sessionFile ? partialCopy(name, sessionFile) : void 0;
|
|
462
|
+
extras = {
|
|
463
|
+
...extras,
|
|
464
|
+
...sessionFile ? { sessionFile } : {},
|
|
465
|
+
...partial ? { partial } : {}
|
|
466
|
+
};
|
|
467
|
+
}
|
|
418
468
|
const recorded = record ? await writeRecord(
|
|
419
469
|
record.target,
|
|
420
470
|
name,
|
|
@@ -445,6 +495,8 @@ ${recorded}` : message;
|
|
|
445
495
|
answer: outcome === "done" ? agent?.lastText ?? null : null,
|
|
446
496
|
elapsedMs: extras.elapsedMs ?? null,
|
|
447
497
|
workspace: extras.workspace ?? null,
|
|
498
|
+
sessionFile: agent?.sessionFile ?? extras.sessionFile ?? null,
|
|
499
|
+
partial: extras.partial ?? null,
|
|
448
500
|
delivery
|
|
449
501
|
}
|
|
450
502
|
},
|
|
@@ -476,7 +528,7 @@ ${recorded}` : message;
|
|
|
476
528
|
cwd = typeof params.cwd === "string" && params.cwd ? params.cwd : ctx?.cwd ?? process.cwd();
|
|
477
529
|
if (!isDir(cwd)) throw new Error(`mu_delegate: cwd ${cwd} is not a directory`);
|
|
478
530
|
}
|
|
479
|
-
const { name, runs, attach, workspace } = await spawn(
|
|
531
|
+
const { name, runs, attach, workspace, sessionFile } = await spawn(
|
|
480
532
|
params,
|
|
481
533
|
brief ? `${brief}
|
|
482
534
|
|
|
@@ -487,6 +539,7 @@ ${task}` : task,
|
|
|
487
539
|
const entry = {
|
|
488
540
|
abort: new AbortController(),
|
|
489
541
|
cancelling: false,
|
|
542
|
+
...sessionFile ? { sessionFile } : {},
|
|
490
543
|
...record ? { record: { target: record, label: recordLabel(params, name) } } : {}
|
|
491
544
|
};
|
|
492
545
|
inflight.set(name, entry);
|
|
@@ -522,7 +575,8 @@ ${task}` : task,
|
|
|
522
575
|
elapsedMs: Date.now() - started,
|
|
523
576
|
...queuedAs ? { queuedAs } : {},
|
|
524
577
|
...attach ? { attach } : {},
|
|
525
|
-
...workspace ? { workspace } : {}
|
|
578
|
+
...workspace ? { workspace } : {},
|
|
579
|
+
...entry.sessionFile ? { sessionFile: entry.sessionFile } : {}
|
|
526
580
|
},
|
|
527
581
|
delivery,
|
|
528
582
|
entry.record
|
|
@@ -733,6 +787,12 @@ ${task}` : task,
|
|
|
733
787
|
}
|
|
734
788
|
failed.delete(name);
|
|
735
789
|
let text = `Aborted ${W}/${name}.`;
|
|
790
|
+
const sessionFile = entry?.sessionFile;
|
|
791
|
+
const partial = sessionFile ? partialCopy(name, sessionFile) : void 0;
|
|
792
|
+
const evidence = evidenceLines({
|
|
793
|
+
...sessionFile ? { sessionFile } : {},
|
|
794
|
+
...partial ? { partial } : {}
|
|
795
|
+
});
|
|
736
796
|
if (entry?.record)
|
|
737
797
|
text += ` ${await writeRecord(entry.record.target, name, recordNote(entry.record.label, name, "cancelled", void 0, 0))}`;
|
|
738
798
|
if (params.keep === true) text += " Pane kept.";
|
|
@@ -740,6 +800,8 @@ ${task}` : task,
|
|
|
740
800
|
const c = await mu(["agent", "close", name, "-w", W]);
|
|
741
801
|
text += c.code === 0 ? " Pane closed." : ` Pane kept: close refused: ${(c.stderr || c.stdout).trim()}`;
|
|
742
802
|
}
|
|
803
|
+
if (evidence.length > 0) text += `
|
|
804
|
+
${evidence.join("\n")}`;
|
|
743
805
|
return { content: [{ type: "text", text }], details: { name, workstream: W } };
|
|
744
806
|
}
|
|
745
807
|
});
|
|
@@ -785,6 +847,9 @@ ${task}` : task,
|
|
|
785
847
|
}
|
|
786
848
|
if (inflight.size === 0 && queue.length === 0) return;
|
|
787
849
|
const names = [...inflight.keys()];
|
|
850
|
+
const sessions = [...inflight].flatMap(
|
|
851
|
+
([n, e]) => e.sessionFile ? [`${n}: ${e.sessionFile}`] : []
|
|
852
|
+
);
|
|
788
853
|
const never = queue.splice(0).map((q) => q.handle);
|
|
789
854
|
for (const e of inflight.values()) e.abort.abort();
|
|
790
855
|
inflight.clear();
|
|
@@ -795,6 +860,7 @@ ${task}` : task,
|
|
|
795
860
|
parts.push(
|
|
796
861
|
`${names.length} delegate${names.length === 1 ? "" : "s"} still running: ${names.join(", ")}. Their answers will not come back here; use mu agent wait <name> -w ${W} --json.`
|
|
797
862
|
);
|
|
863
|
+
if (sessions.length > 0) parts.push(`Sessions: ${sessions.join("; ")}.`);
|
|
798
864
|
if (never.length > 0)
|
|
799
865
|
parts.push(`${never.length} queued, never started: ${never.join(", ")}. Re-issue them.`);
|
|
800
866
|
const msg = parts.join(" ");
|
|
@@ -805,7 +871,7 @@ ${task}` : task,
|
|
|
805
871
|
}
|
|
806
872
|
|
|
807
873
|
// extension/nudge.ts
|
|
808
|
-
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
874
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
809
875
|
import { join as join3 } from "path";
|
|
810
876
|
var NUDGE_MESSAGE_TYPE = "mu-keep-driving";
|
|
811
877
|
var NUDGE_LOG_KIND = "nudge";
|
|
@@ -831,7 +897,7 @@ function keepDrivingRule(skillMd) {
|
|
|
831
897
|
function readSkill() {
|
|
832
898
|
for (const up of ["..", "../.."]) {
|
|
833
899
|
const p = join3(import.meta.dirname ?? "", up, "skills", "mu", "SKILL.md");
|
|
834
|
-
if (existsSync2(p)) return
|
|
900
|
+
if (existsSync2(p)) return readFileSync2(p, "utf8");
|
|
835
901
|
}
|
|
836
902
|
return void 0;
|
|
837
903
|
}
|
|
@@ -1231,7 +1297,7 @@ function registerRefuteNudge(pi, run = defaultRunner(), nested = notNested) {
|
|
|
1231
1297
|
}
|
|
1232
1298
|
|
|
1233
1299
|
// extension/mu-pi.ts
|
|
1234
|
-
var EXT_VERSION = true ? "3.
|
|
1300
|
+
var EXT_VERSION = true ? "3.12.0" : void 0;
|
|
1235
1301
|
var FRESH_COMMAND = "mu-fresh";
|
|
1236
1302
|
var FRESH_TIMEOUT_MS = 3e4;
|
|
1237
1303
|
function commandName(name) {
|
|
@@ -1253,7 +1319,7 @@ function detectPiVersion() {
|
|
|
1253
1319
|
for (let i = 0; i < 6; i++) {
|
|
1254
1320
|
const pkgPath = join4(dir, "package.json");
|
|
1255
1321
|
if (existsSync3(pkgPath)) {
|
|
1256
|
-
const pkg = JSON.parse(
|
|
1322
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
|
|
1257
1323
|
if (typeof pkg === "object" && pkg !== null) {
|
|
1258
1324
|
const { name, version } = pkg;
|
|
1259
1325
|
if (typeof name === "string" && /pi/.test(name) && typeof version === "string") {
|
|
@@ -1404,7 +1470,8 @@ function serveCtl(pi) {
|
|
|
1404
1470
|
state: g.state,
|
|
1405
1471
|
since: g.since,
|
|
1406
1472
|
runs: g.runs,
|
|
1407
|
-
pending: g.ctx?.hasPendingMessages() ?? false
|
|
1473
|
+
pending: g.ctx?.hasPendingMessages() ?? false,
|
|
1474
|
+
...sessionFileOf(g.ctx)
|
|
1408
1475
|
});
|
|
1409
1476
|
const settleFresh = (r) => {
|
|
1410
1477
|
const f = g.fresh;
|
|
@@ -1428,6 +1495,14 @@ function serveCtl(pi) {
|
|
|
1428
1495
|
g.endText = lastAssistantText(e);
|
|
1429
1496
|
g.endError = lastAssistantError(e);
|
|
1430
1497
|
});
|
|
1498
|
+
function sessionFileOf(c) {
|
|
1499
|
+
try {
|
|
1500
|
+
const f = c?.sessionManager?.getSessionFile();
|
|
1501
|
+
return f ? { sessionFile: f } : {};
|
|
1502
|
+
} catch {
|
|
1503
|
+
return {};
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1431
1506
|
pi.on("agent_settled", (_e, c) => {
|
|
1432
1507
|
g.ctx = c;
|
|
1433
1508
|
g.state = "idle";
|
|
@@ -1437,11 +1512,7 @@ function serveCtl(pi) {
|
|
|
1437
1512
|
g.endText = void 0;
|
|
1438
1513
|
g.lastError = g.endError;
|
|
1439
1514
|
g.endError = void 0;
|
|
1440
|
-
|
|
1441
|
-
g.sessionFile = c.sessionManager?.getSessionFile();
|
|
1442
|
-
} catch {
|
|
1443
|
-
g.sessionFile = void 0;
|
|
1444
|
-
}
|
|
1515
|
+
g.sessionFile = sessionFileOf(c).sessionFile;
|
|
1445
1516
|
for (const w of [...g.waiters]) w();
|
|
1446
1517
|
});
|
|
1447
1518
|
pi.registerCommand(FRESH_COMMAND, {
|