@nelsonlongxiang/dsh-open-a2a-net 0.5.14 → 0.5.15

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/lib/index.js CHANGED
@@ -38,6 +38,7 @@ export const Config = s.object({
38
38
  dshHome: s.string().default(''),
39
39
  sessionNodes: s.boolean().default(true),
40
40
  wakeJoinedOnBoot: s.boolean().default(false),
41
+ wakeBootStaggerMs: s.number().default(3_000),
41
42
  cardTtlMs: s.number().default(172_800_000),
42
43
  flushTimeoutMs: s.number().default(300_000),
43
44
  routeTimeoutMs: s.number().default(1_800_000),
@@ -464,13 +465,31 @@ export function apply(ctx, config) {
464
465
  logger.warn('wakeJoinedOnBoot is on but no api gateway is composed; cold joined sessions stay asleep');
465
466
  return;
466
467
  }
468
+ // Serial with a configurable pause: one full log replay at a time
469
+ // keeps the decode from saturating the event loop (concurrent wakes
470
+ // of several huge logs stalled every request for tens of seconds).
471
+ // The first wake starts immediately; the re-check drops ids another
472
+ // path (wake-on-route, a manual open) already materialized.
473
+ let bootWakeChain = Promise.resolve();
474
+ let firstBootWake = true;
467
475
  for (const id of joinedSessions.list()) {
468
476
  if (liveRoots.has(id))
469
477
  continue;
470
478
  // The remount listener joins the node the moment the woken agent
471
479
  // publishes; a failed wake keeps the cold row and its intent.
472
- materialize(id)?.catch((error) => {
473
- logger.warn(`boot wake of ${id} failed: ${String(error)}`);
480
+ const pauseMs = firstBootWake ? 0 : config.wakeBootStaggerMs;
481
+ firstBootWake = false;
482
+ bootWakeChain = bootWakeChain.then(async () => {
483
+ if (pauseMs > 0)
484
+ await new Promise(resolve => setTimeout(resolve, pauseMs));
485
+ if (liveRoots.has(id))
486
+ return;
487
+ try {
488
+ await materialize(id);
489
+ }
490
+ catch (error) {
491
+ logger.warn(`boot wake of ${id} failed: ${String(error)}`);
492
+ }
474
493
  });
475
494
  }
476
495
  };
@@ -89,6 +89,15 @@ export interface Config {
89
89
  * the sidebar's wake button remain available).
90
90
  */
91
91
  readonly wakeJoinedOnBoot: boolean;
92
+ /**
93
+ * Pause between consecutive boot wakes. Each wake replays a full session
94
+ * log — the zstd decode yields the event loop only every 500ms — so
95
+ * unbounded concurrent wakes of several huge logs starve every request
96
+ * for tens of seconds after a restart. The serial queue with this pause
97
+ * keeps the preheat while capping decode saturation: the first wake
98
+ * starts immediately, and wake-on-route never waits on this queue.
99
+ */
100
+ readonly wakeBootStaggerMs: number;
92
101
  /**
93
102
  * `final` reply budget: how long an inbound direct route waits for the
94
103
  * session's next assistant message before answering with a timeout
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nelsonlongxiang/dsh-open-a2a-net",
3
- "version": "0.5.14",
3
+ "version": "0.5.15",
4
4
  "description": "Open A2A network plugin for DeepSeek Harness: signed agent cards, decentralized peer/zone discovery, direct routing model tools, and joinable session nodes with a sidebar control",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",