@masons/runtime-broker 0.1.0

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.
Files changed (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -0
  3. package/dist/broker/broker-daemon.d.ts +71 -0
  4. package/dist/broker/broker-daemon.d.ts.map +1 -0
  5. package/dist/broker/broker-daemon.js +837 -0
  6. package/dist/broker/claude-code-spawn-driver.d.ts +14 -0
  7. package/dist/broker/claude-code-spawn-driver.d.ts.map +1 -0
  8. package/dist/broker/claude-code-spawn-driver.js +39 -0
  9. package/dist/broker/closed-endpoint-lookup.d.ts +25 -0
  10. package/dist/broker/closed-endpoint-lookup.d.ts.map +1 -0
  11. package/dist/broker/closed-endpoint-lookup.js +59 -0
  12. package/dist/broker/codex-spawn-driver-stub.d.ts +7 -0
  13. package/dist/broker/codex-spawn-driver-stub.d.ts.map +1 -0
  14. package/dist/broker/codex-spawn-driver-stub.js +13 -0
  15. package/dist/broker/connector-ws.d.ts +47 -0
  16. package/dist/broker/connector-ws.d.ts.map +1 -0
  17. package/dist/broker/connector-ws.js +60 -0
  18. package/dist/broker/control-event-dispatcher.d.ts +21 -0
  19. package/dist/broker/control-event-dispatcher.d.ts.map +1 -0
  20. package/dist/broker/control-event-dispatcher.js +45 -0
  21. package/dist/broker/control-event-types.d.ts +28 -0
  22. package/dist/broker/control-event-types.d.ts.map +1 -0
  23. package/dist/broker/control-event-types.js +1 -0
  24. package/dist/broker/correlation-ring.d.ts +10 -0
  25. package/dist/broker/correlation-ring.d.ts.map +1 -0
  26. package/dist/broker/correlation-ring.js +32 -0
  27. package/dist/broker/discovery-file.d.ts +12 -0
  28. package/dist/broker/discovery-file.d.ts.map +1 -0
  29. package/dist/broker/discovery-file.js +77 -0
  30. package/dist/broker/endpoint-registry.d.ts +53 -0
  31. package/dist/broker/endpoint-registry.d.ts.map +1 -0
  32. package/dist/broker/endpoint-registry.js +83 -0
  33. package/dist/broker/endpoint-state-machine.d.ts +40 -0
  34. package/dist/broker/endpoint-state-machine.d.ts.map +1 -0
  35. package/dist/broker/endpoint-state-machine.js +92 -0
  36. package/dist/broker/entry.d.ts +13 -0
  37. package/dist/broker/entry.d.ts.map +1 -0
  38. package/dist/broker/entry.js +235 -0
  39. package/dist/broker/grace-timer.d.ts +9 -0
  40. package/dist/broker/grace-timer.d.ts.map +1 -0
  41. package/dist/broker/grace-timer.js +34 -0
  42. package/dist/broker/ipc-server.d.ts +79 -0
  43. package/dist/broker/ipc-server.d.ts.map +1 -0
  44. package/dist/broker/ipc-server.js +263 -0
  45. package/dist/broker/logger.d.ts +10 -0
  46. package/dist/broker/logger.d.ts.map +1 -0
  47. package/dist/broker/logger.js +34 -0
  48. package/dist/broker/network-presence-changed-event-types.d.ts +8 -0
  49. package/dist/broker/network-presence-changed-event-types.d.ts.map +1 -0
  50. package/dist/broker/network-presence-changed-event-types.js +1 -0
  51. package/dist/broker/network-presence-emitter.d.ts +22 -0
  52. package/dist/broker/network-presence-emitter.d.ts.map +1 -0
  53. package/dist/broker/network-presence-emitter.js +150 -0
  54. package/dist/broker/network-presence.d.ts +31 -0
  55. package/dist/broker/network-presence.d.ts.map +1 -0
  56. package/dist/broker/network-presence.js +109 -0
  57. package/dist/broker/paths.d.ts +11 -0
  58. package/dist/broker/paths.d.ts.map +1 -0
  59. package/dist/broker/paths.js +30 -0
  60. package/dist/broker/plugin-liveness.d.ts +2 -0
  61. package/dist/broker/plugin-liveness.d.ts.map +1 -0
  62. package/dist/broker/plugin-liveness.js +15 -0
  63. package/dist/broker/received-message-correlation-cache.d.ts +23 -0
  64. package/dist/broker/received-message-correlation-cache.d.ts.map +1 -0
  65. package/dist/broker/received-message-correlation-cache.js +114 -0
  66. package/dist/broker/reconnecting-buffer.d.ts +23 -0
  67. package/dist/broker/reconnecting-buffer.d.ts.map +1 -0
  68. package/dist/broker/reconnecting-buffer.js +107 -0
  69. package/dist/broker/routing-table.d.ts +22 -0
  70. package/dist/broker/routing-table.d.ts.map +1 -0
  71. package/dist/broker/routing-table.js +35 -0
  72. package/dist/broker/runtime-endpoint-port.d.ts +20 -0
  73. package/dist/broker/runtime-endpoint-port.d.ts.map +1 -0
  74. package/dist/broker/runtime-endpoint-port.js +1 -0
  75. package/dist/broker/services-event-client.d.ts +21 -0
  76. package/dist/broker/services-event-client.d.ts.map +1 -0
  77. package/dist/broker/services-event-client.js +221 -0
  78. package/dist/broker/spawn-correlation.d.ts +28 -0
  79. package/dist/broker/spawn-correlation.d.ts.map +1 -0
  80. package/dist/broker/spawn-correlation.js +77 -0
  81. package/dist/broker/spawn-driver.d.ts +27 -0
  82. package/dist/broker/spawn-driver.d.ts.map +1 -0
  83. package/dist/broker/spawn-driver.js +15 -0
  84. package/dist/broker/task-hint-handler.d.ts +21 -0
  85. package/dist/broker/task-hint-handler.d.ts.map +1 -0
  86. package/dist/broker/task-hint-handler.js +33 -0
  87. package/dist/broker/transition-state-retry-queue.d.ts +20 -0
  88. package/dist/broker/transition-state-retry-queue.d.ts.map +1 -0
  89. package/dist/broker/transition-state-retry-queue.js +48 -0
  90. package/dist/broker/undispatched-changed-event-types.d.ts +29 -0
  91. package/dist/broker/undispatched-changed-event-types.d.ts.map +1 -0
  92. package/dist/broker/undispatched-changed-event-types.js +14 -0
  93. package/dist/broker/undispatched-emitter.d.ts +22 -0
  94. package/dist/broker/undispatched-emitter.d.ts.map +1 -0
  95. package/dist/broker/undispatched-emitter.js +149 -0
  96. package/dist/broker/undispatched-inbox.d.ts +26 -0
  97. package/dist/broker/undispatched-inbox.d.ts.map +1 -0
  98. package/dist/broker/undispatched-inbox.js +53 -0
  99. package/dist/broker/version-handshake.d.ts +30 -0
  100. package/dist/broker/version-handshake.d.ts.map +1 -0
  101. package/dist/broker/version-handshake.js +47 -0
  102. package/dist/broker-client/broker-client.d.ts +65 -0
  103. package/dist/broker-client/broker-client.d.ts.map +1 -0
  104. package/dist/broker-client/broker-client.js +165 -0
  105. package/dist/broker-client/lazy-spawn.d.ts +18 -0
  106. package/dist/broker-client/lazy-spawn.d.ts.map +1 -0
  107. package/dist/broker-client/lazy-spawn.js +61 -0
  108. package/dist/config-fs.d.ts +4 -0
  109. package/dist/config-fs.d.ts.map +1 -0
  110. package/dist/config-fs.js +23 -0
  111. package/dist/connector-client.d.ts +65 -0
  112. package/dist/connector-client.d.ts.map +1 -0
  113. package/dist/connector-client.js +364 -0
  114. package/dist/environment-context.d.ts +21 -0
  115. package/dist/environment-context.d.ts.map +1 -0
  116. package/dist/environment-context.js +39 -0
  117. package/dist/platform-client.d.ts +84 -0
  118. package/dist/platform-client.d.ts.map +1 -0
  119. package/dist/platform-client.js +94 -0
  120. package/dist/runtime-endpoint-client.d.ts +74 -0
  121. package/dist/runtime-endpoint-client.d.ts.map +1 -0
  122. package/dist/runtime-endpoint-client.js +163 -0
  123. package/dist/types.d.ts +90 -0
  124. package/dist/types.d.ts.map +1 -0
  125. package/dist/types.js +38 -0
  126. package/dist/version.d.ts +2 -0
  127. package/dist/version.d.ts.map +1 -0
  128. package/dist/version.js +1 -0
  129. package/package.json +60 -0
@@ -0,0 +1,28 @@
1
+ export declare const DEFAULT_SPAWN_TIMEOUT_MS = 30000;
2
+ export declare const DEFAULT_RATE_LIMIT_WINDOW_MS = 30000;
3
+ export declare const DEFAULT_RATE_LIMIT_MAX = 3;
4
+ export interface PendingSpawn {
5
+ spawn_token: string;
6
+ expires_at: number;
7
+ }
8
+ export interface SpawnCorrelationOptions {
9
+ timeoutMs?: number;
10
+ }
11
+ export interface SpawnCorrelationManager {
12
+ track(spawn_token: string, onTimeout: () => void): void;
13
+ consume(spawn_token: string): PendingSpawn | undefined;
14
+ isTracked(spawn_token: string): boolean;
15
+ size(): number;
16
+ cancelAll(): void;
17
+ }
18
+ export declare function createSpawnCorrelationManager(opts?: SpawnCorrelationOptions): SpawnCorrelationManager;
19
+ export interface SpawnRateLimiter {
20
+ tryConsume(now?: number): boolean;
21
+ count(now?: number): number;
22
+ }
23
+ export interface SpawnRateLimiterOptions {
24
+ maxInWindow?: number;
25
+ windowMs?: number;
26
+ }
27
+ export declare function createSpawnRateLimiter(opts?: SpawnRateLimiterOptions): SpawnRateLimiter;
28
+ //# sourceMappingURL=spawn-correlation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-correlation.d.ts","sourceRoot":"","sources":["../../src/broker/spawn-correlation.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,eAAO,MAAM,4BAA4B,QAAS,CAAC;AACnD,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IAEpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IAOtC,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAMxD,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAEvD,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAExC,IAAI,IAAI,MAAM,CAAC;IAEf,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,GAAE,uBAA4B,GACjC,uBAAuB,CA+CzB;AAOD,MAAM,WAAW,gBAAgB;IAE/B,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAElC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,GAAE,uBAA4B,GACjC,gBAAgB,CA0BlB"}
@@ -0,0 +1,77 @@
1
+ export const DEFAULT_SPAWN_TIMEOUT_MS = 30_000;
2
+ export const DEFAULT_RATE_LIMIT_WINDOW_MS = 30_000;
3
+ export const DEFAULT_RATE_LIMIT_MAX = 3;
4
+ export function createSpawnCorrelationManager(opts = {}) {
5
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_SPAWN_TIMEOUT_MS;
6
+ const entries = new Map();
7
+ const timers = new Map();
8
+ return {
9
+ track(spawn_token, onTimeout) {
10
+ const priorTimer = timers.get(spawn_token);
11
+ if (priorTimer)
12
+ clearTimeout(priorTimer);
13
+ entries.set(spawn_token, {
14
+ spawn_token,
15
+ expires_at: Date.now() + timeoutMs,
16
+ });
17
+ const handle = setTimeout(() => {
18
+ entries.delete(spawn_token);
19
+ timers.delete(spawn_token);
20
+ onTimeout();
21
+ }, timeoutMs);
22
+ handle.unref?.();
23
+ timers.set(spawn_token, handle);
24
+ },
25
+ consume(spawn_token) {
26
+ const entry = entries.get(spawn_token);
27
+ if (!entry)
28
+ return undefined;
29
+ entries.delete(spawn_token);
30
+ const timer = timers.get(spawn_token);
31
+ if (timer) {
32
+ clearTimeout(timer);
33
+ timers.delete(spawn_token);
34
+ }
35
+ return entry;
36
+ },
37
+ isTracked(spawn_token) {
38
+ return entries.has(spawn_token);
39
+ },
40
+ size() {
41
+ return entries.size;
42
+ },
43
+ cancelAll() {
44
+ for (const [, t] of timers)
45
+ clearTimeout(t);
46
+ timers.clear();
47
+ entries.clear();
48
+ },
49
+ };
50
+ }
51
+ export function createSpawnRateLimiter(opts = {}) {
52
+ const max = opts.maxInWindow ?? DEFAULT_RATE_LIMIT_MAX;
53
+ const windowMs = opts.windowMs ?? DEFAULT_RATE_LIMIT_WINDOW_MS;
54
+ const timestamps = [];
55
+ const sweep = (now) => {
56
+ const cutoff = now - windowMs;
57
+ while (timestamps.length > 0) {
58
+ const head = timestamps[0];
59
+ if (head === undefined || head >= cutoff)
60
+ break;
61
+ timestamps.shift();
62
+ }
63
+ };
64
+ return {
65
+ tryConsume(now = Date.now()) {
66
+ sweep(now);
67
+ if (timestamps.length >= max)
68
+ return false;
69
+ timestamps.push(now);
70
+ return true;
71
+ },
72
+ count(now = Date.now()) {
73
+ sweep(now);
74
+ return timestamps.length;
75
+ },
76
+ };
77
+ }
@@ -0,0 +1,27 @@
1
+ export interface SpawnCommand {
2
+ binary: string;
3
+ args: string[];
4
+ env?: Record<string, string>;
5
+ cwd?: string;
6
+ }
7
+ export interface SpawnContext {
8
+ prompt: string;
9
+ spawn_token: string;
10
+ cwd?: string;
11
+ }
12
+ export interface DriverAvailability {
13
+ available: boolean;
14
+ reason?: string;
15
+ }
16
+ export interface SpawnDriver {
17
+ readonly runtime_kind: string;
18
+ buildSpawnCommand(ctx: SpawnContext): SpawnCommand;
19
+ isAvailable(): Promise<DriverAvailability>;
20
+ }
21
+ export declare class SpawnDriverRegistry {
22
+ private readonly drivers;
23
+ register(driver: SpawnDriver): void;
24
+ lookup(runtime_kind: string): SpawnDriver | undefined;
25
+ list(): readonly string[];
26
+ }
27
+ //# sourceMappingURL=spawn-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-driver.d.ts","sourceRoot":"","sources":["../../src/broker/spawn-driver.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,YAAY;IAE3B,MAAM,EAAE,MAAM,CAAC;IAOf,WAAW,EAAE,MAAM,CAAC;IAEpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IAGnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAOD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAAC;IACnD,WAAW,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC5C;AAGD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAG1D,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAUnC,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAKrD,IAAI,IAAI,SAAS,MAAM,EAAE;CAG1B"}
@@ -0,0 +1,15 @@
1
+ export class SpawnDriverRegistry {
2
+ drivers = new Map();
3
+ register(driver) {
4
+ if (this.drivers.has(driver.runtime_kind)) {
5
+ throw new Error(`driver already registered for runtime_kind: ${driver.runtime_kind}`);
6
+ }
7
+ this.drivers.set(driver.runtime_kind, driver);
8
+ }
9
+ lookup(runtime_kind) {
10
+ return this.drivers.get(runtime_kind);
11
+ }
12
+ list() {
13
+ return Array.from(this.drivers.keys());
14
+ }
15
+ }
@@ -0,0 +1,21 @@
1
+ import type { EndpointRegistry } from "./endpoint-registry.js";
2
+ export declare const TASK_HINT_MAX_LENGTH = 200;
3
+ export interface TaskHintHandlerOptions {
4
+ registry: EndpointRegistry;
5
+ }
6
+ export interface TaskHintUpdate {
7
+ endpoint_id: string;
8
+ plugin_pid: number;
9
+ task_hint: string;
10
+ }
11
+ export type TaskHintResult = {
12
+ ok: true;
13
+ truncated: boolean;
14
+ effective: string;
15
+ } | {
16
+ ok: false;
17
+ code: "endpoint_unknown" | "ownership_mismatch" | "task_hint_invalid";
18
+ message: string;
19
+ };
20
+ export declare function updateTaskHint(opts: TaskHintHandlerOptions, update: TaskHintUpdate): TaskHintResult;
21
+ //# sourceMappingURL=task-hint-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-hint-handler.d.ts","sourceRoot":"","sources":["../../src/broker/task-hint-handler.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACnD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,IAAI,EAAE,kBAAkB,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;IACtE,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,wBAAgB,cAAc,CAC5B,IAAI,EAAE,sBAAsB,EAC5B,MAAM,EAAE,cAAc,GACrB,cAAc,CAmChB"}
@@ -0,0 +1,33 @@
1
+ export const TASK_HINT_MAX_LENGTH = 200;
2
+ export function updateTaskHint(opts, update) {
3
+ if (typeof update.task_hint !== "string") {
4
+ return {
5
+ ok: false,
6
+ code: "task_hint_invalid",
7
+ message: "task_hint must be a string",
8
+ };
9
+ }
10
+ const entry = opts.registry.get(update.endpoint_id);
11
+ if (!entry) {
12
+ return {
13
+ ok: false,
14
+ code: "endpoint_unknown",
15
+ message: `unknown endpoint_id: ${update.endpoint_id}`,
16
+ };
17
+ }
18
+ if (entry.plugin_pid !== update.plugin_pid) {
19
+ return {
20
+ ok: false,
21
+ code: "ownership_mismatch",
22
+ message: "task_hint is Plugin-write-only; plugin_pid does not match",
23
+ };
24
+ }
25
+ const raw = update.task_hint;
26
+ const codePoints = [...raw];
27
+ const truncated = codePoints.length > TASK_HINT_MAX_LENGTH;
28
+ const effective = truncated
29
+ ? codePoints.slice(0, TASK_HINT_MAX_LENGTH).join("")
30
+ : raw;
31
+ entry.display_metadata.task_hint = effective;
32
+ return { ok: true, truncated, effective };
33
+ }
@@ -0,0 +1,20 @@
1
+ import type { TransitionRuntimeEndpointStateParams } from "../runtime-endpoint-client.js";
2
+ export declare const DEFAULT_QUEUE_CAPACITY = 256;
3
+ export interface QueuedTransition {
4
+ endpoint_id: string;
5
+ params: TransitionRuntimeEndpointStateParams;
6
+ enqueued_at: number;
7
+ }
8
+ export interface TransitionStateRetryQueue {
9
+ enqueue(endpoint_id: string, params: TransitionRuntimeEndpointStateParams): boolean;
10
+ flush(emit: (entry: QueuedTransition) => Promise<void>): Promise<void>;
11
+ size(): number;
12
+ capacity(): number;
13
+ peek(): readonly QueuedTransition[];
14
+ }
15
+ export interface TransitionStateRetryQueueOptions {
16
+ capacity?: number;
17
+ onDrop?: (dropped: QueuedTransition) => void;
18
+ }
19
+ export declare function createTransitionStateRetryQueue(opts?: TransitionStateRetryQueueOptions): TransitionStateRetryQueue;
20
+ //# sourceMappingURL=transition-state-retry-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transition-state-retry-queue.d.ts","sourceRoot":"","sources":["../../src/broker/transition-state-retry-queue.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,+BAA+B,CAAC;AAE1F,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,oCAAoC,CAAC;IAE7C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,yBAAyB;IAExC,OAAO,CACL,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,oCAAoC,GAC3C,OAAO,CAAC;IAOX,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,IAAI,IAAI,MAAM,CAAC;IACf,QAAQ,IAAI,MAAM,CAAC;IAEnB,IAAI,IAAI,SAAS,gBAAgB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC9C;AAED,wBAAgB,+BAA+B,CAC7C,IAAI,GAAE,gCAAqC,GAC1C,yBAAyB,CA4C3B"}
@@ -0,0 +1,48 @@
1
+ export const DEFAULT_QUEUE_CAPACITY = 256;
2
+ export function createTransitionStateRetryQueue(opts = {}) {
3
+ const cap = opts.capacity ?? DEFAULT_QUEUE_CAPACITY;
4
+ if (cap <= 0)
5
+ throw new Error(`capacity must be positive: ${cap}`);
6
+ const queue = [];
7
+ return {
8
+ enqueue(endpoint_id, params) {
9
+ const entry = {
10
+ endpoint_id,
11
+ params,
12
+ enqueued_at: Date.now(),
13
+ };
14
+ if (queue.length >= cap) {
15
+ const dropped = queue.shift();
16
+ if (dropped && opts.onDrop)
17
+ opts.onDrop(dropped);
18
+ queue.push(entry);
19
+ return false;
20
+ }
21
+ queue.push(entry);
22
+ return true;
23
+ },
24
+ async flush(emit) {
25
+ while (queue.length > 0) {
26
+ const entry = queue[0];
27
+ if (!entry)
28
+ break;
29
+ try {
30
+ await emit(entry);
31
+ }
32
+ catch {
33
+ return;
34
+ }
35
+ queue.shift();
36
+ }
37
+ },
38
+ size() {
39
+ return queue.length;
40
+ },
41
+ capacity() {
42
+ return cap;
43
+ },
44
+ peek() {
45
+ return queue.slice();
46
+ },
47
+ };
48
+ }
@@ -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
+ }
@@ -0,0 +1,26 @@
1
+ export declare const DEFAULT_INBOX_CAPACITY = 256;
2
+ export interface UndispatchedMessage {
3
+ id: string;
4
+ arrived_at: string;
5
+ sender_address: string;
6
+ content: string;
7
+ content_type: string;
8
+ metadata: Record<string, unknown>;
9
+ reason: "unaddressed" | "closed_session_continuation";
10
+ original_target_endpoint_id?: string;
11
+ original_correlation_id?: string;
12
+ }
13
+ export interface UndispatchedInbox {
14
+ tryAdd(msg: UndispatchedMessage): boolean;
15
+ list(): UndispatchedMessage[];
16
+ get(id: string): UndispatchedMessage | undefined;
17
+ take(id: string): UndispatchedMessage | undefined;
18
+ size(): number;
19
+ capacity(): number;
20
+ isUnderPressure(): boolean;
21
+ }
22
+ export interface UndispatchedInboxOptions {
23
+ capacity?: number;
24
+ }
25
+ export declare function createUndispatchedInbox(opts?: UndispatchedInboxOptions): UndispatchedInbox;
26
+ //# sourceMappingURL=undispatched-inbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undispatched-inbox.d.ts","sourceRoot":"","sources":["../../src/broker/undispatched-inbox.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAMlC,MAAM,EAAE,aAAa,GAAG,6BAA6B,CAAC;IAEtD,2BAA2B,CAAC,EAAE,MAAM,CAAC;IAErC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAMhC,MAAM,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC;IAE1C,IAAI,IAAI,mBAAmB,EAAE,CAAC;IAE9B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAAC;IAKjD,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAAC;IAElD,IAAI,IAAI,MAAM,CAAC;IAEf,QAAQ,IAAI,MAAM,CAAC;IAEnB,eAAe,IAAI,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CACrC,IAAI,GAAE,wBAA6B,GAClC,iBAAiB,CAkDnB"}
@@ -0,0 +1,53 @@
1
+ export const DEFAULT_INBOX_CAPACITY = 256;
2
+ export function createUndispatchedInbox(opts = {}) {
3
+ const cap = opts.capacity ?? DEFAULT_INBOX_CAPACITY;
4
+ if (cap <= 0)
5
+ throw new Error(`capacity must be positive: ${cap}`);
6
+ const byId = new Map();
7
+ const order = [];
8
+ return {
9
+ tryAdd(msg) {
10
+ if (byId.has(msg.id)) {
11
+ byId.set(msg.id, msg);
12
+ return true;
13
+ }
14
+ if (byId.size >= cap) {
15
+ return false;
16
+ }
17
+ byId.set(msg.id, msg);
18
+ order.push(msg.id);
19
+ return true;
20
+ },
21
+ list() {
22
+ const out = [];
23
+ for (const id of order) {
24
+ const m = byId.get(id);
25
+ if (m)
26
+ out.push(m);
27
+ }
28
+ return out;
29
+ },
30
+ get(id) {
31
+ return byId.get(id);
32
+ },
33
+ take(id) {
34
+ const m = byId.get(id);
35
+ if (!m)
36
+ return undefined;
37
+ byId.delete(id);
38
+ const idx = order.indexOf(id);
39
+ if (idx >= 0)
40
+ order.splice(idx, 1);
41
+ return m;
42
+ },
43
+ size() {
44
+ return byId.size;
45
+ },
46
+ capacity() {
47
+ return cap;
48
+ },
49
+ isUnderPressure() {
50
+ return byId.size >= Math.floor(cap * 0.9);
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,30 @@
1
+ export declare const IPC_PROTOCOL_VERSION = "1.0";
2
+ export interface IpcCapabilities {
3
+ endpoint_metadata_v1?: boolean;
4
+ remote_spawn_v1?: boolean;
5
+ undispatched_inbox_v1?: boolean;
6
+ }
7
+ export declare const SERVER_CAPABILITIES: Readonly<IpcCapabilities>;
8
+ export interface InitializeRequestBody {
9
+ client_protocol_version: string;
10
+ client_kind: string;
11
+ client_version: string;
12
+ capabilities?: IpcCapabilities;
13
+ }
14
+ export interface InitializeResponseBody {
15
+ server_protocol_version: string;
16
+ server_capabilities: IpcCapabilities;
17
+ session_id: string;
18
+ }
19
+ export interface InitializeErrorBody {
20
+ error: "protocol_version_mismatch" | "bad_request";
21
+ message: string;
22
+ }
23
+ export declare function handleInitialize(req: InitializeRequestBody): {
24
+ status: 200;
25
+ body: InitializeResponseBody;
26
+ } | {
27
+ status: 400;
28
+ body: InitializeErrorBody;
29
+ };
30
+ //# sourceMappingURL=version-handshake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-handshake.d.ts","sourceRoot":"","sources":["../../src/broker/version-handshake.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAM1C,MAAM,WAAW,eAAe;IAE9B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAG1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAGD,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,eAAe,CAIxD,CAAC;AAEH,MAAM,WAAW,qBAAqB;IAEpC,uBAAuB,EAAE,MAAM,CAAC;IAEhC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,uBAAuB,EAAE,MAAM,CAAC;IAChC,mBAAmB,EAAE,eAAe,CAAC;IAErC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,2BAA2B,GAAG,aAAa,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,qBAAqB,GAExB;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,sBAAsB,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,mBAAmB,CAAA;CAAE,CA0C7C"}