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