@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/chunk-6FXRLPLR.mjs +436 -0
- package/dist/chunk-CC4O7GSQ.mjs +978 -0
- package/dist/chunk-CQ5TV7CQ.mjs +989 -0
- package/dist/chunk-GPKQUVAV.mjs +987 -0
- package/dist/chunk-KOCCGNEQ.mjs +269 -0
- package/dist/chunk-LJQEO3CY.mjs +150 -0
- package/dist/chunk-NCQVOLS4.mjs +269 -0
- package/dist/chunk-S7MOQCV4.mjs +137 -0
- package/dist/chunk-XHPFY5MH.mjs +132 -0
- package/dist/cli/index.js +1009 -54
- package/dist/cli/index.mjs +244 -24
- package/dist/daemon/index.d.mts +3 -3
- package/dist/daemon/index.d.ts +3 -3
- package/dist/daemon/index.js +411 -129
- package/dist/daemon/index.mjs +2 -1
- package/dist/display-KKJPO6UA.mjs +14 -0
- package/dist/errors-CY6HW2I5.mjs +24 -0
- package/dist/index.d.mts +66 -4
- package/dist/index.d.ts +66 -4
- package/dist/index.js +903 -124
- package/dist/index.mjs +18 -6
- package/dist/listeners-BBNBsJCk.d.ts +372 -0
- package/dist/listeners-CMUKjEkb.d.mts +372 -0
- package/dist/listeners-CadPNUHd.d.ts +372 -0
- package/dist/listeners-Ckdj6D8T.d.mts +372 -0
- package/dist/mcp.d.mts +2 -2
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +405 -101
- package/dist/mcp.mjs +4 -2
- package/dist/param-parser-JVKB5FQK.mjs +12 -0
- package/dist/param-parser-PAKCNDBX.mjs +136 -0
- package/dist/sdk-Cl5Qzt4I.d.mts +1165 -0
- package/dist/sdk-Cl5Qzt4I.d.ts +1165 -0
- package/dist/sdk-DQKNbBce.d.mts +1162 -0
- package/dist/sdk-DQKNbBce.d.ts +1162 -0
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -41,6 +41,19 @@ var init_cjs_shims = __esm({
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
// src/errors.ts
|
|
44
|
+
var errors_exports = {};
|
|
45
|
+
__export(errors_exports, {
|
|
46
|
+
AuthenticationError: () => AuthenticationError,
|
|
47
|
+
NetworkError: () => NetworkError,
|
|
48
|
+
NotFoundError: () => NotFoundError,
|
|
49
|
+
RainfallError: () => RainfallError,
|
|
50
|
+
RateLimitError: () => RateLimitError,
|
|
51
|
+
ServerError: () => ServerError,
|
|
52
|
+
TimeoutError: () => TimeoutError,
|
|
53
|
+
ToolNotFoundError: () => ToolNotFoundError,
|
|
54
|
+
ValidationError: () => ValidationError,
|
|
55
|
+
parseErrorResponse: () => parseErrorResponse
|
|
56
|
+
});
|
|
44
57
|
function parseErrorResponse(response, data) {
|
|
45
58
|
const statusCode = response.status;
|
|
46
59
|
if (statusCode === 429) {
|
|
@@ -89,7 +102,7 @@ function parseErrorResponse(response, data) {
|
|
|
89
102
|
);
|
|
90
103
|
}
|
|
91
104
|
}
|
|
92
|
-
var RainfallError, AuthenticationError, RateLimitError, ValidationError, NotFoundError, ServerError, TimeoutError, NetworkError;
|
|
105
|
+
var RainfallError, AuthenticationError, RateLimitError, ValidationError, NotFoundError, ServerError, TimeoutError, NetworkError, ToolNotFoundError;
|
|
93
106
|
var init_errors = __esm({
|
|
94
107
|
"src/errors.ts"() {
|
|
95
108
|
"use strict";
|
|
@@ -175,6 +188,179 @@ var init_errors = __esm({
|
|
|
175
188
|
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
176
189
|
}
|
|
177
190
|
};
|
|
191
|
+
ToolNotFoundError = class _ToolNotFoundError extends RainfallError {
|
|
192
|
+
constructor(toolId) {
|
|
193
|
+
super(`Tool '${toolId}' not found`, "TOOL_NOT_FOUND", 404, { toolId });
|
|
194
|
+
this.name = "ToolNotFoundError";
|
|
195
|
+
Object.setPrototypeOf(this, _ToolNotFoundError.prototype);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// src/validation.ts
|
|
202
|
+
async function fetchToolSchema(client, toolId) {
|
|
203
|
+
const cached = schemaCache.get(toolId);
|
|
204
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
205
|
+
return cached.schema;
|
|
206
|
+
}
|
|
207
|
+
const response = await client.request(
|
|
208
|
+
`/olympic/subscribers/me/nodes/${toolId}/params`
|
|
209
|
+
);
|
|
210
|
+
if (!response.success || !response.params) {
|
|
211
|
+
throw new ValidationError(`Failed to fetch schema for tool '${toolId}'`);
|
|
212
|
+
}
|
|
213
|
+
schemaCache.set(toolId, { schema: response.params, timestamp: Date.now() });
|
|
214
|
+
return response.params;
|
|
215
|
+
}
|
|
216
|
+
function validateParams(schema, params, toolId) {
|
|
217
|
+
const errors = [];
|
|
218
|
+
const parameters = schema.parameters || {};
|
|
219
|
+
for (const [key, paramSchema] of Object.entries(parameters)) {
|
|
220
|
+
if (paramSchema.optional !== true && !(key in (params || {}))) {
|
|
221
|
+
errors.push({
|
|
222
|
+
path: key,
|
|
223
|
+
message: `Missing required parameter '${key}'`,
|
|
224
|
+
expected: paramSchema.type
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (params) {
|
|
229
|
+
for (const [key, value] of Object.entries(params)) {
|
|
230
|
+
const paramSchema = parameters[key];
|
|
231
|
+
if (!paramSchema) {
|
|
232
|
+
errors.push({
|
|
233
|
+
path: key,
|
|
234
|
+
message: `Unknown parameter '${key}'`,
|
|
235
|
+
received: value
|
|
236
|
+
});
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const typeError = validateType(key, value, paramSchema);
|
|
240
|
+
if (typeError) {
|
|
241
|
+
errors.push(typeError);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
valid: errors.length === 0,
|
|
247
|
+
errors
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function validateType(path, value, schema) {
|
|
251
|
+
if (value === null || value === void 0) {
|
|
252
|
+
if (schema.optional === true) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
path,
|
|
257
|
+
message: `Parameter '${path}' is required but received ${value}`,
|
|
258
|
+
received: value,
|
|
259
|
+
expected: schema.type
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
const expectedType = schema.type;
|
|
263
|
+
const actualType = getJsType(value);
|
|
264
|
+
switch (expectedType) {
|
|
265
|
+
case "string":
|
|
266
|
+
if (typeof value !== "string") {
|
|
267
|
+
return {
|
|
268
|
+
path,
|
|
269
|
+
message: `Parameter '${path}' must be a string, received ${actualType}`,
|
|
270
|
+
received: value,
|
|
271
|
+
expected: "string"
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
break;
|
|
275
|
+
case "number":
|
|
276
|
+
if (typeof value !== "number" || isNaN(value)) {
|
|
277
|
+
return {
|
|
278
|
+
path,
|
|
279
|
+
message: `Parameter '${path}' must be a number, received ${actualType}`,
|
|
280
|
+
received: value,
|
|
281
|
+
expected: "number"
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
break;
|
|
285
|
+
case "boolean":
|
|
286
|
+
if (typeof value !== "boolean") {
|
|
287
|
+
return {
|
|
288
|
+
path,
|
|
289
|
+
message: `Parameter '${path}' must be a boolean, received ${actualType}`,
|
|
290
|
+
received: value,
|
|
291
|
+
expected: "boolean"
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
break;
|
|
295
|
+
case "array":
|
|
296
|
+
if (!Array.isArray(value)) {
|
|
297
|
+
return {
|
|
298
|
+
path,
|
|
299
|
+
message: `Parameter '${path}' must be an array, received ${actualType}`,
|
|
300
|
+
received: value,
|
|
301
|
+
expected: "array"
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
if (schema.items) {
|
|
305
|
+
for (let i = 0; i < value.length; i++) {
|
|
306
|
+
const itemError = validateType(`${path}[${i}]`, value[i], schema.items);
|
|
307
|
+
if (itemError) {
|
|
308
|
+
return itemError;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
break;
|
|
313
|
+
case "object":
|
|
314
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
315
|
+
return {
|
|
316
|
+
path,
|
|
317
|
+
message: `Parameter '${path}' must be an object, received ${actualType}`,
|
|
318
|
+
received: value,
|
|
319
|
+
expected: "object"
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
if (schema.properties) {
|
|
323
|
+
const objValue = value;
|
|
324
|
+
for (const [propKey, propSchema] of Object.entries(schema.properties)) {
|
|
325
|
+
if (objValue[propKey] !== void 0) {
|
|
326
|
+
const propError = validateType(`${path}.${propKey}`, objValue[propKey], propSchema);
|
|
327
|
+
if (propError) {
|
|
328
|
+
return propError;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
break;
|
|
334
|
+
default:
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
function getJsType(value) {
|
|
340
|
+
if (value === null) return "null";
|
|
341
|
+
if (Array.isArray(value)) return "array";
|
|
342
|
+
return typeof value;
|
|
343
|
+
}
|
|
344
|
+
function formatValidationErrors(result) {
|
|
345
|
+
if (result.valid) return "No validation errors";
|
|
346
|
+
const lines = result.errors.map((err) => {
|
|
347
|
+
let line = ` - ${err.message}`;
|
|
348
|
+
if (err.received !== void 0) {
|
|
349
|
+
line += ` (received: ${JSON.stringify(err.received).slice(0, 50)})`;
|
|
350
|
+
}
|
|
351
|
+
return line;
|
|
352
|
+
});
|
|
353
|
+
return `Validation failed with ${result.errors.length} error(s):
|
|
354
|
+
${lines.join("\n")}`;
|
|
355
|
+
}
|
|
356
|
+
var schemaCache, CACHE_TTL_MS;
|
|
357
|
+
var init_validation = __esm({
|
|
358
|
+
"src/validation.ts"() {
|
|
359
|
+
"use strict";
|
|
360
|
+
init_cjs_shims();
|
|
361
|
+
init_errors();
|
|
362
|
+
schemaCache = /* @__PURE__ */ new Map();
|
|
363
|
+
CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
178
364
|
}
|
|
179
365
|
});
|
|
180
366
|
|
|
@@ -185,6 +371,7 @@ var init_client = __esm({
|
|
|
185
371
|
"use strict";
|
|
186
372
|
init_cjs_shims();
|
|
187
373
|
init_errors();
|
|
374
|
+
init_validation();
|
|
188
375
|
DEFAULT_BASE_URL = "https://olympic-api.pragma-digital.org/v1";
|
|
189
376
|
DEFAULT_TIMEOUT = 3e4;
|
|
190
377
|
DEFAULT_RETRIES = 3;
|
|
@@ -195,6 +382,7 @@ var init_client = __esm({
|
|
|
195
382
|
defaultTimeout;
|
|
196
383
|
defaultRetries;
|
|
197
384
|
defaultRetryDelay;
|
|
385
|
+
disableValidation;
|
|
198
386
|
lastRateLimitInfo;
|
|
199
387
|
subscriberId;
|
|
200
388
|
constructor(config) {
|
|
@@ -203,6 +391,7 @@ var init_client = __esm({
|
|
|
203
391
|
this.defaultTimeout = config.timeout || DEFAULT_TIMEOUT;
|
|
204
392
|
this.defaultRetries = config.retries ?? DEFAULT_RETRIES;
|
|
205
393
|
this.defaultRetryDelay = config.retryDelay || DEFAULT_RETRY_DELAY;
|
|
394
|
+
this.disableValidation = config.disableValidation ?? false;
|
|
206
395
|
}
|
|
207
396
|
/**
|
|
208
397
|
* Get the last rate limit info from the API
|
|
@@ -285,15 +474,68 @@ var init_client = __esm({
|
|
|
285
474
|
}
|
|
286
475
|
/**
|
|
287
476
|
* Execute a tool/node by ID
|
|
477
|
+
*
|
|
478
|
+
* @param toolId - The ID of the tool/node to execute
|
|
479
|
+
* @param params - Parameters to pass to the tool
|
|
480
|
+
* @param options - Request options including skipValidation to bypass param validation
|
|
288
481
|
*/
|
|
289
482
|
async executeTool(toolId, params, options) {
|
|
483
|
+
if (!this.disableValidation && !options?.skipValidation) {
|
|
484
|
+
const validation = await this.validateToolParams(toolId, params);
|
|
485
|
+
if (!validation.valid) {
|
|
486
|
+
const { ValidationError: ValidationError2 } = await Promise.resolve().then(() => (init_errors(), errors_exports));
|
|
487
|
+
throw new ValidationError2(
|
|
488
|
+
`Parameter validation failed for tool '${toolId}': ${formatValidationErrors(validation)}`,
|
|
489
|
+
{ toolId, errors: validation.errors }
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
290
493
|
const subscriberId = await this.ensureSubscriberId();
|
|
291
494
|
const response = await this.request(`/olympic/subscribers/${subscriberId}/nodes/${toolId}`, {
|
|
292
495
|
method: "POST",
|
|
293
496
|
body: params || {}
|
|
294
497
|
}, options);
|
|
498
|
+
if (response.success === false) {
|
|
499
|
+
const errorMessage = typeof response.error === "string" ? response.error : JSON.stringify(response.error);
|
|
500
|
+
throw new RainfallError(
|
|
501
|
+
`Tool execution failed: ${errorMessage}`,
|
|
502
|
+
"TOOL_EXECUTION_ERROR",
|
|
503
|
+
400,
|
|
504
|
+
{ toolId, error: response.error }
|
|
505
|
+
);
|
|
506
|
+
}
|
|
295
507
|
return response.result;
|
|
296
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* Validate parameters for a tool without executing it
|
|
511
|
+
* Fetches the tool schema and validates the provided params
|
|
512
|
+
*
|
|
513
|
+
* @param toolId - The ID of the tool to validate params for
|
|
514
|
+
* @param params - Parameters to validate
|
|
515
|
+
* @returns Validation result with detailed error information
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* ```typescript
|
|
519
|
+
* const result = await client.validateToolParams('finviz-quotes', { tickers: ['AAPL'] });
|
|
520
|
+
* if (!result.valid) {
|
|
521
|
+
* console.log('Validation errors:', result.errors);
|
|
522
|
+
* }
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
async validateToolParams(toolId, params) {
|
|
526
|
+
try {
|
|
527
|
+
const schema = await fetchToolSchema(this, toolId);
|
|
528
|
+
return validateParams(schema, params, toolId);
|
|
529
|
+
} catch (error) {
|
|
530
|
+
if (error instanceof RainfallError && error.statusCode === 404) {
|
|
531
|
+
return {
|
|
532
|
+
valid: false,
|
|
533
|
+
errors: [{ path: toolId, message: `Tool '${toolId}' not found` }]
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
return { valid: true, errors: [] };
|
|
537
|
+
}
|
|
538
|
+
}
|
|
297
539
|
/**
|
|
298
540
|
* List all available tools
|
|
299
541
|
*/
|
|
@@ -316,11 +558,20 @@ var init_client = __esm({
|
|
|
316
558
|
}
|
|
317
559
|
/**
|
|
318
560
|
* Get tool schema/parameters
|
|
561
|
+
*
|
|
562
|
+
* @param toolId - The ID of the tool to get schema for
|
|
563
|
+
* @returns Tool schema including parameters and output definitions
|
|
319
564
|
*/
|
|
320
565
|
async getToolSchema(toolId) {
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
566
|
+
const schema = await fetchToolSchema(this, toolId);
|
|
567
|
+
return {
|
|
568
|
+
name: schema.name,
|
|
569
|
+
description: schema.description,
|
|
570
|
+
category: schema.category,
|
|
571
|
+
parameters: schema.parameters,
|
|
572
|
+
output: schema.output,
|
|
573
|
+
metadata: schema.metadata || {}
|
|
574
|
+
};
|
|
324
575
|
}
|
|
325
576
|
/**
|
|
326
577
|
* Get subscriber info
|
|
@@ -898,9 +1149,40 @@ var init_sdk = __esm({
|
|
|
898
1149
|
}
|
|
899
1150
|
/**
|
|
900
1151
|
* Execute any tool by ID (low-level access)
|
|
1152
|
+
*
|
|
1153
|
+
* @param toolId - The ID of the tool to execute
|
|
1154
|
+
* @param params - Parameters to pass to the tool
|
|
1155
|
+
* @param options - Execution options including skipValidation to bypass param validation
|
|
1156
|
+
*
|
|
1157
|
+
* @example
|
|
1158
|
+
* ```typescript
|
|
1159
|
+
* // Execute with validation (default)
|
|
1160
|
+
* const result = await rainfall.executeTool('finviz-quotes', { tickers: ['AAPL'] });
|
|
1161
|
+
*
|
|
1162
|
+
* // Execute without validation
|
|
1163
|
+
* const result = await rainfall.executeTool('finviz-quotes', { tickers: ['AAPL'] }, { skipValidation: true });
|
|
1164
|
+
* ```
|
|
901
1165
|
*/
|
|
902
|
-
async executeTool(toolId, params) {
|
|
903
|
-
return this.client.executeTool(toolId, params);
|
|
1166
|
+
async executeTool(toolId, params, options) {
|
|
1167
|
+
return this.client.executeTool(toolId, params, options);
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Validate parameters for a tool without executing it
|
|
1171
|
+
*
|
|
1172
|
+
* @param toolId - The ID of the tool to validate params for
|
|
1173
|
+
* @param params - Parameters to validate
|
|
1174
|
+
* @returns Validation result with detailed error information
|
|
1175
|
+
*
|
|
1176
|
+
* @example
|
|
1177
|
+
* ```typescript
|
|
1178
|
+
* const result = await rainfall.validateToolParams('finviz-quotes', { tickers: ['AAPL'] });
|
|
1179
|
+
* if (!result.valid) {
|
|
1180
|
+
* console.log('Validation errors:', result.errors);
|
|
1181
|
+
* }
|
|
1182
|
+
* ```
|
|
1183
|
+
*/
|
|
1184
|
+
async validateToolParams(toolId, params) {
|
|
1185
|
+
return this.client.validateToolParams(toolId, params);
|
|
904
1186
|
}
|
|
905
1187
|
/**
|
|
906
1188
|
* Get current subscriber info and usage
|
|
@@ -1058,6 +1340,291 @@ var init_config = __esm({
|
|
|
1058
1340
|
}
|
|
1059
1341
|
});
|
|
1060
1342
|
|
|
1343
|
+
// src/cli/core/display.ts
|
|
1344
|
+
var display_exports = {};
|
|
1345
|
+
__export(display_exports, {
|
|
1346
|
+
detectImageData: () => detectImageData,
|
|
1347
|
+
detectImageSupport: () => detectImageSupport,
|
|
1348
|
+
displayImage: () => displayImage,
|
|
1349
|
+
formatAsTable: () => formatAsTable,
|
|
1350
|
+
formatResult: () => formatResult
|
|
1351
|
+
});
|
|
1352
|
+
function detectImageSupport() {
|
|
1353
|
+
if (process.env.TERM_PROGRAM === "iTerm.app") {
|
|
1354
|
+
return { supported: true, command: "imgcat" };
|
|
1355
|
+
}
|
|
1356
|
+
if (process.env.KITTY_WINDOW_ID) {
|
|
1357
|
+
return { supported: true, command: "kitty +kitten icat" };
|
|
1358
|
+
}
|
|
1359
|
+
try {
|
|
1360
|
+
return { supported: true, command: "xan" };
|
|
1361
|
+
} catch {
|
|
1362
|
+
}
|
|
1363
|
+
try {
|
|
1364
|
+
return { supported: true, command: "catimg" };
|
|
1365
|
+
} catch {
|
|
1366
|
+
}
|
|
1367
|
+
return { supported: false };
|
|
1368
|
+
}
|
|
1369
|
+
async function displayImage(imageData, options = {}) {
|
|
1370
|
+
const imageCommand = options.imageCommand || detectImageSupport().command;
|
|
1371
|
+
if (!imageCommand) {
|
|
1372
|
+
const { writeFileSync: writeFileSync3 } = await import("fs");
|
|
1373
|
+
const { tmpdir } = await import("os");
|
|
1374
|
+
const { join: join3 } = await import("path");
|
|
1375
|
+
const tempPath = join3(tmpdir(), `rainfall-image-${Date.now()}.png`);
|
|
1376
|
+
const buffer = typeof imageData === "string" ? Buffer.from(imageData, "base64") : imageData;
|
|
1377
|
+
writeFileSync3(tempPath, buffer);
|
|
1378
|
+
console.log(`Image saved to: ${tempPath}`);
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
return new Promise((resolve, reject) => {
|
|
1382
|
+
const buffer = typeof imageData === "string" ? Buffer.from(imageData, "base64") : imageData;
|
|
1383
|
+
const child = (0, import_child_process.spawn)(imageCommand, [], {
|
|
1384
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
1385
|
+
shell: true
|
|
1386
|
+
});
|
|
1387
|
+
child.stdin.write(buffer);
|
|
1388
|
+
child.stdin.end();
|
|
1389
|
+
child.on("close", (code) => {
|
|
1390
|
+
if (code === 0) {
|
|
1391
|
+
resolve();
|
|
1392
|
+
} else {
|
|
1393
|
+
reject(new Error(`Image display failed with code ${code}`));
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
child.on("error", reject);
|
|
1397
|
+
});
|
|
1398
|
+
}
|
|
1399
|
+
function formatAsTable(data, columns) {
|
|
1400
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
1401
|
+
return "No data";
|
|
1402
|
+
}
|
|
1403
|
+
const cols = columns || Object.keys(data[0]);
|
|
1404
|
+
const widths = {};
|
|
1405
|
+
for (const col of cols) {
|
|
1406
|
+
widths[col] = Math.max(
|
|
1407
|
+
col.length,
|
|
1408
|
+
...data.map((row) => {
|
|
1409
|
+
const val = row?.[col];
|
|
1410
|
+
return String(val ?? "").slice(0, 50).length;
|
|
1411
|
+
})
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
const lines = [];
|
|
1415
|
+
const header = cols.map((col) => col.padEnd(widths[col])).join(" ");
|
|
1416
|
+
lines.push(header);
|
|
1417
|
+
lines.push(cols.map((col) => "-".repeat(widths[col])).join(" "));
|
|
1418
|
+
for (const row of data) {
|
|
1419
|
+
const line = cols.map((col) => {
|
|
1420
|
+
const val = row?.[col];
|
|
1421
|
+
const str = String(val ?? "").slice(0, 50);
|
|
1422
|
+
return str.padEnd(widths[col]);
|
|
1423
|
+
}).join(" ");
|
|
1424
|
+
lines.push(line);
|
|
1425
|
+
}
|
|
1426
|
+
return lines.join("\n");
|
|
1427
|
+
}
|
|
1428
|
+
async function formatResult(result, options = {}) {
|
|
1429
|
+
const mode = options.mode || "pretty";
|
|
1430
|
+
switch (mode) {
|
|
1431
|
+
case "raw":
|
|
1432
|
+
return JSON.stringify(result);
|
|
1433
|
+
case "pretty":
|
|
1434
|
+
return JSON.stringify(result, null, 2);
|
|
1435
|
+
case "table":
|
|
1436
|
+
if (Array.isArray(result)) {
|
|
1437
|
+
return formatAsTable(result, options.columns);
|
|
1438
|
+
}
|
|
1439
|
+
return JSON.stringify(result, null, 2);
|
|
1440
|
+
case "terminal":
|
|
1441
|
+
if (typeof result === "string") {
|
|
1442
|
+
return result;
|
|
1443
|
+
}
|
|
1444
|
+
if (Array.isArray(result) && result.every((r) => typeof r === "string")) {
|
|
1445
|
+
return result.join("\n");
|
|
1446
|
+
}
|
|
1447
|
+
return JSON.stringify(result);
|
|
1448
|
+
default:
|
|
1449
|
+
return JSON.stringify(result, null, 2);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
function detectImageData(result) {
|
|
1453
|
+
if (!result || typeof result !== "object") {
|
|
1454
|
+
return { hasImage: false };
|
|
1455
|
+
}
|
|
1456
|
+
const obj = result;
|
|
1457
|
+
const imageFields = ["image", "imageData", "imageBase64", "png", "jpeg", "data"];
|
|
1458
|
+
for (const field of imageFields) {
|
|
1459
|
+
if (obj[field] && typeof obj[field] === "string") {
|
|
1460
|
+
const value = obj[field];
|
|
1461
|
+
if (value.startsWith("data:image/") || value.length > 100) {
|
|
1462
|
+
return {
|
|
1463
|
+
hasImage: true,
|
|
1464
|
+
imageData: value.startsWith("data:image/") ? value.split(",")[1] : value
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
if (obj.url && typeof obj.url === "string" && (obj.url.endsWith(".png") || obj.url.endsWith(".jpg") || obj.url.endsWith(".jpeg"))) {
|
|
1470
|
+
return { hasImage: true, imagePath: obj.url };
|
|
1471
|
+
}
|
|
1472
|
+
return { hasImage: false };
|
|
1473
|
+
}
|
|
1474
|
+
var import_child_process;
|
|
1475
|
+
var init_display = __esm({
|
|
1476
|
+
"src/cli/core/display.ts"() {
|
|
1477
|
+
"use strict";
|
|
1478
|
+
init_cjs_shims();
|
|
1479
|
+
import_child_process = require("child_process");
|
|
1480
|
+
}
|
|
1481
|
+
});
|
|
1482
|
+
|
|
1483
|
+
// src/cli/core/param-parser.ts
|
|
1484
|
+
var param_parser_exports = {};
|
|
1485
|
+
__export(param_parser_exports, {
|
|
1486
|
+
formatValueForDisplay: () => formatValueForDisplay,
|
|
1487
|
+
generateParamExample: () => generateParamExample,
|
|
1488
|
+
parseCliArgs: () => parseCliArgs,
|
|
1489
|
+
parseValue: () => parseValue
|
|
1490
|
+
});
|
|
1491
|
+
function parseValue(value, schema, options = {}) {
|
|
1492
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
1493
|
+
if (!schema) {
|
|
1494
|
+
try {
|
|
1495
|
+
return JSON.parse(value);
|
|
1496
|
+
} catch {
|
|
1497
|
+
return value;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
const expectedType = schema.type;
|
|
1501
|
+
switch (expectedType) {
|
|
1502
|
+
case "array":
|
|
1503
|
+
return parseArrayValue(value, schema, opts);
|
|
1504
|
+
case "number":
|
|
1505
|
+
return parseNumberValue(value, opts);
|
|
1506
|
+
case "boolean":
|
|
1507
|
+
return parseBooleanValue(value, opts);
|
|
1508
|
+
case "string":
|
|
1509
|
+
return value;
|
|
1510
|
+
case "object":
|
|
1511
|
+
try {
|
|
1512
|
+
return JSON.parse(value);
|
|
1513
|
+
} catch {
|
|
1514
|
+
return value;
|
|
1515
|
+
}
|
|
1516
|
+
default:
|
|
1517
|
+
try {
|
|
1518
|
+
return JSON.parse(value);
|
|
1519
|
+
} catch {
|
|
1520
|
+
return value;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
function parseArrayValue(value, schema, options) {
|
|
1525
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1526
|
+
try {
|
|
1527
|
+
return JSON.parse(value);
|
|
1528
|
+
} catch {
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
if (options.arrayInterpolation && value.includes(options.arraySeparator)) {
|
|
1532
|
+
const items = value.split(options.arraySeparator).map((s) => s.trim()).filter(Boolean);
|
|
1533
|
+
if (schema.items) {
|
|
1534
|
+
return items.map((item) => parseValue(item, schema.items, { ...options, arrayInterpolation: false }));
|
|
1535
|
+
}
|
|
1536
|
+
return items;
|
|
1537
|
+
}
|
|
1538
|
+
if (schema.items) {
|
|
1539
|
+
return [parseValue(value, schema.items, { ...options, arrayInterpolation: false })];
|
|
1540
|
+
}
|
|
1541
|
+
return [value];
|
|
1542
|
+
}
|
|
1543
|
+
function parseNumberValue(value, options) {
|
|
1544
|
+
if (!options.numberParsing) {
|
|
1545
|
+
return value;
|
|
1546
|
+
}
|
|
1547
|
+
const num = Number(value);
|
|
1548
|
+
if (!isNaN(num) && isFinite(num)) {
|
|
1549
|
+
return num;
|
|
1550
|
+
}
|
|
1551
|
+
return value;
|
|
1552
|
+
}
|
|
1553
|
+
function parseBooleanValue(value, options) {
|
|
1554
|
+
if (!options.booleanParsing) {
|
|
1555
|
+
return value;
|
|
1556
|
+
}
|
|
1557
|
+
const lower = value.toLowerCase();
|
|
1558
|
+
if (lower === "true" || lower === "yes" || lower === "1" || lower === "on") {
|
|
1559
|
+
return true;
|
|
1560
|
+
}
|
|
1561
|
+
if (lower === "false" || lower === "no" || lower === "0" || lower === "off") {
|
|
1562
|
+
return false;
|
|
1563
|
+
}
|
|
1564
|
+
return value;
|
|
1565
|
+
}
|
|
1566
|
+
function parseCliArgs(args, schema, options = {}) {
|
|
1567
|
+
const params = {};
|
|
1568
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
1569
|
+
const parameters = schema?.parameters || {};
|
|
1570
|
+
for (let i = 0; i < args.length; i++) {
|
|
1571
|
+
const arg = args[i];
|
|
1572
|
+
if (arg.startsWith("--")) {
|
|
1573
|
+
const key = arg.slice(2);
|
|
1574
|
+
const value = args[++i];
|
|
1575
|
+
if (value === void 0) {
|
|
1576
|
+
params[key] = true;
|
|
1577
|
+
continue;
|
|
1578
|
+
}
|
|
1579
|
+
const paramSchema = parameters[key];
|
|
1580
|
+
params[key] = parseValue(value, paramSchema, opts);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return params;
|
|
1584
|
+
}
|
|
1585
|
+
function formatValueForDisplay(value) {
|
|
1586
|
+
if (value === null) return "null";
|
|
1587
|
+
if (value === void 0) return "undefined";
|
|
1588
|
+
if (typeof value === "string") return value;
|
|
1589
|
+
if (typeof value === "number") return String(value);
|
|
1590
|
+
if (typeof value === "boolean") return String(value);
|
|
1591
|
+
if (Array.isArray(value)) {
|
|
1592
|
+
return value.map(formatValueForDisplay).join(",");
|
|
1593
|
+
}
|
|
1594
|
+
return JSON.stringify(value);
|
|
1595
|
+
}
|
|
1596
|
+
function generateParamExample(key, schema) {
|
|
1597
|
+
const type = schema.type || "string";
|
|
1598
|
+
switch (type) {
|
|
1599
|
+
case "array":
|
|
1600
|
+
if (schema.items?.type === "string") {
|
|
1601
|
+
return `--${key} item1,item2,item3`;
|
|
1602
|
+
}
|
|
1603
|
+
return `--${key} '["item1", "item2"]'`;
|
|
1604
|
+
case "number":
|
|
1605
|
+
return `--${key} 42`;
|
|
1606
|
+
case "boolean":
|
|
1607
|
+
return `--${key} true`;
|
|
1608
|
+
case "object":
|
|
1609
|
+
return `--${key} '{"key": "value"}'`;
|
|
1610
|
+
default:
|
|
1611
|
+
return `--${key} "value"`;
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
var DEFAULT_OPTIONS;
|
|
1615
|
+
var init_param_parser = __esm({
|
|
1616
|
+
"src/cli/core/param-parser.ts"() {
|
|
1617
|
+
"use strict";
|
|
1618
|
+
init_cjs_shims();
|
|
1619
|
+
DEFAULT_OPTIONS = {
|
|
1620
|
+
arrayInterpolation: true,
|
|
1621
|
+
numberParsing: true,
|
|
1622
|
+
booleanParsing: true,
|
|
1623
|
+
arraySeparator: ","
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
});
|
|
1627
|
+
|
|
1061
1628
|
// src/services/networked.ts
|
|
1062
1629
|
var RainfallNetworkedExecutor;
|
|
1063
1630
|
var init_networked = __esm({
|
|
@@ -1717,7 +2284,7 @@ var init_listeners = __esm({
|
|
|
1717
2284
|
});
|
|
1718
2285
|
|
|
1719
2286
|
// src/services/mcp-proxy.ts
|
|
1720
|
-
var import_ws, import_client2, import_stdio, import_streamableHttp,
|
|
2287
|
+
var import_ws, import_client2, import_stdio, import_streamableHttp, import_types2, MCPProxyHub;
|
|
1721
2288
|
var init_mcp_proxy = __esm({
|
|
1722
2289
|
"src/services/mcp-proxy.ts"() {
|
|
1723
2290
|
"use strict";
|
|
@@ -1726,7 +2293,7 @@ var init_mcp_proxy = __esm({
|
|
|
1726
2293
|
import_client2 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
1727
2294
|
import_stdio = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
1728
2295
|
import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
1729
|
-
|
|
2296
|
+
import_types2 = require("@modelcontextprotocol/sdk/types.js");
|
|
1730
2297
|
MCPProxyHub = class {
|
|
1731
2298
|
clients = /* @__PURE__ */ new Map();
|
|
1732
2299
|
options;
|
|
@@ -1845,7 +2412,7 @@ var init_mcp_proxy = __esm({
|
|
|
1845
2412
|
method: "tools/list",
|
|
1846
2413
|
params: {}
|
|
1847
2414
|
},
|
|
1848
|
-
|
|
2415
|
+
import_types2.ListToolsResultSchema
|
|
1849
2416
|
);
|
|
1850
2417
|
const tools = toolsResult.tools.map((tool) => ({
|
|
1851
2418
|
name: tool.name,
|
|
@@ -1959,7 +2526,7 @@ var init_mcp_proxy = __esm({
|
|
|
1959
2526
|
arguments: args
|
|
1960
2527
|
}
|
|
1961
2528
|
},
|
|
1962
|
-
|
|
2529
|
+
import_types2.CallToolResultSchema
|
|
1963
2530
|
),
|
|
1964
2531
|
new Promise(
|
|
1965
2532
|
(_, reject) => setTimeout(() => reject(new Error(`Tool call timeout after ${timeout}ms`)), timeout)
|
|
@@ -1969,7 +2536,7 @@ var init_mcp_proxy = __esm({
|
|
|
1969
2536
|
return this.formatToolResult(result);
|
|
1970
2537
|
} catch (error) {
|
|
1971
2538
|
this.log(`[${requestId}] Failed:`, error instanceof Error ? error.message : error);
|
|
1972
|
-
if (error instanceof
|
|
2539
|
+
if (error instanceof import_types2.McpError) {
|
|
1973
2540
|
throw new Error(`MCP Error (${toolName}): ${error.message} (code: ${error.code})`);
|
|
1974
2541
|
}
|
|
1975
2542
|
throw error;
|
|
@@ -2053,7 +2620,7 @@ var init_mcp_proxy = __esm({
|
|
|
2053
2620
|
method: "tools/list",
|
|
2054
2621
|
params: {}
|
|
2055
2622
|
},
|
|
2056
|
-
|
|
2623
|
+
import_types2.ListToolsResultSchema
|
|
2057
2624
|
);
|
|
2058
2625
|
client.tools = toolsResult.tools.map((tool) => ({
|
|
2059
2626
|
name: tool.name,
|
|
@@ -2084,7 +2651,7 @@ var init_mcp_proxy = __esm({
|
|
|
2084
2651
|
method: "resources/list",
|
|
2085
2652
|
params: {}
|
|
2086
2653
|
},
|
|
2087
|
-
|
|
2654
|
+
import_types2.ListResourcesResultSchema
|
|
2088
2655
|
);
|
|
2089
2656
|
results.push({
|
|
2090
2657
|
clientName: name,
|
|
@@ -2110,7 +2677,7 @@ var init_mcp_proxy = __esm({
|
|
|
2110
2677
|
method: "resources/read",
|
|
2111
2678
|
params: { uri }
|
|
2112
2679
|
},
|
|
2113
|
-
|
|
2680
|
+
import_types2.ReadResourceResultSchema
|
|
2114
2681
|
);
|
|
2115
2682
|
return result;
|
|
2116
2683
|
} else {
|
|
@@ -2121,7 +2688,7 @@ var init_mcp_proxy = __esm({
|
|
|
2121
2688
|
method: "resources/read",
|
|
2122
2689
|
params: { uri }
|
|
2123
2690
|
},
|
|
2124
|
-
|
|
2691
|
+
import_types2.ReadResourceResultSchema
|
|
2125
2692
|
);
|
|
2126
2693
|
return { clientName: name, ...result };
|
|
2127
2694
|
} catch {
|
|
@@ -2145,7 +2712,7 @@ var init_mcp_proxy = __esm({
|
|
|
2145
2712
|
method: "prompts/list",
|
|
2146
2713
|
params: {}
|
|
2147
2714
|
},
|
|
2148
|
-
|
|
2715
|
+
import_types2.ListPromptsResultSchema
|
|
2149
2716
|
);
|
|
2150
2717
|
results.push({
|
|
2151
2718
|
clientName: name,
|
|
@@ -2171,7 +2738,7 @@ var init_mcp_proxy = __esm({
|
|
|
2171
2738
|
method: "prompts/get",
|
|
2172
2739
|
params: { name, arguments: args }
|
|
2173
2740
|
},
|
|
2174
|
-
|
|
2741
|
+
import_types2.GetPromptResultSchema
|
|
2175
2742
|
);
|
|
2176
2743
|
return result;
|
|
2177
2744
|
} else {
|
|
@@ -2182,7 +2749,7 @@ var init_mcp_proxy = __esm({
|
|
|
2182
2749
|
method: "prompts/get",
|
|
2183
2750
|
params: { name, arguments: args }
|
|
2184
2751
|
},
|
|
2185
|
-
|
|
2752
|
+
import_types2.GetPromptResultSchema
|
|
2186
2753
|
);
|
|
2187
2754
|
return { clientName: cName, ...result };
|
|
2188
2755
|
} catch {
|
|
@@ -2204,7 +2771,7 @@ var init_mcp_proxy = __esm({
|
|
|
2204
2771
|
method: "tools/list",
|
|
2205
2772
|
params: {}
|
|
2206
2773
|
},
|
|
2207
|
-
|
|
2774
|
+
import_types2.ListToolsResultSchema
|
|
2208
2775
|
);
|
|
2209
2776
|
results.set(name, {
|
|
2210
2777
|
status: "healthy",
|
|
@@ -3274,17 +3841,17 @@ var import_path2 = require("path");
|
|
|
3274
3841
|
var import_url = require("url");
|
|
3275
3842
|
init_sdk();
|
|
3276
3843
|
init_config();
|
|
3277
|
-
var
|
|
3844
|
+
var import_child_process2 = require("child_process");
|
|
3278
3845
|
|
|
3279
3846
|
// src/security/edge-node.ts
|
|
3280
3847
|
init_cjs_shims();
|
|
3281
|
-
var
|
|
3848
|
+
var import_libsodium_wrappers_sumo = __toESM(require("libsodium-wrappers-sumo"));
|
|
3282
3849
|
var EdgeNodeSecurity = class {
|
|
3283
3850
|
sodiumReady;
|
|
3284
3851
|
backendSecret;
|
|
3285
3852
|
keyPair;
|
|
3286
3853
|
constructor(options = {}) {
|
|
3287
|
-
this.sodiumReady =
|
|
3854
|
+
this.sodiumReady = import_libsodium_wrappers_sumo.default.ready;
|
|
3288
3855
|
this.backendSecret = options.backendSecret;
|
|
3289
3856
|
this.keyPair = options.keyPair;
|
|
3290
3857
|
}
|
|
@@ -3414,7 +3981,7 @@ var EdgeNodeSecurity = class {
|
|
|
3414
3981
|
*/
|
|
3415
3982
|
async generateKeyPair() {
|
|
3416
3983
|
await this.sodiumReady;
|
|
3417
|
-
const keyPair =
|
|
3984
|
+
const keyPair = import_libsodium_wrappers_sumo.default.crypto_box_keypair();
|
|
3418
3985
|
return {
|
|
3419
3986
|
publicKey: this.bytesToBase64(keyPair.publicKey),
|
|
3420
3987
|
privateKey: this.bytesToBase64(keyPair.privateKey)
|
|
@@ -3429,10 +3996,10 @@ var EdgeNodeSecurity = class {
|
|
|
3429
3996
|
throw new Error("Local key pair not configured");
|
|
3430
3997
|
}
|
|
3431
3998
|
const targetPublicKey = this.base64ToBytes(targetPublicKeyBase64);
|
|
3432
|
-
const ephemeralKeyPair =
|
|
3433
|
-
const nonce =
|
|
3999
|
+
const ephemeralKeyPair = import_libsodium_wrappers_sumo.default.crypto_box_keypair();
|
|
4000
|
+
const nonce = import_libsodium_wrappers_sumo.default.randombytes_buf(import_libsodium_wrappers_sumo.default.crypto_box_NONCEBYTES);
|
|
3434
4001
|
const message = new TextEncoder().encode(plaintext);
|
|
3435
|
-
const ciphertext =
|
|
4002
|
+
const ciphertext = import_libsodium_wrappers_sumo.default.crypto_box_easy(
|
|
3436
4003
|
message,
|
|
3437
4004
|
nonce,
|
|
3438
4005
|
targetPublicKey,
|
|
@@ -3456,7 +4023,7 @@ var EdgeNodeSecurity = class {
|
|
|
3456
4023
|
const ephemeralPublicKey = this.base64ToBytes(encrypted.ephemeralPublicKey);
|
|
3457
4024
|
const nonce = this.base64ToBytes(encrypted.nonce);
|
|
3458
4025
|
const ciphertext = this.base64ToBytes(encrypted.ciphertext);
|
|
3459
|
-
const decrypted =
|
|
4026
|
+
const decrypted = import_libsodium_wrappers_sumo.default.crypto_box_open_easy(
|
|
3460
4027
|
ciphertext,
|
|
3461
4028
|
nonce,
|
|
3462
4029
|
ephemeralPublicKey,
|
|
@@ -3473,9 +4040,9 @@ var EdgeNodeSecurity = class {
|
|
|
3473
4040
|
async encryptLocal(plaintext, key) {
|
|
3474
4041
|
await this.sodiumReady;
|
|
3475
4042
|
const keyBytes = this.deriveKey(key);
|
|
3476
|
-
const nonce =
|
|
4043
|
+
const nonce = import_libsodium_wrappers_sumo.default.randombytes_buf(import_libsodium_wrappers_sumo.default.crypto_secretbox_NONCEBYTES);
|
|
3477
4044
|
const message = new TextEncoder().encode(plaintext);
|
|
3478
|
-
const ciphertext =
|
|
4045
|
+
const ciphertext = import_libsodium_wrappers_sumo.default.crypto_secretbox_easy(message, nonce, keyBytes);
|
|
3479
4046
|
return {
|
|
3480
4047
|
ciphertext: this.bytesToBase64(ciphertext),
|
|
3481
4048
|
nonce: this.bytesToBase64(nonce)
|
|
@@ -3489,7 +4056,7 @@ var EdgeNodeSecurity = class {
|
|
|
3489
4056
|
const keyBytes = this.deriveKey(key);
|
|
3490
4057
|
const nonce = this.base64ToBytes(encrypted.nonce);
|
|
3491
4058
|
const ciphertext = this.base64ToBytes(encrypted.ciphertext);
|
|
3492
|
-
const decrypted =
|
|
4059
|
+
const decrypted = import_libsodium_wrappers_sumo.default.crypto_secretbox_open_easy(ciphertext, nonce, keyBytes);
|
|
3493
4060
|
if (!decrypted) {
|
|
3494
4061
|
throw new Error("Local decryption failed");
|
|
3495
4062
|
}
|
|
@@ -3512,7 +4079,7 @@ var EdgeNodeSecurity = class {
|
|
|
3512
4079
|
hmacSha256(message, secret) {
|
|
3513
4080
|
const key = new TextEncoder().encode(secret);
|
|
3514
4081
|
const msg = new TextEncoder().encode(message);
|
|
3515
|
-
const hash =
|
|
4082
|
+
const hash = import_libsodium_wrappers_sumo.default.crypto_auth(msg, key);
|
|
3516
4083
|
return this.bytesToBase64(hash);
|
|
3517
4084
|
}
|
|
3518
4085
|
timingSafeEqual(a, b) {
|
|
@@ -3533,7 +4100,7 @@ var EdgeNodeSecurity = class {
|
|
|
3533
4100
|
}
|
|
3534
4101
|
deriveKey(password) {
|
|
3535
4102
|
const passwordBytes = new TextEncoder().encode(password);
|
|
3536
|
-
return
|
|
4103
|
+
return import_libsodium_wrappers_sumo.default.crypto_generichash(32, passwordBytes, null);
|
|
3537
4104
|
}
|
|
3538
4105
|
};
|
|
3539
4106
|
async function createEdgeNodeSecurity(options = {}) {
|
|
@@ -3542,6 +4109,179 @@ async function createEdgeNodeSecurity(options = {}) {
|
|
|
3542
4109
|
return security;
|
|
3543
4110
|
}
|
|
3544
4111
|
|
|
4112
|
+
// src/cli/index.ts
|
|
4113
|
+
init_display();
|
|
4114
|
+
|
|
4115
|
+
// src/cli/handlers/_registry.ts
|
|
4116
|
+
init_cjs_shims();
|
|
4117
|
+
|
|
4118
|
+
// src/cli/core/types.ts
|
|
4119
|
+
init_cjs_shims();
|
|
4120
|
+
var ToolHandlerRegistry = class {
|
|
4121
|
+
handlers = [];
|
|
4122
|
+
register(handler) {
|
|
4123
|
+
this.handlers.push(handler);
|
|
4124
|
+
}
|
|
4125
|
+
findHandler(toolId) {
|
|
4126
|
+
return this.handlers.find((h) => {
|
|
4127
|
+
if (typeof h.toolId === "string") {
|
|
4128
|
+
return h.toolId === toolId;
|
|
4129
|
+
}
|
|
4130
|
+
return h.toolId.test(toolId);
|
|
4131
|
+
});
|
|
4132
|
+
}
|
|
4133
|
+
getAllHandlers() {
|
|
4134
|
+
return [...this.handlers];
|
|
4135
|
+
}
|
|
4136
|
+
};
|
|
4137
|
+
var globalHandlerRegistry = new ToolHandlerRegistry();
|
|
4138
|
+
|
|
4139
|
+
// src/cli/handlers/_registry.ts
|
|
4140
|
+
var imageGenerationHandler = {
|
|
4141
|
+
toolId: /image-generation|generate-image/,
|
|
4142
|
+
async display(context) {
|
|
4143
|
+
const { detectImageData: detectImageData2, displayImage: displayImage2 } = await Promise.resolve().then(() => (init_display(), display_exports));
|
|
4144
|
+
const { result, flags } = context;
|
|
4145
|
+
const imageInfo = detectImageData2(result);
|
|
4146
|
+
if (imageInfo.hasImage && !flags.raw) {
|
|
4147
|
+
try {
|
|
4148
|
+
if (imageInfo.imageData) {
|
|
4149
|
+
await displayImage2(imageInfo.imageData);
|
|
4150
|
+
return true;
|
|
4151
|
+
}
|
|
4152
|
+
} catch (error) {
|
|
4153
|
+
console.warn("Failed to display image:", error instanceof Error ? error.message : error);
|
|
4154
|
+
}
|
|
4155
|
+
}
|
|
4156
|
+
return false;
|
|
4157
|
+
}
|
|
4158
|
+
};
|
|
4159
|
+
var finvizQuotesHandler = {
|
|
4160
|
+
toolId: "finviz-quotes",
|
|
4161
|
+
async preflight(context) {
|
|
4162
|
+
const { parseValue: parseValue2 } = await Promise.resolve().then(() => (init_param_parser(), param_parser_exports));
|
|
4163
|
+
const params = { ...context.params };
|
|
4164
|
+
if (params.tickers && typeof params.tickers === "string") {
|
|
4165
|
+
params.tickers = parseValue2(params.tickers, { type: "array", items: { type: "string" } });
|
|
4166
|
+
}
|
|
4167
|
+
return { params };
|
|
4168
|
+
},
|
|
4169
|
+
async display(context) {
|
|
4170
|
+
const { result, flags } = context;
|
|
4171
|
+
if (flags.raw) {
|
|
4172
|
+
return false;
|
|
4173
|
+
}
|
|
4174
|
+
const obj = result;
|
|
4175
|
+
const quotes = obj?.quotes;
|
|
4176
|
+
if (Array.isArray(quotes) && quotes.length > 0) {
|
|
4177
|
+
const { formatAsTable: formatAsTable2 } = await Promise.resolve().then(() => (init_display(), display_exports));
|
|
4178
|
+
const tableData = quotes.map((q) => {
|
|
4179
|
+
const quote = q;
|
|
4180
|
+
const data = quote.data || {};
|
|
4181
|
+
return {
|
|
4182
|
+
Ticker: quote.ticker || data.Ticker || "-",
|
|
4183
|
+
Price: data.Price || data.Close || "-",
|
|
4184
|
+
Change: data.Change || "-",
|
|
4185
|
+
Volume: data.Volume || "-",
|
|
4186
|
+
"Market Cap": data.MarketCap || "-"
|
|
4187
|
+
};
|
|
4188
|
+
});
|
|
4189
|
+
console.log(formatAsTable2(tableData));
|
|
4190
|
+
const summary = obj?.summary;
|
|
4191
|
+
if (summary && typeof summary === "string") {
|
|
4192
|
+
console.log(`
|
|
4193
|
+
${summary}`);
|
|
4194
|
+
}
|
|
4195
|
+
return true;
|
|
4196
|
+
}
|
|
4197
|
+
return false;
|
|
4198
|
+
}
|
|
4199
|
+
};
|
|
4200
|
+
var csvQueryHandler = {
|
|
4201
|
+
toolId: /query-csv|csv-query/,
|
|
4202
|
+
async display(context) {
|
|
4203
|
+
const { result, flags } = context;
|
|
4204
|
+
if (flags.raw) {
|
|
4205
|
+
return false;
|
|
4206
|
+
}
|
|
4207
|
+
if (Array.isArray(result) && result.length > 0) {
|
|
4208
|
+
const { formatAsTable: formatAsTable2 } = await Promise.resolve().then(() => (init_display(), display_exports));
|
|
4209
|
+
console.log(formatAsTable2(result));
|
|
4210
|
+
return true;
|
|
4211
|
+
}
|
|
4212
|
+
return false;
|
|
4213
|
+
}
|
|
4214
|
+
};
|
|
4215
|
+
var webSearchHandler = {
|
|
4216
|
+
toolId: /web-search|exa-web-search|perplexity/,
|
|
4217
|
+
async display(context) {
|
|
4218
|
+
const { result, flags } = context;
|
|
4219
|
+
if (flags.raw) {
|
|
4220
|
+
return false;
|
|
4221
|
+
}
|
|
4222
|
+
const obj = result;
|
|
4223
|
+
if (obj.results && typeof obj.results === "string") {
|
|
4224
|
+
console.log(obj.results);
|
|
4225
|
+
return true;
|
|
4226
|
+
}
|
|
4227
|
+
if (obj.answer || obj.summary) {
|
|
4228
|
+
console.log(obj.answer || obj.summary);
|
|
4229
|
+
if (obj.sources && Array.isArray(obj.sources)) {
|
|
4230
|
+
console.log("\n--- Sources ---");
|
|
4231
|
+
obj.sources.forEach((source, i) => {
|
|
4232
|
+
if (typeof source === "string") {
|
|
4233
|
+
console.log(` ${i + 1}. ${source}`);
|
|
4234
|
+
} else if (source && typeof source === "object") {
|
|
4235
|
+
const s = source;
|
|
4236
|
+
console.log(` ${i + 1}. ${s.title || s.url || JSON.stringify(source)}`);
|
|
4237
|
+
}
|
|
4238
|
+
});
|
|
4239
|
+
}
|
|
4240
|
+
return true;
|
|
4241
|
+
}
|
|
4242
|
+
return false;
|
|
4243
|
+
}
|
|
4244
|
+
};
|
|
4245
|
+
var memoryRecallHandler = {
|
|
4246
|
+
toolId: /memory-recall|recall/,
|
|
4247
|
+
async display(context) {
|
|
4248
|
+
const { result, flags } = context;
|
|
4249
|
+
if (flags.raw) {
|
|
4250
|
+
return false;
|
|
4251
|
+
}
|
|
4252
|
+
if (Array.isArray(result)) {
|
|
4253
|
+
if (result.length === 0) {
|
|
4254
|
+
console.log("No memories found.");
|
|
4255
|
+
return true;
|
|
4256
|
+
}
|
|
4257
|
+
console.log(`Found ${result.length} memory(s):
|
|
4258
|
+
`);
|
|
4259
|
+
result.forEach((mem, i) => {
|
|
4260
|
+
const memory = mem;
|
|
4261
|
+
console.log(`\u2500`.repeat(60));
|
|
4262
|
+
console.log(` ${i + 1}. ${memory.content || memory.text || JSON.stringify(memory).slice(0, 100)}`);
|
|
4263
|
+
if (memory.similarity) {
|
|
4264
|
+
console.log(` Similarity: ${(Number(memory.similarity) * 100).toFixed(1)}%`);
|
|
4265
|
+
}
|
|
4266
|
+
if (memory.keywords && Array.isArray(memory.keywords)) {
|
|
4267
|
+
console.log(` Keywords: ${memory.keywords.join(", ")}`);
|
|
4268
|
+
}
|
|
4269
|
+
console.log();
|
|
4270
|
+
});
|
|
4271
|
+
return true;
|
|
4272
|
+
}
|
|
4273
|
+
return false;
|
|
4274
|
+
}
|
|
4275
|
+
};
|
|
4276
|
+
function registerBuiltInHandlers(registry = globalHandlerRegistry) {
|
|
4277
|
+
registry.register(imageGenerationHandler);
|
|
4278
|
+
registry.register(finvizQuotesHandler);
|
|
4279
|
+
registry.register(csvQueryHandler);
|
|
4280
|
+
registry.register(webSearchHandler);
|
|
4281
|
+
registry.register(memoryRecallHandler);
|
|
4282
|
+
}
|
|
4283
|
+
registerBuiltInHandlers();
|
|
4284
|
+
|
|
3545
4285
|
// src/cli/index.ts
|
|
3546
4286
|
function printHelp() {
|
|
3547
4287
|
console.log(`
|
|
@@ -3593,7 +4333,12 @@ Options for 'run':
|
|
|
3593
4333
|
--params, -p <json> Tool parameters as JSON
|
|
3594
4334
|
--file, -f <path> Read parameters from file
|
|
3595
4335
|
--raw Output raw JSON
|
|
4336
|
+
--table Output as table (if applicable)
|
|
4337
|
+
--terminal Output for terminal consumption (minimal formatting)
|
|
3596
4338
|
--<key> <value> Pass individual parameters (e.g., --query "AI news")
|
|
4339
|
+
Arrays: --tickers AAPL,GOOGL (comma-separated)
|
|
4340
|
+
Numbers: --count 42
|
|
4341
|
+
Booleans: --enabled true
|
|
3597
4342
|
|
|
3598
4343
|
Options for 'daemon start':
|
|
3599
4344
|
--port <port> WebSocket port (default: 8765)
|
|
@@ -3609,6 +4354,7 @@ Examples:
|
|
|
3609
4354
|
rainfall tools describe github-create-issue
|
|
3610
4355
|
rainfall run exa-web-search -p '{"query": "AI news"}'
|
|
3611
4356
|
rainfall run exa-web-search --query "AI news"
|
|
4357
|
+
rainfall run finviz-quotes --tickers AAPL,GOOGL,MSFT
|
|
3612
4358
|
rainfall run github-create-issue --owner facebook --repo react --title "Bug"
|
|
3613
4359
|
rainfall run article-summarize -f ./article.json
|
|
3614
4360
|
rainfall daemon start
|
|
@@ -3626,6 +4372,24 @@ function getRainfall() {
|
|
|
3626
4372
|
baseUrl: config.baseUrl
|
|
3627
4373
|
});
|
|
3628
4374
|
}
|
|
4375
|
+
async function fetchAllNodeIds(rainfall) {
|
|
4376
|
+
try {
|
|
4377
|
+
const client = rainfall.getClient();
|
|
4378
|
+
const subscriberId = await client.ensureSubscriberId();
|
|
4379
|
+
const result = await client.request(
|
|
4380
|
+
`/olympic/subscribers/${subscriberId}/nodes/_utils/node-list`
|
|
4381
|
+
);
|
|
4382
|
+
if (result.keys && Array.isArray(result.keys)) {
|
|
4383
|
+
return result.keys;
|
|
4384
|
+
}
|
|
4385
|
+
if (result.nodes && Array.isArray(result.nodes)) {
|
|
4386
|
+
return result.nodes.map((n) => n.id);
|
|
4387
|
+
}
|
|
4388
|
+
return [];
|
|
4389
|
+
} catch {
|
|
4390
|
+
return [];
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
3629
4393
|
async function authLogin(args) {
|
|
3630
4394
|
const apiKey = args[0] || process.env.RAINFALL_API_KEY;
|
|
3631
4395
|
if (!apiKey) {
|
|
@@ -3712,6 +4476,100 @@ function formatSchema(obj, indent = 0) {
|
|
|
3712
4476
|
}
|
|
3713
4477
|
return lines.join("\n");
|
|
3714
4478
|
}
|
|
4479
|
+
function levenshteinDistance(a, b) {
|
|
4480
|
+
const matrix = [];
|
|
4481
|
+
for (let i = 0; i <= b.length; i++) {
|
|
4482
|
+
matrix[i] = [i];
|
|
4483
|
+
}
|
|
4484
|
+
for (let j = 0; j <= a.length; j++) {
|
|
4485
|
+
matrix[0][j] = j;
|
|
4486
|
+
}
|
|
4487
|
+
for (let i = 1; i <= b.length; i++) {
|
|
4488
|
+
for (let j = 1; j <= a.length; j++) {
|
|
4489
|
+
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
4490
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
4491
|
+
} else {
|
|
4492
|
+
matrix[i][j] = Math.min(
|
|
4493
|
+
matrix[i - 1][j - 1] + 1,
|
|
4494
|
+
// substitution
|
|
4495
|
+
matrix[i][j - 1] + 1,
|
|
4496
|
+
// insertion
|
|
4497
|
+
matrix[i - 1][j] + 1
|
|
4498
|
+
// deletion
|
|
4499
|
+
);
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4502
|
+
}
|
|
4503
|
+
return matrix[b.length][a.length];
|
|
4504
|
+
}
|
|
4505
|
+
function jaroWinklerSimilarity(a, b) {
|
|
4506
|
+
if (a === b) return 1;
|
|
4507
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
4508
|
+
const matchDistance = Math.floor(Math.max(a.length, b.length) / 2) - 1;
|
|
4509
|
+
const aMatches = new Array(a.length).fill(false);
|
|
4510
|
+
const bMatches = new Array(b.length).fill(false);
|
|
4511
|
+
let matches = 0;
|
|
4512
|
+
let transpositions = 0;
|
|
4513
|
+
for (let i = 0; i < a.length; i++) {
|
|
4514
|
+
const start = Math.max(0, i - matchDistance);
|
|
4515
|
+
const end = Math.min(i + matchDistance + 1, b.length);
|
|
4516
|
+
for (let j = start; j < end; j++) {
|
|
4517
|
+
if (bMatches[j] || a.charAt(i) !== b.charAt(j)) continue;
|
|
4518
|
+
aMatches[i] = true;
|
|
4519
|
+
bMatches[j] = true;
|
|
4520
|
+
matches++;
|
|
4521
|
+
break;
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4524
|
+
if (matches === 0) return 0;
|
|
4525
|
+
let k = 0;
|
|
4526
|
+
for (let i = 0; i < a.length; i++) {
|
|
4527
|
+
if (!aMatches[i]) continue;
|
|
4528
|
+
while (!bMatches[k]) k++;
|
|
4529
|
+
if (a.charAt(i) !== b.charAt(k)) transpositions++;
|
|
4530
|
+
k++;
|
|
4531
|
+
}
|
|
4532
|
+
const jaro = (matches / a.length + matches / b.length + (matches - transpositions / 2) / matches) / 3;
|
|
4533
|
+
let prefixLength = 0;
|
|
4534
|
+
for (let i = 0; i < Math.min(a.length, b.length); i++) {
|
|
4535
|
+
if (a.charAt(i) === b.charAt(i)) {
|
|
4536
|
+
prefixLength++;
|
|
4537
|
+
} else {
|
|
4538
|
+
break;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
const scalingFactor = 0.1;
|
|
4542
|
+
return jaro + prefixLength * scalingFactor * (1 - jaro);
|
|
4543
|
+
}
|
|
4544
|
+
function calculateSimilarity(toolId, candidateId, description = "") {
|
|
4545
|
+
const lowerToolId = toolId.toLowerCase();
|
|
4546
|
+
const lowerCandidate = candidateId.toLowerCase();
|
|
4547
|
+
const prefix = lowerToolId.split("-")[0];
|
|
4548
|
+
const hasPrefix = lowerToolId.includes("-");
|
|
4549
|
+
const jwScore = jaroWinklerSimilarity(lowerToolId, lowerCandidate);
|
|
4550
|
+
const maxLen = Math.max(lowerToolId.length, lowerCandidate.length);
|
|
4551
|
+
const lvScore = maxLen === 0 ? 1 : 1 - levenshteinDistance(lowerToolId, lowerCandidate) / maxLen;
|
|
4552
|
+
let substringBoost = 0;
|
|
4553
|
+
if (lowerCandidate.includes(lowerToolId) || lowerToolId.includes(lowerCandidate)) {
|
|
4554
|
+
substringBoost = 0.4;
|
|
4555
|
+
}
|
|
4556
|
+
let prefixBoost = 0;
|
|
4557
|
+
if (hasPrefix && lowerCandidate === prefix) {
|
|
4558
|
+
prefixBoost = 0.5;
|
|
4559
|
+
}
|
|
4560
|
+
if (hasPrefix && lowerCandidate.startsWith(prefix + "-")) {
|
|
4561
|
+
prefixBoost = 0.35;
|
|
4562
|
+
}
|
|
4563
|
+
const descMatch = description.toLowerCase().includes(lowerToolId) ? 0.1 : 0;
|
|
4564
|
+
return jwScore * 0.4 + lvScore * 0.25 + substringBoost + prefixBoost + descMatch;
|
|
4565
|
+
}
|
|
4566
|
+
function findSimilarToolIds(toolId, toolIds) {
|
|
4567
|
+
const scored = toolIds.map((id) => ({
|
|
4568
|
+
id,
|
|
4569
|
+
score: calculateSimilarity(toolId, id)
|
|
4570
|
+
}));
|
|
4571
|
+
return scored.filter((item) => item.score > 0.35).sort((a, b) => b.score - a.score).slice(0, 5).map((item) => item.id);
|
|
4572
|
+
}
|
|
3715
4573
|
async function describeTool(args) {
|
|
3716
4574
|
const toolId = args[0];
|
|
3717
4575
|
if (!toolId) {
|
|
@@ -3747,6 +4605,17 @@ async function describeTool(args) {
|
|
|
3747
4605
|
console.log();
|
|
3748
4606
|
} catch (error) {
|
|
3749
4607
|
console.error(`Error: Tool '${toolId}' not found`);
|
|
4608
|
+
try {
|
|
4609
|
+
const allNodeIds = await fetchAllNodeIds(rainfall);
|
|
4610
|
+
const suggestions = findSimilarToolIds(toolId, allNodeIds);
|
|
4611
|
+
if (suggestions.length > 0) {
|
|
4612
|
+
console.error("\nDid you mean:");
|
|
4613
|
+
for (const suggestion of suggestions) {
|
|
4614
|
+
console.error(` \u2022 ${suggestion}`);
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4617
|
+
} catch {
|
|
4618
|
+
}
|
|
3750
4619
|
process.exit(1);
|
|
3751
4620
|
}
|
|
3752
4621
|
}
|
|
@@ -3790,12 +4659,18 @@ Options:
|
|
|
3790
4659
|
-p, --params <json> Tool parameters as JSON string
|
|
3791
4660
|
-f, --file <path> Read parameters from JSON file
|
|
3792
4661
|
--raw Output raw JSON (no formatting)
|
|
4662
|
+
--table Output as table (if applicable)
|
|
4663
|
+
--terminal Output for terminal consumption (minimal formatting)
|
|
3793
4664
|
--<key> <value> Pass individual parameters (e.g., --query "AI news")
|
|
4665
|
+
Arrays: --tickers AAPL,GOOGL (comma-separated)
|
|
4666
|
+
Numbers: --count 42
|
|
4667
|
+
Booleans: --enabled true
|
|
3794
4668
|
|
|
3795
4669
|
Examples:
|
|
3796
4670
|
rainfall run figma-users-getMe
|
|
3797
4671
|
rainfall run exa-web-search -p '{"query": "AI news"}'
|
|
3798
4672
|
rainfall run exa-web-search --query "AI news"
|
|
4673
|
+
rainfall run finviz-quotes --tickers AAPL,GOOGL,MSFT
|
|
3799
4674
|
rainfall run github-create-issue --owner facebook --repo react --title "Bug"
|
|
3800
4675
|
rainfall run github-create-issue -f ./issue.json
|
|
3801
4676
|
echo '{"query": "hello"}' | rainfall run exa-web-search
|
|
@@ -3804,6 +4679,7 @@ Examples:
|
|
|
3804
4679
|
}
|
|
3805
4680
|
let params = {};
|
|
3806
4681
|
const rawArgs = [];
|
|
4682
|
+
let displayMode = "pretty";
|
|
3807
4683
|
for (let i = 1; i < args.length; i++) {
|
|
3808
4684
|
const arg = args[i];
|
|
3809
4685
|
if (arg === "--params" || arg === "-p") {
|
|
@@ -3831,16 +4707,17 @@ Examples:
|
|
|
3831
4707
|
process.exit(1);
|
|
3832
4708
|
}
|
|
3833
4709
|
} else if (arg === "--raw") {
|
|
4710
|
+
displayMode = "raw";
|
|
4711
|
+
} else if (arg === "--table") {
|
|
4712
|
+
displayMode = "table";
|
|
4713
|
+
} else if (arg === "--terminal") {
|
|
4714
|
+
displayMode = "terminal";
|
|
3834
4715
|
} else if (arg.startsWith("--")) {
|
|
3835
4716
|
const key = arg.slice(2);
|
|
3836
4717
|
const value = args[++i];
|
|
3837
4718
|
if (value === void 0) {
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
}
|
|
3841
|
-
try {
|
|
3842
|
-
params[key] = JSON.parse(value);
|
|
3843
|
-
} catch {
|
|
4719
|
+
params[key] = true;
|
|
4720
|
+
} else {
|
|
3844
4721
|
params[key] = value;
|
|
3845
4722
|
}
|
|
3846
4723
|
} else {
|
|
@@ -3882,30 +4759,108 @@ Examples:
|
|
|
3882
4759
|
}
|
|
3883
4760
|
}
|
|
3884
4761
|
const rainfall = getRainfall();
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
4762
|
+
let toolSchema;
|
|
4763
|
+
try {
|
|
4764
|
+
const fullSchema = await rainfall.getToolSchema(toolId);
|
|
4765
|
+
toolSchema = {
|
|
4766
|
+
parameters: fullSchema.parameters
|
|
4767
|
+
};
|
|
4768
|
+
} catch {
|
|
4769
|
+
}
|
|
4770
|
+
const cliFlags = /* @__PURE__ */ new Set(["--params", "-p", "--file", "-f", "--raw", "--table", "--terminal"]);
|
|
4771
|
+
const toolArgs = args.slice(1).filter((arg, i, arr) => {
|
|
4772
|
+
if (cliFlags.has(arg)) {
|
|
4773
|
+
return false;
|
|
4774
|
+
}
|
|
4775
|
+
if (i > 0 && cliFlags.has(arr[i - 1])) {
|
|
4776
|
+
return false;
|
|
4777
|
+
}
|
|
4778
|
+
return true;
|
|
4779
|
+
});
|
|
4780
|
+
if (toolSchema?.parameters) {
|
|
4781
|
+
const { parseCliArgs: parseCliArgs2 } = await Promise.resolve().then(() => (init_param_parser(), param_parser_exports));
|
|
4782
|
+
const parsedParams = parseCliArgs2(
|
|
4783
|
+
toolArgs,
|
|
4784
|
+
{
|
|
4785
|
+
name: toolId,
|
|
4786
|
+
description: "",
|
|
4787
|
+
category: "",
|
|
4788
|
+
parameters: toolSchema.parameters
|
|
3895
4789
|
}
|
|
3896
|
-
|
|
4790
|
+
);
|
|
4791
|
+
params = { ...parsedParams, ...params };
|
|
4792
|
+
}
|
|
4793
|
+
if (rawArgs.length === 1 && Object.keys(params).length === 0 && toolSchema?.parameters) {
|
|
4794
|
+
const paramEntries = Object.entries(toolSchema.parameters);
|
|
4795
|
+
const requiredParams = paramEntries.filter(([, p]) => !p.optional);
|
|
4796
|
+
if (requiredParams.length === 1) {
|
|
4797
|
+
const [paramName, paramSchema] = requiredParams[0];
|
|
4798
|
+
const { parseValue: parseValue2 } = await Promise.resolve().then(() => (init_param_parser(), param_parser_exports));
|
|
4799
|
+
params = { [paramName]: parseValue2(rawArgs[0], paramSchema) };
|
|
3897
4800
|
}
|
|
3898
4801
|
}
|
|
4802
|
+
const handler = globalHandlerRegistry.findHandler(toolId);
|
|
4803
|
+
const toolContext = {
|
|
4804
|
+
rainfall,
|
|
4805
|
+
toolId,
|
|
4806
|
+
params,
|
|
4807
|
+
args: rawArgs,
|
|
4808
|
+
flags: { raw: displayMode === "raw" }
|
|
4809
|
+
};
|
|
3899
4810
|
try {
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
4811
|
+
let executionParams = params;
|
|
4812
|
+
let preflightContext;
|
|
4813
|
+
let skipExecution;
|
|
4814
|
+
if (handler?.preflight) {
|
|
4815
|
+
const preflightResult = await handler.preflight(toolContext);
|
|
4816
|
+
if (preflightResult) {
|
|
4817
|
+
if (preflightResult.skipExecution !== void 0) {
|
|
4818
|
+
skipExecution = preflightResult.skipExecution;
|
|
4819
|
+
}
|
|
4820
|
+
if (preflightResult.params) {
|
|
4821
|
+
executionParams = preflightResult.params;
|
|
4822
|
+
}
|
|
4823
|
+
preflightContext = preflightResult.context;
|
|
4824
|
+
}
|
|
4825
|
+
}
|
|
4826
|
+
let result;
|
|
4827
|
+
if (skipExecution !== void 0) {
|
|
4828
|
+
result = skipExecution;
|
|
3903
4829
|
} else {
|
|
3904
|
-
|
|
4830
|
+
result = await rainfall.executeTool(toolId, executionParams);
|
|
4831
|
+
}
|
|
4832
|
+
const postflightContext = {
|
|
4833
|
+
...toolContext,
|
|
4834
|
+
result,
|
|
4835
|
+
preflightContext
|
|
4836
|
+
};
|
|
4837
|
+
if (handler?.postflight) {
|
|
4838
|
+
await handler.postflight(postflightContext);
|
|
4839
|
+
}
|
|
4840
|
+
let displayed = false;
|
|
4841
|
+
if (handler?.display) {
|
|
4842
|
+
displayed = await handler.display({ ...postflightContext, flags: { ...toolContext.flags, mode: displayMode } });
|
|
4843
|
+
}
|
|
4844
|
+
if (!displayed) {
|
|
4845
|
+
const output = await formatResult(result, { mode: displayMode });
|
|
4846
|
+
console.log(output);
|
|
3905
4847
|
}
|
|
3906
4848
|
} catch (error) {
|
|
3907
4849
|
const message = error instanceof Error ? error.message : String(error);
|
|
3908
4850
|
console.error(`Error: ${message}`);
|
|
4851
|
+
if (message.toLowerCase().includes("not found") || message.toLowerCase().includes("not found")) {
|
|
4852
|
+
try {
|
|
4853
|
+
const allNodeIds = await fetchAllNodeIds(rainfall);
|
|
4854
|
+
const suggestions = findSimilarToolIds(toolId, allNodeIds);
|
|
4855
|
+
if (suggestions.length > 0) {
|
|
4856
|
+
console.error("\nDid you mean:");
|
|
4857
|
+
for (const suggestion of suggestions) {
|
|
4858
|
+
console.error(` \u2022 ${suggestion}`);
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
} catch {
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
3909
4864
|
process.exit(1);
|
|
3910
4865
|
}
|
|
3911
4866
|
}
|
|
@@ -4022,7 +4977,7 @@ async function upgrade() {
|
|
|
4022
4977
|
console.log(`Running: ${command} ${args.join(" ")}`);
|
|
4023
4978
|
console.log();
|
|
4024
4979
|
return new Promise((resolve, reject) => {
|
|
4025
|
-
const child = (0,
|
|
4980
|
+
const child = (0, import_child_process2.spawn)(command, args, {
|
|
4026
4981
|
stdio: "inherit",
|
|
4027
4982
|
shell: true
|
|
4028
4983
|
});
|