@femtomc/mu-agent 26.2.69 → 26.2.70
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 +20 -1
- package/dist/backend.d.ts +1 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +11 -2
- package/dist/extensions/activities.d.ts +4 -1
- package/dist/extensions/activities.d.ts.map +1 -1
- package/dist/extensions/activities.js +127 -16
- package/dist/extensions/branding.d.ts +2 -3
- package/dist/extensions/branding.d.ts.map +1 -1
- package/dist/extensions/branding.js +73 -58
- package/dist/extensions/cron.d.ts +4 -1
- package/dist/extensions/cron.d.ts.map +1 -1
- package/dist/extensions/cron.js +74 -14
- package/dist/extensions/heartbeats.d.ts +4 -1
- package/dist/extensions/heartbeats.d.ts.map +1 -1
- package/dist/extensions/heartbeats.js +60 -17
- package/dist/extensions/index.d.ts +13 -3
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +13 -3
- package/dist/extensions/messaging-setup.d.ts +4 -1
- package/dist/extensions/messaging-setup.d.ts.map +1 -1
- package/dist/extensions/messaging-setup.js +47 -10
- package/dist/extensions/mu-full-tools.d.ts +10 -0
- package/dist/extensions/mu-full-tools.d.ts.map +1 -0
- package/dist/extensions/mu-full-tools.js +25 -0
- package/dist/extensions/mu-operator.d.ts.map +1 -1
- package/dist/extensions/mu-operator.js +2 -6
- package/dist/extensions/mu-query-tools.d.ts +10 -0
- package/dist/extensions/mu-query-tools.d.ts.map +1 -0
- package/dist/extensions/mu-query-tools.js +11 -0
- package/dist/extensions/operator-command.d.ts.map +1 -1
- package/dist/extensions/operator-command.js +106 -6
- package/dist/extensions/orchestration-runs-readonly.d.ts.map +1 -1
- package/dist/extensions/orchestration-runs-readonly.js +180 -10
- package/dist/extensions/orchestration-runs.d.ts.map +1 -1
- package/dist/extensions/orchestration-runs.js +206 -14
- package/dist/extensions/server-tools.d.ts +10 -0
- package/dist/extensions/server-tools.d.ts.map +1 -1
- package/dist/extensions/server-tools.js +688 -290
- package/dist/extensions/shared.d.ts +11 -0
- package/dist/extensions/shared.d.ts.map +1 -1
- package/dist/extensions/shared.js +81 -0
- package/dist/session_factory.d.ts.map +1 -1
- package/dist/session_factory.js +3 -1
- package/dist/ui_defaults.d.ts +4 -0
- package/dist/ui_defaults.d.ts.map +1 -0
- package/dist/ui_defaults.js +18 -0
- package/package.json +4 -3
- package/prompts/roles/operator.md +5 -0
- package/prompts/roles/orchestrator.md +1 -0
- package/prompts/roles/worker.md +10 -4
- package/themes/mu-gruvbox-dark.json +90 -0
package/dist/extensions/cron.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
|
-
import { clampInt, fetchMuJson, textResult, toJsonText } from "./shared.js";
|
|
3
|
+
import { asArray, asNumber, asRecord, asString, clampInt, fetchMuJson, parseFieldPaths, previewText, selectFields, textResult, toJsonText, } from "./shared.js";
|
|
4
4
|
function trimOrNull(value) {
|
|
5
5
|
if (value == null)
|
|
6
6
|
return null;
|
|
@@ -13,9 +13,40 @@ function normalizedNumber(value) {
|
|
|
13
13
|
}
|
|
14
14
|
return Math.trunc(value);
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
function summarizeCronProgram(program) {
|
|
17
|
+
const target = asRecord(program.target);
|
|
18
|
+
const schedule = asRecord(program.schedule);
|
|
19
|
+
return {
|
|
20
|
+
program_id: asString(program.program_id),
|
|
21
|
+
title: previewText(program.title, 120),
|
|
22
|
+
enabled: program.enabled ?? null,
|
|
23
|
+
target_kind: target ? asString(target.kind) : asString(program.target_kind),
|
|
24
|
+
target_job_id: target ? asString(target.job_id) : asString(program.run_job_id),
|
|
25
|
+
target_root_issue_id: target ? asString(target.root_issue_id) : asString(program.run_root_issue_id),
|
|
26
|
+
target_activity_id: target ? asString(target.activity_id) : asString(program.activity_id),
|
|
27
|
+
schedule_kind: schedule ? asString(schedule.kind) : asString(program.schedule_kind),
|
|
28
|
+
schedule_preview: previewText(schedule ?? program, 180),
|
|
29
|
+
reason: asString(program.reason),
|
|
30
|
+
wake_mode: asString(program.wake_mode),
|
|
31
|
+
last_result: asString(program.last_result),
|
|
32
|
+
updated_at_ms: asNumber(program.updated_at_ms),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function summarizeCronMutation(payload) {
|
|
36
|
+
const program = asRecord(payload.program);
|
|
37
|
+
return {
|
|
38
|
+
ok: payload.ok ?? null,
|
|
39
|
+
reason: asString(payload.reason),
|
|
40
|
+
program: program ? summarizeCronProgram(program) : null,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function cronExtension(pi, opts = {}) {
|
|
44
|
+
const allowMutations = opts.allowMutations ?? true;
|
|
45
|
+
const cronActions = allowMutations
|
|
46
|
+
? ["status", "list", "get", "create", "update", "delete", "trigger", "enable", "disable"]
|
|
47
|
+
: ["status", "list", "get"];
|
|
17
48
|
const Params = Type.Object({
|
|
18
|
-
action: StringEnum(
|
|
49
|
+
action: StringEnum(cronActions),
|
|
19
50
|
program_id: Type.Optional(Type.String({ description: "Cron program ID" })),
|
|
20
51
|
title: Type.Optional(Type.String({ description: "Program title" })),
|
|
21
52
|
target_kind: Type.Optional(Type.String({ description: "Target kind (run|activity)" })),
|
|
@@ -32,18 +63,34 @@ export function cronExtension(pi) {
|
|
|
32
63
|
reason: Type.Optional(Type.String({ description: "Execution reason" })),
|
|
33
64
|
enabled: Type.Optional(Type.Boolean({ description: "Enabled state" })),
|
|
34
65
|
schedule_filter: Type.Optional(Type.String({ description: "Filter list by schedule kind" })),
|
|
35
|
-
|
|
66
|
+
fields: Type.Optional(Type.String({ description: "Comma-separated fields for get selection" })),
|
|
67
|
+
limit: Type.Optional(Type.Number({ description: "Max returned items for list (default: 20)" })),
|
|
36
68
|
});
|
|
37
69
|
pi.registerTool({
|
|
38
70
|
name: "mu_cron",
|
|
39
71
|
label: "Cron",
|
|
40
|
-
description:
|
|
72
|
+
description: allowMutations
|
|
73
|
+
? "Manage persistent cron programs. Actions: status, list, get, create, update, delete, trigger, enable, disable. Summary-first output; use fields for precise retrieval."
|
|
74
|
+
: "Read cron programs. Actions: status, list, get. Query-only mode excludes mutations.",
|
|
41
75
|
parameters: Params,
|
|
42
76
|
async execute(_toolCallId, params) {
|
|
43
77
|
switch (params.action) {
|
|
44
78
|
case "status": {
|
|
45
79
|
const payload = await fetchMuJson("/api/cron/status");
|
|
46
|
-
|
|
80
|
+
const status = {
|
|
81
|
+
count: asNumber(payload.count) ?? 0,
|
|
82
|
+
enabled_count: asNumber(payload.enabled_count),
|
|
83
|
+
armed_count: asNumber(payload.armed_count),
|
|
84
|
+
running_count: asNumber(payload.running_count) ?? asNumber(payload.count_running) ?? null,
|
|
85
|
+
armed: asArray(payload.armed)
|
|
86
|
+
.map((entry) => asRecord(entry))
|
|
87
|
+
.filter((entry) => entry != null)
|
|
88
|
+
.map((entry) => ({
|
|
89
|
+
program_id: asString(entry.program_id),
|
|
90
|
+
due_at_ms: asNumber(entry.due_at_ms),
|
|
91
|
+
})),
|
|
92
|
+
};
|
|
93
|
+
return textResult(toJsonText(status), { action: "status", payload });
|
|
47
94
|
}
|
|
48
95
|
case "list": {
|
|
49
96
|
const query = new URLSearchParams();
|
|
@@ -58,13 +105,20 @@ export function cronExtension(pi) {
|
|
|
58
105
|
if (scheduleFilter) {
|
|
59
106
|
query.set("schedule_kind", scheduleFilter);
|
|
60
107
|
}
|
|
61
|
-
|
|
108
|
+
const limit = clampInt(params.limit, 20, 1, 500);
|
|
109
|
+
query.set("limit", String(limit));
|
|
62
110
|
const payload = await fetchMuJson(`/api/cron?${query.toString()}`);
|
|
63
|
-
|
|
111
|
+
const programs = asArray(payload.programs)
|
|
112
|
+
.map((program) => asRecord(program))
|
|
113
|
+
.filter((program) => program != null)
|
|
114
|
+
.map((program) => summarizeCronProgram(program));
|
|
115
|
+
return textResult(toJsonText({ count: programs.length, programs }), {
|
|
64
116
|
action: "list",
|
|
65
117
|
targetKind,
|
|
66
118
|
enabled: params.enabled,
|
|
67
119
|
scheduleFilter,
|
|
120
|
+
limit,
|
|
121
|
+
payload,
|
|
68
122
|
});
|
|
69
123
|
}
|
|
70
124
|
case "get": {
|
|
@@ -72,7 +126,11 @@ export function cronExtension(pi) {
|
|
|
72
126
|
if (!programId)
|
|
73
127
|
return textResult("get requires program_id");
|
|
74
128
|
const payload = await fetchMuJson(`/api/cron/${encodeURIComponent(programId)}`);
|
|
75
|
-
|
|
129
|
+
const fields = parseFieldPaths(trimOrNull(params.fields) ?? undefined);
|
|
130
|
+
const content = fields.length > 0
|
|
131
|
+
? { program_id: programId, selected: selectFields(payload, fields) }
|
|
132
|
+
: { program: summarizeCronProgram(payload) };
|
|
133
|
+
return textResult(toJsonText(content), { action: "get", programId, fields, payload });
|
|
76
134
|
}
|
|
77
135
|
case "create": {
|
|
78
136
|
const title = trimOrNull(params.title);
|
|
@@ -103,11 +161,12 @@ export function cronExtension(pi) {
|
|
|
103
161
|
enabled: typeof params.enabled === "boolean" ? params.enabled : undefined,
|
|
104
162
|
},
|
|
105
163
|
});
|
|
106
|
-
return textResult(toJsonText(payload), {
|
|
164
|
+
return textResult(toJsonText(summarizeCronMutation(payload)), {
|
|
107
165
|
action: "create",
|
|
108
166
|
title,
|
|
109
167
|
targetKind,
|
|
110
168
|
scheduleKind,
|
|
169
|
+
payload,
|
|
111
170
|
});
|
|
112
171
|
}
|
|
113
172
|
case "update": {
|
|
@@ -134,7 +193,7 @@ export function cronExtension(pi) {
|
|
|
134
193
|
enabled: typeof params.enabled === "boolean" ? params.enabled : undefined,
|
|
135
194
|
},
|
|
136
195
|
});
|
|
137
|
-
return textResult(toJsonText(payload), { action: "update", programId });
|
|
196
|
+
return textResult(toJsonText(summarizeCronMutation(payload)), { action: "update", programId, payload });
|
|
138
197
|
}
|
|
139
198
|
case "delete": {
|
|
140
199
|
const programId = trimOrNull(params.program_id);
|
|
@@ -146,7 +205,7 @@ export function cronExtension(pi) {
|
|
|
146
205
|
program_id: programId,
|
|
147
206
|
},
|
|
148
207
|
});
|
|
149
|
-
return textResult(toJsonText(payload), { action: "delete", programId });
|
|
208
|
+
return textResult(toJsonText(summarizeCronMutation(payload)), { action: "delete", programId, payload });
|
|
150
209
|
}
|
|
151
210
|
case "trigger": {
|
|
152
211
|
const programId = trimOrNull(params.program_id);
|
|
@@ -159,7 +218,7 @@ export function cronExtension(pi) {
|
|
|
159
218
|
reason: trimOrNull(params.reason),
|
|
160
219
|
},
|
|
161
220
|
});
|
|
162
|
-
return textResult(toJsonText(payload), { action: "trigger", programId });
|
|
221
|
+
return textResult(toJsonText(summarizeCronMutation(payload)), { action: "trigger", programId, payload });
|
|
163
222
|
}
|
|
164
223
|
case "enable":
|
|
165
224
|
case "disable": {
|
|
@@ -173,9 +232,10 @@ export function cronExtension(pi) {
|
|
|
173
232
|
enabled: params.action === "enable",
|
|
174
233
|
},
|
|
175
234
|
});
|
|
176
|
-
return textResult(toJsonText(payload), {
|
|
235
|
+
return textResult(toJsonText(summarizeCronMutation(payload)), {
|
|
177
236
|
action: params.action,
|
|
178
237
|
programId,
|
|
238
|
+
payload,
|
|
179
239
|
});
|
|
180
240
|
}
|
|
181
241
|
default:
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
export
|
|
2
|
+
export type HeartbeatsExtensionOpts = {
|
|
3
|
+
allowMutations?: boolean;
|
|
4
|
+
};
|
|
5
|
+
export declare function heartbeatsExtension(pi: ExtensionAPI, opts?: HeartbeatsExtensionOpts): void;
|
|
3
6
|
export default heartbeatsExtension;
|
|
4
7
|
//# sourceMappingURL=heartbeats.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heartbeats.d.ts","sourceRoot":"","sources":["../../src/extensions/heartbeats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"heartbeats.d.ts","sourceRoot":"","sources":["../../src/extensions/heartbeats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiDlE,MAAM,MAAM,uBAAuB,GAAG;IACrC,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,GAAE,uBAA4B,QA8JvF;AAED,eAAe,mBAAmB,CAAC"}
|
|
@@ -1,15 +1,44 @@
|
|
|
1
1
|
import { StringEnum } from "@mariozechner/pi-ai";
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
|
-
import { clampInt, fetchMuJson, textResult, toJsonText } from "./shared.js";
|
|
3
|
+
import { asArray, asNumber, asRecord, asString, clampInt, fetchMuJson, parseFieldPaths, previewText, selectFields, textResult, toJsonText, } from "./shared.js";
|
|
4
4
|
function trimOrNull(value) {
|
|
5
5
|
if (value == null)
|
|
6
6
|
return null;
|
|
7
7
|
const trimmed = value.trim();
|
|
8
8
|
return trimmed.length > 0 ? trimmed : null;
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
function summarizeHeartbeatProgram(program) {
|
|
11
|
+
const target = asRecord(program.target);
|
|
12
|
+
return {
|
|
13
|
+
program_id: asString(program.program_id),
|
|
14
|
+
title: previewText(program.title, 120),
|
|
15
|
+
enabled: program.enabled ?? null,
|
|
16
|
+
every_ms: asNumber(program.every_ms),
|
|
17
|
+
reason: asString(program.reason),
|
|
18
|
+
wake_mode: asString(program.wake_mode),
|
|
19
|
+
target_kind: target ? asString(target.kind) : asString(program.target_kind),
|
|
20
|
+
target_job_id: target ? asString(target.job_id) : asString(program.run_job_id),
|
|
21
|
+
target_root_issue_id: target ? asString(target.root_issue_id) : asString(program.run_root_issue_id),
|
|
22
|
+
target_activity_id: target ? asString(target.activity_id) : asString(program.activity_id),
|
|
23
|
+
last_result: asString(program.last_result),
|
|
24
|
+
updated_at_ms: asNumber(program.updated_at_ms),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function summarizeHeartbeatMutation(payload) {
|
|
28
|
+
const program = asRecord(payload.program);
|
|
29
|
+
return {
|
|
30
|
+
ok: payload.ok ?? null,
|
|
31
|
+
reason: asString(payload.reason),
|
|
32
|
+
program: program ? summarizeHeartbeatProgram(program) : null,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function heartbeatsExtension(pi, opts = {}) {
|
|
36
|
+
const allowMutations = opts.allowMutations ?? true;
|
|
37
|
+
const heartbeatActions = allowMutations
|
|
38
|
+
? ["list", "get", "create", "update", "delete", "trigger", "enable", "disable"]
|
|
39
|
+
: ["list", "get"];
|
|
11
40
|
const Params = Type.Object({
|
|
12
|
-
action: StringEnum(
|
|
41
|
+
action: StringEnum(heartbeatActions),
|
|
13
42
|
program_id: Type.Optional(Type.String({ description: "Heartbeat program ID" })),
|
|
14
43
|
title: Type.Optional(Type.String({ description: "Program title" })),
|
|
15
44
|
target_kind: Type.Optional(Type.String({ description: "Target kind (run|activity)" })),
|
|
@@ -19,12 +48,15 @@ export function heartbeatsExtension(pi) {
|
|
|
19
48
|
every_ms: Type.Optional(Type.Number({ description: "Heartbeat interval in ms" })),
|
|
20
49
|
reason: Type.Optional(Type.String({ description: "Heartbeat reason" })),
|
|
21
50
|
enabled: Type.Optional(Type.Boolean({ description: "Enabled state" })),
|
|
22
|
-
|
|
51
|
+
fields: Type.Optional(Type.String({ description: "Comma-separated fields for get selection" })),
|
|
52
|
+
limit: Type.Optional(Type.Number({ description: "Max returned items for list (default: 20)" })),
|
|
23
53
|
});
|
|
24
54
|
pi.registerTool({
|
|
25
55
|
name: "mu_heartbeats",
|
|
26
56
|
label: "Heartbeats",
|
|
27
|
-
description:
|
|
57
|
+
description: allowMutations
|
|
58
|
+
? "Program and manage persistent heartbeat schedules. Actions: list, get, create, update, delete, trigger, enable, disable. Summary-first output; use fields for precise retrieval."
|
|
59
|
+
: "Read heartbeat programs. Actions: list, get. Query-only mode excludes mutations.",
|
|
28
60
|
parameters: Params,
|
|
29
61
|
async execute(_toolCallId, params) {
|
|
30
62
|
switch (params.action) {
|
|
@@ -37,20 +69,25 @@ export function heartbeatsExtension(pi) {
|
|
|
37
69
|
if (typeof params.enabled === "boolean") {
|
|
38
70
|
query.set("enabled", params.enabled ? "true" : "false");
|
|
39
71
|
}
|
|
40
|
-
|
|
72
|
+
const limit = clampInt(params.limit, 20, 1, 500);
|
|
73
|
+
query.set("limit", String(limit));
|
|
41
74
|
const payload = await fetchMuJson(`/api/heartbeats?${query.toString()}`);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
75
|
+
const programs = asArray(payload.programs)
|
|
76
|
+
.map((program) => asRecord(program))
|
|
77
|
+
.filter((program) => program != null)
|
|
78
|
+
.map((program) => summarizeHeartbeatProgram(program));
|
|
79
|
+
return textResult(toJsonText({ count: programs.length, programs }), { action: "list", targetKind, enabled: params.enabled, limit, payload });
|
|
47
80
|
}
|
|
48
81
|
case "get": {
|
|
49
82
|
const programId = trimOrNull(params.program_id);
|
|
50
83
|
if (!programId)
|
|
51
84
|
return textResult("get requires program_id");
|
|
52
85
|
const payload = await fetchMuJson(`/api/heartbeats/${encodeURIComponent(programId)}`);
|
|
53
|
-
|
|
86
|
+
const fields = parseFieldPaths(trimOrNull(params.fields) ?? undefined);
|
|
87
|
+
const content = fields.length > 0
|
|
88
|
+
? { program_id: programId, selected: selectFields(payload, fields) }
|
|
89
|
+
: { program: summarizeHeartbeatProgram(payload) };
|
|
90
|
+
return textResult(toJsonText(content), { action: "get", programId, fields, payload });
|
|
54
91
|
}
|
|
55
92
|
case "create": {
|
|
56
93
|
const title = trimOrNull(params.title);
|
|
@@ -74,7 +111,12 @@ export function heartbeatsExtension(pi) {
|
|
|
74
111
|
enabled: typeof params.enabled === "boolean" ? params.enabled : undefined,
|
|
75
112
|
},
|
|
76
113
|
});
|
|
77
|
-
return textResult(toJsonText(payload), {
|
|
114
|
+
return textResult(toJsonText(summarizeHeartbeatMutation(payload)), {
|
|
115
|
+
action: "create",
|
|
116
|
+
title,
|
|
117
|
+
targetKind,
|
|
118
|
+
payload,
|
|
119
|
+
});
|
|
78
120
|
}
|
|
79
121
|
case "update": {
|
|
80
122
|
const programId = trimOrNull(params.program_id);
|
|
@@ -96,7 +138,7 @@ export function heartbeatsExtension(pi) {
|
|
|
96
138
|
enabled: typeof params.enabled === "boolean" ? params.enabled : undefined,
|
|
97
139
|
},
|
|
98
140
|
});
|
|
99
|
-
return textResult(toJsonText(payload), { action: "update", programId });
|
|
141
|
+
return textResult(toJsonText(summarizeHeartbeatMutation(payload)), { action: "update", programId, payload });
|
|
100
142
|
}
|
|
101
143
|
case "delete": {
|
|
102
144
|
const programId = trimOrNull(params.program_id);
|
|
@@ -108,7 +150,7 @@ export function heartbeatsExtension(pi) {
|
|
|
108
150
|
program_id: programId,
|
|
109
151
|
},
|
|
110
152
|
});
|
|
111
|
-
return textResult(toJsonText(payload), { action: "delete", programId });
|
|
153
|
+
return textResult(toJsonText(summarizeHeartbeatMutation(payload)), { action: "delete", programId, payload });
|
|
112
154
|
}
|
|
113
155
|
case "trigger": {
|
|
114
156
|
const programId = trimOrNull(params.program_id);
|
|
@@ -121,7 +163,7 @@ export function heartbeatsExtension(pi) {
|
|
|
121
163
|
reason: trimOrNull(params.reason),
|
|
122
164
|
},
|
|
123
165
|
});
|
|
124
|
-
return textResult(toJsonText(payload), { action: "trigger", programId });
|
|
166
|
+
return textResult(toJsonText(summarizeHeartbeatMutation(payload)), { action: "trigger", programId, payload });
|
|
125
167
|
}
|
|
126
168
|
case "enable":
|
|
127
169
|
case "disable": {
|
|
@@ -135,9 +177,10 @@ export function heartbeatsExtension(pi) {
|
|
|
135
177
|
enabled: params.action === "enable",
|
|
136
178
|
},
|
|
137
179
|
});
|
|
138
|
-
return textResult(toJsonText(payload), {
|
|
180
|
+
return textResult(toJsonText(summarizeHeartbeatMutation(payload)), {
|
|
139
181
|
action: params.action,
|
|
140
182
|
programId,
|
|
183
|
+
payload,
|
|
141
184
|
});
|
|
142
185
|
}
|
|
143
186
|
default:
|
|
@@ -4,20 +4,30 @@ export { cronExtension } from "./cron.js";
|
|
|
4
4
|
export { eventLogExtension } from "./event-log.js";
|
|
5
5
|
export { heartbeatsExtension } from "./heartbeats.js";
|
|
6
6
|
export { messagingSetupExtension } from "./messaging-setup.js";
|
|
7
|
+
export { muFullToolsExtension } from "./mu-full-tools.js";
|
|
7
8
|
export { muOperatorExtension } from "./mu-operator.js";
|
|
9
|
+
export { muQueryToolsExtension } from "./mu-query-tools.js";
|
|
8
10
|
export { muServeExtension } from "./mu-serve.js";
|
|
9
11
|
export { operatorCommandExtension } from "./operator-command.js";
|
|
10
12
|
export { orchestrationRunsExtension } from "./orchestration-runs.js";
|
|
11
13
|
export { orchestrationRunsReadOnlyExtension } from "./orchestration-runs-readonly.js";
|
|
12
|
-
export { serverToolsExtension, serverToolsReadOnlyExtension } from "./server-tools.js";
|
|
14
|
+
export { serverToolsExtension, serverToolsIssueForumExtension, serverToolsReadOnlyExtension } from "./server-tools.js";
|
|
13
15
|
export { serverToolsReadonlyExtension } from "./server-tools-readonly.js";
|
|
14
16
|
/**
|
|
15
17
|
* Serve-mode extension — single facade that bundles all serve extensions.
|
|
16
18
|
*/
|
|
17
19
|
export declare const serveExtensionPaths: string[];
|
|
18
20
|
/**
|
|
19
|
-
* Operator-mode extension — single facade that bundles
|
|
20
|
-
*
|
|
21
|
+
* Operator-mode extension — single facade that bundles operator UI +
|
|
22
|
+
* full mu tools + approved `/mu` command flow.
|
|
21
23
|
*/
|
|
22
24
|
export declare const operatorExtensionPaths: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Tool-only extension bundle for orchestrator sessions (full tool surface).
|
|
27
|
+
*/
|
|
28
|
+
export declare const orchestratorToolExtensionPaths: string[];
|
|
29
|
+
/**
|
|
30
|
+
* Tool-only extension bundle for worker sessions (issue/forum coordination only).
|
|
31
|
+
*/
|
|
32
|
+
export declare const workerToolExtensionPaths: string[];
|
|
23
33
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,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,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,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;
|
|
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,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,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,8BAA8B,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACvH,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAQ1E;;GAEG;AACH,eAAO,MAAM,mBAAmB,UAA4C,CAAC;AAE7E;;;GAGG;AACH,eAAO,MAAM,sBAAsB,UAA+C,CAAC;AAEnF;;GAEG;AACH,eAAO,MAAM,8BAA8B,UAAiD,CAAC;AAE7F;;GAEG;AACH,eAAO,MAAM,wBAAwB,UAAkD,CAAC"}
|
package/dist/extensions/index.js
CHANGED
|
@@ -4,12 +4,14 @@ export { cronExtension } from "./cron.js";
|
|
|
4
4
|
export { eventLogExtension } from "./event-log.js";
|
|
5
5
|
export { heartbeatsExtension } from "./heartbeats.js";
|
|
6
6
|
export { messagingSetupExtension } from "./messaging-setup.js";
|
|
7
|
+
export { muFullToolsExtension } from "./mu-full-tools.js";
|
|
7
8
|
export { muOperatorExtension } from "./mu-operator.js";
|
|
9
|
+
export { muQueryToolsExtension } from "./mu-query-tools.js";
|
|
8
10
|
export { muServeExtension } from "./mu-serve.js";
|
|
9
11
|
export { operatorCommandExtension } from "./operator-command.js";
|
|
10
12
|
export { orchestrationRunsExtension } from "./orchestration-runs.js";
|
|
11
13
|
export { orchestrationRunsReadOnlyExtension } from "./orchestration-runs-readonly.js";
|
|
12
|
-
export { serverToolsExtension, serverToolsReadOnlyExtension } from "./server-tools.js";
|
|
14
|
+
export { serverToolsExtension, serverToolsIssueForumExtension, serverToolsReadOnlyExtension } from "./server-tools.js";
|
|
13
15
|
export { serverToolsReadonlyExtension } from "./server-tools-readonly.js";
|
|
14
16
|
const RUNTIME_EXTENSION = import.meta.url.endsWith(".ts") ? "ts" : "js";
|
|
15
17
|
function resolveBundledExtensionPath(moduleBasename) {
|
|
@@ -20,7 +22,15 @@ function resolveBundledExtensionPath(moduleBasename) {
|
|
|
20
22
|
*/
|
|
21
23
|
export const serveExtensionPaths = [resolveBundledExtensionPath("mu-serve")];
|
|
22
24
|
/**
|
|
23
|
-
* Operator-mode extension — single facade that bundles
|
|
24
|
-
*
|
|
25
|
+
* Operator-mode extension — single facade that bundles operator UI +
|
|
26
|
+
* full mu tools + approved `/mu` command flow.
|
|
25
27
|
*/
|
|
26
28
|
export const operatorExtensionPaths = [resolveBundledExtensionPath("mu-operator")];
|
|
29
|
+
/**
|
|
30
|
+
* Tool-only extension bundle for orchestrator sessions (full tool surface).
|
|
31
|
+
*/
|
|
32
|
+
export const orchestratorToolExtensionPaths = [resolveBundledExtensionPath("mu-full-tools")];
|
|
33
|
+
/**
|
|
34
|
+
* Tool-only extension bundle for worker sessions (issue/forum coordination only).
|
|
35
|
+
*/
|
|
36
|
+
export const workerToolExtensionPaths = [resolveBundledExtensionPath("mu-query-tools")];
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* - Support plan/apply/verify workflow with in-process control-plane reload.
|
|
8
8
|
*/
|
|
9
9
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
10
|
-
export
|
|
10
|
+
export type MessagingSetupExtensionOpts = {
|
|
11
|
+
allowApply?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare function messagingSetupExtension(pi: ExtensionAPI, opts?: MessagingSetupExtensionOpts): void;
|
|
11
14
|
export default messagingSetupExtension;
|
|
12
15
|
//# sourceMappingURL=messaging-setup.d.ts.map
|
|
@@ -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;AAoqC7G,MAAM,MAAM,2BAA2B,GAAG;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,GAAE,2BAAgC,QAsR/F;AAED,eAAe,uBAAuB,CAAC"}
|
|
@@ -334,6 +334,9 @@ function summarizeChecks(checks) {
|
|
|
334
334
|
}
|
|
335
335
|
function preflightSummary(checks, runtime) {
|
|
336
336
|
const lines = ["Messaging adapter preflight:", ""];
|
|
337
|
+
if (checks.length === 0) {
|
|
338
|
+
lines.push("(no matching adapters)");
|
|
339
|
+
}
|
|
337
340
|
for (const check of checks) {
|
|
338
341
|
const route = check.route ? ` · route ${check.route}` : "";
|
|
339
342
|
const missing = check.missing.length > 0 ? ` · missing ${check.missing.join(", ")}` : "";
|
|
@@ -867,6 +870,13 @@ function dispatchSetupPromptToAgent(pi, ctx, prompt) {
|
|
|
867
870
|
function findCheckByAdapter(checks, adapterId) {
|
|
868
871
|
return checks.find((check) => check.id === adapterId) ?? null;
|
|
869
872
|
}
|
|
873
|
+
function checksForAdapter(checks, adapterId) {
|
|
874
|
+
if (!adapterId) {
|
|
875
|
+
return checks;
|
|
876
|
+
}
|
|
877
|
+
const match = checks.find((check) => check.id === adapterId);
|
|
878
|
+
return match ? [match] : [];
|
|
879
|
+
}
|
|
870
880
|
async function maybeDispatchAgentSetupBrief(opts) {
|
|
871
881
|
if (!opts.parsed.adapterId)
|
|
872
882
|
return false;
|
|
@@ -934,7 +944,8 @@ async function runInteractiveApply(ctx, adapterId) {
|
|
|
934
944
|
];
|
|
935
945
|
return lines.join("\n");
|
|
936
946
|
}
|
|
937
|
-
export function messagingSetupExtension(pi) {
|
|
947
|
+
export function messagingSetupExtension(pi, opts = {}) {
|
|
948
|
+
const allowApply = opts.allowApply ?? true;
|
|
938
949
|
pi.on("before_agent_start", async (event) => {
|
|
939
950
|
const { checks } = await collectChecksCached();
|
|
940
951
|
const summary = summarizeChecks(checks);
|
|
@@ -942,7 +953,9 @@ export function messagingSetupExtension(pi) {
|
|
|
942
953
|
"",
|
|
943
954
|
"[MU MESSAGING]",
|
|
944
955
|
summary.length > 0 ? summary : "no adapter status available",
|
|
945
|
-
|
|
956
|
+
allowApply
|
|
957
|
+
? "Use mu_messaging_setup(action=preflight|plan|apply|verify|guide) for operator workflow."
|
|
958
|
+
: "Use mu_messaging_setup(action=preflight|plan|verify|guide) for query workflow.",
|
|
946
959
|
];
|
|
947
960
|
return {
|
|
948
961
|
systemPrompt: `${event.systemPrompt}${lines.join("\n")}`,
|
|
@@ -951,8 +964,11 @@ export function messagingSetupExtension(pi) {
|
|
|
951
964
|
pi.on("session_start", async (_event, ctx) => {
|
|
952
965
|
await refreshMessagingStatus(ctx);
|
|
953
966
|
});
|
|
967
|
+
const setupActions = allowApply
|
|
968
|
+
? ["check", "preflight", "guide", "plan", "apply", "verify"]
|
|
969
|
+
: ["check", "preflight", "guide", "plan", "verify"];
|
|
954
970
|
const SetupParams = Type.Object({
|
|
955
|
-
action: StringEnum(
|
|
971
|
+
action: StringEnum(setupActions),
|
|
956
972
|
adapter: Type.Optional(Type.String({ description: "Adapter name: slack, discord, telegram, gmail" })),
|
|
957
973
|
public_base_url: Type.Optional(Type.String({
|
|
958
974
|
description: "Optional public base URL used to compute expected webhook endpoints (e.g. https://example.ngrok.app)",
|
|
@@ -964,9 +980,11 @@ export function messagingSetupExtension(pi) {
|
|
|
964
980
|
pi.registerTool({
|
|
965
981
|
name: "mu_messaging_setup",
|
|
966
982
|
label: "Messaging Setup",
|
|
967
|
-
description:
|
|
983
|
+
description: allowApply
|
|
984
|
+
? "Messaging setup workflow. Actions: check/preflight/guide/plan/apply/verify. For apply, pass field values via the fields parameter (e.g. fields={bot_token:'...', webhook_secret:'...'})."
|
|
985
|
+
: "Messaging setup query workflow. Actions: check/preflight/guide/plan/verify. Apply is disabled in query-only mode.",
|
|
968
986
|
parameters: SetupParams,
|
|
969
|
-
async execute(_toolCallId, params, _signal, _onUpdate,
|
|
987
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
970
988
|
const adapterId = params.adapter ? normalizeAdapterId(params.adapter) : null;
|
|
971
989
|
if (params.adapter && !adapterId) {
|
|
972
990
|
return textResult(`Unknown adapter: ${params.adapter}. Available: ${ADAPTERS.map((adapter) => adapter.id).join(", ")}`);
|
|
@@ -974,17 +992,24 @@ export function messagingSetupExtension(pi) {
|
|
|
974
992
|
switch (params.action) {
|
|
975
993
|
case "check": {
|
|
976
994
|
const { checks, runtime } = await collectChecksCached();
|
|
995
|
+
const filteredChecks = checksForAdapter(checks, adapterId);
|
|
977
996
|
return textResult(toJsonText({
|
|
978
|
-
checks,
|
|
997
|
+
checks: filteredChecks,
|
|
979
998
|
runtime: { ...runtime, routesByAdapter: Object.fromEntries(runtime.routesByAdapter) },
|
|
980
999
|
}), {
|
|
981
|
-
checks,
|
|
1000
|
+
checks: filteredChecks,
|
|
982
1001
|
runtime,
|
|
1002
|
+
adapter: adapterId,
|
|
983
1003
|
});
|
|
984
1004
|
}
|
|
985
1005
|
case "preflight": {
|
|
986
1006
|
const { checks, runtime } = await collectChecksCached();
|
|
987
|
-
|
|
1007
|
+
const filteredChecks = checksForAdapter(checks, adapterId);
|
|
1008
|
+
return textResult(preflightSummary(filteredChecks, runtime), {
|
|
1009
|
+
checks: filteredChecks,
|
|
1010
|
+
runtime,
|
|
1011
|
+
adapter: adapterId,
|
|
1012
|
+
});
|
|
988
1013
|
}
|
|
989
1014
|
case "guide":
|
|
990
1015
|
case "plan": {
|
|
@@ -1010,6 +1035,12 @@ export function messagingSetupExtension(pi) {
|
|
|
1010
1035
|
return textResult(planSummary(plans), { plans, runtime, adapter: null });
|
|
1011
1036
|
}
|
|
1012
1037
|
case "apply": {
|
|
1038
|
+
if (!allowApply) {
|
|
1039
|
+
return textResult("apply is disabled in query-only mode. Use plan/guide/verify actions.", {
|
|
1040
|
+
blocked: true,
|
|
1041
|
+
reason: "messaging_setup_query_only_mode",
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1013
1044
|
if (!adapterId) {
|
|
1014
1045
|
return textResult("apply requires adapter (slack|discord|telegram)");
|
|
1015
1046
|
}
|
|
@@ -1071,8 +1102,9 @@ export function messagingSetupExtension(pi) {
|
|
|
1071
1102
|
switch (parsed.action) {
|
|
1072
1103
|
case "check": {
|
|
1073
1104
|
const { checks, runtime } = await collectChecksCached(0);
|
|
1105
|
+
const filteredChecks = checksForAdapter(checks, parsed.adapterId);
|
|
1074
1106
|
ctx.ui.notify(toJsonText({
|
|
1075
|
-
checks,
|
|
1107
|
+
checks: filteredChecks,
|
|
1076
1108
|
runtime: { ...runtime, routesByAdapter: Object.fromEntries(runtime.routesByAdapter) },
|
|
1077
1109
|
}), "info");
|
|
1078
1110
|
await refreshMessagingStatus(ctx);
|
|
@@ -1087,7 +1119,8 @@ export function messagingSetupExtension(pi) {
|
|
|
1087
1119
|
await refreshMessagingStatus(ctx);
|
|
1088
1120
|
return;
|
|
1089
1121
|
}
|
|
1090
|
-
|
|
1122
|
+
const filteredChecks = checksForAdapter(checks, parsed.adapterId);
|
|
1123
|
+
ctx.ui.notify(preflightSummary(filteredChecks, runtime), "info");
|
|
1091
1124
|
await refreshMessagingStatus(ctx);
|
|
1092
1125
|
return;
|
|
1093
1126
|
}
|
|
@@ -1123,6 +1156,10 @@ export function messagingSetupExtension(pi) {
|
|
|
1123
1156
|
return;
|
|
1124
1157
|
}
|
|
1125
1158
|
case "apply": {
|
|
1159
|
+
if (!allowApply) {
|
|
1160
|
+
ctx.ui.notify("apply is disabled in query-only mode. Use /mu setup plan and /mu setup verify.", "warning");
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1126
1163
|
if (!parsed.adapterId) {
|
|
1127
1164
|
ctx.ui.notify("apply requires adapter. Example: /mu setup apply slack", "error");
|
|
1128
1165
|
return;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mu-full-tools — Tool-only extension bundle with full mu tool surface.
|
|
3
|
+
*
|
|
4
|
+
* Intended for orchestrator/operator contexts that should have the complete
|
|
5
|
+
* server-backed tool set (including mutation-capable tool actions).
|
|
6
|
+
*/
|
|
7
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
8
|
+
export declare function muFullToolsExtension(pi: ExtensionAPI): void;
|
|
9
|
+
export default muFullToolsExtension;
|
|
10
|
+
//# sourceMappingURL=mu-full-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mu-full-tools.d.ts","sourceRoot":"","sources":["../../src/extensions/mu-full-tools.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAQlE,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,YAAY,QAYpD;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mu-full-tools — Tool-only extension bundle with full mu tool surface.
|
|
3
|
+
*
|
|
4
|
+
* Intended for orchestrator/operator contexts that should have the complete
|
|
5
|
+
* server-backed tool set (including mutation-capable tool actions).
|
|
6
|
+
*/
|
|
7
|
+
import { activitiesExtension } from "./activities.js";
|
|
8
|
+
import { cronExtension } from "./cron.js";
|
|
9
|
+
import { heartbeatsExtension } from "./heartbeats.js";
|
|
10
|
+
import { messagingSetupExtension } from "./messaging-setup.js";
|
|
11
|
+
import { orchestrationRunsExtension } from "./orchestration-runs.js";
|
|
12
|
+
import { serverToolsExtension } from "./server-tools.js";
|
|
13
|
+
export function muFullToolsExtension(pi) {
|
|
14
|
+
serverToolsExtension(pi, {
|
|
15
|
+
allowForumPost: true,
|
|
16
|
+
allowIdentityMutations: true,
|
|
17
|
+
toolIntroLine: "Tools: mu_status, mu_control_plane, mu_issues, mu_forum, mu_events, mu_runs, mu_activities, mu_heartbeats, mu_cron, mu_messaging_setup, mu_identity.",
|
|
18
|
+
});
|
|
19
|
+
messagingSetupExtension(pi, { allowApply: true });
|
|
20
|
+
orchestrationRunsExtension(pi);
|
|
21
|
+
activitiesExtension(pi, { allowMutations: true });
|
|
22
|
+
heartbeatsExtension(pi, { allowMutations: true });
|
|
23
|
+
cronExtension(pi, { allowMutations: true });
|
|
24
|
+
}
|
|
25
|
+
export default muFullToolsExtension;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mu-operator.d.ts","sourceRoot":"","sources":["../../src/extensions/mu-operator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"mu-operator.d.ts","sourceRoot":"","sources":["../../src/extensions/mu-operator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAMlE,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,QAKnD;AAED,eAAe,mBAAmB,CAAC"}
|