@chucky.cloud/sdk 0.2.5 → 0.3.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 (95) hide show
  1. package/README.md +6 -1
  2. package/dist/browser.cjs +1361 -0
  3. package/dist/browser.cjs.map +1 -0
  4. package/dist/browser.d.cts +1 -0
  5. package/dist/browser.d.ts +1 -8
  6. package/dist/browser.js +1278 -11
  7. package/dist/browser.js.map +1 -1
  8. package/dist/index.cjs +1361 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.d.cts +1973 -0
  11. package/dist/index.d.ts +1953 -48
  12. package/dist/index.js +1278 -72
  13. package/dist/index.js.map +1 -1
  14. package/dist/node.cjs +1361 -0
  15. package/dist/node.cjs.map +1 -0
  16. package/dist/node.d.cts +1 -0
  17. package/dist/node.d.ts +1 -8
  18. package/dist/node.js +1278 -10
  19. package/dist/node.js.map +1 -1
  20. package/package.json +31 -9
  21. package/dist/browser.d.ts.map +0 -1
  22. package/dist/client/ChuckyClient.d.ts +0 -141
  23. package/dist/client/ChuckyClient.d.ts.map +0 -1
  24. package/dist/client/ChuckyClient.js +0 -209
  25. package/dist/client/ChuckyClient.js.map +0 -1
  26. package/dist/client/Session.d.ts +0 -167
  27. package/dist/client/Session.d.ts.map +0 -1
  28. package/dist/client/Session.js +0 -392
  29. package/dist/client/Session.js.map +0 -1
  30. package/dist/client/index.d.ts +0 -10
  31. package/dist/client/index.d.ts.map +0 -1
  32. package/dist/client/index.js +0 -9
  33. package/dist/client/index.js.map +0 -1
  34. package/dist/index.d.ts.map +0 -1
  35. package/dist/node.d.ts.map +0 -1
  36. package/dist/tools/McpServer.d.ts +0 -117
  37. package/dist/tools/McpServer.d.ts.map +0 -1
  38. package/dist/tools/McpServer.js +0 -142
  39. package/dist/tools/McpServer.js.map +0 -1
  40. package/dist/tools/index.d.ts +0 -9
  41. package/dist/tools/index.d.ts.map +0 -1
  42. package/dist/tools/index.js +0 -8
  43. package/dist/tools/index.js.map +0 -1
  44. package/dist/tools/tool.d.ts +0 -146
  45. package/dist/tools/tool.d.ts.map +0 -1
  46. package/dist/tools/tool.js +0 -232
  47. package/dist/tools/tool.js.map +0 -1
  48. package/dist/transport/Transport.d.ts +0 -82
  49. package/dist/transport/Transport.d.ts.map +0 -1
  50. package/dist/transport/Transport.js +0 -47
  51. package/dist/transport/Transport.js.map +0 -1
  52. package/dist/transport/WebSocketTransport.d.ts +0 -78
  53. package/dist/transport/WebSocketTransport.d.ts.map +0 -1
  54. package/dist/transport/WebSocketTransport.js +0 -258
  55. package/dist/transport/WebSocketTransport.js.map +0 -1
  56. package/dist/transport/index.d.ts +0 -10
  57. package/dist/transport/index.d.ts.map +0 -1
  58. package/dist/transport/index.js +0 -8
  59. package/dist/transport/index.js.map +0 -1
  60. package/dist/types/index.d.ts +0 -12
  61. package/dist/types/index.d.ts.map +0 -1
  62. package/dist/types/index.js +0 -8
  63. package/dist/types/index.js.map +0 -1
  64. package/dist/types/messages.d.ts +0 -327
  65. package/dist/types/messages.d.ts.map +0 -1
  66. package/dist/types/messages.js +0 -133
  67. package/dist/types/messages.js.map +0 -1
  68. package/dist/types/options.d.ts +0 -212
  69. package/dist/types/options.d.ts.map +0 -1
  70. package/dist/types/options.js +0 -8
  71. package/dist/types/options.js.map +0 -1
  72. package/dist/types/results.d.ts +0 -186
  73. package/dist/types/results.d.ts.map +0 -1
  74. package/dist/types/results.js +0 -7
  75. package/dist/types/results.js.map +0 -1
  76. package/dist/types/token.d.ts +0 -124
  77. package/dist/types/token.d.ts.map +0 -1
  78. package/dist/types/token.js +0 -7
  79. package/dist/types/token.js.map +0 -1
  80. package/dist/types/tools.d.ts +0 -234
  81. package/dist/types/tools.d.ts.map +0 -1
  82. package/dist/types/tools.js +0 -31
  83. package/dist/types/tools.js.map +0 -1
  84. package/dist/utils/errors.d.ts +0 -80
  85. package/dist/utils/errors.d.ts.map +0 -1
  86. package/dist/utils/errors.js +0 -158
  87. package/dist/utils/errors.js.map +0 -1
  88. package/dist/utils/index.d.ts +0 -8
  89. package/dist/utils/index.d.ts.map +0 -1
  90. package/dist/utils/index.js +0 -8
  91. package/dist/utils/index.js.map +0 -1
  92. package/dist/utils/token.d.ts +0 -104
  93. package/dist/utils/token.d.ts.map +0 -1
  94. package/dist/utils/token.js +0 -209
  95. package/dist/utils/token.js.map +0 -1
@@ -0,0 +1,1361 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
31
+
32
+ // src/browser.ts
33
+ var browser_exports = {};
34
+ __export(browser_exports, {
35
+ AuthenticationError: () => AuthenticationError,
36
+ BudgetExceededError: () => BudgetExceededError,
37
+ ChuckyClient: () => ChuckyClient,
38
+ ChuckyError: () => ChuckyError,
39
+ ConcurrencyLimitError: () => ConcurrencyLimitError,
40
+ ConnectionError: () => ConnectionError,
41
+ McpServerBuilder: () => McpServerBuilder,
42
+ RateLimitError: () => RateLimitError,
43
+ Session: () => Session,
44
+ SessionError: () => SessionError,
45
+ TimeoutError: () => TimeoutError,
46
+ ToolExecutionError: () => ToolExecutionError,
47
+ ValidationError: () => ValidationError,
48
+ WebSocketTransport: () => WebSocketTransport,
49
+ browserTool: () => browserTool,
50
+ createBudget: () => createBudget,
51
+ createClient: () => createClient,
52
+ createControlMessage: () => createControlMessage,
53
+ createError: () => createError,
54
+ createInitMessage: () => createInitMessage,
55
+ createMcpServer: () => createMcpServer,
56
+ createPingMessage: () => createPingMessage,
57
+ createToken: () => createToken,
58
+ createTool: () => createTool,
59
+ createToolResultMessage: () => createToolResultMessage,
60
+ createUserMessage: () => createUserMessage,
61
+ decodeToken: () => decodeToken,
62
+ errorResult: () => errorResult,
63
+ extractProjectId: () => extractProjectId,
64
+ getAssistantText: () => getAssistantText,
65
+ getResultText: () => getResultText,
66
+ imageResult: () => imageResult,
67
+ isAssistantMessage: () => isAssistantMessage,
68
+ isControlMessage: () => isControlMessage,
69
+ isErrorMessage: () => isErrorMessage,
70
+ isErrorResult: () => isErrorResult,
71
+ isResultMessage: () => isResultMessage,
72
+ isStreamEvent: () => isStreamEvent,
73
+ isSuccessResult: () => isSuccessResult,
74
+ isSystemMessage: () => isSystemMessage,
75
+ isTokenExpired: () => isTokenExpired,
76
+ isToolCallMessage: () => isToolCallMessage,
77
+ isUserMessage: () => isUserMessage,
78
+ mcpServer: () => mcpServer,
79
+ serverTool: () => serverTool,
80
+ textResult: () => textResult,
81
+ tool: () => tool,
82
+ verifyToken: () => verifyToken
83
+ });
84
+ module.exports = __toCommonJS(browser_exports);
85
+
86
+ // src/types/messages.ts
87
+ function createInitMessage(payload) {
88
+ return { type: "init", payload };
89
+ }
90
+ function createUserMessage(content, sessionId, options = {}) {
91
+ const messageContent = typeof content === "string" ? content : content;
92
+ return {
93
+ type: "user",
94
+ uuid: options.uuid,
95
+ session_id: sessionId,
96
+ message: {
97
+ role: "user",
98
+ content: messageContent
99
+ },
100
+ parent_tool_use_id: options.parentToolUseId ?? null
101
+ };
102
+ }
103
+ function createControlMessage(action, data) {
104
+ return { type: "control", payload: { action, data } };
105
+ }
106
+ function createPingMessage() {
107
+ return { type: "ping", payload: { timestamp: Date.now() } };
108
+ }
109
+ function createToolResultMessage(callId, result) {
110
+ return { type: "tool_result", payload: { callId, result } };
111
+ }
112
+ function isUserMessage(message) {
113
+ return message.type === "user";
114
+ }
115
+ function isAssistantMessage(message) {
116
+ return message.type === "assistant";
117
+ }
118
+ function isResultMessage(message) {
119
+ return message.type === "result";
120
+ }
121
+ function isSuccessResult(message) {
122
+ return message.type === "result" && message.subtype === "success";
123
+ }
124
+ function isErrorResult(message) {
125
+ return message.type === "result" && message.subtype !== "success";
126
+ }
127
+ function isSystemMessage(message) {
128
+ return message.type === "system";
129
+ }
130
+ function isStreamEvent(message) {
131
+ return message.type === "stream_event";
132
+ }
133
+ function isToolCallMessage(message) {
134
+ return message.type === "tool_call";
135
+ }
136
+ function isControlMessage(message) {
137
+ return message.type === "control";
138
+ }
139
+ function isErrorMessage(message) {
140
+ return message.type === "error";
141
+ }
142
+
143
+ // src/transport/Transport.ts
144
+ var BaseTransport = class {
145
+ constructor(config) {
146
+ __publicField(this, "_status", "disconnected");
147
+ __publicField(this, "handlers", {});
148
+ __publicField(this, "config");
149
+ const cleanConfig = Object.fromEntries(
150
+ Object.entries(config).filter(([_, v]) => v !== void 0)
151
+ );
152
+ this.config = {
153
+ timeout: 6e4,
154
+ // 60s - container startup can take time
155
+ keepAliveInterval: 3e5,
156
+ // 5 minutes
157
+ autoReconnect: false,
158
+ // Disabled - server doesn't support reconnect
159
+ maxReconnectAttempts: 0,
160
+ debug: false,
161
+ ...cleanConfig
162
+ };
163
+ }
164
+ get status() {
165
+ return this._status;
166
+ }
167
+ setStatus(status) {
168
+ if (this._status !== status) {
169
+ this._status = status;
170
+ this.handlers.onStatusChange?.(status);
171
+ }
172
+ }
173
+ log(...args) {
174
+ if (this.config.debug) {
175
+ console.log("[ChuckySDK]", ...args);
176
+ }
177
+ }
178
+ logError(...args) {
179
+ console.error("[ChuckySDK]", ...args);
180
+ }
181
+ setEventHandlers(handlers) {
182
+ this.handlers = { ...this.handlers, ...handlers };
183
+ }
184
+ };
185
+
186
+ // src/transport/WebSocketTransport.ts
187
+ async function getWebSocket() {
188
+ if (typeof WebSocket !== "undefined") {
189
+ return WebSocket;
190
+ }
191
+ const ws = await import("ws");
192
+ return ws.default;
193
+ }
194
+ var WebSocketTransport = class extends BaseTransport {
195
+ constructor(config) {
196
+ super(config);
197
+ __publicField(this, "ws", null);
198
+ __publicField(this, "keepAliveTimer", null);
199
+ __publicField(this, "reconnectAttempts", 0);
200
+ __publicField(this, "reconnectTimer", null);
201
+ __publicField(this, "readyPromise", null);
202
+ __publicField(this, "readyResolve", null);
203
+ __publicField(this, "readyReject", null);
204
+ __publicField(this, "messageQueue", []);
205
+ }
206
+ /**
207
+ * Build the WebSocket URL with token
208
+ */
209
+ buildUrl() {
210
+ const url = new URL(this.config.url);
211
+ url.searchParams.set("token", this.config.token);
212
+ return url.toString();
213
+ }
214
+ /**
215
+ * Connect to the WebSocket server
216
+ */
217
+ async connect() {
218
+ if (this._status === "connected" || this._status === "connecting") {
219
+ return this.waitForReady();
220
+ }
221
+ this.setStatus("connecting");
222
+ this.log("Connecting to", this.config.url);
223
+ this.readyPromise = new Promise((resolve, reject) => {
224
+ this.readyResolve = resolve;
225
+ this.readyReject = reject;
226
+ });
227
+ try {
228
+ const WS = await getWebSocket();
229
+ const wsUrl = this.buildUrl();
230
+ this.ws = new WS(wsUrl);
231
+ const timeoutId = setTimeout(() => {
232
+ if (this._status === "connecting") {
233
+ this.ws?.close();
234
+ const error = new Error("Connection timeout");
235
+ this.readyReject?.(error);
236
+ this.handlers.onError?.(error);
237
+ this.setStatus("error");
238
+ }
239
+ }, this.config.timeout);
240
+ this.ws.onopen = () => {
241
+ clearTimeout(timeoutId);
242
+ this.log("Connected");
243
+ this.setStatus("connected");
244
+ this.reconnectAttempts = 0;
245
+ this.startKeepAlive();
246
+ this.readyResolve?.();
247
+ this.flushMessageQueue();
248
+ };
249
+ this.ws.onclose = (event) => {
250
+ clearTimeout(timeoutId);
251
+ this.log("Disconnected:", event.code, event.reason);
252
+ this.stopKeepAlive();
253
+ if (this._status === "connecting") {
254
+ const error = new Error(`Connection failed: ${event.reason || "Unknown"}`);
255
+ this.readyReject?.(error);
256
+ }
257
+ this.setStatus("disconnected");
258
+ this.handlers.onClose?.(event.code, event.reason);
259
+ if (this.config.autoReconnect && this.reconnectAttempts < (this.config.maxReconnectAttempts || 5)) {
260
+ this.scheduleReconnect();
261
+ }
262
+ };
263
+ this.ws.onerror = (event) => {
264
+ clearTimeout(timeoutId);
265
+ const error = new Error("WebSocket error");
266
+ this.logError("WebSocket error:", event);
267
+ this.handlers.onError?.(error);
268
+ if (this._status === "connecting") {
269
+ this.readyReject?.(error);
270
+ }
271
+ this.setStatus("error");
272
+ };
273
+ this.ws.onmessage = (event) => {
274
+ this.handleMessage(event.data);
275
+ };
276
+ return this.readyPromise;
277
+ } catch (error) {
278
+ this.setStatus("error");
279
+ this.readyReject?.(error);
280
+ throw error;
281
+ }
282
+ }
283
+ /**
284
+ * Disconnect from the server
285
+ */
286
+ async disconnect() {
287
+ this.log("Disconnecting");
288
+ this.stopKeepAlive();
289
+ this.clearReconnectTimer();
290
+ if (this.ws) {
291
+ this.ws.close(1e3, "Client disconnect");
292
+ this.ws = null;
293
+ }
294
+ this.setStatus("disconnected");
295
+ }
296
+ /**
297
+ * Send a message to the server
298
+ */
299
+ async send(message) {
300
+ if (this._status === "disconnected" && !this.config.autoReconnect) {
301
+ this.log("Message dropped (disconnected):", message.type);
302
+ return;
303
+ }
304
+ if (this._status !== "connected") {
305
+ this.messageQueue.push(message);
306
+ this.log("Message queued (not connected):", message.type);
307
+ if (this._status === "disconnected" && this.config.autoReconnect) {
308
+ await this.connect();
309
+ }
310
+ return;
311
+ }
312
+ this.sendImmediate(message);
313
+ }
314
+ /**
315
+ * Send a message immediately
316
+ */
317
+ sendImmediate(message) {
318
+ if (!this.ws || this.ws.readyState !== 1) {
319
+ this.logError("Cannot send: WebSocket not ready");
320
+ return;
321
+ }
322
+ const data = JSON.stringify(message);
323
+ this.handlers.onRawMessage?.("out", message);
324
+ this.ws.send(data);
325
+ this.log("Sent:", message.type);
326
+ }
327
+ /**
328
+ * Wait for the connection to be ready
329
+ */
330
+ async waitForReady() {
331
+ if (this._status === "connected") {
332
+ return;
333
+ }
334
+ if (this.readyPromise) {
335
+ return this.readyPromise;
336
+ }
337
+ return this.connect();
338
+ }
339
+ /**
340
+ * Handle incoming message
341
+ */
342
+ handleMessage(data) {
343
+ try {
344
+ const text = typeof data === "string" ? data : new TextDecoder().decode(data);
345
+ const message = JSON.parse(text);
346
+ this.handlers.onRawMessage?.("in", message);
347
+ this.log("Received:", message.type);
348
+ if (message.type === "pong") {
349
+ return;
350
+ }
351
+ if (isErrorMessage(message)) {
352
+ const error = new Error(message.payload.message);
353
+ this.handlers.onError?.(error);
354
+ }
355
+ this.handlers.onMessage?.(message);
356
+ } catch (error) {
357
+ this.logError("Failed to parse message:", error);
358
+ }
359
+ }
360
+ /**
361
+ * Start keep-alive ping
362
+ */
363
+ startKeepAlive() {
364
+ this.stopKeepAlive();
365
+ if (this.config.keepAliveInterval && this.config.keepAliveInterval > 0) {
366
+ this.keepAliveTimer = setInterval(() => {
367
+ if (this._status === "connected" && this.ws?.readyState === 1) {
368
+ this.sendImmediate(createPingMessage());
369
+ }
370
+ }, this.config.keepAliveInterval);
371
+ }
372
+ }
373
+ /**
374
+ * Stop keep-alive ping
375
+ */
376
+ stopKeepAlive() {
377
+ if (this.keepAliveTimer) {
378
+ clearInterval(this.keepAliveTimer);
379
+ this.keepAliveTimer = null;
380
+ }
381
+ }
382
+ /**
383
+ * Schedule a reconnection attempt
384
+ */
385
+ scheduleReconnect() {
386
+ this.clearReconnectTimer();
387
+ this.reconnectAttempts++;
388
+ const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts - 1), 16e3);
389
+ this.log(`Scheduling reconnect in ${delay}ms (attempt ${this.reconnectAttempts})`);
390
+ this.setStatus("reconnecting");
391
+ this.reconnectTimer = setTimeout(() => {
392
+ this.connect().catch((error) => {
393
+ this.logError("Reconnect failed:", error);
394
+ });
395
+ }, delay);
396
+ }
397
+ /**
398
+ * Clear reconnect timer
399
+ */
400
+ clearReconnectTimer() {
401
+ if (this.reconnectTimer) {
402
+ clearTimeout(this.reconnectTimer);
403
+ this.reconnectTimer = null;
404
+ }
405
+ }
406
+ /**
407
+ * Flush queued messages
408
+ */
409
+ flushMessageQueue() {
410
+ while (this.messageQueue.length > 0) {
411
+ const message = this.messageQueue.shift();
412
+ this.sendImmediate(message);
413
+ }
414
+ }
415
+ };
416
+
417
+ // src/client/Session.ts
418
+ function generateUUID() {
419
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
420
+ const r = Math.random() * 16 | 0;
421
+ const v = c === "x" ? r : r & 3 | 8;
422
+ return v.toString(16);
423
+ });
424
+ }
425
+ var Session = class {
426
+ constructor(transport, options, config = {}) {
427
+ __publicField(this, "transport");
428
+ __publicField(this, "options");
429
+ __publicField(this, "config");
430
+ __publicField(this, "eventHandlers", {});
431
+ __publicField(this, "toolHandlers", /* @__PURE__ */ new Map());
432
+ __publicField(this, "messageBuffer", []);
433
+ __publicField(this, "_state", "idle");
434
+ __publicField(this, "_sessionId");
435
+ __publicField(this, "messageResolvers", []);
436
+ __publicField(this, "connected", false);
437
+ __publicField(this, "connectPromise", null);
438
+ this.transport = transport;
439
+ this.options = options;
440
+ this.config = config;
441
+ this._sessionId = options.sessionId || generateUUID();
442
+ if (options.mcpServers) {
443
+ for (const server of options.mcpServers) {
444
+ if ("tools" in server) {
445
+ for (const tool2 of server.tools) {
446
+ if (tool2.handler) {
447
+ this.toolHandlers.set(tool2.name, tool2.handler);
448
+ }
449
+ }
450
+ }
451
+ }
452
+ }
453
+ this.transport.setEventHandlers({
454
+ onMessage: (message) => this.handleMessage(message),
455
+ onError: (error) => this.eventHandlers.onError?.(error),
456
+ onStatusChange: (status) => {
457
+ if (status === "disconnected" && this._state !== "completed") {
458
+ this._state = "error";
459
+ }
460
+ }
461
+ });
462
+ }
463
+ /**
464
+ * Get the session ID
465
+ */
466
+ get sessionId() {
467
+ return this._sessionId;
468
+ }
469
+ /**
470
+ * Set event handlers
471
+ */
472
+ on(handlers) {
473
+ this.eventHandlers = { ...this.eventHandlers, ...handlers };
474
+ return this;
475
+ }
476
+ /**
477
+ * Connect and initialize the session (called automatically on first send)
478
+ */
479
+ async ensureConnected() {
480
+ if (this.connected) return;
481
+ if (this.connectPromise) {
482
+ return this.connectPromise;
483
+ }
484
+ this.connectPromise = this.connect();
485
+ await this.connectPromise;
486
+ }
487
+ async connect() {
488
+ this._state = "initializing";
489
+ await this.transport.connect();
490
+ const initPayload = this.buildInitPayload();
491
+ await this.transport.send(createInitMessage(initPayload));
492
+ await this.waitForReady();
493
+ this._state = "ready";
494
+ this.connected = true;
495
+ }
496
+ /**
497
+ * Send a message to the session
498
+ *
499
+ * Matches V2 SDK: send() returns Promise<void>
500
+ * Use stream() to get the response.
501
+ *
502
+ * @example
503
+ * ```typescript
504
+ * await session.send('Hello!');
505
+ * for await (const msg of session.stream()) {
506
+ * // Handle messages
507
+ * }
508
+ * ```
509
+ */
510
+ async send(message) {
511
+ await this.ensureConnected();
512
+ if (this._state !== "ready") {
513
+ throw new Error(`Cannot send: session state is ${this._state}`);
514
+ }
515
+ this._state = "processing";
516
+ const userMessage = createUserMessage(message, this._sessionId);
517
+ await this.transport.send(userMessage);
518
+ }
519
+ /**
520
+ * Stream the response after sending a message
521
+ *
522
+ * Matches V2 SDK: Returns AsyncGenerator<SDKMessage>
523
+ *
524
+ * @example
525
+ * ```typescript
526
+ * await session.send('Hello!');
527
+ * for await (const msg of session.stream()) {
528
+ * if (msg.type === 'assistant') {
529
+ * const text = msg.message.content
530
+ * .filter(b => b.type === 'text')
531
+ * .map(b => b.text)
532
+ * .join('');
533
+ * console.log(text);
534
+ * }
535
+ * if (msg.type === 'result') {
536
+ * console.log('Done:', msg.result);
537
+ * }
538
+ * }
539
+ * ```
540
+ */
541
+ async *stream() {
542
+ while (this._state === "processing" || this._state === "waiting_tool") {
543
+ const msg = await this.waitForNextMessage();
544
+ if (isToolCallMessage(msg)) {
545
+ this._state = "waiting_tool";
546
+ await this.handleToolCall(msg.payload);
547
+ this._state = "processing";
548
+ continue;
549
+ }
550
+ if (isAssistantMessage(msg) || isResultMessage(msg) || isSystemMessage(msg) || isStreamEvent(msg)) {
551
+ yield msg;
552
+ }
553
+ if (isResultMessage(msg)) {
554
+ this._state = "ready";
555
+ break;
556
+ }
557
+ if (isErrorMessage(msg)) {
558
+ this._state = "ready";
559
+ throw new Error(msg.payload.message);
560
+ }
561
+ }
562
+ }
563
+ /**
564
+ * Receive messages (alias for stream for V2 compatibility)
565
+ */
566
+ receive() {
567
+ return this.stream();
568
+ }
569
+ /**
570
+ * Close the session
571
+ */
572
+ close() {
573
+ this.transport.send(createControlMessage("close")).catch(() => {
574
+ });
575
+ this.transport.disconnect().catch(() => {
576
+ });
577
+ this._state = "completed";
578
+ }
579
+ /**
580
+ * Support for `await using` (TypeScript 5.2+)
581
+ */
582
+ async [Symbol.asyncDispose]() {
583
+ this.close();
584
+ }
585
+ /**
586
+ * Build init payload from options
587
+ */
588
+ buildInitPayload() {
589
+ const { mcpServers, ...rest } = this.options;
590
+ const serializedMcpServers = mcpServers?.map((server) => {
591
+ if ("tools" in server) {
592
+ return {
593
+ name: server.name,
594
+ version: server.version,
595
+ tools: server.tools.map((tool2) => ({
596
+ name: tool2.name,
597
+ description: tool2.description,
598
+ inputSchema: tool2.inputSchema,
599
+ // If tool has a handler, it executes on the client (SDK) side
600
+ executeIn: tool2.handler ? "client" : tool2.executeIn
601
+ }))
602
+ };
603
+ }
604
+ return server;
605
+ });
606
+ return {
607
+ ...rest,
608
+ // tools is passed through as-is (string[] or preset for allowlisting)
609
+ mcpServers: serializedMcpServers
610
+ };
611
+ }
612
+ /**
613
+ * Handle incoming message
614
+ */
615
+ handleMessage(message) {
616
+ this.log("Received:", message.type);
617
+ if (isControlMessage(message)) {
618
+ if (message.payload.action === "session_info") {
619
+ const info = message.payload.data;
620
+ this._sessionId = info.sessionId || this._sessionId;
621
+ this.eventHandlers.onSessionInfo?.(info);
622
+ }
623
+ }
624
+ if (isSystemMessage(message) && message.subtype === "init") {
625
+ this._sessionId = message.session_id || this._sessionId;
626
+ this.eventHandlers.onSessionInfo?.({
627
+ sessionId: message.session_id,
628
+ model: message.model,
629
+ tools: message.tools
630
+ });
631
+ }
632
+ if (isErrorMessage(message)) {
633
+ const error = new Error(message.payload.message);
634
+ this.eventHandlers.onError?.(error);
635
+ }
636
+ const resolver = this.messageResolvers.shift();
637
+ if (resolver) {
638
+ resolver(message);
639
+ } else {
640
+ this.messageBuffer.push(message);
641
+ }
642
+ }
643
+ /**
644
+ * Wait for session to be ready
645
+ */
646
+ async waitForReady() {
647
+ return new Promise((resolve, reject) => {
648
+ const timeout = setTimeout(() => {
649
+ reject(new Error("Session initialization timeout"));
650
+ }, 3e4);
651
+ const checkReady = (message) => {
652
+ if (isControlMessage(message)) {
653
+ if (message.payload.action === "ready" || message.payload.action === "session_info") {
654
+ clearTimeout(timeout);
655
+ resolve();
656
+ return true;
657
+ }
658
+ }
659
+ if (isSystemMessage(message) && message.subtype === "init") {
660
+ clearTimeout(timeout);
661
+ resolve();
662
+ return true;
663
+ }
664
+ if (isErrorMessage(message)) {
665
+ clearTimeout(timeout);
666
+ reject(new Error(message.payload.message));
667
+ return true;
668
+ }
669
+ return false;
670
+ };
671
+ for (let i = 0; i < this.messageBuffer.length; i++) {
672
+ if (checkReady(this.messageBuffer[i])) {
673
+ this.messageBuffer.splice(i, 1);
674
+ return;
675
+ }
676
+ }
677
+ this.messageResolvers.push((msg) => {
678
+ checkReady(msg);
679
+ });
680
+ });
681
+ }
682
+ /**
683
+ * Wait for next message
684
+ */
685
+ async waitForNextMessage() {
686
+ if (this.messageBuffer.length > 0) {
687
+ return this.messageBuffer.shift();
688
+ }
689
+ return new Promise((resolve) => {
690
+ this.messageResolvers.push(resolve);
691
+ });
692
+ }
693
+ /**
694
+ * Handle a tool call
695
+ */
696
+ async handleToolCall(toolCall) {
697
+ const handler = this.toolHandlers.get(toolCall.toolName);
698
+ if (!handler) {
699
+ this.log("No local handler for tool:", toolCall.toolName);
700
+ return;
701
+ }
702
+ this.log("Executing tool:", toolCall.toolName);
703
+ try {
704
+ const result = await handler(toolCall.input);
705
+ await this.transport.send(createToolResultMessage(toolCall.callId, result));
706
+ } catch (error) {
707
+ const errorResult2 = {
708
+ content: [{ type: "text", text: error.message }],
709
+ isError: true
710
+ };
711
+ await this.transport.send(createToolResultMessage(toolCall.callId, errorResult2));
712
+ }
713
+ }
714
+ /**
715
+ * Log debug messages
716
+ */
717
+ log(...args) {
718
+ if (this.config.debug) {
719
+ console.log("[Session]", ...args);
720
+ }
721
+ }
722
+ };
723
+ function getAssistantText(msg) {
724
+ if (msg.type !== "assistant") return null;
725
+ return msg.message.content.filter((block) => block.type === "text").map((block) => block.text).join("");
726
+ }
727
+ function getResultText(msg) {
728
+ if (msg.type !== "result") return null;
729
+ const resultMsg = msg;
730
+ if (resultMsg.subtype === "success") {
731
+ return resultMsg.result;
732
+ }
733
+ return null;
734
+ }
735
+
736
+ // src/client/ChuckyClient.ts
737
+ var DEFAULT_BASE_URL = "wss://conjure.chucky.cloud/ws";
738
+ var ChuckyClient = class {
739
+ /**
740
+ * Create a new Chucky client
741
+ */
742
+ constructor(options) {
743
+ __publicField(this, "options");
744
+ __publicField(this, "eventHandlers", {});
745
+ __publicField(this, "activeSessions", /* @__PURE__ */ new Map());
746
+ this.options = {
747
+ baseUrl: DEFAULT_BASE_URL,
748
+ debug: false,
749
+ ...options
750
+ };
751
+ }
752
+ /**
753
+ * Set event handlers
754
+ */
755
+ on(handlers) {
756
+ this.eventHandlers = { ...this.eventHandlers, ...handlers };
757
+ return this;
758
+ }
759
+ /**
760
+ * Create a new session
761
+ *
762
+ * Matches V2 SDK: createSession() returns a Session immediately.
763
+ * Connection happens automatically on first send().
764
+ *
765
+ * @param options - Session configuration options
766
+ * @returns A new session instance
767
+ *
768
+ * @example
769
+ * ```typescript
770
+ * const session = client.createSession({
771
+ * model: 'claude-sonnet-4-5-20250929',
772
+ * systemPrompt: 'You are a helpful coding assistant.',
773
+ * });
774
+ *
775
+ * await session.send('Hello!');
776
+ * for await (const msg of session.stream()) {
777
+ * // Handle messages
778
+ * }
779
+ * ```
780
+ */
781
+ createSession(options = {}) {
782
+ const transport = this.createTransport();
783
+ const session = new Session(transport, options, {
784
+ debug: this.options.debug
785
+ });
786
+ session.on({
787
+ onSessionInfo: (info) => {
788
+ if (info.sessionId) {
789
+ this.activeSessions.set(info.sessionId, session);
790
+ }
791
+ }
792
+ });
793
+ return session;
794
+ }
795
+ /**
796
+ * Resume an existing session
797
+ *
798
+ * @param sessionId - The session ID to resume
799
+ * @param options - Additional session options
800
+ * @returns The resumed session
801
+ *
802
+ * @example
803
+ * ```typescript
804
+ * const session = client.resumeSession('session-123');
805
+ * await session.send('Continue our conversation');
806
+ * ```
807
+ */
808
+ resumeSession(sessionId, options = {}) {
809
+ return this.createSession({
810
+ ...options,
811
+ sessionId
812
+ });
813
+ }
814
+ /**
815
+ * Execute a one-shot prompt (stateless)
816
+ *
817
+ * Supports two call signatures:
818
+ * - `prompt('message', { model: '...' })` - positional style
819
+ * - `prompt({ message: '...', model: '...' })` - object style
820
+ *
821
+ * @param messageOrOptions - The message string OR an options object with message
822
+ * @param options - Prompt configuration (only used with positional style)
823
+ * @returns The result message
824
+ *
825
+ * @example
826
+ * ```typescript
827
+ * // Positional style
828
+ * const result = await client.prompt(
829
+ * 'Explain quantum computing in simple terms',
830
+ * { model: 'claude-sonnet-4-5-20250929' }
831
+ * );
832
+ *
833
+ * // Object style
834
+ * const result = await client.prompt({
835
+ * message: 'Explain quantum computing in simple terms',
836
+ * model: 'claude-sonnet-4-5-20250929',
837
+ * });
838
+ *
839
+ * if (result.subtype === 'success') {
840
+ * console.log(result.result);
841
+ * }
842
+ * ```
843
+ */
844
+ async prompt(messageOrOptions, options = {}) {
845
+ let message;
846
+ let sessionOptions;
847
+ if (typeof messageOrOptions === "object") {
848
+ const { message: msg, ...rest } = messageOrOptions;
849
+ message = msg;
850
+ sessionOptions = rest;
851
+ } else {
852
+ message = messageOrOptions;
853
+ sessionOptions = options;
854
+ }
855
+ const session = this.createSession(sessionOptions);
856
+ try {
857
+ await session.send(message);
858
+ let result = null;
859
+ for await (const msg of session.stream()) {
860
+ if (msg.type === "result") {
861
+ result = msg;
862
+ break;
863
+ }
864
+ }
865
+ if (!result) {
866
+ throw new Error("No result message received");
867
+ }
868
+ return result;
869
+ } finally {
870
+ session.close();
871
+ }
872
+ }
873
+ /**
874
+ * Close all active sessions and disconnect
875
+ */
876
+ close() {
877
+ for (const session of this.activeSessions.values()) {
878
+ session.close();
879
+ }
880
+ this.activeSessions.clear();
881
+ }
882
+ /**
883
+ * Create a new transport instance
884
+ */
885
+ createTransport() {
886
+ return new WebSocketTransport({
887
+ url: this.options.baseUrl,
888
+ token: this.options.token,
889
+ timeout: this.options.timeout,
890
+ keepAliveInterval: this.options.keepAliveInterval,
891
+ autoReconnect: this.options.autoReconnect,
892
+ maxReconnectAttempts: this.options.maxReconnectAttempts,
893
+ debug: this.options.debug
894
+ });
895
+ }
896
+ };
897
+ function createClient(options) {
898
+ return new ChuckyClient(options);
899
+ }
900
+
901
+ // src/tools/tool.ts
902
+ function isZodSchema(schema) {
903
+ return typeof schema === "object" && schema !== null && ("_def" in schema || "shape" in schema);
904
+ }
905
+ function zodToJsonSchema(zodSchema) {
906
+ const def = zodSchema._def;
907
+ if (!def) {
908
+ return {
909
+ type: "object",
910
+ properties: {}
911
+ };
912
+ }
913
+ const typeName = def.typeName;
914
+ if (typeName === "ZodObject") {
915
+ const shape = def.shape?.() || {};
916
+ const properties = {};
917
+ const required = [];
918
+ for (const [key, value] of Object.entries(shape)) {
919
+ const valueDef = value._def;
920
+ if (valueDef) {
921
+ const prop = zodDefToJsonSchema(valueDef);
922
+ if (prop) {
923
+ properties[key] = prop;
924
+ if (valueDef.typeName !== "ZodOptional") {
925
+ required.push(key);
926
+ }
927
+ }
928
+ }
929
+ }
930
+ return {
931
+ type: "object",
932
+ properties,
933
+ required: required.length > 0 ? required : void 0
934
+ };
935
+ }
936
+ return {
937
+ type: "object",
938
+ properties: {}
939
+ };
940
+ }
941
+ function zodDefToJsonSchema(def) {
942
+ const typeName = def.typeName;
943
+ switch (typeName) {
944
+ case "ZodString":
945
+ return { type: "string", description: def.description };
946
+ case "ZodNumber":
947
+ return { type: "number", description: def.description };
948
+ case "ZodBoolean":
949
+ return { type: "boolean", description: def.description };
950
+ case "ZodArray":
951
+ const innerDef = def.innerType?._def;
952
+ return {
953
+ type: "array",
954
+ description: def.description,
955
+ items: innerDef ? zodDefToJsonSchema(innerDef) || { type: "string" } : { type: "string" }
956
+ };
957
+ case "ZodEnum":
958
+ return {
959
+ type: "string",
960
+ description: def.description,
961
+ enum: def.values
962
+ };
963
+ case "ZodOptional":
964
+ const innerOptDef = def.innerType?._def;
965
+ return innerOptDef ? zodDefToJsonSchema(innerOptDef) : null;
966
+ default:
967
+ return { type: "string" };
968
+ }
969
+ }
970
+ function createTool(options) {
971
+ let inputSchema;
972
+ if (isZodSchema(options.inputSchema)) {
973
+ inputSchema = zodToJsonSchema(options.inputSchema);
974
+ } else {
975
+ inputSchema = options.inputSchema;
976
+ }
977
+ return {
978
+ name: options.name,
979
+ description: options.description,
980
+ inputSchema,
981
+ executeIn: options.executeIn ?? "server",
982
+ handler: options.handler
983
+ };
984
+ }
985
+ function tool(name, description, inputSchema, handler) {
986
+ return createTool({ name, description, inputSchema, handler });
987
+ }
988
+ function browserTool(options) {
989
+ return createTool({ ...options, executeIn: "browser" });
990
+ }
991
+ function serverTool(options) {
992
+ return createTool({ ...options, executeIn: "server" });
993
+ }
994
+ function textResult(text) {
995
+ return {
996
+ content: [{ type: "text", text }]
997
+ };
998
+ }
999
+ function errorResult(message) {
1000
+ return {
1001
+ content: [{ type: "text", text: message }],
1002
+ isError: true
1003
+ };
1004
+ }
1005
+ function imageResult(data, mimeType) {
1006
+ return {
1007
+ content: [{ type: "image", data, mimeType }]
1008
+ };
1009
+ }
1010
+
1011
+ // src/tools/McpServer.ts
1012
+ var McpServerBuilder = class {
1013
+ /**
1014
+ * Create a new MCP server builder
1015
+ *
1016
+ * @param name - Server name
1017
+ * @param version - Server version (default: '1.0.0')
1018
+ */
1019
+ constructor(name, version = "1.0.0") {
1020
+ __publicField(this, "name");
1021
+ __publicField(this, "version");
1022
+ __publicField(this, "tools", []);
1023
+ this.name = name;
1024
+ this.version = version;
1025
+ }
1026
+ /**
1027
+ * Add a tool to the server
1028
+ *
1029
+ * @param options - Tool configuration
1030
+ * @returns This builder for chaining
1031
+ */
1032
+ addTool(options) {
1033
+ this.tools.push(createTool(options));
1034
+ return this;
1035
+ }
1036
+ /**
1037
+ * Add an existing tool definition
1038
+ *
1039
+ * @param tool - Tool definition
1040
+ * @returns This builder for chaining
1041
+ */
1042
+ add(tool2) {
1043
+ this.tools.push(tool2);
1044
+ return this;
1045
+ }
1046
+ /**
1047
+ * Add multiple tools at once
1048
+ *
1049
+ * @param tools - Array of tool definitions
1050
+ * @returns This builder for chaining
1051
+ */
1052
+ addTools(tools) {
1053
+ this.tools.push(...tools);
1054
+ return this;
1055
+ }
1056
+ /**
1057
+ * Build the MCP server definition
1058
+ *
1059
+ * @returns Complete MCP server definition
1060
+ */
1061
+ build() {
1062
+ return {
1063
+ name: this.name,
1064
+ version: this.version,
1065
+ tools: this.tools
1066
+ };
1067
+ }
1068
+ };
1069
+ function createMcpServer(name, tools, version = "1.0.0") {
1070
+ return {
1071
+ name,
1072
+ version,
1073
+ tools
1074
+ };
1075
+ }
1076
+ function mcpServer(name, version) {
1077
+ return new McpServerBuilder(name, version);
1078
+ }
1079
+
1080
+ // src/utils/token.ts
1081
+ function base64UrlEncode(data) {
1082
+ let base64;
1083
+ if (typeof data === "string") {
1084
+ const bytes = new TextEncoder().encode(data);
1085
+ base64 = btoa(String.fromCharCode(...bytes));
1086
+ } else {
1087
+ base64 = btoa(String.fromCharCode(...data));
1088
+ }
1089
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1090
+ }
1091
+ function base64UrlDecode(str) {
1092
+ const base64 = str.replace(/-/g, "+").replace(/_/g, "/");
1093
+ const padding = "=".repeat((4 - base64.length % 4) % 4);
1094
+ const bytes = atob(base64 + padding);
1095
+ return bytes;
1096
+ }
1097
+ async function getCrypto() {
1098
+ if (typeof crypto !== "undefined" && crypto.subtle) {
1099
+ return crypto;
1100
+ }
1101
+ const nodeCrypto = await import("crypto");
1102
+ return nodeCrypto.webcrypto;
1103
+ }
1104
+ async function createHmacSignature(secret, data) {
1105
+ const { subtle } = await getCrypto();
1106
+ const keyData = new TextEncoder().encode(secret);
1107
+ const key = await subtle.importKey(
1108
+ "raw",
1109
+ keyData,
1110
+ { name: "HMAC", hash: "SHA-256" },
1111
+ false,
1112
+ ["sign"]
1113
+ );
1114
+ const signature = await subtle.sign("HMAC", key, new TextEncoder().encode(data));
1115
+ return base64UrlEncode(new Uint8Array(signature));
1116
+ }
1117
+ async function verifyHmacSignature(secret, data, signature) {
1118
+ const expectedSignature = await createHmacSignature(secret, data);
1119
+ return signature === expectedSignature;
1120
+ }
1121
+ async function createToken(options) {
1122
+ const {
1123
+ userId,
1124
+ projectId,
1125
+ secret,
1126
+ expiresIn = 3600,
1127
+ budget,
1128
+ permissions,
1129
+ sdkConfig
1130
+ } = options;
1131
+ const now = Math.floor(Date.now() / 1e3);
1132
+ const payload = {
1133
+ sub: userId,
1134
+ iss: projectId,
1135
+ iat: now,
1136
+ exp: now + expiresIn,
1137
+ budget,
1138
+ ...permissions && { permissions },
1139
+ ...sdkConfig && { sdkConfig }
1140
+ };
1141
+ const header = {
1142
+ alg: "HS256",
1143
+ typ: "JWT"
1144
+ };
1145
+ const encodedHeader = base64UrlEncode(JSON.stringify(header));
1146
+ const encodedPayload = base64UrlEncode(JSON.stringify(payload));
1147
+ const signatureInput = `${encodedHeader}.${encodedPayload}`;
1148
+ const signature = await createHmacSignature(secret, signatureInput);
1149
+ return `${encodedHeader}.${encodedPayload}.${signature}`;
1150
+ }
1151
+ function decodeToken(token) {
1152
+ const parts = token.split(".");
1153
+ if (parts.length !== 3) {
1154
+ throw new Error("Invalid token format");
1155
+ }
1156
+ const [encodedHeader, encodedPayload, signature] = parts;
1157
+ const header = JSON.parse(base64UrlDecode(encodedHeader));
1158
+ const payload = JSON.parse(base64UrlDecode(encodedPayload));
1159
+ return { header, payload, signature };
1160
+ }
1161
+ async function verifyToken(token, secret) {
1162
+ const parts = token.split(".");
1163
+ if (parts.length !== 3) {
1164
+ return false;
1165
+ }
1166
+ const [encodedHeader, encodedPayload, signature] = parts;
1167
+ const signatureInput = `${encodedHeader}.${encodedPayload}`;
1168
+ return verifyHmacSignature(secret, signatureInput, signature);
1169
+ }
1170
+ function isTokenExpired(token) {
1171
+ try {
1172
+ const decoded = decodeToken(token);
1173
+ const now = Math.floor(Date.now() / 1e3);
1174
+ return decoded.payload.exp < now;
1175
+ } catch {
1176
+ return true;
1177
+ }
1178
+ }
1179
+ function extractProjectId(_hmacKey) {
1180
+ throw new Error(
1181
+ "extractProjectId() is deprecated. The project ID is now separate from the HMAC key for security. Get your project ID from the Chucky portal (app.chucky.cloud) in your project settings."
1182
+ );
1183
+ }
1184
+ function createBudget(options) {
1185
+ return {
1186
+ ai: Math.floor(options.aiDollars * 1e6),
1187
+ // Convert to microdollars
1188
+ compute: Math.floor(options.computeHours * 3600),
1189
+ // Convert to seconds
1190
+ window: options.window,
1191
+ windowStart: (options.windowStart || /* @__PURE__ */ new Date()).toISOString()
1192
+ };
1193
+ }
1194
+
1195
+ // src/utils/errors.ts
1196
+ var ChuckyError = class _ChuckyError extends Error {
1197
+ constructor(message, code, details) {
1198
+ super(message);
1199
+ /** Error code */
1200
+ __publicField(this, "code");
1201
+ /** Additional error details */
1202
+ __publicField(this, "details");
1203
+ this.name = "ChuckyError";
1204
+ this.code = code;
1205
+ this.details = details;
1206
+ if (Error.captureStackTrace) {
1207
+ Error.captureStackTrace(this, _ChuckyError);
1208
+ }
1209
+ }
1210
+ };
1211
+ var ConnectionError = class extends ChuckyError {
1212
+ constructor(message, details) {
1213
+ super(message, "CONNECTION_ERROR", details);
1214
+ this.name = "ConnectionError";
1215
+ }
1216
+ };
1217
+ var AuthenticationError = class extends ChuckyError {
1218
+ constructor(message, details) {
1219
+ super(message, "AUTHENTICATION_ERROR", details);
1220
+ this.name = "AuthenticationError";
1221
+ }
1222
+ };
1223
+ var BudgetExceededError = class extends ChuckyError {
1224
+ constructor(message, details) {
1225
+ super(message, "BUDGET_EXCEEDED", details);
1226
+ this.name = "BudgetExceededError";
1227
+ }
1228
+ };
1229
+ var ConcurrencyLimitError = class extends ChuckyError {
1230
+ constructor(message, details) {
1231
+ super(message, "CONCURRENCY_LIMIT", details);
1232
+ this.name = "ConcurrencyLimitError";
1233
+ }
1234
+ };
1235
+ var RateLimitError = class extends ChuckyError {
1236
+ constructor(message, details) {
1237
+ super(message, "RATE_LIMIT", details);
1238
+ this.name = "RateLimitError";
1239
+ }
1240
+ };
1241
+ var SessionError = class extends ChuckyError {
1242
+ constructor(message, details) {
1243
+ super(message, "SESSION_ERROR", details);
1244
+ this.name = "SessionError";
1245
+ }
1246
+ };
1247
+ var ToolExecutionError = class extends ChuckyError {
1248
+ constructor(message, toolName, details) {
1249
+ super(message, "TOOL_EXECUTION_ERROR", { ...details, toolName });
1250
+ /** Tool name */
1251
+ __publicField(this, "toolName");
1252
+ this.name = "ToolExecutionError";
1253
+ this.toolName = toolName;
1254
+ }
1255
+ };
1256
+ var TimeoutError = class extends ChuckyError {
1257
+ constructor(message, details) {
1258
+ super(message, "TIMEOUT", details);
1259
+ this.name = "TimeoutError";
1260
+ }
1261
+ };
1262
+ var ValidationError = class extends ChuckyError {
1263
+ constructor(message, details) {
1264
+ super(message, "VALIDATION_ERROR", details);
1265
+ this.name = "ValidationError";
1266
+ }
1267
+ };
1268
+ function parseErrorCode(message) {
1269
+ const patterns = [
1270
+ { pattern: /budget.*exceed/i, code: "BUDGET_EXCEEDED" },
1271
+ { pattern: /concurrency.*limit/i, code: "CONCURRENCY_LIMIT" },
1272
+ { pattern: /rate.*limit/i, code: "RATE_LIMIT" },
1273
+ { pattern: /auth|unauthorized|forbidden/i, code: "AUTHENTICATION_ERROR" },
1274
+ { pattern: /timeout/i, code: "TIMEOUT" },
1275
+ { pattern: /connect|disconnect|websocket/i, code: "CONNECTION_ERROR" },
1276
+ { pattern: /session/i, code: "SESSION_ERROR" },
1277
+ { pattern: /tool/i, code: "TOOL_EXECUTION_ERROR" },
1278
+ { pattern: /invalid|validation/i, code: "VALIDATION_ERROR" }
1279
+ ];
1280
+ for (const { pattern, code } of patterns) {
1281
+ if (pattern.test(message)) {
1282
+ return code;
1283
+ }
1284
+ }
1285
+ return null;
1286
+ }
1287
+ function createError(message, code) {
1288
+ const errorCode = code || parseErrorCode(message) || "UNKNOWN_ERROR";
1289
+ switch (errorCode) {
1290
+ case "CONNECTION_ERROR":
1291
+ return new ConnectionError(message);
1292
+ case "AUTHENTICATION_ERROR":
1293
+ return new AuthenticationError(message);
1294
+ case "BUDGET_EXCEEDED":
1295
+ return new BudgetExceededError(message);
1296
+ case "CONCURRENCY_LIMIT":
1297
+ return new ConcurrencyLimitError(message);
1298
+ case "RATE_LIMIT":
1299
+ return new RateLimitError(message);
1300
+ case "SESSION_ERROR":
1301
+ return new SessionError(message);
1302
+ case "TIMEOUT":
1303
+ return new TimeoutError(message);
1304
+ case "VALIDATION_ERROR":
1305
+ return new ValidationError(message);
1306
+ default:
1307
+ return new ChuckyError(message, errorCode);
1308
+ }
1309
+ }
1310
+ // Annotate the CommonJS export names for ESM import in node:
1311
+ 0 && (module.exports = {
1312
+ AuthenticationError,
1313
+ BudgetExceededError,
1314
+ ChuckyClient,
1315
+ ChuckyError,
1316
+ ConcurrencyLimitError,
1317
+ ConnectionError,
1318
+ McpServerBuilder,
1319
+ RateLimitError,
1320
+ Session,
1321
+ SessionError,
1322
+ TimeoutError,
1323
+ ToolExecutionError,
1324
+ ValidationError,
1325
+ WebSocketTransport,
1326
+ browserTool,
1327
+ createBudget,
1328
+ createClient,
1329
+ createControlMessage,
1330
+ createError,
1331
+ createInitMessage,
1332
+ createMcpServer,
1333
+ createPingMessage,
1334
+ createToken,
1335
+ createTool,
1336
+ createToolResultMessage,
1337
+ createUserMessage,
1338
+ decodeToken,
1339
+ errorResult,
1340
+ extractProjectId,
1341
+ getAssistantText,
1342
+ getResultText,
1343
+ imageResult,
1344
+ isAssistantMessage,
1345
+ isControlMessage,
1346
+ isErrorMessage,
1347
+ isErrorResult,
1348
+ isResultMessage,
1349
+ isStreamEvent,
1350
+ isSuccessResult,
1351
+ isSystemMessage,
1352
+ isTokenExpired,
1353
+ isToolCallMessage,
1354
+ isUserMessage,
1355
+ mcpServer,
1356
+ serverTool,
1357
+ textResult,
1358
+ tool,
1359
+ verifyToken
1360
+ });
1361
+ //# sourceMappingURL=browser.cjs.map