@algosuite/vo-mcp 0.2.0-beta.63 → 0.2.0-beta.65

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.
@@ -61,6 +61,67 @@ async function fetchInstallationToken({ req, required = false, readOnly = false,
61
61
  }
62
62
  }
63
63
 
64
+ // ../../scripts/virtual-office/code-runner/control-plane-heartbeat-body.mjs
65
+ function buildRunnerHeartbeatBody({
66
+ runnerId: runnerId2,
67
+ runnerInstanceId,
68
+ operatorId,
69
+ uptimeSec,
70
+ activeTasks,
71
+ maxConcurrency,
72
+ effectiveConcurrency,
73
+ measuredTaskSlots,
74
+ measuredCpuSlots,
75
+ measuredMemorySlots,
76
+ version,
77
+ daemonVersion,
78
+ nodeVersion,
79
+ defaultAgent,
80
+ supervisorInstanceId: supervisorInstanceId2,
81
+ supervisorVersion: supervisorVersion2,
82
+ supervisorCapabilities,
83
+ servedRepos,
84
+ servedOperators,
85
+ availableAgents,
86
+ accountUsage,
87
+ availableLocalModels,
88
+ prepared_job_shadow: preparedJobShadow
89
+ } = {}) {
90
+ const body = { runner_id: runnerId2, ...preparedJobShadow ? { prepared_job_shadow: preparedJobShadow } : {} };
91
+ if (runnerInstanceId) body.runner_instance_id = runnerInstanceId;
92
+ if (operatorId) body.operator_id = operatorId;
93
+ if (typeof uptimeSec === "number") body.uptime_sec = uptimeSec;
94
+ if (typeof activeTasks === "number") body.active_tasks = activeTasks;
95
+ if (typeof maxConcurrency === "number") body.max_concurrency = maxConcurrency;
96
+ if (typeof effectiveConcurrency === "number") body.effective_concurrency = effectiveConcurrency;
97
+ if (typeof measuredTaskSlots === "number") body.measured_task_slots = measuredTaskSlots;
98
+ if (typeof measuredCpuSlots === "number") body.measured_cpu_slots = measuredCpuSlots;
99
+ if (typeof measuredMemorySlots === "number") body.measured_memory_slots = measuredMemorySlots;
100
+ if (version) body.version = version;
101
+ if (daemonVersion) body.daemon_version = daemonVersion;
102
+ if (nodeVersion) body.node_version = nodeVersion;
103
+ if (defaultAgent) body.default_agent = defaultAgent;
104
+ if (supervisorInstanceId2) body.supervisor_instance_id = supervisorInstanceId2;
105
+ if (supervisorVersion2) body.supervisor_version = supervisorVersion2;
106
+ if (Array.isArray(supervisorCapabilities) && supervisorCapabilities.length > 0) {
107
+ body.supervisor_capabilities = supervisorCapabilities;
108
+ }
109
+ if (Array.isArray(servedRepos) && servedRepos.length > 0) body.served_repos = servedRepos;
110
+ if (Array.isArray(servedOperators) && servedOperators.length > 0) {
111
+ body.served_operator_ids = servedOperators;
112
+ }
113
+ if (Array.isArray(availableAgents) && availableAgents.length > 0) {
114
+ body.available_agents = availableAgents;
115
+ }
116
+ if (Array.isArray(accountUsage) && accountUsage.length > 0) {
117
+ body.account_usage = accountUsage;
118
+ }
119
+ if (Array.isArray(availableLocalModels) && availableLocalModels.length > 0) {
120
+ body.available_local_models = availableLocalModels;
121
+ }
122
+ return body;
123
+ }
124
+
64
125
  // ../../scripts/virtual-office/code-runner/control-plane-promote.mjs
65
126
  async function promoteDraftPrRequest(req, prNumber, automationContext, onUnauthorized = () => {
66
127
  }) {
@@ -675,38 +736,8 @@ function createControlPlaneClient({
675
736
  * authenticated operator so the web shows a TRUE "runner online" signal.
676
737
  * Best-effort caller; throws on 401/non-ok so the daemon can log + retry.
677
738
  */
678
- async postHeartbeat({ runnerId: runnerId3, runnerInstanceId: runnerInstanceId2, operatorId, uptimeSec, activeTasks, maxConcurrency, effectiveConcurrency, measuredTaskSlots, measuredCpuSlots, measuredMemorySlots, version, daemonVersion, defaultAgent, supervisorInstanceId: supervisorInstanceId2, supervisorVersion: supervisorVersion2, supervisorCapabilities, servedRepos, servedOperators, availableAgents, accountUsage, availableLocalModels, prepared_job_shadow: preparedJobShadow }) {
679
- const body = { runner_id: runnerId3, ...preparedJobShadow ? { prepared_job_shadow: preparedJobShadow } : {} };
680
- if (runnerInstanceId2) body.runner_instance_id = runnerInstanceId2;
681
- if (operatorId) body.operator_id = operatorId;
682
- if (typeof uptimeSec === "number") body.uptime_sec = uptimeSec;
683
- if (typeof activeTasks === "number") body.active_tasks = activeTasks;
684
- if (typeof maxConcurrency === "number") body.max_concurrency = maxConcurrency;
685
- if (typeof effectiveConcurrency === "number") body.effective_concurrency = effectiveConcurrency;
686
- if (typeof measuredTaskSlots === "number") body.measured_task_slots = measuredTaskSlots;
687
- if (typeof measuredCpuSlots === "number") body.measured_cpu_slots = measuredCpuSlots;
688
- if (typeof measuredMemorySlots === "number") body.measured_memory_slots = measuredMemorySlots;
689
- if (version) body.version = version;
690
- if (daemonVersion) body.daemon_version = daemonVersion;
691
- if (defaultAgent) body.default_agent = defaultAgent;
692
- if (supervisorInstanceId2) body.supervisor_instance_id = supervisorInstanceId2;
693
- if (supervisorVersion2) body.supervisor_version = supervisorVersion2;
694
- if (Array.isArray(supervisorCapabilities) && supervisorCapabilities.length > 0) {
695
- body.supervisor_capabilities = supervisorCapabilities;
696
- }
697
- if (Array.isArray(servedRepos) && servedRepos.length > 0) body.served_repos = servedRepos;
698
- if (Array.isArray(servedOperators) && servedOperators.length > 0) {
699
- body.served_operator_ids = servedOperators;
700
- }
701
- if (Array.isArray(availableAgents) && availableAgents.length > 0) {
702
- body.available_agents = availableAgents;
703
- }
704
- if (Array.isArray(accountUsage) && accountUsage.length > 0) {
705
- body.account_usage = accountUsage;
706
- }
707
- if (Array.isArray(availableLocalModels) && availableLocalModels.length > 0) {
708
- body.available_local_models = availableLocalModels;
709
- }
739
+ async postHeartbeat(heartbeat) {
740
+ const body = buildRunnerHeartbeatBody(heartbeat);
710
741
  const res = await req("POST", "/api/v1/runner/heartbeat", body, {
711
742
  timeoutMs: heartbeatTimeoutMs
712
743
  });
@@ -2966,22 +2997,33 @@ var terminatedChildren = /* @__PURE__ */ new WeakSet();
2966
2997
  function attachSupervisorChildTerminationCustody(target, onTerminated, onObservedError = () => {
2967
2998
  }) {
2968
2999
  let accounted = false;
2969
- const account = (kind, error = null) => {
3000
+ const account = (kind, { error = null, code = null, signal = null } = {}) => {
2970
3001
  terminatedChildren.add(target);
2971
3002
  if (accounted) return false;
2972
3003
  accounted = true;
2973
- onTerminated(Object.freeze({ target, kind, error }));
3004
+ onTerminated(Object.freeze({ target, kind, error, code, signal }));
2974
3005
  return true;
2975
3006
  };
2976
3007
  target.on("error", (error) => {
2977
3008
  onObservedError(error);
2978
- if (target.pid === void 0 || target.pid === null) account("error", error);
3009
+ if (target.pid === void 0 || target.pid === null) account("error", { error });
2979
3010
  });
2980
- target.on("exit", () => {
2981
- account("exit");
3011
+ target.on("exit", (code, signal) => {
3012
+ account("exit", { code: code ?? null, signal: signal ?? null });
2982
3013
  });
2983
3014
  return Object.freeze({ accounted: () => accounted });
2984
3015
  }
3016
+ function describeChildTermination(record, runtime = process.version) {
3017
+ if (!record || typeof record !== "object") return `unknown termination on Node ${runtime}`;
3018
+ if (record.kind === "error") {
3019
+ const detail = record.error instanceof Error ? record.error.message : String(record.error ?? "no detail");
3020
+ return `spawn error on Node ${runtime}: ${detail}`;
3021
+ }
3022
+ if (record.signal) return `killed by ${record.signal} on Node ${runtime}`;
3023
+ if (record.code === 0) return `exited cleanly (code 0) on Node ${runtime}`;
3024
+ if (record.code === null) return `exited with no reported code or signal on Node ${runtime}`;
3025
+ return `exited with code ${record.code} on Node ${runtime}`;
3026
+ }
2985
3027
  function supervisorChildHasExited(target) {
2986
3028
  return terminatedChildren.has(target) || target.exitCode !== null || (target.signalCode ?? null) !== null;
2987
3029
  }
@@ -3440,13 +3482,14 @@ async function main() {
3440
3482
  });
3441
3483
  attachSupervisorChildTerminationCustody(
3442
3484
  next,
3443
- () => {
3485
+ (record) => {
3444
3486
  if (stopping || expectedChildStops.delete(next)) {
3445
3487
  readinessDeferrals.forget(next);
3446
3488
  return;
3447
3489
  }
3448
3490
  if (captureChildReadinessDeferral(next)) return;
3449
3491
  readinessDeferrals.forget(next);
3492
+ console.error(`[vo-runner supervisor] child ${describeChildTermination(record)}`);
3450
3493
  const decision = respawnCircuit.recordExit(startedAt, Date.now());
3451
3494
  if (decision.tripped) {
3452
3495
  markSupervisorDegraded();