@rainfall-devkit/sdk 0.1.8 → 0.2.1
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/README.md +51 -0
- package/dist/chunk-7MRE4ZVI.mjs +662 -0
- package/dist/chunk-AQFC7YAX.mjs +27 -0
- package/dist/chunk-EI7SJH5K.mjs +85 -0
- package/dist/chunk-NTTAVKRT.mjs +89 -0
- package/dist/chunk-RVKW5KBT.mjs +269 -0
- package/dist/chunk-V5QWJVLC.mjs +662 -0
- package/dist/chunk-VDPKDC3R.mjs +869 -0
- package/dist/chunk-WOITG5TG.mjs +84 -0
- package/dist/chunk-XAHJQRBJ.mjs +269 -0
- package/dist/chunk-XEQ6U3JQ.mjs +269 -0
- package/dist/cli/index.js +3797 -632
- package/dist/cli/index.mjs +453 -36
- package/dist/config-7UT7GYSN.mjs +16 -0
- package/dist/config-DDTQQBN7.mjs +14 -0
- package/dist/config-MD45VGWD.mjs +14 -0
- package/dist/config-ZKNHII2A.mjs +8 -0
- package/dist/daemon/index.d.mts +168 -0
- package/dist/daemon/index.d.ts +168 -0
- package/dist/daemon/index.js +3182 -0
- package/dist/daemon/index.mjs +1548 -0
- package/dist/errors-BMPseAnM.d.mts +47 -0
- package/dist/errors-BMPseAnM.d.ts +47 -0
- package/dist/errors-CZdRoYyw.d.ts +332 -0
- package/dist/errors-Chjq1Mev.d.mts +332 -0
- package/dist/index.d.mts +249 -2
- package/dist/index.d.ts +249 -2
- package/dist/index.js +1247 -3
- package/dist/index.mjs +227 -2
- package/dist/listeners-B5Vy9Ao5.d.ts +372 -0
- package/dist/listeners-BbYIaNCs.d.mts +372 -0
- package/dist/listeners-CP2A9J_2.d.ts +372 -0
- package/dist/listeners-CTRSofnm.d.mts +372 -0
- package/dist/listeners-CYI-YwIF.d.mts +372 -0
- package/dist/listeners-DRwITBW_.d.mts +372 -0
- package/dist/listeners-DrMrvFT5.d.ts +372 -0
- package/dist/listeners-MNAnpZj-.d.mts +372 -0
- package/dist/listeners-PZI7iT85.d.ts +372 -0
- package/dist/listeners-QJeEtLbV.d.ts +372 -0
- package/dist/listeners-hp0Ib2Ox.d.ts +372 -0
- package/dist/listeners-jLwetUnx.d.mts +372 -0
- package/dist/mcp.d.mts +7 -2
- package/dist/mcp.d.ts +7 -2
- package/dist/mcp.js +92 -1
- package/dist/mcp.mjs +1 -1
- package/dist/sdk-4OvXPr8E.d.mts +1054 -0
- package/dist/sdk-4OvXPr8E.d.ts +1054 -0
- package/dist/sdk-CJ9g5lFo.d.mts +772 -0
- package/dist/sdk-CJ9g5lFo.d.ts +772 -0
- package/dist/sdk-CN1ezZrI.d.mts +1054 -0
- package/dist/sdk-CN1ezZrI.d.ts +1054 -0
- package/dist/sdk-DD1OeGRJ.d.mts +871 -0
- package/dist/sdk-DD1OeGRJ.d.ts +871 -0
- package/dist/sdk-Xw0BjsLd.d.mts +1054 -0
- package/dist/sdk-Xw0BjsLd.d.ts +1054 -0
- package/dist/types-GnRAfH-h.d.mts +489 -0
- package/dist/types-GnRAfH-h.d.ts +489 -0
- package/package.json +17 -5
package/dist/cli/index.mjs
CHANGED
|
@@ -1,41 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createEdgeNodeSecurity
|
|
4
|
+
} from "../chunk-XEQ6U3JQ.mjs";
|
|
2
5
|
import {
|
|
3
6
|
Rainfall
|
|
4
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-VDPKDC3R.mjs";
|
|
8
|
+
import {
|
|
9
|
+
getConfigDir,
|
|
10
|
+
loadConfig,
|
|
11
|
+
saveConfig
|
|
12
|
+
} from "../chunk-NTTAVKRT.mjs";
|
|
5
13
|
|
|
6
14
|
// src/cli/index.ts
|
|
7
|
-
import { readFileSync, existsSync,
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
var CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
12
|
-
function loadConfig() {
|
|
13
|
-
if (!existsSync(CONFIG_FILE)) {
|
|
14
|
-
return {};
|
|
15
|
-
}
|
|
16
|
-
try {
|
|
17
|
-
return JSON.parse(readFileSync(CONFIG_FILE, "utf8"));
|
|
18
|
-
} catch {
|
|
19
|
-
return {};
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function saveConfig(config) {
|
|
23
|
-
if (!existsSync(CONFIG_DIR)) {
|
|
24
|
-
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
25
|
-
}
|
|
26
|
-
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
27
|
-
}
|
|
28
|
-
function getRainfall() {
|
|
29
|
-
const config = loadConfig();
|
|
30
|
-
if (!config.apiKey) {
|
|
31
|
-
console.error("Error: No API key configured. Run: rainfall auth login");
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
return new Rainfall({
|
|
35
|
-
apiKey: config.apiKey,
|
|
36
|
-
baseUrl: config.baseUrl
|
|
37
|
-
});
|
|
38
|
-
}
|
|
15
|
+
import { readFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
|
|
16
|
+
import { join, dirname } from "path";
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
18
|
+
import { spawn } from "child_process";
|
|
39
19
|
function printHelp() {
|
|
40
20
|
console.log(`
|
|
41
21
|
Rainfall CLI - 200+ tools, one key
|
|
@@ -53,28 +33,72 @@ Commands:
|
|
|
53
33
|
tools search <query> Search for tools
|
|
54
34
|
|
|
55
35
|
run <tool> [options] Execute a tool
|
|
36
|
+
|
|
37
|
+
daemon start Start the Rainfall daemon
|
|
38
|
+
daemon stop Stop the Rainfall daemon
|
|
39
|
+
daemon restart Restart the Rainfall daemon
|
|
40
|
+
daemon status Check daemon status
|
|
41
|
+
|
|
42
|
+
workflow new Create a new workflow (interactive)
|
|
43
|
+
workflow run <workflow> Run a saved workflow
|
|
56
44
|
|
|
57
45
|
me Show account info and usage
|
|
58
46
|
|
|
59
47
|
config get [key] Get configuration value
|
|
60
48
|
config set <key> <value> Set configuration value
|
|
49
|
+
config llm Show LLM configuration
|
|
50
|
+
|
|
51
|
+
edge generate-keys Generate key pair for edge node encryption
|
|
52
|
+
edge status Show edge node security status
|
|
53
|
+
|
|
54
|
+
version Show version information
|
|
55
|
+
upgrade Upgrade to the latest version
|
|
61
56
|
|
|
62
57
|
help Show this help message
|
|
63
58
|
|
|
59
|
+
Configuration keys:
|
|
60
|
+
llm.provider LLM provider (rainfall|openai|anthropic|ollama|local)
|
|
61
|
+
llm.baseUrl Base URL for the LLM API
|
|
62
|
+
llm.apiKey API key for the LLM provider
|
|
63
|
+
llm.model Default model to use
|
|
64
|
+
|
|
64
65
|
Options for 'run':
|
|
65
66
|
--params, -p <json> Tool parameters as JSON
|
|
66
67
|
--file, -f <path> Read parameters from file
|
|
67
68
|
--raw Output raw JSON
|
|
69
|
+
--<key> <value> Pass individual parameters (e.g., --query "AI news")
|
|
70
|
+
|
|
71
|
+
Options for 'daemon start':
|
|
72
|
+
--port <port> WebSocket port (default: 8765)
|
|
73
|
+
--openai-port <port> OpenAI API port (default: 8787)
|
|
74
|
+
--mcp-proxy Enable MCP proxy hub (default: enabled)
|
|
75
|
+
--no-mcp-proxy Disable MCP proxy hub
|
|
76
|
+
--secure Enable edge node security (JWT, ACLs, encryption)
|
|
77
|
+
--debug Enable verbose debug logging
|
|
68
78
|
|
|
69
79
|
Examples:
|
|
70
80
|
rainfall auth login
|
|
71
81
|
rainfall tools list
|
|
72
82
|
rainfall tools describe github-create-issue
|
|
73
83
|
rainfall run exa-web-search -p '{"query": "AI news"}'
|
|
84
|
+
rainfall run exa-web-search --query "AI news"
|
|
85
|
+
rainfall run github-create-issue --owner facebook --repo react --title "Bug"
|
|
74
86
|
rainfall run article-summarize -f ./article.json
|
|
87
|
+
rainfall daemon start
|
|
75
88
|
echo '{"query": "hello"}' | rainfall run exa-web-search
|
|
76
89
|
`);
|
|
77
90
|
}
|
|
91
|
+
function getRainfall() {
|
|
92
|
+
const config = loadConfig();
|
|
93
|
+
if (!config.apiKey) {
|
|
94
|
+
console.error("Error: No API key configured. Run: rainfall auth login");
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
return new Rainfall({
|
|
98
|
+
apiKey: config.apiKey,
|
|
99
|
+
baseUrl: config.baseUrl
|
|
100
|
+
});
|
|
101
|
+
}
|
|
78
102
|
async function authLogin(args) {
|
|
79
103
|
const apiKey = args[0] || process.env.RAINFALL_API_KEY;
|
|
80
104
|
if (!apiKey) {
|
|
@@ -239,16 +263,20 @@ Options:
|
|
|
239
263
|
-p, --params <json> Tool parameters as JSON string
|
|
240
264
|
-f, --file <path> Read parameters from JSON file
|
|
241
265
|
--raw Output raw JSON (no formatting)
|
|
266
|
+
--<key> <value> Pass individual parameters (e.g., --query "AI news")
|
|
242
267
|
|
|
243
268
|
Examples:
|
|
244
269
|
rainfall run figma-users-getMe
|
|
245
270
|
rainfall run exa-web-search -p '{"query": "AI news"}'
|
|
271
|
+
rainfall run exa-web-search --query "AI news"
|
|
272
|
+
rainfall run github-create-issue --owner facebook --repo react --title "Bug"
|
|
246
273
|
rainfall run github-create-issue -f ./issue.json
|
|
247
274
|
echo '{"query": "hello"}' | rainfall run exa-web-search
|
|
248
275
|
`);
|
|
249
276
|
return;
|
|
250
277
|
}
|
|
251
278
|
let params = {};
|
|
279
|
+
const rawArgs = [];
|
|
252
280
|
for (let i = 1; i < args.length; i++) {
|
|
253
281
|
const arg = args[i];
|
|
254
282
|
if (arg === "--params" || arg === "-p") {
|
|
@@ -276,6 +304,20 @@ Examples:
|
|
|
276
304
|
process.exit(1);
|
|
277
305
|
}
|
|
278
306
|
} else if (arg === "--raw") {
|
|
307
|
+
} else if (arg.startsWith("--")) {
|
|
308
|
+
const key = arg.slice(2);
|
|
309
|
+
const value = args[++i];
|
|
310
|
+
if (value === void 0) {
|
|
311
|
+
console.error(`Error: ${arg} requires a value`);
|
|
312
|
+
process.exit(1);
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
params[key] = JSON.parse(value);
|
|
316
|
+
} catch {
|
|
317
|
+
params[key] = value;
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
rawArgs.push(arg);
|
|
279
321
|
}
|
|
280
322
|
}
|
|
281
323
|
if (!process.stdin.isTTY) {
|
|
@@ -313,6 +355,20 @@ Examples:
|
|
|
313
355
|
}
|
|
314
356
|
}
|
|
315
357
|
const rainfall = getRainfall();
|
|
358
|
+
if (rawArgs.length === 1 && Object.keys(params).length === 0) {
|
|
359
|
+
try {
|
|
360
|
+
const schema = await rainfall.getToolSchema(toolId);
|
|
361
|
+
if (schema.parameters && typeof schema.parameters === "object") {
|
|
362
|
+
const paramEntries = Object.entries(schema.parameters);
|
|
363
|
+
const requiredParams = paramEntries.filter(([, p]) => !p.optional);
|
|
364
|
+
if (requiredParams.length === 1) {
|
|
365
|
+
const [paramName] = requiredParams[0];
|
|
366
|
+
params = { [paramName]: rawArgs[0] };
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
} catch {
|
|
370
|
+
}
|
|
371
|
+
}
|
|
316
372
|
try {
|
|
317
373
|
const result = await rainfall.executeTool(toolId, params);
|
|
318
374
|
if (args.includes("--raw")) {
|
|
@@ -339,7 +395,16 @@ function configGet(args) {
|
|
|
339
395
|
const key = args[0];
|
|
340
396
|
const config = loadConfig();
|
|
341
397
|
if (key) {
|
|
342
|
-
|
|
398
|
+
const parts = key.split(".");
|
|
399
|
+
let value = config;
|
|
400
|
+
for (const part of parts) {
|
|
401
|
+
value = value?.[part];
|
|
402
|
+
}
|
|
403
|
+
if (typeof value === "object" && value !== null) {
|
|
404
|
+
console.log(JSON.stringify(value, null, 2));
|
|
405
|
+
} else {
|
|
406
|
+
console.log(value ?? "");
|
|
407
|
+
}
|
|
343
408
|
} else {
|
|
344
409
|
console.log(JSON.stringify(config, null, 2));
|
|
345
410
|
}
|
|
@@ -350,13 +415,306 @@ function configSet(args) {
|
|
|
350
415
|
if (!key || !value) {
|
|
351
416
|
console.error("Error: Both key and value required");
|
|
352
417
|
console.error("\nUsage: rainfall config set <key> <value>");
|
|
418
|
+
console.error("\nExamples:");
|
|
419
|
+
console.error(" rainfall config set llm.provider local");
|
|
420
|
+
console.error(" rainfall config set llm.baseUrl http://localhost:1234/v1");
|
|
421
|
+
console.error(" rainfall config set llm.model llama-3.3-70b-versatile");
|
|
353
422
|
process.exit(1);
|
|
354
423
|
}
|
|
355
424
|
const config = loadConfig();
|
|
356
|
-
|
|
425
|
+
const parts = key.split(".");
|
|
426
|
+
if (parts.length === 1) {
|
|
427
|
+
config[key] = value;
|
|
428
|
+
} else {
|
|
429
|
+
let target = config;
|
|
430
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
431
|
+
if (!target[parts[i]] || typeof target[parts[i]] !== "object") {
|
|
432
|
+
target[parts[i]] = {};
|
|
433
|
+
}
|
|
434
|
+
target = target[parts[i]];
|
|
435
|
+
}
|
|
436
|
+
target[parts[parts.length - 1]] = value;
|
|
437
|
+
}
|
|
357
438
|
saveConfig(config);
|
|
358
439
|
console.log(`\u2713 Set ${key} = ${value}`);
|
|
359
440
|
}
|
|
441
|
+
function configLLM() {
|
|
442
|
+
const config = loadConfig();
|
|
443
|
+
const llm = config.llm || { provider: "rainfall" };
|
|
444
|
+
console.log("LLM Configuration:");
|
|
445
|
+
console.log(` Provider: ${llm.provider}`);
|
|
446
|
+
console.log(` Base URL: ${llm.baseUrl || "(default)"}`);
|
|
447
|
+
console.log(` Model: ${llm.model || "(default)"}`);
|
|
448
|
+
console.log(` API Key: ${llm.apiKey ? "****" + llm.apiKey.slice(-4) : "(none)"}`);
|
|
449
|
+
console.log();
|
|
450
|
+
console.log("Providers:");
|
|
451
|
+
console.log(" rainfall - Use Rainfall backend (default, uses your credits)");
|
|
452
|
+
console.log(" openai - Use OpenAI API directly");
|
|
453
|
+
console.log(" anthropic - Use Anthropic API directly");
|
|
454
|
+
console.log(" ollama - Use local Ollama instance");
|
|
455
|
+
console.log(" local - Use any OpenAI-compatible endpoint (LM Studio, etc.)");
|
|
456
|
+
console.log(" custom - Use any custom OpenAI-compatible endpoint (RunPod, etc.)");
|
|
457
|
+
console.log();
|
|
458
|
+
console.log("Examples:");
|
|
459
|
+
console.log(" rainfall config set llm.provider local");
|
|
460
|
+
console.log(" rainfall config set llm.baseUrl http://localhost:1234/v1");
|
|
461
|
+
console.log(" rainfall config set llm.provider custom");
|
|
462
|
+
console.log(" rainfall config set llm.baseUrl https://your-runpod-endpoint.runpod.net/v1");
|
|
463
|
+
console.log(" rainfall config set llm.provider openai");
|
|
464
|
+
console.log(" rainfall config set llm.apiKey sk-...");
|
|
465
|
+
}
|
|
466
|
+
function getPackageJson() {
|
|
467
|
+
try {
|
|
468
|
+
const __filename2 = fileURLToPath(import.meta.url);
|
|
469
|
+
const __dirname2 = dirname(__filename2);
|
|
470
|
+
const packagePath = join(__dirname2, "..", "..", "package.json");
|
|
471
|
+
const content = readFileSync(packagePath, "utf8");
|
|
472
|
+
return JSON.parse(content);
|
|
473
|
+
} catch {
|
|
474
|
+
return { version: "unknown", name: "@rainfall-devkit/sdk" };
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function showVersion() {
|
|
478
|
+
const pkg = getPackageJson();
|
|
479
|
+
console.log(`${pkg.name} v${pkg.version}`);
|
|
480
|
+
}
|
|
481
|
+
async function upgrade() {
|
|
482
|
+
const pkg = getPackageJson();
|
|
483
|
+
console.log(`Upgrading ${pkg.name}...`);
|
|
484
|
+
const execPath = process.argv[0];
|
|
485
|
+
const isBun = execPath.includes("bun");
|
|
486
|
+
let command;
|
|
487
|
+
let args;
|
|
488
|
+
if (isBun) {
|
|
489
|
+
command = "bun";
|
|
490
|
+
args = ["add", "-g", `${pkg.name}@latest`];
|
|
491
|
+
} else {
|
|
492
|
+
command = "npm";
|
|
493
|
+
args = ["i", "-g", `${pkg.name}@latest`];
|
|
494
|
+
}
|
|
495
|
+
console.log(`Running: ${command} ${args.join(" ")}`);
|
|
496
|
+
console.log();
|
|
497
|
+
return new Promise((resolve, reject) => {
|
|
498
|
+
const child = spawn(command, args, {
|
|
499
|
+
stdio: "inherit",
|
|
500
|
+
shell: true
|
|
501
|
+
});
|
|
502
|
+
child.on("close", (code) => {
|
|
503
|
+
if (code === 0) {
|
|
504
|
+
console.log();
|
|
505
|
+
console.log("\u2713 Upgrade complete");
|
|
506
|
+
resolve();
|
|
507
|
+
} else {
|
|
508
|
+
reject(new Error(`Upgrade failed with exit code ${code}`));
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
child.on("error", (err) => {
|
|
512
|
+
reject(err);
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
async function daemonStart(args) {
|
|
517
|
+
let port;
|
|
518
|
+
let openaiPort;
|
|
519
|
+
let debug = false;
|
|
520
|
+
let enableMcpProxy = true;
|
|
521
|
+
for (let i = 0; i < args.length; i++) {
|
|
522
|
+
const arg = args[i];
|
|
523
|
+
if (arg === "--port") {
|
|
524
|
+
const val = parseInt(args[++i], 10);
|
|
525
|
+
if (!isNaN(val)) port = val;
|
|
526
|
+
} else if (arg === "--openai-port") {
|
|
527
|
+
const val = parseInt(args[++i], 10);
|
|
528
|
+
if (!isNaN(val)) openaiPort = val;
|
|
529
|
+
} else if (arg === "--debug") {
|
|
530
|
+
debug = true;
|
|
531
|
+
} else if (arg === "--mcp-proxy") {
|
|
532
|
+
enableMcpProxy = true;
|
|
533
|
+
} else if (arg === "--no-mcp-proxy") {
|
|
534
|
+
enableMcpProxy = false;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
const { startDaemon } = await import("../daemon/index.mjs");
|
|
538
|
+
try {
|
|
539
|
+
await startDaemon({ port, openaiPort, debug, enableMcpProxy });
|
|
540
|
+
process.on("SIGINT", async () => {
|
|
541
|
+
console.log("\n");
|
|
542
|
+
const { stopDaemon } = await import("../daemon/index.mjs");
|
|
543
|
+
await stopDaemon();
|
|
544
|
+
process.exit(0);
|
|
545
|
+
});
|
|
546
|
+
process.on("SIGTERM", async () => {
|
|
547
|
+
const { stopDaemon } = await import("../daemon/index.mjs");
|
|
548
|
+
await stopDaemon();
|
|
549
|
+
process.exit(0);
|
|
550
|
+
});
|
|
551
|
+
} catch (error) {
|
|
552
|
+
console.error("Failed to start daemon:", error instanceof Error ? error.message : error);
|
|
553
|
+
process.exit(1);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
async function daemonStop() {
|
|
557
|
+
const { stopDaemon } = await import("../daemon/index.mjs");
|
|
558
|
+
await stopDaemon();
|
|
559
|
+
}
|
|
560
|
+
async function daemonRestart(args) {
|
|
561
|
+
const { stopDaemon, startDaemon } = await import("../daemon/index.mjs");
|
|
562
|
+
let port;
|
|
563
|
+
let openaiPort;
|
|
564
|
+
let debug = false;
|
|
565
|
+
for (let i = 0; i < args.length; i++) {
|
|
566
|
+
const arg = args[i];
|
|
567
|
+
if (arg === "--port") {
|
|
568
|
+
const val = parseInt(args[++i], 10);
|
|
569
|
+
if (!isNaN(val)) port = val;
|
|
570
|
+
} else if (arg === "--openai-port") {
|
|
571
|
+
const val = parseInt(args[++i], 10);
|
|
572
|
+
if (!isNaN(val)) openaiPort = val;
|
|
573
|
+
} else if (arg === "--debug") {
|
|
574
|
+
debug = true;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
console.log("\u{1F504} Restarting daemon...");
|
|
578
|
+
try {
|
|
579
|
+
await stopDaemon();
|
|
580
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
581
|
+
await startDaemon({ port, openaiPort, debug });
|
|
582
|
+
process.on("SIGINT", async () => {
|
|
583
|
+
console.log("\n");
|
|
584
|
+
const { stopDaemon: stop } = await import("../daemon/index.mjs");
|
|
585
|
+
await stop();
|
|
586
|
+
process.exit(0);
|
|
587
|
+
});
|
|
588
|
+
process.on("SIGTERM", async () => {
|
|
589
|
+
const { stopDaemon: stop } = await import("../daemon/index.mjs");
|
|
590
|
+
await stop();
|
|
591
|
+
process.exit(0);
|
|
592
|
+
});
|
|
593
|
+
} catch (error) {
|
|
594
|
+
console.error("Failed to restart daemon:", error instanceof Error ? error.message : error);
|
|
595
|
+
process.exit(1);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
async function daemonStatus() {
|
|
599
|
+
const { getDaemonStatus } = await import("../daemon/index.mjs");
|
|
600
|
+
const status = getDaemonStatus();
|
|
601
|
+
if (!status) {
|
|
602
|
+
console.log("Daemon not running");
|
|
603
|
+
console.log("Run: rainfall daemon start");
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
console.log("Daemon status:");
|
|
607
|
+
console.log(` Running: ${status.running ? "yes" : "no"}`);
|
|
608
|
+
console.log(` WebSocket port: ${status.port}`);
|
|
609
|
+
console.log(` OpenAI API port: ${status.openaiPort}`);
|
|
610
|
+
console.log(` Tools loaded: ${status.toolsLoaded}`);
|
|
611
|
+
console.log(` MCP clients: ${status.mcpClients || 0}`);
|
|
612
|
+
console.log(` MCP tools: ${status.mcpTools || 0}`);
|
|
613
|
+
console.log(` Clients connected: ${status.clientsConnected}`);
|
|
614
|
+
console.log(` Edge Node ID: ${status.edgeNodeId || "local"}`);
|
|
615
|
+
console.log();
|
|
616
|
+
console.log("Context:");
|
|
617
|
+
console.log(` Memories cached: ${status.context.memoriesCached}`);
|
|
618
|
+
console.log(` Active sessions: ${status.context.activeSessions}`);
|
|
619
|
+
console.log(` Current session: ${status.context.currentSession || "none"}`);
|
|
620
|
+
console.log(` Execution history: ${status.context.executionHistorySize}`);
|
|
621
|
+
console.log();
|
|
622
|
+
console.log("Listeners:");
|
|
623
|
+
console.log(` File watchers: ${status.listeners.fileWatchers}`);
|
|
624
|
+
console.log(` Cron triggers: ${status.listeners.cronTriggers}`);
|
|
625
|
+
console.log(` Recent events: ${status.listeners.recentEvents}`);
|
|
626
|
+
}
|
|
627
|
+
async function workflowNew() {
|
|
628
|
+
console.log("\u{1F6A7} Interactive workflow creation coming soon!");
|
|
629
|
+
console.log();
|
|
630
|
+
console.log("For now, create workflows using the SDK:");
|
|
631
|
+
console.log(' import { createFileWatcherWorkflow } from "@rainfall-devkit/sdk/daemon";');
|
|
632
|
+
console.log();
|
|
633
|
+
console.log("Example:");
|
|
634
|
+
console.log(` const workflow = createFileWatcherWorkflow('pdf-processor', '~/Downloads', {`);
|
|
635
|
+
console.log(` pattern: '*.pdf',`);
|
|
636
|
+
console.log(` events: ['create'],`);
|
|
637
|
+
console.log(` workflow: [`);
|
|
638
|
+
console.log(` { toolId: 'ocr-pdf', params: {} },`);
|
|
639
|
+
console.log(` { toolId: 'notion-create-page', params: { parent: '...' } },`);
|
|
640
|
+
console.log(` ],`);
|
|
641
|
+
console.log(` });`);
|
|
642
|
+
}
|
|
643
|
+
async function workflowRun(args) {
|
|
644
|
+
const workflowId = args[0];
|
|
645
|
+
if (!workflowId) {
|
|
646
|
+
console.error("Error: Workflow ID required");
|
|
647
|
+
console.error("\nUsage: rainfall workflow run <workflow-id>");
|
|
648
|
+
process.exit(1);
|
|
649
|
+
}
|
|
650
|
+
console.log(`\u{1F6A7} Running workflow: ${workflowId}`);
|
|
651
|
+
console.log("Workflow execution coming soon!");
|
|
652
|
+
}
|
|
653
|
+
async function edgeGenerateKeys() {
|
|
654
|
+
console.log("\u{1F510} Generating edge node key pair...\n");
|
|
655
|
+
try {
|
|
656
|
+
const security = await createEdgeNodeSecurity();
|
|
657
|
+
const keyPair = await security.generateKeyPair();
|
|
658
|
+
const configDir = getConfigDir();
|
|
659
|
+
const keysDir = join(configDir, "keys");
|
|
660
|
+
if (!existsSync(keysDir)) {
|
|
661
|
+
mkdirSync(keysDir, { recursive: true });
|
|
662
|
+
}
|
|
663
|
+
const publicKeyPath = join(keysDir, "edge-node.pub");
|
|
664
|
+
const privateKeyPath = join(keysDir, "edge-node.key");
|
|
665
|
+
writeFileSync(publicKeyPath, keyPair.publicKey, { mode: 420 });
|
|
666
|
+
writeFileSync(privateKeyPath, keyPair.privateKey, { mode: 384 });
|
|
667
|
+
console.log("\u2705 Key pair generated successfully!\n");
|
|
668
|
+
console.log("Public key:", keyPair.publicKey);
|
|
669
|
+
console.log("\nKey files saved to:");
|
|
670
|
+
console.log(" Public:", publicKeyPath);
|
|
671
|
+
console.log(" Private:", privateKeyPath);
|
|
672
|
+
console.log("\n\u{1F4CB} To register this edge node:");
|
|
673
|
+
console.log(" 1. Copy the public key above");
|
|
674
|
+
console.log(" 2. Register with: rainfall edge register <public-key>");
|
|
675
|
+
console.log(" 3. The backend will return an edgeNodeSecret (JWT)");
|
|
676
|
+
console.log(" 4. Store the secret securely - it expires in 30 days");
|
|
677
|
+
} catch (error) {
|
|
678
|
+
console.error("\u274C Failed to generate keys:", error instanceof Error ? error.message : error);
|
|
679
|
+
process.exit(1);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
async function edgeStatus() {
|
|
683
|
+
const configDir = getConfigDir();
|
|
684
|
+
const keysDir = join(configDir, "keys");
|
|
685
|
+
const publicKeyPath = join(keysDir, "edge-node.pub");
|
|
686
|
+
const privateKeyPath = join(keysDir, "edge-node.key");
|
|
687
|
+
console.log("\u{1F510} Edge Node Security Status\n");
|
|
688
|
+
const hasPublicKey = existsSync(publicKeyPath);
|
|
689
|
+
const hasPrivateKey = existsSync(privateKeyPath);
|
|
690
|
+
console.log("Key Pair:");
|
|
691
|
+
console.log(" Public key:", hasPublicKey ? "\u2705 Present" : "\u274C Missing");
|
|
692
|
+
console.log(" Private key:", hasPrivateKey ? "\u2705 Present" : "\u274C Missing");
|
|
693
|
+
if (hasPublicKey) {
|
|
694
|
+
const publicKey = readFileSync(publicKeyPath, "utf-8");
|
|
695
|
+
console.log("\nPublic Key:");
|
|
696
|
+
console.log(" " + publicKey.substring(0, 50) + "...");
|
|
697
|
+
}
|
|
698
|
+
const config = loadConfig();
|
|
699
|
+
if (config.edgeNodeId) {
|
|
700
|
+
console.log("\nRegistration:");
|
|
701
|
+
console.log(" Edge Node ID:", config.edgeNodeId);
|
|
702
|
+
}
|
|
703
|
+
if (config.edgeNodeSecret) {
|
|
704
|
+
console.log(" JWT Secret: \u2705 Present (expires: check with backend)");
|
|
705
|
+
} else {
|
|
706
|
+
console.log(" JWT Secret: \u274C Not configured");
|
|
707
|
+
}
|
|
708
|
+
console.log("\n\u{1F4DA} Next steps:");
|
|
709
|
+
if (!hasPublicKey) {
|
|
710
|
+
console.log(" 1. Run: rainfall edge generate-keys");
|
|
711
|
+
} else if (!config.edgeNodeSecret) {
|
|
712
|
+
console.log(" 1. Register your edge node with the backend");
|
|
713
|
+
console.log(" 2. Store the returned edgeNodeSecret in config");
|
|
714
|
+
} else {
|
|
715
|
+
console.log(" Edge node is configured and ready for secure operation");
|
|
716
|
+
}
|
|
717
|
+
}
|
|
360
718
|
async function main() {
|
|
361
719
|
const args = process.argv.slice(2);
|
|
362
720
|
const command = args[0];
|
|
@@ -400,6 +758,40 @@ async function main() {
|
|
|
400
758
|
case "run":
|
|
401
759
|
await runTool(args.slice(1));
|
|
402
760
|
break;
|
|
761
|
+
case "daemon":
|
|
762
|
+
switch (subcommand) {
|
|
763
|
+
case "start":
|
|
764
|
+
await daemonStart(rest);
|
|
765
|
+
break;
|
|
766
|
+
case "stop":
|
|
767
|
+
await daemonStop();
|
|
768
|
+
break;
|
|
769
|
+
case "restart":
|
|
770
|
+
await daemonRestart(rest);
|
|
771
|
+
break;
|
|
772
|
+
case "status":
|
|
773
|
+
await daemonStatus();
|
|
774
|
+
break;
|
|
775
|
+
default:
|
|
776
|
+
console.error("Error: Unknown daemon subcommand");
|
|
777
|
+
console.error("\nUsage: rainfall daemon <start|stop|restart|status>");
|
|
778
|
+
process.exit(1);
|
|
779
|
+
}
|
|
780
|
+
break;
|
|
781
|
+
case "workflow":
|
|
782
|
+
switch (subcommand) {
|
|
783
|
+
case "new":
|
|
784
|
+
await workflowNew();
|
|
785
|
+
break;
|
|
786
|
+
case "run":
|
|
787
|
+
await workflowRun(rest);
|
|
788
|
+
break;
|
|
789
|
+
default:
|
|
790
|
+
console.error("Error: Unknown workflow subcommand");
|
|
791
|
+
console.error("\nUsage: rainfall workflow <new|run>");
|
|
792
|
+
process.exit(1);
|
|
793
|
+
}
|
|
794
|
+
break;
|
|
403
795
|
case "me":
|
|
404
796
|
await showMe();
|
|
405
797
|
break;
|
|
@@ -411,9 +803,34 @@ async function main() {
|
|
|
411
803
|
case "set":
|
|
412
804
|
configSet(rest);
|
|
413
805
|
break;
|
|
806
|
+
case "llm":
|
|
807
|
+
configLLM();
|
|
808
|
+
break;
|
|
414
809
|
default:
|
|
415
810
|
console.error("Error: Unknown config subcommand");
|
|
416
|
-
console.error("\nUsage: rainfall config <get|set>");
|
|
811
|
+
console.error("\nUsage: rainfall config <get|set|llm>");
|
|
812
|
+
process.exit(1);
|
|
813
|
+
}
|
|
814
|
+
break;
|
|
815
|
+
case "version":
|
|
816
|
+
case "--version":
|
|
817
|
+
case "-v":
|
|
818
|
+
showVersion();
|
|
819
|
+
break;
|
|
820
|
+
case "upgrade":
|
|
821
|
+
await upgrade();
|
|
822
|
+
break;
|
|
823
|
+
case "edge":
|
|
824
|
+
switch (subcommand) {
|
|
825
|
+
case "generate-keys":
|
|
826
|
+
await edgeGenerateKeys();
|
|
827
|
+
break;
|
|
828
|
+
case "status":
|
|
829
|
+
await edgeStatus();
|
|
830
|
+
break;
|
|
831
|
+
default:
|
|
832
|
+
console.error("Error: Unknown edge subcommand");
|
|
833
|
+
console.error("\nUsage: rainfall edge <generate-keys|status>");
|
|
417
834
|
process.exit(1);
|
|
418
835
|
}
|
|
419
836
|
break;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getConfigDir,
|
|
3
|
+
getLLMConfig,
|
|
4
|
+
getProviderBaseUrl,
|
|
5
|
+
isLocalProvider,
|
|
6
|
+
loadConfig,
|
|
7
|
+
saveConfig
|
|
8
|
+
} from "./chunk-NTTAVKRT.mjs";
|
|
9
|
+
export {
|
|
10
|
+
getConfigDir,
|
|
11
|
+
getLLMConfig,
|
|
12
|
+
getProviderBaseUrl,
|
|
13
|
+
isLocalProvider,
|
|
14
|
+
loadConfig,
|
|
15
|
+
saveConfig
|
|
16
|
+
};
|