@agentconnect.md/daemon 1.0.0-rc.60 → 1.0.0-rc.62

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
@@ -7595,7 +7595,7 @@ function cachedRuntimeNames(root) {
7595
7595
  }
7596
7596
  /**
7597
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.
7598
+ * stamp each entry of the `facts/daemon-runtimes` snapshot the daemon reports.
7599
7599
  * Entries with no `version` are omitted (callers fall back to ''). `{}` when no
7600
7600
  * cached registry doc exists.
7601
7601
  */
@@ -13254,6 +13254,74 @@ const SessionHistoryPage = object({
13254
13254
  nextCursor: string().optional()
13255
13255
  });
13256
13256
  //#endregion
13257
+ //#region ../protocol/dist/frames/telemetry.js
13258
+ /**
13259
+ * Telemetry & facts (D→C) — protocol §7.
13260
+ *
13261
+ * The dashboard's real-time source. `event/session` is the converged milestone
13262
+ * feed (NOT the message stream); `facts/daemon-runtimes` is the observed runtime
13263
+ * capability feed; `heartbeat` drives the watchdog.
13264
+ */
13265
+ const Heartbeat = object({
13266
+ load: object({
13267
+ cpu: number(),
13268
+ mem: number(),
13269
+ agents: number().int()
13270
+ }),
13271
+ health: _enum(["ok", "degraded"]),
13272
+ activeSessions: number().int(),
13273
+ degradedScopes: array(string()).default([])
13274
+ });
13275
+ /** Converged session lifecycle milestone — protocol §7.2. NOT the message stream. */
13276
+ const EventSession = object({
13277
+ sessionId: string().uuid(),
13278
+ agentId: string().uuid(),
13279
+ launchId: string().uuid(),
13280
+ phase: _enum([
13281
+ "start",
13282
+ "plan",
13283
+ "problem",
13284
+ "end"
13285
+ ]),
13286
+ link: string().optional(),
13287
+ summary: string().optional(),
13288
+ ts: string().datetime()
13289
+ });
13290
+ /**
13291
+ * Per-session token-usage report — D→C EVT. The daemon meters usage from the
13292
+ * agent's ACP stream and reports the session's CUMULATIVE snapshot (latest-wins)
13293
+ * so the CP can persist it for the console's historical usage aggregates. This is
13294
+ * dashboard metadata (token counts + cost), never the message stream. Idempotent
13295
+ * by `sessionId`: re-sending the same snapshot is a no-op upsert on the CP.
13296
+ */
13297
+ const UsageReport = object({
13298
+ sessionId: string(),
13299
+ agentId: string().uuid(),
13300
+ platform: string().optional(),
13301
+ channel: string().optional(),
13302
+ lastActivityAt: string(),
13303
+ usage: SessionUsage
13304
+ });
13305
+ /**
13306
+ * Observed capabilities of an installed runtime — protocol §7.3. The element
13307
+ * type of the `facts/daemon-runtimes` snapshot. As a standalone per-runtime
13308
+ * frame (`facts/runtime-profile`, upsert-only) it is DEPRECATED: current
13309
+ * daemons report the full snapshot instead; the CP keeps accepting the old
13310
+ * frame from older daemons.
13311
+ */
13312
+ const FactsRuntimeProfile = object({
13313
+ runtime: string(),
13314
+ version: string(),
13315
+ models: array(string()),
13316
+ contextWindow: number().int().optional(),
13317
+ acpSupport: _enum([
13318
+ "full",
13319
+ "partial",
13320
+ "none"
13321
+ ]),
13322
+ toolCalling: boolean()
13323
+ });
13324
+ //#endregion
13257
13325
  //#region ../protocol/dist/frame.js
13258
13326
  /**
13259
13327
  * The single source of truth for the wire: `type` string → payload zod schema.
@@ -13271,16 +13339,7 @@ const FRAME_SCHEMAS = {
13271
13339
  "auth/ok": AuthOk,
13272
13340
  register: RegisterReq,
13273
13341
  "register/ok": RegisterOk,
13274
- heartbeat: object({
13275
- load: object({
13276
- cpu: number(),
13277
- mem: number(),
13278
- agents: number().int()
13279
- }),
13280
- health: _enum(["ok", "degraded"]),
13281
- activeSessions: number().int(),
13282
- degradedScopes: array(string()).default([])
13283
- }),
13342
+ heartbeat: Heartbeat,
13284
13343
  "agent/launch": AgentLaunch,
13285
13344
  "agent/launched": AgentLaunched,
13286
13345
  "agent/stop": AgentStop,
@@ -13306,40 +13365,10 @@ const FRAME_SCHEMAS = {
13306
13365
  "secrets/renew": SecretsRenew,
13307
13366
  "secrets/revoke": SecretsRevoke,
13308
13367
  "scope-attestation": ScopeAttestation,
13309
- "event/session": object({
13310
- sessionId: string().uuid(),
13311
- agentId: string().uuid(),
13312
- launchId: string().uuid(),
13313
- phase: _enum([
13314
- "start",
13315
- "plan",
13316
- "problem",
13317
- "end"
13318
- ]),
13319
- link: string().optional(),
13320
- summary: string().optional(),
13321
- ts: string().datetime()
13322
- }),
13323
- "usage/report": object({
13324
- sessionId: string(),
13325
- agentId: string().uuid(),
13326
- platform: string().optional(),
13327
- channel: string().optional(),
13328
- lastActivityAt: string(),
13329
- usage: SessionUsage
13330
- }),
13331
- "facts/runtime-profile": object({
13332
- runtime: string(),
13333
- version: string(),
13334
- models: array(string()),
13335
- contextWindow: number().int().optional(),
13336
- acpSupport: _enum([
13337
- "full",
13338
- "partial",
13339
- "none"
13340
- ]),
13341
- toolCalling: boolean()
13342
- }),
13368
+ "event/session": EventSession,
13369
+ "usage/report": UsageReport,
13370
+ "facts/runtime-profile": FactsRuntimeProfile,
13371
+ "facts/daemon-runtimes": object({ runtimes: array(FactsRuntimeProfile) }),
13343
13372
  "session/list": SessionListReq,
13344
13373
  "session/list/page": SessionListPage,
13345
13374
  "session/history": SessionHistoryReq,
@@ -13434,6 +13463,7 @@ discriminatedUnion("type", [
13434
13463
  frame("event/session", FRAME_SCHEMAS["event/session"]),
13435
13464
  frame("usage/report", FRAME_SCHEMAS["usage/report"]),
13436
13465
  frame("facts/runtime-profile", FRAME_SCHEMAS["facts/runtime-profile"]),
13466
+ frame("facts/daemon-runtimes", FRAME_SCHEMAS["facts/daemon-runtimes"]),
13437
13467
  frame("session/list", FRAME_SCHEMAS["session/list"]),
13438
13468
  frame("session/list/page", FRAME_SCHEMAS["session/list/page"]),
13439
13469
  frame("session/history", FRAME_SCHEMAS["session/history"]),
@@ -81880,13 +81910,14 @@ async function probeRuntime(id, rt, cwd, opts = {}) {
81880
81910
  return host.modelOptions();
81881
81911
  };
81882
81912
  try {
81883
- const models = await Promise.race([run(), timeout]);
81884
- opts.log?.info(`probe: ${id} ok (models: ${models?.models.length ? models.models.join(", ") : "none advertised"})`);
81913
+ const opt = await Promise.race([run(), timeout]);
81914
+ const models = (opt?.models ?? []).filter((m) => m !== "default");
81915
+ opts.log?.info(`probe: ${id} ok (models: ${models.length ? models.join(", ") : "none advertised"})`);
81885
81916
  return {
81886
81917
  runtime: id,
81887
81918
  ok: true,
81888
- models: models?.models ?? [],
81889
- currentModel: models?.current
81919
+ models,
81920
+ currentModel: opt?.current
81890
81921
  };
81891
81922
  } catch (err) {
81892
81923
  const error = err.message;
@@ -82136,17 +82167,19 @@ var CpClient = class {
82136
82167
  this.heartbeatMs = ok.heartbeatSec > 0 ? ok.heartbeatSec * 1e3 : this.deps.heartbeatDefaultMs;
82137
82168
  this.armHeartbeat();
82138
82169
  this.deps.log.info(`cp: READY (epoch=${this.sessionEpoch}, routingEpoch=${this.routingEpoch})`);
82139
- for (const profile of this.deps.runtimeProfiles()) this.emitRuntimeProfile(profile);
82170
+ this.emitDaemonRuntimes(this.deps.runtimeProfiles());
82140
82171
  this.deps.onReady?.();
82141
82172
  }
82142
82173
  /**
82143
- * Push a single runtime profile mid-session (D→C EVT, fire-and-forget). No-op
82144
- * unless connected and READY/DRAINING — the CP only accepts control frames
82145
- * there, and a reconnect's handshake re-emits the latest profiles anyway.
82174
+ * Push the full runtime snapshot (D→C `facts/daemon-runtimes` EVT,
82175
+ * fire-and-forget) — sent on each register and again when a probe sweep
82176
+ * completes. REPLACE semantics on the CP: it reconciles the daemon's stored
82177
+ * runtime list to exactly this snapshot, pruning runtimes that are no longer
82178
+ * installed. No-op unless READY/DRAINING.
82146
82179
  */
82147
- emitRuntimeProfile(profile) {
82180
+ emitDaemonRuntimes(runtimes) {
82148
82181
  if (this.state !== "READY" && this.state !== "DRAINING") return;
82149
- this.transport?.send(encode(buildEnvelope("facts/runtime-profile", profile)));
82182
+ this.transport?.send(encode(buildEnvelope("facts/daemon-runtimes", { runtimes })));
82150
82183
  }
82151
82184
  /**
82152
82185
  * Report a session's cumulative token usage (D→C `usage/report` EVT,
@@ -83900,8 +83933,9 @@ var Daemon = class Daemon {
83900
83933
  this.cpClient.start();
83901
83934
  this.log.info(`cp: connecting to ${url}…`);
83902
83935
  }
83903
- /** Build the current `facts/runtime-profile` for a runtime, folding in any
83904
- * models learned by the probe sweep. */
83936
+ /** Build the current profile entry for a runtime (one element of the
83937
+ * `facts/daemon-runtimes` snapshot), folding in any models learned by the
83938
+ * probe sweep. */
83905
83939
  runtimeProfileFor(id) {
83906
83940
  return {
83907
83941
  runtime: id,
@@ -83916,8 +83950,8 @@ var Daemon = class Daemon {
83916
83950
  static PROBE_TTL_MS = 5 * 6e4;
83917
83951
  /**
83918
83952
  * Probe every installed runtime in the background (launch → initialize →
83919
- * session/new → read models → tear down), then emit a refreshed
83920
- * `facts/runtime-profile` per runtime once the whole sweep completes.
83953
+ * session/new → read models → tear down), then emit one `facts/daemon-runtimes`
83954
+ * snapshot once the whole sweep completes so the CP replaces its runtime list.
83921
83955
  *
83922
83956
  * Triggered on each CP (re)connect. Deduped while in flight; skipped (with a
83923
83957
  * cached re-emit) when the last sweep is still fresh, so a reconnect storm can't
@@ -83930,7 +83964,7 @@ var Daemon = class Daemon {
83930
83964
  if (ids.length === 0) return;
83931
83965
  if (this.probing) return;
83932
83966
  if (this.lastProbeAtMs > 0 && Date.now() - this.lastProbeAtMs < Daemon.PROBE_TTL_MS) {
83933
- for (const id of ids) this.cpClient?.emitRuntimeProfile(this.runtimeProfileFor(id));
83967
+ this.cpClient?.emitDaemonRuntimes(ids.map((id) => this.runtimeProfileFor(id)));
83934
83968
  return;
83935
83969
  }
83936
83970
  this.probing = true;
@@ -83941,7 +83975,7 @@ var Daemon = class Daemon {
83941
83975
  this.lastProbeAtMs = Date.now();
83942
83976
  const okCount = results.filter((r) => r.ok).length;
83943
83977
  this.log.info(`probe: sweep complete — ${okCount}/${results.length} runtime(s) reachable`);
83944
- for (const id of ids) this.cpClient?.emitRuntimeProfile(this.runtimeProfileFor(id));
83978
+ this.cpClient?.emitDaemonRuntimes(ids.map((id) => this.runtimeProfileFor(id)));
83945
83979
  } catch (err) {
83946
83980
  this.log.warn(`probe: sweep failed: ${formatErr(err)}`);
83947
83981
  } finally {