@rainfall-devkit/sdk 0.2.2 → 0.2.4
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-2FYYTIJQ.mjs +993 -0
- 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-LJQEO3CY.mjs +150 -0
- package/dist/chunk-S7MOQCV4.mjs +137 -0
- package/dist/chunk-XHPFY5MH.mjs +132 -0
- package/dist/cli/index.js +1128 -49
- package/dist/cli/index.mjs +370 -30
- package/dist/daemon/index.d.mts +3 -3
- package/dist/daemon/index.d.ts +3 -3
- package/dist/daemon/index.js +416 -130
- 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 +896 -113
- package/dist/index.mjs +18 -6
- package/dist/listeners-BBNBsJCk.d.ts +372 -0
- package/dist/listeners-BCEypw1u.d.ts +372 -0
- package/dist/listeners-BGdrWpkP.d.mts +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 +410 -102
- 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-BUVNdBc7.d.mts +1167 -0
- package/dist/sdk-BUVNdBc7.d.ts +1167 -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 +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
createEdgeNodeSecurity
|
|
4
|
-
|
|
3
|
+
createEdgeNodeSecurity,
|
|
4
|
+
globalHandlerRegistry
|
|
5
|
+
} from "../chunk-6FXRLPLR.mjs";
|
|
5
6
|
import {
|
|
6
7
|
Rainfall
|
|
7
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-2FYYTIJQ.mjs";
|
|
9
|
+
import "../chunk-LJQEO3CY.mjs";
|
|
10
|
+
import {
|
|
11
|
+
formatResult
|
|
12
|
+
} from "../chunk-XHPFY5MH.mjs";
|
|
8
13
|
import {
|
|
9
14
|
getConfigDir,
|
|
10
15
|
loadConfig,
|
|
@@ -49,6 +54,7 @@ Commands:
|
|
|
49
54
|
config llm Show LLM configuration
|
|
50
55
|
|
|
51
56
|
edge generate-keys Generate key pair for edge node encryption
|
|
57
|
+
edge register <proc-node-id> Register a proc node for edge execution
|
|
52
58
|
edge status Show edge node security status
|
|
53
59
|
|
|
54
60
|
version Show version information
|
|
@@ -66,7 +72,12 @@ Options for 'run':
|
|
|
66
72
|
--params, -p <json> Tool parameters as JSON
|
|
67
73
|
--file, -f <path> Read parameters from file
|
|
68
74
|
--raw Output raw JSON
|
|
75
|
+
--table Output as table (if applicable)
|
|
76
|
+
--terminal Output for terminal consumption (minimal formatting)
|
|
69
77
|
--<key> <value> Pass individual parameters (e.g., --query "AI news")
|
|
78
|
+
Arrays: --tickers AAPL,GOOGL (comma-separated)
|
|
79
|
+
Numbers: --count 42
|
|
80
|
+
Booleans: --enabled true
|
|
70
81
|
|
|
71
82
|
Options for 'daemon start':
|
|
72
83
|
--port <port> WebSocket port (default: 8765)
|
|
@@ -82,6 +93,7 @@ Examples:
|
|
|
82
93
|
rainfall tools describe github-create-issue
|
|
83
94
|
rainfall run exa-web-search -p '{"query": "AI news"}'
|
|
84
95
|
rainfall run exa-web-search --query "AI news"
|
|
96
|
+
rainfall run finviz-quotes --tickers AAPL,GOOGL,MSFT
|
|
85
97
|
rainfall run github-create-issue --owner facebook --repo react --title "Bug"
|
|
86
98
|
rainfall run article-summarize -f ./article.json
|
|
87
99
|
rainfall daemon start
|
|
@@ -99,6 +111,24 @@ function getRainfall() {
|
|
|
99
111
|
baseUrl: config.baseUrl
|
|
100
112
|
});
|
|
101
113
|
}
|
|
114
|
+
async function fetchAllNodeIds(rainfall) {
|
|
115
|
+
try {
|
|
116
|
+
const client = rainfall.getClient();
|
|
117
|
+
const subscriberId = await client.ensureSubscriberId();
|
|
118
|
+
const result = await client.request(
|
|
119
|
+
`/olympic/subscribers/${subscriberId}/nodes/_utils/node-list`
|
|
120
|
+
);
|
|
121
|
+
if (result.keys && Array.isArray(result.keys)) {
|
|
122
|
+
return result.keys;
|
|
123
|
+
}
|
|
124
|
+
if (result.nodes && Array.isArray(result.nodes)) {
|
|
125
|
+
return result.nodes.map((n) => n.id);
|
|
126
|
+
}
|
|
127
|
+
return [];
|
|
128
|
+
} catch {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
102
132
|
async function authLogin(args) {
|
|
103
133
|
const apiKey = args[0] || process.env.RAINFALL_API_KEY;
|
|
104
134
|
if (!apiKey) {
|
|
@@ -185,6 +215,100 @@ function formatSchema(obj, indent = 0) {
|
|
|
185
215
|
}
|
|
186
216
|
return lines.join("\n");
|
|
187
217
|
}
|
|
218
|
+
function levenshteinDistance(a, b) {
|
|
219
|
+
const matrix = [];
|
|
220
|
+
for (let i = 0; i <= b.length; i++) {
|
|
221
|
+
matrix[i] = [i];
|
|
222
|
+
}
|
|
223
|
+
for (let j = 0; j <= a.length; j++) {
|
|
224
|
+
matrix[0][j] = j;
|
|
225
|
+
}
|
|
226
|
+
for (let i = 1; i <= b.length; i++) {
|
|
227
|
+
for (let j = 1; j <= a.length; j++) {
|
|
228
|
+
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
229
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
230
|
+
} else {
|
|
231
|
+
matrix[i][j] = Math.min(
|
|
232
|
+
matrix[i - 1][j - 1] + 1,
|
|
233
|
+
// substitution
|
|
234
|
+
matrix[i][j - 1] + 1,
|
|
235
|
+
// insertion
|
|
236
|
+
matrix[i - 1][j] + 1
|
|
237
|
+
// deletion
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return matrix[b.length][a.length];
|
|
243
|
+
}
|
|
244
|
+
function jaroWinklerSimilarity(a, b) {
|
|
245
|
+
if (a === b) return 1;
|
|
246
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
247
|
+
const matchDistance = Math.floor(Math.max(a.length, b.length) / 2) - 1;
|
|
248
|
+
const aMatches = new Array(a.length).fill(false);
|
|
249
|
+
const bMatches = new Array(b.length).fill(false);
|
|
250
|
+
let matches = 0;
|
|
251
|
+
let transpositions = 0;
|
|
252
|
+
for (let i = 0; i < a.length; i++) {
|
|
253
|
+
const start = Math.max(0, i - matchDistance);
|
|
254
|
+
const end = Math.min(i + matchDistance + 1, b.length);
|
|
255
|
+
for (let j = start; j < end; j++) {
|
|
256
|
+
if (bMatches[j] || a.charAt(i) !== b.charAt(j)) continue;
|
|
257
|
+
aMatches[i] = true;
|
|
258
|
+
bMatches[j] = true;
|
|
259
|
+
matches++;
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (matches === 0) return 0;
|
|
264
|
+
let k = 0;
|
|
265
|
+
for (let i = 0; i < a.length; i++) {
|
|
266
|
+
if (!aMatches[i]) continue;
|
|
267
|
+
while (!bMatches[k]) k++;
|
|
268
|
+
if (a.charAt(i) !== b.charAt(k)) transpositions++;
|
|
269
|
+
k++;
|
|
270
|
+
}
|
|
271
|
+
const jaro = (matches / a.length + matches / b.length + (matches - transpositions / 2) / matches) / 3;
|
|
272
|
+
let prefixLength = 0;
|
|
273
|
+
for (let i = 0; i < Math.min(a.length, b.length); i++) {
|
|
274
|
+
if (a.charAt(i) === b.charAt(i)) {
|
|
275
|
+
prefixLength++;
|
|
276
|
+
} else {
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const scalingFactor = 0.1;
|
|
281
|
+
return jaro + prefixLength * scalingFactor * (1 - jaro);
|
|
282
|
+
}
|
|
283
|
+
function calculateSimilarity(toolId, candidateId, description = "") {
|
|
284
|
+
const lowerToolId = toolId.toLowerCase();
|
|
285
|
+
const lowerCandidate = candidateId.toLowerCase();
|
|
286
|
+
const prefix = lowerToolId.split("-")[0];
|
|
287
|
+
const hasPrefix = lowerToolId.includes("-");
|
|
288
|
+
const jwScore = jaroWinklerSimilarity(lowerToolId, lowerCandidate);
|
|
289
|
+
const maxLen = Math.max(lowerToolId.length, lowerCandidate.length);
|
|
290
|
+
const lvScore = maxLen === 0 ? 1 : 1 - levenshteinDistance(lowerToolId, lowerCandidate) / maxLen;
|
|
291
|
+
let substringBoost = 0;
|
|
292
|
+
if (lowerCandidate.includes(lowerToolId) || lowerToolId.includes(lowerCandidate)) {
|
|
293
|
+
substringBoost = 0.4;
|
|
294
|
+
}
|
|
295
|
+
let prefixBoost = 0;
|
|
296
|
+
if (hasPrefix && lowerCandidate === prefix) {
|
|
297
|
+
prefixBoost = 0.5;
|
|
298
|
+
}
|
|
299
|
+
if (hasPrefix && lowerCandidate.startsWith(prefix + "-")) {
|
|
300
|
+
prefixBoost = 0.35;
|
|
301
|
+
}
|
|
302
|
+
const descMatch = description.toLowerCase().includes(lowerToolId) ? 0.1 : 0;
|
|
303
|
+
return jwScore * 0.4 + lvScore * 0.25 + substringBoost + prefixBoost + descMatch;
|
|
304
|
+
}
|
|
305
|
+
function findSimilarToolIds(toolId, toolIds) {
|
|
306
|
+
const scored = toolIds.map((id) => ({
|
|
307
|
+
id,
|
|
308
|
+
score: calculateSimilarity(toolId, id)
|
|
309
|
+
}));
|
|
310
|
+
return scored.filter((item) => item.score > 0.35).sort((a, b) => b.score - a.score).slice(0, 5).map((item) => item.id);
|
|
311
|
+
}
|
|
188
312
|
async function describeTool(args) {
|
|
189
313
|
const toolId = args[0];
|
|
190
314
|
if (!toolId) {
|
|
@@ -220,6 +344,17 @@ async function describeTool(args) {
|
|
|
220
344
|
console.log();
|
|
221
345
|
} catch (error) {
|
|
222
346
|
console.error(`Error: Tool '${toolId}' not found`);
|
|
347
|
+
try {
|
|
348
|
+
const allNodeIds = await fetchAllNodeIds(rainfall);
|
|
349
|
+
const suggestions = findSimilarToolIds(toolId, allNodeIds);
|
|
350
|
+
if (suggestions.length > 0) {
|
|
351
|
+
console.error("\nDid you mean:");
|
|
352
|
+
for (const suggestion of suggestions) {
|
|
353
|
+
console.error(` \u2022 ${suggestion}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
} catch {
|
|
357
|
+
}
|
|
223
358
|
process.exit(1);
|
|
224
359
|
}
|
|
225
360
|
}
|
|
@@ -263,20 +398,30 @@ Options:
|
|
|
263
398
|
-p, --params <json> Tool parameters as JSON string
|
|
264
399
|
-f, --file <path> Read parameters from JSON file
|
|
265
400
|
--raw Output raw JSON (no formatting)
|
|
401
|
+
--table Output as table (if applicable)
|
|
402
|
+
--terminal Output for terminal consumption (minimal formatting)
|
|
403
|
+
--target-edge <id> Execute on specific edge node (for cross-node jobs)
|
|
266
404
|
--<key> <value> Pass individual parameters (e.g., --query "AI news")
|
|
405
|
+
Arrays: --tickers AAPL,GOOGL (comma-separated)
|
|
406
|
+
Numbers: --count 42
|
|
407
|
+
Booleans: --enabled true
|
|
267
408
|
|
|
268
409
|
Examples:
|
|
269
410
|
rainfall run figma-users-getMe
|
|
270
411
|
rainfall run exa-web-search -p '{"query": "AI news"}'
|
|
271
412
|
rainfall run exa-web-search --query "AI news"
|
|
413
|
+
rainfall run finviz-quotes --tickers AAPL,GOOGL,MSFT
|
|
272
414
|
rainfall run github-create-issue --owner facebook --repo react --title "Bug"
|
|
273
415
|
rainfall run github-create-issue -f ./issue.json
|
|
416
|
+
rainfall run exa-web-search --query "latest AI" --target-edge <edge-id>
|
|
274
417
|
echo '{"query": "hello"}' | rainfall run exa-web-search
|
|
275
418
|
`);
|
|
276
419
|
return;
|
|
277
420
|
}
|
|
278
421
|
let params = {};
|
|
279
422
|
const rawArgs = [];
|
|
423
|
+
let displayMode = "pretty";
|
|
424
|
+
let targetEdge;
|
|
280
425
|
for (let i = 1; i < args.length; i++) {
|
|
281
426
|
const arg = args[i];
|
|
282
427
|
if (arg === "--params" || arg === "-p") {
|
|
@@ -304,16 +449,23 @@ Examples:
|
|
|
304
449
|
process.exit(1);
|
|
305
450
|
}
|
|
306
451
|
} else if (arg === "--raw") {
|
|
452
|
+
displayMode = "raw";
|
|
453
|
+
} else if (arg === "--table") {
|
|
454
|
+
displayMode = "table";
|
|
455
|
+
} else if (arg === "--terminal") {
|
|
456
|
+
displayMode = "terminal";
|
|
457
|
+
} else if (arg === "--target-edge") {
|
|
458
|
+
targetEdge = args[++i];
|
|
459
|
+
if (!targetEdge) {
|
|
460
|
+
console.error("Error: --target-edge requires an edge node ID");
|
|
461
|
+
process.exit(1);
|
|
462
|
+
}
|
|
307
463
|
} else if (arg.startsWith("--")) {
|
|
308
464
|
const key = arg.slice(2);
|
|
309
465
|
const value = args[++i];
|
|
310
466
|
if (value === void 0) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
314
|
-
try {
|
|
315
|
-
params[key] = JSON.parse(value);
|
|
316
|
-
} catch {
|
|
467
|
+
params[key] = true;
|
|
468
|
+
} else {
|
|
317
469
|
params[key] = value;
|
|
318
470
|
}
|
|
319
471
|
} else {
|
|
@@ -355,30 +507,110 @@ Examples:
|
|
|
355
507
|
}
|
|
356
508
|
}
|
|
357
509
|
const rainfall = getRainfall();
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
510
|
+
let toolSchema;
|
|
511
|
+
try {
|
|
512
|
+
const fullSchema = await rainfall.getToolSchema(toolId);
|
|
513
|
+
toolSchema = {
|
|
514
|
+
parameters: fullSchema.parameters
|
|
515
|
+
};
|
|
516
|
+
} catch {
|
|
517
|
+
}
|
|
518
|
+
const cliFlags = /* @__PURE__ */ new Set(["--params", "-p", "--file", "-f", "--raw", "--table", "--terminal", "--target-edge"]);
|
|
519
|
+
const toolArgs = args.slice(1).filter((arg, i, arr) => {
|
|
520
|
+
if (cliFlags.has(arg)) {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
if (i > 0 && cliFlags.has(arr[i - 1])) {
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
return true;
|
|
527
|
+
});
|
|
528
|
+
if (toolSchema?.parameters) {
|
|
529
|
+
const { parseCliArgs } = await import("../param-parser-PAKCNDBX.mjs");
|
|
530
|
+
const parsedParams = parseCliArgs(
|
|
531
|
+
toolArgs,
|
|
532
|
+
{
|
|
533
|
+
name: toolId,
|
|
534
|
+
description: "",
|
|
535
|
+
category: "",
|
|
536
|
+
parameters: toolSchema.parameters
|
|
368
537
|
}
|
|
369
|
-
|
|
538
|
+
);
|
|
539
|
+
params = { ...parsedParams, ...params };
|
|
540
|
+
}
|
|
541
|
+
if (rawArgs.length === 1 && Object.keys(params).length === 0 && toolSchema?.parameters) {
|
|
542
|
+
const paramEntries = Object.entries(toolSchema.parameters);
|
|
543
|
+
const requiredParams = paramEntries.filter(([, p]) => !p.optional);
|
|
544
|
+
if (requiredParams.length === 1) {
|
|
545
|
+
const [paramName, paramSchema] = requiredParams[0];
|
|
546
|
+
const { parseValue } = await import("../param-parser-PAKCNDBX.mjs");
|
|
547
|
+
params = { [paramName]: parseValue(rawArgs[0], paramSchema) };
|
|
370
548
|
}
|
|
371
549
|
}
|
|
550
|
+
const handler = globalHandlerRegistry.findHandler(toolId);
|
|
551
|
+
const toolContext = {
|
|
552
|
+
rainfall,
|
|
553
|
+
toolId,
|
|
554
|
+
params,
|
|
555
|
+
args: rawArgs,
|
|
556
|
+
flags: { raw: displayMode === "raw" }
|
|
557
|
+
};
|
|
372
558
|
try {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
559
|
+
let executionParams = params;
|
|
560
|
+
let preflightContext;
|
|
561
|
+
let skipExecution;
|
|
562
|
+
if (handler?.preflight) {
|
|
563
|
+
const preflightResult = await handler.preflight(toolContext);
|
|
564
|
+
if (preflightResult) {
|
|
565
|
+
if (preflightResult.skipExecution !== void 0) {
|
|
566
|
+
skipExecution = preflightResult.skipExecution;
|
|
567
|
+
}
|
|
568
|
+
if (preflightResult.params) {
|
|
569
|
+
executionParams = preflightResult.params;
|
|
570
|
+
}
|
|
571
|
+
preflightContext = preflightResult.context;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
let result;
|
|
575
|
+
if (skipExecution !== void 0) {
|
|
576
|
+
result = skipExecution;
|
|
577
|
+
} else if (targetEdge) {
|
|
578
|
+
result = await rainfall.executeTool(toolId, executionParams, { targetEdge });
|
|
376
579
|
} else {
|
|
377
|
-
|
|
580
|
+
result = await rainfall.executeTool(toolId, executionParams);
|
|
581
|
+
}
|
|
582
|
+
const postflightContext = {
|
|
583
|
+
...toolContext,
|
|
584
|
+
result,
|
|
585
|
+
preflightContext
|
|
586
|
+
};
|
|
587
|
+
if (handler?.postflight) {
|
|
588
|
+
await handler.postflight(postflightContext);
|
|
589
|
+
}
|
|
590
|
+
let displayed = false;
|
|
591
|
+
if (handler?.display) {
|
|
592
|
+
displayed = await handler.display({ ...postflightContext, flags: { ...toolContext.flags, mode: displayMode } });
|
|
593
|
+
}
|
|
594
|
+
if (!displayed) {
|
|
595
|
+
const output = await formatResult(result, { mode: displayMode });
|
|
596
|
+
console.log(output);
|
|
378
597
|
}
|
|
379
598
|
} catch (error) {
|
|
380
599
|
const message = error instanceof Error ? error.message : String(error);
|
|
381
600
|
console.error(`Error: ${message}`);
|
|
601
|
+
if (message.toLowerCase().includes("not found") || message.toLowerCase().includes("not found")) {
|
|
602
|
+
try {
|
|
603
|
+
const allNodeIds = await fetchAllNodeIds(rainfall);
|
|
604
|
+
const suggestions = findSimilarToolIds(toolId, allNodeIds);
|
|
605
|
+
if (suggestions.length > 0) {
|
|
606
|
+
console.error("\nDid you mean:");
|
|
607
|
+
for (const suggestion of suggestions) {
|
|
608
|
+
console.error(` \u2022 ${suggestion}`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
} catch {
|
|
612
|
+
}
|
|
613
|
+
}
|
|
382
614
|
process.exit(1);
|
|
383
615
|
}
|
|
384
616
|
}
|
|
@@ -671,7 +903,7 @@ async function edgeGenerateKeys() {
|
|
|
671
903
|
console.log(" Private:", privateKeyPath);
|
|
672
904
|
console.log("\n\u{1F4CB} To register this edge node:");
|
|
673
905
|
console.log(" 1. Copy the public key above");
|
|
674
|
-
console.log(" 2. Register with: rainfall edge register <public-key>");
|
|
906
|
+
console.log(" 2. Register proc node with: rainfall edge register <proc-node-id> --public-key <key>");
|
|
675
907
|
console.log(" 3. The backend will return an edgeNodeSecret (JWT)");
|
|
676
908
|
console.log(" 4. Store the secret securely - it expires in 30 days");
|
|
677
909
|
} catch (error) {
|
|
@@ -679,6 +911,98 @@ async function edgeGenerateKeys() {
|
|
|
679
911
|
process.exit(1);
|
|
680
912
|
}
|
|
681
913
|
}
|
|
914
|
+
async function edgeRegister(args) {
|
|
915
|
+
const procNodeId = args[0];
|
|
916
|
+
if (!procNodeId) {
|
|
917
|
+
console.error("Error: Proc node ID required");
|
|
918
|
+
console.error("\nUsage: rainfall edge register <proc-node-id> [options]");
|
|
919
|
+
console.error("\nOptions:");
|
|
920
|
+
console.error(" --public-key <key> Public key for encryption (optional)");
|
|
921
|
+
console.error(" --list <id1,id2,...> Register multiple proc nodes (comma-separated)");
|
|
922
|
+
console.error("\nExamples:");
|
|
923
|
+
console.error(" rainfall edge register exa-web-search");
|
|
924
|
+
console.error(' rainfall edge register exa-web-search --public-key "base64key..."');
|
|
925
|
+
console.error(' rainfall edge register --list "exa-web-search,github-create-issue"');
|
|
926
|
+
process.exit(1);
|
|
927
|
+
}
|
|
928
|
+
const rainfall = getRainfall();
|
|
929
|
+
const config = loadConfig();
|
|
930
|
+
let publicKey;
|
|
931
|
+
let procNodeIds = [procNodeId];
|
|
932
|
+
for (let i = 1; i < args.length; i++) {
|
|
933
|
+
const arg = args[i];
|
|
934
|
+
if (arg === "--public-key" || arg === "-k") {
|
|
935
|
+
publicKey = args[++i];
|
|
936
|
+
} else if (arg === "--list" || arg === "-l") {
|
|
937
|
+
const list = args[++i];
|
|
938
|
+
if (list) {
|
|
939
|
+
procNodeIds = list.split(",").map((id) => id.trim());
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
if (!publicKey) {
|
|
944
|
+
const configDir = getConfigDir();
|
|
945
|
+
const keysDir = join(configDir, "keys");
|
|
946
|
+
const publicKeyPath = join(keysDir, "edge-node.pub");
|
|
947
|
+
if (existsSync(publicKeyPath)) {
|
|
948
|
+
publicKey = readFileSync(publicKeyPath, "utf-8");
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
console.log(`\u{1F310} Registering ${procNodeIds.length} proc node(s) for edge execution...
|
|
952
|
+
`);
|
|
953
|
+
try {
|
|
954
|
+
let edgeNodeId = config.edgeNodeId;
|
|
955
|
+
if (!edgeNodeId) {
|
|
956
|
+
console.log("\u{1F4E1} Registering edge node with backend...");
|
|
957
|
+
const registerResult = await rainfall.executeTool("register-edge-node", {
|
|
958
|
+
hostname: process.env.HOSTNAME || "local-edge",
|
|
959
|
+
capabilities: procNodeIds,
|
|
960
|
+
version: "1.0.0",
|
|
961
|
+
metadata: {
|
|
962
|
+
publicKey: publicKey || void 0,
|
|
963
|
+
source: "rainfall-devkit-cli"
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
edgeNodeId = registerResult.edgeNodeId;
|
|
967
|
+
console.log(` Edge node registered: ${edgeNodeId}`);
|
|
968
|
+
} else {
|
|
969
|
+
console.log(` Using existing edge node: ${edgeNodeId}`);
|
|
970
|
+
}
|
|
971
|
+
console.log("\n\u{1F4E1} Registering proc nodes...");
|
|
972
|
+
const result = await rainfall.executeTool("register-proc-edge-nodes", {
|
|
973
|
+
edgeNodeId,
|
|
974
|
+
procNodeIds,
|
|
975
|
+
publicKey,
|
|
976
|
+
hostname: process.env.HOSTNAME || "local-edge"
|
|
977
|
+
});
|
|
978
|
+
if (!result.success) {
|
|
979
|
+
console.error("\u274C Registration failed");
|
|
980
|
+
process.exit(1);
|
|
981
|
+
}
|
|
982
|
+
config.edgeNodeId = result.edgeNodeId;
|
|
983
|
+
config.edgeNodeSecret = result.edgeNodeSecret;
|
|
984
|
+
config.edgeNodeKeysPath = join(getConfigDir(), "keys");
|
|
985
|
+
saveConfig(config);
|
|
986
|
+
console.log("\u2705 Proc node(s) registered successfully!\n");
|
|
987
|
+
console.log("Edge Node ID:", result.edgeNodeId);
|
|
988
|
+
console.log("Proc Nodes Registered:");
|
|
989
|
+
for (const nodeId of result.registeredProcNodes) {
|
|
990
|
+
console.log(` \u2022 ${nodeId}`);
|
|
991
|
+
}
|
|
992
|
+
console.log("\n\u{1F510} Edge node secret stored in config.");
|
|
993
|
+
console.log(" This secret is used for authentication with the backend.");
|
|
994
|
+
console.log("\n\u{1F4CB} You can now run tools on this edge node:");
|
|
995
|
+
console.log(` rainfall run ${procNodeIds[0]} --target-edge ${result.edgeNodeId}`);
|
|
996
|
+
} catch (error) {
|
|
997
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
998
|
+
console.error("\u274C Failed to register proc node:", message);
|
|
999
|
+
if (message.includes("not found") || message.includes("does not exist")) {
|
|
1000
|
+
console.error("\n\u{1F4A1} The backend may not have the registration tools yet.");
|
|
1001
|
+
console.error(" Make sure you are running the latest version of Rainyday.");
|
|
1002
|
+
}
|
|
1003
|
+
process.exit(1);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
682
1006
|
async function edgeStatus() {
|
|
683
1007
|
const configDir = getConfigDir();
|
|
684
1008
|
const keysDir = join(configDir, "keys");
|
|
@@ -696,23 +1020,36 @@ async function edgeStatus() {
|
|
|
696
1020
|
console.log(" " + publicKey.substring(0, 50) + "...");
|
|
697
1021
|
}
|
|
698
1022
|
const config = loadConfig();
|
|
1023
|
+
console.log("\nRegistration:");
|
|
699
1024
|
if (config.edgeNodeId) {
|
|
700
|
-
console.log("\nRegistration:");
|
|
701
1025
|
console.log(" Edge Node ID:", config.edgeNodeId);
|
|
1026
|
+
} else {
|
|
1027
|
+
console.log(" Edge Node ID: \u274C Not registered");
|
|
702
1028
|
}
|
|
703
1029
|
if (config.edgeNodeSecret) {
|
|
704
|
-
console.log(" JWT Secret: \u2705 Present
|
|
1030
|
+
console.log(" JWT Secret: \u2705 Present");
|
|
1031
|
+
const masked = config.edgeNodeSecret.substring(0, 10) + "..." + config.edgeNodeSecret.substring(config.edgeNodeSecret.length - 4);
|
|
1032
|
+
console.log(" (" + masked + ")");
|
|
705
1033
|
} else {
|
|
706
1034
|
console.log(" JWT Secret: \u274C Not configured");
|
|
707
1035
|
}
|
|
1036
|
+
if (config.procNodeIds && config.procNodeIds.length > 0) {
|
|
1037
|
+
console.log("\nRegistered Proc Nodes:");
|
|
1038
|
+
for (const nodeId of config.procNodeIds) {
|
|
1039
|
+
console.log(` \u2022 ${nodeId}`);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
708
1042
|
console.log("\n\u{1F4DA} Next steps:");
|
|
709
1043
|
if (!hasPublicKey) {
|
|
710
1044
|
console.log(" 1. Run: rainfall edge generate-keys");
|
|
1045
|
+
console.log(" 2. Run: rainfall edge register <proc-node-id>");
|
|
711
1046
|
} else if (!config.edgeNodeSecret) {
|
|
712
|
-
console.log(" 1. Register your
|
|
713
|
-
console.log("
|
|
1047
|
+
console.log(" 1. Register your proc node:");
|
|
1048
|
+
console.log(" rainfall edge register exa-web-search");
|
|
714
1049
|
} else {
|
|
715
1050
|
console.log(" Edge node is configured and ready for secure operation");
|
|
1051
|
+
console.log(" Run tools on this edge node:");
|
|
1052
|
+
console.log(` rainfall run <tool> --target-edge ${config.edgeNodeId}`);
|
|
716
1053
|
}
|
|
717
1054
|
}
|
|
718
1055
|
async function main() {
|
|
@@ -825,12 +1162,15 @@ async function main() {
|
|
|
825
1162
|
case "generate-keys":
|
|
826
1163
|
await edgeGenerateKeys();
|
|
827
1164
|
break;
|
|
1165
|
+
case "register":
|
|
1166
|
+
await edgeRegister(rest);
|
|
1167
|
+
break;
|
|
828
1168
|
case "status":
|
|
829
1169
|
await edgeStatus();
|
|
830
1170
|
break;
|
|
831
1171
|
default:
|
|
832
1172
|
console.error("Error: Unknown edge subcommand");
|
|
833
|
-
console.error("\nUsage: rainfall edge <generate-keys|status>");
|
|
1173
|
+
console.error("\nUsage: rainfall edge <generate-keys|register|status>");
|
|
834
1174
|
process.exit(1);
|
|
835
1175
|
}
|
|
836
1176
|
break;
|
package/dist/daemon/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { R as RainfallConfig, g as MCPClientConfig, h as MCPProxyHub } from '../sdk-
|
|
2
|
-
export { i as MCPClientInfo, j as MCPToolInfo, k as MCPTransportType } from '../sdk-
|
|
3
|
-
import { N as NetworkedExecutorOptions, C as ContextOptions, R as RainfallNetworkedExecutor, a as RainfallDaemonContext, b as RainfallListenerRegistry } from '../listeners-
|
|
1
|
+
import { R as RainfallConfig, g as MCPClientConfig, h as MCPProxyHub } from '../sdk-BUVNdBc7.mjs';
|
|
2
|
+
export { i as MCPClientInfo, j as MCPToolInfo, k as MCPTransportType } from '../sdk-BUVNdBc7.mjs';
|
|
3
|
+
import { N as NetworkedExecutorOptions, C as ContextOptions, R as RainfallNetworkedExecutor, a as RainfallDaemonContext, b as RainfallListenerRegistry } from '../listeners-BGdrWpkP.mjs';
|
|
4
4
|
import 'ws';
|
|
5
5
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
6
6
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
package/dist/daemon/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { R as RainfallConfig, g as MCPClientConfig, h as MCPProxyHub } from '../sdk-
|
|
2
|
-
export { i as MCPClientInfo, j as MCPToolInfo, k as MCPTransportType } from '../sdk-
|
|
3
|
-
import { N as NetworkedExecutorOptions, C as ContextOptions, R as RainfallNetworkedExecutor, a as RainfallDaemonContext, b as RainfallListenerRegistry } from '../listeners-
|
|
1
|
+
import { R as RainfallConfig, g as MCPClientConfig, h as MCPProxyHub } from '../sdk-BUVNdBc7.js';
|
|
2
|
+
export { i as MCPClientInfo, j as MCPToolInfo, k as MCPTransportType } from '../sdk-BUVNdBc7.js';
|
|
3
|
+
import { N as NetworkedExecutorOptions, C as ContextOptions, R as RainfallNetworkedExecutor, a as RainfallDaemonContext, b as RainfallListenerRegistry } from '../listeners-BCEypw1u.js';
|
|
4
4
|
import 'ws';
|
|
5
5
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
6
6
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|