@femtomc/mu-server 26.2.73 → 26.2.75

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.
Files changed (51) hide show
  1. package/README.md +54 -66
  2. package/dist/api/control_plane.js +56 -0
  3. package/dist/api/cron.js +2 -23
  4. package/dist/api/heartbeats.js +1 -66
  5. package/dist/api/identities.js +3 -2
  6. package/dist/api/runs.js +0 -83
  7. package/dist/api/session_flash.d.ts +60 -0
  8. package/dist/api/session_flash.js +326 -0
  9. package/dist/api/session_turn.d.ts +38 -0
  10. package/dist/api/session_turn.js +423 -0
  11. package/dist/config.d.ts +9 -4
  12. package/dist/config.js +24 -24
  13. package/dist/control_plane.d.ts +2 -16
  14. package/dist/control_plane.js +57 -83
  15. package/dist/control_plane_adapter_registry.d.ts +19 -0
  16. package/dist/control_plane_adapter_registry.js +74 -0
  17. package/dist/control_plane_contract.d.ts +1 -7
  18. package/dist/control_plane_run_queue_coordinator.d.ts +1 -7
  19. package/dist/control_plane_run_queue_coordinator.js +1 -62
  20. package/dist/control_plane_telegram_generation.js +1 -0
  21. package/dist/control_plane_wake_delivery.js +1 -0
  22. package/dist/cron_programs.d.ts +21 -35
  23. package/dist/cron_programs.js +32 -113
  24. package/dist/cron_request.d.ts +0 -6
  25. package/dist/cron_request.js +0 -41
  26. package/dist/heartbeat_programs.d.ts +20 -35
  27. package/dist/heartbeat_programs.js +26 -122
  28. package/dist/index.d.ts +2 -2
  29. package/dist/outbound_delivery_router.d.ts +12 -0
  30. package/dist/outbound_delivery_router.js +29 -0
  31. package/dist/run_supervisor.d.ts +1 -16
  32. package/dist/run_supervisor.js +0 -70
  33. package/dist/server.d.ts +0 -5
  34. package/dist/server.js +95 -127
  35. package/dist/server_program_orchestration.d.ts +4 -19
  36. package/dist/server_program_orchestration.js +49 -200
  37. package/dist/server_routing.d.ts +0 -9
  38. package/dist/server_routing.js +19 -654
  39. package/dist/server_runtime.js +0 -1
  40. package/dist/server_types.d.ts +0 -2
  41. package/dist/server_types.js +0 -7
  42. package/package.json +6 -9
  43. package/dist/api/context.d.ts +0 -5
  44. package/dist/api/context.js +0 -1147
  45. package/dist/api/forum.d.ts +0 -2
  46. package/dist/api/forum.js +0 -75
  47. package/dist/api/issues.d.ts +0 -2
  48. package/dist/api/issues.js +0 -173
  49. package/public/assets/index-CxkevQNh.js +0 -100
  50. package/public/assets/index-D_8anM-D.css +0 -1
  51. package/public/index.html +0 -14
@@ -1,25 +1,34 @@
1
1
  import { CronProgramRegistry } from "./cron_programs.js";
2
2
  import { HeartbeatProgramRegistry } from "./heartbeat_programs.js";
3
- const AUTO_RUN_HEARTBEAT_REASON = "auto-run-heartbeat";
3
+ function describeError(err) {
4
+ if (err instanceof Error) {
5
+ return err.message;
6
+ }
7
+ return String(err);
8
+ }
4
9
  export function createServerProgramOrchestration(opts) {
5
- const autoRunHeartbeatProgramByJobId = new Map();
6
10
  const heartbeatPrograms = new HeartbeatProgramRegistry({
7
11
  repoRoot: opts.repoRoot,
8
12
  heartbeatScheduler: opts.heartbeatScheduler,
9
- runHeartbeat: async (runOpts) => {
10
- const result = await opts.controlPlaneProxy.heartbeatRun?.({
11
- jobId: runOpts.jobId ?? null,
12
- rootIssueId: runOpts.rootIssueId ?? null,
13
- reason: runOpts.reason ?? null,
14
- wakeMode: runOpts.wakeMode,
15
- });
16
- return result ?? { ok: false, reason: "not_found" };
17
- },
18
- activityHeartbeat: async (activityOpts) => {
19
- return opts.activitySupervisor.heartbeat({
20
- activityId: activityOpts.activityId ?? null,
21
- reason: activityOpts.reason ?? null,
13
+ dispatchWake: async (wakeOpts) => {
14
+ const wakeResult = await opts.emitOperatorWake({
15
+ dedupeKey: `heartbeat-program:${wakeOpts.programId}`,
16
+ message: `Heartbeat wake: ${wakeOpts.title}`,
17
+ payload: {
18
+ wake_source: "heartbeat_program",
19
+ source_ts_ms: wakeOpts.triggeredAtMs,
20
+ program_id: wakeOpts.programId,
21
+ reason: wakeOpts.reason,
22
+ metadata: wakeOpts.metadata,
23
+ },
22
24
  });
25
+ if (wakeResult.status === "coalesced") {
26
+ return { status: "coalesced", reason: wakeResult.reason };
27
+ }
28
+ if (wakeResult.status === "failed") {
29
+ return { status: "failed", reason: wakeResult.reason };
30
+ }
31
+ return { status: "ok" };
23
32
  },
24
33
  onTickEvent: async (event) => {
25
34
  await opts.eventLog.emit("heartbeat_program.tick", {
@@ -32,44 +41,36 @@ export function createServerProgramOrchestration(opts) {
32
41
  program: event.program,
33
42
  },
34
43
  });
35
- await opts.emitOperatorWake({
36
- dedupeKey: `heartbeat-program:${event.program_id}`,
37
- message: event.message,
38
- payload: {
39
- wake_source: "heartbeat_program",
40
- source_ts_ms: event.ts_ms,
41
- program_id: event.program_id,
42
- status: event.status,
43
- reason: event.reason,
44
- wake_mode: event.program.wake_mode,
45
- target_kind: event.program.target.kind,
46
- target: event.program.target.kind === "run"
47
- ? {
48
- job_id: event.program.target.job_id,
49
- root_issue_id: event.program.target.root_issue_id,
50
- }
51
- : { activity_id: event.program.target.activity_id },
52
- },
53
- });
54
44
  },
55
45
  });
56
46
  const cronPrograms = new CronProgramRegistry({
57
47
  repoRoot: opts.repoRoot,
58
48
  heartbeatScheduler: opts.heartbeatScheduler,
59
- runHeartbeat: async (runOpts) => {
60
- const result = await opts.controlPlaneProxy.heartbeatRun?.({
61
- jobId: runOpts.jobId ?? null,
62
- rootIssueId: runOpts.rootIssueId ?? null,
63
- reason: runOpts.reason ?? null,
64
- wakeMode: runOpts.wakeMode,
65
- });
66
- return result ?? { ok: false, reason: "not_found" };
67
- },
68
- activityHeartbeat: async (activityOpts) => {
69
- return opts.activitySupervisor.heartbeat({
70
- activityId: activityOpts.activityId ?? null,
71
- reason: activityOpts.reason ?? null,
72
- });
49
+ dispatchWake: async (wakeOpts) => {
50
+ try {
51
+ const wakeResult = await opts.emitOperatorWake({
52
+ dedupeKey: `cron-program:${wakeOpts.programId}`,
53
+ message: `Cron wake: ${wakeOpts.title}`,
54
+ payload: {
55
+ wake_source: "cron_program",
56
+ source_ts_ms: wakeOpts.triggeredAtMs,
57
+ program_id: wakeOpts.programId,
58
+ reason: wakeOpts.reason,
59
+ schedule: wakeOpts.schedule,
60
+ metadata: wakeOpts.metadata,
61
+ },
62
+ });
63
+ if (wakeResult.status === "coalesced") {
64
+ return { status: "coalesced", reason: wakeResult.reason };
65
+ }
66
+ if (wakeResult.status === "failed") {
67
+ return { status: "failed", reason: wakeResult.reason };
68
+ }
69
+ return { status: "ok" };
70
+ }
71
+ catch (error) {
72
+ return { status: "failed", reason: describeError(error) };
73
+ }
73
74
  },
74
75
  onLifecycleEvent: async (event) => {
75
76
  await opts.eventLog.emit("cron_program.lifecycle", {
@@ -93,162 +94,10 @@ export function createServerProgramOrchestration(opts) {
93
94
  program: event.program,
94
95
  },
95
96
  });
96
- await opts.emitOperatorWake({
97
- dedupeKey: `cron-program:${event.program_id}`,
98
- message: event.message,
99
- payload: {
100
- wake_source: "cron_program",
101
- source_ts_ms: event.ts_ms,
102
- program_id: event.program_id,
103
- status: event.status,
104
- reason: event.reason,
105
- wake_mode: event.program.wake_mode,
106
- target_kind: event.program.target.kind,
107
- target: event.program.target.kind === "run"
108
- ? {
109
- job_id: event.program.target.job_id,
110
- root_issue_id: event.program.target.root_issue_id,
111
- }
112
- : { activity_id: event.program.target.activity_id },
113
- },
114
- });
115
97
  },
116
98
  });
117
- const findAutoRunHeartbeatProgram = async (jobId) => {
118
- const normalizedJobId = jobId.trim();
119
- if (!normalizedJobId) {
120
- return null;
121
- }
122
- const knownProgramId = autoRunHeartbeatProgramByJobId.get(normalizedJobId);
123
- if (knownProgramId) {
124
- const knownProgram = await heartbeatPrograms.get(knownProgramId);
125
- if (knownProgram) {
126
- return knownProgram;
127
- }
128
- autoRunHeartbeatProgramByJobId.delete(normalizedJobId);
129
- }
130
- const programs = await heartbeatPrograms.list({ targetKind: "run", limit: 500 });
131
- for (const program of programs) {
132
- if (program.metadata.auto_run_job_id !== normalizedJobId) {
133
- continue;
134
- }
135
- autoRunHeartbeatProgramByJobId.set(normalizedJobId, program.program_id);
136
- return program;
137
- }
138
- return null;
139
- };
140
- const registerAutoRunHeartbeatProgram = async (run) => {
141
- if (run.source === "command") {
142
- return;
143
- }
144
- const jobId = run.job_id.trim();
145
- if (!jobId || run.status !== "running") {
146
- return;
147
- }
148
- const rootIssueId = typeof run.root_issue_id === "string" ? run.root_issue_id.trim() : "";
149
- const metadata = {
150
- auto_run_heartbeat: true,
151
- auto_run_job_id: jobId,
152
- auto_run_root_issue_id: rootIssueId || null,
153
- auto_disable_on_terminal: true,
154
- run_mode: run.mode,
155
- run_source: run.source,
156
- };
157
- const existing = await findAutoRunHeartbeatProgram(jobId);
158
- if (existing) {
159
- const result = await heartbeatPrograms.update({
160
- programId: existing.program_id,
161
- title: `Run heartbeat: ${rootIssueId || jobId}`,
162
- target: {
163
- kind: "run",
164
- job_id: jobId,
165
- root_issue_id: rootIssueId || null,
166
- },
167
- enabled: true,
168
- everyMs: opts.autoRunHeartbeatEveryMs,
169
- reason: AUTO_RUN_HEARTBEAT_REASON,
170
- wakeMode: "next_heartbeat",
171
- metadata,
172
- });
173
- if (result.ok && result.program) {
174
- autoRunHeartbeatProgramByJobId.set(jobId, result.program.program_id);
175
- await opts.eventLog.emit("run.auto_heartbeat.lifecycle", {
176
- source: "mu-server.runs",
177
- payload: {
178
- action: "updated",
179
- run_job_id: jobId,
180
- run_root_issue_id: rootIssueId || null,
181
- program_id: result.program.program_id,
182
- program: result.program,
183
- },
184
- });
185
- }
186
- return;
187
- }
188
- const created = await heartbeatPrograms.create({
189
- title: `Run heartbeat: ${rootIssueId || jobId}`,
190
- target: {
191
- kind: "run",
192
- job_id: jobId,
193
- root_issue_id: rootIssueId || null,
194
- },
195
- everyMs: opts.autoRunHeartbeatEveryMs,
196
- reason: AUTO_RUN_HEARTBEAT_REASON,
197
- wakeMode: "next_heartbeat",
198
- metadata,
199
- enabled: true,
200
- });
201
- autoRunHeartbeatProgramByJobId.set(jobId, created.program_id);
202
- await opts.eventLog.emit("run.auto_heartbeat.lifecycle", {
203
- source: "mu-server.runs",
204
- payload: {
205
- action: "registered",
206
- run_job_id: jobId,
207
- run_root_issue_id: rootIssueId || null,
208
- program_id: created.program_id,
209
- program: created,
210
- },
211
- });
212
- };
213
- const disableAutoRunHeartbeatProgram = async (disableOpts) => {
214
- const program = await findAutoRunHeartbeatProgram(disableOpts.jobId);
215
- if (!program) {
216
- return;
217
- }
218
- const metadata = {
219
- ...program.metadata,
220
- auto_disabled_from_status: disableOpts.status,
221
- auto_disabled_reason: disableOpts.reason,
222
- auto_disabled_at_ms: Date.now(),
223
- };
224
- const result = await heartbeatPrograms.update({
225
- programId: program.program_id,
226
- enabled: false,
227
- everyMs: 0,
228
- reason: AUTO_RUN_HEARTBEAT_REASON,
229
- wakeMode: program.wake_mode,
230
- metadata,
231
- });
232
- autoRunHeartbeatProgramByJobId.delete(disableOpts.jobId.trim());
233
- if (!result.ok || !result.program) {
234
- return;
235
- }
236
- await opts.eventLog.emit("run.auto_heartbeat.lifecycle", {
237
- source: "mu-server.runs",
238
- payload: {
239
- action: "disabled",
240
- run_job_id: disableOpts.jobId,
241
- status: disableOpts.status,
242
- reason: disableOpts.reason,
243
- program_id: result.program.program_id,
244
- program: result.program,
245
- },
246
- });
247
- };
248
99
  return {
249
100
  heartbeatPrograms,
250
101
  cronPrograms,
251
- registerAutoRunHeartbeatProgram,
252
- disableAutoRunHeartbeatProgram,
253
102
  };
254
103
  }
@@ -3,7 +3,6 @@ import type { MuConfig } from "./config.js";
3
3
  import type { ControlPlaneHandle } from "./control_plane_contract.js";
4
4
  import type { CronProgramRegistry } from "./cron_programs.js";
5
5
  import type { HeartbeatProgramRegistry } from "./heartbeat_programs.js";
6
- import type { AutoHeartbeatRunSnapshot } from "./server_program_orchestration.js";
7
6
  import type { ServerContext } from "./server.js";
8
7
  export type ServerRoutingDependencies = {
9
8
  context: ServerContext;
@@ -17,15 +16,7 @@ export type ServerRoutingDependencies = {
17
16
  ok: boolean;
18
17
  }>;
19
18
  getControlPlaneStatus: () => unknown;
20
- registerAutoRunHeartbeatProgram: (run: AutoHeartbeatRunSnapshot) => Promise<void>;
21
- disableAutoRunHeartbeatProgram: (opts: {
22
- jobId: string;
23
- status: string;
24
- reason: string;
25
- }) => Promise<void>;
26
19
  describeError: (error: unknown) => string;
27
20
  initiateShutdown?: () => Promise<void>;
28
- publicDir?: string;
29
- mimeTypes?: Record<string, string>;
30
21
  };
31
22
  export declare function createServerRequestHandler(deps: ServerRoutingDependencies): (request: Request) => Promise<Response>;