@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.
@@ -0,0 +1,987 @@
1
+ import {
2
+ NetworkError,
3
+ RainfallError,
4
+ TimeoutError,
5
+ ValidationError,
6
+ parseErrorResponse
7
+ } from "./chunk-LJQEO3CY.mjs";
8
+
9
+ // src/validation.ts
10
+ var schemaCache = /* @__PURE__ */ new Map();
11
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
12
+ async function fetchToolSchema(client, toolId) {
13
+ const cached = schemaCache.get(toolId);
14
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
15
+ return cached.schema;
16
+ }
17
+ const response = await client.request(
18
+ `/olympic/subscribers/me/nodes/${toolId}/params`
19
+ );
20
+ if (!response.success || !response.params) {
21
+ throw new ValidationError(`Failed to fetch schema for tool '${toolId}'`);
22
+ }
23
+ schemaCache.set(toolId, { schema: response.params, timestamp: Date.now() });
24
+ return response.params;
25
+ }
26
+ function clearSchemaCache() {
27
+ schemaCache.clear();
28
+ }
29
+ function validateParams(schema, params, toolId) {
30
+ const errors = [];
31
+ const parameters = schema.parameters || {};
32
+ for (const [key, paramSchema] of Object.entries(parameters)) {
33
+ if (paramSchema.optional !== true && !(key in (params || {}))) {
34
+ errors.push({
35
+ path: key,
36
+ message: `Missing required parameter '${key}'`,
37
+ expected: paramSchema.type
38
+ });
39
+ }
40
+ }
41
+ if (params) {
42
+ for (const [key, value] of Object.entries(params)) {
43
+ const paramSchema = parameters[key];
44
+ if (!paramSchema) {
45
+ errors.push({
46
+ path: key,
47
+ message: `Unknown parameter '${key}'`,
48
+ received: value
49
+ });
50
+ continue;
51
+ }
52
+ const typeError = validateType(key, value, paramSchema);
53
+ if (typeError) {
54
+ errors.push(typeError);
55
+ }
56
+ }
57
+ }
58
+ return {
59
+ valid: errors.length === 0,
60
+ errors
61
+ };
62
+ }
63
+ function validateType(path, value, schema) {
64
+ if (value === null || value === void 0) {
65
+ if (schema.optional === true) {
66
+ return null;
67
+ }
68
+ return {
69
+ path,
70
+ message: `Parameter '${path}' is required but received ${value}`,
71
+ received: value,
72
+ expected: schema.type
73
+ };
74
+ }
75
+ const expectedType = schema.type;
76
+ const actualType = getJsType(value);
77
+ switch (expectedType) {
78
+ case "string":
79
+ if (typeof value !== "string") {
80
+ return {
81
+ path,
82
+ message: `Parameter '${path}' must be a string, received ${actualType}`,
83
+ received: value,
84
+ expected: "string"
85
+ };
86
+ }
87
+ break;
88
+ case "number":
89
+ if (typeof value !== "number" || isNaN(value)) {
90
+ return {
91
+ path,
92
+ message: `Parameter '${path}' must be a number, received ${actualType}`,
93
+ received: value,
94
+ expected: "number"
95
+ };
96
+ }
97
+ break;
98
+ case "boolean":
99
+ if (typeof value !== "boolean") {
100
+ return {
101
+ path,
102
+ message: `Parameter '${path}' must be a boolean, received ${actualType}`,
103
+ received: value,
104
+ expected: "boolean"
105
+ };
106
+ }
107
+ break;
108
+ case "array":
109
+ if (!Array.isArray(value)) {
110
+ return {
111
+ path,
112
+ message: `Parameter '${path}' must be an array, received ${actualType}`,
113
+ received: value,
114
+ expected: "array"
115
+ };
116
+ }
117
+ if (schema.items) {
118
+ for (let i = 0; i < value.length; i++) {
119
+ const itemError = validateType(`${path}[${i}]`, value[i], schema.items);
120
+ if (itemError) {
121
+ return itemError;
122
+ }
123
+ }
124
+ }
125
+ break;
126
+ case "object":
127
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
128
+ return {
129
+ path,
130
+ message: `Parameter '${path}' must be an object, received ${actualType}`,
131
+ received: value,
132
+ expected: "object"
133
+ };
134
+ }
135
+ if (schema.properties) {
136
+ const objValue = value;
137
+ for (const [propKey, propSchema] of Object.entries(schema.properties)) {
138
+ if (objValue[propKey] !== void 0) {
139
+ const propError = validateType(`${path}.${propKey}`, objValue[propKey], propSchema);
140
+ if (propError) {
141
+ return propError;
142
+ }
143
+ }
144
+ }
145
+ }
146
+ break;
147
+ default:
148
+ break;
149
+ }
150
+ return null;
151
+ }
152
+ function getJsType(value) {
153
+ if (value === null) return "null";
154
+ if (Array.isArray(value)) return "array";
155
+ return typeof value;
156
+ }
157
+ function formatValidationErrors(result) {
158
+ if (result.valid) return "No validation errors";
159
+ const lines = result.errors.map((err) => {
160
+ let line = ` - ${err.message}`;
161
+ if (err.received !== void 0) {
162
+ line += ` (received: ${JSON.stringify(err.received).slice(0, 50)})`;
163
+ }
164
+ return line;
165
+ });
166
+ return `Validation failed with ${result.errors.length} error(s):
167
+ ${lines.join("\n")}`;
168
+ }
169
+
170
+ // src/client.ts
171
+ var DEFAULT_BASE_URL = "https://olympic-api.pragma-digital.org/v1";
172
+ var DEFAULT_TIMEOUT = 3e4;
173
+ var DEFAULT_RETRIES = 3;
174
+ var DEFAULT_RETRY_DELAY = 1e3;
175
+ var RainfallClient = class {
176
+ apiKey;
177
+ baseUrl;
178
+ defaultTimeout;
179
+ defaultRetries;
180
+ defaultRetryDelay;
181
+ lastRateLimitInfo;
182
+ subscriberId;
183
+ constructor(config) {
184
+ this.apiKey = config.apiKey;
185
+ this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
186
+ this.defaultTimeout = config.timeout || DEFAULT_TIMEOUT;
187
+ this.defaultRetries = config.retries ?? DEFAULT_RETRIES;
188
+ this.defaultRetryDelay = config.retryDelay || DEFAULT_RETRY_DELAY;
189
+ }
190
+ /**
191
+ * Get the last rate limit info from the API
192
+ */
193
+ getRateLimitInfo() {
194
+ return this.lastRateLimitInfo;
195
+ }
196
+ /**
197
+ * Make an authenticated request to the Rainfall API
198
+ */
199
+ async request(path, options = {}, requestOptions) {
200
+ const timeout = requestOptions?.timeout ?? this.defaultTimeout;
201
+ const maxRetries = requestOptions?.retries ?? this.defaultRetries;
202
+ const retryDelay = requestOptions?.retryDelay ?? this.defaultRetryDelay;
203
+ const url = `${this.baseUrl}${path}`;
204
+ const method = options.method || "GET";
205
+ let lastError;
206
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
207
+ try {
208
+ const controller = new AbortController();
209
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
210
+ const response = await fetch(url, {
211
+ method,
212
+ headers: {
213
+ "x-api-key": this.apiKey,
214
+ "Content-Type": "application/json",
215
+ "Accept": "application/json",
216
+ "X-Rainfall-SDK-Version": "0.1.0",
217
+ ...options.headers
218
+ },
219
+ body: options.body ? JSON.stringify(options.body) : void 0,
220
+ signal: controller.signal
221
+ });
222
+ clearTimeout(timeoutId);
223
+ const limit = response.headers.get("x-ratelimit-limit");
224
+ const remaining = response.headers.get("x-ratelimit-remaining");
225
+ const reset = response.headers.get("x-ratelimit-reset");
226
+ if (limit && remaining && reset) {
227
+ this.lastRateLimitInfo = {
228
+ limit: parseInt(limit, 10),
229
+ remaining: parseInt(remaining, 10),
230
+ resetAt: new Date(parseInt(reset, 10) * 1e3)
231
+ };
232
+ }
233
+ let data;
234
+ const contentType = response.headers.get("content-type");
235
+ if (contentType?.includes("application/json")) {
236
+ data = await response.json();
237
+ } else {
238
+ data = await response.text();
239
+ }
240
+ if (!response.ok) {
241
+ throw parseErrorResponse(response, data);
242
+ }
243
+ return data;
244
+ } catch (error) {
245
+ if (error instanceof RainfallError) {
246
+ if (error.statusCode && error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429) {
247
+ throw error;
248
+ }
249
+ if (error.statusCode === 401) {
250
+ throw error;
251
+ }
252
+ }
253
+ if (error instanceof Error && error.name === "AbortError") {
254
+ lastError = new TimeoutError(timeout);
255
+ } else if (error instanceof TypeError) {
256
+ lastError = new NetworkError(error.message);
257
+ } else {
258
+ lastError = error instanceof Error ? error : new Error(String(error));
259
+ }
260
+ if (attempt >= maxRetries) {
261
+ break;
262
+ }
263
+ const delay = retryDelay * Math.pow(2, attempt) + Math.random() * 1e3;
264
+ await this.sleep(delay);
265
+ }
266
+ }
267
+ throw lastError || new RainfallError("Request failed", "REQUEST_FAILED");
268
+ }
269
+ /**
270
+ * Execute a tool/node by ID
271
+ *
272
+ * @param toolId - The ID of the tool/node to execute
273
+ * @param params - Parameters to pass to the tool
274
+ * @param options - Request options including skipValidation to bypass param validation
275
+ */
276
+ async executeTool(toolId, params, options) {
277
+ if (!options?.skipValidation) {
278
+ const validation = await this.validateToolParams(toolId, params);
279
+ if (!validation.valid) {
280
+ const { ValidationError: ValidationError2 } = await import("./errors-CY6HW2I5.mjs");
281
+ throw new ValidationError2(
282
+ `Parameter validation failed for tool '${toolId}': ${formatValidationErrors(validation)}`,
283
+ { toolId, errors: validation.errors }
284
+ );
285
+ }
286
+ }
287
+ const subscriberId = await this.ensureSubscriberId();
288
+ const response = await this.request(`/olympic/subscribers/${subscriberId}/nodes/${toolId}`, {
289
+ method: "POST",
290
+ body: params || {}
291
+ }, options);
292
+ if (response.success === false) {
293
+ const errorMessage = typeof response.error === "string" ? response.error : JSON.stringify(response.error);
294
+ throw new RainfallError(
295
+ `Tool execution failed: ${errorMessage}`,
296
+ "TOOL_EXECUTION_ERROR",
297
+ 400,
298
+ { toolId, error: response.error }
299
+ );
300
+ }
301
+ return response.result;
302
+ }
303
+ /**
304
+ * Validate parameters for a tool without executing it
305
+ * Fetches the tool schema and validates the provided params
306
+ *
307
+ * @param toolId - The ID of the tool to validate params for
308
+ * @param params - Parameters to validate
309
+ * @returns Validation result with detailed error information
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * const result = await client.validateToolParams('finviz-quotes', { tickers: ['AAPL'] });
314
+ * if (!result.valid) {
315
+ * console.log('Validation errors:', result.errors);
316
+ * }
317
+ * ```
318
+ */
319
+ async validateToolParams(toolId, params) {
320
+ try {
321
+ const schema = await fetchToolSchema(this, toolId);
322
+ return validateParams(schema, params, toolId);
323
+ } catch (error) {
324
+ if (error instanceof RainfallError && error.statusCode === 404) {
325
+ return {
326
+ valid: false,
327
+ errors: [{ path: toolId, message: `Tool '${toolId}' not found` }]
328
+ };
329
+ }
330
+ return { valid: true, errors: [] };
331
+ }
332
+ }
333
+ /**
334
+ * List all available tools
335
+ */
336
+ async listTools() {
337
+ const subscriberId = await this.ensureSubscriberId();
338
+ const result = await this.request(`/olympic/subscribers/${subscriberId}/nodes/_utils/node-descriptions`);
339
+ if (result.success && result.nodes) {
340
+ return Object.values(result.nodes);
341
+ }
342
+ const legacyResult = await this.request(`/olympic/subscribers/${subscriberId}/nodes/_utils/node-list`);
343
+ if (legacyResult.keys && Array.isArray(legacyResult.keys)) {
344
+ return legacyResult.keys.map((key) => ({
345
+ id: key,
346
+ name: key,
347
+ description: "",
348
+ category: "general"
349
+ }));
350
+ }
351
+ return legacyResult.nodes || [];
352
+ }
353
+ /**
354
+ * Get tool schema/parameters
355
+ *
356
+ * @param toolId - The ID of the tool to get schema for
357
+ * @returns Tool schema including parameters and output definitions
358
+ */
359
+ async getToolSchema(toolId) {
360
+ const schema = await fetchToolSchema(this, toolId);
361
+ return {
362
+ name: schema.name,
363
+ description: schema.description,
364
+ category: schema.category,
365
+ parameters: schema.parameters,
366
+ output: schema.output,
367
+ metadata: schema.metadata || {}
368
+ };
369
+ }
370
+ /**
371
+ * Get subscriber info
372
+ */
373
+ async getMe() {
374
+ const result = await this.request("/olympic/subscribers/me");
375
+ if (result.subscriber?.id) {
376
+ this.subscriberId = result.subscriber.id;
377
+ }
378
+ const subscriber = result.subscriber;
379
+ return {
380
+ id: subscriber.id,
381
+ name: subscriber.name,
382
+ email: subscriber.google_id,
383
+ billingStatus: subscriber.billing_status,
384
+ plan: subscriber.billing_status,
385
+ usage: {
386
+ callsThisMonth: subscriber.metadata?.usage?.callsThisMonth ?? 0,
387
+ callsLimit: subscriber.metadata?.usage?.callsLimit ?? 5e3
388
+ }
389
+ };
390
+ }
391
+ /**
392
+ * Ensure we have a subscriber ID, fetching it if necessary
393
+ */
394
+ async ensureSubscriberId() {
395
+ if (this.subscriberId) {
396
+ return this.subscriberId;
397
+ }
398
+ const me = await this.getMe();
399
+ if (!me.id) {
400
+ throw new RainfallError("Failed to get subscriber ID", "NO_SUBSCRIBER_ID");
401
+ }
402
+ return me.id;
403
+ }
404
+ sleep(ms) {
405
+ return new Promise((resolve) => setTimeout(resolve, ms));
406
+ }
407
+ /**
408
+ * OpenAI-compatible chat completions with tool support
409
+ */
410
+ async chatCompletions(params) {
411
+ const { subscriber_id, ...body } = params;
412
+ if (body.stream) {
413
+ const url = `${this.baseUrl}/olympic/subscribers/${subscriber_id}/v1/chat/completions`;
414
+ const response = await fetch(url, {
415
+ method: "POST",
416
+ headers: {
417
+ "x-api-key": this.apiKey,
418
+ "Content-Type": "application/json",
419
+ "Accept": "text/event-stream"
420
+ },
421
+ body: JSON.stringify(body)
422
+ });
423
+ if (!response.ok) {
424
+ const error = await response.text();
425
+ throw new RainfallError(`Chat completions failed: ${error}`, "CHAT_ERROR");
426
+ }
427
+ if (!response.body) {
428
+ throw new RainfallError("No response body", "CHAT_ERROR");
429
+ }
430
+ return response.body;
431
+ }
432
+ return this.request(
433
+ `/olympic/subscribers/${subscriber_id}/v1/chat/completions`,
434
+ {
435
+ method: "POST",
436
+ body
437
+ }
438
+ );
439
+ }
440
+ /**
441
+ * List available models (OpenAI-compatible format)
442
+ */
443
+ async listModels(subscriberId) {
444
+ const sid = subscriberId || this.subscriberId || await this.ensureSubscriberId();
445
+ const result = await this.request(
446
+ `/olympic/subscribers/${sid}/v1/models`
447
+ );
448
+ return result.data || [];
449
+ }
450
+ };
451
+
452
+ // src/namespaces/integrations.ts
453
+ function createIntegrations(client) {
454
+ return new IntegrationsNamespace(client);
455
+ }
456
+ var IntegrationsNamespace = class {
457
+ constructor(client) {
458
+ this.client = client;
459
+ }
460
+ get github() {
461
+ return {
462
+ issues: {
463
+ create: (params) => this.client.executeTool("github-create-issue", params),
464
+ list: (params) => this.client.executeTool("github-list-issues", params),
465
+ get: (params) => this.client.executeTool("github-get-issue", params),
466
+ update: (params) => this.client.executeTool("github-update-issue", params),
467
+ addComment: (params) => this.client.executeTool("github-add-issue-comment", params)
468
+ },
469
+ repos: {
470
+ get: (params) => this.client.executeTool("github-get-repository", params),
471
+ listBranches: (params) => this.client.executeTool("github-list-branches", params)
472
+ },
473
+ pullRequests: {
474
+ list: (params) => this.client.executeTool("github-list-pull-requests", params),
475
+ get: (params) => this.client.executeTool("github-get-pull-request", params)
476
+ }
477
+ };
478
+ }
479
+ get notion() {
480
+ return {
481
+ pages: {
482
+ create: (params) => this.client.executeTool("notion-pages-create", params),
483
+ retrieve: (params) => this.client.executeTool("notion-pages-retrieve", params),
484
+ update: (params) => this.client.executeTool("notion-pages-update", params)
485
+ },
486
+ databases: {
487
+ query: (params) => this.client.executeTool("notion-databases-query", params),
488
+ retrieve: (params) => this.client.executeTool("notion-databases-retrieve", params)
489
+ },
490
+ blocks: {
491
+ appendChildren: (params) => this.client.executeTool("notion-blocks-append-children", params),
492
+ retrieveChildren: (params) => this.client.executeTool("notion-blocks-retrieve-children", params)
493
+ }
494
+ };
495
+ }
496
+ get linear() {
497
+ return {
498
+ issues: {
499
+ create: (params) => this.client.executeTool("linear-core-issueCreate", params),
500
+ list: (params) => this.client.executeTool("linear-core-issues", params),
501
+ get: (params) => this.client.executeTool("linear-core-issue", params),
502
+ update: (params) => this.client.executeTool("linear-core-issueUpdate", params),
503
+ archive: (params) => this.client.executeTool("linear-core-issueArchive", params)
504
+ },
505
+ teams: {
506
+ list: () => this.client.executeTool("linear-core-teams", {})
507
+ }
508
+ };
509
+ }
510
+ get slack() {
511
+ return {
512
+ messages: {
513
+ send: (params) => this.client.executeTool("slack-core-postMessage", params),
514
+ list: (params) => this.client.executeTool("slack-core-listMessages", params)
515
+ },
516
+ channels: {
517
+ list: () => this.client.executeTool("slack-core-listChannels", {})
518
+ },
519
+ users: {
520
+ list: () => this.client.executeTool("slack-core-listUsers", {})
521
+ },
522
+ reactions: {
523
+ add: (params) => this.client.executeTool("slack-core-addReaction", params)
524
+ }
525
+ };
526
+ }
527
+ get figma() {
528
+ return {
529
+ files: {
530
+ get: (params) => this.client.executeTool("figma-files-getFile", { fileKey: params.fileKey }),
531
+ getNodes: (params) => this.client.executeTool("figma-files-getFileNodes", { fileKey: params.fileKey, nodeIds: params.nodeIds }),
532
+ getImages: (params) => this.client.executeTool("figma-files-getFileImage", { fileKey: params.fileKey, nodeIds: params.nodeIds, format: params.format }),
533
+ getComments: (params) => this.client.executeTool("figma-comments-getFileComments", { fileKey: params.fileKey }),
534
+ postComment: (params) => this.client.executeTool("figma-comments-postComment", { fileKey: params.fileKey, message: params.message, nodeId: params.nodeId })
535
+ },
536
+ projects: {
537
+ list: (params) => this.client.executeTool("figma-projects-getTeamProjects", { teamId: params.teamId }),
538
+ getFiles: (params) => this.client.executeTool("figma-projects-getProjectFiles", { projectId: params.projectId })
539
+ }
540
+ };
541
+ }
542
+ get stripe() {
543
+ return {
544
+ customers: {
545
+ create: (params) => this.client.executeTool("stripe-customers-create", params),
546
+ retrieve: (params) => this.client.executeTool("stripe-customers-retrieve", { customerId: params.customerId }),
547
+ update: (params) => this.client.executeTool("stripe-customers-update", params),
548
+ listPaymentMethods: (params) => this.client.executeTool("stripe-customers-list-payment-methods", { customerId: params.customerId })
549
+ },
550
+ paymentIntents: {
551
+ create: (params) => this.client.executeTool("stripe-payment-intents-create", params),
552
+ retrieve: (params) => this.client.executeTool("stripe-payment-intents-retrieve", { paymentIntentId: params.paymentIntentId }),
553
+ confirm: (params) => this.client.executeTool("stripe-payment-intents-confirm", { paymentIntentId: params.paymentIntentId })
554
+ },
555
+ subscriptions: {
556
+ create: (params) => this.client.executeTool("stripe-subscriptions-create", params),
557
+ retrieve: (params) => this.client.executeTool("stripe-subscriptions-retrieve", { subscriptionId: params.subscriptionId }),
558
+ cancel: (params) => this.client.executeTool("stripe-subscriptions-cancel", { subscriptionId: params.subscriptionId })
559
+ }
560
+ };
561
+ }
562
+ };
563
+
564
+ // src/namespaces/memory.ts
565
+ function createMemory(client) {
566
+ return {
567
+ create: (params) => client.executeTool("memory-create", params),
568
+ get: (params) => client.executeTool("memory-get", { memoryId: params.memoryId }),
569
+ recall: (params) => client.executeTool("memory-recall", params),
570
+ list: (params) => client.executeTool("memory-list", params ?? {}),
571
+ update: (params) => client.executeTool("memory-update", params),
572
+ delete: (params) => client.executeTool("memory-delete", { memoryId: params.memoryId })
573
+ };
574
+ }
575
+
576
+ // src/namespaces/articles.ts
577
+ function createArticles(client) {
578
+ return {
579
+ search: (params) => client.executeTool("article-search", params),
580
+ create: (params) => client.executeTool("article-create", params),
581
+ createFromUrl: (params) => client.executeTool("article-create-from-url", params),
582
+ fetch: (params) => client.executeTool("article-fetch", params),
583
+ recent: (params) => client.executeTool("article-recent", params ?? {}),
584
+ relevant: (params) => client.executeTool("article-relevant-news", params),
585
+ summarize: (params) => client.executeTool("article-summarize", params),
586
+ extractTopics: (params) => client.executeTool("article-topic-extractor", params)
587
+ };
588
+ }
589
+
590
+ // src/namespaces/web.ts
591
+ function createWeb(client) {
592
+ return {
593
+ search: {
594
+ exa: (params) => client.executeTool("exa-web-search", params),
595
+ perplexity: (params) => client.executeTool("perplexity-search", params)
596
+ },
597
+ fetch: (params) => client.executeTool("web-fetch", params),
598
+ htmlToMarkdown: (params) => client.executeTool("html-to-markdown-converter", params),
599
+ extractHtml: (params) => client.executeTool("extract-html-selector", params)
600
+ };
601
+ }
602
+
603
+ // src/namespaces/ai.ts
604
+ function createAI(client) {
605
+ return {
606
+ embeddings: {
607
+ document: (params) => client.executeTool("jina-document-embedding", params),
608
+ query: (params) => client.executeTool("jina-query-embedding", params),
609
+ image: (params) => client.executeTool("jina-image-embedding", { image: params.imageBase64 })
610
+ },
611
+ image: {
612
+ generate: (params) => client.executeTool("image-generation", params)
613
+ },
614
+ ocr: (params) => client.executeTool("ocr-text-extraction", { image: params.imageBase64 }),
615
+ vision: (params) => client.executeTool("llama-scout-vision", { image: params.imageBase64, prompt: params.prompt }),
616
+ chat: (params) => client.executeTool("xai-chat-completions", params),
617
+ complete: (params) => client.executeTool("fim", params),
618
+ classify: (params) => client.executeTool("jina-document-classifier", params),
619
+ segment: (params) => client.executeTool("jina-text-segmenter", params),
620
+ /**
621
+ * OpenAI-compatible chat completions with full tool support
622
+ * This is the recommended method for multi-turn conversations with tools
623
+ */
624
+ chatCompletions: (params) => client.chatCompletions(params)
625
+ };
626
+ }
627
+
628
+ // src/namespaces/data.ts
629
+ function createData(client) {
630
+ return {
631
+ csv: {
632
+ query: (params) => client.executeTool("query-csv", params),
633
+ convert: (params) => client.executeTool("csv-convert", params)
634
+ },
635
+ scripts: {
636
+ create: (params) => client.executeTool("create-saved-script", params),
637
+ execute: (params) => client.executeTool("execute-saved-script", params),
638
+ list: () => client.executeTool("list-saved-scripts", {}),
639
+ update: (params) => client.executeTool("update-saved-script", params),
640
+ delete: (params) => client.executeTool("delete-saved-script", params)
641
+ },
642
+ similarity: {
643
+ search: (params) => client.executeTool("duck-db-similarity-search", params),
644
+ duckDbSearch: (params) => client.executeTool("duck-db-similarity-search", params)
645
+ }
646
+ };
647
+ }
648
+
649
+ // src/namespaces/utils.ts
650
+ function createUtils(client) {
651
+ return {
652
+ mermaid: (params) => client.executeTool("mermaid-diagram-generator", { mermaid: params.diagram }),
653
+ documentConvert: (params) => client.executeTool("document-format-converter", {
654
+ base64: `data:${params.mimeType};base64,${Buffer.from(params.document).toString("base64")}`,
655
+ format: params.format
656
+ }),
657
+ regex: {
658
+ match: (params) => client.executeTool("regex-match", params),
659
+ replace: (params) => client.executeTool("regex-replace", params)
660
+ },
661
+ jsonExtract: (params) => client.executeTool("json-extract", params),
662
+ digest: (params) => client.executeTool("digest-generator", { text: params.data }),
663
+ monteCarlo: (params) => client.executeTool("monte-carlo-simulation", params)
664
+ };
665
+ }
666
+
667
+ // src/sdk.ts
668
+ var Rainfall = class {
669
+ client;
670
+ _integrations;
671
+ _memory;
672
+ _articles;
673
+ _web;
674
+ _ai;
675
+ _data;
676
+ _utils;
677
+ constructor(config) {
678
+ this.client = new RainfallClient(config);
679
+ }
680
+ /**
681
+ * Integrations namespace - GitHub, Notion, Linear, Slack, Figma, Stripe
682
+ *
683
+ * @example
684
+ * ```typescript
685
+ * // GitHub
686
+ * await rainfall.integrations.github.issues.create({
687
+ * owner: 'facebook',
688
+ * repo: 'react',
689
+ * title: 'Bug report'
690
+ * });
691
+ *
692
+ * // Slack
693
+ * await rainfall.integrations.slack.messages.send({
694
+ * channelId: 'C123456',
695
+ * text: 'Hello team!'
696
+ * });
697
+ *
698
+ * // Linear
699
+ * const issues = await rainfall.integrations.linear.issues.list();
700
+ * ```
701
+ */
702
+ get integrations() {
703
+ if (!this._integrations) {
704
+ this._integrations = createIntegrations(this.client);
705
+ }
706
+ return this._integrations;
707
+ }
708
+ /**
709
+ * Memory namespace - Semantic memory storage and retrieval
710
+ *
711
+ * @example
712
+ * ```typescript
713
+ * // Store a memory
714
+ * await rainfall.memory.create({
715
+ * content: 'User prefers dark mode',
716
+ * keywords: ['preference', 'ui']
717
+ * });
718
+ *
719
+ * // Recall similar memories
720
+ * const memories = await rainfall.memory.recall({
721
+ * query: 'user preferences',
722
+ * topK: 5
723
+ * });
724
+ * ```
725
+ */
726
+ get memory() {
727
+ if (!this._memory) {
728
+ this._memory = createMemory(this.client);
729
+ }
730
+ return this._memory;
731
+ }
732
+ /**
733
+ * Articles namespace - News aggregation and article management
734
+ *
735
+ * @example
736
+ * ```typescript
737
+ * // Search news
738
+ * const articles = await rainfall.articles.search({
739
+ * query: 'artificial intelligence'
740
+ * });
741
+ *
742
+ * // Create from URL
743
+ * const article = await rainfall.articles.createFromUrl({
744
+ * url: 'https://example.com/article'
745
+ * });
746
+ *
747
+ * // Summarize
748
+ * const summary = await rainfall.articles.summarize({
749
+ * text: article.content
750
+ * });
751
+ * ```
752
+ */
753
+ get articles() {
754
+ if (!this._articles) {
755
+ this._articles = createArticles(this.client);
756
+ }
757
+ return this._articles;
758
+ }
759
+ /**
760
+ * Web namespace - Web search, scraping, and content extraction
761
+ *
762
+ * @example
763
+ * ```typescript
764
+ * // Search with Exa
765
+ * const results = await rainfall.web.search.exa({
766
+ * query: 'latest AI research'
767
+ * });
768
+ *
769
+ * // Fetch and convert
770
+ * const html = await rainfall.web.fetch({ url: 'https://example.com' });
771
+ * const markdown = await rainfall.web.htmlToMarkdown({ html });
772
+ *
773
+ * // Extract specific elements
774
+ * const links = await rainfall.web.extractHtml({
775
+ * html,
776
+ * selector: 'a[href]'
777
+ * });
778
+ * ```
779
+ */
780
+ get web() {
781
+ if (!this._web) {
782
+ this._web = createWeb(this.client);
783
+ }
784
+ return this._web;
785
+ }
786
+ /**
787
+ * AI namespace - Embeddings, image generation, OCR, vision, chat
788
+ *
789
+ * @example
790
+ * ```typescript
791
+ * // Generate embeddings
792
+ * const embedding = await rainfall.ai.embeddings.document({
793
+ * text: 'Hello world'
794
+ * });
795
+ *
796
+ * // Generate image
797
+ * const image = await rainfall.ai.image.generate({
798
+ * prompt: 'A serene mountain landscape'
799
+ * });
800
+ *
801
+ * // OCR
802
+ * const text = await rainfall.ai.ocr({ imageBase64: '...' });
803
+ *
804
+ * // Chat
805
+ * const response = await rainfall.ai.chat({
806
+ * messages: [{ role: 'user', content: 'Hello!' }]
807
+ * });
808
+ * ```
809
+ */
810
+ get ai() {
811
+ if (!this._ai) {
812
+ this._ai = createAI(this.client);
813
+ }
814
+ return this._ai;
815
+ }
816
+ /**
817
+ * Data namespace - CSV processing, scripts, similarity search
818
+ *
819
+ * @example
820
+ * ```typescript
821
+ * // Query CSV with SQL
822
+ * const results = await rainfall.data.csv.query({
823
+ * sql: 'SELECT * FROM data WHERE value > 100'
824
+ * });
825
+ *
826
+ * // Execute saved script
827
+ * const result = await rainfall.data.scripts.execute({
828
+ * name: 'my-script',
829
+ * params: { input: 'data' }
830
+ * });
831
+ * ```
832
+ */
833
+ get data() {
834
+ if (!this._data) {
835
+ this._data = createData(this.client);
836
+ }
837
+ return this._data;
838
+ }
839
+ /**
840
+ * Utils namespace - Mermaid diagrams, document conversion, regex, JSON extraction
841
+ *
842
+ * @example
843
+ * ```typescript
844
+ * // Generate diagram
845
+ * const diagram = await rainfall.utils.mermaid({
846
+ * diagram: 'graph TD; A-->B;'
847
+ * });
848
+ *
849
+ * // Convert document
850
+ * const pdf = await rainfall.utils.documentConvert({
851
+ * document: markdownContent,
852
+ * mimeType: 'text/markdown',
853
+ * format: 'pdf'
854
+ * });
855
+ *
856
+ * // Extract JSON from text
857
+ * const json = await rainfall.utils.jsonExtract({
858
+ * text: 'Here is some data: {"key": "value"}'
859
+ * });
860
+ * ```
861
+ */
862
+ get utils() {
863
+ if (!this._utils) {
864
+ this._utils = createUtils(this.client);
865
+ }
866
+ return this._utils;
867
+ }
868
+ /**
869
+ * Get the underlying HTTP client for advanced usage
870
+ */
871
+ getClient() {
872
+ return this.client;
873
+ }
874
+ /**
875
+ * List all available tools
876
+ */
877
+ async listTools() {
878
+ return this.client.listTools();
879
+ }
880
+ /**
881
+ * Get schema for a specific tool
882
+ */
883
+ async getToolSchema(toolId) {
884
+ return this.client.getToolSchema(toolId);
885
+ }
886
+ /**
887
+ * Execute any tool by ID (low-level access)
888
+ *
889
+ * @param toolId - The ID of the tool to execute
890
+ * @param params - Parameters to pass to the tool
891
+ * @param options - Execution options including skipValidation to bypass param validation
892
+ *
893
+ * @example
894
+ * ```typescript
895
+ * // Execute with validation (default)
896
+ * const result = await rainfall.executeTool('finviz-quotes', { tickers: ['AAPL'] });
897
+ *
898
+ * // Execute without validation
899
+ * const result = await rainfall.executeTool('finviz-quotes', { tickers: ['AAPL'] }, { skipValidation: true });
900
+ * ```
901
+ */
902
+ async executeTool(toolId, params, options) {
903
+ return this.client.executeTool(toolId, params, options);
904
+ }
905
+ /**
906
+ * Validate parameters for a tool without executing it
907
+ *
908
+ * @param toolId - The ID of the tool to validate params for
909
+ * @param params - Parameters to validate
910
+ * @returns Validation result with detailed error information
911
+ *
912
+ * @example
913
+ * ```typescript
914
+ * const result = await rainfall.validateToolParams('finviz-quotes', { tickers: ['AAPL'] });
915
+ * if (!result.valid) {
916
+ * console.log('Validation errors:', result.errors);
917
+ * }
918
+ * ```
919
+ */
920
+ async validateToolParams(toolId, params) {
921
+ return this.client.validateToolParams(toolId, params);
922
+ }
923
+ /**
924
+ * Get current subscriber info and usage
925
+ */
926
+ async getMe() {
927
+ return this.client.getMe();
928
+ }
929
+ /**
930
+ * Get current rate limit info
931
+ */
932
+ getRateLimitInfo() {
933
+ return this.client.getRateLimitInfo();
934
+ }
935
+ /**
936
+ * OpenAI-compatible chat completions with tool support
937
+ *
938
+ * @example
939
+ * ```typescript
940
+ * // Simple chat
941
+ * const response = await rainfall.chatCompletions({
942
+ * subscriber_id: 'my-subscriber',
943
+ * messages: [{ role: 'user', content: 'Hello!' }],
944
+ * model: 'llama-3.3-70b-versatile'
945
+ * });
946
+ *
947
+ * // With tools
948
+ * const response = await rainfall.chatCompletions({
949
+ * subscriber_id: 'my-subscriber',
950
+ * messages: [{ role: 'user', content: 'Search for AI news' }],
951
+ * tools: [{ type: 'function', function: { name: 'web-search' } }],
952
+ * enable_stacked: true
953
+ * });
954
+ *
955
+ * // Streaming
956
+ * const stream = await rainfall.chatCompletions({
957
+ * subscriber_id: 'my-subscriber',
958
+ * messages: [{ role: 'user', content: 'Tell me a story' }],
959
+ * stream: true
960
+ * });
961
+ * ```
962
+ */
963
+ async chatCompletions(params) {
964
+ return this.client.chatCompletions(params);
965
+ }
966
+ /**
967
+ * List available models (OpenAI-compatible format)
968
+ *
969
+ * @example
970
+ * ```typescript
971
+ * const models = await rainfall.listModels();
972
+ * console.log(models); // [{ id: 'llama-3.3-70b-versatile', ... }]
973
+ * ```
974
+ */
975
+ async listModels(subscriberId) {
976
+ return this.client.listModels(subscriberId);
977
+ }
978
+ };
979
+
980
+ export {
981
+ fetchToolSchema,
982
+ clearSchemaCache,
983
+ validateParams,
984
+ formatValidationErrors,
985
+ RainfallClient,
986
+ Rainfall
987
+ };