@masons/agent-network 0.5.321 → 0.5.322

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.
@@ -7,11 +7,13 @@ import type { ControlAck } from "./control-event-types.js";
7
7
  import { type EndpointState } from "./endpoint-state-machine.js";
8
8
  import type { BrokerLogger } from "./logger.js";
9
9
  import { type NetworkPresence } from "./network-presence.js";
10
+ import type { NetworkPresenceChangedEvent } from "./network-presence-changed-event-types.js";
10
11
  import type { BrokerPaths } from "./paths.js";
11
12
  import { type BufferedMessage } from "./reconnecting-buffer.js";
12
13
  import type { RuntimeEndpointPort } from "./runtime-endpoint-port.js";
13
14
  import type { ServicesEventClient } from "./services-event-client.js";
14
15
  import type { SpawnDriverRegistry } from "./spawn-driver.js";
16
+ import { type UndispatchedChangedEvent } from "./undispatched-changed-event-types.js";
15
17
  import { type UndispatchedInbox } from "./undispatched-inbox.js";
16
18
  export interface BrokerDaemonOptions {
17
19
  paths: BrokerPaths;
@@ -37,6 +39,16 @@ export interface BrokerDaemonOptions {
37
39
  postControlAck?: (ack: ControlAck) => Promise<void>;
38
40
  replyCorrelationTtlMs?: number;
39
41
  replyCorrelationCapPerEndpoint?: number;
42
+ undispatchedChangedPost?: (event: UndispatchedChangedEvent) => Promise<import("./runtime-endpoint-port.js").EmitOutcome>;
43
+ undispatchedChangedCapacity?: number;
44
+ undispatchedChangedBackoffInitialMs?: number;
45
+ undispatchedChangedBackoffMaxMs?: number;
46
+ undispatchedChangedMaxRetries?: number;
47
+ networkPresenceChangedPost?: (event: NetworkPresenceChangedEvent) => Promise<import("./runtime-endpoint-port.js").EmitOutcome>;
48
+ networkPresenceChangedCapacity?: number;
49
+ networkPresenceChangedBackoffInitialMs?: number;
50
+ networkPresenceChangedBackoffMaxMs?: number;
51
+ networkPresenceChangedMaxRetries?: number;
40
52
  }
41
53
  export interface RunningBroker {
42
54
  bearerToken: string;
@@ -50,6 +62,8 @@ export interface RunningBroker {
50
62
  pendingSpawnCount(): number;
51
63
  retryQueueSize(): number;
52
64
  replyCorrelationCacheSize(endpoint_id: string): number;
65
+ undispatchedChangedQueueSize(): number;
66
+ networkPresenceChangedQueueSize(): number;
53
67
  }
54
68
  export declare function startBrokerDaemon(opts: BrokerDaemonOptions): Promise<RunningBroker>;
55
69
  export declare function readPluginPidHeader(req: IncomingMessage): number | null;
@@ -1 +1 @@
1
- {"version":3,"file":"broker-daemon.d.ts","sourceRoot":"","sources":["../../src/broker/broker-daemon.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"broker-daemon.d.ts","sourceRoot":"","sources":["../../src/broker/broker-daemon.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ import { DEFAULT_GRACE_MS, transition, } from "./endpoint-state-machine.js";
7
7
  import { createGraceTimerManager } from "./grace-timer.js";
8
8
  import { BrokerHttpError, pushToPlugin, startIPCServer, } from "./ipc-server.js";
9
9
  import { transitionPresence, } from "./network-presence.js";
10
+ import { createNetworkPresenceEmitter, postNetworkPresenceChangedViaPort, } from "./network-presence-emitter.js";
10
11
  import { isPluginAlive as defaultIsPluginAlive } from "./plugin-liveness.js";
11
12
  import { createReceivedMessageCorrelationCache, DEFAULT_TTL_MS as DEFAULT_REPLY_CORRELATION_TTL_MS, } from "./received-message-correlation-cache.js";
12
13
  import { createReconnectingBufferManager, } from "./reconnecting-buffer.js";
@@ -14,6 +15,8 @@ import { RoutingTable } from "./routing-table.js";
14
15
  import { createSpawnCorrelationManager, createSpawnRateLimiter, } from "./spawn-correlation.js";
15
16
  import { TASK_HINT_MAX_LENGTH, updateTaskHint } from "./task-hint-handler.js";
16
17
  import { createTransitionStateRetryQueue } from "./transition-state-retry-queue.js";
18
+ import { CONTENT_PREVIEW_MAX_CODEPOINTS, truncateContentPreview, } from "./undispatched-changed-event-types.js";
19
+ import { createUndispatchedChangedEmitter, postUndispatchedChangedViaPort, } from "./undispatched-emitter.js";
17
20
  import { createUndispatchedInbox, } from "./undispatched-inbox.js";
18
21
  export async function startBrokerDaemon(opts) {
19
22
  const { paths, asNodeId: _asNodeIdReservedForA3, connector, apiPort, logger, closedEndpointLookup, livenessProbe = defaultIsPluginAlive, spawnDriverRegistry, spawnFn = spawnChild, servicesEventClientFactory, } = opts;
@@ -69,6 +72,25 @@ export async function startBrokerDaemon(opts) {
69
72
  }
70
73
  }, replyCorrelationSweepInterval);
71
74
  replyCorrelationSweepTimer.unref?.();
75
+ const undispatchedEmitter = createUndispatchedChangedEmitter(opts.undispatchedChangedPost ?? postUndispatchedChangedViaPort(apiPort), logger, {
76
+ capacity: opts.undispatchedChangedCapacity,
77
+ backoffInitialMs: opts.undispatchedChangedBackoffInitialMs,
78
+ backoffMaxMs: opts.undispatchedChangedBackoffMaxMs,
79
+ maxRetries: opts.undispatchedChangedMaxRetries,
80
+ });
81
+ const emitUndispatched = (event) => {
82
+ undispatchedEmitter.enqueue(event);
83
+ };
84
+ const networkPresenceEmitter = createNetworkPresenceEmitter(opts.networkPresenceChangedPost ??
85
+ postNetworkPresenceChangedViaPort(apiPort), logger, {
86
+ capacity: opts.networkPresenceChangedCapacity,
87
+ backoffInitialMs: opts.networkPresenceChangedBackoffInitialMs,
88
+ backoffMaxMs: opts.networkPresenceChangedBackoffMaxMs,
89
+ maxRetries: opts.networkPresenceChangedMaxRetries,
90
+ });
91
+ const emitNetworkPresence = (event) => {
92
+ networkPresenceEmitter.enqueue(event);
93
+ };
72
94
  const recordInboundCorrelation = (endpoint_id, metadata) => {
73
95
  const c = metadata && typeof metadata.correlation_id === "string"
74
96
  ? metadata.correlation_id
@@ -107,6 +129,13 @@ export async function startBrokerDaemon(opts) {
107
129
  presence: effect.presence,
108
130
  reason: effect.reason,
109
131
  });
132
+ emitNetworkPresence({
133
+ type: "network_presence_changed",
134
+ version: 1,
135
+ state: effect.presence,
136
+ ts: Date.now(),
137
+ reason: effect.reason,
138
+ });
110
139
  if (effect.presence === "online") {
111
140
  void retryQueue.flush(async (entry) => {
112
141
  await apiPort.transitionState(entry.endpoint_id, entry.params);
@@ -222,6 +251,13 @@ export async function startBrokerDaemon(opts) {
222
251
  inbox_size: undispatchedInbox.size(),
223
252
  inbox_capacity: undispatchedInbox.capacity(),
224
253
  });
254
+ emitUndispatched({
255
+ type: "undispatched_changed",
256
+ version: 1,
257
+ action: "remove",
258
+ undispatched_id: event.undispatched_id,
259
+ remove_reason: "lost_at_capacity_during_redispatch_bounce",
260
+ });
225
261
  }
226
262
  return {
227
263
  ok: false,
@@ -261,6 +297,13 @@ export async function startBrokerDaemon(opts) {
261
297
  target_endpoint_id: event.target_endpoint_id,
262
298
  target_state: target.state,
263
299
  });
300
+ emitUndispatched({
301
+ type: "undispatched_changed",
302
+ version: 1,
303
+ action: "dispatch",
304
+ undispatched_id: event.undispatched_id,
305
+ dispatched_to_endpoint_id: event.target_endpoint_id,
306
+ });
264
307
  return { ok: true };
265
308
  });
266
309
  controlEventDispatcher.on("spawn_request", async (event) => {
@@ -658,6 +701,25 @@ export async function startBrokerDaemon(opts) {
658
701
  }
659
702
  else {
660
703
  logger.info("undispatched_added", { id: undispatched.id, reason });
704
+ const wireReason = undispatched.reason === "unaddressed"
705
+ ? "no_target_endpoint"
706
+ : undispatched.reason;
707
+ emitUndispatched({
708
+ type: "undispatched_changed",
709
+ version: 1,
710
+ action: "add",
711
+ undispatched_id: undispatched.id,
712
+ sender_address: undispatched.sender_address,
713
+ content_preview: truncateContentPreview(undispatched.content, CONTENT_PREVIEW_MAX_CODEPOINTS),
714
+ reason: wireReason,
715
+ ...(undispatched.original_target_endpoint_id !== undefined && {
716
+ target_endpoint_id_hint: undispatched.original_target_endpoint_id,
717
+ }),
718
+ ...(typeof correlation_id === "string" && {
719
+ in_reply_to: correlation_id,
720
+ }),
721
+ arrived_at: Date.parse(undispatched.arrived_at),
722
+ });
661
723
  }
662
724
  });
663
725
  connector.on("delivery_pending", ({ payload }) => {
@@ -712,6 +774,20 @@ export async function startBrokerDaemon(opts) {
712
774
  reason,
713
775
  });
714
776
  }
777
+ if (undispatchedEmitter.size() > 0) {
778
+ logger.warn("undispatched_changed_queue_dropped_on_shutdown", {
779
+ size: undispatchedEmitter.size(),
780
+ reason,
781
+ });
782
+ }
783
+ await undispatchedEmitter.shutdown();
784
+ if (networkPresenceEmitter.size() > 0) {
785
+ logger.warn("network_presence_changed_queue_dropped_on_shutdown", {
786
+ size: networkPresenceEmitter.size(),
787
+ reason,
788
+ });
789
+ }
790
+ await networkPresenceEmitter.shutdown();
715
791
  const endpoints = registry.list();
716
792
  await Promise.all(endpoints.map(async (entry) => {
717
793
  try {
@@ -746,6 +822,8 @@ export async function startBrokerDaemon(opts) {
746
822
  networkPresence: () => networkPresence,
747
823
  pendingSpawnCount: () => spawnCorrelation.size(),
748
824
  retryQueueSize: () => retryQueue.size(),
825
+ undispatchedChangedQueueSize: () => undispatchedEmitter.size(),
826
+ networkPresenceChangedQueueSize: () => networkPresenceEmitter.size(),
749
827
  replyCorrelationCacheSize: (endpoint_id) => replyCorrelationCache.sizeForEndpoint(endpoint_id),
750
828
  };
751
829
  }
@@ -1 +1 @@
1
- {"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/broker/entry.ts"],"names":[],"mappings":"AA6EA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,aAAa,CAAC;AAEpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAMtE,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA8F9B;AAyDD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,YAAY,GACnB,mBAAmB,CAkErB;AAYD,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA8F1C"}
1
+ {"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/broker/entry.ts"],"names":[],"mappings":"AA+EA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,aAAa,CAAC;AAEpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAMtE,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA8F9B;AAyDD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,YAAY,GACnB,mBAAmB,CAwGrB;AAYD,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA8F1C"}
@@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises";
2
2
  import { pathToFileURL } from "node:url";
3
3
  import { readConfig } from "../config-fs.js";
4
4
  import { DEFAULT_API_HOST } from "../platform-client.js";
5
- import { heartbeatRuntimeEndpoint, registerRuntimeEndpoint, transitionRuntimeEndpointState, unregisterRuntimeEndpoint, } from "../runtime-endpoint-client.js";
5
+ import { emitRuntimeNetworkPresenceChanged, emitRuntimeUndispatchedChanged, heartbeatRuntimeEndpoint, registerRuntimeEndpoint, transitionRuntimeEndpointState, unregisterRuntimeEndpoint, } from "../runtime-endpoint-client.js";
6
6
  import { startBrokerDaemon } from "./broker-daemon.js";
7
7
  import { ClaudeCodeSpawnDriver } from "./claude-code-spawn-driver.js";
8
8
  import { CodexSpawnDriverStub } from "./codex-spawn-driver-stub.js";
@@ -132,6 +132,12 @@ export function buildApiPort(apiHost, runtimeKey, logger) {
132
132
  }
133
133
  }
134
134
  },
135
+ async emitUndispatchedChanged(event) {
136
+ return emitRuntimeUndispatchedChanged({ apiHost }, runtimeKey, event);
137
+ },
138
+ async emitNetworkPresenceChanged(event) {
139
+ return emitRuntimeNetworkPresenceChanged({ apiHost }, runtimeKey, event);
140
+ },
135
141
  };
136
142
  }
137
143
  function errorStatus(err) {
@@ -0,0 +1,8 @@
1
+ export interface NetworkPresenceChangedEvent {
2
+ type: "network_presence_changed";
3
+ version: 1;
4
+ state: "online" | "reconnecting" | "offline";
5
+ ts: number;
6
+ reason?: string;
7
+ }
8
+ //# sourceMappingURL=network-presence-changed-event-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-presence-changed-event-types.d.ts","sourceRoot":"","sources":["../../src/broker/network-presence-changed-event-types.ts"],"names":[],"mappings":"AAqCA,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,0BAA0B,CAAC;IAGjC,OAAO,EAAE,CAAC,CAAC;IAEX,KAAK,EAAE,QAAQ,GAAG,cAAc,GAAG,SAAS,CAAC;IAG7C,EAAE,EAAE,MAAM,CAAC;IAMX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,22 @@
1
+ import type { BrokerLogger } from "./logger.js";
2
+ import type { NetworkPresenceChangedEvent } from "./network-presence-changed-event-types.js";
3
+ import type { EmitOutcome, RuntimeEndpointPort } from "./runtime-endpoint-port.js";
4
+ export declare const DEFAULT_PRESENCE_EMITTER_CAPACITY = 128;
5
+ export declare const DEFAULT_PRESENCE_EMITTER_BACKOFF_INITIAL_MS = 500;
6
+ export declare const DEFAULT_PRESENCE_EMITTER_BACKOFF_MAX_MS = 30000;
7
+ export declare const DEFAULT_PRESENCE_EMITTER_MAX_RETRIES = 5;
8
+ export interface NetworkPresenceEmitterOptions {
9
+ capacity?: number;
10
+ backoffInitialMs?: number;
11
+ backoffMaxMs?: number;
12
+ maxRetries?: number;
13
+ }
14
+ export interface NetworkPresenceEmitter {
15
+ enqueue(event: NetworkPresenceChangedEvent): boolean;
16
+ size(): number;
17
+ capacity(): number;
18
+ shutdown(): Promise<void>;
19
+ }
20
+ export declare function createNetworkPresenceEmitter(post: (event: NetworkPresenceChangedEvent) => Promise<EmitOutcome>, logger: BrokerLogger, opts?: NetworkPresenceEmitterOptions): NetworkPresenceEmitter;
21
+ export declare function postNetworkPresenceChangedViaPort(apiPort: RuntimeEndpointPort): (event: NetworkPresenceChangedEvent) => Promise<EmitOutcome>;
22
+ //# sourceMappingURL=network-presence-emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-presence-emitter.d.ts","sourceRoot":"","sources":["../../src/broker/network-presence-emitter.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAC7F,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAEpC,eAAO,MAAM,iCAAiC,MAAM,CAAC;AACrD,eAAO,MAAM,2CAA2C,MAAM,CAAC;AAC/D,eAAO,MAAM,uCAAuC,QAAS,CAAC;AAC9D,eAAO,MAAM,oCAAoC,IAAI,CAAC;AAEtD,MAAM,WAAW,6BAA6B;IAE5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IAIrC,OAAO,CAAC,KAAK,EAAE,2BAA2B,GAAG,OAAO,CAAC;IAErD,IAAI,IAAI,MAAM,CAAC;IAEf,QAAQ,IAAI,MAAM,CAAC;IAGnB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,OAAO,CAAC,WAAW,CAAC,EAClE,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,6BAAkC,GACvC,sBAAsB,CAyIxB;AAcD,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,mBAAmB,GAC3B,CAAC,KAAK,EAAE,2BAA2B,KAAK,OAAO,CAAC,WAAW,CAAC,CAW9D"}
@@ -0,0 +1,150 @@
1
+ export const DEFAULT_PRESENCE_EMITTER_CAPACITY = 128;
2
+ export const DEFAULT_PRESENCE_EMITTER_BACKOFF_INITIAL_MS = 500;
3
+ export const DEFAULT_PRESENCE_EMITTER_BACKOFF_MAX_MS = 30_000;
4
+ export const DEFAULT_PRESENCE_EMITTER_MAX_RETRIES = 5;
5
+ export function createNetworkPresenceEmitter(post, logger, opts = {}) {
6
+ const cap = opts.capacity ?? DEFAULT_PRESENCE_EMITTER_CAPACITY;
7
+ const initialBackoff = opts.backoffInitialMs ?? DEFAULT_PRESENCE_EMITTER_BACKOFF_INITIAL_MS;
8
+ const maxBackoff = opts.backoffMaxMs ?? DEFAULT_PRESENCE_EMITTER_BACKOFF_MAX_MS;
9
+ const maxRetries = opts.maxRetries ?? DEFAULT_PRESENCE_EMITTER_MAX_RETRIES;
10
+ if (cap <= 0)
11
+ throw new Error(`capacity must be positive: ${cap}`);
12
+ if (initialBackoff <= 0)
13
+ throw new Error(`backoffInitialMs must be positive: ${initialBackoff}`);
14
+ if (maxBackoff < initialBackoff)
15
+ throw new Error(`backoffMaxMs must be >= backoffInitialMs`);
16
+ if (maxRetries < 0)
17
+ throw new Error(`maxRetries must be non-negative: ${maxRetries}`);
18
+ const queue = [];
19
+ let draining = false;
20
+ let stopped = false;
21
+ let activeDrain = null;
22
+ let wakeSleep = null;
23
+ const sleep = (ms) => new Promise((resolve) => {
24
+ const t = setTimeout(() => {
25
+ wakeSleep = null;
26
+ resolve();
27
+ }, ms);
28
+ t.unref?.();
29
+ wakeSleep = () => {
30
+ clearTimeout(t);
31
+ wakeSleep = null;
32
+ resolve();
33
+ };
34
+ });
35
+ const drain = async () => {
36
+ while (!stopped && queue.length > 0) {
37
+ const event = queue[0];
38
+ if (!event)
39
+ break;
40
+ let attempts = 0;
41
+ while (true) {
42
+ if (stopped)
43
+ return;
44
+ let outcome;
45
+ try {
46
+ outcome = await post(event);
47
+ }
48
+ catch (err) {
49
+ outcome = {
50
+ ok: false,
51
+ terminal: false,
52
+ detail: err instanceof Error ? err.message : String(err),
53
+ };
54
+ }
55
+ if (outcome.ok)
56
+ break;
57
+ if (outcome.terminal) {
58
+ logger.warn("network_presence_changed_drop_terminal", {
59
+ state: event.state,
60
+ ts: event.ts,
61
+ reason: event.reason,
62
+ status: outcome.status,
63
+ detail: outcome.detail,
64
+ });
65
+ break;
66
+ }
67
+ attempts++;
68
+ if (attempts > maxRetries) {
69
+ logger.warn("network_presence_changed_drop_max_retries", {
70
+ state: event.state,
71
+ ts: event.ts,
72
+ attempts,
73
+ status: outcome.status,
74
+ detail: outcome.detail,
75
+ });
76
+ break;
77
+ }
78
+ const backoff = Math.min(initialBackoff * 2 ** (attempts - 1), maxBackoff);
79
+ logger.info("network_presence_changed_retry", {
80
+ state: event.state,
81
+ ts: event.ts,
82
+ attempt: attempts,
83
+ backoff_ms: backoff,
84
+ status: outcome.status,
85
+ });
86
+ await sleep(backoff);
87
+ }
88
+ queue.shift();
89
+ }
90
+ draining = false;
91
+ };
92
+ const kick = () => {
93
+ if (draining || stopped)
94
+ return;
95
+ draining = true;
96
+ activeDrain = drain().catch((err) => {
97
+ logger.error("network_presence_changed_drain_unexpected_error", {
98
+ err: err instanceof Error ? err.message : String(err),
99
+ });
100
+ draining = false;
101
+ });
102
+ };
103
+ return {
104
+ enqueue(event) {
105
+ if (stopped)
106
+ return true;
107
+ let evicted = false;
108
+ if (queue.length >= cap) {
109
+ const old = queue.shift();
110
+ if (old) {
111
+ logger.warn("network_presence_changed_queue_overflow", {
112
+ dropped_state: old.state,
113
+ dropped_ts: old.ts,
114
+ size: queue.length,
115
+ capacity: cap,
116
+ });
117
+ evicted = true;
118
+ }
119
+ }
120
+ queue.push(event);
121
+ kick();
122
+ return !evicted;
123
+ },
124
+ size() {
125
+ return queue.length;
126
+ },
127
+ capacity() {
128
+ return cap;
129
+ },
130
+ async shutdown() {
131
+ stopped = true;
132
+ wakeSleep?.();
133
+ if (activeDrain) {
134
+ await activeDrain.catch(() => { });
135
+ }
136
+ },
137
+ };
138
+ }
139
+ export function postNetworkPresenceChangedViaPort(apiPort) {
140
+ return async (event) => {
141
+ if (!apiPort.emitNetworkPresenceChanged) {
142
+ return {
143
+ ok: false,
144
+ terminal: true,
145
+ detail: "emitNetworkPresenceChanged not implemented on this apiPort",
146
+ };
147
+ }
148
+ return apiPort.emitNetworkPresenceChanged(event);
149
+ };
150
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"network-presence.d.ts","sourceRoot":"","sources":["../../src/broker/network-presence.ts"],"names":[],"mappings":"AA8BA,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,cAAc,GAAG,SAAS,CAAC;AAEpE,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,qBAAqB,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,wBAAwB,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,wBAAwB,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAOD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,aAAa,EACpB,IAAI,GAAE,yBAA8B,GACnC,wBAAwB,CAgH1B"}
1
+ {"version":3,"file":"network-presence.d.ts","sourceRoot":"","sources":["../../src/broker/network-presence.ts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,cAAc,GAAG,SAAS,CAAC;AAEpE,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,qBAAqB,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,wBAAwB,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,wBAAwB,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAOD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,aAAa,EACpB,IAAI,GAAE,yBAA8B,GACnC,wBAAwB,CAgH1B"}
@@ -1,8 +1,20 @@
1
1
  import type { RegisterRuntimeEndpointParams, RegisterRuntimeEndpointResponse, TransitionRuntimeEndpointStateParams } from "../runtime-endpoint-client.js";
2
+ import type { NetworkPresenceChangedEvent } from "./network-presence-changed-event-types.js";
3
+ import type { UndispatchedChangedEvent } from "./undispatched-changed-event-types.js";
4
+ export type EmitOutcome = {
5
+ ok: true;
6
+ } | {
7
+ ok: false;
8
+ terminal: boolean;
9
+ status?: number;
10
+ detail?: string;
11
+ };
2
12
  export interface RuntimeEndpointPort {
3
13
  register(params: RegisterRuntimeEndpointParams): Promise<RegisterRuntimeEndpointResponse>;
4
14
  heartbeat(endpointId: string): Promise<void>;
5
15
  unregister(endpointId: string, asNodeId?: string): Promise<void>;
6
16
  transitionState(endpointId: string, params: TransitionRuntimeEndpointStateParams): Promise<void>;
17
+ emitUndispatchedChanged?(event: UndispatchedChangedEvent): Promise<EmitOutcome>;
18
+ emitNetworkPresenceChanged?(event: NetworkPresenceChangedEvent): Promise<EmitOutcome>;
7
19
  }
8
20
  //# sourceMappingURL=runtime-endpoint-port.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-endpoint-port.d.ts","sourceRoot":"","sources":["../../src/broker/runtime-endpoint-port.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,6BAA6B,EAC7B,+BAA+B,EAC/B,oCAAoC,EACrC,MAAM,+BAA+B,CAAC;AAEvC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CACN,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,+BAA+B,CAAC,CAAC;IAC5C,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAO7C,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAQjE,eAAe,CACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,oCAAoC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
1
+ {"version":3,"file":"runtime-endpoint-port.d.ts","sourceRoot":"","sources":["../../src/broker/runtime-endpoint-port.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,6BAA6B,EAC7B,+BAA+B,EAC/B,oCAAoC,EACrC,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAC7F,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAWtF,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CACN,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,+BAA+B,CAAC,CAAC;IAC5C,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAO7C,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAQjE,eAAe,CACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,oCAAoC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAAC;IAqBjB,uBAAuB,CAAC,CACtB,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,WAAW,CAAC,CAAC;IAYxB,0BAA0B,CAAC,CACzB,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,WAAW,CAAC,CAAC;CACzB"}
@@ -0,0 +1,29 @@
1
+ export declare const CONTENT_PREVIEW_MAX_CODEPOINTS = 80;
2
+ export type UndispatchedReason = "no_target_endpoint" | "closed_session_continuation";
3
+ export type UndispatchedRemoveReason = "lost_at_capacity_during_redispatch_bounce";
4
+ interface UndispatchedChangedEventBase {
5
+ type: "undispatched_changed";
6
+ version: 1;
7
+ undispatched_id: string;
8
+ }
9
+ export interface UndispatchedAddEvent extends UndispatchedChangedEventBase {
10
+ action: "add";
11
+ sender_address: string;
12
+ content_preview: string;
13
+ reason: UndispatchedReason;
14
+ target_endpoint_id_hint?: string;
15
+ in_reply_to?: string;
16
+ arrived_at: number;
17
+ }
18
+ export interface UndispatchedDispatchEvent extends UndispatchedChangedEventBase {
19
+ action: "dispatch";
20
+ dispatched_to_endpoint_id: string;
21
+ }
22
+ export interface UndispatchedRemoveEvent extends UndispatchedChangedEventBase {
23
+ action: "remove";
24
+ remove_reason: UndispatchedRemoveReason;
25
+ }
26
+ export type UndispatchedChangedEvent = UndispatchedAddEvent | UndispatchedDispatchEvent | UndispatchedRemoveEvent;
27
+ export declare function truncateContentPreview(raw: string, n?: number): string;
28
+ export {};
29
+ //# sourceMappingURL=undispatched-changed-event-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undispatched-changed-event-types.d.ts","sourceRoot":"","sources":["../../src/broker/undispatched-changed-event-types.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAMjD,MAAM,MAAM,kBAAkB,GAC1B,oBAAoB,GACpB,6BAA6B,CAAC;AAOlC,MAAM,MAAM,wBAAwB,GAWlC,2CAA2C,CAAC;AAG9C,UAAU,4BAA4B;IACpC,IAAI,EAAE,sBAAsB,CAAC;IAG7B,OAAO,EAAE,CAAC,CAAC;IAEX,eAAe,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,oBAAqB,SAAQ,4BAA4B;IACxE,MAAM,EAAE,KAAK,CAAC;IAEd,cAAc,EAAE,MAAM,CAAC;IASvB,eAAe,EAAE,MAAM,CAAC;IAExB,MAAM,EAAE,kBAAkB,CAAC;IAO3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAMjC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,UAAU,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,WAAW,yBACf,SAAQ,4BAA4B;IACpC,MAAM,EAAE,UAAU,CAAC;IAQnB,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAID,MAAM,WAAW,uBAAwB,SAAQ,4BAA4B;IAC3E,MAAM,EAAE,QAAQ,CAAC;IACjB,aAAa,EAAE,wBAAwB,CAAC;CACzC;AAED,MAAM,MAAM,wBAAwB,GAChC,oBAAoB,GACpB,yBAAyB,GACzB,uBAAuB,CAAC;AAqB5B,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,CAAC,GAAE,MAAuC,GACzC,MAAM,CAYR"}
@@ -0,0 +1,14 @@
1
+ export const CONTENT_PREVIEW_MAX_CODEPOINTS = 80;
2
+ export function truncateContentPreview(raw, n = CONTENT_PREVIEW_MAX_CODEPOINTS) {
3
+ if (raw.length <= n)
4
+ return raw;
5
+ let out = "";
6
+ let count = 0;
7
+ for (const cp of raw) {
8
+ if (count >= n)
9
+ break;
10
+ out += cp;
11
+ count++;
12
+ }
13
+ return out;
14
+ }
@@ -0,0 +1,22 @@
1
+ import type { BrokerLogger } from "./logger.js";
2
+ import type { EmitOutcome, RuntimeEndpointPort } from "./runtime-endpoint-port.js";
3
+ import type { UndispatchedChangedEvent } from "./undispatched-changed-event-types.js";
4
+ export declare const DEFAULT_EMITTER_CAPACITY = 1024;
5
+ export declare const DEFAULT_EMITTER_BACKOFF_INITIAL_MS = 500;
6
+ export declare const DEFAULT_EMITTER_BACKOFF_MAX_MS = 30000;
7
+ export declare const DEFAULT_EMITTER_MAX_RETRIES = 5;
8
+ export interface UndispatchedChangedEmitterOptions {
9
+ capacity?: number;
10
+ backoffInitialMs?: number;
11
+ backoffMaxMs?: number;
12
+ maxRetries?: number;
13
+ }
14
+ export interface UndispatchedChangedEmitter {
15
+ enqueue(event: UndispatchedChangedEvent): boolean;
16
+ size(): number;
17
+ capacity(): number;
18
+ shutdown(): Promise<void>;
19
+ }
20
+ export declare function createUndispatchedChangedEmitter(post: (event: UndispatchedChangedEvent) => Promise<EmitOutcome>, logger: BrokerLogger, opts?: UndispatchedChangedEmitterOptions): UndispatchedChangedEmitter;
21
+ export declare function postUndispatchedChangedViaPort(apiPort: RuntimeEndpointPort): (event: UndispatchedChangedEvent) => Promise<EmitOutcome>;
22
+ //# sourceMappingURL=undispatched-emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undispatched-emitter.d.ts","sourceRoot":"","sources":["../../src/broker/undispatched-emitter.ts"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAEtF,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,kCAAkC,MAAM,CAAC;AACtD,eAAO,MAAM,8BAA8B,QAAS,CAAC;AACrD,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,MAAM,WAAW,iCAAiC;IAEhD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IAIzC,OAAO,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC;IAElD,IAAI,IAAI,MAAM,CAAC;IAEf,QAAQ,IAAI,MAAM,CAAC;IAGnB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,OAAO,CAAC,WAAW,CAAC,EAC/D,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,iCAAsC,GAC3C,0BAA0B,CA8J5B;AAaD,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,mBAAmB,GAC3B,CAAC,KAAK,EAAE,wBAAwB,KAAK,OAAO,CAAC,WAAW,CAAC,CAW3D"}
@@ -0,0 +1,149 @@
1
+ export const DEFAULT_EMITTER_CAPACITY = 1024;
2
+ export const DEFAULT_EMITTER_BACKOFF_INITIAL_MS = 500;
3
+ export const DEFAULT_EMITTER_BACKOFF_MAX_MS = 30_000;
4
+ export const DEFAULT_EMITTER_MAX_RETRIES = 5;
5
+ export function createUndispatchedChangedEmitter(post, logger, opts = {}) {
6
+ const cap = opts.capacity ?? DEFAULT_EMITTER_CAPACITY;
7
+ const initialBackoff = opts.backoffInitialMs ?? DEFAULT_EMITTER_BACKOFF_INITIAL_MS;
8
+ const maxBackoff = opts.backoffMaxMs ?? DEFAULT_EMITTER_BACKOFF_MAX_MS;
9
+ const maxRetries = opts.maxRetries ?? DEFAULT_EMITTER_MAX_RETRIES;
10
+ if (cap <= 0)
11
+ throw new Error(`capacity must be positive: ${cap}`);
12
+ if (initialBackoff <= 0)
13
+ throw new Error(`backoffInitialMs must be positive: ${initialBackoff}`);
14
+ if (maxBackoff < initialBackoff)
15
+ throw new Error(`backoffMaxMs must be >= backoffInitialMs`);
16
+ if (maxRetries < 0)
17
+ throw new Error(`maxRetries must be non-negative: ${maxRetries}`);
18
+ const queue = [];
19
+ let draining = false;
20
+ let stopped = false;
21
+ let activeDrain = null;
22
+ let wakeSleep = null;
23
+ const sleep = (ms) => new Promise((resolve) => {
24
+ const t = setTimeout(() => {
25
+ wakeSleep = null;
26
+ resolve();
27
+ }, ms);
28
+ t.unref?.();
29
+ wakeSleep = () => {
30
+ clearTimeout(t);
31
+ wakeSleep = null;
32
+ resolve();
33
+ };
34
+ });
35
+ const drain = async () => {
36
+ while (!stopped && queue.length > 0) {
37
+ const event = queue[0];
38
+ if (!event)
39
+ break;
40
+ let attempts = 0;
41
+ while (true) {
42
+ if (stopped)
43
+ return;
44
+ let outcome;
45
+ try {
46
+ outcome = await post(event);
47
+ }
48
+ catch (err) {
49
+ outcome = {
50
+ ok: false,
51
+ terminal: false,
52
+ detail: err instanceof Error ? err.message : String(err),
53
+ };
54
+ }
55
+ if (outcome.ok)
56
+ break;
57
+ if (outcome.terminal) {
58
+ logger.warn("undispatched_changed_drop_terminal", {
59
+ action: event.action,
60
+ undispatched_id: event.undispatched_id,
61
+ status: outcome.status,
62
+ detail: outcome.detail,
63
+ });
64
+ break;
65
+ }
66
+ attempts++;
67
+ if (attempts > maxRetries) {
68
+ logger.warn("undispatched_changed_drop_max_retries", {
69
+ action: event.action,
70
+ undispatched_id: event.undispatched_id,
71
+ attempts,
72
+ status: outcome.status,
73
+ detail: outcome.detail,
74
+ });
75
+ break;
76
+ }
77
+ const backoff = Math.min(initialBackoff * 2 ** (attempts - 1), maxBackoff);
78
+ logger.info("undispatched_changed_retry", {
79
+ action: event.action,
80
+ undispatched_id: event.undispatched_id,
81
+ attempt: attempts,
82
+ backoff_ms: backoff,
83
+ status: outcome.status,
84
+ });
85
+ await sleep(backoff);
86
+ }
87
+ queue.shift();
88
+ }
89
+ draining = false;
90
+ };
91
+ const kick = () => {
92
+ if (draining || stopped)
93
+ return;
94
+ draining = true;
95
+ activeDrain = drain().catch((err) => {
96
+ logger.error("undispatched_changed_drain_unexpected_error", {
97
+ err: err instanceof Error ? err.message : String(err),
98
+ });
99
+ draining = false;
100
+ });
101
+ };
102
+ return {
103
+ enqueue(event) {
104
+ if (stopped)
105
+ return true;
106
+ let evicted = false;
107
+ if (queue.length >= cap) {
108
+ const old = queue.shift();
109
+ if (old) {
110
+ logger.warn("undispatched_changed_queue_overflow", {
111
+ dropped_action: old.action,
112
+ dropped_undispatched_id: old.undispatched_id,
113
+ size: queue.length,
114
+ capacity: cap,
115
+ });
116
+ evicted = true;
117
+ }
118
+ }
119
+ queue.push(event);
120
+ kick();
121
+ return !evicted;
122
+ },
123
+ size() {
124
+ return queue.length;
125
+ },
126
+ capacity() {
127
+ return cap;
128
+ },
129
+ async shutdown() {
130
+ stopped = true;
131
+ wakeSleep?.();
132
+ if (activeDrain) {
133
+ await activeDrain.catch(() => { });
134
+ }
135
+ },
136
+ };
137
+ }
138
+ export function postUndispatchedChangedViaPort(apiPort) {
139
+ return async (event) => {
140
+ if (!apiPort.emitUndispatchedChanged) {
141
+ return {
142
+ ok: false,
143
+ terminal: true,
144
+ detail: "emitUndispatchedChanged not implemented on this apiPort",
145
+ };
146
+ }
147
+ return apiPort.emitUndispatchedChanged(event);
148
+ };
149
+ }
@@ -61,4 +61,14 @@ export declare function transitionRuntimeEndpointState(cfg: PlatformClientConfig
61
61
  export declare function unregisterRuntimeEndpoint(cfg: PlatformClientConfig, runtimeKey: string, endpointId: string, asNodeId?: string): Promise<UnregisterRuntimeEndpointResponse>;
62
62
  export declare function listOwnedRuntimeEndpoints(cfg: PlatformClientConfig, runtimeKey: string, asNodeId: string): Promise<ListOwnedRuntimeEndpointsResponse>;
63
63
  export declare function getOwnedRuntimeEndpoint(cfg: PlatformClientConfig, runtimeKey: string, endpointId: string, asNodeId: string): Promise<OwnedRuntimeEndpointView>;
64
+ export declare function emitRuntimeUndispatchedChanged(cfg: PlatformClientConfig, runtimeKey: string, event: Readonly<Record<string, unknown>>): Promise<EmitUndispatchedChangedOutcome>;
65
+ export type EmitUndispatchedChangedOutcome = {
66
+ ok: true;
67
+ } | {
68
+ ok: false;
69
+ terminal: boolean;
70
+ status?: number;
71
+ detail?: string;
72
+ };
73
+ export declare function emitRuntimeNetworkPresenceChanged(cfg: PlatformClientConfig, runtimeKey: string, event: Readonly<Record<string, unknown>>): Promise<EmitUndispatchedChangedOutcome>;
64
74
  //# sourceMappingURL=runtime-endpoint-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-endpoint-client.d.ts","sourceRoot":"","sources":["../src/runtime-endpoint-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-endpoint-client.d.ts","sourceRoot":"","sources":["../src/runtime-endpoint-client.ts"],"names":[],"mappings":"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"}
@@ -82,3 +82,82 @@ export async function getOwnedRuntimeEndpoint(cfg, runtimeKey, endpointId, asNod
82
82
  return handleError(res);
83
83
  return (await res.json());
84
84
  }
85
+ export async function emitRuntimeUndispatchedChanged(cfg, runtimeKey, event) {
86
+ let res;
87
+ try {
88
+ res = await fetch(`${baseUrl(cfg)}/runtime/undispatched-changed`, {
89
+ method: "POST",
90
+ headers: jsonHeaders(runtimeKey),
91
+ body: JSON.stringify(event),
92
+ });
93
+ }
94
+ catch (err) {
95
+ return {
96
+ ok: false,
97
+ terminal: false,
98
+ detail: err instanceof Error ? err.message : String(err),
99
+ };
100
+ }
101
+ if (res.status === 204)
102
+ return { ok: true };
103
+ if (res.status === 401 || res.status === 422) {
104
+ return {
105
+ ok: false,
106
+ terminal: true,
107
+ status: res.status,
108
+ detail: await readErrorDetail(res),
109
+ };
110
+ }
111
+ return {
112
+ ok: false,
113
+ terminal: false,
114
+ status: res.status,
115
+ detail: await readErrorDetail(res),
116
+ };
117
+ }
118
+ export async function emitRuntimeNetworkPresenceChanged(cfg, runtimeKey, event) {
119
+ let res;
120
+ try {
121
+ res = await fetch(`${baseUrl(cfg)}/runtime/network-presence-changed`, {
122
+ method: "POST",
123
+ headers: jsonHeaders(runtimeKey),
124
+ body: JSON.stringify(event),
125
+ });
126
+ }
127
+ catch (err) {
128
+ return {
129
+ ok: false,
130
+ terminal: false,
131
+ detail: err instanceof Error ? err.message : String(err),
132
+ };
133
+ }
134
+ if (res.status === 204)
135
+ return { ok: true };
136
+ if (res.status === 401 || res.status === 422) {
137
+ return {
138
+ ok: false,
139
+ terminal: true,
140
+ status: res.status,
141
+ detail: await readErrorDetail(res),
142
+ };
143
+ }
144
+ return {
145
+ ok: false,
146
+ terminal: false,
147
+ status: res.status,
148
+ detail: await readErrorDetail(res),
149
+ };
150
+ }
151
+ async function readErrorDetail(res) {
152
+ try {
153
+ const body = (await res.json().catch(() => null));
154
+ if (!body)
155
+ return undefined;
156
+ const code = typeof body.error === "string" ? body.error : undefined;
157
+ const message = typeof body.message === "string" ? body.message : undefined;
158
+ return [code, message].filter(Boolean).join(": ") || undefined;
159
+ }
160
+ catch {
161
+ return undefined;
162
+ }
163
+ }
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const PLUGIN_VERSION = "0.5.321";
1
+ export declare const PLUGIN_VERSION = "0.5.322";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const PLUGIN_VERSION = "0.5.321";
1
+ export const PLUGIN_VERSION = "0.5.322";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masons/agent-network",
3
- "version": "0.5.321",
3
+ "version": "0.5.322",
4
4
  "description": "MASONS Agent Network — connects agent runtimes to the Agent Network over MSTP. Ships an OpenClaw channel plugin (root export) and subpath exports consumed by the Claude Code plugin today (planned: Codex and future hosts).",
5
5
  "license": "MIT",
6
6
  "author": "MASONS.ai <hello@masons.ai> (https://masons.ai)",