@femtomc/mu-server 26.2.64 → 26.2.66
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/dist/control_plane.d.ts +7 -1
- package/dist/control_plane.js +7 -1
- package/dist/server.js +97 -0
- package/package.json +38 -38
package/dist/control_plane.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type MessagingOperatorBackend, MessagingOperatorRuntime } from "@femtomc/mu-agent";
|
|
2
|
-
import { type Channel, type GenerationTelemetryRecorder, type ReloadableGenerationIdentity } from "@femtomc/mu-control-plane";
|
|
2
|
+
import { type Channel, type CommandPipelineResult, type GenerationTelemetryRecorder, type ReloadableGenerationIdentity } from "@femtomc/mu-control-plane";
|
|
3
3
|
import { type MuConfig } from "./config.js";
|
|
4
4
|
import type { ActivityHeartbeatScheduler } from "./heartbeat_scheduler.js";
|
|
5
5
|
import { type ControlPlaneRunHeartbeatResult, type ControlPlaneRunInterruptResult, type ControlPlaneRunSnapshot, type ControlPlaneRunSupervisorOpts, type ControlPlaneRunTrace } from "./run_supervisor.js";
|
|
@@ -76,6 +76,11 @@ export type ControlPlaneHandle = {
|
|
|
76
76
|
idOrRoot: string;
|
|
77
77
|
limit?: number;
|
|
78
78
|
}): Promise<ControlPlaneRunTrace | null>;
|
|
79
|
+
submitTerminalCommand?(opts: {
|
|
80
|
+
commandText: string;
|
|
81
|
+
repoRoot: string;
|
|
82
|
+
requestId?: string;
|
|
83
|
+
}): Promise<CommandPipelineResult>;
|
|
79
84
|
stop(): Promise<void>;
|
|
80
85
|
};
|
|
81
86
|
export type ControlPlaneConfig = MuConfig["control_plane"];
|
|
@@ -138,6 +143,7 @@ export type BootstrapControlPlaneOpts = {
|
|
|
138
143
|
generation?: ControlPlaneGenerationContext;
|
|
139
144
|
telemetry?: GenerationTelemetryRecorder | null;
|
|
140
145
|
telegramGenerationHooks?: TelegramGenerationSwapHooks;
|
|
146
|
+
terminalEnabled?: boolean;
|
|
141
147
|
};
|
|
142
148
|
export declare function bootstrapControlPlane(opts: BootstrapControlPlaneOpts): Promise<ControlPlaneHandle | null>;
|
|
143
149
|
export {};
|
package/dist/control_plane.js
CHANGED
|
@@ -702,7 +702,7 @@ export async function bootstrapControlPlane(opts) {
|
|
|
702
702
|
},
|
|
703
703
|
}
|
|
704
704
|
: undefined;
|
|
705
|
-
if (detected.length === 0) {
|
|
705
|
+
if (detected.length === 0 && !opts.terminalEnabled) {
|
|
706
706
|
return null;
|
|
707
707
|
}
|
|
708
708
|
const paths = getControlPlanePaths(opts.repoRoot);
|
|
@@ -1050,6 +1050,12 @@ export async function bootstrapControlPlane(opts) {
|
|
|
1050
1050
|
async traceRun(traceOpts) {
|
|
1051
1051
|
return (await runSupervisor?.trace(traceOpts.idOrRoot, { limit: traceOpts.limit })) ?? null;
|
|
1052
1052
|
},
|
|
1053
|
+
async submitTerminalCommand(terminalOpts) {
|
|
1054
|
+
if (!pipeline) {
|
|
1055
|
+
throw new Error("control_plane_pipeline_unavailable");
|
|
1056
|
+
}
|
|
1057
|
+
return await pipeline.handleTerminalInbound(terminalOpts);
|
|
1058
|
+
},
|
|
1053
1059
|
async stop() {
|
|
1054
1060
|
if (drainInterval) {
|
|
1055
1061
|
clearInterval(drainInterval);
|
package/dist/server.js
CHANGED
|
@@ -214,6 +214,7 @@ export function createServer(options = {}) {
|
|
|
214
214
|
heartbeatScheduler,
|
|
215
215
|
generation,
|
|
216
216
|
telemetry: generationTelemetry,
|
|
217
|
+
terminalEnabled: true,
|
|
217
218
|
});
|
|
218
219
|
});
|
|
219
220
|
const controlPlaneProxy = {
|
|
@@ -272,6 +273,13 @@ export function createServer(options = {}) {
|
|
|
272
273
|
return null;
|
|
273
274
|
return await handle.traceRun(opts);
|
|
274
275
|
},
|
|
276
|
+
async submitTerminalCommand(opts) {
|
|
277
|
+
const handle = controlPlaneCurrent;
|
|
278
|
+
if (!handle?.submitTerminalCommand) {
|
|
279
|
+
throw new Error("control_plane_unavailable");
|
|
280
|
+
}
|
|
281
|
+
return await handle.submitTerminalCommand(opts);
|
|
282
|
+
},
|
|
275
283
|
async stop() {
|
|
276
284
|
const handle = controlPlaneCurrent;
|
|
277
285
|
controlPlaneCurrent = null;
|
|
@@ -1102,6 +1110,94 @@ export function createServer(options = {}) {
|
|
|
1102
1110
|
control_plane: controlPlane,
|
|
1103
1111
|
}, { headers });
|
|
1104
1112
|
}
|
|
1113
|
+
if (path === "/api/commands/submit") {
|
|
1114
|
+
if (request.method !== "POST") {
|
|
1115
|
+
return Response.json({ error: "Method Not Allowed" }, { status: 405, headers });
|
|
1116
|
+
}
|
|
1117
|
+
let body;
|
|
1118
|
+
try {
|
|
1119
|
+
body = (await request.json());
|
|
1120
|
+
}
|
|
1121
|
+
catch {
|
|
1122
|
+
return Response.json({ error: "invalid json body" }, { status: 400, headers });
|
|
1123
|
+
}
|
|
1124
|
+
const kind = typeof body.kind === "string" ? body.kind.trim() : "";
|
|
1125
|
+
if (!kind) {
|
|
1126
|
+
return Response.json({ error: "kind is required" }, { status: 400, headers });
|
|
1127
|
+
}
|
|
1128
|
+
let commandText;
|
|
1129
|
+
switch (kind) {
|
|
1130
|
+
case "run_start": {
|
|
1131
|
+
const prompt = typeof body.prompt === "string" ? body.prompt.trim() : "";
|
|
1132
|
+
if (!prompt) {
|
|
1133
|
+
return Response.json({ error: "prompt is required for run_start" }, { status: 400, headers });
|
|
1134
|
+
}
|
|
1135
|
+
const maxStepsSuffix = typeof body.max_steps === "number" && Number.isFinite(body.max_steps)
|
|
1136
|
+
? ` --max-steps ${Math.max(1, Math.trunc(body.max_steps))}`
|
|
1137
|
+
: "";
|
|
1138
|
+
commandText = `mu! run start ${prompt}${maxStepsSuffix}`;
|
|
1139
|
+
break;
|
|
1140
|
+
}
|
|
1141
|
+
case "run_resume": {
|
|
1142
|
+
const rootId = typeof body.root_issue_id === "string" ? body.root_issue_id.trim() : "";
|
|
1143
|
+
const maxSteps = typeof body.max_steps === "number" && Number.isFinite(body.max_steps)
|
|
1144
|
+
? ` ${Math.max(1, Math.trunc(body.max_steps))}`
|
|
1145
|
+
: "";
|
|
1146
|
+
commandText = `mu! run resume${rootId ? ` ${rootId}` : ""}${maxSteps}`;
|
|
1147
|
+
break;
|
|
1148
|
+
}
|
|
1149
|
+
case "run_interrupt": {
|
|
1150
|
+
const rootId = typeof body.root_issue_id === "string" ? body.root_issue_id.trim() : "";
|
|
1151
|
+
commandText = `mu! run interrupt${rootId ? ` ${rootId}` : ""}`;
|
|
1152
|
+
break;
|
|
1153
|
+
}
|
|
1154
|
+
case "status":
|
|
1155
|
+
commandText = "/mu status";
|
|
1156
|
+
break;
|
|
1157
|
+
case "issue_list":
|
|
1158
|
+
commandText = "/mu issue list";
|
|
1159
|
+
break;
|
|
1160
|
+
case "issue_get": {
|
|
1161
|
+
const issueId = typeof body.issue_id === "string" ? body.issue_id.trim() : "";
|
|
1162
|
+
commandText = `/mu issue get${issueId ? ` ${issueId}` : ""}`;
|
|
1163
|
+
break;
|
|
1164
|
+
}
|
|
1165
|
+
case "forum_read": {
|
|
1166
|
+
const topic = typeof body.topic === "string" ? body.topic.trim() : "";
|
|
1167
|
+
const limit = typeof body.limit === "number" && Number.isFinite(body.limit)
|
|
1168
|
+
? ` ${Math.max(1, Math.trunc(body.limit))}`
|
|
1169
|
+
: "";
|
|
1170
|
+
commandText = `/mu forum read${topic ? ` ${topic}` : ""}${limit}`;
|
|
1171
|
+
break;
|
|
1172
|
+
}
|
|
1173
|
+
case "run_list":
|
|
1174
|
+
commandText = "/mu run list";
|
|
1175
|
+
break;
|
|
1176
|
+
case "run_status": {
|
|
1177
|
+
const rootId = typeof body.root_issue_id === "string" ? body.root_issue_id.trim() : "";
|
|
1178
|
+
commandText = `/mu run status${rootId ? ` ${rootId}` : ""}`;
|
|
1179
|
+
break;
|
|
1180
|
+
}
|
|
1181
|
+
case "ready":
|
|
1182
|
+
commandText = "/mu ready";
|
|
1183
|
+
break;
|
|
1184
|
+
default:
|
|
1185
|
+
return Response.json({ error: `unknown command kind: ${kind}` }, { status: 400, headers });
|
|
1186
|
+
}
|
|
1187
|
+
try {
|
|
1188
|
+
if (!controlPlaneProxy.submitTerminalCommand) {
|
|
1189
|
+
return Response.json({ error: "control plane not available" }, { status: 503, headers });
|
|
1190
|
+
}
|
|
1191
|
+
const result = await controlPlaneProxy.submitTerminalCommand({
|
|
1192
|
+
commandText,
|
|
1193
|
+
repoRoot: context.repoRoot,
|
|
1194
|
+
});
|
|
1195
|
+
return Response.json({ ok: true, result }, { headers });
|
|
1196
|
+
}
|
|
1197
|
+
catch (err) {
|
|
1198
|
+
return Response.json({ error: `command failed: ${describeError(err)}` }, { status: 500, headers });
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1105
1201
|
if (path === "/api/runs") {
|
|
1106
1202
|
if (request.method !== "GET") {
|
|
1107
1203
|
return Response.json({ error: "Method Not Allowed" }, { status: 405, headers });
|
|
@@ -2016,6 +2112,7 @@ export async function createServerAsync(options = {}) {
|
|
|
2016
2112
|
generation_seq: 0,
|
|
2017
2113
|
},
|
|
2018
2114
|
telemetry: generationTelemetry,
|
|
2115
|
+
terminalEnabled: true,
|
|
2019
2116
|
});
|
|
2020
2117
|
const serverConfig = createServer({
|
|
2021
2118
|
...options,
|
package/package.json
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
2
|
+
"name": "@femtomc/mu-server",
|
|
3
|
+
"version": "26.2.66",
|
|
4
|
+
"description": "HTTP API server for mu status, work items, messaging setup, and web UI.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mu",
|
|
7
|
+
"server",
|
|
8
|
+
"api",
|
|
9
|
+
"web",
|
|
10
|
+
"automation"
|
|
11
|
+
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"bin": {
|
|
16
|
+
"mu-server": "./dist/cli.js"
|
|
17
|
+
},
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist/**",
|
|
26
|
+
"public/**"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc -p tsconfig.build.json",
|
|
30
|
+
"test": "bun test",
|
|
31
|
+
"start": "bun run dist/cli.js"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@femtomc/mu-agent": "26.2.65",
|
|
35
|
+
"@femtomc/mu-control-plane": "26.2.65",
|
|
36
|
+
"@femtomc/mu-core": "26.2.65",
|
|
37
|
+
"@femtomc/mu-forum": "26.2.65",
|
|
38
|
+
"@femtomc/mu-issue": "26.2.65"
|
|
39
|
+
}
|
|
40
40
|
}
|