@rainfall-devkit/sdk 0.2.1 → 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.
package/dist/index.js CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,122 +30,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
+ // node_modules/tsup/assets/cjs_shims.js
34
+ var init_cjs_shims = __esm({
35
+ "node_modules/tsup/assets/cjs_shims.js"() {
36
+ "use strict";
37
+ }
38
+ });
39
+
40
+ // src/errors.ts
41
+ var errors_exports = {};
42
+ __export(errors_exports, {
33
43
  AuthenticationError: () => AuthenticationError,
34
- EdgeNodeSecurity: () => EdgeNodeSecurity,
35
44
  NetworkError: () => NetworkError,
36
45
  NotFoundError: () => NotFoundError,
37
- Rainfall: () => Rainfall,
38
- RainfallClient: () => RainfallClient,
39
- RainfallDaemonContext: () => RainfallDaemonContext,
40
46
  RainfallError: () => RainfallError,
41
- RainfallListenerRegistry: () => RainfallListenerRegistry,
42
- RainfallNetworkedExecutor: () => RainfallNetworkedExecutor,
43
47
  RateLimitError: () => RateLimitError,
44
- SecureEdgeClient: () => SecureEdgeClient,
45
48
  ServerError: () => ServerError,
46
49
  TimeoutError: () => TimeoutError,
47
50
  ToolNotFoundError: () => ToolNotFoundError,
48
- VERSION: () => VERSION,
49
51
  ValidationError: () => ValidationError,
50
- createCronWorkflow: () => createCronWorkflow,
51
- createEdgeNodeSecurity: () => createEdgeNodeSecurity,
52
- createFileWatcherWorkflow: () => createFileWatcherWorkflow,
53
- createSecureEdgeClient: () => createSecureEdgeClient
52
+ parseErrorResponse: () => parseErrorResponse
54
53
  });
55
- module.exports = __toCommonJS(index_exports);
56
-
57
- // src/errors.ts
58
- var RainfallError = class _RainfallError extends Error {
59
- constructor(message, code, statusCode, details) {
60
- super(message);
61
- this.code = code;
62
- this.statusCode = statusCode;
63
- this.details = details;
64
- this.name = "RainfallError";
65
- Object.setPrototypeOf(this, _RainfallError.prototype);
66
- }
67
- toJSON() {
68
- return {
69
- name: this.name,
70
- code: this.code,
71
- message: this.message,
72
- statusCode: this.statusCode,
73
- details: this.details
74
- };
75
- }
76
- };
77
- var AuthenticationError = class _AuthenticationError extends RainfallError {
78
- constructor(message = "Invalid API key", details) {
79
- super(message, "AUTHENTICATION_ERROR", 401, details);
80
- this.name = "AuthenticationError";
81
- Object.setPrototypeOf(this, _AuthenticationError.prototype);
82
- }
83
- };
84
- var RateLimitError = class _RateLimitError extends RainfallError {
85
- retryAfter;
86
- limit;
87
- remaining;
88
- resetAt;
89
- constructor(message = "Rate limit exceeded", retryAfter = 60, limit = 0, remaining = 0, resetAt) {
90
- super(message, "RATE_LIMIT_ERROR", 429, { retryAfter, limit, remaining });
91
- this.name = "RateLimitError";
92
- this.retryAfter = retryAfter;
93
- this.limit = limit;
94
- this.remaining = remaining;
95
- this.resetAt = resetAt || new Date(Date.now() + retryAfter * 1e3);
96
- Object.setPrototypeOf(this, _RateLimitError.prototype);
97
- }
98
- };
99
- var ValidationError = class _ValidationError extends RainfallError {
100
- constructor(message, details) {
101
- super(message, "VALIDATION_ERROR", 400, details);
102
- this.name = "ValidationError";
103
- Object.setPrototypeOf(this, _ValidationError.prototype);
104
- }
105
- };
106
- var NotFoundError = class _NotFoundError extends RainfallError {
107
- constructor(resource, identifier) {
108
- super(
109
- `${resource}${identifier ? ` '${identifier}'` : ""} not found`,
110
- "NOT_FOUND_ERROR",
111
- 404,
112
- { resource, identifier }
113
- );
114
- this.name = "NotFoundError";
115
- Object.setPrototypeOf(this, _NotFoundError.prototype);
116
- }
117
- };
118
- var ServerError = class _ServerError extends RainfallError {
119
- constructor(message = "Internal server error", statusCode = 500) {
120
- super(message, "SERVER_ERROR", statusCode);
121
- this.name = "ServerError";
122
- Object.setPrototypeOf(this, _ServerError.prototype);
123
- }
124
- };
125
- var TimeoutError = class _TimeoutError extends RainfallError {
126
- constructor(timeoutMs) {
127
- super(`Request timed out after ${timeoutMs}ms`, "TIMEOUT_ERROR", 408);
128
- this.name = "TimeoutError";
129
- Object.setPrototypeOf(this, _TimeoutError.prototype);
130
- }
131
- };
132
- var NetworkError = class _NetworkError extends RainfallError {
133
- constructor(message = "Network error", details) {
134
- super(message, "NETWORK_ERROR", void 0, details);
135
- this.name = "NetworkError";
136
- Object.setPrototypeOf(this, _NetworkError.prototype);
137
- }
138
- };
139
- var ToolNotFoundError = class _ToolNotFoundError extends RainfallError {
140
- constructor(toolId) {
141
- super(`Tool '${toolId}' not found`, "TOOL_NOT_FOUND", 404, { toolId });
142
- this.name = "ToolNotFoundError";
143
- Object.setPrototypeOf(this, _ToolNotFoundError.prototype);
144
- }
145
- };
146
54
  function parseErrorResponse(response, data) {
147
55
  const statusCode = response.status;
148
56
  if (statusCode === 429) {
@@ -191,6 +99,586 @@ function parseErrorResponse(response, data) {
191
99
  );
192
100
  }
193
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
+
198
+ // src/cli/core/display.ts
199
+ var display_exports = {};
200
+ __export(display_exports, {
201
+ detectImageData: () => detectImageData,
202
+ detectImageSupport: () => detectImageSupport,
203
+ displayImage: () => displayImage,
204
+ formatAsTable: () => formatAsTable,
205
+ formatResult: () => formatResult
206
+ });
207
+ function detectImageSupport() {
208
+ if (process.env.TERM_PROGRAM === "iTerm.app") {
209
+ return { supported: true, command: "imgcat" };
210
+ }
211
+ if (process.env.KITTY_WINDOW_ID) {
212
+ return { supported: true, command: "kitty +kitten icat" };
213
+ }
214
+ try {
215
+ return { supported: true, command: "xan" };
216
+ } catch {
217
+ }
218
+ try {
219
+ return { supported: true, command: "catimg" };
220
+ } catch {
221
+ }
222
+ return { supported: false };
223
+ }
224
+ async function displayImage(imageData, options = {}) {
225
+ const imageCommand = options.imageCommand || detectImageSupport().command;
226
+ if (!imageCommand) {
227
+ const { writeFileSync } = await import("fs");
228
+ const { tmpdir } = await import("os");
229
+ const { join: join2 } = await import("path");
230
+ const tempPath = join2(tmpdir(), `rainfall-image-${Date.now()}.png`);
231
+ const buffer = typeof imageData === "string" ? Buffer.from(imageData, "base64") : imageData;
232
+ writeFileSync(tempPath, buffer);
233
+ console.log(`Image saved to: ${tempPath}`);
234
+ return;
235
+ }
236
+ return new Promise((resolve, reject) => {
237
+ const buffer = typeof imageData === "string" ? Buffer.from(imageData, "base64") : imageData;
238
+ const child = (0, import_child_process.spawn)(imageCommand, [], {
239
+ stdio: ["pipe", "inherit", "inherit"],
240
+ shell: true
241
+ });
242
+ child.stdin.write(buffer);
243
+ child.stdin.end();
244
+ child.on("close", (code) => {
245
+ if (code === 0) {
246
+ resolve();
247
+ } else {
248
+ reject(new Error(`Image display failed with code ${code}`));
249
+ }
250
+ });
251
+ child.on("error", reject);
252
+ });
253
+ }
254
+ function formatAsTable(data, columns) {
255
+ if (!Array.isArray(data) || data.length === 0) {
256
+ return "No data";
257
+ }
258
+ const cols = columns || Object.keys(data[0]);
259
+ const widths = {};
260
+ for (const col of cols) {
261
+ widths[col] = Math.max(
262
+ col.length,
263
+ ...data.map((row) => {
264
+ const val = row?.[col];
265
+ return String(val ?? "").slice(0, 50).length;
266
+ })
267
+ );
268
+ }
269
+ const lines = [];
270
+ const header = cols.map((col) => col.padEnd(widths[col])).join(" ");
271
+ lines.push(header);
272
+ lines.push(cols.map((col) => "-".repeat(widths[col])).join(" "));
273
+ for (const row of data) {
274
+ const line = cols.map((col) => {
275
+ const val = row?.[col];
276
+ const str = String(val ?? "").slice(0, 50);
277
+ return str.padEnd(widths[col]);
278
+ }).join(" ");
279
+ lines.push(line);
280
+ }
281
+ return lines.join("\n");
282
+ }
283
+ async function formatResult(result, options = {}) {
284
+ const mode = options.mode || "pretty";
285
+ switch (mode) {
286
+ case "raw":
287
+ return JSON.stringify(result);
288
+ case "pretty":
289
+ return JSON.stringify(result, null, 2);
290
+ case "table":
291
+ if (Array.isArray(result)) {
292
+ return formatAsTable(result, options.columns);
293
+ }
294
+ return JSON.stringify(result, null, 2);
295
+ case "terminal":
296
+ if (typeof result === "string") {
297
+ return result;
298
+ }
299
+ if (Array.isArray(result) && result.every((r) => typeof r === "string")) {
300
+ return result.join("\n");
301
+ }
302
+ return JSON.stringify(result);
303
+ default:
304
+ return JSON.stringify(result, null, 2);
305
+ }
306
+ }
307
+ function detectImageData(result) {
308
+ if (!result || typeof result !== "object") {
309
+ return { hasImage: false };
310
+ }
311
+ const obj = result;
312
+ const imageFields = ["image", "imageData", "imageBase64", "png", "jpeg", "data"];
313
+ for (const field of imageFields) {
314
+ if (obj[field] && typeof obj[field] === "string") {
315
+ const value = obj[field];
316
+ if (value.startsWith("data:image/") || value.length > 100) {
317
+ return {
318
+ hasImage: true,
319
+ imageData: value.startsWith("data:image/") ? value.split(",")[1] : value
320
+ };
321
+ }
322
+ }
323
+ }
324
+ if (obj.url && typeof obj.url === "string" && (obj.url.endsWith(".png") || obj.url.endsWith(".jpg") || obj.url.endsWith(".jpeg"))) {
325
+ return { hasImage: true, imagePath: obj.url };
326
+ }
327
+ return { hasImage: false };
328
+ }
329
+ var import_child_process;
330
+ var init_display = __esm({
331
+ "src/cli/core/display.ts"() {
332
+ "use strict";
333
+ init_cjs_shims();
334
+ import_child_process = require("child_process");
335
+ }
336
+ });
337
+
338
+ // src/cli/core/param-parser.ts
339
+ var param_parser_exports = {};
340
+ __export(param_parser_exports, {
341
+ formatValueForDisplay: () => formatValueForDisplay,
342
+ generateParamExample: () => generateParamExample,
343
+ parseCliArgs: () => parseCliArgs,
344
+ parseValue: () => parseValue
345
+ });
346
+ function parseValue(value, schema, options = {}) {
347
+ const opts = { ...DEFAULT_OPTIONS, ...options };
348
+ if (!schema) {
349
+ try {
350
+ return JSON.parse(value);
351
+ } catch {
352
+ return value;
353
+ }
354
+ }
355
+ const expectedType = schema.type;
356
+ switch (expectedType) {
357
+ case "array":
358
+ return parseArrayValue(value, schema, opts);
359
+ case "number":
360
+ return parseNumberValue(value, opts);
361
+ case "boolean":
362
+ return parseBooleanValue(value, opts);
363
+ case "string":
364
+ return value;
365
+ case "object":
366
+ try {
367
+ return JSON.parse(value);
368
+ } catch {
369
+ return value;
370
+ }
371
+ default:
372
+ try {
373
+ return JSON.parse(value);
374
+ } catch {
375
+ return value;
376
+ }
377
+ }
378
+ }
379
+ function parseArrayValue(value, schema, options) {
380
+ if (value.startsWith("[") && value.endsWith("]")) {
381
+ try {
382
+ return JSON.parse(value);
383
+ } catch {
384
+ }
385
+ }
386
+ if (options.arrayInterpolation && value.includes(options.arraySeparator)) {
387
+ const items = value.split(options.arraySeparator).map((s) => s.trim()).filter(Boolean);
388
+ if (schema.items) {
389
+ return items.map((item) => parseValue(item, schema.items, { ...options, arrayInterpolation: false }));
390
+ }
391
+ return items;
392
+ }
393
+ if (schema.items) {
394
+ return [parseValue(value, schema.items, { ...options, arrayInterpolation: false })];
395
+ }
396
+ return [value];
397
+ }
398
+ function parseNumberValue(value, options) {
399
+ if (!options.numberParsing) {
400
+ return value;
401
+ }
402
+ const num = Number(value);
403
+ if (!isNaN(num) && isFinite(num)) {
404
+ return num;
405
+ }
406
+ return value;
407
+ }
408
+ function parseBooleanValue(value, options) {
409
+ if (!options.booleanParsing) {
410
+ return value;
411
+ }
412
+ const lower = value.toLowerCase();
413
+ if (lower === "true" || lower === "yes" || lower === "1" || lower === "on") {
414
+ return true;
415
+ }
416
+ if (lower === "false" || lower === "no" || lower === "0" || lower === "off") {
417
+ return false;
418
+ }
419
+ return value;
420
+ }
421
+ function parseCliArgs(args, schema, options = {}) {
422
+ const params = {};
423
+ const opts = { ...DEFAULT_OPTIONS, ...options };
424
+ const parameters = schema?.parameters || {};
425
+ for (let i = 0; i < args.length; i++) {
426
+ const arg = args[i];
427
+ if (arg.startsWith("--")) {
428
+ const key = arg.slice(2);
429
+ const value = args[++i];
430
+ if (value === void 0) {
431
+ params[key] = true;
432
+ continue;
433
+ }
434
+ const paramSchema = parameters[key];
435
+ params[key] = parseValue(value, paramSchema, opts);
436
+ }
437
+ }
438
+ return params;
439
+ }
440
+ function formatValueForDisplay(value) {
441
+ if (value === null) return "null";
442
+ if (value === void 0) return "undefined";
443
+ if (typeof value === "string") return value;
444
+ if (typeof value === "number") return String(value);
445
+ if (typeof value === "boolean") return String(value);
446
+ if (Array.isArray(value)) {
447
+ return value.map(formatValueForDisplay).join(",");
448
+ }
449
+ return JSON.stringify(value);
450
+ }
451
+ function generateParamExample(key, schema) {
452
+ const type = schema.type || "string";
453
+ switch (type) {
454
+ case "array":
455
+ if (schema.items?.type === "string") {
456
+ return `--${key} item1,item2,item3`;
457
+ }
458
+ return `--${key} '["item1", "item2"]'`;
459
+ case "number":
460
+ return `--${key} 42`;
461
+ case "boolean":
462
+ return `--${key} true`;
463
+ case "object":
464
+ return `--${key} '{"key": "value"}'`;
465
+ default:
466
+ return `--${key} "value"`;
467
+ }
468
+ }
469
+ var DEFAULT_OPTIONS;
470
+ var init_param_parser = __esm({
471
+ "src/cli/core/param-parser.ts"() {
472
+ "use strict";
473
+ init_cjs_shims();
474
+ DEFAULT_OPTIONS = {
475
+ arrayInterpolation: true,
476
+ numberParsing: true,
477
+ booleanParsing: true,
478
+ arraySeparator: ","
479
+ };
480
+ }
481
+ });
482
+
483
+ // src/index.ts
484
+ var index_exports = {};
485
+ __export(index_exports, {
486
+ AuthenticationError: () => AuthenticationError,
487
+ EdgeNodeSecurity: () => EdgeNodeSecurity,
488
+ NetworkError: () => NetworkError,
489
+ NotFoundError: () => NotFoundError,
490
+ Rainfall: () => Rainfall,
491
+ RainfallClient: () => RainfallClient,
492
+ RainfallDaemonContext: () => RainfallDaemonContext,
493
+ RainfallError: () => RainfallError,
494
+ RainfallListenerRegistry: () => RainfallListenerRegistry,
495
+ RainfallNetworkedExecutor: () => RainfallNetworkedExecutor,
496
+ RateLimitError: () => RateLimitError,
497
+ SecureEdgeClient: () => SecureEdgeClient,
498
+ ServerError: () => ServerError,
499
+ TimeoutError: () => TimeoutError,
500
+ ToolNotFoundError: () => ToolNotFoundError,
501
+ VERSION: () => VERSION,
502
+ ValidationError: () => ValidationError,
503
+ clearSchemaCache: () => clearSchemaCache,
504
+ createCronWorkflow: () => createCronWorkflow,
505
+ createEdgeNodeSecurity: () => createEdgeNodeSecurity,
506
+ createFileWatcherWorkflow: () => createFileWatcherWorkflow,
507
+ createSecureEdgeClient: () => createSecureEdgeClient,
508
+ fetchToolSchema: () => fetchToolSchema,
509
+ formatValidationErrors: () => formatValidationErrors,
510
+ globalHandlerRegistry: () => globalHandlerRegistry,
511
+ validateParams: () => validateParams
512
+ });
513
+ module.exports = __toCommonJS(index_exports);
514
+ init_cjs_shims();
515
+
516
+ // src/client.ts
517
+ init_cjs_shims();
518
+ init_errors();
519
+
520
+ // src/validation.ts
521
+ init_cjs_shims();
522
+ init_errors();
523
+ var schemaCache = /* @__PURE__ */ new Map();
524
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
525
+ async function fetchToolSchema(client, toolId) {
526
+ const cached = schemaCache.get(toolId);
527
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
528
+ return cached.schema;
529
+ }
530
+ const response = await client.request(
531
+ `/olympic/subscribers/me/nodes/${toolId}/params`
532
+ );
533
+ if (!response.success || !response.params) {
534
+ throw new ValidationError(`Failed to fetch schema for tool '${toolId}'`);
535
+ }
536
+ schemaCache.set(toolId, { schema: response.params, timestamp: Date.now() });
537
+ return response.params;
538
+ }
539
+ function clearSchemaCache() {
540
+ schemaCache.clear();
541
+ }
542
+ function validateParams(schema, params, toolId) {
543
+ const errors = [];
544
+ const parameters = schema.parameters || {};
545
+ for (const [key, paramSchema] of Object.entries(parameters)) {
546
+ if (paramSchema.optional !== true && !(key in (params || {}))) {
547
+ errors.push({
548
+ path: key,
549
+ message: `Missing required parameter '${key}'`,
550
+ expected: paramSchema.type
551
+ });
552
+ }
553
+ }
554
+ if (params) {
555
+ for (const [key, value] of Object.entries(params)) {
556
+ const paramSchema = parameters[key];
557
+ if (!paramSchema) {
558
+ errors.push({
559
+ path: key,
560
+ message: `Unknown parameter '${key}'`,
561
+ received: value
562
+ });
563
+ continue;
564
+ }
565
+ const typeError = validateType(key, value, paramSchema);
566
+ if (typeError) {
567
+ errors.push(typeError);
568
+ }
569
+ }
570
+ }
571
+ return {
572
+ valid: errors.length === 0,
573
+ errors
574
+ };
575
+ }
576
+ function validateType(path, value, schema) {
577
+ if (value === null || value === void 0) {
578
+ if (schema.optional === true) {
579
+ return null;
580
+ }
581
+ return {
582
+ path,
583
+ message: `Parameter '${path}' is required but received ${value}`,
584
+ received: value,
585
+ expected: schema.type
586
+ };
587
+ }
588
+ const expectedType = schema.type;
589
+ const actualType = getJsType(value);
590
+ switch (expectedType) {
591
+ case "string":
592
+ if (typeof value !== "string") {
593
+ return {
594
+ path,
595
+ message: `Parameter '${path}' must be a string, received ${actualType}`,
596
+ received: value,
597
+ expected: "string"
598
+ };
599
+ }
600
+ break;
601
+ case "number":
602
+ if (typeof value !== "number" || isNaN(value)) {
603
+ return {
604
+ path,
605
+ message: `Parameter '${path}' must be a number, received ${actualType}`,
606
+ received: value,
607
+ expected: "number"
608
+ };
609
+ }
610
+ break;
611
+ case "boolean":
612
+ if (typeof value !== "boolean") {
613
+ return {
614
+ path,
615
+ message: `Parameter '${path}' must be a boolean, received ${actualType}`,
616
+ received: value,
617
+ expected: "boolean"
618
+ };
619
+ }
620
+ break;
621
+ case "array":
622
+ if (!Array.isArray(value)) {
623
+ return {
624
+ path,
625
+ message: `Parameter '${path}' must be an array, received ${actualType}`,
626
+ received: value,
627
+ expected: "array"
628
+ };
629
+ }
630
+ if (schema.items) {
631
+ for (let i = 0; i < value.length; i++) {
632
+ const itemError = validateType(`${path}[${i}]`, value[i], schema.items);
633
+ if (itemError) {
634
+ return itemError;
635
+ }
636
+ }
637
+ }
638
+ break;
639
+ case "object":
640
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
641
+ return {
642
+ path,
643
+ message: `Parameter '${path}' must be an object, received ${actualType}`,
644
+ received: value,
645
+ expected: "object"
646
+ };
647
+ }
648
+ if (schema.properties) {
649
+ const objValue = value;
650
+ for (const [propKey, propSchema] of Object.entries(schema.properties)) {
651
+ if (objValue[propKey] !== void 0) {
652
+ const propError = validateType(`${path}.${propKey}`, objValue[propKey], propSchema);
653
+ if (propError) {
654
+ return propError;
655
+ }
656
+ }
657
+ }
658
+ }
659
+ break;
660
+ default:
661
+ break;
662
+ }
663
+ return null;
664
+ }
665
+ function getJsType(value) {
666
+ if (value === null) return "null";
667
+ if (Array.isArray(value)) return "array";
668
+ return typeof value;
669
+ }
670
+ function formatValidationErrors(result) {
671
+ if (result.valid) return "No validation errors";
672
+ const lines = result.errors.map((err) => {
673
+ let line = ` - ${err.message}`;
674
+ if (err.received !== void 0) {
675
+ line += ` (received: ${JSON.stringify(err.received).slice(0, 50)})`;
676
+ }
677
+ return line;
678
+ });
679
+ return `Validation failed with ${result.errors.length} error(s):
680
+ ${lines.join("\n")}`;
681
+ }
194
682
 
195
683
  // src/client.ts
196
684
  var DEFAULT_BASE_URL = "https://olympic-api.pragma-digital.org/v1";
@@ -203,6 +691,7 @@ var RainfallClient = class {
203
691
  defaultTimeout;
204
692
  defaultRetries;
205
693
  defaultRetryDelay;
694
+ disableValidation;
206
695
  lastRateLimitInfo;
207
696
  subscriberId;
208
697
  constructor(config) {
@@ -211,6 +700,7 @@ var RainfallClient = class {
211
700
  this.defaultTimeout = config.timeout || DEFAULT_TIMEOUT;
212
701
  this.defaultRetries = config.retries ?? DEFAULT_RETRIES;
213
702
  this.defaultRetryDelay = config.retryDelay || DEFAULT_RETRY_DELAY;
703
+ this.disableValidation = config.disableValidation ?? false;
214
704
  }
215
705
  /**
216
706
  * Get the last rate limit info from the API
@@ -293,15 +783,68 @@ var RainfallClient = class {
293
783
  }
294
784
  /**
295
785
  * Execute a tool/node by ID
786
+ *
787
+ * @param toolId - The ID of the tool/node to execute
788
+ * @param params - Parameters to pass to the tool
789
+ * @param options - Request options including skipValidation to bypass param validation
296
790
  */
297
791
  async executeTool(toolId, params, options) {
792
+ if (!this.disableValidation && !options?.skipValidation) {
793
+ const validation = await this.validateToolParams(toolId, params);
794
+ if (!validation.valid) {
795
+ const { ValidationError: ValidationError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
796
+ throw new ValidationError2(
797
+ `Parameter validation failed for tool '${toolId}': ${formatValidationErrors(validation)}`,
798
+ { toolId, errors: validation.errors }
799
+ );
800
+ }
801
+ }
298
802
  const subscriberId = await this.ensureSubscriberId();
299
803
  const response = await this.request(`/olympic/subscribers/${subscriberId}/nodes/${toolId}`, {
300
804
  method: "POST",
301
805
  body: params || {}
302
806
  }, options);
807
+ if (response.success === false) {
808
+ const errorMessage = typeof response.error === "string" ? response.error : JSON.stringify(response.error);
809
+ throw new RainfallError(
810
+ `Tool execution failed: ${errorMessage}`,
811
+ "TOOL_EXECUTION_ERROR",
812
+ 400,
813
+ { toolId, error: response.error }
814
+ );
815
+ }
303
816
  return response.result;
304
817
  }
818
+ /**
819
+ * Validate parameters for a tool without executing it
820
+ * Fetches the tool schema and validates the provided params
821
+ *
822
+ * @param toolId - The ID of the tool to validate params for
823
+ * @param params - Parameters to validate
824
+ * @returns Validation result with detailed error information
825
+ *
826
+ * @example
827
+ * ```typescript
828
+ * const result = await client.validateToolParams('finviz-quotes', { tickers: ['AAPL'] });
829
+ * if (!result.valid) {
830
+ * console.log('Validation errors:', result.errors);
831
+ * }
832
+ * ```
833
+ */
834
+ async validateToolParams(toolId, params) {
835
+ try {
836
+ const schema = await fetchToolSchema(this, toolId);
837
+ return validateParams(schema, params, toolId);
838
+ } catch (error) {
839
+ if (error instanceof RainfallError && error.statusCode === 404) {
840
+ return {
841
+ valid: false,
842
+ errors: [{ path: toolId, message: `Tool '${toolId}' not found` }]
843
+ };
844
+ }
845
+ return { valid: true, errors: [] };
846
+ }
847
+ }
305
848
  /**
306
849
  * List all available tools
307
850
  */
@@ -324,11 +867,20 @@ var RainfallClient = class {
324
867
  }
325
868
  /**
326
869
  * Get tool schema/parameters
870
+ *
871
+ * @param toolId - The ID of the tool to get schema for
872
+ * @returns Tool schema including parameters and output definitions
327
873
  */
328
874
  async getToolSchema(toolId) {
329
- const subscriberId = await this.ensureSubscriberId();
330
- const response = await this.request(`/olympic/subscribers/${subscriberId}/nodes/${toolId}/params`);
331
- return response.params;
875
+ const schema = await fetchToolSchema(this, toolId);
876
+ return {
877
+ name: schema.name,
878
+ description: schema.description,
879
+ category: schema.category,
880
+ parameters: schema.parameters,
881
+ output: schema.output,
882
+ metadata: schema.metadata || {}
883
+ };
332
884
  }
333
885
  /**
334
886
  * Get subscriber info
@@ -412,7 +964,11 @@ var RainfallClient = class {
412
964
  }
413
965
  };
414
966
 
967
+ // src/sdk.ts
968
+ init_cjs_shims();
969
+
415
970
  // src/namespaces/integrations.ts
971
+ init_cjs_shims();
416
972
  function createIntegrations(client) {
417
973
  return new IntegrationsNamespace(client);
418
974
  }
@@ -525,6 +1081,7 @@ var IntegrationsNamespace = class {
525
1081
  };
526
1082
 
527
1083
  // src/namespaces/memory.ts
1084
+ init_cjs_shims();
528
1085
  function createMemory(client) {
529
1086
  return {
530
1087
  create: (params) => client.executeTool("memory-create", params),
@@ -537,6 +1094,7 @@ function createMemory(client) {
537
1094
  }
538
1095
 
539
1096
  // src/namespaces/articles.ts
1097
+ init_cjs_shims();
540
1098
  function createArticles(client) {
541
1099
  return {
542
1100
  search: (params) => client.executeTool("article-search", params),
@@ -551,6 +1109,7 @@ function createArticles(client) {
551
1109
  }
552
1110
 
553
1111
  // src/namespaces/web.ts
1112
+ init_cjs_shims();
554
1113
  function createWeb(client) {
555
1114
  return {
556
1115
  search: {
@@ -564,6 +1123,7 @@ function createWeb(client) {
564
1123
  }
565
1124
 
566
1125
  // src/namespaces/ai.ts
1126
+ init_cjs_shims();
567
1127
  function createAI(client) {
568
1128
  return {
569
1129
  embeddings: {
@@ -589,6 +1149,7 @@ function createAI(client) {
589
1149
  }
590
1150
 
591
1151
  // src/namespaces/data.ts
1152
+ init_cjs_shims();
592
1153
  function createData(client) {
593
1154
  return {
594
1155
  csv: {
@@ -610,6 +1171,7 @@ function createData(client) {
610
1171
  }
611
1172
 
612
1173
  // src/namespaces/utils.ts
1174
+ init_cjs_shims();
613
1175
  function createUtils(client) {
614
1176
  return {
615
1177
  mermaid: (params) => client.executeTool("mermaid-diagram-generator", { mermaid: params.diagram }),
@@ -848,9 +1410,40 @@ var Rainfall = class {
848
1410
  }
849
1411
  /**
850
1412
  * Execute any tool by ID (low-level access)
1413
+ *
1414
+ * @param toolId - The ID of the tool to execute
1415
+ * @param params - Parameters to pass to the tool
1416
+ * @param options - Execution options including skipValidation to bypass param validation
1417
+ *
1418
+ * @example
1419
+ * ```typescript
1420
+ * // Execute with validation (default)
1421
+ * const result = await rainfall.executeTool('finviz-quotes', { tickers: ['AAPL'] });
1422
+ *
1423
+ * // Execute without validation
1424
+ * const result = await rainfall.executeTool('finviz-quotes', { tickers: ['AAPL'] }, { skipValidation: true });
1425
+ * ```
851
1426
  */
852
- async executeTool(toolId, params) {
853
- return this.client.executeTool(toolId, params);
1427
+ async executeTool(toolId, params, options) {
1428
+ return this.client.executeTool(toolId, params, options);
1429
+ }
1430
+ /**
1431
+ * Validate parameters for a tool without executing it
1432
+ *
1433
+ * @param toolId - The ID of the tool to validate params for
1434
+ * @param params - Parameters to validate
1435
+ * @returns Validation result with detailed error information
1436
+ *
1437
+ * @example
1438
+ * ```typescript
1439
+ * const result = await rainfall.validateToolParams('finviz-quotes', { tickers: ['AAPL'] });
1440
+ * if (!result.valid) {
1441
+ * console.log('Validation errors:', result.errors);
1442
+ * }
1443
+ * ```
1444
+ */
1445
+ async validateToolParams(toolId, params) {
1446
+ return this.client.validateToolParams(toolId, params);
854
1447
  }
855
1448
  /**
856
1449
  * Get current subscriber info and usage
@@ -909,7 +1502,11 @@ var Rainfall = class {
909
1502
  }
910
1503
  };
911
1504
 
1505
+ // src/index.ts
1506
+ init_errors();
1507
+
912
1508
  // src/services/networked.ts
1509
+ init_cjs_shims();
913
1510
  var RainfallNetworkedExecutor = class {
914
1511
  rainfall;
915
1512
  options;
@@ -1101,6 +1698,7 @@ var RainfallNetworkedExecutor = class {
1101
1698
  };
1102
1699
 
1103
1700
  // src/services/context.ts
1701
+ init_cjs_shims();
1104
1702
  var RainfallDaemonContext = class {
1105
1703
  rainfall;
1106
1704
  options;
@@ -1354,6 +1952,7 @@ var RainfallDaemonContext = class {
1354
1952
  };
1355
1953
 
1356
1954
  // src/services/listeners.ts
1955
+ init_cjs_shims();
1357
1956
  var RainfallListenerRegistry = class {
1358
1957
  rainfall;
1359
1958
  context;
@@ -1564,14 +2163,18 @@ function createCronWorkflow(name, cron, workflow) {
1564
2163
  };
1565
2164
  }
1566
2165
 
2166
+ // src/security/index.ts
2167
+ init_cjs_shims();
2168
+
1567
2169
  // src/security/edge-node.ts
1568
- var sodium = __toESM(require("libsodium-wrappers"));
2170
+ init_cjs_shims();
2171
+ var import_libsodium_wrappers_sumo = __toESM(require("libsodium-wrappers-sumo"));
1569
2172
  var EdgeNodeSecurity = class {
1570
2173
  sodiumReady;
1571
2174
  backendSecret;
1572
2175
  keyPair;
1573
2176
  constructor(options = {}) {
1574
- this.sodiumReady = sodium.ready;
2177
+ this.sodiumReady = import_libsodium_wrappers_sumo.default.ready;
1575
2178
  this.backendSecret = options.backendSecret;
1576
2179
  this.keyPair = options.keyPair;
1577
2180
  }
@@ -1701,7 +2304,7 @@ var EdgeNodeSecurity = class {
1701
2304
  */
1702
2305
  async generateKeyPair() {
1703
2306
  await this.sodiumReady;
1704
- const keyPair = sodium.crypto_box_keypair();
2307
+ const keyPair = import_libsodium_wrappers_sumo.default.crypto_box_keypair();
1705
2308
  return {
1706
2309
  publicKey: this.bytesToBase64(keyPair.publicKey),
1707
2310
  privateKey: this.bytesToBase64(keyPair.privateKey)
@@ -1716,10 +2319,10 @@ var EdgeNodeSecurity = class {
1716
2319
  throw new Error("Local key pair not configured");
1717
2320
  }
1718
2321
  const targetPublicKey = this.base64ToBytes(targetPublicKeyBase64);
1719
- const ephemeralKeyPair = sodium.crypto_box_keypair();
1720
- const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);
2322
+ const ephemeralKeyPair = import_libsodium_wrappers_sumo.default.crypto_box_keypair();
2323
+ const nonce = import_libsodium_wrappers_sumo.default.randombytes_buf(import_libsodium_wrappers_sumo.default.crypto_box_NONCEBYTES);
1721
2324
  const message = new TextEncoder().encode(plaintext);
1722
- const ciphertext = sodium.crypto_box_easy(
2325
+ const ciphertext = import_libsodium_wrappers_sumo.default.crypto_box_easy(
1723
2326
  message,
1724
2327
  nonce,
1725
2328
  targetPublicKey,
@@ -1743,7 +2346,7 @@ var EdgeNodeSecurity = class {
1743
2346
  const ephemeralPublicKey = this.base64ToBytes(encrypted.ephemeralPublicKey);
1744
2347
  const nonce = this.base64ToBytes(encrypted.nonce);
1745
2348
  const ciphertext = this.base64ToBytes(encrypted.ciphertext);
1746
- const decrypted = sodium.crypto_box_open_easy(
2349
+ const decrypted = import_libsodium_wrappers_sumo.default.crypto_box_open_easy(
1747
2350
  ciphertext,
1748
2351
  nonce,
1749
2352
  ephemeralPublicKey,
@@ -1760,9 +2363,9 @@ var EdgeNodeSecurity = class {
1760
2363
  async encryptLocal(plaintext, key) {
1761
2364
  await this.sodiumReady;
1762
2365
  const keyBytes = this.deriveKey(key);
1763
- const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
2366
+ const nonce = import_libsodium_wrappers_sumo.default.randombytes_buf(import_libsodium_wrappers_sumo.default.crypto_secretbox_NONCEBYTES);
1764
2367
  const message = new TextEncoder().encode(plaintext);
1765
- const ciphertext = sodium.crypto_secretbox_easy(message, nonce, keyBytes);
2368
+ const ciphertext = import_libsodium_wrappers_sumo.default.crypto_secretbox_easy(message, nonce, keyBytes);
1766
2369
  return {
1767
2370
  ciphertext: this.bytesToBase64(ciphertext),
1768
2371
  nonce: this.bytesToBase64(nonce)
@@ -1776,7 +2379,7 @@ var EdgeNodeSecurity = class {
1776
2379
  const keyBytes = this.deriveKey(key);
1777
2380
  const nonce = this.base64ToBytes(encrypted.nonce);
1778
2381
  const ciphertext = this.base64ToBytes(encrypted.ciphertext);
1779
- const decrypted = sodium.crypto_secretbox_open_easy(ciphertext, nonce, keyBytes);
2382
+ const decrypted = import_libsodium_wrappers_sumo.default.crypto_secretbox_open_easy(ciphertext, nonce, keyBytes);
1780
2383
  if (!decrypted) {
1781
2384
  throw new Error("Local decryption failed");
1782
2385
  }
@@ -1799,7 +2402,7 @@ var EdgeNodeSecurity = class {
1799
2402
  hmacSha256(message, secret) {
1800
2403
  const key = new TextEncoder().encode(secret);
1801
2404
  const msg = new TextEncoder().encode(message);
1802
- const hash = sodium.crypto_auth(msg, key);
2405
+ const hash = import_libsodium_wrappers_sumo.default.crypto_auth(msg, key);
1803
2406
  return this.bytesToBase64(hash);
1804
2407
  }
1805
2408
  timingSafeEqual(a, b) {
@@ -1820,7 +2423,7 @@ var EdgeNodeSecurity = class {
1820
2423
  }
1821
2424
  deriveKey(password) {
1822
2425
  const passwordBytes = new TextEncoder().encode(password);
1823
- return sodium.crypto_generichash(32, passwordBytes, null);
2426
+ return import_libsodium_wrappers_sumo.default.crypto_generichash(32, passwordBytes, null);
1824
2427
  }
1825
2428
  };
1826
2429
  async function createEdgeNodeSecurity(options = {}) {
@@ -1830,6 +2433,7 @@ async function createEdgeNodeSecurity(options = {}) {
1830
2433
  }
1831
2434
 
1832
2435
  // src/security/edge-client.ts
2436
+ init_cjs_shims();
1833
2437
  var import_fs = require("fs");
1834
2438
  var import_path = require("path");
1835
2439
  var SecureEdgeClient = class {
@@ -2034,6 +2638,176 @@ async function createSecureEdgeClient(client, options) {
2034
2638
  return secureClient;
2035
2639
  }
2036
2640
 
2641
+ // src/cli/handlers/_registry.ts
2642
+ init_cjs_shims();
2643
+
2644
+ // src/cli/core/types.ts
2645
+ init_cjs_shims();
2646
+ var ToolHandlerRegistry = class {
2647
+ handlers = [];
2648
+ register(handler) {
2649
+ this.handlers.push(handler);
2650
+ }
2651
+ findHandler(toolId) {
2652
+ return this.handlers.find((h) => {
2653
+ if (typeof h.toolId === "string") {
2654
+ return h.toolId === toolId;
2655
+ }
2656
+ return h.toolId.test(toolId);
2657
+ });
2658
+ }
2659
+ getAllHandlers() {
2660
+ return [...this.handlers];
2661
+ }
2662
+ };
2663
+ var globalHandlerRegistry = new ToolHandlerRegistry();
2664
+
2665
+ // src/cli/handlers/_registry.ts
2666
+ var imageGenerationHandler = {
2667
+ toolId: /image-generation|generate-image/,
2668
+ async display(context) {
2669
+ const { detectImageData: detectImageData2, displayImage: displayImage2 } = await Promise.resolve().then(() => (init_display(), display_exports));
2670
+ const { result, flags } = context;
2671
+ const imageInfo = detectImageData2(result);
2672
+ if (imageInfo.hasImage && !flags.raw) {
2673
+ try {
2674
+ if (imageInfo.imageData) {
2675
+ await displayImage2(imageInfo.imageData);
2676
+ return true;
2677
+ }
2678
+ } catch (error) {
2679
+ console.warn("Failed to display image:", error instanceof Error ? error.message : error);
2680
+ }
2681
+ }
2682
+ return false;
2683
+ }
2684
+ };
2685
+ var finvizQuotesHandler = {
2686
+ toolId: "finviz-quotes",
2687
+ async preflight(context) {
2688
+ const { parseValue: parseValue2 } = await Promise.resolve().then(() => (init_param_parser(), param_parser_exports));
2689
+ const params = { ...context.params };
2690
+ if (params.tickers && typeof params.tickers === "string") {
2691
+ params.tickers = parseValue2(params.tickers, { type: "array", items: { type: "string" } });
2692
+ }
2693
+ return { params };
2694
+ },
2695
+ async display(context) {
2696
+ const { result, flags } = context;
2697
+ if (flags.raw) {
2698
+ return false;
2699
+ }
2700
+ const obj = result;
2701
+ const quotes = obj?.quotes;
2702
+ if (Array.isArray(quotes) && quotes.length > 0) {
2703
+ const { formatAsTable: formatAsTable2 } = await Promise.resolve().then(() => (init_display(), display_exports));
2704
+ const tableData = quotes.map((q) => {
2705
+ const quote = q;
2706
+ const data = quote.data || {};
2707
+ return {
2708
+ Ticker: quote.ticker || data.Ticker || "-",
2709
+ Price: data.Price || data.Close || "-",
2710
+ Change: data.Change || "-",
2711
+ Volume: data.Volume || "-",
2712
+ "Market Cap": data.MarketCap || "-"
2713
+ };
2714
+ });
2715
+ console.log(formatAsTable2(tableData));
2716
+ const summary = obj?.summary;
2717
+ if (summary && typeof summary === "string") {
2718
+ console.log(`
2719
+ ${summary}`);
2720
+ }
2721
+ return true;
2722
+ }
2723
+ return false;
2724
+ }
2725
+ };
2726
+ var csvQueryHandler = {
2727
+ toolId: /query-csv|csv-query/,
2728
+ async display(context) {
2729
+ const { result, flags } = context;
2730
+ if (flags.raw) {
2731
+ return false;
2732
+ }
2733
+ if (Array.isArray(result) && result.length > 0) {
2734
+ const { formatAsTable: formatAsTable2 } = await Promise.resolve().then(() => (init_display(), display_exports));
2735
+ console.log(formatAsTable2(result));
2736
+ return true;
2737
+ }
2738
+ return false;
2739
+ }
2740
+ };
2741
+ var webSearchHandler = {
2742
+ toolId: /web-search|exa-web-search|perplexity/,
2743
+ async display(context) {
2744
+ const { result, flags } = context;
2745
+ if (flags.raw) {
2746
+ return false;
2747
+ }
2748
+ const obj = result;
2749
+ if (obj.results && typeof obj.results === "string") {
2750
+ console.log(obj.results);
2751
+ return true;
2752
+ }
2753
+ if (obj.answer || obj.summary) {
2754
+ console.log(obj.answer || obj.summary);
2755
+ if (obj.sources && Array.isArray(obj.sources)) {
2756
+ console.log("\n--- Sources ---");
2757
+ obj.sources.forEach((source, i) => {
2758
+ if (typeof source === "string") {
2759
+ console.log(` ${i + 1}. ${source}`);
2760
+ } else if (source && typeof source === "object") {
2761
+ const s = source;
2762
+ console.log(` ${i + 1}. ${s.title || s.url || JSON.stringify(source)}`);
2763
+ }
2764
+ });
2765
+ }
2766
+ return true;
2767
+ }
2768
+ return false;
2769
+ }
2770
+ };
2771
+ var memoryRecallHandler = {
2772
+ toolId: /memory-recall|recall/,
2773
+ async display(context) {
2774
+ const { result, flags } = context;
2775
+ if (flags.raw) {
2776
+ return false;
2777
+ }
2778
+ if (Array.isArray(result)) {
2779
+ if (result.length === 0) {
2780
+ console.log("No memories found.");
2781
+ return true;
2782
+ }
2783
+ console.log(`Found ${result.length} memory(s):
2784
+ `);
2785
+ result.forEach((mem, i) => {
2786
+ const memory = mem;
2787
+ console.log(`\u2500`.repeat(60));
2788
+ console.log(` ${i + 1}. ${memory.content || memory.text || JSON.stringify(memory).slice(0, 100)}`);
2789
+ if (memory.similarity) {
2790
+ console.log(` Similarity: ${(Number(memory.similarity) * 100).toFixed(1)}%`);
2791
+ }
2792
+ if (memory.keywords && Array.isArray(memory.keywords)) {
2793
+ console.log(` Keywords: ${memory.keywords.join(", ")}`);
2794
+ }
2795
+ console.log();
2796
+ });
2797
+ return true;
2798
+ }
2799
+ return false;
2800
+ }
2801
+ };
2802
+ function registerBuiltInHandlers(registry = globalHandlerRegistry) {
2803
+ registry.register(imageGenerationHandler);
2804
+ registry.register(finvizQuotesHandler);
2805
+ registry.register(csvQueryHandler);
2806
+ registry.register(webSearchHandler);
2807
+ registry.register(memoryRecallHandler);
2808
+ }
2809
+ registerBuiltInHandlers();
2810
+
2037
2811
  // src/index.ts
2038
2812
  var VERSION = "0.1.0";
2039
2813
  // Annotate the CommonJS export names for ESM import in node:
@@ -2055,8 +2829,13 @@ var VERSION = "0.1.0";
2055
2829
  ToolNotFoundError,
2056
2830
  VERSION,
2057
2831
  ValidationError,
2832
+ clearSchemaCache,
2058
2833
  createCronWorkflow,
2059
2834
  createEdgeNodeSecurity,
2060
2835
  createFileWatcherWorkflow,
2061
- createSecureEdgeClient
2836
+ createSecureEdgeClient,
2837
+ fetchToolSchema,
2838
+ formatValidationErrors,
2839
+ globalHandlerRegistry,
2840
+ validateParams
2062
2841
  });