@mu-crew/mu 3.2.0 → 3.2.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/AGENTS.md +203 -599
- package/README.md +76 -327
- package/dist/cli.js.map +1 -1
- package/dist/extension/mu-pi.js +178 -45
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/docs/ARCHITECTURE.md +175 -1072
- package/docs/ROADMAP.md +88 -169
- package/docs/VISION.md +205 -415
- package/docs/VOCABULARY.md +202 -466
- package/docs/architecture/control-socket.md +119 -0
- package/docs/architecture/dag.md +113 -0
- package/docs/architecture/mux.md +163 -0
- package/docs/architecture/ops-log.md +140 -0
- package/docs/architecture/sdk.md +185 -0
- package/docs/architecture/sync.md +129 -0
- package/docs/architecture/tui.md +146 -0
- package/docs/guide/README.md +25 -0
- package/docs/guide/backends.md +61 -0
- package/docs/guide/cleanup.md +74 -0
- package/docs/guide/delegate.md +87 -0
- package/docs/guide/dispatch.md +137 -0
- package/docs/guide/getting-started.md +177 -0
- package/docs/guide/recovery.md +133 -0
- package/docs/guide/remote.md +74 -0
- package/docs/guide/sql.md +76 -0
- package/docs/guide/stop-a-worker.md +64 -0
- package/docs/guide/sync.md +78 -0
- package/docs/guide/tui.md +98 -0
- package/docs/guide/upgrade.md +76 -0
- package/docs/history/CHANGELOG-pre-3.md +4866 -0
- package/docs/reference/env.md +87 -0
- package/docs/reference/naming.md +82 -0
- package/docs/specs/2026-09-28-agent-state-from-murmur.md +1 -1
- package/docs/specs/2026-09-29-task-substates.md +1 -1
- package/package.json +1 -1
- package/skills/mu/REMOTE_WORKERS.md +179 -504
- package/skills/mu/SKILL.md +116 -185
- package/docs/HANDOVER.md +0 -486
- package/docs/USAGE_GUIDE.md +0 -2738
package/dist/extension/mu-pi.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
readFileSync,
|
|
8
8
|
realpathSync,
|
|
9
9
|
rmSync,
|
|
10
|
-
statSync
|
|
10
|
+
statSync as statSync2
|
|
11
11
|
} from "fs";
|
|
12
12
|
import { connect, createServer } from "net";
|
|
13
13
|
import { dirname, join as join2 } from "path";
|
|
@@ -39,13 +39,17 @@ var LineDecoder = class {
|
|
|
39
39
|
|
|
40
40
|
// extension/delegate.ts
|
|
41
41
|
import { execFile } from "child_process";
|
|
42
|
-
import { existsSync } from "fs";
|
|
42
|
+
import { existsSync, statSync } from "fs";
|
|
43
43
|
import { delimiter, join } from "path";
|
|
44
44
|
import { fileURLToPath } from "url";
|
|
45
45
|
var DELEGATE_TOOL = "mu_delegate";
|
|
46
46
|
var DELEGATE_CANCEL_TOOL = "mu_delegate_cancel";
|
|
47
47
|
var DELEGATE_MESSAGE_TYPE = "mu-delegate";
|
|
48
48
|
var DELEGATE_WORKSTREAM = "scratch";
|
|
49
|
+
var DELEGATE_STATUS_KEY = "mu-delegate";
|
|
50
|
+
function delegateStatus(n) {
|
|
51
|
+
return n > 0 ? `${n} delegate${n === 1 ? "" : "s"} running` : void 0;
|
|
52
|
+
}
|
|
49
53
|
var DELEGATE_TIMEOUT_S = 3600;
|
|
50
54
|
var W = DELEGATE_WORKSTREAM;
|
|
51
55
|
function delegateEnabled(env = process.env) {
|
|
@@ -54,6 +58,13 @@ function delegateEnabled(env = process.env) {
|
|
|
54
58
|
if (env.MU_MUX || env.HERDR_ENV === "1" || env.TMUX || env.TMUX_PANE) return true;
|
|
55
59
|
return onPath("tmux", env) || onPath("herdr", env);
|
|
56
60
|
}
|
|
61
|
+
function isDir(p) {
|
|
62
|
+
try {
|
|
63
|
+
return statSync(p).isDirectory();
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
57
68
|
function onPath(bin, env) {
|
|
58
69
|
return (env.PATH ?? "").split(delimiter).some((d) => d !== "" && existsSync(join(d, bin)));
|
|
59
70
|
}
|
|
@@ -77,41 +88,71 @@ function defaultRunner() {
|
|
|
77
88
|
);
|
|
78
89
|
});
|
|
79
90
|
}
|
|
80
|
-
function
|
|
91
|
+
function formatElapsed(ms) {
|
|
92
|
+
const t = Math.max(0, Math.round(ms / 1e3));
|
|
93
|
+
if (t < 60) return `${t}s`;
|
|
94
|
+
const m = Math.floor(t / 60);
|
|
95
|
+
if (m < 60) return `${m}m ${String(t % 60).padStart(2, "0")}s`;
|
|
96
|
+
return `${Math.floor(m / 60)}h ${String(m % 60).padStart(2, "0")}m`;
|
|
97
|
+
}
|
|
98
|
+
function delegateMessage(name, agent, pane, x = {}) {
|
|
99
|
+
const timeoutS = x.timeoutS ?? DELEGATE_TIMEOUT_S;
|
|
81
100
|
const who = `Delegate ${W}/${name}`;
|
|
101
|
+
const took = x.elapsedMs !== void 0 ? ` after ${formatElapsed(x.elapsedMs)}` : "";
|
|
82
102
|
const fate = pane.closed ? "Pane closed." : `Pane kept (${pane.why}).`;
|
|
83
103
|
const look = [
|
|
84
|
-
attach ? `Attach: ${attach}` : void 0,
|
|
104
|
+
x.attach ? `Attach: ${x.attach}` : void 0,
|
|
85
105
|
`Read: mu agent read ${name} -n 50 -w ${W}`
|
|
86
|
-
].filter((
|
|
87
|
-
const tailBlock = tail?.trim() ? `
|
|
106
|
+
].filter((v) => v !== void 0);
|
|
107
|
+
const tailBlock = x.tail?.trim() ? `
|
|
88
108
|
|
|
89
109
|
Pane tail:
|
|
90
|
-
${tail.trimEnd()}` : "";
|
|
110
|
+
${x.tail.trimEnd()}` : "";
|
|
111
|
+
const ws = x.workspace ? ` Workspace: ${x.workspace}` : "";
|
|
91
112
|
switch (agent?.outcome) {
|
|
92
113
|
case "done":
|
|
93
|
-
return `${who} finished. ${fate}
|
|
114
|
+
return `${who} finished${took}. ${fate}${ws}
|
|
94
115
|
|
|
95
116
|
${agent.lastText ?? ""}`;
|
|
96
117
|
case "empty":
|
|
97
|
-
return `${who} finished without a text answer. ${fate}${tailBlock}`;
|
|
118
|
+
return `${who} finished${took} without a text answer. ${fate}${ws}${tailBlock}`;
|
|
98
119
|
case "died":
|
|
99
|
-
return `${who} died before answering. ${fate}${tailBlock}`;
|
|
120
|
+
return `${who} died${took} before answering. ${fate}${ws}${tailBlock}`;
|
|
100
121
|
case "timeout":
|
|
101
122
|
case "pending":
|
|
102
123
|
return [
|
|
103
|
-
`${who} is still running after ${
|
|
124
|
+
`${who} is still running after ${timeoutS}s; stopped waiting, so its answer will not arrive here. ${fate}${ws}`,
|
|
104
125
|
...look,
|
|
105
126
|
`Wait again: mu agent wait ${name} -w ${W} --json`
|
|
106
127
|
].join("\n");
|
|
107
128
|
default:
|
|
108
|
-
return `${who}: mu agent wait gave no result. ${fate}${tailBlock}`;
|
|
129
|
+
return `${who}: mu agent wait gave no result. ${fate}${ws}${tailBlock}`;
|
|
109
130
|
}
|
|
110
131
|
}
|
|
132
|
+
function labelStem(label) {
|
|
133
|
+
if (typeof label !== "string") return void 0;
|
|
134
|
+
const stem = label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 20).replace(/-+$/, "");
|
|
135
|
+
return stem || void 0;
|
|
136
|
+
}
|
|
111
137
|
function registerDelegate(pi, run = defaultRunner()) {
|
|
112
138
|
if (!delegateEnabled()) return;
|
|
113
139
|
const inflight = /* @__PURE__ */ new Map();
|
|
114
140
|
const reserved = /* @__PURE__ */ new Set();
|
|
141
|
+
let ui;
|
|
142
|
+
const showStatus = () => {
|
|
143
|
+
try {
|
|
144
|
+
ui?.setStatus?.(DELEGATE_STATUS_KEY, delegateStatus(inflight.size));
|
|
145
|
+
} catch {
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const track = (ctx) => {
|
|
149
|
+
if (ctx?.hasUI !== false && ctx?.ui) ui = ctx.ui;
|
|
150
|
+
};
|
|
151
|
+
const forget = (name) => {
|
|
152
|
+
inflight.delete(name);
|
|
153
|
+
reserved.delete(name);
|
|
154
|
+
showStatus();
|
|
155
|
+
};
|
|
115
156
|
const mu = run;
|
|
116
157
|
const json = (r) => {
|
|
117
158
|
try {
|
|
@@ -122,28 +163,39 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
122
163
|
}
|
|
123
164
|
};
|
|
124
165
|
const failure = (what, r) => new Error(`${what} failed (exit ${r.code}): ${(r.stderr || r.stdout).trim()}`);
|
|
125
|
-
async function pickName() {
|
|
166
|
+
async function pickName(stem) {
|
|
126
167
|
const r = await mu(["agent", "list", "-w", W, "--json"]);
|
|
127
168
|
const agents = json(r)?.agents;
|
|
128
169
|
const taken = new Set(
|
|
129
170
|
Array.isArray(agents) ? agents.map((a) => a.name).filter((n) => n) : []
|
|
130
171
|
);
|
|
131
172
|
for (let n = 1; ; n++) {
|
|
132
|
-
const name = `delegate-${n}`;
|
|
173
|
+
const name = stem ? n === 1 ? `delegate-${stem}` : `delegate-${stem}-${n}` : `delegate-${n}`;
|
|
133
174
|
if (!taken.has(name) && !reserved.has(name)) {
|
|
134
175
|
reserved.add(name);
|
|
135
176
|
return name;
|
|
136
177
|
}
|
|
137
178
|
}
|
|
138
179
|
}
|
|
139
|
-
async function spawn(params) {
|
|
180
|
+
async function spawn(params, cwd, signal) {
|
|
181
|
+
const stem = labelStem(params.label);
|
|
140
182
|
for (let attempt = 0; ; attempt++) {
|
|
141
|
-
|
|
183
|
+
signal?.throwIfAborted();
|
|
184
|
+
const name = await pickName(stem);
|
|
142
185
|
const args = ["agent", "spawn", name, "-w", W, "--json"];
|
|
143
186
|
if (params.workspace === true) args.push("--workspace");
|
|
187
|
+
else if (cwd) args.push("--cwd", cwd);
|
|
144
188
|
if (typeof params.cli === "string" && params.cli) args.push("--cli", params.cli);
|
|
145
189
|
const r = await mu(args);
|
|
146
|
-
if (
|
|
190
|
+
if (signal?.aborted && r.code === 0) {
|
|
191
|
+
reserved.delete(name);
|
|
192
|
+
await mu(["agent", "close", name, "-w", W]);
|
|
193
|
+
signal.throwIfAborted();
|
|
194
|
+
}
|
|
195
|
+
if (r.code !== 0 && /already exists/.test(r.stderr) && attempt < 3) {
|
|
196
|
+
reserved.delete(name);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
147
199
|
if (r.code !== 0) {
|
|
148
200
|
reserved.delete(name);
|
|
149
201
|
throw failure("mu agent spawn", r);
|
|
@@ -157,10 +209,15 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
157
209
|
}
|
|
158
210
|
const steps = Array.isArray(out.nextSteps) ? out.nextSteps : [];
|
|
159
211
|
const attach = steps.map((s) => s).find((s) => s.intent === "Attach the pane")?.command;
|
|
160
|
-
|
|
212
|
+
const wsPath = out.workspace?.path;
|
|
213
|
+
return {
|
|
214
|
+
name,
|
|
215
|
+
...typeof attach === "string" ? { attach } : {},
|
|
216
|
+
...typeof wsPath === "string" ? { workspace: wsPath } : {}
|
|
217
|
+
};
|
|
161
218
|
}
|
|
162
219
|
}
|
|
163
|
-
async function deliver(name, wait, keep,
|
|
220
|
+
async function deliver(name, wait, keep, extras) {
|
|
164
221
|
const agent = json(wait)?.agents?.[0];
|
|
165
222
|
const outcome = agent?.outcome;
|
|
166
223
|
const tail = outcome === "done" || outcome === "timeout" || outcome === "pending" ? void 0 : (await mu(["agent", "read", name, "-n", "50", "-w", W])).stdout;
|
|
@@ -174,9 +231,17 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
174
231
|
await pi.sendMessage(
|
|
175
232
|
{
|
|
176
233
|
customType: DELEGATE_MESSAGE_TYPE,
|
|
177
|
-
content: delegateMessage(name, agent, pane,
|
|
234
|
+
content: delegateMessage(name, agent, pane, { ...extras, ...tail ? { tail } : {} }),
|
|
178
235
|
display: true,
|
|
179
|
-
details: {
|
|
236
|
+
details: {
|
|
237
|
+
name,
|
|
238
|
+
workstream: W,
|
|
239
|
+
outcome: outcome ?? null,
|
|
240
|
+
closed: pane.closed,
|
|
241
|
+
answer: outcome === "done" ? agent?.lastText ?? null : null,
|
|
242
|
+
elapsedMs: extras.elapsedMs ?? null,
|
|
243
|
+
workspace: extras.workspace ?? null
|
|
244
|
+
}
|
|
180
245
|
},
|
|
181
246
|
{ deliverAs: "followUp", triggerTurn: true }
|
|
182
247
|
);
|
|
@@ -184,23 +249,36 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
184
249
|
pi.registerTool({
|
|
185
250
|
name: DELEGATE_TOOL,
|
|
186
251
|
label: "mu delegate",
|
|
187
|
-
description: `
|
|
188
|
-
promptSnippet: "
|
|
252
|
+
description: `Subagent: run one self-contained task in a fresh pi agent (its own mux pane in mu's ${W} workstream) while you keep working. Use it whenever you would reach for a subagent: research, a review, a draft, an investigation; call it several times to fan out in parallel. The subagent starts with no context, in your working directory: put everything it needs in task. The call returns at once and the answer arrives later as a follow-up message: carry on with other work, or end your turn if your next step needs the answer (the follow-up resumes you). The pane closes after a clean finish; keep: true leaves it open.`,
|
|
253
|
+
promptSnippet: "Subagent: delegate a self-contained task to a background pi agent; its answer arrives later as a follow-up",
|
|
189
254
|
parameters: {
|
|
190
255
|
type: "object",
|
|
191
256
|
properties: {
|
|
192
257
|
task: { type: "string", description: "The complete task, with all context it needs" },
|
|
258
|
+
label: {
|
|
259
|
+
type: "string",
|
|
260
|
+
description: "Short label naming the delegate, e.g. 'review' \u2192 delegate-review. Use one per subtask when fanning out."
|
|
261
|
+
},
|
|
193
262
|
brief: {
|
|
194
263
|
type: "string",
|
|
195
|
-
description: "Optional
|
|
264
|
+
description: "Optional standing role or rules, sent before the task, e.g. 'You are a reviewer; read only.' The rules are instructions, not enforced. The job itself goes in task."
|
|
265
|
+
},
|
|
266
|
+
cwd: {
|
|
267
|
+
type: "string",
|
|
268
|
+
description: "Working directory for the delegate (default: yours; ignored with workspace)"
|
|
269
|
+
},
|
|
270
|
+
timeout: {
|
|
271
|
+
type: "number",
|
|
272
|
+
exclusiveMinimum: 0,
|
|
273
|
+
description: `Seconds to wait for the answer (default ${DELEGATE_TIMEOUT_S}). On timeout you get a "still running" follow-up instead of the answer, and the answer will not arrive later; the subagent keeps running in its pane.`
|
|
196
274
|
},
|
|
197
275
|
workspace: {
|
|
198
276
|
type: "boolean",
|
|
199
|
-
description: "
|
|
277
|
+
description: "For tasks that edit files: its own VCS checkout (jj workspace / git worktree / sl share) branched from the current commit. The result and follow-up name the path; changes stay there until you merge them. This isolates repository edits only: the subagent runs as you, with your files, environment and network."
|
|
200
278
|
},
|
|
201
279
|
cli: {
|
|
202
280
|
type: "string",
|
|
203
|
-
description: "Agent CLI key
|
|
281
|
+
description: "Agent CLI key (default pi). Name a configured key such as 'pi_fast' to run a cheaper model."
|
|
204
282
|
},
|
|
205
283
|
keep: {
|
|
206
284
|
type: "boolean",
|
|
@@ -210,16 +288,30 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
210
288
|
required: ["task"],
|
|
211
289
|
additionalProperties: false
|
|
212
290
|
},
|
|
213
|
-
async execute(_id, params) {
|
|
291
|
+
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
292
|
+
track(ctx);
|
|
214
293
|
const task = typeof params.task === "string" ? params.task.trim() : "";
|
|
215
294
|
if (!task) throw new Error("mu_delegate needs a non-empty task");
|
|
216
295
|
const brief = typeof params.brief === "string" ? params.brief.trim() : "";
|
|
217
296
|
const keep = params.keep === true;
|
|
218
|
-
const
|
|
219
|
-
|
|
297
|
+
const t = params.timeout;
|
|
298
|
+
if (t !== void 0 && !(typeof t === "number" && Number.isFinite(t) && t > 0))
|
|
299
|
+
throw new Error(
|
|
300
|
+
`mu_delegate: timeout must be a positive number of seconds (got ${JSON.stringify(t)})`
|
|
301
|
+
);
|
|
302
|
+
const timeoutS = typeof t === "number" ? Math.ceil(t) : DELEGATE_TIMEOUT_S;
|
|
303
|
+
let cwd;
|
|
304
|
+
if (params.workspace !== true) {
|
|
305
|
+
cwd = typeof params.cwd === "string" && params.cwd ? params.cwd : ctx?.cwd ?? process.cwd();
|
|
306
|
+
if (!isDir(cwd)) throw new Error(`mu_delegate: cwd ${cwd} is not a directory`);
|
|
307
|
+
}
|
|
308
|
+
const { name, attach, workspace } = await spawn(params, cwd, signal);
|
|
309
|
+
const entry = { abort: new AbortController(), cancelling: false };
|
|
220
310
|
inflight.set(name, entry);
|
|
311
|
+
showStatus();
|
|
312
|
+
const started = Date.now();
|
|
221
313
|
const waiting = mu(
|
|
222
|
-
["agent", "wait", name, "-w", W, "--json", "--timeout", String(
|
|
314
|
+
["agent", "wait", name, "-w", W, "--json", "--timeout", String(timeoutS)],
|
|
223
315
|
entry.abort.signal
|
|
224
316
|
);
|
|
225
317
|
const sent = await mu(["agent", "send", name, brief ? `${brief}
|
|
@@ -227,23 +319,55 @@ function registerDelegate(pi, run = defaultRunner()) {
|
|
|
227
319
|
${task}` : task, "-w", W]);
|
|
228
320
|
if (sent.code !== 0) {
|
|
229
321
|
entry.abort.abort();
|
|
230
|
-
|
|
231
|
-
|
|
322
|
+
forget(name);
|
|
323
|
+
const c = await mu(["agent", "close", name, "-w", W]);
|
|
324
|
+
const pane = c.code === 0 ? "Pane closed." : `Pane kept; close it with: mu agent close ${name} -w ${W}`;
|
|
325
|
+
throw new Error(`${failure(`mu agent send to ${W}/${name}`, sent).message}. ${pane}`);
|
|
232
326
|
}
|
|
327
|
+
const settle = async (r) => {
|
|
328
|
+
forget(name);
|
|
329
|
+
try {
|
|
330
|
+
await deliver(name, r, keep, {
|
|
331
|
+
timeoutS,
|
|
332
|
+
elapsedMs: Date.now() - started,
|
|
333
|
+
...attach ? { attach } : {},
|
|
334
|
+
...workspace ? { workspace } : {}
|
|
335
|
+
});
|
|
336
|
+
} catch (e) {
|
|
337
|
+
await Promise.resolve(
|
|
338
|
+
pi.sendMessage(
|
|
339
|
+
{
|
|
340
|
+
customType: DELEGATE_MESSAGE_TYPE,
|
|
341
|
+
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}`,
|
|
342
|
+
display: true,
|
|
343
|
+
details: { name, workstream: W, outcome: null, closed: false }
|
|
344
|
+
},
|
|
345
|
+
{ deliverAs: "followUp", triggerTurn: true }
|
|
346
|
+
)
|
|
347
|
+
).catch(() => {
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
};
|
|
233
351
|
void waiting.then(async (r) => {
|
|
234
|
-
if (inflight.get(name) !== entry
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
await deliver(name, r, keep, attach);
|
|
352
|
+
if (inflight.get(name) !== entry) return;
|
|
353
|
+
if (entry.cancelling) entry.parked = () => settle(r);
|
|
354
|
+
else await settle(r);
|
|
238
355
|
});
|
|
239
356
|
const lines = [
|
|
240
357
|
`Delegated to ${W}/${name}. Its answer arrives as a follow-up message when it finishes; do not wait or poll.`,
|
|
358
|
+
workspace ? `Workspace: ${workspace}` : void 0,
|
|
241
359
|
attach ? `Attach: ${attach}` : void 0,
|
|
242
360
|
`Cancel: ${DELEGATE_CANCEL_TOOL} { name: "${name}" }`
|
|
243
361
|
].filter((x) => x !== void 0);
|
|
244
362
|
return {
|
|
245
363
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
246
|
-
details: {
|
|
364
|
+
details: {
|
|
365
|
+
name,
|
|
366
|
+
workstream: W,
|
|
367
|
+
attach: attach ?? null,
|
|
368
|
+
workspace: workspace ?? null,
|
|
369
|
+
keep
|
|
370
|
+
}
|
|
247
371
|
};
|
|
248
372
|
}
|
|
249
373
|
});
|
|
@@ -260,19 +384,26 @@ ${task}` : task, "-w", W]);
|
|
|
260
384
|
required: ["name"],
|
|
261
385
|
additionalProperties: false
|
|
262
386
|
},
|
|
263
|
-
async execute(_id, params) {
|
|
387
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
388
|
+
track(ctx);
|
|
264
389
|
const name = typeof params.name === "string" ? params.name : "";
|
|
265
390
|
if (!name) throw new Error("mu_delegate_cancel needs a name");
|
|
266
391
|
const entry = inflight.get(name);
|
|
267
|
-
if (entry) entry.
|
|
392
|
+
if (entry) entry.cancelling = true;
|
|
268
393
|
const ab = await mu(["agent", "abort", name, "-w", W]);
|
|
269
394
|
if (ab.code !== 0) {
|
|
270
|
-
if (entry)
|
|
395
|
+
if (entry) {
|
|
396
|
+
entry.cancelling = false;
|
|
397
|
+
const parked = entry.parked;
|
|
398
|
+
entry.parked = void 0;
|
|
399
|
+
if (parked) void parked();
|
|
400
|
+
}
|
|
271
401
|
throw failure(`mu agent abort ${W}/${name}`, ab);
|
|
272
402
|
}
|
|
273
|
-
entry
|
|
274
|
-
|
|
275
|
-
|
|
403
|
+
if (entry) {
|
|
404
|
+
entry.abort.abort();
|
|
405
|
+
forget(name);
|
|
406
|
+
}
|
|
276
407
|
let text = `Aborted ${W}/${name}.`;
|
|
277
408
|
if (params.keep === true) text += " Pane kept.";
|
|
278
409
|
else {
|
|
@@ -287,6 +418,8 @@ ${task}` : task, "-w", W]);
|
|
|
287
418
|
const names = [...inflight.keys()];
|
|
288
419
|
for (const e of inflight.values()) e.abort.abort();
|
|
289
420
|
inflight.clear();
|
|
421
|
+
showStatus();
|
|
422
|
+
ui = void 0;
|
|
290
423
|
const msg = `${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.`;
|
|
291
424
|
if (ctx?.hasUI && ctx.ui) ctx.ui.notify(msg, "warning");
|
|
292
425
|
else process.stderr.write(`mu: ${msg}
|
|
@@ -295,7 +428,7 @@ ${task}` : task, "-w", W]);
|
|
|
295
428
|
}
|
|
296
429
|
|
|
297
430
|
// extension/mu-pi.ts
|
|
298
|
-
var EXT_VERSION = true ? "3.2.
|
|
431
|
+
var EXT_VERSION = true ? "3.2.1" : void 0;
|
|
299
432
|
var FRESH_COMMAND = "mu-fresh";
|
|
300
433
|
var FRESH_TIMEOUT_MS = 3e4;
|
|
301
434
|
var LAST_TEXT_MAX_BYTES = 64 * 1024;
|
|
@@ -370,7 +503,7 @@ ${LAST_TEXT_TRUNCATED}`;
|
|
|
370
503
|
}
|
|
371
504
|
function inodeOf(path) {
|
|
372
505
|
try {
|
|
373
|
-
return
|
|
506
|
+
return statSync2(path).ino;
|
|
374
507
|
} catch {
|
|
375
508
|
return void 0;
|
|
376
509
|
}
|