@femtomc/mu-agent 26.2.42 → 26.2.44
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/README.md +11 -0
- package/dist/default_prompts.d.ts +13 -0
- package/dist/default_prompts.d.ts.map +1 -0
- package/dist/default_prompts.js +39 -0
- package/dist/extensions/index.d.ts +10 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +17 -1
- package/dist/extensions/orchestration-runs-readonly.d.ts +4 -0
- package/dist/extensions/orchestration-runs-readonly.d.ts.map +1 -0
- package/dist/extensions/orchestration-runs-readonly.js +56 -0
- package/dist/extensions/server-tools-readonly.d.ts +4 -0
- package/dist/extensions/server-tools-readonly.d.ts.map +1 -0
- package/dist/extensions/server-tools-readonly.js +5 -0
- package/dist/extensions/server-tools.d.ts +7 -1
- package/dist/extensions/server-tools.d.ts.map +1 -1
- package/dist/extensions/server-tools.js +23 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/mu_roles.d.ts +5 -7
- package/dist/mu_roles.d.ts.map +1 -1
- package/dist/mu_roles.js +5 -148
- package/dist/operator.d.ts +3 -2
- package/dist/operator.d.ts.map +1 -1
- package/dist/operator.js +184 -46
- package/package.json +4 -3
- package/prompts/operator.md +49 -0
- package/prompts/orchestrator.md +34 -0
- package/prompts/soul.md +10 -0
- package/prompts/worker.md +34 -0
package/README.md
CHANGED
|
@@ -10,6 +10,17 @@ This package provides reusable runtime pieces for chat, orchestration, and serve
|
|
|
10
10
|
- pi CLI/SDK orchestration backends and resource loader helpers
|
|
11
11
|
- Prompt/template helpers used by orchestration roles
|
|
12
12
|
|
|
13
|
+
## Bundled default prompts
|
|
14
|
+
|
|
15
|
+
Bundled defaults now live as markdown files under `packages/agent/prompts/`:
|
|
16
|
+
|
|
17
|
+
- `operator.md`
|
|
18
|
+
- `orchestrator.md`
|
|
19
|
+
- `worker.md`
|
|
20
|
+
- `soul.md` (shared tail appended to all role prompts)
|
|
21
|
+
|
|
22
|
+
These are loaded by runtime code and are the single source of truth for default system prompts.
|
|
23
|
+
|
|
13
24
|
## Install
|
|
14
25
|
|
|
15
26
|
```bash
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load a bundled markdown prompt from packages/agent/prompts.
|
|
3
|
+
*
|
|
4
|
+
* This is intentionally strict: bundled prompt markdown is the single source
|
|
5
|
+
* of truth for default system prompts.
|
|
6
|
+
*/
|
|
7
|
+
export declare function loadBundledPrompt(name: string): string;
|
|
8
|
+
export declare function appendSharedSoul(basePrompt: string, soulPrompt: string): string;
|
|
9
|
+
export declare const DEFAULT_SOUL_PROMPT: string;
|
|
10
|
+
export declare const DEFAULT_ORCHESTRATOR_PROMPT: string;
|
|
11
|
+
export declare const DEFAULT_WORKER_PROMPT: string;
|
|
12
|
+
export declare const DEFAULT_OPERATOR_SYSTEM_PROMPT: string;
|
|
13
|
+
//# sourceMappingURL=default_prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default_prompts.d.ts","sourceRoot":"","sources":["../src/default_prompts.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAStD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAO/E;AAED,eAAO,MAAM,mBAAmB,QAA+B,CAAC;AAMhE,eAAO,MAAM,2BAA2B,QAAkE,CAAC;AAC3G,eAAO,MAAM,qBAAqB,QAA4D,CAAC;AAC/F,eAAO,MAAM,8BAA8B,QAAqE,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { splitFrontmatter } from "./prompt.js";
|
|
5
|
+
function bundledPromptPath(name) {
|
|
6
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
return join(here, "..", "prompts", name);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Load a bundled markdown prompt from packages/agent/prompts.
|
|
11
|
+
*
|
|
12
|
+
* This is intentionally strict: bundled prompt markdown is the single source
|
|
13
|
+
* of truth for default system prompts.
|
|
14
|
+
*/
|
|
15
|
+
export function loadBundledPrompt(name) {
|
|
16
|
+
const path = bundledPromptPath(name);
|
|
17
|
+
const raw = readFileSync(path, "utf8");
|
|
18
|
+
const { body } = splitFrontmatter(raw);
|
|
19
|
+
const prompt = body.trim();
|
|
20
|
+
if (prompt.length === 0) {
|
|
21
|
+
throw new Error(`bundled prompt is empty: ${name}`);
|
|
22
|
+
}
|
|
23
|
+
return prompt;
|
|
24
|
+
}
|
|
25
|
+
export function appendSharedSoul(basePrompt, soulPrompt) {
|
|
26
|
+
const base = basePrompt.trim();
|
|
27
|
+
const soul = soulPrompt.trim();
|
|
28
|
+
if (soul.length === 0) {
|
|
29
|
+
return base;
|
|
30
|
+
}
|
|
31
|
+
return `${base}\n\n${soul}`;
|
|
32
|
+
}
|
|
33
|
+
export const DEFAULT_SOUL_PROMPT = loadBundledPrompt("soul.md");
|
|
34
|
+
const BASE_ORCHESTRATOR_PROMPT = loadBundledPrompt("orchestrator.md");
|
|
35
|
+
const BASE_WORKER_PROMPT = loadBundledPrompt("worker.md");
|
|
36
|
+
const BASE_OPERATOR_SYSTEM_PROMPT = loadBundledPrompt("operator.md");
|
|
37
|
+
export const DEFAULT_ORCHESTRATOR_PROMPT = appendSharedSoul(BASE_ORCHESTRATOR_PROMPT, DEFAULT_SOUL_PROMPT);
|
|
38
|
+
export const DEFAULT_WORKER_PROMPT = appendSharedSoul(BASE_WORKER_PROMPT, DEFAULT_SOUL_PROMPT);
|
|
39
|
+
export const DEFAULT_OPERATOR_SYSTEM_PROMPT = appendSharedSoul(BASE_OPERATOR_SYSTEM_PROMPT, DEFAULT_SOUL_PROMPT);
|
|
@@ -4,7 +4,9 @@ export { eventLogExtension } from "./event-log.js";
|
|
|
4
4
|
export { heartbeatsExtension } from "./heartbeats.js";
|
|
5
5
|
export { messagingSetupExtension } from "./messaging-setup.js";
|
|
6
6
|
export { orchestrationRunsExtension } from "./orchestration-runs.js";
|
|
7
|
-
export {
|
|
7
|
+
export { orchestrationRunsReadOnlyExtension } from "./orchestration-runs-readonly.js";
|
|
8
|
+
export { serverToolsExtension, serverToolsReadOnlyExtension } from "./server-tools.js";
|
|
9
|
+
export { serverToolsReadonlyExtension } from "./server-tools-readonly.js";
|
|
8
10
|
/**
|
|
9
11
|
* Serve-mode extension module paths.
|
|
10
12
|
*
|
|
@@ -13,4 +15,11 @@ export { serverToolsExtension } from "./server-tools.js";
|
|
|
13
15
|
* anonymous inline factories.
|
|
14
16
|
*/
|
|
15
17
|
export declare const serveExtensionPaths: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Control-plane operator extension module paths.
|
|
20
|
+
*
|
|
21
|
+
* This set is intentionally read-only for tool-invoked actions so all
|
|
22
|
+
* mutations flow through approved `/mu ...` command proposals and policy.
|
|
23
|
+
*/
|
|
24
|
+
export declare const operatorExtensionPaths: string[];
|
|
16
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,kCAAkC,EAAE,MAAM,kCAAkC,CAAC;AACtF,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAyB1E;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,UAE/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,UAElC,CAAC"}
|
package/dist/extensions/index.js
CHANGED
|
@@ -4,7 +4,9 @@ export { eventLogExtension } from "./event-log.js";
|
|
|
4
4
|
export { heartbeatsExtension } from "./heartbeats.js";
|
|
5
5
|
export { messagingSetupExtension } from "./messaging-setup.js";
|
|
6
6
|
export { orchestrationRunsExtension } from "./orchestration-runs.js";
|
|
7
|
-
export {
|
|
7
|
+
export { orchestrationRunsReadOnlyExtension } from "./orchestration-runs-readonly.js";
|
|
8
|
+
export { serverToolsExtension, serverToolsReadOnlyExtension } from "./server-tools.js";
|
|
9
|
+
export { serverToolsReadonlyExtension } from "./server-tools-readonly.js";
|
|
8
10
|
const SERVE_EXTENSION_MODULE_BASENAMES = [
|
|
9
11
|
"branding",
|
|
10
12
|
"server-tools",
|
|
@@ -14,6 +16,13 @@ const SERVE_EXTENSION_MODULE_BASENAMES = [
|
|
|
14
16
|
"activities",
|
|
15
17
|
"heartbeats",
|
|
16
18
|
];
|
|
19
|
+
const OPERATOR_EXTENSION_MODULE_BASENAMES = [
|
|
20
|
+
"branding",
|
|
21
|
+
"server-tools-readonly",
|
|
22
|
+
"event-log",
|
|
23
|
+
"messaging-setup",
|
|
24
|
+
"orchestration-runs-readonly",
|
|
25
|
+
];
|
|
17
26
|
const RUNTIME_EXTENSION = import.meta.url.endsWith(".ts") ? "ts" : "js";
|
|
18
27
|
function resolveBundledExtensionPath(moduleBasename) {
|
|
19
28
|
return new URL(`./${moduleBasename}.${RUNTIME_EXTENSION}`, import.meta.url).pathname;
|
|
@@ -26,3 +35,10 @@ function resolveBundledExtensionPath(moduleBasename) {
|
|
|
26
35
|
* anonymous inline factories.
|
|
27
36
|
*/
|
|
28
37
|
export const serveExtensionPaths = SERVE_EXTENSION_MODULE_BASENAMES.map((moduleBasename) => resolveBundledExtensionPath(moduleBasename));
|
|
38
|
+
/**
|
|
39
|
+
* Control-plane operator extension module paths.
|
|
40
|
+
*
|
|
41
|
+
* This set is intentionally read-only for tool-invoked actions so all
|
|
42
|
+
* mutations flow through approved `/mu ...` command proposals and policy.
|
|
43
|
+
*/
|
|
44
|
+
export const operatorExtensionPaths = OPERATOR_EXTENSION_MODULE_BASENAMES.map((moduleBasename) => resolveBundledExtensionPath(moduleBasename));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestration-runs-readonly.d.ts","sourceRoot":"","sources":["../../src/extensions/orchestration-runs-readonly.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAUlE,wBAAgB,kCAAkC,CAAC,EAAE,EAAE,YAAY,QA8ClE;AAED,eAAe,kCAAkC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { StringEnum } from "@mariozechner/pi-ai";
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
import { clampInt, fetchMuJson, textResult, toJsonText } from "./shared.js";
|
|
4
|
+
function trimOrNull(value) {
|
|
5
|
+
if (value == null)
|
|
6
|
+
return null;
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
9
|
+
}
|
|
10
|
+
export function orchestrationRunsReadOnlyExtension(pi) {
|
|
11
|
+
const RunsParams = Type.Object({
|
|
12
|
+
action: StringEnum(["list", "status", "trace"]),
|
|
13
|
+
job_id: Type.Optional(Type.String({ description: "Run job ID" })),
|
|
14
|
+
root_issue_id: Type.Optional(Type.String({ description: "Run root issue ID (mu-...)" })),
|
|
15
|
+
limit: Type.Optional(Type.Number({ description: "Optional limit (list/trace)" })),
|
|
16
|
+
status: Type.Optional(Type.String({ description: "Optional status filter for list" })),
|
|
17
|
+
});
|
|
18
|
+
pi.registerTool({
|
|
19
|
+
name: "mu_runs",
|
|
20
|
+
label: "Runs",
|
|
21
|
+
description: "Read-only run inspection. Actions: list, status, trace. Mutating actions are disabled in operator mode.",
|
|
22
|
+
parameters: RunsParams,
|
|
23
|
+
async execute(_toolCallId, params) {
|
|
24
|
+
switch (params.action) {
|
|
25
|
+
case "list": {
|
|
26
|
+
const query = new URLSearchParams();
|
|
27
|
+
const status = trimOrNull(params.status);
|
|
28
|
+
if (status)
|
|
29
|
+
query.set("status", status);
|
|
30
|
+
const limit = clampInt(params.limit, 50, 1, 500);
|
|
31
|
+
query.set("limit", String(limit));
|
|
32
|
+
const payload = await fetchMuJson(`/api/runs?${query.toString()}`);
|
|
33
|
+
return textResult(toJsonText(payload), { action: "list", status, limit });
|
|
34
|
+
}
|
|
35
|
+
case "status": {
|
|
36
|
+
const id = trimOrNull(params.job_id) ?? trimOrNull(params.root_issue_id);
|
|
37
|
+
if (!id)
|
|
38
|
+
return textResult("status requires job_id or root_issue_id");
|
|
39
|
+
const payload = await fetchMuJson(`/api/runs/${encodeURIComponent(id)}`);
|
|
40
|
+
return textResult(toJsonText(payload), { action: "status", id });
|
|
41
|
+
}
|
|
42
|
+
case "trace": {
|
|
43
|
+
const id = trimOrNull(params.job_id) ?? trimOrNull(params.root_issue_id);
|
|
44
|
+
if (!id)
|
|
45
|
+
return textResult("trace requires job_id or root_issue_id");
|
|
46
|
+
const limit = clampInt(params.limit, 200, 1, 2_000);
|
|
47
|
+
const payload = await fetchMuJson(`/api/runs/${encodeURIComponent(id)}/trace?limit=${limit}`);
|
|
48
|
+
return textResult(toJsonText(payload), { action: "trace", id, limit });
|
|
49
|
+
}
|
|
50
|
+
default:
|
|
51
|
+
return textResult(`unknown action: ${params.action}`);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export default orchestrationRunsReadOnlyExtension;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-tools-readonly.d.ts","sourceRoot":"","sources":["../../src/extensions/server-tools-readonly.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,YAAY,QAE5D;AAED,eAAe,4BAA4B,CAAC"}
|
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
* This is the core extension the operator relies on for repo introspection.
|
|
5
5
|
*/
|
|
6
6
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
7
|
-
export
|
|
7
|
+
export type ServerToolsExtensionOpts = {
|
|
8
|
+
allowForumPost?: boolean;
|
|
9
|
+
toolIntroLine?: string;
|
|
10
|
+
extraSystemPromptLines?: string[];
|
|
11
|
+
};
|
|
12
|
+
export declare function serverToolsExtension(pi: ExtensionAPI, opts?: ServerToolsExtensionOpts): void;
|
|
13
|
+
export declare function serverToolsReadOnlyExtension(pi: ExtensionAPI): void;
|
|
8
14
|
export default serverToolsExtension;
|
|
9
15
|
//# sourceMappingURL=server-tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-tools.d.ts","sourceRoot":"","sources":["../../src/extensions/server-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAgElE,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"server-tools.d.ts","sourceRoot":"","sources":["../../src/extensions/server-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAgElE,MAAM,MAAM,wBAAwB,GAAG;IACtC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC,CAAC;AA4SF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,GAAE,wBAA6B,QAQzF;AAED,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,YAAY,QAS5D;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -45,7 +45,7 @@ function sliceWithLimit(items, limitRaw, fallback = 50) {
|
|
|
45
45
|
truncated: sliced.length < total,
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
function registerServerTools(pi, opts) {
|
|
49
49
|
pi.on("before_agent_start", async (event) => {
|
|
50
50
|
const url = muServerUrl();
|
|
51
51
|
if (!url)
|
|
@@ -53,8 +53,9 @@ export function serverToolsExtension(pi) {
|
|
|
53
53
|
const extra = [
|
|
54
54
|
"",
|
|
55
55
|
`[MU SERVER] Connected at ${url}.`,
|
|
56
|
-
|
|
56
|
+
opts.toolIntroLine,
|
|
57
57
|
"Use these tools to inspect repository state and control-plane runtime before advising users.",
|
|
58
|
+
...opts.extraSystemPromptLines,
|
|
58
59
|
].join("\n");
|
|
59
60
|
return {
|
|
60
61
|
systemPrompt: `${event.systemPrompt}${extra}`,
|
|
@@ -201,6 +202,9 @@ export function serverToolsExtension(pi) {
|
|
|
201
202
|
});
|
|
202
203
|
}
|
|
203
204
|
case "post": {
|
|
205
|
+
if (!opts.allowForumPost) {
|
|
206
|
+
return textResult("forum post is disabled in operator read-only mode; use approved /mu command flow for mutations.", { blocked: true, reason: "operator_read_only_tools" });
|
|
207
|
+
}
|
|
204
208
|
const topic = trimOrNull(params.topic);
|
|
205
209
|
const body = trimOrNull(params.body);
|
|
206
210
|
if (!topic)
|
|
@@ -315,4 +319,21 @@ export function serverToolsExtension(pi) {
|
|
|
315
319
|
},
|
|
316
320
|
});
|
|
317
321
|
}
|
|
322
|
+
export function serverToolsExtension(pi, opts = {}) {
|
|
323
|
+
registerServerTools(pi, {
|
|
324
|
+
allowForumPost: opts.allowForumPost ?? true,
|
|
325
|
+
toolIntroLine: opts.toolIntroLine ??
|
|
326
|
+
"Tools: mu_status, mu_control_plane, mu_issues, mu_forum, mu_events, mu_runs, mu_activities, mu_heartbeats.",
|
|
327
|
+
extraSystemPromptLines: opts.extraSystemPromptLines ?? [],
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
export function serverToolsReadOnlyExtension(pi) {
|
|
331
|
+
registerServerTools(pi, {
|
|
332
|
+
allowForumPost: false,
|
|
333
|
+
toolIntroLine: "Tools: mu_status, mu_control_plane, mu_issues, mu_forum(read/topics), mu_events, mu_runs(read), mu_messaging_setup(read).",
|
|
334
|
+
extraSystemPromptLines: [
|
|
335
|
+
"Mutating tool actions are disabled in operator mode; propose mutations via approved /mu commands.",
|
|
336
|
+
],
|
|
337
|
+
});
|
|
338
|
+
}
|
|
318
339
|
export default serverToolsExtension;
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAChG,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/mu_roles.d.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
+
import { DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_WORKER_PROMPT } from "./default_prompts.js";
|
|
1
2
|
export type MuRole = "orchestrator" | "worker";
|
|
2
3
|
/** Determine role from tags. Defaults to orchestrator if no role tag present. */
|
|
3
4
|
export declare function roleFromTags(tags: readonly string[]): MuRole;
|
|
4
|
-
export
|
|
5
|
-
export declare const DEFAULT_WORKER_PROMPT: string;
|
|
5
|
+
export { DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_WORKER_PROMPT };
|
|
6
6
|
/**
|
|
7
7
|
* Load the system prompt for a role.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* Frontmatter is stripped via `splitFrontmatter`.
|
|
12
|
-
* Falls back to the hardcoded default on any error.
|
|
9
|
+
* Role prompts are sourced from bundled markdown defaults only.
|
|
10
|
+
* Repo-local `.mu/roles/*.md` overrides are intentionally unsupported.
|
|
13
11
|
*/
|
|
14
|
-
export declare function systemPromptForRole(role: MuRole,
|
|
12
|
+
export declare function systemPromptForRole(role: MuRole, _repoRoot?: string): Promise<string>;
|
|
15
13
|
//# 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":"
|
|
1
|
+
{"version":3,"file":"mu_roles.d.ts","sourceRoot":"","sources":["../src/mu_roles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE1F,MAAM,MAAM,MAAM,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE/C,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAM5D;AAED,OAAO,EAAE,2BAA2B,EAAE,qBAAqB,EAAE,CAAC;AAE9D;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE3F"}
|
package/dist/mu_roles.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { splitFrontmatter } from "./prompt.js";
|
|
1
|
+
import { DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_WORKER_PROMPT } from "./default_prompts.js";
|
|
3
2
|
/** Determine role from tags. Defaults to orchestrator if no role tag present. */
|
|
4
3
|
export function roleFromTags(tags) {
|
|
5
4
|
for (const tag of tags) {
|
|
@@ -10,155 +9,13 @@ export function roleFromTags(tags) {
|
|
|
10
9
|
}
|
|
11
10
|
return "orchestrator";
|
|
12
11
|
}
|
|
13
|
-
|
|
14
|
-
/* mu CLI reference */
|
|
15
|
-
/* ------------------------------------------------------------------ */
|
|
16
|
-
const MU_CLI_REFERENCE = `
|
|
17
|
-
## mu CLI
|
|
18
|
-
|
|
19
|
-
You are running inside **mu**, an issue-driven orchestration system.
|
|
20
|
-
You have four tools: bash, read, write, edit.
|
|
21
|
-
|
|
22
|
-
- Orchestrator: use bash to run \`mu\` commands; do NOT use write/edit (and avoid read).
|
|
23
|
-
- Worker: use tools as needed to implement your assigned issue.
|
|
24
|
-
|
|
25
|
-
Tip: run \`mu <command> --help\` for details.
|
|
26
|
-
|
|
27
|
-
### Issues
|
|
28
|
-
|
|
29
|
-
\`\`\`bash
|
|
30
|
-
# Create a child issue (always set --parent and --role)
|
|
31
|
-
mu issues create "<title>" --parent <parent-id> --role worker [--body "<text>"] [--priority N] [--tag TAG]
|
|
32
|
-
|
|
33
|
-
# Inspect
|
|
34
|
-
mu issues get <id> # full issue detail
|
|
35
|
-
mu issues list --root <root-id> [--status open|in_progress|closed]
|
|
36
|
-
mu issues children <id> # direct children
|
|
37
|
-
mu issues ready --root <root-id> # executable leaves
|
|
38
|
-
|
|
39
|
-
# Status transitions
|
|
40
|
-
mu issues claim <id> # open → in_progress
|
|
41
|
-
mu issues close <id> --outcome <outcome> # close with outcome
|
|
42
|
-
|
|
43
|
-
# Dependencies
|
|
44
|
-
mu issues dep <src> blocks <dst> # src must close before dst starts
|
|
45
|
-
mu issues dep <child> parent <parent> # set parent-child edge
|
|
46
|
-
mu issues undep <src> blocks <dst> # remove blocking edge
|
|
47
|
-
|
|
48
|
-
# Update fields
|
|
49
|
-
mu issues update <id> [--title "..."] [--body "..."] [--role worker|orchestrator] [--priority N] [--add-tag TAG]
|
|
50
|
-
\`\`\`
|
|
51
|
-
|
|
52
|
-
### Outcomes
|
|
53
|
-
|
|
54
|
-
| Outcome | Meaning |
|
|
55
|
-
|--------------|-----------------------------------------------------|
|
|
56
|
-
| \`success\` | Work completed successfully (terminal) |
|
|
57
|
-
| \`failure\` | Work failed — triggers re-orchestration |
|
|
58
|
-
| \`needs_work\` | Partial — triggers re-orchestration |
|
|
59
|
-
| \`expanded\` | Decomposed into children (orchestrator closes self) |
|
|
60
|
-
| \`skipped\` | Not applicable (terminal) |
|
|
61
|
-
|
|
62
|
-
### Forum (logging & coordination)
|
|
63
|
-
|
|
64
|
-
\`\`\`bash
|
|
65
|
-
mu forum post issue:<id> -m "<message>" --author <role>
|
|
66
|
-
mu forum read issue:<id> [--limit N]
|
|
67
|
-
\`\`\`
|
|
68
|
-
`.trim();
|
|
69
|
-
/* ------------------------------------------------------------------ */
|
|
70
|
-
/* Default role prompts (exported for mu init + tests) */
|
|
71
|
-
/* ------------------------------------------------------------------ */
|
|
72
|
-
export const DEFAULT_ORCHESTRATOR_PROMPT = [
|
|
73
|
-
"# Mu Orchestrator",
|
|
74
|
-
"",
|
|
75
|
-
"You are mu's orchestrator: the hierarchical planner for the issue DAG.",
|
|
76
|
-
"",
|
|
77
|
-
"## Non-Negotiable Constraints",
|
|
78
|
-
"",
|
|
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.",
|
|
82
|
-
"",
|
|
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.",
|
|
87
|
-
"",
|
|
88
|
-
"## Workflow",
|
|
89
|
-
"",
|
|
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.",
|
|
97
|
-
"",
|
|
98
|
-
"## Rules",
|
|
99
|
-
"",
|
|
100
|
-
"- Use only roles: orchestrator, worker.",
|
|
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.",
|
|
110
|
-
"",
|
|
111
|
-
MU_CLI_REFERENCE,
|
|
112
|
-
].join("\n");
|
|
113
|
-
export const DEFAULT_WORKER_PROMPT = [
|
|
114
|
-
"# Mu Worker",
|
|
115
|
-
"",
|
|
116
|
-
"You are mu's worker. You execute exactly one atomic issue end-to-end.",
|
|
117
|
-
"",
|
|
118
|
-
"## Responsibilities",
|
|
119
|
-
"",
|
|
120
|
-
"- Implement the work described in your assigned issue.",
|
|
121
|
-
"- Keep scope tight to the issue specification.",
|
|
122
|
-
"- Verify results (tests, typecheck, build, lint, etc.) and report what changed.",
|
|
123
|
-
"- Close your issue with a terminal outcome when done.",
|
|
124
|
-
"",
|
|
125
|
-
"## Workflow",
|
|
126
|
-
"",
|
|
127
|
-
"1. Inspect: `mu issues get <id>` and `mu forum read issue:<id> --limit 20`.",
|
|
128
|
-
"2. Implement: edit files, run commands, and keep changes scoped to the issue.",
|
|
129
|
-
"3. Verify: run tests/build/typecheck/lint as appropriate. Prefer hard feedback loops.",
|
|
130
|
-
"4. Close: `mu issues close <id> --outcome success` (or `failure`/`skipped`).",
|
|
131
|
-
"5. Log key notes: `mu forum post issue:<id> -m '...' --author worker`.",
|
|
132
|
-
"",
|
|
133
|
-
"## Rules",
|
|
134
|
-
"",
|
|
135
|
-
"- Do NOT create child issues — that is the orchestrator's job.",
|
|
136
|
-
"- If the issue is too large/unclear, close with `--outcome needs_work` and explain what is missing.",
|
|
137
|
-
"",
|
|
138
|
-
MU_CLI_REFERENCE,
|
|
139
|
-
].join("\n");
|
|
140
|
-
/* ------------------------------------------------------------------ */
|
|
141
|
-
/* Role-specific system prompts */
|
|
142
|
-
/* ------------------------------------------------------------------ */
|
|
12
|
+
export { DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_WORKER_PROMPT };
|
|
143
13
|
/**
|
|
144
14
|
* Load the system prompt for a role.
|
|
145
15
|
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* Frontmatter is stripped via `splitFrontmatter`.
|
|
149
|
-
* Falls back to the hardcoded default on any error.
|
|
16
|
+
* Role prompts are sourced from bundled markdown defaults only.
|
|
17
|
+
* Repo-local `.mu/roles/*.md` overrides are intentionally unsupported.
|
|
150
18
|
*/
|
|
151
|
-
export async function systemPromptForRole(role,
|
|
152
|
-
if (repoRoot) {
|
|
153
|
-
try {
|
|
154
|
-
const filePath = join(repoRoot, ".mu", "roles", `${role}.md`);
|
|
155
|
-
const raw = await Bun.file(filePath).text();
|
|
156
|
-
const { body } = splitFrontmatter(raw);
|
|
157
|
-
return body;
|
|
158
|
-
}
|
|
159
|
-
catch {
|
|
160
|
-
// File missing or unreadable — fall through to default.
|
|
161
|
-
}
|
|
162
|
-
}
|
|
19
|
+
export async function systemPromptForRole(role, _repoRoot) {
|
|
163
20
|
return role === "orchestrator" ? DEFAULT_ORCHESTRATOR_PROMPT : DEFAULT_WORKER_PROMPT;
|
|
164
21
|
}
|
package/dist/operator.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { CommandContextResolver } from "./command_context.js";
|
|
3
3
|
import { type CreateMuSessionOpts, type MuSession } from "./session_factory.js";
|
|
4
|
+
import { DEFAULT_OPERATOR_SYSTEM_PROMPT } from "./default_prompts.js";
|
|
4
5
|
export type MessagingOperatorInboundEnvelope = {
|
|
5
6
|
channel: string;
|
|
6
7
|
channel_tenant_id: string;
|
|
@@ -160,13 +161,13 @@ export type PiMessagingOperatorBackendOpts = {
|
|
|
160
161
|
nowMs?: () => number;
|
|
161
162
|
sessionIdleTtlMs?: number;
|
|
162
163
|
maxSessions?: number;
|
|
164
|
+
auditTurns?: boolean;
|
|
163
165
|
};
|
|
164
|
-
export
|
|
166
|
+
export { DEFAULT_OPERATOR_SYSTEM_PROMPT };
|
|
165
167
|
export declare class PiMessagingOperatorBackend implements MessagingOperatorBackend {
|
|
166
168
|
#private;
|
|
167
169
|
constructor(opts?: PiMessagingOperatorBackendOpts);
|
|
168
170
|
runTurn(input: OperatorBackendTurnInput): Promise<OperatorBackendTurnResult>;
|
|
169
171
|
dispose(): void;
|
|
170
172
|
}
|
|
171
|
-
export {};
|
|
172
173
|
//# sourceMappingURL=operator.d.ts.map
|
package/dist/operator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"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"}
|
package/dist/operator.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { appendJsonl } from "@femtomc/mu-core/node";
|
|
2
|
+
import { join } from "node:path";
|
|
1
3
|
import { z } from "zod";
|
|
2
4
|
import { CommandContextResolver } from "./command_context.js";
|
|
3
5
|
import { createMuSession } from "./session_factory.js";
|
|
6
|
+
import { DEFAULT_OPERATOR_SYSTEM_PROMPT } from "./default_prompts.js";
|
|
4
7
|
const SAFE_RESPONSE_RE = /^[\s\S]{1,2000}$/;
|
|
5
8
|
export const OperatorApprovedCommandSchema = z.discriminatedUnion("kind", [
|
|
6
9
|
z.object({ kind: z.literal("status") }),
|
|
@@ -36,6 +39,10 @@ export const OperatorBackendTurnResultSchema = z.discriminatedUnion("kind", [
|
|
|
36
39
|
z.object({ kind: z.literal("respond"), message: z.string().trim().min(1).max(2000) }),
|
|
37
40
|
z.object({ kind: z.literal("command"), command: OperatorApprovedCommandSchema }),
|
|
38
41
|
]);
|
|
42
|
+
const OperatorDecisionEnvelopeSchema = z.discriminatedUnion("kind", [
|
|
43
|
+
z.object({ kind: z.literal("respond"), message: z.string().trim().min(1).max(2000) }),
|
|
44
|
+
z.object({ kind: z.literal("command"), command: OperatorApprovedCommandSchema }),
|
|
45
|
+
]);
|
|
39
46
|
function splitPromptIntoTokens(prompt) {
|
|
40
47
|
return prompt
|
|
41
48
|
.split(/\s+/)
|
|
@@ -157,6 +164,13 @@ function defaultSessionId() {
|
|
|
157
164
|
function defaultTurnId() {
|
|
158
165
|
return `turn-${crypto.randomUUID()}`;
|
|
159
166
|
}
|
|
167
|
+
function buildOperatorFailureFallbackMessage(code) {
|
|
168
|
+
return [
|
|
169
|
+
"I ran into an internal operator formatting/runtime issue and could not complete that turn safely.",
|
|
170
|
+
`Code: ${code}`,
|
|
171
|
+
"You can retry, or use an explicit /mu command (for example: /mu status or /mu run list).",
|
|
172
|
+
].join("\n");
|
|
173
|
+
}
|
|
160
174
|
function conversationKey(inbound, binding) {
|
|
161
175
|
return `${inbound.channel}:${inbound.channel_tenant_id}:${inbound.channel_conversation_id}:${binding.binding_id}`;
|
|
162
176
|
}
|
|
@@ -216,9 +230,8 @@ export class MessagingOperatorRuntime {
|
|
|
216
230
|
}
|
|
217
231
|
catch (err) {
|
|
218
232
|
return {
|
|
219
|
-
kind: "
|
|
220
|
-
|
|
221
|
-
details: err instanceof Error ? err.message : "operator_backend_error",
|
|
233
|
+
kind: "response",
|
|
234
|
+
message: buildOperatorFailureFallbackMessage("operator_backend_error"),
|
|
222
235
|
operatorSessionId: sessionId,
|
|
223
236
|
operatorTurnId: turnId,
|
|
224
237
|
};
|
|
@@ -227,9 +240,8 @@ export class MessagingOperatorRuntime {
|
|
|
227
240
|
const message = backendResult.message.trim();
|
|
228
241
|
if (!SAFE_RESPONSE_RE.test(message)) {
|
|
229
242
|
return {
|
|
230
|
-
kind: "
|
|
231
|
-
|
|
232
|
-
details: "invalid response payload",
|
|
243
|
+
kind: "response",
|
|
244
|
+
message: buildOperatorFailureFallbackMessage("operator_invalid_response_payload"),
|
|
233
245
|
operatorSessionId: sessionId,
|
|
234
246
|
operatorTurnId: turnId,
|
|
235
247
|
};
|
|
@@ -266,63 +278,107 @@ export class MessagingOperatorRuntime {
|
|
|
266
278
|
await this.#backend.dispose?.();
|
|
267
279
|
}
|
|
268
280
|
}
|
|
269
|
-
export
|
|
270
|
-
"You are mu, an AI assistant for the mu orchestration platform.",
|
|
271
|
-
"Help users with:",
|
|
272
|
-
"- Understanding mu's architecture (issues, forum, orchestrator, control-plane)",
|
|
273
|
-
"- Setting up control-plane integrations (Slack, Discord, Telegram, Gmail planning)",
|
|
274
|
-
"- Navigating issues and forum topics",
|
|
275
|
-
"- Running and monitoring orchestrator workflows",
|
|
276
|
-
"- General questions about the mu ecosystem",
|
|
277
|
-
"",
|
|
278
|
-
"Be concise, practical, and actionable.",
|
|
279
|
-
].join("\n");
|
|
281
|
+
export { DEFAULT_OPERATOR_SYSTEM_PROMPT };
|
|
280
282
|
const OPERATOR_COMMAND_PREFIX = "MU_COMMAND:";
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
"Be concise, practical, and actionable.",
|
|
294
|
-
"For normal conversational answers, respond in plain text.",
|
|
295
|
-
].join("\n");
|
|
296
|
-
function parseOperatorCommandDirective(text) {
|
|
283
|
+
const OPERATOR_DECISION_PREFIX = "MU_DECISION:";
|
|
284
|
+
function stripOperatorDirectiveLines(text) {
|
|
285
|
+
return text
|
|
286
|
+
.split(/\r?\n/)
|
|
287
|
+
.filter((line) => {
|
|
288
|
+
const trimmed = line.trim();
|
|
289
|
+
return !(trimmed.startsWith(OPERATOR_COMMAND_PREFIX) || trimmed.startsWith(OPERATOR_DECISION_PREFIX));
|
|
290
|
+
})
|
|
291
|
+
.join("\n")
|
|
292
|
+
.trim();
|
|
293
|
+
}
|
|
294
|
+
function parseOperatorDirective(text) {
|
|
297
295
|
const whole = text.trim();
|
|
298
296
|
if (whole.startsWith("{") && whole.endsWith("}")) {
|
|
299
297
|
try {
|
|
300
|
-
|
|
298
|
+
const parsed = JSON.parse(whole);
|
|
299
|
+
const envelope = OperatorDecisionEnvelopeSchema.safeParse(parsed);
|
|
300
|
+
if (envelope.success) {
|
|
301
|
+
return envelope.data.kind === "command"
|
|
302
|
+
? { kind: "command", command: envelope.data.command }
|
|
303
|
+
: { kind: "respond", message: envelope.data.message };
|
|
304
|
+
}
|
|
305
|
+
const legacy = OperatorApprovedCommandSchema.safeParse(parsed);
|
|
306
|
+
if (legacy.success) {
|
|
307
|
+
return { kind: "command", command: legacy.data };
|
|
308
|
+
}
|
|
301
309
|
}
|
|
302
310
|
catch {
|
|
303
|
-
// fall through to
|
|
311
|
+
// fall through to line-based directives / plain text fallback.
|
|
304
312
|
}
|
|
305
313
|
}
|
|
306
314
|
const lines = text.split(/\r?\n/);
|
|
307
315
|
for (const line of lines) {
|
|
308
316
|
const trimmed = line.trim();
|
|
317
|
+
if (trimmed.startsWith(OPERATOR_DECISION_PREFIX)) {
|
|
318
|
+
const payloadText = trimmed.slice(OPERATOR_DECISION_PREFIX.length).trim();
|
|
319
|
+
if (payloadText.length === 0) {
|
|
320
|
+
return {
|
|
321
|
+
kind: "invalid",
|
|
322
|
+
reason: "operator_decision_directive_missing_payload",
|
|
323
|
+
fallbackMessage: stripOperatorDirectiveLines(text),
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
let parsed;
|
|
327
|
+
try {
|
|
328
|
+
parsed = JSON.parse(payloadText);
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
return {
|
|
332
|
+
kind: "invalid",
|
|
333
|
+
reason: `operator_decision_directive_invalid_json: ${err instanceof Error ? err.message : String(err)}`,
|
|
334
|
+
fallbackMessage: stripOperatorDirectiveLines(text),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
const envelope = OperatorDecisionEnvelopeSchema.safeParse(parsed);
|
|
338
|
+
if (!envelope.success) {
|
|
339
|
+
return {
|
|
340
|
+
kind: "invalid",
|
|
341
|
+
reason: `operator_decision_directive_invalid_payload: ${envelope.error.message}`,
|
|
342
|
+
fallbackMessage: stripOperatorDirectiveLines(text),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
return envelope.data.kind === "command"
|
|
346
|
+
? { kind: "command", command: envelope.data.command }
|
|
347
|
+
: { kind: "respond", message: envelope.data.message };
|
|
348
|
+
}
|
|
309
349
|
if (!trimmed.startsWith(OPERATOR_COMMAND_PREFIX)) {
|
|
310
350
|
continue;
|
|
311
351
|
}
|
|
312
352
|
const payloadText = trimmed.slice(OPERATOR_COMMAND_PREFIX.length).trim();
|
|
313
353
|
if (payloadText.length === 0) {
|
|
314
|
-
|
|
354
|
+
return {
|
|
355
|
+
kind: "invalid",
|
|
356
|
+
reason: "operator_command_directive_missing_payload",
|
|
357
|
+
fallbackMessage: stripOperatorDirectiveLines(text),
|
|
358
|
+
};
|
|
315
359
|
}
|
|
316
360
|
let parsed;
|
|
317
361
|
try {
|
|
318
362
|
parsed = JSON.parse(payloadText);
|
|
319
363
|
}
|
|
320
364
|
catch (err) {
|
|
321
|
-
|
|
365
|
+
return {
|
|
366
|
+
kind: "invalid",
|
|
367
|
+
reason: `operator_command_directive_invalid_json: ${err instanceof Error ? err.message : String(err)}`,
|
|
368
|
+
fallbackMessage: stripOperatorDirectiveLines(text),
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
const command = OperatorApprovedCommandSchema.safeParse(parsed);
|
|
372
|
+
if (!command.success) {
|
|
373
|
+
return {
|
|
374
|
+
kind: "invalid",
|
|
375
|
+
reason: `operator_command_directive_invalid_payload: ${command.error.message}`,
|
|
376
|
+
fallbackMessage: stripOperatorDirectiveLines(text),
|
|
377
|
+
};
|
|
322
378
|
}
|
|
323
|
-
return
|
|
379
|
+
return { kind: "command", command: command.data };
|
|
324
380
|
}
|
|
325
|
-
return
|
|
381
|
+
return { kind: "none" };
|
|
326
382
|
}
|
|
327
383
|
function buildOperatorPrompt(input) {
|
|
328
384
|
return [
|
|
@@ -345,6 +401,7 @@ export class PiMessagingOperatorBackend {
|
|
|
345
401
|
#nowMs;
|
|
346
402
|
#sessionIdleTtlMs;
|
|
347
403
|
#maxSessions;
|
|
404
|
+
#auditTurns;
|
|
348
405
|
#sessions = new Map();
|
|
349
406
|
constructor(opts = {}) {
|
|
350
407
|
this.#provider = opts.provider;
|
|
@@ -357,6 +414,7 @@ export class PiMessagingOperatorBackend {
|
|
|
357
414
|
this.#nowMs = opts.nowMs ?? Date.now;
|
|
358
415
|
this.#sessionIdleTtlMs = Math.max(60_000, Math.trunc(opts.sessionIdleTtlMs ?? 30 * 60 * 1_000));
|
|
359
416
|
this.#maxSessions = Math.max(1, Math.trunc(opts.maxSessions ?? 32));
|
|
417
|
+
this.#auditTurns = opts.auditTurns ?? true;
|
|
360
418
|
}
|
|
361
419
|
#disposeSession(sessionId) {
|
|
362
420
|
const entry = this.#sessions.get(sessionId);
|
|
@@ -429,6 +487,31 @@ export class PiMessagingOperatorBackend {
|
|
|
429
487
|
this.#pruneSessions(nowMs);
|
|
430
488
|
return created;
|
|
431
489
|
}
|
|
490
|
+
async #auditTurn(input, opts) {
|
|
491
|
+
if (!this.#auditTurns) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
const entry = {
|
|
495
|
+
kind: "operator.turn",
|
|
496
|
+
ts_ms: Math.trunc(this.#nowMs()),
|
|
497
|
+
repo_root: input.inbound.repo_root,
|
|
498
|
+
channel: input.inbound.channel,
|
|
499
|
+
request_id: input.inbound.request_id,
|
|
500
|
+
session_id: input.sessionId,
|
|
501
|
+
turn_id: input.turnId,
|
|
502
|
+
outcome: opts.outcome,
|
|
503
|
+
reason: opts.reason ?? null,
|
|
504
|
+
message_preview: opts.messagePreview?.slice(0, 280) ?? null,
|
|
505
|
+
command: opts.command ?? null,
|
|
506
|
+
};
|
|
507
|
+
try {
|
|
508
|
+
const path = join(input.inbound.repo_root, ".mu", "control-plane", "operator_turns.jsonl");
|
|
509
|
+
await appendJsonl(path, entry);
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
// best effort audit
|
|
513
|
+
}
|
|
514
|
+
}
|
|
432
515
|
async runTurn(input) {
|
|
433
516
|
const sessionRecord = await this.#resolveSession(input.sessionId, input.inbound.repo_root);
|
|
434
517
|
const session = sessionRecord.session;
|
|
@@ -463,22 +546,77 @@ export class PiMessagingOperatorBackend {
|
|
|
463
546
|
timeoutPromise,
|
|
464
547
|
]);
|
|
465
548
|
}
|
|
549
|
+
catch (err) {
|
|
550
|
+
await this.#auditTurn(input, {
|
|
551
|
+
outcome: "error",
|
|
552
|
+
reason: err instanceof Error ? err.message : "operator_backend_error",
|
|
553
|
+
messagePreview: assistantText,
|
|
554
|
+
});
|
|
555
|
+
throw err;
|
|
556
|
+
}
|
|
466
557
|
finally {
|
|
467
558
|
unsub();
|
|
468
559
|
sessionRecord.lastUsedAtMs = Math.trunc(this.#nowMs());
|
|
469
560
|
}
|
|
470
561
|
const message = assistantText.trim();
|
|
471
562
|
if (!message) {
|
|
563
|
+
await this.#auditTurn(input, {
|
|
564
|
+
outcome: "error",
|
|
565
|
+
reason: "operator_empty_response",
|
|
566
|
+
});
|
|
472
567
|
throw new Error("operator_empty_response");
|
|
473
568
|
}
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
569
|
+
const parsed = parseOperatorDirective(message);
|
|
570
|
+
switch (parsed.kind) {
|
|
571
|
+
case "command":
|
|
572
|
+
await this.#auditTurn(input, {
|
|
573
|
+
outcome: "command",
|
|
574
|
+
command: parsed.command,
|
|
575
|
+
messagePreview: message,
|
|
576
|
+
});
|
|
577
|
+
return {
|
|
578
|
+
kind: "command",
|
|
579
|
+
command: parsed.command,
|
|
580
|
+
};
|
|
581
|
+
case "respond": {
|
|
582
|
+
const responseMessage = parsed.message.trim().slice(0, 2000);
|
|
583
|
+
if (!SAFE_RESPONSE_RE.test(responseMessage)) {
|
|
584
|
+
const fallback = buildOperatorFailureFallbackMessage("operator_invalid_response_payload");
|
|
585
|
+
await this.#auditTurn(input, {
|
|
586
|
+
outcome: "invalid_directive",
|
|
587
|
+
reason: "operator_invalid_response_payload",
|
|
588
|
+
messagePreview: message,
|
|
589
|
+
});
|
|
590
|
+
return { kind: "respond", message: fallback };
|
|
591
|
+
}
|
|
592
|
+
await this.#auditTurn(input, {
|
|
593
|
+
outcome: "respond",
|
|
594
|
+
messagePreview: responseMessage,
|
|
595
|
+
});
|
|
596
|
+
return { kind: "respond", message: responseMessage };
|
|
597
|
+
}
|
|
598
|
+
case "invalid": {
|
|
599
|
+
const fallbackMessage = parsed.fallbackMessage.trim();
|
|
600
|
+
const responseMessage = fallbackMessage.length > 0
|
|
601
|
+
? fallbackMessage.slice(0, 2000)
|
|
602
|
+
: buildOperatorFailureFallbackMessage("operator_invalid_command_directive");
|
|
603
|
+
await this.#auditTurn(input, {
|
|
604
|
+
outcome: "invalid_directive",
|
|
605
|
+
reason: parsed.reason,
|
|
606
|
+
messagePreview: message,
|
|
607
|
+
});
|
|
608
|
+
return { kind: "respond", message: responseMessage };
|
|
609
|
+
}
|
|
610
|
+
case "none":
|
|
611
|
+
default: {
|
|
612
|
+
const responseMessage = message.slice(0, 2000);
|
|
613
|
+
await this.#auditTurn(input, {
|
|
614
|
+
outcome: "respond",
|
|
615
|
+
messagePreview: responseMessage,
|
|
616
|
+
});
|
|
617
|
+
return { kind: "respond", message: responseMessage };
|
|
618
|
+
}
|
|
480
619
|
}
|
|
481
|
-
return { kind: "respond", message: message.slice(0, 2000) };
|
|
482
620
|
}
|
|
483
621
|
dispose() {
|
|
484
622
|
for (const sessionId of [...this.#sessions.keys()]) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@femtomc/mu-agent",
|
|
3
|
-
"version": "26.2.
|
|
3
|
+
"version": "26.2.44",
|
|
4
4
|
"description": "Shared agent runtime for mu chat, orchestration roles, and serve extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mu",
|
|
@@ -19,10 +19,11 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
|
-
"dist/**"
|
|
22
|
+
"dist/**",
|
|
23
|
+
"prompts/**"
|
|
23
24
|
],
|
|
24
25
|
"dependencies": {
|
|
25
|
-
"@femtomc/mu-core": "26.2.
|
|
26
|
+
"@femtomc/mu-core": "26.2.44",
|
|
26
27
|
"@mariozechner/pi-agent-core": "^0.52.12",
|
|
27
28
|
"@mariozechner/pi-ai": "^0.52.12",
|
|
28
29
|
"@mariozechner/pi-coding-agent": "^0.52.12",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
You are an operator: you help users interact with and utilize all the capabilities that mu has to offer.
|
|
2
|
+
|
|
3
|
+
Mission:
|
|
4
|
+
- Free flowing discussion with users about their interests.
|
|
5
|
+
- Help users with any coding tasks they ask you to handle directly.
|
|
6
|
+
- Help users inspect repository/control-plane state.
|
|
7
|
+
- Help users choose safe next actions.
|
|
8
|
+
- When needed, propose approved operator commands.
|
|
9
|
+
|
|
10
|
+
Available tools:
|
|
11
|
+
- read: Read file contents
|
|
12
|
+
- bash: Execute bash commands
|
|
13
|
+
- edit: Make surgical edits to files
|
|
14
|
+
- write: Create or overwrite files
|
|
15
|
+
|
|
16
|
+
You also have access to specialized read/diagnostic tools:
|
|
17
|
+
- `mu_status`
|
|
18
|
+
- `mu_control_plane`
|
|
19
|
+
- `mu_issues`
|
|
20
|
+
- `mu_forum`
|
|
21
|
+
- `mu_events`
|
|
22
|
+
- `mu_runs`
|
|
23
|
+
- `mu_activities`
|
|
24
|
+
- `mu_heartbeats`
|
|
25
|
+
- `mu_messaging_setup`
|
|
26
|
+
|
|
27
|
+
Hard Constraints:
|
|
28
|
+
- Never perform mutations directly through tools in operator mode.
|
|
29
|
+
- Mutating actions must flow through approved command proposals.
|
|
30
|
+
- If a command is needed, output exactly one line prefixed with `MU_DECISION:` and compact JSON.
|
|
31
|
+
|
|
32
|
+
Command envelope example:
|
|
33
|
+
|
|
34
|
+
`MU_DECISION: {"kind":"command","command":{"kind":"run_start","prompt":"ship release"}}`
|
|
35
|
+
|
|
36
|
+
Allowed command kinds:
|
|
37
|
+
- `status`
|
|
38
|
+
- `ready`
|
|
39
|
+
- `issue_list`
|
|
40
|
+
- `issue_get`
|
|
41
|
+
- `forum_read`
|
|
42
|
+
- `run_list`
|
|
43
|
+
- `run_status`
|
|
44
|
+
- `run_start`
|
|
45
|
+
- `run_resume`
|
|
46
|
+
- `run_interrupt`
|
|
47
|
+
|
|
48
|
+
For normal answers:
|
|
49
|
+
- Respond in plain text (no directive prefix).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
You are an orchestrator: you help by engaging in planning and review as part of the orchestration engine within mu.
|
|
2
|
+
|
|
3
|
+
Mission:
|
|
4
|
+
- Read and think carefully about the issue assigned to you. Use mu's CLI to explore related issues, and the forum for relevant conversation.
|
|
5
|
+
- Decompose your assigned issue into executable worker issues, or further orchestrator issues if multi-layer decomposition is appropriate.
|
|
6
|
+
- Define ordering via dependencies.
|
|
7
|
+
- Move planning state forward by closing expanded planning nodes.
|
|
8
|
+
|
|
9
|
+
Hard Constraints:
|
|
10
|
+
1. You MUST NOT execute work directly. No code changes, no file edits, no git commits.
|
|
11
|
+
2. You MUST decompose the assigned issue into worker child issues.
|
|
12
|
+
3. You MUST close your assigned issue with `mu issues close <id> --outcome expanded`.
|
|
13
|
+
4. Decomposition MUST be deterministic and minimal. Use `blocks` edges for sequencing.
|
|
14
|
+
5. Every executable leaf MUST be `--role worker`.
|
|
15
|
+
|
|
16
|
+
If the task looks atomic, create exactly one worker child issue rather than doing the work yourself.
|
|
17
|
+
|
|
18
|
+
Workflow:
|
|
19
|
+
1. Inspect context:
|
|
20
|
+
- `mu issues get <id>`
|
|
21
|
+
- `mu forum read issue:<id> --limit 20`
|
|
22
|
+
- `mu issues children <id>`
|
|
23
|
+
2. Decompose into worker issues:
|
|
24
|
+
- `mu issues create "<title>" --parent <id> --role worker`
|
|
25
|
+
3. Add ordering where needed:
|
|
26
|
+
- `mu issues dep <src> blocks <dst>`
|
|
27
|
+
4. Close yourself:
|
|
28
|
+
- `mu issues close <id> --outcome expanded`
|
|
29
|
+
|
|
30
|
+
Guardrails:
|
|
31
|
+
- The only valid orchestrator close outcome is `expanded`.
|
|
32
|
+
- Never close with `success`, `failure`, `needs_work`, or `skipped`.
|
|
33
|
+
- Keep plans small, explicit, and testable.
|
|
34
|
+
- Plans should include proposed evidence for successful completion.
|
package/prompts/soul.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
## Shared Soul
|
|
2
|
+
|
|
3
|
+
- Prefer investigation over recall: don't regurgitate from your training, investigate if you can.
|
|
4
|
+
- Prefer truth over fluency: do not invent facts, state uncertainty clearly.
|
|
5
|
+
- Prefer evidence over claims: reference concrete observations, tool results, or commands.
|
|
6
|
+
- Prefer safety over speed: avoid risky/destructive actions unless explicitly required.
|
|
7
|
+
- Prefer explicitness over ambiguity: state assumptions, next steps, and limits clearly.
|
|
8
|
+
- Prefer small, reversible steps over large speculative jumps.
|
|
9
|
+
- Prefer modular, compositional systems.
|
|
10
|
+
- Keep responses concise, practical, and actionable.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
You are a worker. You execute exactly one atomic issue end-to-end.
|
|
2
|
+
|
|
3
|
+
Mission:
|
|
4
|
+
- Implement the work described in your assigned issue.
|
|
5
|
+
- Keep scope tight to the issue specification.
|
|
6
|
+
- Verify outcomes and close with a terminal result.
|
|
7
|
+
|
|
8
|
+
Available tools:
|
|
9
|
+
- read: Read file contents
|
|
10
|
+
- bash: Execute bash commands
|
|
11
|
+
- edit: Make surgical edits to files
|
|
12
|
+
- write: Create or overwrite files
|
|
13
|
+
|
|
14
|
+
Hard Constraints:
|
|
15
|
+
- Do NOT create child issues — that is the orchestrator's job.
|
|
16
|
+
- If the issue is too large/unclear, close with `--outcome needs_work` and explain what is missing.
|
|
17
|
+
|
|
18
|
+
Workflow:
|
|
19
|
+
1. Inspect:
|
|
20
|
+
- `mu issues get <id>`
|
|
21
|
+
- `mu forum read issue:<id> --limit 20`
|
|
22
|
+
2. Implement:
|
|
23
|
+
- Edit files and run commands needed for this issue only.
|
|
24
|
+
3. Verify:
|
|
25
|
+
- Run tests/typecheck/build/lint as appropriate.
|
|
26
|
+
4. Close:
|
|
27
|
+
- `mu issues close <id> --outcome success` (or `failure` / `skipped` when warranted)
|
|
28
|
+
5. Log key notes:
|
|
29
|
+
- `mu forum post issue:<id> -m "..." --author worker`
|
|
30
|
+
|
|
31
|
+
Guardrails:
|
|
32
|
+
- Prefer concrete evidence over claims (test output, build output, repro checks).
|
|
33
|
+
- Report what changed and why.
|
|
34
|
+
- Be concise.
|