@femtomc/mu-orchestrator 26.2.19 → 26.2.22
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/dag_runner.d.ts.map +1 -1
- package/dist/dag_runner.js +40 -25
- package/dist/mu_roles.d.ts +2 -1
- package/dist/mu_roles.d.ts.map +1 -1
- package/dist/mu_roles.js +46 -28
- package/dist/pi_backend.d.ts +3 -1
- package/dist/pi_backend.d.ts.map +1 -1
- package/dist/pi_backend.js +19 -4
- package/package.json +4 -4
package/dist/dag_runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dag_runner.d.ts","sourceRoot":"","sources":["../src/dag_runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAEN,KAAK,QAAQ,EAKb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,uBAAuB,CAAC;AAGjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,MAAM,MAAM,SAAS,GAAG;IACvB,MAAM,EAAE,YAAY,GAAG,oBAAoB,GAAG,qBAAqB,GAAG,OAAO,CAAC;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC5B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,yBAAyB,KAAK,IAAI,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC9B,KAAK,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;
|
|
1
|
+
{"version":3,"file":"dag_runner.d.ts","sourceRoot":"","sources":["../src/dag_runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAEN,KAAK,QAAQ,EAKb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,uBAAuB,CAAC;AAGjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,MAAM,MAAM,SAAS,GAAG;IACvB,MAAM,EAAE,YAAY,GAAG,oBAAoB,GAAG,qBAAqB,GAAG,OAAO,CAAC;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC5B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,yBAAyB,KAAK,IAAI,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC9B,KAAK,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAkBF,qBAAa,SAAS;;gBAYpB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;QAAE,OAAO,CAAC,EAAE,aAAa,CAAC;QAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;QAAC,cAAc,CAAC,EAAE,cAAc,CAAA;KAAO;IAkLrF,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,EAAE,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC;CAiNjG"}
|
package/dist/dag_runner.js
CHANGED
|
@@ -2,20 +2,12 @@ import { mkdir } from "node:fs/promises";
|
|
|
2
2
|
import { join, relative } from "node:path";
|
|
3
3
|
import { currentRunId, fsEventLogFromRepoRoot, getStorePaths, newRunId, runContext, } from "@femtomc/mu-core/node";
|
|
4
4
|
import { resolveModelConfig } from "./model_resolution.js";
|
|
5
|
-
import {
|
|
5
|
+
import { roleFromTags, systemPromptForRole } from "./mu_roles.js";
|
|
6
6
|
import { PiSdkBackend } from "./pi_sdk_backend.js";
|
|
7
7
|
function roundTo(n, digits) {
|
|
8
8
|
const f = 10 ** digits;
|
|
9
9
|
return Math.round(n * f) / f;
|
|
10
10
|
}
|
|
11
|
-
function specRoleFromExecutionSpec(execution_spec) {
|
|
12
|
-
const role = execution_spec?.role;
|
|
13
|
-
if (typeof role !== "string") {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
const trimmed = role.trim();
|
|
17
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
18
|
-
}
|
|
19
11
|
function relPath(repoRoot, path) {
|
|
20
12
|
try {
|
|
21
13
|
const rel = relative(repoRoot, path);
|
|
@@ -33,6 +25,7 @@ export class DagRunner {
|
|
|
33
25
|
#backend;
|
|
34
26
|
#modelOverrides;
|
|
35
27
|
#reorchestrateOutcomes = new Set(["failure", "needs_work"]);
|
|
28
|
+
#attempts = new Map();
|
|
36
29
|
constructor(store, forum, repoRoot, opts = {}) {
|
|
37
30
|
this.#store = store;
|
|
38
31
|
this.#forum = forum;
|
|
@@ -41,11 +34,10 @@ export class DagRunner {
|
|
|
41
34
|
this.#backend = opts.backend ?? new PiSdkBackend();
|
|
42
35
|
this.#modelOverrides = opts.modelOverrides ?? {};
|
|
43
36
|
}
|
|
44
|
-
async #resolveConfig(
|
|
45
|
-
void issue;
|
|
37
|
+
async #resolveConfig() {
|
|
46
38
|
return resolveModelConfig(this.#modelOverrides);
|
|
47
39
|
}
|
|
48
|
-
async #renderUserPrompt(issue, rootId, step) {
|
|
40
|
+
async #renderUserPrompt(issue, rootId, step, attempt = 1) {
|
|
49
41
|
let rendered = issue.title ?? "";
|
|
50
42
|
if (issue.body) {
|
|
51
43
|
rendered += `\n\n${issue.body}`;
|
|
@@ -55,17 +47,21 @@ export class DagRunner {
|
|
|
55
47
|
if (runId) {
|
|
56
48
|
rendered += `Run: ${runId}\n`;
|
|
57
49
|
}
|
|
50
|
+
if (attempt > 1) {
|
|
51
|
+
rendered += `\nAttempt: ${attempt} (previous attempt failed — check \`mu forum read issue:${issue.id}\` for context)\n`;
|
|
52
|
+
}
|
|
58
53
|
return rendered;
|
|
59
54
|
}
|
|
60
55
|
async #executeBackend(issue, cfg, rootId, step, opts = {}) {
|
|
61
|
-
const role =
|
|
56
|
+
const role = roleFromTags(issue.tags);
|
|
62
57
|
const logSuffix = opts.logSuffix ?? "";
|
|
63
|
-
const rendered = await this.#renderUserPrompt(issue, rootId, step);
|
|
58
|
+
const rendered = await this.#renderUserPrompt(issue, rootId, step, opts.attempt ?? 1);
|
|
64
59
|
const systemPrompt = systemPromptForRole(role);
|
|
65
60
|
const { logsDir } = getStorePaths(this.#repoRoot);
|
|
66
|
-
|
|
61
|
+
const rootLogsDir = join(logsDir, rootId);
|
|
62
|
+
await mkdir(rootLogsDir, { recursive: true });
|
|
67
63
|
const suffix = logSuffix ? `.${logSuffix}` : "";
|
|
68
|
-
const teePath = join(
|
|
64
|
+
const teePath = join(rootLogsDir, `${issue.id}${suffix}.jsonl`);
|
|
69
65
|
await this.#events.emit("backend.run.start", {
|
|
70
66
|
source: "backend",
|
|
71
67
|
issueId: issue.id,
|
|
@@ -116,7 +112,7 @@ export class DagRunner {
|
|
|
116
112
|
const reopened = await this.#store.update(issueId, {
|
|
117
113
|
status: "open",
|
|
118
114
|
outcome: null,
|
|
119
|
-
|
|
115
|
+
tags: [...before.tags.filter((t) => !t.startsWith("role:")), "role:orchestrator"],
|
|
120
116
|
});
|
|
121
117
|
await this.#events.emit("dag.unstick.reopen", {
|
|
122
118
|
source: "dag_runner",
|
|
@@ -152,6 +148,9 @@ export class DagRunner {
|
|
|
152
148
|
continue;
|
|
153
149
|
if (row.status !== "closed")
|
|
154
150
|
continue;
|
|
151
|
+
// Circuit breaker: skip issues that have exhausted their attempts.
|
|
152
|
+
if ((this.#attempts.get(row.id) ?? 0) >= 3)
|
|
153
|
+
continue;
|
|
155
154
|
const outcome = row.outcome;
|
|
156
155
|
if (outcome && this.#reorchestrateOutcomes.has(outcome)) {
|
|
157
156
|
if (hasOpenChildren(row.id))
|
|
@@ -215,9 +214,8 @@ export class DagRunner {
|
|
|
215
214
|
...rootIssue,
|
|
216
215
|
title: `Repair stuck DAG: ${rootIssue.title}`,
|
|
217
216
|
body: `${(rootIssue.body || "").trim()}\n\n## Runner Diagnostics\n\n${diag}`.trim(),
|
|
218
|
-
execution_spec: null,
|
|
219
217
|
};
|
|
220
|
-
const cfg = await this.#resolveConfig(
|
|
218
|
+
const cfg = await this.#resolveConfig();
|
|
221
219
|
const logSuffix = "unstick";
|
|
222
220
|
const onBackendLine = hooks?.onBackendLine;
|
|
223
221
|
const { exitCode, elapsedS } = await this.#executeBackend(repairIssue, cfg, rootId, step, {
|
|
@@ -243,8 +241,7 @@ export class DagRunner {
|
|
|
243
241
|
}
|
|
244
242
|
const issue = candidates[0];
|
|
245
243
|
const issueId = issue.id;
|
|
246
|
-
|
|
247
|
-
const role = parseMuRole(specRoleFromExecutionSpec(issue.execution_spec));
|
|
244
|
+
const role = roleFromTags(issue.tags);
|
|
248
245
|
await this.#events.emit("dag.step.start", {
|
|
249
246
|
source: "dag_runner",
|
|
250
247
|
issueId,
|
|
@@ -260,12 +257,16 @@ export class DagRunner {
|
|
|
260
257
|
payload: { root_id: rootId, step },
|
|
261
258
|
});
|
|
262
259
|
await this.#store.claim(issueId);
|
|
260
|
+
// Track attempt count for circuit breaker.
|
|
261
|
+
const attempt = (this.#attempts.get(issueId) ?? 0) + 1;
|
|
262
|
+
this.#attempts.set(issueId, attempt);
|
|
263
263
|
// 4. Route + 5. Render + 6. Execute.
|
|
264
|
-
const cfg = await this.#resolveConfig(
|
|
265
|
-
const logSuffix = "";
|
|
264
|
+
const cfg = await this.#resolveConfig();
|
|
265
|
+
const logSuffix = attempt > 1 ? `attempt-${attempt}` : "";
|
|
266
266
|
const onBackendLine = hooks?.onBackendLine;
|
|
267
267
|
const { exitCode, elapsedS } = await this.#executeBackend(issue, cfg, rootId, step, {
|
|
268
268
|
logSuffix,
|
|
269
|
+
attempt,
|
|
269
270
|
onLine: onBackendLine
|
|
270
271
|
? (line) => onBackendLine({ rootId, step, issueId, logSuffix, line })
|
|
271
272
|
: undefined,
|
|
@@ -277,6 +278,11 @@ export class DagRunner {
|
|
|
277
278
|
return final;
|
|
278
279
|
}
|
|
279
280
|
if (updated.status !== "closed") {
|
|
281
|
+
await this.#events.emit("dag.step.force_close", {
|
|
282
|
+
source: "dag_runner",
|
|
283
|
+
issueId,
|
|
284
|
+
payload: { root_id: rootId, step, role, attempt, reason: "agent_did_not_close" },
|
|
285
|
+
});
|
|
280
286
|
updated = await this.#store.close(issueId, "failure");
|
|
281
287
|
}
|
|
282
288
|
// 8. Log to forum.
|
|
@@ -309,9 +315,18 @@ export class DagRunner {
|
|
|
309
315
|
outcome: updated.outcome,
|
|
310
316
|
},
|
|
311
317
|
});
|
|
312
|
-
// 9. Re-orchestrate on failure / needs_work.
|
|
318
|
+
// 9. Re-orchestrate on failure / needs_work (circuit breaker: max 3 attempts).
|
|
313
319
|
if (updated.outcome && this.#reorchestrateOutcomes.has(updated.outcome)) {
|
|
314
|
-
|
|
320
|
+
if (attempt < 3) {
|
|
321
|
+
await this.#reopenForOrchestration(issueId, { reason: `outcome=${updated.outcome}`, step });
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
await this.#events.emit("dag.circuit_breaker", {
|
|
325
|
+
source: "dag_runner",
|
|
326
|
+
issueId,
|
|
327
|
+
payload: { root_id: rootId, step, attempt, outcome: updated.outcome },
|
|
328
|
+
});
|
|
329
|
+
}
|
|
315
330
|
}
|
|
316
331
|
}
|
|
317
332
|
final = { status: "max_steps_exhausted", steps: maxSteps, error: "" };
|
package/dist/mu_roles.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type MuRole = "orchestrator" | "worker";
|
|
2
|
-
|
|
2
|
+
/** Determine role from tags. Defaults to orchestrator if no role tag present. */
|
|
3
|
+
export declare function roleFromTags(tags: readonly string[]): MuRole;
|
|
3
4
|
export declare function systemPromptForRole(role: MuRole): string;
|
|
4
5
|
//# sourceMappingURL=mu_roles.d.ts.map
|
package/dist/mu_roles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mu_roles.d.ts","sourceRoot":"","sources":["../src/mu_roles.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE/C,wBAAgB,
|
|
1
|
+
{"version":3,"file":"mu_roles.d.ts","sourceRoot":"","sources":["../src/mu_roles.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE/C,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAM5D;AAgED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwExD"}
|
package/dist/mu_roles.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/** Determine role from tags. Defaults to orchestrator if no role tag present. */
|
|
2
|
+
export function roleFromTags(tags) {
|
|
3
|
+
for (const tag of tags) {
|
|
4
|
+
if (tag === "role:worker")
|
|
5
|
+
return "worker";
|
|
6
|
+
if (tag === "role:orchestrator")
|
|
7
|
+
return "orchestrator";
|
|
4
8
|
}
|
|
5
|
-
|
|
6
|
-
if (trimmed === "orchestrator" || trimmed === "worker") {
|
|
7
|
-
return trimmed;
|
|
8
|
-
}
|
|
9
|
-
throw new Error(`unsupported execution_spec.role=${JSON.stringify(trimmed)} (only "orchestrator" and "worker" are supported)`);
|
|
9
|
+
return "orchestrator";
|
|
10
10
|
}
|
|
11
11
|
/* ------------------------------------------------------------------ */
|
|
12
12
|
/* mu CLI reference */
|
|
@@ -15,7 +15,12 @@ const MU_CLI_REFERENCE = `
|
|
|
15
15
|
## mu CLI
|
|
16
16
|
|
|
17
17
|
You are running inside **mu**, an issue-driven orchestration system.
|
|
18
|
-
You have four tools: bash, read, write, edit.
|
|
18
|
+
You have four tools: bash, read, write, edit.
|
|
19
|
+
|
|
20
|
+
- Orchestrator: use bash to run \`mu\` commands; do NOT use write/edit (and avoid read).
|
|
21
|
+
- Worker: use tools as needed to implement your assigned issue.
|
|
22
|
+
|
|
23
|
+
Tip: run \`mu <command> --help\` for details.
|
|
19
24
|
|
|
20
25
|
### Issues
|
|
21
26
|
|
|
@@ -67,28 +72,41 @@ export function systemPromptForRole(role) {
|
|
|
67
72
|
return [
|
|
68
73
|
"# Mu Orchestrator",
|
|
69
74
|
"",
|
|
70
|
-
"You are mu's orchestrator
|
|
75
|
+
"You are mu's orchestrator: the hierarchical planner for the issue DAG.",
|
|
76
|
+
"",
|
|
77
|
+
"## Non-Negotiable Constraints",
|
|
71
78
|
"",
|
|
72
|
-
"
|
|
79
|
+
"1. You MUST NOT execute work directly. No code changes, no file edits, no git commits.",
|
|
80
|
+
"2. You MUST decompose the assigned issue into worker child issues, then close the assigned issue with `--outcome expanded`.",
|
|
81
|
+
"3. Decomposition MUST be deterministic and minimal. Use `blocks` edges for sequencing.",
|
|
73
82
|
"",
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
83
|
+
"Even if the task looks atomic: create exactly one worker child issue rather than doing the work yourself.",
|
|
84
|
+
"If you catch yourself about to implement: STOP and create/refine worker issues instead.",
|
|
85
|
+
"",
|
|
86
|
+
"Your only job is to create child issues, add any required `blocks` dependencies, and then close yourself with outcome=expanded.",
|
|
78
87
|
"",
|
|
79
88
|
"## Workflow",
|
|
80
89
|
"",
|
|
81
|
-
"1.
|
|
82
|
-
"2.
|
|
83
|
-
"3.
|
|
84
|
-
"4.
|
|
85
|
-
"
|
|
90
|
+
"1. Investigate: `mu issues get <id>`, `mu forum read issue:<id> --limit 20`, `mu issues children <id>`.",
|
|
91
|
+
"2. Decompose: create child issues with `mu issues create` (always set `--parent` and `--role worker`).",
|
|
92
|
+
"3. Order: add `blocks` edges between children where sequencing matters.",
|
|
93
|
+
"4. Close: `mu issues close <id> --outcome expanded`.",
|
|
94
|
+
"",
|
|
95
|
+
"The ONLY valid outcome for you is `expanded`.",
|
|
96
|
+
"Never close with `success`, `failure`, `needs_work`, or `skipped` — those are for workers.",
|
|
86
97
|
"",
|
|
87
98
|
"## Rules",
|
|
88
99
|
"",
|
|
89
100
|
"- Use only roles: orchestrator, worker.",
|
|
90
|
-
"-
|
|
91
|
-
"-
|
|
101
|
+
"- Every executable leaf MUST be `--role worker`.",
|
|
102
|
+
"- Never create a child without an explicit role.",
|
|
103
|
+
"",
|
|
104
|
+
"## Strategies For Good Plans",
|
|
105
|
+
"",
|
|
106
|
+
"- Include feedback loops in worker issues: tests, typecheck, build, lint, repro steps.",
|
|
107
|
+
"- Prefer small issues with crisp acceptance criteria over large ambiguous ones.",
|
|
108
|
+
"- If the work needs verification, add a worker review issue blocked by implementation.",
|
|
109
|
+
" If review fails, that worker should close with outcome=needs_work and describe what failed.",
|
|
92
110
|
"",
|
|
93
111
|
MU_CLI_REFERENCE,
|
|
94
112
|
].join("\n");
|
|
@@ -102,21 +120,21 @@ export function systemPromptForRole(role) {
|
|
|
102
120
|
"",
|
|
103
121
|
"- Implement the work described in your assigned issue.",
|
|
104
122
|
"- Keep scope tight to the issue specification.",
|
|
105
|
-
"- Verify results (tests, typecheck, build, etc.) and report what changed.",
|
|
123
|
+
"- Verify results (tests, typecheck, build, lint, etc.) and report what changed.",
|
|
106
124
|
"- Close your issue with a terminal outcome when done.",
|
|
107
125
|
"",
|
|
108
126
|
"## Workflow",
|
|
109
127
|
"",
|
|
110
|
-
"1.
|
|
111
|
-
"2. Implement
|
|
112
|
-
"3. Verify: run tests
|
|
128
|
+
"1. Inspect: `mu issues get <id>` and `mu forum read issue:<id> --limit 20`.",
|
|
129
|
+
"2. Implement: edit files, run commands, and keep changes scoped to the issue.",
|
|
130
|
+
"3. Verify: run tests/build/typecheck/lint as appropriate. Prefer hard feedback loops.",
|
|
113
131
|
"4. Close: `mu issues close <id> --outcome success` (or `failure`/`skipped`).",
|
|
114
|
-
"5.
|
|
132
|
+
"5. Log key notes: `mu forum post issue:<id> -m '...' --author worker`.",
|
|
115
133
|
"",
|
|
116
134
|
"## Rules",
|
|
117
135
|
"",
|
|
118
136
|
"- Do NOT create child issues — that is the orchestrator's job.",
|
|
119
|
-
"- If the issue is too large
|
|
137
|
+
"- If the issue is too large/unclear, close with `--outcome needs_work` and explain what is missing.",
|
|
120
138
|
"",
|
|
121
139
|
MU_CLI_REFERENCE,
|
|
122
140
|
].join("\n");
|
package/dist/pi_backend.d.ts
CHANGED
|
@@ -16,9 +16,11 @@ export type BackendRunOpts = {
|
|
|
16
16
|
export interface BackendRunner {
|
|
17
17
|
run(opts: BackendRunOpts): Promise<number>;
|
|
18
18
|
}
|
|
19
|
+
export type PiCliArgvOpts = Pick<BackendRunOpts, "prompt" | "systemPrompt" | "provider" | "model" | "thinking">;
|
|
20
|
+
/** Build argv for the `pi` CLI. Exported for regression testing. */
|
|
21
|
+
export declare function buildPiCliArgv(opts: PiCliArgvOpts): string[];
|
|
19
22
|
export declare function piStreamHasError(line: string): boolean;
|
|
20
23
|
export declare class PiCliBackend implements BackendRunner {
|
|
21
|
-
#private;
|
|
22
24
|
run(opts: BackendRunOpts): Promise<number>;
|
|
23
25
|
}
|
|
24
26
|
//# sourceMappingURL=pi_backend.d.ts.map
|
package/dist/pi_backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi_backend.d.ts","sourceRoot":"","sources":["../src/pi_backend.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC7B,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3C;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA4BtD;AAED,qBAAa,YAAa,YAAW,aAAa
|
|
1
|
+
{"version":3,"file":"pi_backend.d.ts","sourceRoot":"","sources":["../src/pi_backend.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,WAAW,aAAa;IAC7B,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3C;AAED,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC,CAAC;AAEhH,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,EAAE,CAgB5D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA4BtD;AAED,qBAAa,YAAa,YAAW,aAAa;IACpC,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;CAuEvD"}
|
package/dist/pi_backend.js
CHANGED
|
@@ -3,6 +3,24 @@ import { mkdir, open } from "node:fs/promises";
|
|
|
3
3
|
import { dirname } from "node:path";
|
|
4
4
|
import { createInterface } from "node:readline";
|
|
5
5
|
import { PassThrough } from "node:stream";
|
|
6
|
+
/** Build argv for the `pi` CLI. Exported for regression testing. */
|
|
7
|
+
export function buildPiCliArgv(opts) {
|
|
8
|
+
return [
|
|
9
|
+
"pi",
|
|
10
|
+
"--mode",
|
|
11
|
+
"json",
|
|
12
|
+
"--no-session",
|
|
13
|
+
"--provider",
|
|
14
|
+
opts.provider,
|
|
15
|
+
"--model",
|
|
16
|
+
opts.model,
|
|
17
|
+
"--thinking",
|
|
18
|
+
opts.thinking,
|
|
19
|
+
"--system-prompt",
|
|
20
|
+
opts.systemPrompt,
|
|
21
|
+
opts.prompt,
|
|
22
|
+
];
|
|
23
|
+
}
|
|
6
24
|
export function piStreamHasError(line) {
|
|
7
25
|
let event;
|
|
8
26
|
try {
|
|
@@ -31,14 +49,11 @@ export function piStreamHasError(line) {
|
|
|
31
49
|
return false;
|
|
32
50
|
}
|
|
33
51
|
export class PiCliBackend {
|
|
34
|
-
#buildArgv(prompt, model, thinking) {
|
|
35
|
-
return ["pi", "--mode", "json", "--no-session", "--model", model, "--thinking", thinking, prompt];
|
|
36
|
-
}
|
|
37
52
|
async run(opts) {
|
|
38
53
|
if (opts.cli !== "pi") {
|
|
39
54
|
throw new Error(`unsupported backend cli=${JSON.stringify(opts.cli)} (only "pi" is supported)`);
|
|
40
55
|
}
|
|
41
|
-
const argv =
|
|
56
|
+
const argv = buildPiCliArgv(opts);
|
|
42
57
|
let teeFh = null;
|
|
43
58
|
try {
|
|
44
59
|
if (opts.teePath) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@femtomc/mu-orchestrator",
|
|
3
|
-
"version": "26.2.
|
|
3
|
+
"version": "26.2.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"dist/**"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@femtomc/mu-core": "26.2.
|
|
18
|
-
"@femtomc/mu-forum": "26.2.
|
|
19
|
-
"@femtomc/mu-issue": "26.2.
|
|
17
|
+
"@femtomc/mu-core": "26.2.21",
|
|
18
|
+
"@femtomc/mu-forum": "26.2.21",
|
|
19
|
+
"@femtomc/mu-issue": "26.2.21",
|
|
20
20
|
"@mariozechner/pi-agent-core": "^0.52.12",
|
|
21
21
|
"@mariozechner/pi-coding-agent": "^0.52.12",
|
|
22
22
|
"@mariozechner/pi-ai": "^0.52.12"
|