@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,14 @@
1
+ import type { DriverAvailability, SpawnCommand, SpawnContext, SpawnDriver } from "./spawn-driver.js";
2
+ export interface ClaudeCodeSpawnDriverOptions {
3
+ binary?: string;
4
+ isOnPath?: (binary: string) => boolean;
5
+ }
6
+ export declare class ClaudeCodeSpawnDriver implements SpawnDriver {
7
+ readonly runtime_kind = "claude-code";
8
+ private readonly binary;
9
+ private readonly isOnPath;
10
+ constructor(opts?: ClaudeCodeSpawnDriverOptions);
11
+ buildSpawnCommand(ctx: SpawnContext): SpawnCommand;
12
+ isAvailable(): Promise<DriverAvailability>;
13
+ }
14
+ //# sourceMappingURL=claude-code-spawn-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-spawn-driver.d.ts","sourceRoot":"","sources":["../../src/broker/claude-code-spawn-driver.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAG3B,MAAM,WAAW,4BAA4B;IAE3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAMhB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAED,qBAAa,qBAAsB,YAAW,WAAW;IACvD,QAAQ,CAAC,YAAY,iBAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;gBAE3C,IAAI,GAAE,4BAAiC;IAKnD,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY;IAS5C,WAAW,IAAI,OAAO,CAAC,kBAAkB,CAAC;CASjD"}
@@ -0,0 +1,39 @@
1
+ import { execFileSync } from "node:child_process";
2
+ export class ClaudeCodeSpawnDriver {
3
+ runtime_kind = "claude-code";
4
+ binary;
5
+ isOnPath;
6
+ constructor(opts = {}) {
7
+ this.binary = opts.binary ?? "claude";
8
+ this.isOnPath = opts.isOnPath ?? defaultIsOnPath;
9
+ }
10
+ buildSpawnCommand(ctx) {
11
+ return {
12
+ binary: this.binary,
13
+ args: ["--bg", ctx.prompt],
14
+ env: { MASONS_SPAWN_TOKEN: ctx.spawn_token },
15
+ cwd: ctx.cwd,
16
+ };
17
+ }
18
+ async isAvailable() {
19
+ if (this.isOnPath(this.binary)) {
20
+ return { available: true };
21
+ }
22
+ return {
23
+ available: false,
24
+ reason: `\`${this.binary}\` CLI not found in PATH. Install Claude Code or check $PATH.`,
25
+ };
26
+ }
27
+ }
28
+ function defaultIsOnPath(binary) {
29
+ if (!/^[a-zA-Z0-9._-]+$/.test(binary))
30
+ return false;
31
+ const probe = process.platform === "win32" ? "where" : "which";
32
+ try {
33
+ execFileSync(probe, [binary], { stdio: "ignore" });
34
+ return true;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
@@ -0,0 +1,25 @@
1
+ import type { PlatformClientConfig } from "../platform-client.js";
2
+ import { type OwnedRuntimeEndpointView } from "../runtime-endpoint-client.js";
3
+ export interface ClosedEndpointInfo {
4
+ exists: true;
5
+ closed: boolean;
6
+ view: OwnedRuntimeEndpointView;
7
+ }
8
+ export interface UnknownEndpoint {
9
+ exists: false;
10
+ }
11
+ export type LookupResult = ClosedEndpointInfo | UnknownEndpoint;
12
+ export interface ClosedEndpointLookup {
13
+ lookup(endpoint_id: string, asNodeId: string): Promise<LookupResult>;
14
+ invalidate(endpoint_id: string): void;
15
+ size(): number;
16
+ }
17
+ export interface ClosedEndpointLookupOptions {
18
+ cfg: PlatformClientConfig;
19
+ runtimeKey: string;
20
+ cacheSize?: number;
21
+ cacheTtlMs?: number;
22
+ fetcher?: (cfg: PlatformClientConfig, runtimeKey: string, endpointId: string, asNodeId: string) => Promise<OwnedRuntimeEndpointView>;
23
+ }
24
+ export declare function createClosedEndpointLookup(opts: ClosedEndpointLookupOptions): ClosedEndpointLookup;
25
+ //# sourceMappingURL=closed-endpoint-lookup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closed-endpoint-lookup.d.ts","sourceRoot":"","sources":["../../src/broker/closed-endpoint-lookup.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,+BAA+B,CAAC;AAEvC,MAAM,WAAW,kBAAkB;IAEjC,MAAM,EAAE,IAAI,CAAC;IAEb,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,wBAAwB,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,CAAC;CACf;AAED,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAIrE,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtC,IAAI,IAAI,MAAM,CAAC;CAChB;AAaD,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,oBAAoB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,EAAE,CACR,GAAG,EAAE,oBAAoB,EACzB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACxC;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,2BAA2B,GAChC,oBAAoB,CA6DtB"}
@@ -0,0 +1,59 @@
1
+ import { getOwnedRuntimeEndpoint, } from "../runtime-endpoint-client.js";
2
+ const DEFAULT_CACHE_SIZE = 64;
3
+ const DEFAULT_CACHE_TTL_MS = 5_000;
4
+ export function createClosedEndpointLookup(opts) {
5
+ const cacheSize = opts.cacheSize ?? DEFAULT_CACHE_SIZE;
6
+ const ttl = opts.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
7
+ const fetcher = opts.fetcher ?? getOwnedRuntimeEndpoint;
8
+ const cache = new Map();
9
+ const evict = () => {
10
+ if (cache.size <= cacheSize)
11
+ return;
12
+ const oldest = cache.keys().next();
13
+ if (!oldest.done)
14
+ cache.delete(oldest.value);
15
+ };
16
+ return {
17
+ async lookup(endpoint_id, asNodeId) {
18
+ const now = Date.now();
19
+ const hit = cache.get(endpoint_id);
20
+ if (hit && hit.expires_at > now) {
21
+ cache.delete(endpoint_id);
22
+ cache.set(endpoint_id, hit);
23
+ return hit.result;
24
+ }
25
+ let result;
26
+ try {
27
+ const view = await fetcher(opts.cfg, opts.runtimeKey, endpoint_id, asNodeId);
28
+ result = {
29
+ exists: true,
30
+ closed: typeof view.retired_at === "string" && view.retired_at.length > 0,
31
+ view,
32
+ };
33
+ }
34
+ catch (err) {
35
+ if (isPlatformApi404(err)) {
36
+ result = { exists: false };
37
+ }
38
+ else {
39
+ return { exists: false };
40
+ }
41
+ }
42
+ cache.set(endpoint_id, { result, expires_at: now + ttl });
43
+ evict();
44
+ return result;
45
+ },
46
+ invalidate(endpoint_id) {
47
+ cache.delete(endpoint_id);
48
+ },
49
+ size() {
50
+ return cache.size;
51
+ },
52
+ };
53
+ }
54
+ function isPlatformApi404(err) {
55
+ if (typeof err !== "object" || err === null)
56
+ return false;
57
+ const status = err.status;
58
+ return status === 404;
59
+ }
@@ -0,0 +1,7 @@
1
+ import type { DriverAvailability, SpawnCommand, SpawnContext, SpawnDriver } from "./spawn-driver.js";
2
+ export declare class CodexSpawnDriverStub implements SpawnDriver {
3
+ readonly runtime_kind = "codex";
4
+ buildSpawnCommand(_ctx: SpawnContext): SpawnCommand;
5
+ isAvailable(): Promise<DriverAvailability>;
6
+ }
7
+ //# sourceMappingURL=codex-spawn-driver-stub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-spawn-driver-stub.d.ts","sourceRoot":"","sources":["../../src/broker/codex-spawn-driver-stub.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,oBAAqB,YAAW,WAAW;IACtD,QAAQ,CAAC,YAAY,WAAW;IAEhC,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY;IAW7C,WAAW,IAAI,OAAO,CAAC,kBAAkB,CAAC;CAYjD"}
@@ -0,0 +1,13 @@
1
+ export class CodexSpawnDriverStub {
2
+ runtime_kind = "codex";
3
+ buildSpawnCommand(_ctx) {
4
+ throw new Error("CodexSpawnDriverStub.buildSpawnCommand called — broker logic bug; " +
5
+ "isAvailable() should have short-circuited the spawn before this point");
6
+ }
7
+ async isAvailable() {
8
+ return {
9
+ available: false,
10
+ reason: "codex driver not registered on this broker — Codex distribution will ship a SpawnDriver in a future release (broker restart required after install)",
11
+ };
12
+ }
13
+ }
@@ -0,0 +1,47 @@
1
+ import { ConnectorError } from "../connector-client.js";
2
+ import type { AddressedMessageEvent, DeliveryPendingEvent, DeliveryStatusEvent, SendAckEvent, StructuredErrorEvent } from "../types.js";
3
+ export type ConnectorWSEvent = {
4
+ event: "message_received";
5
+ payload: AddressedMessageEvent;
6
+ } | {
7
+ event: "send_ack";
8
+ payload: SendAckEvent;
9
+ } | {
10
+ event: "delivery_pending";
11
+ payload: DeliveryPendingEvent;
12
+ } | {
13
+ event: "delivery_status";
14
+ payload: DeliveryStatusEvent;
15
+ } | {
16
+ event: "structured_error";
17
+ payload: StructuredErrorEvent;
18
+ } | {
19
+ event: "connected";
20
+ } | {
21
+ event: "disconnected";
22
+ } | {
23
+ event: "error";
24
+ payload: Error;
25
+ };
26
+ type ListenerFor<E extends ConnectorWSEvent["event"]> = (e: Extract<ConnectorWSEvent, {
27
+ event: E;
28
+ }>) => void;
29
+ export interface ConnectorWSOptions {
30
+ url: string;
31
+ token: string;
32
+ }
33
+ export declare class ConnectorWS {
34
+ private readonly client;
35
+ private readonly bus;
36
+ constructor(opts: ConnectorWSOptions);
37
+ connect(): Promise<void>;
38
+ disconnect(): void;
39
+ send(to: string, content: string, contentType?: string, metadata?: Record<string, unknown>): Promise<SendAckEvent>;
40
+ ackDelivery(upTo: string): boolean;
41
+ on<E extends ConnectorWSEvent["event"]>(event: E, listener: ListenerFor<E>): this;
42
+ off<E extends ConnectorWSEvent["event"]>(event: E, listener: ListenerFor<E>): this;
43
+ _emitForTesting(e: ConnectorWSEvent): void;
44
+ private wireForwarders;
45
+ }
46
+ export { ConnectorError };
47
+ //# sourceMappingURL=connector-ws.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connector-ws.d.ts","sourceRoot":"","sources":["../../src/broker/connector-ws.ts"],"names":[],"mappings":"AAaA,OAAO,EAAmB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,qBAAqB,CAAA;CAAE,GAC7D;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC5C;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GAC5D;IAAE,KAAK,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GAC5D;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,GACtB;IAAE,KAAK,EAAE,cAAc,CAAA;CAAE,GACzB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC;AAEvC,KAAK,WAAW,CAAC,CAAC,SAAS,gBAAgB,CAAC,OAAO,CAAC,IAAI,CACtD,CAAC,EAAE,OAAO,CAAC,gBAAgB,EAAE;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC,KACvC,IAAI,CAAC;AAEV,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;gBAE9B,IAAI,EAAE,kBAAkB;IAMpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKxB,UAAU,IAAI,IAAI;IASlB,IAAI,CACF,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,SAAS,EACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,YAAY,CAAC;IAKxB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIlC,EAAE,CAAC,CAAC,SAAS,gBAAgB,CAAC,OAAO,CAAC,EACpC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,IAAI;IAKP,GAAG,CAAC,CAAC,SAAS,gBAAgB,CAAC,OAAO,CAAC,EACrC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,IAAI;IAMS,eAAe,CAAC,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAI1D,OAAO,CAAC,cAAc;CA0BvB;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { ConnectorClient, ConnectorError } from "../connector-client.js";
3
+ export class ConnectorWS {
4
+ client;
5
+ bus = new EventEmitter();
6
+ constructor(opts) {
7
+ this.client = new ConnectorClient(opts.url, opts.token);
8
+ this.wireForwarders();
9
+ }
10
+ connect() {
11
+ return this.client.connect();
12
+ }
13
+ disconnect() {
14
+ this.client.disconnect();
15
+ }
16
+ send(to, content, contentType = "text", metadata) {
17
+ return this.client.send(to, content, contentType, metadata);
18
+ }
19
+ ackDelivery(upTo) {
20
+ return this.client.ackDelivery(upTo);
21
+ }
22
+ on(event, listener) {
23
+ this.bus.on(event, listener);
24
+ return this;
25
+ }
26
+ off(event, listener) {
27
+ this.bus.off(event, listener);
28
+ return this;
29
+ }
30
+ _emitForTesting(e) {
31
+ this.bus.emit(e.event, e);
32
+ }
33
+ wireForwarders() {
34
+ this.client.on("message_received", (payload) => {
35
+ this.bus.emit("message_received", { event: "message_received", payload });
36
+ });
37
+ this.client.on("send_ack", (payload) => {
38
+ this.bus.emit("send_ack", { event: "send_ack", payload });
39
+ });
40
+ this.client.on("delivery_pending", (payload) => {
41
+ this.bus.emit("delivery_pending", { event: "delivery_pending", payload });
42
+ });
43
+ this.client.on("delivery_status", (payload) => {
44
+ this.bus.emit("delivery_status", { event: "delivery_status", payload });
45
+ });
46
+ this.client.on("structured_error", (payload) => {
47
+ this.bus.emit("structured_error", { event: "structured_error", payload });
48
+ });
49
+ this.client.on("connected", () => {
50
+ this.bus.emit("connected", { event: "connected" });
51
+ });
52
+ this.client.on("disconnected", () => {
53
+ this.bus.emit("disconnected", { event: "disconnected" });
54
+ });
55
+ this.client.on("error", (err) => {
56
+ this.bus.emit("error", { event: "error", payload: err });
57
+ });
58
+ }
59
+ }
60
+ export { ConnectorError };
@@ -0,0 +1,21 @@
1
+ import type { ControlEvent } from "./control-event-types.js";
2
+ export declare const DEFAULT_IDEMPOTENCY_RING_SIZE = 1024;
3
+ export type ControlEventOutcome = {
4
+ ok: true;
5
+ ack_hint?: "received";
6
+ } | {
7
+ ok: false;
8
+ detail: string;
9
+ };
10
+ export type ControlEventHandler<E extends ControlEvent = ControlEvent> = (event: E) => Promise<ControlEventOutcome>;
11
+ export interface ControlEventDispatcher {
12
+ on<E extends ControlEvent>(type: E["type"], handler: ControlEventHandler<E>): void;
13
+ dispatch(event: ControlEvent): Promise<ControlEventOutcome>;
14
+ ringSize(): number;
15
+ hasSeen(idempotency_key: string): boolean;
16
+ }
17
+ export interface ControlEventDispatcherOptions {
18
+ ringSize?: number;
19
+ }
20
+ export declare function createControlEventDispatcher(opts?: ControlEventDispatcherOptions): ControlEventDispatcher;
21
+ //# sourceMappingURL=control-event-dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-event-dispatcher.d.ts","sourceRoot":"","sources":["../../src/broker/control-event-dispatcher.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAYlD,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,UAAU,CAAA;CAAE,GACnC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,IAAI,CACvE,KAAK,EAAE,CAAC,KACL,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAElC,MAAM,WAAW,sBAAsB;IAErC,EAAE,CAAC,CAAC,SAAS,YAAY,EACvB,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EACf,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC9B,IAAI,CAAC;IAKR,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAE5D,QAAQ,IAAI,MAAM,CAAC;IAEnB,OAAO,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3C;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,GAAE,6BAAkC,GACvC,sBAAsB,CAqDxB"}
@@ -0,0 +1,45 @@
1
+ export const DEFAULT_IDEMPOTENCY_RING_SIZE = 1024;
2
+ export function createControlEventDispatcher(opts = {}) {
3
+ const cap = opts.ringSize ?? DEFAULT_IDEMPOTENCY_RING_SIZE;
4
+ if (cap <= 0)
5
+ throw new Error(`ringSize must be positive: ${cap}`);
6
+ const seen = new Set();
7
+ const order = [];
8
+ const handlers = new Map();
9
+ return {
10
+ on(type, handler) {
11
+ handlers.set(type, handler);
12
+ },
13
+ async dispatch(event) {
14
+ if (seen.has(event.idempotency_key)) {
15
+ return { ok: true };
16
+ }
17
+ seen.add(event.idempotency_key);
18
+ order.push(event.idempotency_key);
19
+ if (order.length > cap) {
20
+ const oldest = order.shift();
21
+ if (oldest !== undefined)
22
+ seen.delete(oldest);
23
+ }
24
+ const handler = handlers.get(event.type);
25
+ if (!handler) {
26
+ return { ok: false, detail: `no_handler:${event.type}` };
27
+ }
28
+ try {
29
+ return await handler(event);
30
+ }
31
+ catch (err) {
32
+ return {
33
+ ok: false,
34
+ detail: err instanceof Error ? err.message : String(err),
35
+ };
36
+ }
37
+ },
38
+ ringSize() {
39
+ return seen.size;
40
+ },
41
+ hasSeen(idempotency_key) {
42
+ return seen.has(idempotency_key);
43
+ },
44
+ };
45
+ }
@@ -0,0 +1,28 @@
1
+ export interface ControlEventBase {
2
+ version: 1;
3
+ idempotency_key: string;
4
+ emitted_at: number;
5
+ }
6
+ export type ControlEvent = DispatchUndispatchedEvent | SpawnRequestEvent | ForceUnregisterEvent;
7
+ export interface DispatchUndispatchedEvent extends ControlEventBase {
8
+ type: "dispatch_undispatched";
9
+ undispatched_id: string;
10
+ target_endpoint_id: string;
11
+ }
12
+ export interface SpawnRequestEvent extends ControlEventBase {
13
+ type: "spawn_request";
14
+ prompt: string;
15
+ runtime_kind: "claude-code" | "openclaw" | "codex" | "custom";
16
+ origin: "passport-spawn";
17
+ }
18
+ export interface ForceUnregisterEvent extends ControlEventBase {
19
+ type: "force_unregister";
20
+ endpoint_id: string;
21
+ reason: string;
22
+ }
23
+ export interface ControlAck {
24
+ idempotency_key: string;
25
+ status: "received" | "applied" | "failed";
26
+ detail?: string;
27
+ }
28
+ //# sourceMappingURL=control-event-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-event-types.d.ts","sourceRoot":"","sources":["../../src/broker/control-event-types.ts"],"names":[],"mappings":"AAwCA,MAAM,WAAW,gBAAgB;IAI/B,OAAO,EAAE,CAAC,CAAC;IAWX,eAAe,EAAE,MAAM,CAAC;IAKxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,MAAM,YAAY,GACpB,yBAAyB,GACzB,iBAAiB,GACjB,oBAAoB,CAAC;AAGzB,MAAM,WAAW,yBAA0B,SAAQ,gBAAgB;IACjE,IAAI,EAAE,uBAAuB,CAAC;IAE9B,eAAe,EAAE,MAAM,CAAC;IAExB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAGD,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,IAAI,EAAE,eAAe,CAAC;IAEtB,MAAM,EAAE,MAAM,CAAC;IAMf,YAAY,EAAE,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;IAG9D,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAGD,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,IAAI,EAAE,kBAAkB,CAAC;IAEzB,WAAW,EAAE,MAAM,CAAC;IAEpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAwBD,MAAM,WAAW,UAAU;IAEzB,eAAe,EAAE,MAAM,CAAC;IAExB,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IAE1C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ export declare class CorrelationRingBuffer {
2
+ private readonly capacity;
3
+ private readonly set;
4
+ private readonly order;
5
+ constructor(capacity?: number);
6
+ add(correlation_id: string): void;
7
+ has(correlation_id: string): boolean;
8
+ size(): number;
9
+ }
10
+ //# sourceMappingURL=correlation-ring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"correlation-ring.d.ts","sourceRoot":"","sources":["../../src/broker/correlation-ring.ts"],"names":[],"mappings":"AAaA,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;gBAErB,QAAQ,GAAE,MAAoB;IAU1C,GAAG,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAYjC,GAAG,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO;IAIpC,IAAI,IAAI,MAAM;CAGf"}
@@ -0,0 +1,32 @@
1
+ const DEFAULT_CAP = 1024;
2
+ export class CorrelationRingBuffer {
3
+ capacity;
4
+ set;
5
+ order;
6
+ constructor(capacity = DEFAULT_CAP) {
7
+ if (capacity <= 0) {
8
+ throw new Error(`capacity must be positive: ${capacity}`);
9
+ }
10
+ this.capacity = capacity;
11
+ this.set = new Set();
12
+ this.order = [];
13
+ }
14
+ add(correlation_id) {
15
+ if (this.set.has(correlation_id)) {
16
+ return;
17
+ }
18
+ if (this.order.length >= this.capacity) {
19
+ const oldest = this.order.shift();
20
+ if (oldest !== undefined)
21
+ this.set.delete(oldest);
22
+ }
23
+ this.set.add(correlation_id);
24
+ this.order.push(correlation_id);
25
+ }
26
+ has(correlation_id) {
27
+ return this.set.has(correlation_id);
28
+ }
29
+ size() {
30
+ return this.set.size;
31
+ }
32
+ }
@@ -0,0 +1,12 @@
1
+ export interface DiscoveryRecord {
2
+ version: 1;
3
+ pid: number;
4
+ startedAt: string;
5
+ ipcUrl: string;
6
+ bearerToken: string;
7
+ }
8
+ export declare function mintBearerToken(): string;
9
+ export declare function writeDiscoveryFile(path: string, record: DiscoveryRecord): void;
10
+ export declare function readDiscoveryFile(path: string): DiscoveryRecord | null;
11
+ export declare function deleteDiscoveryFile(path: string): void;
12
+ //# sourceMappingURL=discovery-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-file.d.ts","sourceRoot":"","sources":["../../src/broker/discovery-file.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAGD,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAMD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,eAAe,GACtB,IAAI,CA4BN;AAMD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAetE;AAGD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAOtD"}
@@ -0,0 +1,77 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { chmodSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ export function mintBearerToken() {
5
+ return randomBytes(32).toString("base64url");
6
+ }
7
+ export function writeDiscoveryFile(path, record) {
8
+ if (record.version !== 1) {
9
+ throw new Error(`unsupported discovery record version: ${record.version}`);
10
+ }
11
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
12
+ const tmp = `${path}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
13
+ const payload = JSON.stringify(record, null, 2);
14
+ writeFileSync(tmp, payload, { mode: 0o600, encoding: "utf8" });
15
+ try {
16
+ chmodSync(tmp, 0o600);
17
+ }
18
+ catch {
19
+ }
20
+ try {
21
+ renameSync(tmp, path);
22
+ }
23
+ catch (err) {
24
+ try {
25
+ unlinkSync(tmp);
26
+ }
27
+ catch {
28
+ }
29
+ throw err;
30
+ }
31
+ }
32
+ export function readDiscoveryFile(path) {
33
+ let raw;
34
+ try {
35
+ raw = readFileSync(path, "utf8");
36
+ }
37
+ catch (err) {
38
+ if (isNodeErr(err, "ENOENT"))
39
+ return null;
40
+ throw err;
41
+ }
42
+ try {
43
+ const parsed = JSON.parse(raw);
44
+ if (!isDiscoveryRecord(parsed))
45
+ return null;
46
+ return parsed;
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ export function deleteDiscoveryFile(path) {
53
+ try {
54
+ unlinkSync(path);
55
+ }
56
+ catch (err) {
57
+ if (isNodeErr(err, "ENOENT"))
58
+ return;
59
+ throw err;
60
+ }
61
+ }
62
+ function isDiscoveryRecord(value) {
63
+ if (typeof value !== "object" || value === null)
64
+ return false;
65
+ const v = value;
66
+ return (v.version === 1 &&
67
+ typeof v.pid === "number" &&
68
+ typeof v.startedAt === "string" &&
69
+ typeof v.ipcUrl === "string" &&
70
+ typeof v.bearerToken === "string");
71
+ }
72
+ function isNodeErr(err, code) {
73
+ return (typeof err === "object" &&
74
+ err !== null &&
75
+ "code" in err &&
76
+ err.code === code);
77
+ }
@@ -0,0 +1,53 @@
1
+ import type WebSocket from "ws";
2
+ import { CorrelationRingBuffer } from "./correlation-ring.js";
3
+ export interface DisplayMetadata {
4
+ session_name?: string;
5
+ kind: string;
6
+ started_at: string;
7
+ workspace?: string;
8
+ tracking_ref?: string;
9
+ task_hint?: string;
10
+ }
11
+ export interface BrokerEndpointEntry {
12
+ endpoint_id: string;
13
+ agent_id: string;
14
+ plugin_pid: number;
15
+ ipc_ws: WebSocket;
16
+ state: "active" | "reconnecting";
17
+ state_since: Date;
18
+ grace_deadline?: Date;
19
+ display_metadata: DisplayMetadata;
20
+ correlation_ring: CorrelationRingBuffer;
21
+ }
22
+ export interface RegisterArgs {
23
+ endpoint_id: string;
24
+ agent_id: string;
25
+ plugin_pid: number;
26
+ ipc_ws: WebSocket;
27
+ display_metadata: DisplayMetadata;
28
+ }
29
+ export declare class EndpointRegistry {
30
+ private readonly byId;
31
+ register(args: RegisterArgs): BrokerEndpointEntry;
32
+ get(endpoint_id: string): BrokerEndpointEntry | undefined;
33
+ unregister(endpoint_id: string): BrokerEndpointEntry | undefined;
34
+ markReconnecting(endpoint_id: string, grace_deadline: Date): BrokerEndpointEntry;
35
+ markActive(endpoint_id: string, new_ws: WebSocket): BrokerEndpointEntry;
36
+ preconditionForReattach(endpoint_id: string, plugin_pid: number): BrokerEndpointEntry | undefined;
37
+ getReattachStatus(endpoint_id: string, plugin_pid: number): {
38
+ ok: true;
39
+ entry: BrokerEndpointEntry;
40
+ } | {
41
+ ok: false;
42
+ reason: "endpoint_unknown";
43
+ } | {
44
+ ok: false;
45
+ reason: "reattach_pid_mismatch";
46
+ } | {
47
+ ok: false;
48
+ reason: "endpoint_not_reconnecting";
49
+ };
50
+ list(): BrokerEndpointEntry[];
51
+ size(): number;
52
+ }
53
+ //# sourceMappingURL=endpoint-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint-registry.d.ts","sourceRoot":"","sources":["../../src/broker/endpoint-registry.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,SAAS,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,cAAc,CAAC;IACjC,WAAW,EAAE,IAAI,CAAC;IAElB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,gBAAgB,EAAE,eAAe,CAAC;IAClC,gBAAgB,EAAE,qBAAqB,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,gBAAgB,EAAE,eAAe,CAAC;CACnC;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0C;IAG/D,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB;IAkBjD,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAKzD,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAWhE,gBAAgB,CACd,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,IAAI,GACnB,mBAAmB;IAoBtB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,mBAAmB;IA8BvE,uBAAuB,CACrB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,mBAAmB,GAAG,SAAS;IAYlC,iBAAiB,CACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GAEhB;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,mBAAmB,CAAA;KAAE,GACxC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,GACzC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAA;KAAE,GAC9C;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,2BAA2B,CAAA;KAAE;IAWtD,IAAI,IAAI,mBAAmB,EAAE;IAK7B,IAAI,IAAI,MAAM;CAGf"}