@rainfall-devkit/sdk 0.2.2 → 0.2.3

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.
@@ -37,6 +37,164 @@ var init_cjs_shims = __esm({
37
37
  }
38
38
  });
39
39
 
40
+ // src/errors.ts
41
+ var errors_exports = {};
42
+ __export(errors_exports, {
43
+ AuthenticationError: () => AuthenticationError,
44
+ NetworkError: () => NetworkError,
45
+ NotFoundError: () => NotFoundError,
46
+ RainfallError: () => RainfallError,
47
+ RateLimitError: () => RateLimitError,
48
+ ServerError: () => ServerError,
49
+ TimeoutError: () => TimeoutError,
50
+ ToolNotFoundError: () => ToolNotFoundError,
51
+ ValidationError: () => ValidationError,
52
+ parseErrorResponse: () => parseErrorResponse
53
+ });
54
+ function parseErrorResponse(response, data) {
55
+ const statusCode = response.status;
56
+ if (statusCode === 429) {
57
+ const retryAfter = parseInt(response.headers.get("retry-after") || "60", 10);
58
+ const limit = parseInt(response.headers.get("x-ratelimit-limit") || "0", 10);
59
+ const remaining = parseInt(response.headers.get("x-ratelimit-remaining") || "0", 10);
60
+ const resetHeader = response.headers.get("x-ratelimit-reset");
61
+ const resetAt = resetHeader ? new Date(parseInt(resetHeader, 10) * 1e3) : void 0;
62
+ return new RateLimitError(
63
+ typeof data === "object" && data && "message" in data ? String(data.message) : "Rate limit exceeded",
64
+ retryAfter,
65
+ limit,
66
+ remaining,
67
+ resetAt
68
+ );
69
+ }
70
+ switch (statusCode) {
71
+ case 401:
72
+ return new AuthenticationError(
73
+ typeof data === "object" && data && "message" in data ? String(data.message) : "Invalid API key"
74
+ );
75
+ case 404:
76
+ return new NotFoundError(
77
+ typeof data === "object" && data && "resource" in data ? String(data.resource) : "Resource",
78
+ typeof data === "object" && data && "identifier" in data ? String(data.identifier) : void 0
79
+ );
80
+ case 400:
81
+ return new ValidationError(
82
+ typeof data === "object" && data && "message" in data ? String(data.message) : "Invalid request",
83
+ typeof data === "object" && data && "details" in data ? data.details : void 0
84
+ );
85
+ case 500:
86
+ case 502:
87
+ case 503:
88
+ case 504:
89
+ return new ServerError(
90
+ typeof data === "object" && data && "message" in data ? String(data.message) : "Server error",
91
+ statusCode
92
+ );
93
+ default:
94
+ return new RainfallError(
95
+ typeof data === "object" && data && "message" in data ? String(data.message) : `HTTP ${statusCode}`,
96
+ "UNKNOWN_ERROR",
97
+ statusCode,
98
+ typeof data === "object" ? data : void 0
99
+ );
100
+ }
101
+ }
102
+ var RainfallError, AuthenticationError, RateLimitError, ValidationError, NotFoundError, ServerError, TimeoutError, NetworkError, ToolNotFoundError;
103
+ var init_errors = __esm({
104
+ "src/errors.ts"() {
105
+ "use strict";
106
+ init_cjs_shims();
107
+ RainfallError = class _RainfallError extends Error {
108
+ constructor(message, code, statusCode, details) {
109
+ super(message);
110
+ this.code = code;
111
+ this.statusCode = statusCode;
112
+ this.details = details;
113
+ this.name = "RainfallError";
114
+ Object.setPrototypeOf(this, _RainfallError.prototype);
115
+ }
116
+ toJSON() {
117
+ return {
118
+ name: this.name,
119
+ code: this.code,
120
+ message: this.message,
121
+ statusCode: this.statusCode,
122
+ details: this.details
123
+ };
124
+ }
125
+ };
126
+ AuthenticationError = class _AuthenticationError extends RainfallError {
127
+ constructor(message = "Invalid API key", details) {
128
+ super(message, "AUTHENTICATION_ERROR", 401, details);
129
+ this.name = "AuthenticationError";
130
+ Object.setPrototypeOf(this, _AuthenticationError.prototype);
131
+ }
132
+ };
133
+ RateLimitError = class _RateLimitError extends RainfallError {
134
+ retryAfter;
135
+ limit;
136
+ remaining;
137
+ resetAt;
138
+ constructor(message = "Rate limit exceeded", retryAfter = 60, limit = 0, remaining = 0, resetAt) {
139
+ super(message, "RATE_LIMIT_ERROR", 429, { retryAfter, limit, remaining });
140
+ this.name = "RateLimitError";
141
+ this.retryAfter = retryAfter;
142
+ this.limit = limit;
143
+ this.remaining = remaining;
144
+ this.resetAt = resetAt || new Date(Date.now() + retryAfter * 1e3);
145
+ Object.setPrototypeOf(this, _RateLimitError.prototype);
146
+ }
147
+ };
148
+ ValidationError = class _ValidationError extends RainfallError {
149
+ constructor(message, details) {
150
+ super(message, "VALIDATION_ERROR", 400, details);
151
+ this.name = "ValidationError";
152
+ Object.setPrototypeOf(this, _ValidationError.prototype);
153
+ }
154
+ };
155
+ NotFoundError = class _NotFoundError extends RainfallError {
156
+ constructor(resource, identifier) {
157
+ super(
158
+ `${resource}${identifier ? ` '${identifier}'` : ""} not found`,
159
+ "NOT_FOUND_ERROR",
160
+ 404,
161
+ { resource, identifier }
162
+ );
163
+ this.name = "NotFoundError";
164
+ Object.setPrototypeOf(this, _NotFoundError.prototype);
165
+ }
166
+ };
167
+ ServerError = class _ServerError extends RainfallError {
168
+ constructor(message = "Internal server error", statusCode = 500) {
169
+ super(message, "SERVER_ERROR", statusCode);
170
+ this.name = "ServerError";
171
+ Object.setPrototypeOf(this, _ServerError.prototype);
172
+ }
173
+ };
174
+ TimeoutError = class _TimeoutError extends RainfallError {
175
+ constructor(timeoutMs) {
176
+ super(`Request timed out after ${timeoutMs}ms`, "TIMEOUT_ERROR", 408);
177
+ this.name = "TimeoutError";
178
+ Object.setPrototypeOf(this, _TimeoutError.prototype);
179
+ }
180
+ };
181
+ NetworkError = class _NetworkError extends RainfallError {
182
+ constructor(message = "Network error", details) {
183
+ super(message, "NETWORK_ERROR", void 0, details);
184
+ this.name = "NetworkError";
185
+ Object.setPrototypeOf(this, _NetworkError.prototype);
186
+ }
187
+ };
188
+ ToolNotFoundError = class _ToolNotFoundError extends RainfallError {
189
+ constructor(toolId) {
190
+ super(`Tool '${toolId}' not found`, "TOOL_NOT_FOUND", 404, { toolId });
191
+ this.name = "ToolNotFoundError";
192
+ Object.setPrototypeOf(this, _ToolNotFoundError.prototype);
193
+ }
194
+ };
195
+ }
196
+ });
197
+
40
198
  // src/cli/config.ts
41
199
  var config_exports = {};
42
200
  __export(config_exports, {
@@ -154,137 +312,166 @@ init_cjs_shims();
154
312
 
155
313
  // src/client.ts
156
314
  init_cjs_shims();
315
+ init_errors();
157
316
 
158
- // src/errors.ts
317
+ // src/validation.ts
159
318
  init_cjs_shims();
160
- var RainfallError = class _RainfallError extends Error {
161
- constructor(message, code, statusCode, details) {
162
- super(message);
163
- this.code = code;
164
- this.statusCode = statusCode;
165
- this.details = details;
166
- this.name = "RainfallError";
167
- Object.setPrototypeOf(this, _RainfallError.prototype);
168
- }
169
- toJSON() {
170
- return {
171
- name: this.name,
172
- code: this.code,
173
- message: this.message,
174
- statusCode: this.statusCode,
175
- details: this.details
176
- };
177
- }
178
- };
179
- var AuthenticationError = class _AuthenticationError extends RainfallError {
180
- constructor(message = "Invalid API key", details) {
181
- super(message, "AUTHENTICATION_ERROR", 401, details);
182
- this.name = "AuthenticationError";
183
- Object.setPrototypeOf(this, _AuthenticationError.prototype);
184
- }
185
- };
186
- var RateLimitError = class _RateLimitError extends RainfallError {
187
- retryAfter;
188
- limit;
189
- remaining;
190
- resetAt;
191
- constructor(message = "Rate limit exceeded", retryAfter = 60, limit = 0, remaining = 0, resetAt) {
192
- super(message, "RATE_LIMIT_ERROR", 429, { retryAfter, limit, remaining });
193
- this.name = "RateLimitError";
194
- this.retryAfter = retryAfter;
195
- this.limit = limit;
196
- this.remaining = remaining;
197
- this.resetAt = resetAt || new Date(Date.now() + retryAfter * 1e3);
198
- Object.setPrototypeOf(this, _RateLimitError.prototype);
199
- }
200
- };
201
- var ValidationError = class _ValidationError extends RainfallError {
202
- constructor(message, details) {
203
- super(message, "VALIDATION_ERROR", 400, details);
204
- this.name = "ValidationError";
205
- Object.setPrototypeOf(this, _ValidationError.prototype);
206
- }
207
- };
208
- var NotFoundError = class _NotFoundError extends RainfallError {
209
- constructor(resource, identifier) {
210
- super(
211
- `${resource}${identifier ? ` '${identifier}'` : ""} not found`,
212
- "NOT_FOUND_ERROR",
213
- 404,
214
- { resource, identifier }
215
- );
216
- this.name = "NotFoundError";
217
- Object.setPrototypeOf(this, _NotFoundError.prototype);
218
- }
219
- };
220
- var ServerError = class _ServerError extends RainfallError {
221
- constructor(message = "Internal server error", statusCode = 500) {
222
- super(message, "SERVER_ERROR", statusCode);
223
- this.name = "ServerError";
224
- Object.setPrototypeOf(this, _ServerError.prototype);
225
- }
226
- };
227
- var TimeoutError = class _TimeoutError extends RainfallError {
228
- constructor(timeoutMs) {
229
- super(`Request timed out after ${timeoutMs}ms`, "TIMEOUT_ERROR", 408);
230
- this.name = "TimeoutError";
231
- Object.setPrototypeOf(this, _TimeoutError.prototype);
319
+ init_errors();
320
+ var schemaCache = /* @__PURE__ */ new Map();
321
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
322
+ async function fetchToolSchema(client, toolId) {
323
+ const cached = schemaCache.get(toolId);
324
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
325
+ return cached.schema;
326
+ }
327
+ const response = await client.request(
328
+ `/olympic/subscribers/me/nodes/${toolId}/params`
329
+ );
330
+ if (!response.success || !response.params) {
331
+ throw new ValidationError(`Failed to fetch schema for tool '${toolId}'`);
332
+ }
333
+ schemaCache.set(toolId, { schema: response.params, timestamp: Date.now() });
334
+ return response.params;
335
+ }
336
+ function validateParams(schema, params, toolId) {
337
+ const errors = [];
338
+ const parameters = schema.parameters || {};
339
+ for (const [key, paramSchema] of Object.entries(parameters)) {
340
+ if (paramSchema.optional !== true && !(key in (params || {}))) {
341
+ errors.push({
342
+ path: key,
343
+ message: `Missing required parameter '${key}'`,
344
+ expected: paramSchema.type
345
+ });
346
+ }
232
347
  }
233
- };
234
- var NetworkError = class _NetworkError extends RainfallError {
235
- constructor(message = "Network error", details) {
236
- super(message, "NETWORK_ERROR", void 0, details);
237
- this.name = "NetworkError";
238
- Object.setPrototypeOf(this, _NetworkError.prototype);
348
+ if (params) {
349
+ for (const [key, value] of Object.entries(params)) {
350
+ const paramSchema = parameters[key];
351
+ if (!paramSchema) {
352
+ errors.push({
353
+ path: key,
354
+ message: `Unknown parameter '${key}'`,
355
+ received: value
356
+ });
357
+ continue;
358
+ }
359
+ const typeError = validateType(key, value, paramSchema);
360
+ if (typeError) {
361
+ errors.push(typeError);
362
+ }
363
+ }
239
364
  }
240
- };
241
- function parseErrorResponse(response, data) {
242
- const statusCode = response.status;
243
- if (statusCode === 429) {
244
- const retryAfter = parseInt(response.headers.get("retry-after") || "60", 10);
245
- const limit = parseInt(response.headers.get("x-ratelimit-limit") || "0", 10);
246
- const remaining = parseInt(response.headers.get("x-ratelimit-remaining") || "0", 10);
247
- const resetHeader = response.headers.get("x-ratelimit-reset");
248
- const resetAt = resetHeader ? new Date(parseInt(resetHeader, 10) * 1e3) : void 0;
249
- return new RateLimitError(
250
- typeof data === "object" && data && "message" in data ? String(data.message) : "Rate limit exceeded",
251
- retryAfter,
252
- limit,
253
- remaining,
254
- resetAt
255
- );
365
+ return {
366
+ valid: errors.length === 0,
367
+ errors
368
+ };
369
+ }
370
+ function validateType(path, value, schema) {
371
+ if (value === null || value === void 0) {
372
+ if (schema.optional === true) {
373
+ return null;
374
+ }
375
+ return {
376
+ path,
377
+ message: `Parameter '${path}' is required but received ${value}`,
378
+ received: value,
379
+ expected: schema.type
380
+ };
256
381
  }
257
- switch (statusCode) {
258
- case 401:
259
- return new AuthenticationError(
260
- typeof data === "object" && data && "message" in data ? String(data.message) : "Invalid API key"
261
- );
262
- case 404:
263
- return new NotFoundError(
264
- typeof data === "object" && data && "resource" in data ? String(data.resource) : "Resource",
265
- typeof data === "object" && data && "identifier" in data ? String(data.identifier) : void 0
266
- );
267
- case 400:
268
- return new ValidationError(
269
- typeof data === "object" && data && "message" in data ? String(data.message) : "Invalid request",
270
- typeof data === "object" && data && "details" in data ? data.details : void 0
271
- );
272
- case 500:
273
- case 502:
274
- case 503:
275
- case 504:
276
- return new ServerError(
277
- typeof data === "object" && data && "message" in data ? String(data.message) : "Server error",
278
- statusCode
279
- );
382
+ const expectedType = schema.type;
383
+ const actualType = getJsType(value);
384
+ switch (expectedType) {
385
+ case "string":
386
+ if (typeof value !== "string") {
387
+ return {
388
+ path,
389
+ message: `Parameter '${path}' must be a string, received ${actualType}`,
390
+ received: value,
391
+ expected: "string"
392
+ };
393
+ }
394
+ break;
395
+ case "number":
396
+ if (typeof value !== "number" || isNaN(value)) {
397
+ return {
398
+ path,
399
+ message: `Parameter '${path}' must be a number, received ${actualType}`,
400
+ received: value,
401
+ expected: "number"
402
+ };
403
+ }
404
+ break;
405
+ case "boolean":
406
+ if (typeof value !== "boolean") {
407
+ return {
408
+ path,
409
+ message: `Parameter '${path}' must be a boolean, received ${actualType}`,
410
+ received: value,
411
+ expected: "boolean"
412
+ };
413
+ }
414
+ break;
415
+ case "array":
416
+ if (!Array.isArray(value)) {
417
+ return {
418
+ path,
419
+ message: `Parameter '${path}' must be an array, received ${actualType}`,
420
+ received: value,
421
+ expected: "array"
422
+ };
423
+ }
424
+ if (schema.items) {
425
+ for (let i = 0; i < value.length; i++) {
426
+ const itemError = validateType(`${path}[${i}]`, value[i], schema.items);
427
+ if (itemError) {
428
+ return itemError;
429
+ }
430
+ }
431
+ }
432
+ break;
433
+ case "object":
434
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
435
+ return {
436
+ path,
437
+ message: `Parameter '${path}' must be an object, received ${actualType}`,
438
+ received: value,
439
+ expected: "object"
440
+ };
441
+ }
442
+ if (schema.properties) {
443
+ const objValue = value;
444
+ for (const [propKey, propSchema] of Object.entries(schema.properties)) {
445
+ if (objValue[propKey] !== void 0) {
446
+ const propError = validateType(`${path}.${propKey}`, objValue[propKey], propSchema);
447
+ if (propError) {
448
+ return propError;
449
+ }
450
+ }
451
+ }
452
+ }
453
+ break;
280
454
  default:
281
- return new RainfallError(
282
- typeof data === "object" && data && "message" in data ? String(data.message) : `HTTP ${statusCode}`,
283
- "UNKNOWN_ERROR",
284
- statusCode,
285
- typeof data === "object" ? data : void 0
286
- );
455
+ break;
287
456
  }
457
+ return null;
458
+ }
459
+ function getJsType(value) {
460
+ if (value === null) return "null";
461
+ if (Array.isArray(value)) return "array";
462
+ return typeof value;
463
+ }
464
+ function formatValidationErrors(result) {
465
+ if (result.valid) return "No validation errors";
466
+ const lines = result.errors.map((err) => {
467
+ let line = ` - ${err.message}`;
468
+ if (err.received !== void 0) {
469
+ line += ` (received: ${JSON.stringify(err.received).slice(0, 50)})`;
470
+ }
471
+ return line;
472
+ });
473
+ return `Validation failed with ${result.errors.length} error(s):
474
+ ${lines.join("\n")}`;
288
475
  }
289
476
 
290
477
  // src/client.ts
@@ -298,6 +485,7 @@ var RainfallClient = class {
298
485
  defaultTimeout;
299
486
  defaultRetries;
300
487
  defaultRetryDelay;
488
+ disableValidation;
301
489
  lastRateLimitInfo;
302
490
  subscriberId;
303
491
  constructor(config) {
@@ -306,6 +494,7 @@ var RainfallClient = class {
306
494
  this.defaultTimeout = config.timeout || DEFAULT_TIMEOUT;
307
495
  this.defaultRetries = config.retries ?? DEFAULT_RETRIES;
308
496
  this.defaultRetryDelay = config.retryDelay || DEFAULT_RETRY_DELAY;
497
+ this.disableValidation = config.disableValidation ?? false;
309
498
  }
310
499
  /**
311
500
  * Get the last rate limit info from the API
@@ -388,15 +577,68 @@ var RainfallClient = class {
388
577
  }
389
578
  /**
390
579
  * Execute a tool/node by ID
580
+ *
581
+ * @param toolId - The ID of the tool/node to execute
582
+ * @param params - Parameters to pass to the tool
583
+ * @param options - Request options including skipValidation to bypass param validation
391
584
  */
392
585
  async executeTool(toolId, params, options) {
586
+ if (!this.disableValidation && !options?.skipValidation) {
587
+ const validation = await this.validateToolParams(toolId, params);
588
+ if (!validation.valid) {
589
+ const { ValidationError: ValidationError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
590
+ throw new ValidationError2(
591
+ `Parameter validation failed for tool '${toolId}': ${formatValidationErrors(validation)}`,
592
+ { toolId, errors: validation.errors }
593
+ );
594
+ }
595
+ }
393
596
  const subscriberId = await this.ensureSubscriberId();
394
597
  const response = await this.request(`/olympic/subscribers/${subscriberId}/nodes/${toolId}`, {
395
598
  method: "POST",
396
599
  body: params || {}
397
600
  }, options);
601
+ if (response.success === false) {
602
+ const errorMessage = typeof response.error === "string" ? response.error : JSON.stringify(response.error);
603
+ throw new RainfallError(
604
+ `Tool execution failed: ${errorMessage}`,
605
+ "TOOL_EXECUTION_ERROR",
606
+ 400,
607
+ { toolId, error: response.error }
608
+ );
609
+ }
398
610
  return response.result;
399
611
  }
612
+ /**
613
+ * Validate parameters for a tool without executing it
614
+ * Fetches the tool schema and validates the provided params
615
+ *
616
+ * @param toolId - The ID of the tool to validate params for
617
+ * @param params - Parameters to validate
618
+ * @returns Validation result with detailed error information
619
+ *
620
+ * @example
621
+ * ```typescript
622
+ * const result = await client.validateToolParams('finviz-quotes', { tickers: ['AAPL'] });
623
+ * if (!result.valid) {
624
+ * console.log('Validation errors:', result.errors);
625
+ * }
626
+ * ```
627
+ */
628
+ async validateToolParams(toolId, params) {
629
+ try {
630
+ const schema = await fetchToolSchema(this, toolId);
631
+ return validateParams(schema, params, toolId);
632
+ } catch (error) {
633
+ if (error instanceof RainfallError && error.statusCode === 404) {
634
+ return {
635
+ valid: false,
636
+ errors: [{ path: toolId, message: `Tool '${toolId}' not found` }]
637
+ };
638
+ }
639
+ return { valid: true, errors: [] };
640
+ }
641
+ }
400
642
  /**
401
643
  * List all available tools
402
644
  */
@@ -419,11 +661,20 @@ var RainfallClient = class {
419
661
  }
420
662
  /**
421
663
  * Get tool schema/parameters
664
+ *
665
+ * @param toolId - The ID of the tool to get schema for
666
+ * @returns Tool schema including parameters and output definitions
422
667
  */
423
668
  async getToolSchema(toolId) {
424
- const subscriberId = await this.ensureSubscriberId();
425
- const response = await this.request(`/olympic/subscribers/${subscriberId}/nodes/${toolId}/params`);
426
- return response.params;
669
+ const schema = await fetchToolSchema(this, toolId);
670
+ return {
671
+ name: schema.name,
672
+ description: schema.description,
673
+ category: schema.category,
674
+ parameters: schema.parameters,
675
+ output: schema.output,
676
+ metadata: schema.metadata || {}
677
+ };
427
678
  }
428
679
  /**
429
680
  * Get subscriber info
@@ -950,9 +1201,40 @@ var Rainfall = class {
950
1201
  }
951
1202
  /**
952
1203
  * Execute any tool by ID (low-level access)
1204
+ *
1205
+ * @param toolId - The ID of the tool to execute
1206
+ * @param params - Parameters to pass to the tool
1207
+ * @param options - Execution options including skipValidation to bypass param validation
1208
+ *
1209
+ * @example
1210
+ * ```typescript
1211
+ * // Execute with validation (default)
1212
+ * const result = await rainfall.executeTool('finviz-quotes', { tickers: ['AAPL'] });
1213
+ *
1214
+ * // Execute without validation
1215
+ * const result = await rainfall.executeTool('finviz-quotes', { tickers: ['AAPL'] }, { skipValidation: true });
1216
+ * ```
953
1217
  */
954
- async executeTool(toolId, params) {
955
- return this.client.executeTool(toolId, params);
1218
+ async executeTool(toolId, params, options) {
1219
+ return this.client.executeTool(toolId, params, options);
1220
+ }
1221
+ /**
1222
+ * Validate parameters for a tool without executing it
1223
+ *
1224
+ * @param toolId - The ID of the tool to validate params for
1225
+ * @param params - Parameters to validate
1226
+ * @returns Validation result with detailed error information
1227
+ *
1228
+ * @example
1229
+ * ```typescript
1230
+ * const result = await rainfall.validateToolParams('finviz-quotes', { tickers: ['AAPL'] });
1231
+ * if (!result.valid) {
1232
+ * console.log('Validation errors:', result.errors);
1233
+ * }
1234
+ * ```
1235
+ */
1236
+ async validateToolParams(toolId, params) {
1237
+ return this.client.validateToolParams(toolId, params);
956
1238
  }
957
1239
  /**
958
1240
  * Get current subscriber info and usage
@@ -5,7 +5,8 @@ import {
5
5
  } from "../chunk-7MRE4ZVI.mjs";
6
6
  import {
7
7
  Rainfall
8
- } from "../chunk-VDPKDC3R.mjs";
8
+ } from "../chunk-CQ5TV7CQ.mjs";
9
+ import "../chunk-LJQEO3CY.mjs";
9
10
 
10
11
  // src/daemon/index.ts
11
12
  import { WebSocketServer } from "ws";
@@ -0,0 +1,14 @@
1
+ import {
2
+ detectImageData,
3
+ detectImageSupport,
4
+ displayImage,
5
+ formatAsTable,
6
+ formatResult
7
+ } from "./chunk-XHPFY5MH.mjs";
8
+ export {
9
+ detectImageData,
10
+ detectImageSupport,
11
+ displayImage,
12
+ formatAsTable,
13
+ formatResult
14
+ };
@@ -0,0 +1,24 @@
1
+ import {
2
+ AuthenticationError,
3
+ NetworkError,
4
+ NotFoundError,
5
+ RainfallError,
6
+ RateLimitError,
7
+ ServerError,
8
+ TimeoutError,
9
+ ToolNotFoundError,
10
+ ValidationError,
11
+ parseErrorResponse
12
+ } from "./chunk-LJQEO3CY.mjs";
13
+ export {
14
+ AuthenticationError,
15
+ NetworkError,
16
+ NotFoundError,
17
+ RainfallError,
18
+ RateLimitError,
19
+ ServerError,
20
+ TimeoutError,
21
+ ToolNotFoundError,
22
+ ValidationError,
23
+ parseErrorResponse
24
+ };