@agentconnect.md/daemon 1.0.0-rc.38 → 1.0.0-rc.39

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/index.js CHANGED
@@ -9,7 +9,7 @@ import process$1 from "node:process";
9
9
  import { stripVTControlCharacters } from "node:util";
10
10
  import { fileURLToPath } from "node:url";
11
11
  import { createInterface } from "node:readline";
12
- import { freemem, homedir, hostname, loadavg, totalmem, type } from "node:os";
12
+ import { cpus, freemem, homedir, hostname, totalmem, type } from "node:os";
13
13
  import { spawn as spawn$1 } from "child_process";
14
14
  import { Readable, Writable } from "node:stream";
15
15
  import { randomBytes, randomUUID } from "node:crypto";
@@ -7593,6 +7593,19 @@ function cachedRuntimeNames(root) {
7593
7593
  for (const [id, entry] of Object.entries(doc.agents)) if (entry.name) out[id] = entry.name;
7594
7594
  return out;
7595
7595
  }
7596
+ /**
7597
+ * Runtime versions (registry id -> `version`) read from the local cache. Used to
7598
+ * stamp the `facts/runtime-profile` the daemon reports per installed runtime.
7599
+ * Entries with no `version` are omitted (callers fall back to ''). `{}` when no
7600
+ * cached registry doc exists.
7601
+ */
7602
+ function cachedRuntimeVersions(root) {
7603
+ const doc = readCachedDoc(root);
7604
+ if (!doc) return {};
7605
+ const out = {};
7606
+ for (const [id, entry] of Object.entries(doc.agents)) if (entry.version) out[id] = entry.version;
7607
+ return out;
7608
+ }
7596
7609
  async function defaultRuntimes(root, opts = {}) {
7597
7610
  const cached = (opts.mode ?? "blocking") === "cache-first" ? readCachedDoc(root) : null;
7598
7611
  let doc;
@@ -81692,6 +81705,7 @@ var CpClient = class {
81692
81705
  this.heartbeatMs = ok.heartbeatSec > 0 ? ok.heartbeatSec * 1e3 : this.deps.heartbeatDefaultMs;
81693
81706
  this.armHeartbeat();
81694
81707
  this.deps.log.info(`cp: READY (epoch=${this.sessionEpoch}, routingEpoch=${this.routingEpoch})`);
81708
+ for (const profile of this.deps.runtimeProfiles()) this.transport?.send(encode(buildEnvelope("facts/runtime-profile", profile)));
81695
81709
  }
81696
81710
  request(type, payload) {
81697
81711
  const frame = buildEnvelope(type, payload);
@@ -82137,6 +82151,22 @@ function pendingSessionKey(p) {
82137
82151
  channel: p.channel
82138
82152
  };
82139
82153
  }
82154
+ /** Aggregate CPU time across all cores — busy vs idle jiffies. CPU utilization is the
82155
+ * ratio of busy-time DELTAS between two of these samples (a single sample is meaningless;
82156
+ * it's cumulative since boot). This is real utilization, NOT the run-queue load average. */
82157
+ function cpuTotals() {
82158
+ let idle = 0;
82159
+ let busy = 0;
82160
+ for (const c of cpus()) {
82161
+ const t = c.times;
82162
+ idle += t.idle;
82163
+ busy += t.user + t.nice + t.sys + t.irq;
82164
+ }
82165
+ return {
82166
+ idle,
82167
+ busy
82168
+ };
82169
+ }
82140
82170
  var Daemon = class {
82141
82171
  opts;
82142
82172
  store;
@@ -82155,8 +82185,10 @@ var Daemon = class {
82155
82185
  cfg;
82156
82186
  log = makeLogger("info");
82157
82187
  root = "";
82188
+ lastCpu = cpuTotals();
82158
82189
  runtimes = {};
82159
82190
  runtimeNames = {};
82191
+ runtimeVersions = {};
82160
82192
  cpClient;
82161
82193
  cpCrons;
82162
82194
  cpAgents;
@@ -82202,6 +82234,7 @@ var Daemon = class {
82202
82234
  });
82203
82235
  this.runtimes = installedRuntimes(resolvedRuntimes);
82204
82236
  this.runtimeNames = cachedRuntimeNames(root);
82237
+ this.runtimeVersions = cachedRuntimeVersions(root);
82205
82238
  this.log.info(`runtimes ready: ${Object.keys(this.runtimes).join(", ") || "(none)"}`);
82206
82239
  const skipped = Object.keys(resolvedRuntimes).filter((id) => !this.runtimes[id]);
82207
82240
  if (skipped.length) this.log.info(`runtimes not installed (skipped): ${skipped.join(", ")}`);
@@ -83067,6 +83100,17 @@ var Daemon = class {
83067
83100
  };
83068
83101
  this.onInbound(msg);
83069
83102
  }
83103
+ /** Real CPU utilization (0..1) across all cores since the previous call — the busy
83104
+ * fraction of the time delta. Called once per heartbeat, so it reflects load over the
83105
+ * heartbeat interval (like a system monitor), not the run-queue load average. */
83106
+ cpuUtilization() {
83107
+ const now = cpuTotals();
83108
+ const idle = now.idle - this.lastCpu.idle;
83109
+ const busy = now.busy - this.lastCpu.busy;
83110
+ this.lastCpu = now;
83111
+ const total = idle + busy;
83112
+ return total > 0 ? Math.min(1, Math.max(0, busy / total)) : 0;
83113
+ }
83070
83114
  startCpClient(root) {
83071
83115
  const cp = this.cfg.controlPlane;
83072
83116
  if (!cp?.enabled || !cp.url || !cp.key) {
@@ -83095,13 +83139,20 @@ var Daemon = class {
83095
83139
  acp: true,
83096
83140
  features: []
83097
83141
  }),
83142
+ runtimeProfiles: () => Object.keys(this.runtimes).map((id) => ({
83143
+ runtime: id,
83144
+ version: this.runtimeVersions[id] ?? "",
83145
+ models: [],
83146
+ acpSupport: "full",
83147
+ toolCalling: true
83148
+ })),
83098
83149
  localState: () => ({
83099
83150
  assignments: [],
83100
83151
  crons: this.cpCrons?.ids() ?? [],
83101
83152
  leases: []
83102
83153
  }),
83103
83154
  loadSnapshot: () => ({
83104
- cpu: loadavg()[0] ?? 0,
83155
+ cpu: this.cpuUtilization(),
83105
83156
  mem: totalmem() > 0 ? 1 - freemem() / totalmem() : 0,
83106
83157
  agents: this.hosts.size
83107
83158
  }),