@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.
- package/LICENSE +21 -0
- package/README.md +35 -0
- package/dist/broker/broker-daemon.d.ts +71 -0
- package/dist/broker/broker-daemon.d.ts.map +1 -0
- package/dist/broker/broker-daemon.js +837 -0
- package/dist/broker/claude-code-spawn-driver.d.ts +14 -0
- package/dist/broker/claude-code-spawn-driver.d.ts.map +1 -0
- package/dist/broker/claude-code-spawn-driver.js +39 -0
- package/dist/broker/closed-endpoint-lookup.d.ts +25 -0
- package/dist/broker/closed-endpoint-lookup.d.ts.map +1 -0
- package/dist/broker/closed-endpoint-lookup.js +59 -0
- package/dist/broker/codex-spawn-driver-stub.d.ts +7 -0
- package/dist/broker/codex-spawn-driver-stub.d.ts.map +1 -0
- package/dist/broker/codex-spawn-driver-stub.js +13 -0
- package/dist/broker/connector-ws.d.ts +47 -0
- package/dist/broker/connector-ws.d.ts.map +1 -0
- package/dist/broker/connector-ws.js +60 -0
- package/dist/broker/control-event-dispatcher.d.ts +21 -0
- package/dist/broker/control-event-dispatcher.d.ts.map +1 -0
- package/dist/broker/control-event-dispatcher.js +45 -0
- package/dist/broker/control-event-types.d.ts +28 -0
- package/dist/broker/control-event-types.d.ts.map +1 -0
- package/dist/broker/control-event-types.js +1 -0
- package/dist/broker/correlation-ring.d.ts +10 -0
- package/dist/broker/correlation-ring.d.ts.map +1 -0
- package/dist/broker/correlation-ring.js +32 -0
- package/dist/broker/discovery-file.d.ts +12 -0
- package/dist/broker/discovery-file.d.ts.map +1 -0
- package/dist/broker/discovery-file.js +77 -0
- package/dist/broker/endpoint-registry.d.ts +53 -0
- package/dist/broker/endpoint-registry.d.ts.map +1 -0
- package/dist/broker/endpoint-registry.js +83 -0
- package/dist/broker/endpoint-state-machine.d.ts +40 -0
- package/dist/broker/endpoint-state-machine.d.ts.map +1 -0
- package/dist/broker/endpoint-state-machine.js +92 -0
- package/dist/broker/entry.d.ts +13 -0
- package/dist/broker/entry.d.ts.map +1 -0
- package/dist/broker/entry.js +235 -0
- package/dist/broker/grace-timer.d.ts +9 -0
- package/dist/broker/grace-timer.d.ts.map +1 -0
- package/dist/broker/grace-timer.js +34 -0
- package/dist/broker/ipc-server.d.ts +79 -0
- package/dist/broker/ipc-server.d.ts.map +1 -0
- package/dist/broker/ipc-server.js +263 -0
- package/dist/broker/logger.d.ts +10 -0
- package/dist/broker/logger.d.ts.map +1 -0
- package/dist/broker/logger.js +34 -0
- package/dist/broker/network-presence-changed-event-types.d.ts +8 -0
- package/dist/broker/network-presence-changed-event-types.d.ts.map +1 -0
- package/dist/broker/network-presence-changed-event-types.js +1 -0
- package/dist/broker/network-presence-emitter.d.ts +22 -0
- package/dist/broker/network-presence-emitter.d.ts.map +1 -0
- package/dist/broker/network-presence-emitter.js +150 -0
- package/dist/broker/network-presence.d.ts +31 -0
- package/dist/broker/network-presence.d.ts.map +1 -0
- package/dist/broker/network-presence.js +109 -0
- package/dist/broker/paths.d.ts +11 -0
- package/dist/broker/paths.d.ts.map +1 -0
- package/dist/broker/paths.js +30 -0
- package/dist/broker/plugin-liveness.d.ts +2 -0
- package/dist/broker/plugin-liveness.d.ts.map +1 -0
- package/dist/broker/plugin-liveness.js +15 -0
- package/dist/broker/received-message-correlation-cache.d.ts +23 -0
- package/dist/broker/received-message-correlation-cache.d.ts.map +1 -0
- package/dist/broker/received-message-correlation-cache.js +114 -0
- package/dist/broker/reconnecting-buffer.d.ts +23 -0
- package/dist/broker/reconnecting-buffer.d.ts.map +1 -0
- package/dist/broker/reconnecting-buffer.js +107 -0
- package/dist/broker/routing-table.d.ts +22 -0
- package/dist/broker/routing-table.d.ts.map +1 -0
- package/dist/broker/routing-table.js +35 -0
- package/dist/broker/runtime-endpoint-port.d.ts +20 -0
- package/dist/broker/runtime-endpoint-port.d.ts.map +1 -0
- package/dist/broker/runtime-endpoint-port.js +1 -0
- package/dist/broker/services-event-client.d.ts +21 -0
- package/dist/broker/services-event-client.d.ts.map +1 -0
- package/dist/broker/services-event-client.js +221 -0
- package/dist/broker/spawn-correlation.d.ts +28 -0
- package/dist/broker/spawn-correlation.d.ts.map +1 -0
- package/dist/broker/spawn-correlation.js +77 -0
- package/dist/broker/spawn-driver.d.ts +27 -0
- package/dist/broker/spawn-driver.d.ts.map +1 -0
- package/dist/broker/spawn-driver.js +15 -0
- package/dist/broker/task-hint-handler.d.ts +21 -0
- package/dist/broker/task-hint-handler.d.ts.map +1 -0
- package/dist/broker/task-hint-handler.js +33 -0
- package/dist/broker/transition-state-retry-queue.d.ts +20 -0
- package/dist/broker/transition-state-retry-queue.d.ts.map +1 -0
- package/dist/broker/transition-state-retry-queue.js +48 -0
- package/dist/broker/undispatched-changed-event-types.d.ts +29 -0
- package/dist/broker/undispatched-changed-event-types.d.ts.map +1 -0
- package/dist/broker/undispatched-changed-event-types.js +14 -0
- package/dist/broker/undispatched-emitter.d.ts +22 -0
- package/dist/broker/undispatched-emitter.d.ts.map +1 -0
- package/dist/broker/undispatched-emitter.js +149 -0
- package/dist/broker/undispatched-inbox.d.ts +26 -0
- package/dist/broker/undispatched-inbox.d.ts.map +1 -0
- package/dist/broker/undispatched-inbox.js +53 -0
- package/dist/broker/version-handshake.d.ts +30 -0
- package/dist/broker/version-handshake.d.ts.map +1 -0
- package/dist/broker/version-handshake.js +47 -0
- package/dist/broker-client/broker-client.d.ts +65 -0
- package/dist/broker-client/broker-client.d.ts.map +1 -0
- package/dist/broker-client/broker-client.js +165 -0
- package/dist/broker-client/lazy-spawn.d.ts +18 -0
- package/dist/broker-client/lazy-spawn.d.ts.map +1 -0
- package/dist/broker-client/lazy-spawn.js +61 -0
- package/dist/config-fs.d.ts +4 -0
- package/dist/config-fs.d.ts.map +1 -0
- package/dist/config-fs.js +23 -0
- package/dist/connector-client.d.ts +65 -0
- package/dist/connector-client.d.ts.map +1 -0
- package/dist/connector-client.js +364 -0
- package/dist/environment-context.d.ts +21 -0
- package/dist/environment-context.d.ts.map +1 -0
- package/dist/environment-context.js +39 -0
- package/dist/platform-client.d.ts +84 -0
- package/dist/platform-client.d.ts.map +1 -0
- package/dist/platform-client.js +94 -0
- package/dist/runtime-endpoint-client.d.ts +74 -0
- package/dist/runtime-endpoint-client.d.ts.map +1 -0
- package/dist/runtime-endpoint-client.js +163 -0
- package/dist/types.d.ts +90 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +38 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
export const IPC_PROTOCOL_VERSION = "1.0";
|
|
3
|
+
export const SERVER_CAPABILITIES = Object.freeze({
|
|
4
|
+
endpoint_metadata_v1: true,
|
|
5
|
+
remote_spawn_v1: false,
|
|
6
|
+
undispatched_inbox_v1: false,
|
|
7
|
+
});
|
|
8
|
+
export function handleInitialize(req) {
|
|
9
|
+
if (typeof req.client_protocol_version !== "string") {
|
|
10
|
+
return {
|
|
11
|
+
status: 400,
|
|
12
|
+
body: {
|
|
13
|
+
error: "bad_request",
|
|
14
|
+
message: "client_protocol_version is required and must be a string",
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (typeof req.client_kind !== "string" || !req.client_kind) {
|
|
19
|
+
return {
|
|
20
|
+
status: 400,
|
|
21
|
+
body: {
|
|
22
|
+
error: "bad_request",
|
|
23
|
+
message: "client_kind is required and must be a non-empty string",
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const clientMajor = req.client_protocol_version.split(".")[0];
|
|
28
|
+
const serverMajor = IPC_PROTOCOL_VERSION.split(".")[0];
|
|
29
|
+
if (clientMajor !== serverMajor) {
|
|
30
|
+
return {
|
|
31
|
+
status: 400,
|
|
32
|
+
body: {
|
|
33
|
+
error: "protocol_version_mismatch",
|
|
34
|
+
message: `broker IPC protocol major ${serverMajor} does not match client ` +
|
|
35
|
+
`protocol major ${clientMajor}`,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
status: 200,
|
|
41
|
+
body: {
|
|
42
|
+
server_protocol_version: IPC_PROTOCOL_VERSION,
|
|
43
|
+
server_capabilities: { ...SERVER_CAPABILITIES },
|
|
44
|
+
session_id: randomUUID(),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { type InitializeResponseBody } from "../broker/version-handshake.js";
|
|
3
|
+
export interface BrokerClientDiscoverOptions {
|
|
4
|
+
accountId: string;
|
|
5
|
+
runtimeToken: string;
|
|
6
|
+
userDataDir?: string;
|
|
7
|
+
env?: Record<string, string>;
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
brokerEntry?: string;
|
|
10
|
+
nodeBinary?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface BrokerClientConnectOptions {
|
|
13
|
+
pluginPid: number;
|
|
14
|
+
clientKind: string;
|
|
15
|
+
clientVersion: string;
|
|
16
|
+
}
|
|
17
|
+
export interface RegisterEndpointArgs {
|
|
18
|
+
agentId: string;
|
|
19
|
+
kind: string;
|
|
20
|
+
sessionName?: string;
|
|
21
|
+
workspace?: string;
|
|
22
|
+
trackingRef?: string;
|
|
23
|
+
taskHint?: string;
|
|
24
|
+
spawnToken?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RegisterEndpointOutcome {
|
|
27
|
+
endpoint_id: string;
|
|
28
|
+
}
|
|
29
|
+
export interface BrokerInboundMessage {
|
|
30
|
+
from: string;
|
|
31
|
+
content: string;
|
|
32
|
+
contentType: string;
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
type Events = {
|
|
36
|
+
message_received: (msg: BrokerInboundMessage) => void;
|
|
37
|
+
disconnected: () => void;
|
|
38
|
+
error: (err: Error) => void;
|
|
39
|
+
};
|
|
40
|
+
export declare class BrokerClient extends EventEmitter {
|
|
41
|
+
private readonly handle;
|
|
42
|
+
private ws;
|
|
43
|
+
private pluginPid;
|
|
44
|
+
private _sessionId;
|
|
45
|
+
private constructor();
|
|
46
|
+
static discover(opts: BrokerClientDiscoverOptions): Promise<BrokerClient>;
|
|
47
|
+
get spawnedNew(): boolean;
|
|
48
|
+
get ipcUrl(): string;
|
|
49
|
+
get sessionId(): string | null;
|
|
50
|
+
connect(opts: BrokerClientConnectOptions): Promise<InitializeResponseBody>;
|
|
51
|
+
registerEndpoint(args: RegisterEndpointArgs): Promise<RegisterEndpointOutcome>;
|
|
52
|
+
send(endpointId: string, to: string, content: string, contentType?: string, metadata?: Record<string, unknown>): Promise<{
|
|
53
|
+
messageId: string;
|
|
54
|
+
status: string;
|
|
55
|
+
}>;
|
|
56
|
+
close(endpointId?: string): Promise<void>;
|
|
57
|
+
on<K extends keyof Events>(event: K, listener: Events[K]): this;
|
|
58
|
+
on(event: string | symbol, listener: (...args: unknown[]) => void): this;
|
|
59
|
+
emit<K extends keyof Events>(event: K, ...args: Parameters<Events[K]>): boolean;
|
|
60
|
+
emit(event: string | symbol, ...args: unknown[]): boolean;
|
|
61
|
+
private httpJson;
|
|
62
|
+
private handleFrame;
|
|
63
|
+
}
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=broker-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker-client.d.ts","sourceRoot":"","sources":["../../src/broker-client/broker-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
import { resolveBrokerPaths } from "../broker/paths.js";
|
|
4
|
+
import { IPC_PROTOCOL_VERSION, } from "../broker/version-handshake.js";
|
|
5
|
+
import { discoverBroker } from "./lazy-spawn.js";
|
|
6
|
+
export class BrokerClient extends EventEmitter {
|
|
7
|
+
handle;
|
|
8
|
+
ws = null;
|
|
9
|
+
pluginPid = null;
|
|
10
|
+
_sessionId = null;
|
|
11
|
+
constructor(handle) {
|
|
12
|
+
super();
|
|
13
|
+
this.handle = handle;
|
|
14
|
+
}
|
|
15
|
+
static async discover(opts) {
|
|
16
|
+
const paths = resolveBrokerPaths(opts.accountId, opts.runtimeToken, {
|
|
17
|
+
userDataDir: opts.userDataDir,
|
|
18
|
+
});
|
|
19
|
+
const handle = await discoverBroker({
|
|
20
|
+
discoveryFile: paths.discoveryFile,
|
|
21
|
+
timeoutMs: opts.timeoutMs,
|
|
22
|
+
brokerEntry: opts.brokerEntry,
|
|
23
|
+
nodeBinary: opts.nodeBinary,
|
|
24
|
+
env: {
|
|
25
|
+
MASONS_BROKER_ACCOUNT_ID: opts.accountId,
|
|
26
|
+
...(opts.userDataDir
|
|
27
|
+
? { MASONS_BROKER_USER_DATA: opts.userDataDir }
|
|
28
|
+
: {}),
|
|
29
|
+
...(opts.env ?? {}),
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
return new BrokerClient(handle);
|
|
33
|
+
}
|
|
34
|
+
get spawnedNew() {
|
|
35
|
+
return this.handle.spawned;
|
|
36
|
+
}
|
|
37
|
+
get ipcUrl() {
|
|
38
|
+
return this.handle.record.ipcUrl;
|
|
39
|
+
}
|
|
40
|
+
get sessionId() {
|
|
41
|
+
return this._sessionId;
|
|
42
|
+
}
|
|
43
|
+
async connect(opts) {
|
|
44
|
+
if (this.ws) {
|
|
45
|
+
throw new Error("BrokerClient already connected");
|
|
46
|
+
}
|
|
47
|
+
this.pluginPid = opts.pluginPid;
|
|
48
|
+
const initRes = await this.httpJson("POST", "/v1/initialize", {
|
|
49
|
+
client_protocol_version: IPC_PROTOCOL_VERSION,
|
|
50
|
+
client_kind: opts.clientKind,
|
|
51
|
+
client_version: opts.clientVersion,
|
|
52
|
+
capabilities: { endpoint_metadata_v1: true },
|
|
53
|
+
});
|
|
54
|
+
this._sessionId = initRes.session_id;
|
|
55
|
+
const wsUrl = `${this.handle.record.ipcUrl.replace(/^http/, "ws")}/v1/stream`;
|
|
56
|
+
const ws = new WebSocket(wsUrl, {
|
|
57
|
+
headers: {
|
|
58
|
+
Authorization: `Bearer ${this.handle.record.bearerToken}`,
|
|
59
|
+
"x-plugin-pid": String(opts.pluginPid),
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
this.ws = ws;
|
|
63
|
+
await new Promise((resolve, reject) => {
|
|
64
|
+
const onOpen = () => {
|
|
65
|
+
ws.off("error", onError);
|
|
66
|
+
resolve();
|
|
67
|
+
};
|
|
68
|
+
const onError = (err) => {
|
|
69
|
+
ws.off("open", onOpen);
|
|
70
|
+
reject(err);
|
|
71
|
+
};
|
|
72
|
+
ws.once("open", onOpen);
|
|
73
|
+
ws.once("error", onError);
|
|
74
|
+
});
|
|
75
|
+
ws.on("message", (data) => this.handleFrame(data.toString()));
|
|
76
|
+
ws.on("close", () => {
|
|
77
|
+
this.ws = null;
|
|
78
|
+
this.emit("disconnected");
|
|
79
|
+
});
|
|
80
|
+
ws.on("error", (err) => this.emit("error", err));
|
|
81
|
+
return initRes;
|
|
82
|
+
}
|
|
83
|
+
async registerEndpoint(args) {
|
|
84
|
+
if (this.pluginPid === null) {
|
|
85
|
+
throw new Error("BrokerClient.connect must be called before registerEndpoint");
|
|
86
|
+
}
|
|
87
|
+
return this.httpJson("POST", "/v1/endpoint/register", {
|
|
88
|
+
agent_id: args.agentId,
|
|
89
|
+
plugin_pid: this.pluginPid,
|
|
90
|
+
kind: args.kind,
|
|
91
|
+
session_name: args.sessionName,
|
|
92
|
+
workspace: args.workspace,
|
|
93
|
+
tracking_ref: args.trackingRef,
|
|
94
|
+
task_hint: args.taskHint,
|
|
95
|
+
spawn_token: args.spawnToken,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
async send(endpointId, to, content, contentType = "text", metadata) {
|
|
99
|
+
return this.httpJson("POST", "/v1/send", {
|
|
100
|
+
endpoint_id: endpointId,
|
|
101
|
+
to,
|
|
102
|
+
content,
|
|
103
|
+
contentType,
|
|
104
|
+
metadata,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async close(endpointId) {
|
|
108
|
+
if (endpointId) {
|
|
109
|
+
try {
|
|
110
|
+
await this.httpJson("DELETE", `/v1/endpoint/${encodeURIComponent(endpointId)}`);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (this.ws &&
|
|
116
|
+
(this.ws.readyState === WebSocket.OPEN ||
|
|
117
|
+
this.ws.readyState === WebSocket.CONNECTING)) {
|
|
118
|
+
this.ws.close(1000, "client_close");
|
|
119
|
+
}
|
|
120
|
+
this.ws = null;
|
|
121
|
+
}
|
|
122
|
+
on(event, listener) {
|
|
123
|
+
return super.on(event, listener);
|
|
124
|
+
}
|
|
125
|
+
emit(event, ...args) {
|
|
126
|
+
return super.emit(event, ...args);
|
|
127
|
+
}
|
|
128
|
+
async httpJson(method, path, body) {
|
|
129
|
+
const res = await fetch(`${this.handle.record.ipcUrl}${path}`, {
|
|
130
|
+
method,
|
|
131
|
+
headers: {
|
|
132
|
+
Authorization: `Bearer ${this.handle.record.bearerToken}`,
|
|
133
|
+
...(body ? { "Content-Type": "application/json" } : {}),
|
|
134
|
+
},
|
|
135
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
136
|
+
});
|
|
137
|
+
if (!res.ok) {
|
|
138
|
+
const errText = await res.text().catch(() => "");
|
|
139
|
+
throw new Error(`broker ${method} ${path} failed: ${res.status} ${errText}`);
|
|
140
|
+
}
|
|
141
|
+
return (await res.json());
|
|
142
|
+
}
|
|
143
|
+
handleFrame(raw) {
|
|
144
|
+
let parsed;
|
|
145
|
+
try {
|
|
146
|
+
parsed = JSON.parse(raw);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
this.emit("error", new Error("BrokerClient received non-JSON frame"));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (!parsed || typeof parsed !== "object" || !("event" in parsed))
|
|
153
|
+
return;
|
|
154
|
+
const event = parsed.event;
|
|
155
|
+
if (event === "message_received") {
|
|
156
|
+
const msg = parsed;
|
|
157
|
+
this.emit("message_received", {
|
|
158
|
+
from: msg.from,
|
|
159
|
+
content: msg.content,
|
|
160
|
+
contentType: msg.contentType,
|
|
161
|
+
metadata: msg.metadata,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type DiscoveryRecord } from "../broker/discovery-file.js";
|
|
2
|
+
export interface LazySpawnOptions {
|
|
3
|
+
brokerEntry?: string;
|
|
4
|
+
env?: Record<string, string>;
|
|
5
|
+
nodeBinary?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DiscoverOptions extends LazySpawnOptions {
|
|
8
|
+
discoveryFile: string;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
pollIntervalMs?: number;
|
|
11
|
+
forceSpawn?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface DiscoveryHandle {
|
|
14
|
+
record: DiscoveryRecord;
|
|
15
|
+
spawned: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function discoverBroker(opts: DiscoverOptions): Promise<DiscoveryHandle>;
|
|
18
|
+
//# sourceMappingURL=lazy-spawn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy-spawn.d.ts","sourceRoot":"","sources":["../../src/broker-client/lazy-spawn.ts"],"names":[],"mappings":"AA0CA,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,gBAAgB;IAE/B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IAEvD,aAAa,EAAE,MAAM,CAAC;IAEtB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,eAAe,CAAC;IAExB,OAAO,EAAE,OAAO,CAAC;CAClB;AAMD,wBAAsB,cAAc,CAClC,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,eAAe,CAAC,CA8B1B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { readDiscoveryFile, } from "../broker/discovery-file.js";
|
|
4
|
+
const DEFAULT_POLL_INTERVAL_MS = 100;
|
|
5
|
+
const DEFAULT_DISCOVER_TIMEOUT_MS = 5_000;
|
|
6
|
+
const DEFAULT_HEALTH_TIMEOUT_MS = 2_000;
|
|
7
|
+
export async function discoverBroker(opts) {
|
|
8
|
+
const deadline = Date.now() + (opts.timeoutMs ?? DEFAULT_DISCOVER_TIMEOUT_MS);
|
|
9
|
+
const poll = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
10
|
+
if (!opts.forceSpawn) {
|
|
11
|
+
const existing = readDiscoveryFile(opts.discoveryFile);
|
|
12
|
+
if (existing &&
|
|
13
|
+
(await probeHealth(existing.ipcUrl, existing.bearerToken))) {
|
|
14
|
+
return { record: existing, spawned: false };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
spawnDaemon(opts);
|
|
18
|
+
while (Date.now() < deadline) {
|
|
19
|
+
const rec = readDiscoveryFile(opts.discoveryFile);
|
|
20
|
+
if (rec && (await probeHealth(rec.ipcUrl, rec.bearerToken))) {
|
|
21
|
+
return { record: rec, spawned: true };
|
|
22
|
+
}
|
|
23
|
+
await sleep(poll);
|
|
24
|
+
}
|
|
25
|
+
throw new Error(`broker did not become healthy within ${opts.timeoutMs ?? DEFAULT_DISCOVER_TIMEOUT_MS}ms; ` +
|
|
26
|
+
`check ${opts.discoveryFile} and the daemon log`);
|
|
27
|
+
}
|
|
28
|
+
function spawnDaemon(opts) {
|
|
29
|
+
const entry = opts.brokerEntry ?? resolveDefaultBrokerEntry();
|
|
30
|
+
const child = spawn(opts.nodeBinary ?? process.execPath, [entry], {
|
|
31
|
+
detached: true,
|
|
32
|
+
stdio: "ignore",
|
|
33
|
+
windowsHide: true,
|
|
34
|
+
env: { ...process.env, ...(opts.env ?? {}) },
|
|
35
|
+
});
|
|
36
|
+
child.unref();
|
|
37
|
+
}
|
|
38
|
+
function resolveDefaultBrokerEntry() {
|
|
39
|
+
const self = fileURLToPath(import.meta.url);
|
|
40
|
+
return self.replace(/broker-client\/lazy-spawn\.(c?js|ts)$/, "broker/entry.$1");
|
|
41
|
+
}
|
|
42
|
+
async function probeHealth(ipcUrl, bearerToken) {
|
|
43
|
+
const ctrl = new AbortController();
|
|
44
|
+
const timer = setTimeout(() => ctrl.abort(), DEFAULT_HEALTH_TIMEOUT_MS);
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch(`${ipcUrl}/health`, {
|
|
47
|
+
headers: { Authorization: `Bearer ${bearerToken}` },
|
|
48
|
+
signal: ctrl.signal,
|
|
49
|
+
});
|
|
50
|
+
return res.ok;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function sleep(ms) {
|
|
60
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-fs.d.ts","sourceRoot":"","sources":["../src/config-fs.ts"],"names":[],"mappings":"AAKA,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAMD,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAOnE;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
export function getOpenClawHome() {
|
|
5
|
+
return process.env.OPENCLAW_HOME || join(homedir(), ".openclaw");
|
|
6
|
+
}
|
|
7
|
+
function getConfigPath() {
|
|
8
|
+
return join(getOpenClawHome(), "openclaw.json");
|
|
9
|
+
}
|
|
10
|
+
export async function readConfig() {
|
|
11
|
+
try {
|
|
12
|
+
const raw = await readFile(getConfigPath(), "utf-8");
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function persistConfig(config) {
|
|
20
|
+
const configPath = getConfigPath();
|
|
21
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
22
|
+
await writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
23
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { type AddressedMessageEvent, type DeliveryPendingEvent, type DeliveryStatusEvent, type SendAckEvent, type StructuredErrorEvent } from "./types.js";
|
|
3
|
+
export declare class ConnectorError extends Error {
|
|
4
|
+
readonly code: string;
|
|
5
|
+
readonly to?: string;
|
|
6
|
+
constructor(message: string, code: string, to?: string);
|
|
7
|
+
}
|
|
8
|
+
type ConnectorClientEvents = {
|
|
9
|
+
message_received: (event: AddressedMessageEvent) => void;
|
|
10
|
+
send_ack: (event: SendAckEvent) => void;
|
|
11
|
+
delivery_pending: (event: DeliveryPendingEvent) => void;
|
|
12
|
+
delivery_status: (event: DeliveryStatusEvent) => void;
|
|
13
|
+
structured_error: (event: StructuredErrorEvent) => void;
|
|
14
|
+
error: (error: Error) => void;
|
|
15
|
+
connected: () => void;
|
|
16
|
+
disconnected: () => void;
|
|
17
|
+
};
|
|
18
|
+
export declare class ConnectorClient extends EventEmitter {
|
|
19
|
+
private readonly url;
|
|
20
|
+
private readonly token;
|
|
21
|
+
private ws;
|
|
22
|
+
private intentionalClose;
|
|
23
|
+
private backoffMs;
|
|
24
|
+
private alreadyConnectedRetries;
|
|
25
|
+
private reconnectTimer;
|
|
26
|
+
private registerResolve;
|
|
27
|
+
private registerReject;
|
|
28
|
+
private registerTimer;
|
|
29
|
+
private lastKnownSeq;
|
|
30
|
+
private pendingSends;
|
|
31
|
+
constructor(url: string, token: string);
|
|
32
|
+
connect(): Promise<void>;
|
|
33
|
+
disconnect(): void;
|
|
34
|
+
send(to: string, content: string, contentType?: string, metadata?: Record<string, unknown>): Promise<SendAckEvent>;
|
|
35
|
+
sendTyping(to: string, isTyping: boolean): boolean;
|
|
36
|
+
ackDelivery(upTo: string): boolean;
|
|
37
|
+
on<K extends keyof ConnectorClientEvents>(event: K, listener: ConnectorClientEvents[K]): this;
|
|
38
|
+
on(event: string | symbol, listener: (...args: unknown[]) => void): this;
|
|
39
|
+
once<K extends keyof ConnectorClientEvents>(event: K, listener: ConnectorClientEvents[K]): this;
|
|
40
|
+
once(event: string | symbol, listener: (...args: unknown[]) => void): this;
|
|
41
|
+
off<K extends keyof ConnectorClientEvents>(event: K, listener: ConnectorClientEvents[K]): this;
|
|
42
|
+
off(event: string | symbol, listener: (...args: unknown[]) => void): this;
|
|
43
|
+
emit<K extends keyof ConnectorClientEvents>(event: K, ...args: Parameters<ConnectorClientEvents[K]>): boolean;
|
|
44
|
+
emit(event: string | symbol, ...args: unknown[]): boolean;
|
|
45
|
+
private doConnect;
|
|
46
|
+
private sendRegister;
|
|
47
|
+
private startRegisterTimeout;
|
|
48
|
+
private resolveRegister;
|
|
49
|
+
private rejectRegister;
|
|
50
|
+
private handleMessage;
|
|
51
|
+
private dispatchAddressed;
|
|
52
|
+
private handleRegisterAck;
|
|
53
|
+
private handleSendAck;
|
|
54
|
+
private handleStructuredError;
|
|
55
|
+
private handleClose;
|
|
56
|
+
private handleError;
|
|
57
|
+
private scheduleReconnect;
|
|
58
|
+
private calculateBackoff;
|
|
59
|
+
private nextExponentialBackoff;
|
|
60
|
+
private clearReconnectTimer;
|
|
61
|
+
private cleanupConnection;
|
|
62
|
+
private sendEvent;
|
|
63
|
+
}
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=connector-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector-client.d.ts","sourceRoot":"","sources":["../src/connector-client.ts"],"names":[],"mappings":"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"}
|