@femtomc/mu-agent 26.2.35 → 26.2.37

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 CHANGED
@@ -26,3 +26,55 @@ From repo root (`mu/`):
26
26
  bun run build
27
27
  bun test packages/orchestrator packages/control-plane
28
28
  ```
29
+
30
+ ## Serve-mode extensions (`mu serve`)
31
+
32
+ When `mu serve` starts the interactive assistant, it loads
33
+ `serveExtensionPaths` from `src/extensions/index.ts` (path-based extensions,
34
+ not anonymous inline factories).
35
+
36
+ Current stack:
37
+
38
+ - `brandingExtension` — mu header/footer/widgets
39
+ - `serverToolsExtension` — status + issues/forum/events/control-plane tools
40
+ - `eventLogExtension` — event tail + watch widget
41
+ - `messagingSetupExtension` — adapter diagnostics and setup guidance
42
+
43
+ `mu serve` sets `MU_SERVER_URL` automatically for these extensions.
44
+
45
+ ## Slash commands (operator-facing)
46
+
47
+ - `/mu-status` — concise server status
48
+ - `/mu-control` — active control-plane adapters and webhook routes
49
+ - `/mu-setup` — adapter preflight
50
+ - `/mu-setup plan <adapter>` — actionable wiring plan
51
+ - `/mu-setup apply <adapter>` — guided config apply + control-plane reload
52
+ - `/mu-setup verify [adapter]` — runtime verification for mounted routes
53
+ - `/mu-setup <adapter>` — sends adapter setup brief to mu agent (`--no-agent` prints local guide)
54
+ - `/mu-events [n]` / `/mu-events tail [n]` — event log tail
55
+ - `/mu-events watch on|off` — toggle event watch widget
56
+ - `/mu-brand on|off|toggle` — enable/disable UI branding
57
+
58
+ ## Tools (agent/meta-agent-facing)
59
+
60
+ - `mu_status()`
61
+ - High-level server status.
62
+ - `mu_control_plane({ action })`
63
+ - `action`: `status | adapters | routes`
64
+ - `mu_issues({ action, ... })`
65
+ - `action`: `list | get | ready`
66
+ - `mu_forum({ action, ... })`
67
+ - `action`: `read | post | topics`
68
+ - `mu_events({ action, ... })`
69
+ - `action`: `tail | query`
70
+ - `mu_messaging_setup({ action, adapter?, public_base_url? })`
71
+ - `action`: `check | preflight | guide | plan | apply | verify`
72
+ - `adapter`: `slack | discord | telegram | gmail`
73
+
74
+ ## Messaging setup notes
75
+
76
+ - Runtime setup state comes from `GET /api/config` and `.mu/config.json`.
77
+ - `slack`, `discord`, `telegram` are currently modeled as available adapters.
78
+ - `gmail` is modeled as planned guidance (not mounted by runtime yet).
79
+ - `mu_messaging_setup(action=preflight)` is the quickest health check during
80
+ onboarding.
@@ -0,0 +1,13 @@
1
+ /**
2
+ * mu-branding — Custom serve-mode TUI chrome for mu.
3
+ *
4
+ * Adds:
5
+ * - Custom header + footer
6
+ * - Quick command widget above the editor
7
+ * - Terminal title and working message branding
8
+ * - Lightweight periodic status refresh (open/ready/control-plane)
9
+ */
10
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
11
+ export declare function brandingExtension(pi: ExtensionAPI): void;
12
+ export default brandingExtension;
13
+ //# sourceMappingURL=branding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.d.ts","sourceRoot":"","sources":["../../src/extensions/branding.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,+BAA+B,CAAC;AA+CpF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,YAAY,QA4NjD;AAED,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,253 @@
1
+ /**
2
+ * mu-branding — Custom serve-mode TUI chrome for mu.
3
+ *
4
+ * Adds:
5
+ * - Custom header + footer
6
+ * - Quick command widget above the editor
7
+ * - Terminal title and working message branding
8
+ * - Lightweight periodic status refresh (open/ready/control-plane)
9
+ */
10
+ import { basename } from "node:path";
11
+ import { fetchMuStatus, muServerUrl } from "./shared.js";
12
+ const EMPTY_SNAPSHOT = {
13
+ openCount: 0,
14
+ readyCount: 0,
15
+ controlPlaneActive: false,
16
+ adapters: [],
17
+ error: null,
18
+ };
19
+ const ANSI_RE = /\u001b\[[0-9;]*m/g;
20
+ function visibleWidth(text) {
21
+ return text.replace(ANSI_RE, "").length;
22
+ }
23
+ function truncateToWidth(text, width) {
24
+ if (width <= 0)
25
+ return "";
26
+ if (visibleWidth(text) <= width)
27
+ return text;
28
+ const plain = text.replace(ANSI_RE, "");
29
+ if (width === 1)
30
+ return plain.slice(0, 1);
31
+ return `${plain.slice(0, width - 1)}…`;
32
+ }
33
+ function routesFromStatus(adapters, routes) {
34
+ if (routes && routes.length > 0)
35
+ return routes;
36
+ return adapters.map((name) => ({ name, route: `/webhooks/${name}` }));
37
+ }
38
+ function modelLabelFromContext(ctx) {
39
+ if (!ctx.model)
40
+ return "model:unknown";
41
+ return `${ctx.model.provider}/${ctx.model.id}`;
42
+ }
43
+ function modelLabelFromEventModel(model) {
44
+ return `${model.provider}/${model.id}`;
45
+ }
46
+ export function brandingExtension(pi) {
47
+ let enabled = true;
48
+ let repoName = "mu";
49
+ let currentModel = "model:unknown";
50
+ let snapshot = { ...EMPTY_SNAPSHOT };
51
+ let activeCtx = null;
52
+ let pollTimer = null;
53
+ let footerRequestRender = null;
54
+ function refreshWidget(ctx) {
55
+ if (!ctx.hasUI)
56
+ return;
57
+ ctx.ui.setWidget("mu-quick-actions", (_tui, theme) => ({
58
+ render(width) {
59
+ const cpState = snapshot.error
60
+ ? theme.fg("warning", "cp unavailable")
61
+ : snapshot.controlPlaneActive
62
+ ? theme.fg("success", `cp ${snapshot.adapters.join(",") || "on"}`)
63
+ : theme.fg("muted", "cp off");
64
+ const line1 = `${theme.fg("accent", "μ")}${theme.fg("dim", " quick actions")}: ${theme.fg("muted", "/mu-status /mu-control /mu-setup /mu-events")}`;
65
+ const line2 = `${theme.fg("dim", `open ${snapshot.openCount} · ready ${snapshot.readyCount}`)} · ${cpState}`;
66
+ return [truncateToWidth(line1, width), truncateToWidth(line2, width)];
67
+ },
68
+ invalidate() { },
69
+ }));
70
+ }
71
+ function applyChrome(ctx) {
72
+ if (!ctx.hasUI || !enabled)
73
+ return;
74
+ ctx.ui.setTitle(`mu • ${repoName}`);
75
+ ctx.ui.setWorkingMessage("μ working...");
76
+ ctx.ui.setHeader((_tui, theme) => ({
77
+ render(width) {
78
+ const line1 = `${theme.fg("accent", theme.bold("μ"))} ${theme.bold("mu")} ${theme.fg("muted", "serve console")}`;
79
+ const line2 = theme.fg("dim", `repo: ${repoName}`);
80
+ const line3 = theme.fg("muted", "status via: mu_status · mu_control_plane · mu_messaging_setup");
81
+ return [
82
+ "",
83
+ truncateToWidth(line1, width),
84
+ truncateToWidth(line2, width),
85
+ truncateToWidth(line3, width),
86
+ "",
87
+ ];
88
+ },
89
+ invalidate() { },
90
+ }));
91
+ ctx.ui.setFooter((tui, theme, footerData) => {
92
+ const requestRender = () => tui.requestRender();
93
+ const unsubscribeBranch = footerData.onBranchChange(requestRender);
94
+ footerRequestRender = requestRender;
95
+ return {
96
+ dispose() {
97
+ if (footerRequestRender === requestRender) {
98
+ footerRequestRender = null;
99
+ }
100
+ unsubscribeBranch();
101
+ },
102
+ invalidate() { },
103
+ render(width) {
104
+ const cpLabel = snapshot.error
105
+ ? theme.fg("warning", "cp:unavailable")
106
+ : snapshot.controlPlaneActive
107
+ ? theme.fg("success", `cp:${snapshot.adapters.join(",") || "on"}`)
108
+ : theme.fg("muted", "cp:off");
109
+ const left = [
110
+ theme.fg("accent", "μ"),
111
+ theme.fg("dim", repoName),
112
+ theme.fg("muted", "|"),
113
+ theme.fg("dim", `open ${snapshot.openCount} ready ${snapshot.readyCount}`),
114
+ theme.fg("muted", "|"),
115
+ cpLabel,
116
+ ].join(" ");
117
+ const branch = footerData.getGitBranch();
118
+ const right = theme.fg("dim", branch ? `${currentModel} · branch:${branch}` : currentModel);
119
+ const pad = " ".repeat(Math.max(1, width - visibleWidth(left) - visibleWidth(right)));
120
+ return [truncateToWidth(`${left}${pad}${right}`, width)];
121
+ },
122
+ };
123
+ });
124
+ refreshWidget(ctx);
125
+ }
126
+ function clearChrome(ctx) {
127
+ if (!ctx.hasUI)
128
+ return;
129
+ ctx.ui.setHeader(undefined);
130
+ ctx.ui.setFooter(undefined);
131
+ ctx.ui.setWidget("mu-quick-actions", undefined);
132
+ ctx.ui.setWorkingMessage();
133
+ ctx.ui.setStatus("mu-overview", undefined);
134
+ }
135
+ async function refreshStatus(ctx) {
136
+ if (!ctx.hasUI || !enabled)
137
+ return;
138
+ if (!muServerUrl()) {
139
+ snapshot = {
140
+ ...EMPTY_SNAPSHOT,
141
+ error: "MU_SERVER_URL not set",
142
+ };
143
+ ctx.ui.setStatus("mu-overview", ctx.ui.theme.fg("warning", "μ server unavailable"));
144
+ refreshWidget(ctx);
145
+ footerRequestRender?.();
146
+ return;
147
+ }
148
+ try {
149
+ const status = await fetchMuStatus(4_000);
150
+ const cp = status.control_plane ?? {
151
+ active: false,
152
+ adapters: [],
153
+ routes: [],
154
+ };
155
+ snapshot = {
156
+ openCount: status.open_count,
157
+ readyCount: status.ready_count,
158
+ controlPlaneActive: cp.active,
159
+ adapters: routesFromStatus(cp.adapters, cp.routes).map((entry) => entry.name),
160
+ error: null,
161
+ };
162
+ ctx.ui.setStatus("mu-overview", ctx.ui.theme.fg("dim", `μ open ${snapshot.openCount} · ready ${snapshot.readyCount} · cp ${snapshot.controlPlaneActive ? "on" : "off"}`));
163
+ }
164
+ catch (err) {
165
+ snapshot = {
166
+ ...EMPTY_SNAPSHOT,
167
+ error: err instanceof Error ? err.message : String(err),
168
+ };
169
+ ctx.ui.setStatus("mu-overview", ctx.ui.theme.fg("warning", "μ status refresh failed"));
170
+ }
171
+ refreshWidget(ctx);
172
+ footerRequestRender?.();
173
+ }
174
+ function ensurePolling() {
175
+ if (pollTimer)
176
+ return;
177
+ pollTimer = setInterval(() => {
178
+ if (!activeCtx)
179
+ return;
180
+ void refreshStatus(activeCtx);
181
+ }, 12_000);
182
+ }
183
+ function stopPolling() {
184
+ if (!pollTimer)
185
+ return;
186
+ clearInterval(pollTimer);
187
+ pollTimer = null;
188
+ }
189
+ async function initialize(ctx) {
190
+ activeCtx = ctx;
191
+ repoName = basename(ctx.cwd);
192
+ currentModel = modelLabelFromContext(ctx);
193
+ if (!ctx.hasUI)
194
+ return;
195
+ if (enabled) {
196
+ applyChrome(ctx);
197
+ await refreshStatus(ctx);
198
+ ensurePolling();
199
+ }
200
+ else {
201
+ clearChrome(ctx);
202
+ stopPolling();
203
+ }
204
+ }
205
+ pi.on("session_start", async (_event, ctx) => {
206
+ await initialize(ctx);
207
+ });
208
+ pi.on("session_switch", async (_event, ctx) => {
209
+ await initialize(ctx);
210
+ });
211
+ pi.on("model_select", async (event, ctx) => {
212
+ currentModel = modelLabelFromEventModel(event.model);
213
+ if (!ctx.hasUI || !enabled)
214
+ return;
215
+ ctx.ui.setStatus("mu-model", ctx.ui.theme.fg("dim", currentModel));
216
+ footerRequestRender?.();
217
+ });
218
+ pi.on("session_shutdown", async () => {
219
+ stopPolling();
220
+ footerRequestRender = null;
221
+ activeCtx = null;
222
+ });
223
+ pi.registerCommand("mu-brand", {
224
+ description: "Toggle mu TUI branding (`/mu-brand on|off|toggle`)",
225
+ handler: async (args, ctx) => {
226
+ const mode = args.trim().toLowerCase();
227
+ if (mode === "on") {
228
+ enabled = true;
229
+ }
230
+ else if (mode === "off") {
231
+ enabled = false;
232
+ }
233
+ else {
234
+ enabled = !enabled;
235
+ }
236
+ if (!ctx.hasUI) {
237
+ ctx.ui.notify(`mu branding ${enabled ? "enabled" : "disabled"}.`, "info");
238
+ return;
239
+ }
240
+ if (enabled) {
241
+ applyChrome(ctx);
242
+ await refreshStatus(ctx);
243
+ ensurePolling();
244
+ }
245
+ else {
246
+ clearChrome(ctx);
247
+ stopPolling();
248
+ }
249
+ ctx.ui.notify(`mu branding ${enabled ? "enabled" : "disabled"}.`, "info");
250
+ },
251
+ });
252
+ }
253
+ export default brandingExtension;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * mu-event-log — Event stream helper for mu serve.
3
+ *
4
+ * - Status line with last event type and tail count
5
+ * - Optional watch widget below editor (`/mu-events watch on|off`)
6
+ * - Command for quick tail inspection (`/mu-events [n]` or `/mu-events tail [n]`)
7
+ */
8
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
9
+ export declare function eventLogExtension(pi: ExtensionAPI): void;
10
+ export default eventLogExtension;
11
+ //# sourceMappingURL=event-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-log.d.ts","sourceRoot":"","sources":["../../src/extensions/event-log.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,+BAA+B,CAAC;AAgCpF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,YAAY,QAgHjD;AAED,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * mu-event-log — Event stream helper for mu serve.
3
+ *
4
+ * - Status line with last event type and tail count
5
+ * - Optional watch widget below editor (`/mu-events watch on|off`)
6
+ * - Command for quick tail inspection (`/mu-events [n]` or `/mu-events tail [n]`)
7
+ */
8
+ import { clampInt, fetchMuJson, muServerUrl } from "./shared.js";
9
+ function eventTime(tsMs) {
10
+ return new Date(tsMs).toLocaleTimeString();
11
+ }
12
+ function formatEventLine(event) {
13
+ const ts = eventTime(event.ts_ms);
14
+ const payloadHint = event.issue_id ? ` issue:${event.issue_id}` : "";
15
+ return `${ts} ${event.type} (${event.source})${payloadHint}`;
16
+ }
17
+ async function fetchTail(n) {
18
+ if (!muServerUrl())
19
+ return [];
20
+ try {
21
+ return await fetchMuJson(`/api/events/tail?n=${n}`, { timeoutMs: 6_000 });
22
+ }
23
+ catch {
24
+ return [];
25
+ }
26
+ }
27
+ export function eventLogExtension(pi) {
28
+ let watchEnabled = false;
29
+ let pollTimer = null;
30
+ let activeCtx = null;
31
+ async function refresh(ctx, opts = {}) {
32
+ if (!ctx.hasUI)
33
+ return;
34
+ const tail = clampInt(opts.tail, 8, 1, 50);
35
+ const events = await fetchTail(tail);
36
+ if (events.length === 0) {
37
+ ctx.ui.setStatus("mu-events", ctx.ui.theme.fg("dim", "events: none"));
38
+ if (watchEnabled) {
39
+ ctx.ui.setWidget("mu-events", [ctx.ui.theme.fg("dim", "(no events yet)")], { placement: "belowEditor" });
40
+ }
41
+ return;
42
+ }
43
+ const last = events[events.length - 1];
44
+ ctx.ui.setStatus("mu-events", ctx.ui.theme.fg("dim", `events: ${events.length} · last ${last.type}`));
45
+ if (watchEnabled) {
46
+ const lines = events.slice(-5).map((event) => ` ${formatEventLine(event)}`);
47
+ ctx.ui.setWidget("mu-events", lines, { placement: "belowEditor" });
48
+ }
49
+ }
50
+ function stopPolling() {
51
+ if (!pollTimer)
52
+ return;
53
+ clearInterval(pollTimer);
54
+ pollTimer = null;
55
+ }
56
+ function ensurePolling() {
57
+ if (pollTimer)
58
+ return;
59
+ pollTimer = setInterval(() => {
60
+ if (!activeCtx)
61
+ return;
62
+ void refresh(activeCtx);
63
+ }, 8_000);
64
+ }
65
+ function setWatchEnabled(next) {
66
+ watchEnabled = next;
67
+ if (watchEnabled) {
68
+ ensurePolling();
69
+ if (activeCtx) {
70
+ void refresh(activeCtx);
71
+ }
72
+ return;
73
+ }
74
+ if (activeCtx?.hasUI) {
75
+ activeCtx.ui.setWidget("mu-events", undefined);
76
+ }
77
+ stopPolling();
78
+ }
79
+ pi.on("session_start", async (_event, ctx) => {
80
+ activeCtx = ctx;
81
+ if (!ctx.hasUI)
82
+ return;
83
+ await refresh(ctx);
84
+ if (watchEnabled)
85
+ ensurePolling();
86
+ });
87
+ pi.on("session_switch", async (_event, ctx) => {
88
+ activeCtx = ctx;
89
+ if (!ctx.hasUI)
90
+ return;
91
+ await refresh(ctx);
92
+ if (watchEnabled)
93
+ ensurePolling();
94
+ });
95
+ pi.on("session_shutdown", async () => {
96
+ stopPolling();
97
+ activeCtx = null;
98
+ });
99
+ pi.registerCommand("mu-events", {
100
+ description: "Inspect events (`/mu-events [n]`, `/mu-events tail [n]`, `/mu-events watch on|off`)",
101
+ handler: async (args, ctx) => {
102
+ const tokens = args
103
+ .trim()
104
+ .split(/\s+/)
105
+ .filter((token) => token.length > 0);
106
+ if (tokens[0] === "watch") {
107
+ const mode = (tokens[1] ?? "toggle").toLowerCase();
108
+ if (mode === "on") {
109
+ setWatchEnabled(true);
110
+ ctx.ui.notify("Event watch enabled.", "info");
111
+ return;
112
+ }
113
+ if (mode === "off") {
114
+ setWatchEnabled(false);
115
+ ctx.ui.notify("Event watch disabled.", "info");
116
+ return;
117
+ }
118
+ setWatchEnabled(!watchEnabled);
119
+ ctx.ui.notify(`Event watch ${watchEnabled ? "enabled" : "disabled"}.`, "info");
120
+ return;
121
+ }
122
+ const requestedLimit = tokens[0] === "tail" ? Number.parseInt(tokens[1] ?? "20", 10) : Number.parseInt(tokens[0] ?? "20", 10);
123
+ const limit = clampInt(Number.isFinite(requestedLimit) ? requestedLimit : undefined, 20, 1, 100);
124
+ const events = await fetchTail(limit);
125
+ if (events.length === 0) {
126
+ ctx.ui.notify("No events found.", "info");
127
+ return;
128
+ }
129
+ const lines = events.map((event) => formatEventLine(event));
130
+ ctx.ui.notify(lines.join("\n"), "info");
131
+ },
132
+ });
133
+ }
134
+ export default eventLogExtension;
@@ -0,0 +1,21 @@
1
+ export { brandingExtension } from "./branding.js";
2
+ export { eventLogExtension } from "./event-log.js";
3
+ export { messagingSetupExtension } from "./messaging-setup.js";
4
+ export { serverToolsExtension } from "./server-tools.js";
5
+ import { brandingExtension } from "./branding.js";
6
+ /**
7
+ * Serve-mode extension module paths.
8
+ *
9
+ * Prefer this for session creation so extensions are loaded through pi's
10
+ * normal path-based loader (discoverable and visible by file path), not as
11
+ * anonymous inline factories.
12
+ */
13
+ export declare const serveExtensionPaths: string[];
14
+ /**
15
+ * Legacy serve-mode extension factories.
16
+ *
17
+ * Kept for compatibility in cases where callers need programmatic inline
18
+ * factories, but path-based loading is preferred.
19
+ */
20
+ export declare const serveExtensionFactories: (typeof brandingExtension)[];
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAYlD;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,UAE/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,8BAKnC,CAAC"}
@@ -0,0 +1,33 @@
1
+ export { brandingExtension } from "./branding.js";
2
+ export { eventLogExtension } from "./event-log.js";
3
+ export { messagingSetupExtension } from "./messaging-setup.js";
4
+ export { serverToolsExtension } from "./server-tools.js";
5
+ import { brandingExtension } from "./branding.js";
6
+ import { eventLogExtension } from "./event-log.js";
7
+ import { messagingSetupExtension } from "./messaging-setup.js";
8
+ import { serverToolsExtension } from "./server-tools.js";
9
+ const SERVE_EXTENSION_MODULE_BASENAMES = ["branding", "server-tools", "event-log", "messaging-setup"];
10
+ const RUNTIME_EXTENSION = import.meta.url.endsWith(".ts") ? "ts" : "js";
11
+ function resolveBundledExtensionPath(moduleBasename) {
12
+ return new URL(`./${moduleBasename}.${RUNTIME_EXTENSION}`, import.meta.url).pathname;
13
+ }
14
+ /**
15
+ * Serve-mode extension module paths.
16
+ *
17
+ * Prefer this for session creation so extensions are loaded through pi's
18
+ * normal path-based loader (discoverable and visible by file path), not as
19
+ * anonymous inline factories.
20
+ */
21
+ export const serveExtensionPaths = SERVE_EXTENSION_MODULE_BASENAMES.map((moduleBasename) => resolveBundledExtensionPath(moduleBasename));
22
+ /**
23
+ * Legacy serve-mode extension factories.
24
+ *
25
+ * Kept for compatibility in cases where callers need programmatic inline
26
+ * factories, but path-based loading is preferred.
27
+ */
28
+ export const serveExtensionFactories = [
29
+ brandingExtension,
30
+ serverToolsExtension,
31
+ eventLogExtension,
32
+ messagingSetupExtension,
33
+ ];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * mu-messaging-setup — Adapter configuration diagnostics + guided setup.
3
+ *
4
+ * Goals:
5
+ * - Make `/mu-setup <adapter>` hand setup context to the active mu agent.
6
+ * - Keep configuration in `.mu/config.json` (no process.env mutations).
7
+ * - Support plan/apply/verify workflow with in-process control-plane reload.
8
+ */
9
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
10
+ export declare function messagingSetupExtension(pi: ExtensionAPI): void;
11
+ export default messagingSetupExtension;
12
+ //# sourceMappingURL=messaging-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging-setup.d.ts","sourceRoot":"","sources":["../../src/extensions/messaging-setup.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,YAAY,EAA6C,MAAM,+BAA+B,CAAC;AAgjC7G,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,YAAY,QAqPvD;AAED,eAAe,uBAAuB,CAAC"}