@clawroom/sdk 0.5.24 → 0.5.26

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.
@@ -0,0 +1,297 @@
1
+ /**
2
+ * ClawRoom Machine Client — machine-level auth with multi-agent support.
3
+ * WebSocket primary for real-time push, HTTP polling as fallback.
4
+ */
5
+ import * as os from "node:os";
6
+ import { WsTransport } from "./ws-transport.js";
7
+ const DEFAULT_AGENT_CHAT_PROFILE = {
8
+ role: "No role defined",
9
+ systemPrompt: "No system prompt configured",
10
+ memory: "No memory recorded yet",
11
+ continuityPacket: "No continuity packet available yet",
12
+ };
13
+ const MAX_RECENT_CHAT_IDS = 1000;
14
+ export class ClawroomMachineClient {
15
+ options;
16
+ heartbeatTimer = null;
17
+ pollTimer = null;
18
+ heartbeatInFlight = false;
19
+ pollInFlight = false;
20
+ taskHandler = null;
21
+ chatHandler = null;
22
+ connectHandler = null;
23
+ disconnectHandler = null;
24
+ _connected = false;
25
+ _stopped = false;
26
+ wsTransport = null;
27
+ recentChatIds = new Map();
28
+ constructor(options) {
29
+ this.options = options;
30
+ }
31
+ get baseUrl() {
32
+ return this.options.endpoint ?? "http://localhost:3000/api/machines";
33
+ }
34
+ get wsUrl() {
35
+ if (this.options.wsUrl)
36
+ return this.options.wsUrl;
37
+ return this.baseUrl.replace(/\/api\/machines$/, "").replace(/^http/, "ws") + "/api/ws";
38
+ }
39
+ async httpRequest(method, path, body) {
40
+ const url = `${this.baseUrl}${path}`;
41
+ const res = await fetch(url, {
42
+ method,
43
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.options.apiKey}` },
44
+ body: body ? JSON.stringify(body) : undefined,
45
+ });
46
+ if (!res.ok)
47
+ throw new Error(`HTTP ${res.status}: ${await res.text()}`);
48
+ const text = await res.text();
49
+ if (!text.trim())
50
+ return null;
51
+ try {
52
+ return JSON.parse(text);
53
+ }
54
+ catch (error) {
55
+ throw new Error(`Invalid JSON from ${path}: ${error instanceof Error ? error.message : "unknown parse error"}`);
56
+ }
57
+ }
58
+ onAgentTask(handler) { this.taskHandler = handler; }
59
+ onAgentChat(handler) { this.chatHandler = handler; }
60
+ onConnected(handler) { this.connectHandler = handler; }
61
+ onDisconnected(handler) { this.disconnectHandler = handler; }
62
+ async sendAgentComplete(agentId, taskId, output, attachments, workRef) {
63
+ await this.httpRequest("POST", "/complete", { agentId, taskId, output, attachments, workRef });
64
+ }
65
+ async sendAgentFail(agentId, taskId, reason, workRef) {
66
+ await this.httpRequest("POST", "/fail", { agentId, taskId, reason, workRef });
67
+ }
68
+ async sendAgentChatReply(agentId, channelId, content, replyTo, workRefs) {
69
+ await this.httpRequest("POST", "/chat-reply", { agentId, channelId, content, replyTo, workRefs });
70
+ }
71
+ async sendAgentTyping(agentId, channelId) {
72
+ await this.httpRequest("POST", "/typing", { agentId, channelId });
73
+ }
74
+ async sendAgentReflection(agentId, reflection) {
75
+ await this.httpRequest("POST", "/reflections", { agentId, ...reflection });
76
+ }
77
+ get connected() { return this._connected; }
78
+ get stopped() { return this._stopped; }
79
+ rememberChat(messageId) {
80
+ if (!messageId)
81
+ return false;
82
+ const now = Date.now();
83
+ for (const [id, seenAt] of this.recentChatIds) {
84
+ if (now - seenAt > 10 * 60_000)
85
+ this.recentChatIds.delete(id);
86
+ }
87
+ if (this.recentChatIds.has(messageId))
88
+ return false;
89
+ if (this.recentChatIds.size >= MAX_RECENT_CHAT_IDS) {
90
+ const oldestId = this.recentChatIds.keys().next().value;
91
+ if (oldestId)
92
+ this.recentChatIds.delete(oldestId);
93
+ }
94
+ this.recentChatIds.set(messageId, now);
95
+ return true;
96
+ }
97
+ markConnected(machineId) {
98
+ if (!this._connected) {
99
+ this._connected = true;
100
+ this.options.log?.info?.("[machine] connected");
101
+ this.connectHandler?.(machineId);
102
+ }
103
+ }
104
+ markDisconnected() {
105
+ if (this._connected) {
106
+ this._connected = false;
107
+ this.options.log?.warn?.("[machine] disconnected");
108
+ this.disconnectHandler?.();
109
+ }
110
+ }
111
+ async pollOnce() {
112
+ if (!this._connected || this.pollInFlight)
113
+ return;
114
+ this.pollInFlight = true;
115
+ try {
116
+ const result = (await this.httpRequest("POST", "/poll", {}));
117
+ for (const agent of result.agents) {
118
+ if (agent.task && this.taskHandler) {
119
+ try {
120
+ this.taskHandler(agent.agentId, agent.task);
121
+ }
122
+ catch (err) {
123
+ this.options.log?.warn?.(`[machine] task dispatch failed for agent ${agent.agentId} task ${agent.task.taskId}: ${err}`);
124
+ }
125
+ }
126
+ if (agent.chat && agent.chat.length > 0 && this.chatHandler) {
127
+ try {
128
+ const freshMessages = agent.chat.filter((message) => this.rememberChat(message.workId ?? message.messageId));
129
+ if (freshMessages.length > 0) {
130
+ this.chatHandler(agent.agentId, freshMessages);
131
+ }
132
+ }
133
+ catch (err) {
134
+ this.options.log?.warn?.(`[machine] chat dispatch failed for agent ${agent.agentId}: ${err}`);
135
+ }
136
+ }
137
+ }
138
+ }
139
+ catch (err) {
140
+ this.options.log?.warn?.(`[machine] poll error: ${err}`);
141
+ }
142
+ finally {
143
+ this.pollInFlight = false;
144
+ }
145
+ }
146
+ connect() {
147
+ this.stopHeartbeat();
148
+ this.stopPolling();
149
+ this.wsTransport?.disconnect();
150
+ this.wsTransport = null;
151
+ this._stopped = false;
152
+ const hostname = this.options.hostname ?? os.hostname();
153
+ const hbBody = {
154
+ hostname,
155
+ capabilities: this.options.capabilities,
156
+ platform: os.platform(),
157
+ architecture: os.arch(),
158
+ osRelease: os.release(),
159
+ };
160
+ const sendHeartbeat = async () => {
161
+ if (this.heartbeatInFlight)
162
+ return;
163
+ this.heartbeatInFlight = true;
164
+ try {
165
+ const result = (await this.httpRequest("POST", "/heartbeat", hbBody));
166
+ this.markConnected(result.machineId);
167
+ }
168
+ catch (err) {
169
+ if (!this.wsTransport?.connected) {
170
+ this.markDisconnected();
171
+ }
172
+ else {
173
+ this.options.log?.warn?.(`[machine] heartbeat failed while WS is still connected: ${err}`);
174
+ }
175
+ throw err;
176
+ }
177
+ finally {
178
+ this.heartbeatInFlight = false;
179
+ }
180
+ };
181
+ // Heartbeat every 30s (always HTTP)
182
+ this.heartbeatTimer = setInterval(() => {
183
+ void sendHeartbeat().catch(() => { });
184
+ }, 30_000);
185
+ sendHeartbeat().catch((err) => this.options.log?.warn?.(`[machine] initial heartbeat failed: ${err}`));
186
+ // WebSocket transport
187
+ this.wsTransport = new WsTransport({
188
+ url: this.wsUrl,
189
+ token: this.options.apiKey,
190
+ log: { info: (m) => this.options.log?.info?.(m), warn: (m) => this.options.log?.warn?.(m) },
191
+ onConnected: () => {
192
+ this.options.log?.info?.("[machine] WebSocket connected");
193
+ },
194
+ onDisconnected: () => {
195
+ this.options.log?.info?.("[machine] WebSocket disconnected, HTTP polling active");
196
+ },
197
+ onMessage: (msg) => {
198
+ const message = getRecord(msg.message);
199
+ if (msg.type === "message") {
200
+ const targetAgentId = getOptionalString(msg.agentId) ?? getOptionalString(message?.agentId);
201
+ const messageId = getString(message?.id, getString(msg.messageId));
202
+ if (message && targetAgentId && this.chatHandler && this.rememberChat(messageId)) {
203
+ const agentProfile = resolveAgentChatProfile(msg.agentProfile, message?.agentProfile);
204
+ const messages = [{
205
+ type: "server.chat",
206
+ kind: (typeof msg.kind === "string" ? msg.kind : "wake"),
207
+ workId: getString(message?.workId),
208
+ leaseToken: getString(message?.leaseToken),
209
+ messageId,
210
+ channelId: getString(message?.channelId),
211
+ content: getString(message?.content),
212
+ attachments: getAttachments(msg.attachments) ?? getAttachments(message?.attachments),
213
+ isMention: typeof msg.isMention === "boolean" ? msg.isMention : false,
214
+ wakeReason: getWakeReason(msg.wakeReason) ?? getWakeReason(message?.wakeReason),
215
+ triggerReason: getOptionalString(msg.triggerReason) ?? getOptionalString(message?.triggerReason),
216
+ context: getContext(msg.context),
217
+ agentProfile,
218
+ }];
219
+ this.chatHandler(targetAgentId, messages);
220
+ }
221
+ }
222
+ const taskAgentId = getOptionalString(msg.agentId);
223
+ if (msg.type === "task" && taskAgentId && this.taskHandler) {
224
+ this.taskHandler(taskAgentId, msg.task ?? null);
225
+ }
226
+ },
227
+ });
228
+ this.wsTransport.connect();
229
+ // Keep HTTP polling active even when WS is up.
230
+ // Machine WS chat delivery is best-effort; polling is the durable delivery path.
231
+ this.pollTimer = setInterval(async () => {
232
+ await this.pollOnce();
233
+ }, 10_000);
234
+ void this.pollOnce();
235
+ }
236
+ disconnect() {
237
+ this._stopped = true;
238
+ this._connected = false;
239
+ this.stopHeartbeat();
240
+ this.stopPolling();
241
+ this.wsTransport?.disconnect();
242
+ this.wsTransport = null;
243
+ this.recentChatIds.clear();
244
+ }
245
+ stopHeartbeat() {
246
+ if (this.heartbeatTimer) {
247
+ clearInterval(this.heartbeatTimer);
248
+ this.heartbeatTimer = null;
249
+ }
250
+ }
251
+ stopPolling() {
252
+ if (this.pollTimer) {
253
+ clearInterval(this.pollTimer);
254
+ this.pollTimer = null;
255
+ }
256
+ }
257
+ }
258
+ function getRecord(value) {
259
+ if (!value || typeof value !== "object" || Array.isArray(value))
260
+ return null;
261
+ return value;
262
+ }
263
+ function getString(value, fallback = "") {
264
+ return typeof value === "string" ? value : fallback;
265
+ }
266
+ function getOptionalString(value) {
267
+ return typeof value === "string" ? value : undefined;
268
+ }
269
+ function getAttachments(value) {
270
+ return Array.isArray(value) ? value : undefined;
271
+ }
272
+ function getContext(value) {
273
+ return Array.isArray(value) ? value : [];
274
+ }
275
+ function getWakeReason(value) {
276
+ return typeof value === "string" ? value : undefined;
277
+ }
278
+ function getAgentChatProfile(value) {
279
+ const record = getRecord(value);
280
+ if (!record)
281
+ return null;
282
+ return {
283
+ role: getString(record.role, DEFAULT_AGENT_CHAT_PROFILE.role),
284
+ systemPrompt: getString(record.systemPrompt, DEFAULT_AGENT_CHAT_PROFILE.systemPrompt),
285
+ memory: getString(record.memory, DEFAULT_AGENT_CHAT_PROFILE.memory),
286
+ continuityPacket: getString(record.continuityPacket, DEFAULT_AGENT_CHAT_PROFILE.continuityPacket),
287
+ };
288
+ }
289
+ function resolveAgentChatProfile(...values) {
290
+ for (const value of values) {
291
+ const profile = getAgentChatProfile(value);
292
+ if (profile)
293
+ return profile;
294
+ }
295
+ return DEFAULT_AGENT_CHAT_PROFILE;
296
+ }
297
+ //# sourceMappingURL=machine-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-client.js","sourceRoot":"","sources":["../src/machine-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type { AgentChatProfile, AgentWorkRef, ChatAttachmentRef, AgentHeartbeat, AgentResultFile, AgentComplete, AgentProgress, AgentFail, AgentChatReply, AgentTyping, AgentMessage, ServerTask, ServerChatMessage, ServerMessage, RuntimeDef, } from "@clawroom/protocol";
2
+ export { RUNTIMES, BRIDGE_MANAGED_RUNTIME_IDS, RUNTIME_MAP, } from "@clawroom/protocol";
3
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,aAAa,EACb,aAAa,EACb,SAAS,EACT,cAAc,EACd,WAAW,EACX,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,UAAU,GACX,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,QAAQ,EACR,0BAA0B,EAC1B,WAAW,GACZ,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { RUNTIMES, BRIDGE_MANAGED_RUNTIME_IDS, RUNTIME_MAP, } from "@clawroom/protocol";
2
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,QAAQ,EACR,0BAA0B,EAC1B,WAAW,GACZ,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Shared WebSocket transport with auto-reconnect and fallback support.
3
+ * Used by both ClawroomClient and ClawroomMachineClient.
4
+ */
5
+ export type WsLike = {
6
+ readyState: number;
7
+ on: (event: string, listener: (...args: unknown[]) => void) => void;
8
+ removeAllListeners?: (event?: string) => void;
9
+ send: (data: string) => void;
10
+ close: () => void;
11
+ };
12
+ export type WsTransportOptions = {
13
+ url: string;
14
+ token: string;
15
+ onMessage: (msg: Record<string, unknown>) => void;
16
+ onConnected: () => void;
17
+ onDisconnected: () => void;
18
+ createSocket?: (url: string) => WsLike | Promise<WsLike>;
19
+ log?: {
20
+ info?: (message: string) => void;
21
+ warn?: (message: string) => void;
22
+ };
23
+ };
24
+ export declare class WsTransport {
25
+ private static readonly MAX_SEND_QUEUE;
26
+ private ws;
27
+ private options;
28
+ private _connected;
29
+ private stopped;
30
+ private reconnectTimer;
31
+ private reconnectDelay;
32
+ private failCount;
33
+ private sendQueue;
34
+ static readonly MAX_RECONNECT_DELAY = 60000;
35
+ static readonly MAX_RECONNECT_FAILS = 10;
36
+ constructor(options: WsTransportOptions);
37
+ get connected(): boolean;
38
+ connect(): Promise<void>;
39
+ send(msg: Record<string, unknown>): boolean;
40
+ disconnect(): void;
41
+ private handleDisconnect;
42
+ private scheduleReconnect;
43
+ private createSocket;
44
+ private closeSocket;
45
+ private resetReconnectState;
46
+ private flushSendQueue;
47
+ }
48
+ //# sourceMappingURL=ws-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-transport.d.ts","sourceRoot":"","sources":["../src/ws-transport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,MAAM,GAAG;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACpE,kBAAkB,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,GAAG,CAAC,EAAE;QACJ,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAClC,CAAC;CACH,CAAC;AAMF,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;IAC7C,OAAO,CAAC,EAAE,CAAuB;IACjC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,SAAS,CAAgB;IAEjC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,SAAU;IAC7C,MAAM,CAAC,QAAQ,CAAC,mBAAmB,MAAM;gBAE7B,OAAO,EAAE,kBAAkB;IAIvC,IAAI,SAAS,YAA8B;IAErC,OAAO;IAqEb,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IAmB3C,UAAU;IAaV,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,iBAAiB;YAoBX,YAAY;IAgB1B,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,cAAc;CAOvB"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Shared WebSocket transport with auto-reconnect and fallback support.
3
+ * Used by both ClawroomClient and ClawroomMachineClient.
4
+ */
5
+ export class WsTransport {
6
+ static MAX_SEND_QUEUE = 500;
7
+ ws = null;
8
+ options;
9
+ _connected = false;
10
+ stopped = false;
11
+ reconnectTimer = null;
12
+ reconnectDelay = 1000;
13
+ failCount = 0;
14
+ sendQueue = [];
15
+ static MAX_RECONNECT_DELAY = 60_000;
16
+ static MAX_RECONNECT_FAILS = 10;
17
+ constructor(options) {
18
+ this.options = options;
19
+ }
20
+ get connected() { return this._connected; }
21
+ async connect() {
22
+ this.stopped = false;
23
+ if (this.reconnectTimer) {
24
+ clearTimeout(this.reconnectTimer);
25
+ this.reconnectTimer = null;
26
+ }
27
+ if (this.ws && (this.ws.readyState === 0 || this.ws.readyState === 1))
28
+ return;
29
+ if (this.ws) {
30
+ const staleSocket = this.ws;
31
+ this.ws = null;
32
+ this.closeSocket(staleSocket);
33
+ }
34
+ try {
35
+ this.ws = await this.createSocket();
36
+ if (!this.ws)
37
+ return;
38
+ }
39
+ catch {
40
+ this._connected = false;
41
+ this.scheduleReconnect();
42
+ return;
43
+ }
44
+ const socket = this.ws;
45
+ socket.on("open", () => {
46
+ this.reconnectDelay = 1000;
47
+ socket.send(JSON.stringify({ type: "auth", token: this.options.token }));
48
+ });
49
+ socket.on("message", (raw) => {
50
+ if (!raw || typeof raw !== "object" || !("toString" in raw) || typeof raw.toString !== "function")
51
+ return;
52
+ let msg;
53
+ try {
54
+ msg = JSON.parse(raw.toString());
55
+ }
56
+ catch {
57
+ return;
58
+ }
59
+ if (msg.type === "auth_ok") {
60
+ this._connected = true;
61
+ this.failCount = 0;
62
+ this.flushSendQueue(socket);
63
+ this.options.onConnected();
64
+ return;
65
+ }
66
+ if (msg.type === "auth_error") {
67
+ this._connected = false;
68
+ this.options.log?.warn?.(`WS auth failed: ${msg.error ?? "unknown"}`);
69
+ socket.close();
70
+ return;
71
+ }
72
+ if (msg.type === "pong")
73
+ return;
74
+ this.options.onMessage(msg);
75
+ });
76
+ socket.on("close", () => {
77
+ this.handleDisconnect(socket);
78
+ });
79
+ socket.on("error", () => {
80
+ this.handleDisconnect(socket);
81
+ try {
82
+ if (socket.readyState === 0 || socket.readyState === 1)
83
+ socket.close();
84
+ }
85
+ catch {
86
+ /* ignore close errors */
87
+ }
88
+ });
89
+ }
90
+ send(msg) {
91
+ const payload = JSON.stringify(msg);
92
+ if (this._connected && this.ws?.readyState === 1) {
93
+ this.ws.send(payload);
94
+ return true;
95
+ }
96
+ if (!this.stopped) {
97
+ if (!this.sendQueue.includes(payload)) {
98
+ if (this.sendQueue.length >= WsTransport.MAX_SEND_QUEUE) {
99
+ this.sendQueue.shift();
100
+ this.options.log?.warn?.(`WS send queue full; dropping oldest queued message`);
101
+ }
102
+ this.sendQueue.push(payload);
103
+ }
104
+ this.options.log?.warn?.("WS send queued until the socket is ready");
105
+ }
106
+ return false;
107
+ }
108
+ disconnect() {
109
+ this.stopped = true;
110
+ this._connected = false;
111
+ if (this.reconnectTimer) {
112
+ clearTimeout(this.reconnectTimer);
113
+ this.reconnectTimer = null;
114
+ }
115
+ this.resetReconnectState();
116
+ this.sendQueue = [];
117
+ if (this.ws) {
118
+ const socket = this.ws;
119
+ this.ws = null;
120
+ this.closeSocket(socket);
121
+ }
122
+ }
123
+ handleDisconnect(socket) {
124
+ if (this.ws !== socket)
125
+ return;
126
+ this.ws = null;
127
+ const wasConnected = this._connected;
128
+ this._connected = false;
129
+ if (wasConnected)
130
+ this.options.onDisconnected();
131
+ if (!this.stopped)
132
+ this.scheduleReconnect();
133
+ }
134
+ scheduleReconnect() {
135
+ if (this.stopped || this.reconnectTimer)
136
+ return;
137
+ this.failCount++;
138
+ const failedAttempts = this.failCount;
139
+ if (failedAttempts > WsTransport.MAX_RECONNECT_FAILS) {
140
+ this._connected = false;
141
+ this.resetReconnectState();
142
+ this.options.log?.warn?.(`WS reconnect failed ${failedAttempts} times, giving up. HTTP polling active.`);
143
+ return;
144
+ }
145
+ const jitter = Math.random() * 3000;
146
+ this.reconnectTimer = setTimeout(() => {
147
+ this.reconnectTimer = null;
148
+ this.connect();
149
+ }, Math.min(this.reconnectDelay + jitter, WsTransport.MAX_RECONNECT_DELAY));
150
+ this.reconnectDelay = Math.min(this.reconnectDelay * 2, WsTransport.MAX_RECONNECT_DELAY);
151
+ }
152
+ async createSocket() {
153
+ if (this.options.createSocket) {
154
+ return await this.options.createSocket(this.options.url);
155
+ }
156
+ let WebSocket;
157
+ try {
158
+ WebSocket = (await import("ws")).default;
159
+ }
160
+ catch {
161
+ this.options.log?.info?.("ws module not available, skipping WebSocket");
162
+ return null;
163
+ }
164
+ return new WebSocket(this.options.url);
165
+ }
166
+ closeSocket(socket) {
167
+ try {
168
+ socket.removeAllListeners?.();
169
+ socket.close();
170
+ }
171
+ catch {
172
+ /* ignore close errors */
173
+ }
174
+ }
175
+ resetReconnectState() {
176
+ this.reconnectDelay = 1000;
177
+ this.failCount = 0;
178
+ }
179
+ flushSendQueue(socket) {
180
+ while (this.ws === socket && this._connected && socket.readyState === 1 && this.sendQueue.length > 0) {
181
+ const payload = this.sendQueue.shift();
182
+ if (!payload)
183
+ continue;
184
+ socket.send(payload);
185
+ }
186
+ }
187
+ }
188
+ //# sourceMappingURL=ws-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-transport.js","sourceRoot":"","sources":["../src/ws-transport.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,17 @@
1
1
  {
2
2
  "name": "@clawroom/sdk",
3
- "version": "0.5.24",
3
+ "version": "0.5.26",
4
4
  "description": "ClawRoom SDK — polling client and protocol types for connecting any agent to ClawRoom",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
- "main": "./src/index.ts",
8
- "types": "./src/index.ts",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
9
15
  "repository": {
10
16
  "type": "git",
11
17
  "url": "git+https://github.com/clawroom/clawroom.git"
@@ -17,9 +23,18 @@
17
23
  "workspace"
18
24
  ],
19
25
  "files": [
20
- "src"
26
+ "dist"
21
27
  ],
28
+ "scripts": {
29
+ "build": "tsc"
30
+ },
22
31
  "dependencies": {
23
- "@clawroom/protocol": "^0.5.1"
32
+ "@clawroom/protocol": "^0.5.1",
33
+ "ws": "^8.19.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^22.0.0",
37
+ "@types/ws": "^8.5.0",
38
+ "typescript": "^5.7.0"
24
39
  }
25
40
  }