@femtomc/mu-agent 26.2.56 → 26.2.57
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 +10 -10
- package/dist/extensions/branding.d.ts.map +1 -1
- package/dist/extensions/branding.js +6 -3
- package/dist/extensions/cron.d.ts +4 -0
- package/dist/extensions/cron.d.ts.map +1 -0
- package/dist/extensions/cron.js +187 -0
- package/dist/extensions/event-log.d.ts +2 -2
- package/dist/extensions/event-log.d.ts.map +1 -1
- package/dist/extensions/event-log.js +7 -4
- package/dist/extensions/index.d.ts +1 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +2 -0
- package/dist/extensions/messaging-setup.d.ts +1 -1
- package/dist/extensions/messaging-setup.d.ts.map +1 -1
- package/dist/extensions/messaging-setup.js +21 -18
- package/dist/extensions/mu-command-dispatcher.d.ts +11 -0
- package/dist/extensions/mu-command-dispatcher.d.ts.map +1 -0
- package/dist/extensions/mu-command-dispatcher.js +143 -0
- package/dist/extensions/server-tools.d.ts.map +1 -1
- package/dist/extensions/server-tools.js +10 -5
- package/package.json +2 -2
- package/prompts/roles/operator.md +1 -0
package/README.md
CHANGED
|
@@ -54,16 +54,16 @@ Current stack:
|
|
|
54
54
|
|
|
55
55
|
## Slash commands (operator-facing)
|
|
56
56
|
|
|
57
|
-
- `/mu
|
|
58
|
-
- `/mu
|
|
59
|
-
- `/mu
|
|
60
|
-
- `/mu
|
|
61
|
-
- `/mu
|
|
62
|
-
- `/mu
|
|
63
|
-
- `/mu
|
|
64
|
-
- `/mu
|
|
65
|
-
- `/mu
|
|
66
|
-
- `/mu
|
|
57
|
+
- `/mu status` — concise server status
|
|
58
|
+
- `/mu control` — active control-plane adapters and webhook routes
|
|
59
|
+
- `/mu setup` — adapter preflight
|
|
60
|
+
- `/mu setup plan <adapter>` — actionable wiring plan
|
|
61
|
+
- `/mu setup apply <adapter>` — guided config apply + control-plane reload
|
|
62
|
+
- `/mu setup verify [adapter]` — runtime verification for mounted routes
|
|
63
|
+
- `/mu setup <adapter>` — sends adapter setup brief to mu agent (`--no-agent` prints local guide)
|
|
64
|
+
- `/mu events [n]` / `/mu events tail [n]` — event log tail
|
|
65
|
+
- `/mu events watch on|off` — toggle event watch widget
|
|
66
|
+
- `/mu brand on|off|toggle` — enable/disable UI branding
|
|
67
67
|
|
|
68
68
|
## Tools (agent/operator-facing)
|
|
69
69
|
|
|
@@ -1 +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;
|
|
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;AAgDpF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,YAAY,QA8NjD;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* - Lightweight periodic status refresh (open/ready/control-plane)
|
|
9
9
|
*/
|
|
10
10
|
import { basename } from "node:path";
|
|
11
|
+
import { registerMuSubcommand } from "./mu-command-dispatcher.js";
|
|
11
12
|
import { fetchMuStatus, muServerUrl } from "./shared.js";
|
|
12
13
|
const EMPTY_SNAPSHOT = {
|
|
13
14
|
openCount: 0,
|
|
@@ -61,7 +62,7 @@ export function brandingExtension(pi) {
|
|
|
61
62
|
: snapshot.controlPlaneActive
|
|
62
63
|
? theme.fg("success", `cp ${snapshot.adapters.join(",") || "on"}`)
|
|
63
64
|
: theme.fg("muted", "cp off");
|
|
64
|
-
const line1 = `${theme.fg("accent", "μ")}${theme.fg("dim", " quick actions")}: ${theme.fg("muted", "/mu
|
|
65
|
+
const line1 = `${theme.fg("accent", "μ")}${theme.fg("dim", " quick actions")}: ${theme.fg("muted", "/mu status /mu control /mu setup /mu events")}`;
|
|
65
66
|
const line2 = `${theme.fg("dim", `open ${snapshot.openCount} · ready ${snapshot.readyCount}`)} · ${cpState}`;
|
|
66
67
|
return [truncateToWidth(line1, width), truncateToWidth(line2, width)];
|
|
67
68
|
},
|
|
@@ -220,8 +221,10 @@ export function brandingExtension(pi) {
|
|
|
220
221
|
footerRequestRender = null;
|
|
221
222
|
activeCtx = null;
|
|
222
223
|
});
|
|
223
|
-
pi
|
|
224
|
-
|
|
224
|
+
registerMuSubcommand(pi, {
|
|
225
|
+
subcommand: "brand",
|
|
226
|
+
summary: "Toggle mu TUI branding",
|
|
227
|
+
usage: "/mu brand [on|off|toggle]",
|
|
225
228
|
handler: async (args, ctx) => {
|
|
226
229
|
const mode = args.trim().toLowerCase();
|
|
227
230
|
if (mode === "on") {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/extensions/cron.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiBlE,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,QAoK7C;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
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
|
+
function normalizedNumber(value) {
|
|
11
|
+
if (value == null || !Number.isFinite(value)) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
return Math.trunc(value);
|
|
15
|
+
}
|
|
16
|
+
export function cronExtension(pi) {
|
|
17
|
+
const Params = Type.Object({
|
|
18
|
+
action: StringEnum(["status", "list", "get", "create", "update", "delete", "trigger", "enable", "disable"]),
|
|
19
|
+
program_id: Type.Optional(Type.String({ description: "Cron program ID" })),
|
|
20
|
+
title: Type.Optional(Type.String({ description: "Program title" })),
|
|
21
|
+
target_kind: Type.Optional(Type.String({ description: "Target kind (run|activity)" })),
|
|
22
|
+
run_job_id: Type.Optional(Type.String({ description: "Run job ID target" })),
|
|
23
|
+
run_root_issue_id: Type.Optional(Type.String({ description: "Run root issue ID target" })),
|
|
24
|
+
activity_id: Type.Optional(Type.String({ description: "Activity ID target" })),
|
|
25
|
+
schedule_kind: Type.Optional(Type.String({ description: "Schedule kind (at|every|cron)" })),
|
|
26
|
+
at_ms: Type.Optional(Type.Number({ description: "One-shot timestamp in epoch ms" })),
|
|
27
|
+
at: Type.Optional(Type.String({ description: "One-shot timestamp (ISO-8601)" })),
|
|
28
|
+
every_ms: Type.Optional(Type.Number({ description: "Fixed interval in ms" })),
|
|
29
|
+
anchor_ms: Type.Optional(Type.Number({ description: "Anchor timestamp for every schedules" })),
|
|
30
|
+
expr: Type.Optional(Type.String({ description: "Cron expression (5-field)" })),
|
|
31
|
+
tz: Type.Optional(Type.String({ description: "Optional IANA timezone for cron expressions" })),
|
|
32
|
+
reason: Type.Optional(Type.String({ description: "Execution reason" })),
|
|
33
|
+
enabled: Type.Optional(Type.Boolean({ description: "Enabled state" })),
|
|
34
|
+
schedule_filter: Type.Optional(Type.String({ description: "Filter list by schedule kind" })),
|
|
35
|
+
limit: Type.Optional(Type.Number({ description: "Max returned items for list" })),
|
|
36
|
+
});
|
|
37
|
+
pi.registerTool({
|
|
38
|
+
name: "mu_cron",
|
|
39
|
+
label: "Cron",
|
|
40
|
+
description: "Manage persistent cron programs. Actions: status, list, get, create, update, delete, trigger, enable, disable.",
|
|
41
|
+
parameters: Params,
|
|
42
|
+
async execute(_toolCallId, params) {
|
|
43
|
+
switch (params.action) {
|
|
44
|
+
case "status": {
|
|
45
|
+
const payload = await fetchMuJson("/api/cron/status");
|
|
46
|
+
return textResult(toJsonText(payload), { action: "status" });
|
|
47
|
+
}
|
|
48
|
+
case "list": {
|
|
49
|
+
const query = new URLSearchParams();
|
|
50
|
+
const targetKind = trimOrNull(params.target_kind);
|
|
51
|
+
if (targetKind) {
|
|
52
|
+
query.set("target_kind", targetKind);
|
|
53
|
+
}
|
|
54
|
+
if (typeof params.enabled === "boolean") {
|
|
55
|
+
query.set("enabled", params.enabled ? "true" : "false");
|
|
56
|
+
}
|
|
57
|
+
const scheduleFilter = trimOrNull(params.schedule_filter) ?? trimOrNull(params.schedule_kind);
|
|
58
|
+
if (scheduleFilter) {
|
|
59
|
+
query.set("schedule_kind", scheduleFilter);
|
|
60
|
+
}
|
|
61
|
+
query.set("limit", String(clampInt(params.limit, 50, 1, 500)));
|
|
62
|
+
const payload = await fetchMuJson(`/api/cron?${query.toString()}`);
|
|
63
|
+
return textResult(toJsonText(payload), {
|
|
64
|
+
action: "list",
|
|
65
|
+
targetKind,
|
|
66
|
+
enabled: params.enabled,
|
|
67
|
+
scheduleFilter,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
case "get": {
|
|
71
|
+
const programId = trimOrNull(params.program_id);
|
|
72
|
+
if (!programId)
|
|
73
|
+
return textResult("get requires program_id");
|
|
74
|
+
const payload = await fetchMuJson(`/api/cron/${encodeURIComponent(programId)}`);
|
|
75
|
+
return textResult(toJsonText(payload), { action: "get", programId });
|
|
76
|
+
}
|
|
77
|
+
case "create": {
|
|
78
|
+
const title = trimOrNull(params.title);
|
|
79
|
+
const targetKind = trimOrNull(params.target_kind);
|
|
80
|
+
const scheduleKind = trimOrNull(params.schedule_kind);
|
|
81
|
+
if (!title)
|
|
82
|
+
return textResult("create requires title");
|
|
83
|
+
if (!targetKind)
|
|
84
|
+
return textResult("create requires target_kind (run|activity)");
|
|
85
|
+
if (!scheduleKind)
|
|
86
|
+
return textResult("create requires schedule_kind (at|every|cron)");
|
|
87
|
+
const payload = await fetchMuJson("/api/cron/create", {
|
|
88
|
+
method: "POST",
|
|
89
|
+
body: {
|
|
90
|
+
title,
|
|
91
|
+
target_kind: targetKind,
|
|
92
|
+
run_job_id: trimOrNull(params.run_job_id),
|
|
93
|
+
run_root_issue_id: trimOrNull(params.run_root_issue_id),
|
|
94
|
+
activity_id: trimOrNull(params.activity_id),
|
|
95
|
+
schedule_kind: scheduleKind,
|
|
96
|
+
at_ms: normalizedNumber(params.at_ms),
|
|
97
|
+
at: trimOrNull(params.at),
|
|
98
|
+
every_ms: normalizedNumber(params.every_ms),
|
|
99
|
+
anchor_ms: normalizedNumber(params.anchor_ms),
|
|
100
|
+
expr: trimOrNull(params.expr),
|
|
101
|
+
tz: trimOrNull(params.tz),
|
|
102
|
+
reason: trimOrNull(params.reason),
|
|
103
|
+
enabled: typeof params.enabled === "boolean" ? params.enabled : undefined,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
return textResult(toJsonText(payload), {
|
|
107
|
+
action: "create",
|
|
108
|
+
title,
|
|
109
|
+
targetKind,
|
|
110
|
+
scheduleKind,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
case "update": {
|
|
114
|
+
const programId = trimOrNull(params.program_id);
|
|
115
|
+
if (!programId)
|
|
116
|
+
return textResult("update requires program_id");
|
|
117
|
+
const payload = await fetchMuJson("/api/cron/update", {
|
|
118
|
+
method: "POST",
|
|
119
|
+
body: {
|
|
120
|
+
program_id: programId,
|
|
121
|
+
title: trimOrNull(params.title),
|
|
122
|
+
target_kind: trimOrNull(params.target_kind),
|
|
123
|
+
run_job_id: trimOrNull(params.run_job_id),
|
|
124
|
+
run_root_issue_id: trimOrNull(params.run_root_issue_id),
|
|
125
|
+
activity_id: trimOrNull(params.activity_id),
|
|
126
|
+
schedule_kind: trimOrNull(params.schedule_kind),
|
|
127
|
+
at_ms: normalizedNumber(params.at_ms),
|
|
128
|
+
at: trimOrNull(params.at),
|
|
129
|
+
every_ms: normalizedNumber(params.every_ms),
|
|
130
|
+
anchor_ms: normalizedNumber(params.anchor_ms),
|
|
131
|
+
expr: trimOrNull(params.expr),
|
|
132
|
+
tz: trimOrNull(params.tz),
|
|
133
|
+
reason: trimOrNull(params.reason),
|
|
134
|
+
enabled: typeof params.enabled === "boolean" ? params.enabled : undefined,
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
return textResult(toJsonText(payload), { action: "update", programId });
|
|
138
|
+
}
|
|
139
|
+
case "delete": {
|
|
140
|
+
const programId = trimOrNull(params.program_id);
|
|
141
|
+
if (!programId)
|
|
142
|
+
return textResult("delete requires program_id");
|
|
143
|
+
const payload = await fetchMuJson("/api/cron/delete", {
|
|
144
|
+
method: "POST",
|
|
145
|
+
body: {
|
|
146
|
+
program_id: programId,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
return textResult(toJsonText(payload), { action: "delete", programId });
|
|
150
|
+
}
|
|
151
|
+
case "trigger": {
|
|
152
|
+
const programId = trimOrNull(params.program_id);
|
|
153
|
+
if (!programId)
|
|
154
|
+
return textResult("trigger requires program_id");
|
|
155
|
+
const payload = await fetchMuJson("/api/cron/trigger", {
|
|
156
|
+
method: "POST",
|
|
157
|
+
body: {
|
|
158
|
+
program_id: programId,
|
|
159
|
+
reason: trimOrNull(params.reason),
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
return textResult(toJsonText(payload), { action: "trigger", programId });
|
|
163
|
+
}
|
|
164
|
+
case "enable":
|
|
165
|
+
case "disable": {
|
|
166
|
+
const programId = trimOrNull(params.program_id);
|
|
167
|
+
if (!programId)
|
|
168
|
+
return textResult(`${params.action} requires program_id`);
|
|
169
|
+
const payload = await fetchMuJson("/api/cron/update", {
|
|
170
|
+
method: "POST",
|
|
171
|
+
body: {
|
|
172
|
+
program_id: programId,
|
|
173
|
+
enabled: params.action === "enable",
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
return textResult(toJsonText(payload), {
|
|
177
|
+
action: params.action,
|
|
178
|
+
programId,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
default:
|
|
182
|
+
return textResult(`unknown action: ${params.action}`);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
export default cronExtension;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* mu-event-log — Event stream helper for mu serve.
|
|
3
3
|
*
|
|
4
4
|
* - Status line with last event type and tail count
|
|
5
|
-
* - Optional watch widget below editor (`/mu
|
|
6
|
-
* - Command for quick tail inspection (`/mu
|
|
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
7
|
*/
|
|
8
8
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
9
9
|
export declare function eventLogExtension(pi: ExtensionAPI): void;
|
|
@@ -1 +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;
|
|
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;AAiCpF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,YAAY,QAkHjD;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* mu-event-log — Event stream helper for mu serve.
|
|
3
3
|
*
|
|
4
4
|
* - Status line with last event type and tail count
|
|
5
|
-
* - Optional watch widget below editor (`/mu
|
|
6
|
-
* - Command for quick tail inspection (`/mu
|
|
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
7
|
*/
|
|
8
|
+
import { registerMuSubcommand } from "./mu-command-dispatcher.js";
|
|
8
9
|
import { clampInt, fetchMuJson, muServerUrl } from "./shared.js";
|
|
9
10
|
function eventTime(tsMs) {
|
|
10
11
|
return new Date(tsMs).toLocaleTimeString();
|
|
@@ -96,8 +97,10 @@ export function eventLogExtension(pi) {
|
|
|
96
97
|
stopPolling();
|
|
97
98
|
activeCtx = null;
|
|
98
99
|
});
|
|
99
|
-
pi
|
|
100
|
-
|
|
100
|
+
registerMuSubcommand(pi, {
|
|
101
|
+
subcommand: "events",
|
|
102
|
+
summary: "Inspect event tails and toggle the watch widget",
|
|
103
|
+
usage: "/mu events [n] | /mu events tail [n] | /mu events watch on|off",
|
|
101
104
|
handler: async (args, ctx) => {
|
|
102
105
|
const tokens = args
|
|
103
106
|
.trim()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { activitiesExtension } from "./activities.js";
|
|
2
2
|
export { brandingExtension } from "./branding.js";
|
|
3
|
+
export { cronExtension } from "./cron.js";
|
|
3
4
|
export { eventLogExtension } from "./event-log.js";
|
|
4
5
|
export { heartbeatsExtension } from "./heartbeats.js";
|
|
5
6
|
export { messagingSetupExtension } from "./messaging-setup.js";
|
|
@@ -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,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,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;
|
|
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,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,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,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,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;AA2B1E;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,UAE/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,UAElC,CAAC"}
|
package/dist/extensions/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { activitiesExtension } from "./activities.js";
|
|
2
2
|
export { brandingExtension } from "./branding.js";
|
|
3
|
+
export { cronExtension } from "./cron.js";
|
|
3
4
|
export { eventLogExtension } from "./event-log.js";
|
|
4
5
|
export { heartbeatsExtension } from "./heartbeats.js";
|
|
5
6
|
export { messagingSetupExtension } from "./messaging-setup.js";
|
|
@@ -16,6 +17,7 @@ const SERVE_EXTENSION_MODULE_BASENAMES = [
|
|
|
16
17
|
"orchestration-runs",
|
|
17
18
|
"activities",
|
|
18
19
|
"heartbeats",
|
|
20
|
+
"cron",
|
|
19
21
|
];
|
|
20
22
|
const OPERATOR_EXTENSION_MODULE_BASENAMES = [
|
|
21
23
|
"branding",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* mu-messaging-setup — Adapter configuration diagnostics + guided setup.
|
|
3
3
|
*
|
|
4
4
|
* Goals:
|
|
5
|
-
* - Make `/mu
|
|
5
|
+
* - Make `/mu setup <adapter>` hand setup context to the active mu agent.
|
|
6
6
|
* - Keep configuration in `.mu/config.json` (no process.env mutations).
|
|
7
7
|
* - Support plan/apply/verify workflow with in-process control-plane reload.
|
|
8
8
|
*/
|
|
@@ -1 +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;
|
|
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;AAypC7G,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,YAAY,QAyPvD;AAED,eAAe,uBAAuB,CAAC"}
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
* mu-messaging-setup — Adapter configuration diagnostics + guided setup.
|
|
3
3
|
*
|
|
4
4
|
* Goals:
|
|
5
|
-
* - Make `/mu
|
|
5
|
+
* - Make `/mu setup <adapter>` hand setup context to the active mu agent.
|
|
6
6
|
* - Keep configuration in `.mu/config.json` (no process.env mutations).
|
|
7
7
|
* - Support plan/apply/verify workflow with in-process control-plane reload.
|
|
8
8
|
*/
|
|
9
9
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
10
10
|
import { Type } from "@sinclair/typebox";
|
|
11
11
|
import { loadBundledPrompt } from "../default_prompts.js";
|
|
12
|
+
import { registerMuSubcommand } from "./mu-command-dispatcher.js";
|
|
12
13
|
import { fetchMuJson, fetchMuStatus, muServerUrl, textResult, toJsonText } from "./shared.js";
|
|
13
14
|
const MESSAGING_SETUP_BRIEF_TEMPLATE = loadBundledPrompt("skills/messaging-setup-brief.md");
|
|
14
15
|
function interpolateTemplate(template, vars) {
|
|
@@ -31,7 +32,7 @@ const ADAPTERS = [
|
|
|
31
32
|
"Copy Signing Secret into .mu/config.json → control_plane.adapters.slack.signing_secret.",
|
|
32
33
|
"Create a Slash Command (e.g. /mu) with Request URL <public-base-url>/webhooks/slack.",
|
|
33
34
|
"Install/reinstall app after command changes.",
|
|
34
|
-
"Run /mu in Slack, then /mu
|
|
35
|
+
"Run /mu in Slack, then /mu setup verify slack.",
|
|
35
36
|
],
|
|
36
37
|
},
|
|
37
38
|
{
|
|
@@ -49,7 +50,7 @@ const ADAPTERS = [
|
|
|
49
50
|
"Create/open app in Discord Developer Portal.",
|
|
50
51
|
"Copy Interaction Public Key into .mu/config.json → control_plane.adapters.discord.signing_secret.",
|
|
51
52
|
"Set Interactions Endpoint URL to <public-base-url>/webhooks/discord.",
|
|
52
|
-
"Run a Discord command interaction, then /mu
|
|
53
|
+
"Run a Discord command interaction, then /mu setup verify discord.",
|
|
53
54
|
],
|
|
54
55
|
},
|
|
55
56
|
{
|
|
@@ -79,7 +80,7 @@ const ADAPTERS = [
|
|
|
79
80
|
"Call Telegram setWebhook using URL <public-base-url>/webhooks/telegram and matching secret_token.",
|
|
80
81
|
"Link your Telegram identity to control-plane policy (mu control link --channel telegram --actor-id <telegram-user-id> --tenant-id telegram-bot --role <viewer|contributor|operator>).",
|
|
81
82
|
"Optionally set control_plane.adapters.telegram.bot_username.",
|
|
82
|
-
"Send /mu in Telegram chat, then /mu
|
|
83
|
+
"Send /mu in Telegram chat, then /mu setup verify telegram.",
|
|
83
84
|
],
|
|
84
85
|
},
|
|
85
86
|
{
|
|
@@ -251,7 +252,7 @@ function nextStepForState(opts) {
|
|
|
251
252
|
case "active":
|
|
252
253
|
return "No action needed. Adapter is mounted and receiving webhooks.";
|
|
253
254
|
case "configured_not_active":
|
|
254
|
-
return "Run `/mu
|
|
255
|
+
return "Run `/mu setup apply <adapter>` to trigger in-process control-plane reload.";
|
|
255
256
|
case "missing_config":
|
|
256
257
|
return `Set required config fields: ${opts.missing.join(", ")}.`;
|
|
257
258
|
case "planned":
|
|
@@ -383,7 +384,7 @@ function setupGuide(checks, adapterId) {
|
|
|
383
384
|
return [
|
|
384
385
|
"# Messaging Integration Setup",
|
|
385
386
|
"",
|
|
386
|
-
"Use `/mu
|
|
387
|
+
"Use `/mu setup <adapter>` to hand setup context to mu agent.",
|
|
387
388
|
"Config source of truth is `.mu/config.json`.",
|
|
388
389
|
"",
|
|
389
390
|
...sections,
|
|
@@ -402,15 +403,15 @@ function buildPlan(check, publicBaseUrl) {
|
|
|
402
403
|
else {
|
|
403
404
|
if (check.missing.length > 0) {
|
|
404
405
|
steps.push(`Set required config fields: ${check.missing.join(", ")}.`);
|
|
405
|
-
steps.push(`Run /mu
|
|
406
|
+
steps.push(`Run /mu setup apply ${check.id} to write config and reload control-plane.`);
|
|
406
407
|
}
|
|
407
408
|
if (check.state === "configured_not_active") {
|
|
408
|
-
steps.push(`Run /mu
|
|
409
|
+
steps.push(`Run /mu setup apply ${check.id} to trigger control-plane reload.`);
|
|
409
410
|
}
|
|
410
411
|
if (webhookUrl) {
|
|
411
412
|
steps.push(`Configure provider webhook/inbound URL to: ${webhookUrl}`);
|
|
412
413
|
}
|
|
413
|
-
steps.push(`Run verification: /mu
|
|
414
|
+
steps.push(`Run verification: /mu setup verify ${check.id}${normalizedBase ? ` --public-base-url ${normalizedBase}` : ""}`);
|
|
414
415
|
}
|
|
415
416
|
return {
|
|
416
417
|
id: check.id,
|
|
@@ -423,8 +424,8 @@ function buildPlan(check, publicBaseUrl) {
|
|
|
423
424
|
missing_required_fields: check.missing,
|
|
424
425
|
steps,
|
|
425
426
|
commands: {
|
|
426
|
-
apply: `/mu
|
|
427
|
-
verify: `/mu
|
|
427
|
+
apply: `/mu setup apply ${check.id}`,
|
|
428
|
+
verify: `/mu setup verify ${check.id}`,
|
|
428
429
|
},
|
|
429
430
|
};
|
|
430
431
|
}
|
|
@@ -702,7 +703,7 @@ function verifyText(result) {
|
|
|
702
703
|
lines.push(` next: ${check.next_step}`);
|
|
703
704
|
}
|
|
704
705
|
if (!result.ok) {
|
|
705
|
-
lines.push("", "Tip: run `/mu
|
|
706
|
+
lines.push("", "Tip: run `/mu setup plan <adapter>` for exact remediation steps.");
|
|
706
707
|
}
|
|
707
708
|
return lines.join("\n");
|
|
708
709
|
}
|
|
@@ -853,7 +854,7 @@ function buildAgentSetupPrompt(opts) {
|
|
|
853
854
|
missing_fields: opts.check.missing.join(", ") || "(none)",
|
|
854
855
|
provider_steps: adapter.providerSetupSteps.map((step, index) => `${index + 1}. ${step}`).join("\n"),
|
|
855
856
|
field_status: adapterFieldStatusLines(adapter, opts.check).join("\n"),
|
|
856
|
-
verify_command: `/mu
|
|
857
|
+
verify_command: `/mu setup verify ${adapter.id}${verifyFlag}`,
|
|
857
858
|
});
|
|
858
859
|
}
|
|
859
860
|
function dispatchSetupPromptToAgent(pi, ctx, prompt) {
|
|
@@ -1023,7 +1024,7 @@ export function messagingSetupExtension(pi) {
|
|
|
1023
1024
|
const overrides = params.fields ?? {};
|
|
1024
1025
|
const stillMissing = check.missing.filter((field) => !(field in overrides));
|
|
1025
1026
|
if (stillMissing.length > 0) {
|
|
1026
|
-
return textResult(`Cannot apply ${adapterId}: missing required config fields (${stillMissing.join(", ")}). Pass them via the fields parameter or use /mu
|
|
1027
|
+
return textResult(`Cannot apply ${adapterId}: missing required config fields (${stillMissing.join(", ")}). Pass them via the fields parameter or use /mu setup apply ${adapterId} for guided input.`, { adapter: adapterId, missing_required_fields: stillMissing });
|
|
1027
1028
|
}
|
|
1028
1029
|
const outcome = await applyAdapterConfig({
|
|
1029
1030
|
adapterId,
|
|
@@ -1057,12 +1058,14 @@ export function messagingSetupExtension(pi) {
|
|
|
1057
1058
|
}
|
|
1058
1059
|
},
|
|
1059
1060
|
});
|
|
1060
|
-
pi
|
|
1061
|
-
|
|
1061
|
+
registerMuSubcommand(pi, {
|
|
1062
|
+
subcommand: "setup",
|
|
1063
|
+
summary: "Messaging adapter setup workflow (preflight/guide/plan/apply/verify)",
|
|
1064
|
+
usage: "/mu setup [preflight|guide|plan|apply|verify] [adapter] [--public-base-url URL] [--agent|--no-agent]",
|
|
1062
1065
|
handler: async (args, ctx) => {
|
|
1063
1066
|
const parsed = parseSetupCommandArgs(args);
|
|
1064
1067
|
if (parsed.error) {
|
|
1065
|
-
ctx.ui.notify(`${parsed.error}. Usage: /mu
|
|
1068
|
+
ctx.ui.notify(`${parsed.error}. Usage: /mu setup [preflight|guide|plan|apply|verify] [adapter] [--public-base-url URL] [--agent|--no-agent]`, "error");
|
|
1066
1069
|
return;
|
|
1067
1070
|
}
|
|
1068
1071
|
switch (parsed.action) {
|
|
@@ -1121,7 +1124,7 @@ export function messagingSetupExtension(pi) {
|
|
|
1121
1124
|
}
|
|
1122
1125
|
case "apply": {
|
|
1123
1126
|
if (!parsed.adapterId) {
|
|
1124
|
-
ctx.ui.notify("apply requires adapter. Example: /mu
|
|
1127
|
+
ctx.ui.notify("apply requires adapter. Example: /mu setup apply slack", "error");
|
|
1125
1128
|
return;
|
|
1126
1129
|
}
|
|
1127
1130
|
const text = await runInteractiveApply(ctx, parsed.adapterId);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
export type MuSubcommandHandler = (args: string, ctx: ExtensionCommandContext) => Promise<void> | void;
|
|
3
|
+
export type MuSubcommandRegistration = {
|
|
4
|
+
subcommand: string;
|
|
5
|
+
summary: string;
|
|
6
|
+
usage: string;
|
|
7
|
+
aliases?: string[];
|
|
8
|
+
handler: MuSubcommandHandler;
|
|
9
|
+
};
|
|
10
|
+
export declare function registerMuSubcommand(pi: ExtensionAPI, registration: MuSubcommandRegistration): void;
|
|
11
|
+
//# sourceMappingURL=mu-command-dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mu-command-dispatcher.d.ts","sourceRoot":"","sources":["../../src/extensions/mu-command-dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAE3F,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEvG,MAAM,MAAM,wBAAwB,GAAG;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,mBAAmB,CAAC;CAC7B,CAAC;AAiIF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,wBAAwB,GAAG,IAAI,CAsDnG"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
const DISPATCHER_STATES = new WeakMap();
|
|
2
|
+
const RESERVED_SUBCOMMANDS = new Set(["help", "?"]);
|
|
3
|
+
function normalizeSubcommand(value) {
|
|
4
|
+
return value.trim().toLowerCase();
|
|
5
|
+
}
|
|
6
|
+
function isValidSubcommandToken(value) {
|
|
7
|
+
return /^[a-z][a-z0-9_-]*$/.test(value);
|
|
8
|
+
}
|
|
9
|
+
function subcommandUsageSummary(entry) {
|
|
10
|
+
const aliasSuffix = entry.aliases && entry.aliases.length > 0 ? ` (aliases: ${entry.aliases.join(", ")})` : "";
|
|
11
|
+
return `- ${entry.usage} — ${entry.summary}${aliasSuffix}`;
|
|
12
|
+
}
|
|
13
|
+
function renderSubcommandCatalog(state) {
|
|
14
|
+
if (state.entries.size === 0) {
|
|
15
|
+
return ["No /mu subcommands are currently registered.", "", "Try again after extensions finish loading."].join("\n");
|
|
16
|
+
}
|
|
17
|
+
const entries = [...state.entries.values()].sort((left, right) => left.normalizedSubcommand.localeCompare(right.normalizedSubcommand));
|
|
18
|
+
const lines = ["Usage: /mu <subcommand> [args]", "", "Subcommands:"];
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
lines.push(subcommandUsageSummary(entry));
|
|
21
|
+
}
|
|
22
|
+
lines.push("", "Run `/mu help <subcommand>` for focused usage.");
|
|
23
|
+
return lines.join("\n");
|
|
24
|
+
}
|
|
25
|
+
function renderSubcommandHelp(entry) {
|
|
26
|
+
const lines = [entry.summary, "", `Usage: ${entry.usage}`];
|
|
27
|
+
if (entry.aliases && entry.aliases.length > 0) {
|
|
28
|
+
lines.push(`Aliases: ${entry.aliases.map((alias) => `/mu ${alias}`).join(", ")}`);
|
|
29
|
+
}
|
|
30
|
+
return lines.join("\n");
|
|
31
|
+
}
|
|
32
|
+
function parseInvocation(args) {
|
|
33
|
+
const trimmed = args.trim();
|
|
34
|
+
if (trimmed.length === 0) {
|
|
35
|
+
return { subcommand: "", remainder: "" };
|
|
36
|
+
}
|
|
37
|
+
const boundary = trimmed.search(/\s/);
|
|
38
|
+
if (boundary === -1) {
|
|
39
|
+
return { subcommand: trimmed, remainder: "" };
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
subcommand: trimmed.slice(0, boundary),
|
|
43
|
+
remainder: trimmed.slice(boundary + 1).trim(),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function resolveEntry(state, token) {
|
|
47
|
+
const normalized = normalizeSubcommand(token);
|
|
48
|
+
if (!normalized)
|
|
49
|
+
return null;
|
|
50
|
+
const canonical = state.aliases.get(normalized) ?? normalized;
|
|
51
|
+
return state.entries.get(canonical) ?? null;
|
|
52
|
+
}
|
|
53
|
+
function ensureDispatcher(pi) {
|
|
54
|
+
const existing = DISPATCHER_STATES.get(pi);
|
|
55
|
+
if (existing) {
|
|
56
|
+
return existing;
|
|
57
|
+
}
|
|
58
|
+
const state = {
|
|
59
|
+
entries: new Map(),
|
|
60
|
+
aliases: new Map(),
|
|
61
|
+
};
|
|
62
|
+
DISPATCHER_STATES.set(pi, state);
|
|
63
|
+
pi.registerCommand("mu", {
|
|
64
|
+
description: "mu command dispatcher (`/mu <subcommand> ...`)",
|
|
65
|
+
handler: async (args, ctx) => {
|
|
66
|
+
const parsed = parseInvocation(args);
|
|
67
|
+
if (!parsed.subcommand) {
|
|
68
|
+
ctx.ui.notify(renderSubcommandCatalog(state), "info");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const normalized = normalizeSubcommand(parsed.subcommand);
|
|
72
|
+
if (normalized === "help" || normalized === "?") {
|
|
73
|
+
if (!parsed.remainder) {
|
|
74
|
+
ctx.ui.notify(renderSubcommandCatalog(state), "info");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const detail = resolveEntry(state, parsed.remainder.split(/\s+/)[0] ?? "");
|
|
78
|
+
if (!detail) {
|
|
79
|
+
ctx.ui.notify(`Unknown mu subcommand: ${parsed.remainder}\n\n${renderSubcommandCatalog(state)}`, "error");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
ctx.ui.notify(renderSubcommandHelp(detail), "info");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const entry = resolveEntry(state, parsed.subcommand);
|
|
86
|
+
if (!entry) {
|
|
87
|
+
ctx.ui.notify(`Unknown mu subcommand: ${parsed.subcommand}\n\n${renderSubcommandCatalog(state)}`, "error");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
await entry.handler(parsed.remainder, ctx);
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
return state;
|
|
94
|
+
}
|
|
95
|
+
export function registerMuSubcommand(pi, registration) {
|
|
96
|
+
const state = ensureDispatcher(pi);
|
|
97
|
+
const normalizedSubcommand = normalizeSubcommand(registration.subcommand);
|
|
98
|
+
if (!isValidSubcommandToken(normalizedSubcommand)) {
|
|
99
|
+
throw new Error(`Invalid mu subcommand: ${registration.subcommand}`);
|
|
100
|
+
}
|
|
101
|
+
if (RESERVED_SUBCOMMANDS.has(normalizedSubcommand)) {
|
|
102
|
+
throw new Error(`Reserved mu subcommand: ${registration.subcommand}`);
|
|
103
|
+
}
|
|
104
|
+
if (!registration.usage.startsWith("/mu ")) {
|
|
105
|
+
throw new Error(`mu subcommand usage must start with '/mu ': ${registration.usage}`);
|
|
106
|
+
}
|
|
107
|
+
const normalizedAliases = (registration.aliases ?? [])
|
|
108
|
+
.map((alias) => normalizeSubcommand(alias))
|
|
109
|
+
.filter((alias) => alias.length > 0 && alias !== normalizedSubcommand);
|
|
110
|
+
for (const alias of normalizedAliases) {
|
|
111
|
+
if (!isValidSubcommandToken(alias)) {
|
|
112
|
+
throw new Error(`Invalid mu subcommand alias: ${alias}`);
|
|
113
|
+
}
|
|
114
|
+
if (RESERVED_SUBCOMMANDS.has(alias)) {
|
|
115
|
+
throw new Error(`Reserved mu subcommand alias: ${alias}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const existing = state.entries.get(normalizedSubcommand);
|
|
119
|
+
if (existing) {
|
|
120
|
+
for (const alias of existing.normalizedAliases) {
|
|
121
|
+
state.aliases.delete(alias);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (const alias of normalizedAliases) {
|
|
125
|
+
const occupiedBy = state.aliases.get(alias);
|
|
126
|
+
if (occupiedBy && occupiedBy !== normalizedSubcommand) {
|
|
127
|
+
throw new Error(`mu subcommand alias '${alias}' is already registered by '${occupiedBy}'`);
|
|
128
|
+
}
|
|
129
|
+
if (state.entries.has(alias) && alias !== normalizedSubcommand) {
|
|
130
|
+
throw new Error(`mu subcommand alias '${alias}' conflicts with existing subcommand`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const entry = {
|
|
134
|
+
...registration,
|
|
135
|
+
normalizedSubcommand,
|
|
136
|
+
normalizedAliases,
|
|
137
|
+
};
|
|
138
|
+
state.entries.set(normalizedSubcommand, entry);
|
|
139
|
+
state.aliases.set(normalizedSubcommand, normalizedSubcommand);
|
|
140
|
+
for (const alias of normalizedAliases) {
|
|
141
|
+
state.aliases.set(alias, normalizedSubcommand);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -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;
|
|
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;AAqFlE,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;AA2XF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,GAAE,wBAA6B,QAQzF;AAED,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,YAAY,QAS5D;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
7
7
|
import { Type } from "@sinclair/typebox";
|
|
8
|
+
import { registerMuSubcommand } from "./mu-command-dispatcher.js";
|
|
8
9
|
import { clampInt, fetchMuJson, fetchMuStatus, muServerUrl, textResult, toJsonText, } from "./shared.js";
|
|
9
10
|
function trimOrNull(value) {
|
|
10
11
|
if (value == null)
|
|
@@ -376,8 +377,10 @@ function registerServerTools(pi, opts) {
|
|
|
376
377
|
}
|
|
377
378
|
},
|
|
378
379
|
});
|
|
379
|
-
pi
|
|
380
|
-
|
|
380
|
+
registerMuSubcommand(pi, {
|
|
381
|
+
subcommand: "status",
|
|
382
|
+
summary: "Show concise mu server status",
|
|
383
|
+
usage: "/mu status",
|
|
381
384
|
handler: async (_args, ctx) => {
|
|
382
385
|
try {
|
|
383
386
|
const status = await fetchMuStatus();
|
|
@@ -388,8 +391,10 @@ function registerServerTools(pi, opts) {
|
|
|
388
391
|
}
|
|
389
392
|
},
|
|
390
393
|
});
|
|
391
|
-
pi
|
|
392
|
-
|
|
394
|
+
registerMuSubcommand(pi, {
|
|
395
|
+
subcommand: "control",
|
|
396
|
+
summary: "Show control-plane adapter/runtime status",
|
|
397
|
+
usage: "/mu control",
|
|
393
398
|
handler: async (_args, ctx) => {
|
|
394
399
|
try {
|
|
395
400
|
const status = await fetchMuStatus();
|
|
@@ -414,7 +419,7 @@ export function serverToolsExtension(pi, opts = {}) {
|
|
|
414
419
|
registerServerTools(pi, {
|
|
415
420
|
allowForumPost: opts.allowForumPost ?? true,
|
|
416
421
|
toolIntroLine: opts.toolIntroLine ??
|
|
417
|
-
"Tools: mu_status, mu_control_plane, mu_issues, mu_forum, mu_events, mu_runs, mu_activities, mu_heartbeats, mu_identity.",
|
|
422
|
+
"Tools: mu_status, mu_control_plane, mu_issues, mu_forum, mu_events, mu_runs, mu_activities, mu_heartbeats, mu_cron, mu_identity.",
|
|
418
423
|
extraSystemPromptLines: opts.extraSystemPromptLines ?? [],
|
|
419
424
|
});
|
|
420
425
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@femtomc/mu-agent",
|
|
3
|
-
"version": "26.2.
|
|
3
|
+
"version": "26.2.57",
|
|
4
4
|
"description": "Shared agent runtime for mu chat, orchestration roles, and serve extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mu",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"prompts/**"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@femtomc/mu-core": "
|
|
26
|
+
"@femtomc/mu-core": "workspace:*",
|
|
27
27
|
"@mariozechner/pi-agent-core": "^0.52.12",
|
|
28
28
|
"@mariozechner/pi-ai": "^0.52.12",
|
|
29
29
|
"@mariozechner/pi-coding-agent": "^0.52.12",
|