@femtomc/mu-agent 26.2.74 → 26.2.76

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.
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EACN,WAAW,EAOX,qBAAqB,EAErB,eAAe,EACf,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAI5C,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,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,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA4BpD;AAGD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC3B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,WAAW,EACxB,kBAAkB,CAAC,EAAE,MAAM,GACzB,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CA6BxB;AAED;;;;GAIG;AACH,qBAAa,UAAW,YAAW,aAAa;IACzC,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;CAoGhD;AAGD,MAAM,MAAM,0BAA0B,GAAG;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,0BAA0B,GAAG,qBAAqB,CA6B9F"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EACN,WAAW,EAOX,qBAAqB,EAGrB,eAAe,EACf,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAI5C,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,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,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA4BpD;AAGD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC3B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,WAAW,EACxB,kBAAkB,CAAC,EAAE,MAAM,GACzB,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CA6BxB;AAED;;;;GAIG;AACH,qBAAa,UAAW,YAAW,aAAa;IACzC,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;CAoGhD;AAGD,MAAM,MAAM,0BAA0B,GAAG;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,0BAA0B,GAAG,qBAAqB,CA+C9F"}
package/dist/backend.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { mkdir, open } from "node:fs/promises";
3
3
  import { basename, dirname, join } from "node:path";
4
+ import { findRepoRoot, getMuHomeDir, getStorePaths } from "@femtomc/mu-core/node";
4
5
  import { getModels, getProviders } from "@mariozechner/pi-ai";
5
- import { AuthStorage, createAgentSession, createBashTool, createEditTool, createReadTool, createWriteTool, DefaultResourceLoader, SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent";
6
+ import { AuthStorage, createAgentSession, createBashTool, createEditTool, createReadTool, createWriteTool, DefaultResourceLoader, getAgentDir, SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent";
6
7
  import { orchestratorToolExtensionPaths, workerToolExtensionPaths } from "./extensions/index.js";
7
8
  import { MU_DEFAULT_THEME_NAME, MU_DEFAULT_THEME_PATH } from "./ui_defaults.js";
8
9
  export function streamHasError(line) {
@@ -159,25 +160,42 @@ export class SdkBackend {
159
160
  }
160
161
  }
161
162
  export function createMuResourceLoader(opts) {
162
- const skillPaths = new Set();
163
+ const repoRoot = findRepoRoot(opts.cwd);
164
+ const storePaths = getStorePaths(repoRoot);
165
+ const piAgentDir = opts.agentDir ?? getAgentDir();
166
+ const skillPaths = [];
167
+ const seenSkillPaths = new Set();
168
+ const addSkillPath = (path, requireExists) => {
169
+ if (requireExists && !existsSync(path)) {
170
+ return;
171
+ }
172
+ if (seenSkillPaths.has(path)) {
173
+ return;
174
+ }
175
+ seenSkillPaths.add(path);
176
+ skillPaths.push(path);
177
+ };
178
+ // Preference order (first match wins on skill-name collisions):
179
+ // mu workspace -> mu global -> repo top-level -> explicit additions -> pi project -> pi global.
180
+ addSkillPath(join(storePaths.storeDir, "skills"), true);
181
+ addSkillPath(join(getMuHomeDir(), "skills"), true);
182
+ addSkillPath(join(repoRoot, "skills"), true);
163
183
  for (const p of opts.additionalSkillPaths ?? []) {
164
- skillPaths.add(p);
184
+ addSkillPath(p, false);
165
185
  }
186
+ addSkillPath(join(repoRoot, ".pi", "skills"), true);
187
+ addSkillPath(join(piAgentDir, "skills"), true);
166
188
  const themePaths = new Set([MU_DEFAULT_THEME_PATH]);
167
189
  for (const p of opts.additionalThemePaths ?? []) {
168
190
  themePaths.add(p);
169
191
  }
170
- // If a repo has a top-level `skills/` dir (like workshop/), load it.
171
- const repoSkills = join(opts.cwd, "skills");
172
- if (existsSync(repoSkills)) {
173
- skillPaths.add(repoSkills);
174
- }
175
192
  return new DefaultResourceLoader({
176
193
  cwd: opts.cwd,
177
194
  agentDir: opts.agentDir,
178
195
  settingsManager: opts.settingsManager ?? SettingsManager.inMemory({ theme: MU_DEFAULT_THEME_NAME, quietStartup: true }),
179
196
  additionalExtensionPaths: opts.additionalExtensionPaths,
180
- additionalSkillPaths: [...skillPaths],
197
+ noSkills: true,
198
+ additionalSkillPaths: skillPaths,
181
199
  additionalThemePaths: [...themePaths],
182
200
  systemPromptOverride: (_base) => opts.systemPrompt,
183
201
  agentsFilesOverride: (base) => ({
@@ -1 +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,QAAqC,CAAC;AAOtE,eAAO,MAAM,2BAA2B,QAAkE,CAAC;AAC3G,eAAO,MAAM,uBAAuB,QAA8D,CAAC;AACnG,eAAO,MAAM,qBAAqB,QAA4D,CAAC;AAC/F,eAAO,MAAM,8BAA8B,QAAqE,CAAC"}
1
+ {"version":3,"file":"default_prompts.d.ts","sourceRoot":"","sources":["../src/default_prompts.ts"],"names":[],"mappings":"AAWA;;;;;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,QAAqC,CAAC;AAOtE,eAAO,MAAM,2BAA2B,QAAkE,CAAC;AAC3G,eAAO,MAAM,uBAAuB,QAA8D,CAAC;AACnG,eAAO,MAAM,qBAAqB,QAA4D,CAAC;AAC/F,eAAO,MAAM,8BAA8B,QAE1C,CAAC"}
@@ -2,6 +2,7 @@ import { readFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { splitFrontmatter } from "./prompt.js";
5
+ import { appendMuDocumentationSection } from "./self_documentation.js";
5
6
  function bundledPromptPath(name) {
6
7
  const here = dirname(fileURLToPath(import.meta.url));
7
8
  return join(here, "..", "prompts", name);
@@ -38,4 +39,4 @@ const BASE_OPERATOR_SYSTEM_PROMPT = loadBundledPrompt("roles/operator.md");
38
39
  export const DEFAULT_ORCHESTRATOR_PROMPT = appendSharedSoul(BASE_ORCHESTRATOR_PROMPT, DEFAULT_SOUL_PROMPT);
39
40
  export const DEFAULT_REVIEWER_PROMPT = appendSharedSoul(BASE_REVIEWER_PROMPT, DEFAULT_SOUL_PROMPT);
40
41
  export const DEFAULT_WORKER_PROMPT = appendSharedSoul(BASE_WORKER_PROMPT, DEFAULT_SOUL_PROMPT);
41
- export const DEFAULT_OPERATOR_SYSTEM_PROMPT = appendSharedSoul(BASE_OPERATOR_SYSTEM_PROMPT, DEFAULT_SOUL_PROMPT);
42
+ export const DEFAULT_OPERATOR_SYSTEM_PROMPT = appendMuDocumentationSection(appendSharedSoul(BASE_OPERATOR_SYSTEM_PROMPT, DEFAULT_SOUL_PROMPT));
@@ -19,7 +19,7 @@ async function fetchTail(n) {
19
19
  if (!muServerUrl())
20
20
  return [];
21
21
  try {
22
- return await fetchMuJson(`/api/events/tail?n=${n}`, { timeoutMs: 6_000 });
22
+ return await fetchMuJson(`/api/control-plane/events/tail?n=${n}`, { timeoutMs: 6_000 });
23
23
  }
24
24
  catch {
25
25
  return [];
@@ -42,25 +42,25 @@ export async function fetchMuJson(path, opts = {}) {
42
42
  function ensureGenerationScopedStatus(status) {
43
43
  const controlPlane = status.control_plane;
44
44
  if (!controlPlane || typeof controlPlane !== "object") {
45
- throw new Error("mu server /api/status missing control_plane payload (expected generation-scoped contract)");
45
+ throw new Error("mu server /api/control-plane/status missing control_plane payload (expected generation-scoped contract)");
46
46
  }
47
47
  const controlPlaneRecord = controlPlane;
48
48
  if (!("generation" in controlPlaneRecord) || !controlPlaneRecord.generation) {
49
- throw new Error("mu server /api/status missing control_plane.generation (expected generation-scoped contract)");
49
+ throw new Error("mu server /api/control-plane/status missing control_plane.generation (expected generation-scoped contract)");
50
50
  }
51
51
  if (!("observability" in controlPlaneRecord) || !controlPlaneRecord.observability) {
52
- throw new Error("mu server /api/status missing control_plane.observability (expected generation-scoped contract)");
52
+ throw new Error("mu server /api/control-plane/status missing control_plane.observability (expected generation-scoped contract)");
53
53
  }
54
54
  const observability = controlPlaneRecord.observability;
55
55
  if (typeof observability !== "object" ||
56
56
  observability == null ||
57
57
  !("counters" in observability) ||
58
58
  !observability.counters) {
59
- throw new Error("mu server /api/status missing control_plane.observability.counters (expected generation-scoped contract)");
59
+ throw new Error("mu server /api/control-plane/status missing control_plane.observability.counters (expected generation-scoped contract)");
60
60
  }
61
61
  return status;
62
62
  }
63
63
  export async function fetchMuStatus(timeoutMs) {
64
- const status = await fetchMuJson("/api/status", { timeoutMs });
64
+ const status = await fetchMuJson("/api/control-plane/status", { timeoutMs });
65
65
  return ensureGenerationScopedStatus(status);
66
66
  }
package/dist/index.d.ts CHANGED
@@ -6,4 +6,5 @@ export * from "./operator.js";
6
6
  export * from "./mu_roles.js";
7
7
  export * from "./prompt.js";
8
8
  export * from "./session_factory.js";
9
+ export * from "./session_turn.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,OAAO,EACN,8BAA8B,EAC9B,2BAA2B,EAC3B,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,OAAO,EACN,8BAA8B,EAC9B,2BAA2B,EAC3B,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -6,3 +6,4 @@ export * from "./operator.js";
6
6
  export * from "./mu_roles.js";
7
7
  export * from "./prompt.js";
8
8
  export * from "./session_factory.js";
9
+ export * from "./session_turn.js";
@@ -48,6 +48,23 @@ export declare const OperatorApprovedCommandSchema: z.ZodDiscriminatedUnion<[z.Z
48
48
  kind: z.ZodLiteral<"reload">;
49
49
  }, z.core.$strip>, z.ZodObject<{
50
50
  kind: z.ZodLiteral<"update">;
51
+ }, z.core.$strip>, z.ZodObject<{
52
+ kind: z.ZodLiteral<"operator_config_get">;
53
+ }, z.core.$strip>, z.ZodObject<{
54
+ kind: z.ZodLiteral<"operator_model_list">;
55
+ provider: z.ZodOptional<z.ZodString>;
56
+ }, z.core.$strip>, z.ZodObject<{
57
+ kind: z.ZodLiteral<"operator_thinking_list">;
58
+ provider: z.ZodOptional<z.ZodString>;
59
+ model: z.ZodOptional<z.ZodString>;
60
+ }, z.core.$strip>, z.ZodObject<{
61
+ kind: z.ZodLiteral<"operator_model_set">;
62
+ provider: z.ZodString;
63
+ model: z.ZodString;
64
+ thinking: z.ZodOptional<z.ZodString>;
65
+ }, z.core.$strip>, z.ZodObject<{
66
+ kind: z.ZodLiteral<"operator_thinking_set">;
67
+ thinking: z.ZodString;
51
68
  }, z.core.$strip>, z.ZodObject<{
52
69
  kind: z.ZodLiteral<"run_start">;
53
70
  prompt: z.ZodString;
@@ -88,6 +105,23 @@ export declare const OperatorBackendTurnResultSchema: z.ZodDiscriminatedUnion<[z
88
105
  kind: z.ZodLiteral<"reload">;
89
106
  }, z.core.$strip>, z.ZodObject<{
90
107
  kind: z.ZodLiteral<"update">;
108
+ }, z.core.$strip>, z.ZodObject<{
109
+ kind: z.ZodLiteral<"operator_config_get">;
110
+ }, z.core.$strip>, z.ZodObject<{
111
+ kind: z.ZodLiteral<"operator_model_list">;
112
+ provider: z.ZodOptional<z.ZodString>;
113
+ }, z.core.$strip>, z.ZodObject<{
114
+ kind: z.ZodLiteral<"operator_thinking_list">;
115
+ provider: z.ZodOptional<z.ZodString>;
116
+ model: z.ZodOptional<z.ZodString>;
117
+ }, z.core.$strip>, z.ZodObject<{
118
+ kind: z.ZodLiteral<"operator_model_set">;
119
+ provider: z.ZodString;
120
+ model: z.ZodString;
121
+ thinking: z.ZodOptional<z.ZodString>;
122
+ }, z.core.$strip>, z.ZodObject<{
123
+ kind: z.ZodLiteral<"operator_thinking_set">;
124
+ thinking: z.ZodString;
91
125
  }, z.core.$strip>, z.ZodObject<{
92
126
  kind: z.ZodLiteral<"run_start">;
93
127
  prompt: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"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"}
package/dist/operator.js CHANGED
@@ -1,4 +1,4 @@
1
- import { appendJsonl, readJsonl } from "@femtomc/mu-core/node";
1
+ import { appendJsonl, getStorePaths, readJsonl } from "@femtomc/mu-core/node";
2
2
  import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
3
  import { dirname, join } from "node:path";
4
4
  import { z } from "zod";
@@ -32,6 +32,26 @@ export const OperatorApprovedCommandSchema = z.discriminatedUnion("kind", [
32
32
  }),
33
33
  z.object({ kind: z.literal("reload") }),
34
34
  z.object({ kind: z.literal("update") }),
35
+ z.object({ kind: z.literal("operator_config_get") }),
36
+ z.object({
37
+ kind: z.literal("operator_model_list"),
38
+ provider: z.string().trim().min(1).optional(),
39
+ }),
40
+ z.object({
41
+ kind: z.literal("operator_thinking_list"),
42
+ provider: z.string().trim().min(1).optional(),
43
+ model: z.string().trim().min(1).optional(),
44
+ }),
45
+ z.object({
46
+ kind: z.literal("operator_model_set"),
47
+ provider: z.string().trim().min(1),
48
+ model: z.string().trim().min(1),
49
+ thinking: z.string().trim().min(1).optional(),
50
+ }),
51
+ z.object({
52
+ kind: z.literal("operator_thinking_set"),
53
+ thinking: z.string().trim().min(1),
54
+ }),
35
55
  z.object({
36
56
  kind: z.literal("run_start"),
37
57
  prompt: z.string().trim().min(1),
@@ -135,6 +155,43 @@ export class ApprovedCommandBroker {
135
155
  args = [];
136
156
  break;
137
157
  }
158
+ case "operator_config_get": {
159
+ commandKey = "operator config get";
160
+ args = [];
161
+ break;
162
+ }
163
+ case "operator_model_list": {
164
+ commandKey = "operator model list";
165
+ args = [];
166
+ if (opts.proposal.provider) {
167
+ args.push(normalizeArg(opts.proposal.provider));
168
+ }
169
+ break;
170
+ }
171
+ case "operator_thinking_list": {
172
+ commandKey = "operator thinking list";
173
+ args = [];
174
+ if (opts.proposal.provider) {
175
+ args.push(normalizeArg(opts.proposal.provider));
176
+ }
177
+ if (opts.proposal.model) {
178
+ args.push(normalizeArg(opts.proposal.model));
179
+ }
180
+ break;
181
+ }
182
+ case "operator_model_set": {
183
+ commandKey = "operator model set";
184
+ args = [normalizeArg(opts.proposal.provider), normalizeArg(opts.proposal.model)];
185
+ if (opts.proposal.thinking) {
186
+ args.push(normalizeArg(opts.proposal.thinking));
187
+ }
188
+ break;
189
+ }
190
+ case "operator_thinking_set": {
191
+ commandKey = "operator thinking set";
192
+ args = [normalizeArg(opts.proposal.thinking)];
193
+ break;
194
+ }
138
195
  case "run_start": {
139
196
  if (!this.#runTriggersEnabled) {
140
197
  return { kind: "reject", reason: "operator_action_disallowed", details: "run triggers disabled" };
@@ -216,7 +273,7 @@ function stringList(value) {
216
273
  return out;
217
274
  }
218
275
  function sessionFlashPath(repoRoot) {
219
- return join(repoRoot, ".mu", "control-plane", "session_flash.jsonl");
276
+ return join(getStorePaths(repoRoot).storeDir, "control-plane", "session_flash.jsonl");
220
277
  }
221
278
  async function loadPendingSessionFlashes(opts) {
222
279
  const rows = await readJsonl(sessionFlashPath(opts.repoRoot));
@@ -661,7 +718,8 @@ export class PiMessagingOperatorBackend {
661
718
  this.#auditTurns = opts.auditTurns ?? true;
662
719
  this.#persistSessions = opts.persistSessions ?? true;
663
720
  this.#sessionDirForRepoRoot =
664
- opts.sessionDirForRepoRoot ?? ((repoRoot) => join(repoRoot, ".mu", "control-plane", "operator-sessions"));
721
+ opts.sessionDirForRepoRoot ??
722
+ ((repoRoot) => join(getStorePaths(repoRoot).storeDir, "control-plane", "operator-sessions"));
665
723
  // Operator turns can emit structured command proposals captured from tool events.
666
724
  }
667
725
  #disposeSession(sessionId) {
@@ -766,7 +824,7 @@ export class PiMessagingOperatorBackend {
766
824
  command: opts.command ?? null,
767
825
  };
768
826
  try {
769
- const path = join(input.inbound.repo_root, ".mu", "control-plane", "operator_turns.jsonl");
827
+ const path = join(getStorePaths(input.inbound.repo_root).storeDir, "control-plane", "operator_turns.jsonl");
770
828
  await appendJsonl(path, entry);
771
829
  }
772
830
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAyCjD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA6BjF;AAYD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAW1G;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAItE;AAMD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwCxE;AAED,wBAAsB,oBAAoB,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,GAAG,MAAM,CAAC,EAC3C,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9B,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAK9E"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAyCjD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA6BjF;AAYD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAW1G;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAItE;AAMD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwCxE;AAED,wBAAsB,oBAAoB,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,GAAG,MAAM,CAAC,EAC3C,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9B,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAK9E"}
package/dist/prompt.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { getStorePaths } from "@femtomc/mu-core/node";
1
2
  import { readdir } from "node:fs/promises";
2
3
  import { isAbsolute, join, relative } from "node:path";
3
4
  function stripQuotes(s) {
@@ -96,7 +97,7 @@ function toPosixPath(path) {
96
97
  return path.replaceAll("\\", "/");
97
98
  }
98
99
  export async function buildRoleCatalog(repoRoot) {
99
- const rolesDir = join(repoRoot, ".mu", "roles");
100
+ const rolesDir = join(getStorePaths(repoRoot).storeDir, "roles");
100
101
  let entries;
101
102
  try {
102
103
  entries = await readdir(rolesDir);
@@ -0,0 +1,7 @@
1
+ export type MuDocumentation = {
2
+ readmePath?: string;
3
+ docsPath?: string;
4
+ };
5
+ export declare function resolveMuDocumentation(): MuDocumentation;
6
+ export declare function appendMuDocumentationSection(basePrompt: string): string;
7
+ //# sourceMappingURL=self_documentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self_documentation.d.ts","sourceRoot":"","sources":["../src/self_documentation.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,eAAe,GAAG;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,sBAAsB,IAAI,eAAe,CA2BxD;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAiBvE"}
@@ -0,0 +1,67 @@
1
+ import { existsSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const require = createRequire(import.meta.url);
6
+ function findPackageRoot(startDir) {
7
+ let dir = resolve(startDir);
8
+ while (true) {
9
+ if (existsSync(join(dir, "package.json"))) {
10
+ return dir;
11
+ }
12
+ const parent = dirname(dir);
13
+ if (parent === dir) {
14
+ return resolve(startDir);
15
+ }
16
+ dir = parent;
17
+ }
18
+ }
19
+ function firstExistingPath(candidates) {
20
+ for (const candidate of candidates) {
21
+ if (existsSync(candidate)) {
22
+ return candidate;
23
+ }
24
+ }
25
+ return undefined;
26
+ }
27
+ export function resolveMuDocumentation() {
28
+ const thisModuleDir = dirname(fileURLToPath(import.meta.url));
29
+ const agentPackageRoot = findPackageRoot(thisModuleDir);
30
+ let muPackageRoot;
31
+ try {
32
+ const muEntry = require.resolve("@femtomc/mu");
33
+ muPackageRoot = findPackageRoot(dirname(muEntry));
34
+ }
35
+ catch {
36
+ muPackageRoot = undefined;
37
+ }
38
+ const candidateRoots = [muPackageRoot, agentPackageRoot].filter((v) => Boolean(v));
39
+ const readmeCandidates = [];
40
+ const docsCandidates = [];
41
+ for (const root of candidateRoots) {
42
+ readmeCandidates.push(resolve(root, "..", "..", "README.md"));
43
+ readmeCandidates.push(join(root, "README.md"));
44
+ docsCandidates.push(resolve(root, "..", "..", "docs"));
45
+ docsCandidates.push(join(root, "docs"));
46
+ }
47
+ return {
48
+ readmePath: firstExistingPath(readmeCandidates),
49
+ docsPath: firstExistingPath(docsCandidates),
50
+ };
51
+ }
52
+ export function appendMuDocumentationSection(basePrompt) {
53
+ const trimmed = basePrompt.trim();
54
+ const { readmePath, docsPath } = resolveMuDocumentation();
55
+ const lines = ["Mu documentation (for mu feature/configuration/setup questions):"];
56
+ if (readmePath) {
57
+ lines.push(`- Main documentation: ${readmePath}`);
58
+ }
59
+ if (docsPath) {
60
+ lines.push(`- Additional docs: ${docsPath}`);
61
+ }
62
+ if (!readmePath && !docsPath) {
63
+ lines.push("- Documentation path unavailable at runtime; use `mu --help` and package README files.");
64
+ }
65
+ lines.push("- Read these when users ask about mu capabilities, adapters, or operational setup.");
66
+ return `${trimmed}\n\n${lines.join("\n")}`;
67
+ }
@@ -0,0 +1,37 @@
1
+ import { type CreateMuSessionOpts, type MuSession } from "./session_factory.js";
2
+ export type SessionTurnRequest = {
3
+ session_id: string;
4
+ session_kind: string | null;
5
+ body: string;
6
+ source: string | null;
7
+ provider: string | null;
8
+ model: string | null;
9
+ thinking: string | null;
10
+ session_file: string | null;
11
+ session_dir: string | null;
12
+ extension_profile: string | null;
13
+ };
14
+ export type SessionTurnResult = {
15
+ session_id: string;
16
+ session_kind: string | null;
17
+ session_file: string;
18
+ context_entry_id: string | null;
19
+ reply: string;
20
+ source: string | null;
21
+ completed_at_ms: number;
22
+ };
23
+ export declare class SessionTurnError extends Error {
24
+ readonly status: number;
25
+ constructor(status: number, message: string);
26
+ }
27
+ export declare function parseSessionTurnRequest(body: Record<string, unknown>): {
28
+ request: SessionTurnRequest | null;
29
+ error: string | null;
30
+ };
31
+ export declare function executeSessionTurn(opts: {
32
+ repoRoot: string;
33
+ request: SessionTurnRequest;
34
+ sessionFactory?: (opts: CreateMuSessionOpts) => Promise<MuSession>;
35
+ nowMs?: () => number;
36
+ }): Promise<SessionTurnResult>;
37
+ //# sourceMappingURL=session_turn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session_turn.d.ts","sourceRoot":"","sources":["../src/session_turn.ts"],"names":[],"mappings":"AAcA,OAAO,EAAmB,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjG,MAAM,MAAM,kBAAkB,GAAG;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEL,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAIlD;AAoSD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACvE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,CA+BA;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+F7B"}
@@ -0,0 +1,392 @@
1
+ import { getStorePaths } from "@femtomc/mu-core/node";
2
+ import { readdir, readFile, stat } from "node:fs/promises";
3
+ import { dirname, isAbsolute, join, resolve } from "node:path";
4
+ import { DEFAULT_OPERATOR_SYSTEM_PROMPT, DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_REVIEWER_PROMPT, DEFAULT_WORKER_PROMPT, } from "./default_prompts.js";
5
+ import { operatorExtensionPaths, orchestratorToolExtensionPaths, workerToolExtensionPaths, } from "./extensions/index.js";
6
+ import { createMuSession } from "./session_factory.js";
7
+ export class SessionTurnError extends Error {
8
+ status;
9
+ constructor(status, message) {
10
+ super(message);
11
+ this.status = status;
12
+ }
13
+ }
14
+ function nonEmptyString(value) {
15
+ if (typeof value !== "string") {
16
+ return null;
17
+ }
18
+ const trimmed = value.trim();
19
+ return trimmed.length > 0 ? trimmed : null;
20
+ }
21
+ function asRecord(value) {
22
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
23
+ return null;
24
+ }
25
+ return value;
26
+ }
27
+ function normalizeSessionKind(value) {
28
+ if (!value) {
29
+ return null;
30
+ }
31
+ const normalized = value.trim().toLowerCase().replaceAll("-", "_");
32
+ if (normalized === "cpoperator" || normalized === "control_plane_operator") {
33
+ return "cp_operator";
34
+ }
35
+ return normalized;
36
+ }
37
+ function normalizeExtensionProfile(value) {
38
+ if (!value) {
39
+ return null;
40
+ }
41
+ const normalized = value.trim().toLowerCase();
42
+ if (normalized === "operator" ||
43
+ normalized === "worker" ||
44
+ normalized === "orchestrator" ||
45
+ normalized === "reviewer" ||
46
+ normalized === "none") {
47
+ return normalized;
48
+ }
49
+ return null;
50
+ }
51
+ function sessionFileStem(sessionId) {
52
+ const normalized = sessionId.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
53
+ const compact = normalized.replace(/-+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
54
+ return compact.length > 0 ? compact : "session";
55
+ }
56
+ function resolveRepoPath(repoRoot, candidate) {
57
+ return isAbsolute(candidate) ? resolve(candidate) : resolve(repoRoot, candidate);
58
+ }
59
+ function defaultSessionDirForKind(repoRoot, sessionKind) {
60
+ const storeDir = getStorePaths(repoRoot).storeDir;
61
+ switch (sessionKind) {
62
+ case "operator":
63
+ return join(storeDir, "operator", "sessions");
64
+ case "cp_operator":
65
+ return join(storeDir, "control-plane", "operator-sessions");
66
+ case "orchestrator":
67
+ return join(storeDir, "orchestrator", "sessions");
68
+ case "worker":
69
+ return join(storeDir, "worker", "sessions");
70
+ case "reviewer":
71
+ return join(storeDir, "reviewer", "sessions");
72
+ default:
73
+ return join(storeDir, "control-plane", "operator-sessions");
74
+ }
75
+ }
76
+ async function pathExists(path) {
77
+ try {
78
+ await stat(path);
79
+ return true;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ async function directoryExists(path) {
86
+ try {
87
+ const info = await stat(path);
88
+ return info.isDirectory();
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ }
94
+ async function readSessionHeaderId(sessionFile) {
95
+ let raw;
96
+ try {
97
+ raw = await readFile(sessionFile, "utf8");
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ const firstLine = raw
103
+ .split("\n")
104
+ .map((line) => line.trim())
105
+ .find((line) => line.length > 0);
106
+ if (!firstLine) {
107
+ return null;
108
+ }
109
+ try {
110
+ const parsed = JSON.parse(firstLine);
111
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
112
+ return null;
113
+ }
114
+ const header = parsed;
115
+ if (header.type !== "session") {
116
+ return null;
117
+ }
118
+ return nonEmptyString(header.id);
119
+ }
120
+ catch {
121
+ return null;
122
+ }
123
+ }
124
+ async function resolveSessionFileById(opts) {
125
+ const direct = join(opts.sessionDir, `${sessionFileStem(opts.sessionId)}.jsonl`);
126
+ if (await pathExists(direct)) {
127
+ const headerId = await readSessionHeaderId(direct);
128
+ if (headerId === opts.sessionId) {
129
+ return direct;
130
+ }
131
+ }
132
+ const entries = await readdir(opts.sessionDir, { withFileTypes: true });
133
+ for (const entry of entries) {
134
+ if (!entry.isFile() || !entry.name.endsWith(".jsonl")) {
135
+ continue;
136
+ }
137
+ const filePath = join(opts.sessionDir, entry.name);
138
+ if (filePath === direct) {
139
+ continue;
140
+ }
141
+ const headerId = await readSessionHeaderId(filePath);
142
+ if (headerId === opts.sessionId) {
143
+ return filePath;
144
+ }
145
+ }
146
+ return null;
147
+ }
148
+ function extensionPathsForTurn(opts) {
149
+ if (opts.extensionProfile === "none") {
150
+ return [];
151
+ }
152
+ if (opts.extensionProfile === "operator") {
153
+ return [...operatorExtensionPaths];
154
+ }
155
+ if (opts.extensionProfile === "orchestrator") {
156
+ return [...orchestratorToolExtensionPaths];
157
+ }
158
+ if (opts.extensionProfile === "worker" || opts.extensionProfile === "reviewer") {
159
+ return [...workerToolExtensionPaths];
160
+ }
161
+ if (opts.sessionKind === "operator" || opts.sessionKind === "cp_operator") {
162
+ return [...operatorExtensionPaths];
163
+ }
164
+ if (opts.sessionKind === "orchestrator") {
165
+ return [...orchestratorToolExtensionPaths];
166
+ }
167
+ if (opts.sessionKind === "worker" || opts.sessionKind === "reviewer") {
168
+ return [...workerToolExtensionPaths];
169
+ }
170
+ return [...operatorExtensionPaths];
171
+ }
172
+ function systemPromptForTurn(opts) {
173
+ const role = opts.extensionProfile ?? opts.sessionKind;
174
+ if (role === "operator" || role === "cp_operator") {
175
+ return DEFAULT_OPERATOR_SYSTEM_PROMPT;
176
+ }
177
+ if (role === "orchestrator") {
178
+ return DEFAULT_ORCHESTRATOR_PROMPT;
179
+ }
180
+ if (role === "reviewer") {
181
+ return DEFAULT_REVIEWER_PROMPT;
182
+ }
183
+ if (role === "worker") {
184
+ return DEFAULT_WORKER_PROMPT;
185
+ }
186
+ return undefined;
187
+ }
188
+ function extractAssistantText(message) {
189
+ if (!message || typeof message !== "object") {
190
+ return "";
191
+ }
192
+ const record = message;
193
+ if (typeof record.text === "string") {
194
+ return record.text;
195
+ }
196
+ if (typeof record.content === "string") {
197
+ return record.content;
198
+ }
199
+ if (Array.isArray(record.content)) {
200
+ const parts = [];
201
+ for (const item of record.content) {
202
+ if (typeof item === "string") {
203
+ if (item.trim().length > 0) {
204
+ parts.push(item);
205
+ }
206
+ continue;
207
+ }
208
+ if (!item || typeof item !== "object") {
209
+ continue;
210
+ }
211
+ const text = nonEmptyString(item.text);
212
+ if (text) {
213
+ parts.push(text);
214
+ }
215
+ }
216
+ return parts.join("\n");
217
+ }
218
+ return "";
219
+ }
220
+ function safeLeafId(session) {
221
+ const manager = session.sessionManager;
222
+ if (!manager || typeof manager.getLeafId !== "function") {
223
+ return null;
224
+ }
225
+ const value = manager.getLeafId();
226
+ return typeof value === "string" && value.trim().length > 0 ? value : null;
227
+ }
228
+ function safeSessionId(session) {
229
+ const value = session.sessionId;
230
+ return typeof value === "string" && value.trim().length > 0 ? value : null;
231
+ }
232
+ function safeSessionFile(session) {
233
+ const value = session.sessionFile;
234
+ return typeof value === "string" && value.trim().length > 0 ? value : null;
235
+ }
236
+ async function resolveSessionTarget(opts) {
237
+ const sessionDir = opts.request.session_dir
238
+ ? resolveRepoPath(opts.repoRoot, opts.request.session_dir)
239
+ : defaultSessionDirForKind(opts.repoRoot, opts.normalizedSessionKind);
240
+ if (opts.request.session_file) {
241
+ const sessionFile = resolveRepoPath(opts.repoRoot, opts.request.session_file);
242
+ if (!(await pathExists(sessionFile))) {
243
+ throw new SessionTurnError(404, `session_file not found: ${sessionFile}`);
244
+ }
245
+ const headerId = await readSessionHeaderId(sessionFile);
246
+ if (!headerId) {
247
+ throw new SessionTurnError(400, `session_file is missing a valid session header: ${sessionFile}`);
248
+ }
249
+ if (headerId !== opts.request.session_id) {
250
+ throw new SessionTurnError(409, `session_file header id mismatch (expected ${opts.request.session_id}, found ${headerId})`);
251
+ }
252
+ return {
253
+ sessionFile,
254
+ sessionDir: opts.request.session_dir ? sessionDir : dirname(sessionFile),
255
+ };
256
+ }
257
+ if (!(await directoryExists(sessionDir))) {
258
+ throw new SessionTurnError(404, `session directory not found: ${sessionDir}`);
259
+ }
260
+ const sessionFile = await resolveSessionFileById({
261
+ sessionDir,
262
+ sessionId: opts.request.session_id,
263
+ });
264
+ if (!sessionFile) {
265
+ throw new SessionTurnError(404, `session_id not found in ${sessionDir}: ${opts.request.session_id}`);
266
+ }
267
+ return { sessionFile, sessionDir };
268
+ }
269
+ export function parseSessionTurnRequest(body) {
270
+ const sessionId = nonEmptyString(body.session_id);
271
+ if (!sessionId) {
272
+ return { request: null, error: "session_id is required" };
273
+ }
274
+ const messageBody = nonEmptyString(body.body) ?? nonEmptyString(body.message) ?? nonEmptyString(body.prompt);
275
+ if (!messageBody) {
276
+ return { request: null, error: "body (or message/prompt) is required" };
277
+ }
278
+ const extensionProfileRaw = nonEmptyString(body.extension_profile);
279
+ if (extensionProfileRaw && !normalizeExtensionProfile(extensionProfileRaw)) {
280
+ return {
281
+ request: null,
282
+ error: "extension_profile must be one of operator|worker|orchestrator|reviewer|none",
283
+ };
284
+ }
285
+ return {
286
+ request: {
287
+ session_id: sessionId,
288
+ session_kind: nonEmptyString(body.session_kind),
289
+ body: messageBody,
290
+ source: nonEmptyString(body.source),
291
+ provider: nonEmptyString(body.provider),
292
+ model: nonEmptyString(body.model),
293
+ thinking: nonEmptyString(body.thinking),
294
+ session_file: nonEmptyString(body.session_file),
295
+ session_dir: nonEmptyString(body.session_dir),
296
+ extension_profile: extensionProfileRaw,
297
+ },
298
+ error: null,
299
+ };
300
+ }
301
+ export async function executeSessionTurn(opts) {
302
+ const normalizedSessionKind = normalizeSessionKind(opts.request.session_kind);
303
+ const extensionProfile = normalizeExtensionProfile(opts.request.extension_profile);
304
+ const target = await resolveSessionTarget({
305
+ repoRoot: opts.repoRoot,
306
+ request: opts.request,
307
+ normalizedSessionKind,
308
+ });
309
+ const sessionFactory = opts.sessionFactory ?? createMuSession;
310
+ const session = await sessionFactory({
311
+ cwd: opts.repoRoot,
312
+ systemPrompt: systemPromptForTurn({
313
+ sessionKind: normalizedSessionKind,
314
+ extensionProfile,
315
+ }),
316
+ provider: opts.request.provider ?? undefined,
317
+ model: opts.request.model ?? undefined,
318
+ thinking: opts.request.thinking ?? undefined,
319
+ extensionPaths: extensionPathsForTurn({
320
+ sessionKind: normalizedSessionKind,
321
+ extensionProfile,
322
+ }),
323
+ session: {
324
+ mode: "open",
325
+ sessionDir: target.sessionDir,
326
+ sessionFile: target.sessionFile,
327
+ },
328
+ });
329
+ let assistantText = "";
330
+ let contextEntryId = null;
331
+ let resolvedSessionId = null;
332
+ let resolvedSessionFile = null;
333
+ const nowMs = opts.nowMs ?? Date.now;
334
+ try {
335
+ await session.bindExtensions({
336
+ commandContextActions: {
337
+ waitForIdle: () => session.agent.waitForIdle(),
338
+ newSession: async () => ({ cancelled: true }),
339
+ fork: async () => ({ cancelled: true }),
340
+ navigateTree: async () => ({ cancelled: true }),
341
+ switchSession: async () => ({ cancelled: true }),
342
+ reload: async () => { },
343
+ },
344
+ onError: () => { },
345
+ });
346
+ const unsubscribe = session.subscribe((event) => {
347
+ const rec = asRecord(event);
348
+ if (!rec || rec.type !== "message_end") {
349
+ return;
350
+ }
351
+ const message = asRecord(rec.message);
352
+ if (!message || message.role !== "assistant") {
353
+ return;
354
+ }
355
+ const text = extractAssistantText(message);
356
+ if (text.trim().length > 0) {
357
+ assistantText = text;
358
+ }
359
+ });
360
+ try {
361
+ await session.prompt(opts.request.body, { expandPromptTemplates: false });
362
+ await session.agent.waitForIdle();
363
+ }
364
+ finally {
365
+ unsubscribe();
366
+ }
367
+ contextEntryId = safeLeafId(session);
368
+ resolvedSessionId = safeSessionId(session) ?? opts.request.session_id;
369
+ resolvedSessionFile = safeSessionFile(session) ?? target.sessionFile;
370
+ }
371
+ finally {
372
+ try {
373
+ session.dispose();
374
+ }
375
+ catch {
376
+ // Best effort cleanup.
377
+ }
378
+ }
379
+ const reply = assistantText.trim();
380
+ if (reply.length === 0) {
381
+ throw new SessionTurnError(502, "session turn completed without an assistant reply");
382
+ }
383
+ return {
384
+ session_id: resolvedSessionId ?? opts.request.session_id,
385
+ session_kind: normalizedSessionKind,
386
+ session_file: resolvedSessionFile ?? target.sessionFile,
387
+ context_entry_id: contextEntryId,
388
+ reply,
389
+ source: opts.request.source ?? null,
390
+ completed_at_ms: Math.trunc(nowMs()),
391
+ };
392
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@femtomc/mu-agent",
3
- "version": "26.2.74",
3
+ "version": "26.2.76",
4
4
  "description": "Shared agent runtime for mu chat, orchestration roles, and serve extensions.",
5
5
  "keywords": [
6
6
  "mu",
@@ -24,7 +24,7 @@
24
24
  "themes/**"
25
25
  ],
26
26
  "dependencies": {
27
- "@femtomc/mu-core": "26.2.74",
27
+ "@femtomc/mu-core": "26.2.76",
28
28
  "@mariozechner/pi-agent-core": "^0.53.0",
29
29
  "@mariozechner/pi-ai": "^0.53.0",
30
30
  "@mariozechner/pi-coding-agent": "^0.53.0",
@@ -16,6 +16,8 @@ Available tools:
16
16
  CLI-first workflow:
17
17
  - Use `bash` + `mu ...` for issue/forum/run/control-plane state operations.
18
18
  - Prefer `--pretty` (or `--json` + targeted parsing) for clear, auditable output.
19
+ - Use `mu memory search|timeline|stats` as the primary cross-store memory surface.
20
+ - Use `mu memory index status|rebuild` to inspect/refresh local memory index health when needed.
19
21
  - Do not use bespoke query/command wrappers; call the CLI surface directly.
20
22
 
21
23
  Example invocation patterns:
@@ -25,10 +27,16 @@ Example invocation patterns:
25
27
  - `bash("mu runs start \"ship release\" --max-steps 25 --pretty")`
26
28
  - `bash("mu issues close mu-abc123 --outcome success --pretty")`
27
29
  - `bash("mu forum post issue:mu-abc123 -m \"done\" --author operator --pretty")`
30
+ - `bash("mu memory search --query reload --limit 20 --pretty")`
31
+ - `bash("mu memory timeline --issue-id mu-abc123 --order desc --limit 40 --pretty")`
32
+ - `bash("mu memory index status --pretty")`
33
+ - `bash("mu memory index rebuild --sources issues,forum,events --pretty")`
34
+ - `bash("mu control operator set openai-codex gpt-5.3-codex xhigh --pretty")`
35
+ - `bash("mu control operator thinking-set high --pretty")`
28
36
  - `bash("mu control reload --pretty")`
29
37
 
30
38
  Guardrails:
31
- - Never hand-edit `.mu/*.jsonl` for normal lifecycle actions; use `mu` CLI commands.
39
+ - Never hand-edit workspace-store `*.jsonl` files for normal lifecycle actions; use `mu` CLI commands.
32
40
  - Prefer bounded retrieval (`--limit`, scoped filters) before broad scans.
33
41
  - Do NOT pre-fetch status/issues/events/runs at conversation start.
34
42
  - Fetch only what the user request requires.
@@ -25,6 +25,9 @@ Workflow:
25
25
  - `bash("mu issues get <id> --pretty")`
26
26
  - `bash("mu forum read issue:<id> --limit 20 --pretty")`
27
27
  - `bash("mu issues children <id> --pretty")` (or `mu issues list --root <id> --pretty`)
28
+ - `bash("mu memory search --query <keywords> --issue-id <id> --limit 20 --pretty")`
29
+ - `bash("mu memory timeline --issue-id <id> --order desc --limit 40 --pretty")`
30
+ - `bash("mu memory index status --pretty")` (rebuild when missing/stale if broader retrieval is needed)
28
31
  2. Decompose into worker issues:
29
32
  - `bash("mu issues create \"<title>\" --body \"<body>\" --tags \"node:agent,role:worker\" --parent <id> --pretty")`
30
33
  3. Add ordering where needed:
@@ -19,6 +19,8 @@ Workflow:
19
19
  1. Inspect:
20
20
  - `bash("mu issues get <id> --pretty")`
21
21
  - `bash("mu forum read issue:<id> --limit 20 --pretty")`
22
+ - `bash("mu memory search --query <keywords> --issue-id <id> --limit 20 --pretty")`
23
+ - `bash("mu memory timeline --issue-id <id> --order desc --limit 40 --pretty")`
22
24
  2. Verify:
23
25
  - Re-run relevant tests/checks, inspect changed files/logs.
24
26
  3. Decide:
@@ -19,6 +19,9 @@ Workflow:
19
19
  1. Inspect:
20
20
  - `bash("mu issues get <id> --pretty")`
21
21
  - `bash("mu forum read issue:<id> --limit 20 --pretty")`
22
+ - `bash("mu memory search --query <keywords> --issue-id <id> --limit 20 --pretty")`
23
+ - `bash("mu memory timeline --issue-id <id> --order desc --limit 40 --pretty")`
24
+ - `bash("mu memory index status --pretty")` (rebuild when missing/stale if context retrieval quality is poor)
22
25
  2. Implement:
23
26
  - Edit files and run commands needed for this issue only.
24
27
  3. Verify: