@rainfall-devkit/sdk 0.1.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/LICENSE +21 -0
- package/README.md +467 -0
- package/dist/chunk-UP45HOXN.mjs +731 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +1067 -0
- package/dist/cli/index.mjs +357 -0
- package/dist/errors-DdRTwxpT.d.mts +809 -0
- package/dist/errors-DdRTwxpT.d.ts +809 -0
- package/dist/index.d.mts +29 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +771 -0
- package/dist/index.mjs +30 -0
- package/dist/mcp.d.mts +68 -0
- package/dist/mcp.d.ts +68 -0
- package/dist/mcp.js +922 -0
- package/dist/mcp.mjs +181 -0
- package/package.json +69 -0
|
@@ -0,0 +1,1067 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// src/cli/index.ts
|
|
5
|
+
var import_fs = require("fs");
|
|
6
|
+
var import_path = require("path");
|
|
7
|
+
var import_os = require("os");
|
|
8
|
+
|
|
9
|
+
// src/errors.ts
|
|
10
|
+
var RainfallError = class _RainfallError extends Error {
|
|
11
|
+
constructor(message, code, statusCode, details) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.statusCode = statusCode;
|
|
15
|
+
this.details = details;
|
|
16
|
+
this.name = "RainfallError";
|
|
17
|
+
Object.setPrototypeOf(this, _RainfallError.prototype);
|
|
18
|
+
}
|
|
19
|
+
toJSON() {
|
|
20
|
+
return {
|
|
21
|
+
name: this.name,
|
|
22
|
+
code: this.code,
|
|
23
|
+
message: this.message,
|
|
24
|
+
statusCode: this.statusCode,
|
|
25
|
+
details: this.details
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var AuthenticationError = class _AuthenticationError extends RainfallError {
|
|
30
|
+
constructor(message = "Invalid API key", details) {
|
|
31
|
+
super(message, "AUTHENTICATION_ERROR", 401, details);
|
|
32
|
+
this.name = "AuthenticationError";
|
|
33
|
+
Object.setPrototypeOf(this, _AuthenticationError.prototype);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var RateLimitError = class _RateLimitError extends RainfallError {
|
|
37
|
+
retryAfter;
|
|
38
|
+
limit;
|
|
39
|
+
remaining;
|
|
40
|
+
resetAt;
|
|
41
|
+
constructor(message = "Rate limit exceeded", retryAfter = 60, limit = 0, remaining = 0, resetAt) {
|
|
42
|
+
super(message, "RATE_LIMIT_ERROR", 429, { retryAfter, limit, remaining });
|
|
43
|
+
this.name = "RateLimitError";
|
|
44
|
+
this.retryAfter = retryAfter;
|
|
45
|
+
this.limit = limit;
|
|
46
|
+
this.remaining = remaining;
|
|
47
|
+
this.resetAt = resetAt || new Date(Date.now() + retryAfter * 1e3);
|
|
48
|
+
Object.setPrototypeOf(this, _RateLimitError.prototype);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var ValidationError = class _ValidationError extends RainfallError {
|
|
52
|
+
constructor(message, details) {
|
|
53
|
+
super(message, "VALIDATION_ERROR", 400, details);
|
|
54
|
+
this.name = "ValidationError";
|
|
55
|
+
Object.setPrototypeOf(this, _ValidationError.prototype);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var NotFoundError = class _NotFoundError extends RainfallError {
|
|
59
|
+
constructor(resource, identifier) {
|
|
60
|
+
super(
|
|
61
|
+
`${resource}${identifier ? ` '${identifier}'` : ""} not found`,
|
|
62
|
+
"NOT_FOUND_ERROR",
|
|
63
|
+
404,
|
|
64
|
+
{ resource, identifier }
|
|
65
|
+
);
|
|
66
|
+
this.name = "NotFoundError";
|
|
67
|
+
Object.setPrototypeOf(this, _NotFoundError.prototype);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var ServerError = class _ServerError extends RainfallError {
|
|
71
|
+
constructor(message = "Internal server error", statusCode = 500) {
|
|
72
|
+
super(message, "SERVER_ERROR", statusCode);
|
|
73
|
+
this.name = "ServerError";
|
|
74
|
+
Object.setPrototypeOf(this, _ServerError.prototype);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
var TimeoutError = class _TimeoutError extends RainfallError {
|
|
78
|
+
constructor(timeoutMs) {
|
|
79
|
+
super(`Request timed out after ${timeoutMs}ms`, "TIMEOUT_ERROR", 408);
|
|
80
|
+
this.name = "TimeoutError";
|
|
81
|
+
Object.setPrototypeOf(this, _TimeoutError.prototype);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var NetworkError = class _NetworkError extends RainfallError {
|
|
85
|
+
constructor(message = "Network error", details) {
|
|
86
|
+
super(message, "NETWORK_ERROR", void 0, details);
|
|
87
|
+
this.name = "NetworkError";
|
|
88
|
+
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
function parseErrorResponse(response, data) {
|
|
92
|
+
const statusCode = response.status;
|
|
93
|
+
if (statusCode === 429) {
|
|
94
|
+
const retryAfter = parseInt(response.headers.get("retry-after") || "60", 10);
|
|
95
|
+
const limit = parseInt(response.headers.get("x-ratelimit-limit") || "0", 10);
|
|
96
|
+
const remaining = parseInt(response.headers.get("x-ratelimit-remaining") || "0", 10);
|
|
97
|
+
const resetHeader = response.headers.get("x-ratelimit-reset");
|
|
98
|
+
const resetAt = resetHeader ? new Date(parseInt(resetHeader, 10) * 1e3) : void 0;
|
|
99
|
+
return new RateLimitError(
|
|
100
|
+
typeof data === "object" && data && "message" in data ? String(data.message) : "Rate limit exceeded",
|
|
101
|
+
retryAfter,
|
|
102
|
+
limit,
|
|
103
|
+
remaining,
|
|
104
|
+
resetAt
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
switch (statusCode) {
|
|
108
|
+
case 401:
|
|
109
|
+
return new AuthenticationError(
|
|
110
|
+
typeof data === "object" && data && "message" in data ? String(data.message) : "Invalid API key"
|
|
111
|
+
);
|
|
112
|
+
case 404:
|
|
113
|
+
return new NotFoundError(
|
|
114
|
+
typeof data === "object" && data && "resource" in data ? String(data.resource) : "Resource",
|
|
115
|
+
typeof data === "object" && data && "identifier" in data ? String(data.identifier) : void 0
|
|
116
|
+
);
|
|
117
|
+
case 400:
|
|
118
|
+
return new ValidationError(
|
|
119
|
+
typeof data === "object" && data && "message" in data ? String(data.message) : "Invalid request",
|
|
120
|
+
typeof data === "object" && data && "details" in data ? data.details : void 0
|
|
121
|
+
);
|
|
122
|
+
case 500:
|
|
123
|
+
case 502:
|
|
124
|
+
case 503:
|
|
125
|
+
case 504:
|
|
126
|
+
return new ServerError(
|
|
127
|
+
typeof data === "object" && data && "message" in data ? String(data.message) : "Server error",
|
|
128
|
+
statusCode
|
|
129
|
+
);
|
|
130
|
+
default:
|
|
131
|
+
return new RainfallError(
|
|
132
|
+
typeof data === "object" && data && "message" in data ? String(data.message) : `HTTP ${statusCode}`,
|
|
133
|
+
"UNKNOWN_ERROR",
|
|
134
|
+
statusCode,
|
|
135
|
+
typeof data === "object" ? data : void 0
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/client.ts
|
|
141
|
+
var DEFAULT_BASE_URL = "https://olympic-api.pragma-digital.org/v1";
|
|
142
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
143
|
+
var DEFAULT_RETRIES = 3;
|
|
144
|
+
var DEFAULT_RETRY_DELAY = 1e3;
|
|
145
|
+
var RainfallClient = class {
|
|
146
|
+
apiKey;
|
|
147
|
+
baseUrl;
|
|
148
|
+
defaultTimeout;
|
|
149
|
+
defaultRetries;
|
|
150
|
+
defaultRetryDelay;
|
|
151
|
+
lastRateLimitInfo;
|
|
152
|
+
constructor(config) {
|
|
153
|
+
this.apiKey = config.apiKey;
|
|
154
|
+
this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
|
|
155
|
+
this.defaultTimeout = config.timeout || DEFAULT_TIMEOUT;
|
|
156
|
+
this.defaultRetries = config.retries ?? DEFAULT_RETRIES;
|
|
157
|
+
this.defaultRetryDelay = config.retryDelay || DEFAULT_RETRY_DELAY;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get the last rate limit info from the API
|
|
161
|
+
*/
|
|
162
|
+
getRateLimitInfo() {
|
|
163
|
+
return this.lastRateLimitInfo;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Make an authenticated request to the Rainfall API
|
|
167
|
+
*/
|
|
168
|
+
async request(path, options = {}, requestOptions) {
|
|
169
|
+
const timeout = requestOptions?.timeout ?? this.defaultTimeout;
|
|
170
|
+
const maxRetries = requestOptions?.retries ?? this.defaultRetries;
|
|
171
|
+
const retryDelay = requestOptions?.retryDelay ?? this.defaultRetryDelay;
|
|
172
|
+
const url = `${this.baseUrl}${path}`;
|
|
173
|
+
const method = options.method || "GET";
|
|
174
|
+
let lastError;
|
|
175
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
176
|
+
try {
|
|
177
|
+
const controller = new AbortController();
|
|
178
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
179
|
+
const response = await fetch(url, {
|
|
180
|
+
method,
|
|
181
|
+
headers: {
|
|
182
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
183
|
+
"Content-Type": "application/json",
|
|
184
|
+
"Accept": "application/json",
|
|
185
|
+
"X-Rainfall-SDK-Version": "0.1.0",
|
|
186
|
+
...options.headers
|
|
187
|
+
},
|
|
188
|
+
body: options.body ? JSON.stringify(options.body) : void 0,
|
|
189
|
+
signal: controller.signal
|
|
190
|
+
});
|
|
191
|
+
clearTimeout(timeoutId);
|
|
192
|
+
const limit = response.headers.get("x-ratelimit-limit");
|
|
193
|
+
const remaining = response.headers.get("x-ratelimit-remaining");
|
|
194
|
+
const reset = response.headers.get("x-ratelimit-reset");
|
|
195
|
+
if (limit && remaining && reset) {
|
|
196
|
+
this.lastRateLimitInfo = {
|
|
197
|
+
limit: parseInt(limit, 10),
|
|
198
|
+
remaining: parseInt(remaining, 10),
|
|
199
|
+
resetAt: new Date(parseInt(reset, 10) * 1e3)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
let data;
|
|
203
|
+
const contentType = response.headers.get("content-type");
|
|
204
|
+
if (contentType?.includes("application/json")) {
|
|
205
|
+
data = await response.json();
|
|
206
|
+
} else {
|
|
207
|
+
data = await response.text();
|
|
208
|
+
}
|
|
209
|
+
if (!response.ok) {
|
|
210
|
+
throw parseErrorResponse(response, data);
|
|
211
|
+
}
|
|
212
|
+
return data;
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if (error instanceof RainfallError) {
|
|
215
|
+
if (error.statusCode && error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429) {
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
if (error.statusCode === 401) {
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
223
|
+
lastError = new TimeoutError(timeout);
|
|
224
|
+
} else if (error instanceof TypeError) {
|
|
225
|
+
lastError = new NetworkError(error.message);
|
|
226
|
+
} else {
|
|
227
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
228
|
+
}
|
|
229
|
+
if (attempt >= maxRetries) {
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
const delay = retryDelay * Math.pow(2, attempt) + Math.random() * 1e3;
|
|
233
|
+
await this.sleep(delay);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
throw lastError || new RainfallError("Request failed", "REQUEST_FAILED");
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Execute a tool/node by ID
|
|
240
|
+
*/
|
|
241
|
+
async executeTool(toolId, params, options) {
|
|
242
|
+
return this.request(`/tools/${toolId}`, {
|
|
243
|
+
method: "POST",
|
|
244
|
+
body: params
|
|
245
|
+
}, options);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* List all available tools
|
|
249
|
+
*/
|
|
250
|
+
async listTools() {
|
|
251
|
+
return this.request("/tools");
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Get tool schema/parameters
|
|
255
|
+
*/
|
|
256
|
+
async getToolSchema(toolId) {
|
|
257
|
+
return this.request(`/tools/${toolId}/schema`);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get subscriber info
|
|
261
|
+
*/
|
|
262
|
+
async getMe() {
|
|
263
|
+
return this.request("/me");
|
|
264
|
+
}
|
|
265
|
+
sleep(ms) {
|
|
266
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// src/namespaces/integrations.ts
|
|
271
|
+
function createIntegrations(client) {
|
|
272
|
+
return new IntegrationsNamespace(client);
|
|
273
|
+
}
|
|
274
|
+
var IntegrationsNamespace = class {
|
|
275
|
+
constructor(client) {
|
|
276
|
+
this.client = client;
|
|
277
|
+
}
|
|
278
|
+
get github() {
|
|
279
|
+
return {
|
|
280
|
+
issues: {
|
|
281
|
+
create: (params) => this.client.executeTool("github-create-issue", params),
|
|
282
|
+
list: (params) => this.client.executeTool("github-list-issues", params),
|
|
283
|
+
get: (params) => this.client.executeTool("github-get-issue", params),
|
|
284
|
+
update: (params) => this.client.executeTool("github-update-issue", params),
|
|
285
|
+
addComment: (params) => this.client.executeTool("github-add-issue-comment", params)
|
|
286
|
+
},
|
|
287
|
+
repos: {
|
|
288
|
+
get: (params) => this.client.executeTool("github-get-repository", params),
|
|
289
|
+
listBranches: (params) => this.client.executeTool("github-list-branches", params)
|
|
290
|
+
},
|
|
291
|
+
pullRequests: {
|
|
292
|
+
list: (params) => this.client.executeTool("github-list-pull-requests", params),
|
|
293
|
+
get: (params) => this.client.executeTool("github-get-pull-request", params)
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
get notion() {
|
|
298
|
+
return {
|
|
299
|
+
pages: {
|
|
300
|
+
create: (params) => this.client.executeTool("notion-pages-create", params),
|
|
301
|
+
retrieve: (params) => this.client.executeTool("notion-pages-retrieve", params),
|
|
302
|
+
update: (params) => this.client.executeTool("notion-pages-update", params)
|
|
303
|
+
},
|
|
304
|
+
databases: {
|
|
305
|
+
query: (params) => this.client.executeTool("notion-databases-query", params),
|
|
306
|
+
retrieve: (params) => this.client.executeTool("notion-databases-retrieve", params)
|
|
307
|
+
},
|
|
308
|
+
blocks: {
|
|
309
|
+
appendChildren: (params) => this.client.executeTool("notion-blocks-append-children", params),
|
|
310
|
+
retrieveChildren: (params) => this.client.executeTool("notion-blocks-retrieve-children", params)
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
get linear() {
|
|
315
|
+
return {
|
|
316
|
+
issues: {
|
|
317
|
+
create: (params) => this.client.executeTool("linear-core-issueCreate", params),
|
|
318
|
+
list: (params) => this.client.executeTool("linear-core-issues", params),
|
|
319
|
+
get: (params) => this.client.executeTool("linear-core-issue", params),
|
|
320
|
+
update: (params) => this.client.executeTool("linear-core-issueUpdate", params),
|
|
321
|
+
archive: (params) => this.client.executeTool("linear-core-issueArchive", params)
|
|
322
|
+
},
|
|
323
|
+
teams: {
|
|
324
|
+
list: () => this.client.executeTool("linear-core-teams", {})
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
get slack() {
|
|
329
|
+
return {
|
|
330
|
+
messages: {
|
|
331
|
+
send: (params) => this.client.executeTool("slack-core-postMessage", params),
|
|
332
|
+
list: (params) => this.client.executeTool("slack-core-listMessages", params)
|
|
333
|
+
},
|
|
334
|
+
channels: {
|
|
335
|
+
list: () => this.client.executeTool("slack-core-listChannels", {})
|
|
336
|
+
},
|
|
337
|
+
users: {
|
|
338
|
+
list: () => this.client.executeTool("slack-core-listUsers", {})
|
|
339
|
+
},
|
|
340
|
+
reactions: {
|
|
341
|
+
add: (params) => this.client.executeTool("slack-core-addReaction", params)
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
get figma() {
|
|
346
|
+
return {
|
|
347
|
+
files: {
|
|
348
|
+
get: (params) => this.client.executeTool("figma-files-getFile", { fileKey: params.fileKey }),
|
|
349
|
+
getNodes: (params) => this.client.executeTool("figma-files-getFileNodes", { fileKey: params.fileKey, nodeIds: params.nodeIds }),
|
|
350
|
+
getImages: (params) => this.client.executeTool("figma-files-getFileImage", { fileKey: params.fileKey, nodeIds: params.nodeIds, format: params.format }),
|
|
351
|
+
getComments: (params) => this.client.executeTool("figma-comments-getFileComments", { fileKey: params.fileKey }),
|
|
352
|
+
postComment: (params) => this.client.executeTool("figma-comments-postComment", { fileKey: params.fileKey, message: params.message, nodeId: params.nodeId })
|
|
353
|
+
},
|
|
354
|
+
projects: {
|
|
355
|
+
list: (params) => this.client.executeTool("figma-projects-getTeamProjects", { teamId: params.teamId }),
|
|
356
|
+
getFiles: (params) => this.client.executeTool("figma-projects-getProjectFiles", { projectId: params.projectId })
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
get stripe() {
|
|
361
|
+
return {
|
|
362
|
+
customers: {
|
|
363
|
+
create: (params) => this.client.executeTool("stripe-customers-create", params),
|
|
364
|
+
retrieve: (params) => this.client.executeTool("stripe-customers-retrieve", { customerId: params.customerId }),
|
|
365
|
+
update: (params) => this.client.executeTool("stripe-customers-update", params),
|
|
366
|
+
listPaymentMethods: (params) => this.client.executeTool("stripe-customers-list-payment-methods", { customerId: params.customerId })
|
|
367
|
+
},
|
|
368
|
+
paymentIntents: {
|
|
369
|
+
create: (params) => this.client.executeTool("stripe-payment-intents-create", params),
|
|
370
|
+
retrieve: (params) => this.client.executeTool("stripe-payment-intents-retrieve", { paymentIntentId: params.paymentIntentId }),
|
|
371
|
+
confirm: (params) => this.client.executeTool("stripe-payment-intents-confirm", { paymentIntentId: params.paymentIntentId })
|
|
372
|
+
},
|
|
373
|
+
subscriptions: {
|
|
374
|
+
create: (params) => this.client.executeTool("stripe-subscriptions-create", params),
|
|
375
|
+
retrieve: (params) => this.client.executeTool("stripe-subscriptions-retrieve", { subscriptionId: params.subscriptionId }),
|
|
376
|
+
cancel: (params) => this.client.executeTool("stripe-subscriptions-cancel", { subscriptionId: params.subscriptionId })
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// src/namespaces/memory.ts
|
|
383
|
+
function createMemory(client) {
|
|
384
|
+
return {
|
|
385
|
+
create: (params) => client.executeTool("memory-create", params),
|
|
386
|
+
get: (params) => client.executeTool("memory-get", { memoryId: params.memoryId }),
|
|
387
|
+
recall: (params) => client.executeTool("memory-recall", params),
|
|
388
|
+
list: (params) => client.executeTool("memory-list", params ?? {}),
|
|
389
|
+
update: (params) => client.executeTool("memory-update", params),
|
|
390
|
+
delete: (params) => client.executeTool("memory-delete", { memoryId: params.memoryId })
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/namespaces/articles.ts
|
|
395
|
+
function createArticles(client) {
|
|
396
|
+
return {
|
|
397
|
+
search: (params) => client.executeTool("article-search", params),
|
|
398
|
+
create: (params) => client.executeTool("article-create", params),
|
|
399
|
+
createFromUrl: (params) => client.executeTool("article-create-from-url", params),
|
|
400
|
+
fetch: (params) => client.executeTool("article-fetch", params),
|
|
401
|
+
recent: (params) => client.executeTool("article-recent", params ?? {}),
|
|
402
|
+
relevant: (params) => client.executeTool("article-relevant-news", params),
|
|
403
|
+
summarize: (params) => client.executeTool("article-summarize", params),
|
|
404
|
+
extractTopics: (params) => client.executeTool("article-topic-extractor", params)
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// src/namespaces/web.ts
|
|
409
|
+
function createWeb(client) {
|
|
410
|
+
return {
|
|
411
|
+
search: {
|
|
412
|
+
exa: (params) => client.executeTool("exa-web-search", params),
|
|
413
|
+
perplexity: (params) => client.executeTool("perplexity-search", params)
|
|
414
|
+
},
|
|
415
|
+
fetch: (params) => client.executeTool("web-fetch", params),
|
|
416
|
+
htmlToMarkdown: (params) => client.executeTool("html-to-markdown-converter", params),
|
|
417
|
+
extractHtml: (params) => client.executeTool("extract-html-selector", params)
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// src/namespaces/ai.ts
|
|
422
|
+
function createAI(client) {
|
|
423
|
+
return {
|
|
424
|
+
embeddings: {
|
|
425
|
+
document: (params) => client.executeTool("jina-document-embedding", params),
|
|
426
|
+
query: (params) => client.executeTool("jina-query-embedding", params),
|
|
427
|
+
image: (params) => client.executeTool("jina-image-embedding", { image: params.imageBase64 })
|
|
428
|
+
},
|
|
429
|
+
image: {
|
|
430
|
+
generate: (params) => client.executeTool("image-generation", params)
|
|
431
|
+
},
|
|
432
|
+
ocr: (params) => client.executeTool("ocr-text-extraction", { image: params.imageBase64 }),
|
|
433
|
+
vision: (params) => client.executeTool("llama-scout-vision", { image: params.imageBase64, prompt: params.prompt }),
|
|
434
|
+
chat: (params) => client.executeTool("xai-chat-completions", params),
|
|
435
|
+
complete: (params) => client.executeTool("fim", params),
|
|
436
|
+
classify: (params) => client.executeTool("jina-document-classifier", params),
|
|
437
|
+
segment: (params) => client.executeTool("jina-text-segmenter", params)
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// src/namespaces/data.ts
|
|
442
|
+
function createData(client) {
|
|
443
|
+
return {
|
|
444
|
+
csv: {
|
|
445
|
+
query: (params) => client.executeTool("query-csv", params),
|
|
446
|
+
convert: (params) => client.executeTool("csv-convert", params)
|
|
447
|
+
},
|
|
448
|
+
scripts: {
|
|
449
|
+
create: (params) => client.executeTool("create-saved-script", params),
|
|
450
|
+
execute: (params) => client.executeTool("execute-saved-script", params),
|
|
451
|
+
list: () => client.executeTool("list-saved-scripts", {}),
|
|
452
|
+
update: (params) => client.executeTool("update-saved-script", params),
|
|
453
|
+
delete: (params) => client.executeTool("delete-saved-script", params)
|
|
454
|
+
},
|
|
455
|
+
similarity: {
|
|
456
|
+
search: (params) => client.executeTool("duck-db-similarity-search", params),
|
|
457
|
+
duckDbSearch: (params) => client.executeTool("duck-db-similarity-search", params)
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// src/namespaces/utils.ts
|
|
463
|
+
function createUtils(client) {
|
|
464
|
+
return {
|
|
465
|
+
mermaid: (params) => client.executeTool("mermaid-diagram-generator", { mermaid: params.diagram }),
|
|
466
|
+
documentConvert: (params) => client.executeTool("document-format-converter", {
|
|
467
|
+
base64: `data:${params.mimeType};base64,${Buffer.from(params.document).toString("base64")}`,
|
|
468
|
+
format: params.format
|
|
469
|
+
}),
|
|
470
|
+
regex: {
|
|
471
|
+
match: (params) => client.executeTool("regex-match", params),
|
|
472
|
+
replace: (params) => client.executeTool("regex-replace", params)
|
|
473
|
+
},
|
|
474
|
+
jsonExtract: (params) => client.executeTool("json-extract", params),
|
|
475
|
+
digest: (params) => client.executeTool("digest-generator", { text: params.data }),
|
|
476
|
+
monteCarlo: (params) => client.executeTool("monte-carlo-simulation", params)
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// src/sdk.ts
|
|
481
|
+
var Rainfall = class {
|
|
482
|
+
client;
|
|
483
|
+
_integrations;
|
|
484
|
+
_memory;
|
|
485
|
+
_articles;
|
|
486
|
+
_web;
|
|
487
|
+
_ai;
|
|
488
|
+
_data;
|
|
489
|
+
_utils;
|
|
490
|
+
constructor(config) {
|
|
491
|
+
this.client = new RainfallClient(config);
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Integrations namespace - GitHub, Notion, Linear, Slack, Figma, Stripe
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```typescript
|
|
498
|
+
* // GitHub
|
|
499
|
+
* await rainfall.integrations.github.issues.create({
|
|
500
|
+
* owner: 'facebook',
|
|
501
|
+
* repo: 'react',
|
|
502
|
+
* title: 'Bug report'
|
|
503
|
+
* });
|
|
504
|
+
*
|
|
505
|
+
* // Slack
|
|
506
|
+
* await rainfall.integrations.slack.messages.send({
|
|
507
|
+
* channelId: 'C123456',
|
|
508
|
+
* text: 'Hello team!'
|
|
509
|
+
* });
|
|
510
|
+
*
|
|
511
|
+
* // Linear
|
|
512
|
+
* const issues = await rainfall.integrations.linear.issues.list();
|
|
513
|
+
* ```
|
|
514
|
+
*/
|
|
515
|
+
get integrations() {
|
|
516
|
+
if (!this._integrations) {
|
|
517
|
+
this._integrations = createIntegrations(this.client);
|
|
518
|
+
}
|
|
519
|
+
return this._integrations;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Memory namespace - Semantic memory storage and retrieval
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```typescript
|
|
526
|
+
* // Store a memory
|
|
527
|
+
* await rainfall.memory.create({
|
|
528
|
+
* content: 'User prefers dark mode',
|
|
529
|
+
* keywords: ['preference', 'ui']
|
|
530
|
+
* });
|
|
531
|
+
*
|
|
532
|
+
* // Recall similar memories
|
|
533
|
+
* const memories = await rainfall.memory.recall({
|
|
534
|
+
* query: 'user preferences',
|
|
535
|
+
* topK: 5
|
|
536
|
+
* });
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
get memory() {
|
|
540
|
+
if (!this._memory) {
|
|
541
|
+
this._memory = createMemory(this.client);
|
|
542
|
+
}
|
|
543
|
+
return this._memory;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Articles namespace - News aggregation and article management
|
|
547
|
+
*
|
|
548
|
+
* @example
|
|
549
|
+
* ```typescript
|
|
550
|
+
* // Search news
|
|
551
|
+
* const articles = await rainfall.articles.search({
|
|
552
|
+
* query: 'artificial intelligence'
|
|
553
|
+
* });
|
|
554
|
+
*
|
|
555
|
+
* // Create from URL
|
|
556
|
+
* const article = await rainfall.articles.createFromUrl({
|
|
557
|
+
* url: 'https://example.com/article'
|
|
558
|
+
* });
|
|
559
|
+
*
|
|
560
|
+
* // Summarize
|
|
561
|
+
* const summary = await rainfall.articles.summarize({
|
|
562
|
+
* text: article.content
|
|
563
|
+
* });
|
|
564
|
+
* ```
|
|
565
|
+
*/
|
|
566
|
+
get articles() {
|
|
567
|
+
if (!this._articles) {
|
|
568
|
+
this._articles = createArticles(this.client);
|
|
569
|
+
}
|
|
570
|
+
return this._articles;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Web namespace - Web search, scraping, and content extraction
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* ```typescript
|
|
577
|
+
* // Search with Exa
|
|
578
|
+
* const results = await rainfall.web.search.exa({
|
|
579
|
+
* query: 'latest AI research'
|
|
580
|
+
* });
|
|
581
|
+
*
|
|
582
|
+
* // Fetch and convert
|
|
583
|
+
* const html = await rainfall.web.fetch({ url: 'https://example.com' });
|
|
584
|
+
* const markdown = await rainfall.web.htmlToMarkdown({ html });
|
|
585
|
+
*
|
|
586
|
+
* // Extract specific elements
|
|
587
|
+
* const links = await rainfall.web.extractHtml({
|
|
588
|
+
* html,
|
|
589
|
+
* selector: 'a[href]'
|
|
590
|
+
* });
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
get web() {
|
|
594
|
+
if (!this._web) {
|
|
595
|
+
this._web = createWeb(this.client);
|
|
596
|
+
}
|
|
597
|
+
return this._web;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* AI namespace - Embeddings, image generation, OCR, vision, chat
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* // Generate embeddings
|
|
605
|
+
* const embedding = await rainfall.ai.embeddings.document({
|
|
606
|
+
* text: 'Hello world'
|
|
607
|
+
* });
|
|
608
|
+
*
|
|
609
|
+
* // Generate image
|
|
610
|
+
* const image = await rainfall.ai.image.generate({
|
|
611
|
+
* prompt: 'A serene mountain landscape'
|
|
612
|
+
* });
|
|
613
|
+
*
|
|
614
|
+
* // OCR
|
|
615
|
+
* const text = await rainfall.ai.ocr({ imageBase64: '...' });
|
|
616
|
+
*
|
|
617
|
+
* // Chat
|
|
618
|
+
* const response = await rainfall.ai.chat({
|
|
619
|
+
* messages: [{ role: 'user', content: 'Hello!' }]
|
|
620
|
+
* });
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
get ai() {
|
|
624
|
+
if (!this._ai) {
|
|
625
|
+
this._ai = createAI(this.client);
|
|
626
|
+
}
|
|
627
|
+
return this._ai;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Data namespace - CSV processing, scripts, similarity search
|
|
631
|
+
*
|
|
632
|
+
* @example
|
|
633
|
+
* ```typescript
|
|
634
|
+
* // Query CSV with SQL
|
|
635
|
+
* const results = await rainfall.data.csv.query({
|
|
636
|
+
* sql: 'SELECT * FROM data WHERE value > 100'
|
|
637
|
+
* });
|
|
638
|
+
*
|
|
639
|
+
* // Execute saved script
|
|
640
|
+
* const result = await rainfall.data.scripts.execute({
|
|
641
|
+
* name: 'my-script',
|
|
642
|
+
* params: { input: 'data' }
|
|
643
|
+
* });
|
|
644
|
+
* ```
|
|
645
|
+
*/
|
|
646
|
+
get data() {
|
|
647
|
+
if (!this._data) {
|
|
648
|
+
this._data = createData(this.client);
|
|
649
|
+
}
|
|
650
|
+
return this._data;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Utils namespace - Mermaid diagrams, document conversion, regex, JSON extraction
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
* ```typescript
|
|
657
|
+
* // Generate diagram
|
|
658
|
+
* const diagram = await rainfall.utils.mermaid({
|
|
659
|
+
* diagram: 'graph TD; A-->B;'
|
|
660
|
+
* });
|
|
661
|
+
*
|
|
662
|
+
* // Convert document
|
|
663
|
+
* const pdf = await rainfall.utils.documentConvert({
|
|
664
|
+
* document: markdownContent,
|
|
665
|
+
* mimeType: 'text/markdown',
|
|
666
|
+
* format: 'pdf'
|
|
667
|
+
* });
|
|
668
|
+
*
|
|
669
|
+
* // Extract JSON from text
|
|
670
|
+
* const json = await rainfall.utils.jsonExtract({
|
|
671
|
+
* text: 'Here is some data: {"key": "value"}'
|
|
672
|
+
* });
|
|
673
|
+
* ```
|
|
674
|
+
*/
|
|
675
|
+
get utils() {
|
|
676
|
+
if (!this._utils) {
|
|
677
|
+
this._utils = createUtils(this.client);
|
|
678
|
+
}
|
|
679
|
+
return this._utils;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Get the underlying HTTP client for advanced usage
|
|
683
|
+
*/
|
|
684
|
+
getClient() {
|
|
685
|
+
return this.client;
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* List all available tools
|
|
689
|
+
*/
|
|
690
|
+
async listTools() {
|
|
691
|
+
return this.client.listTools();
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Get schema for a specific tool
|
|
695
|
+
*/
|
|
696
|
+
async getToolSchema(toolId) {
|
|
697
|
+
return this.client.getToolSchema(toolId);
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Execute any tool by ID (low-level access)
|
|
701
|
+
*/
|
|
702
|
+
async executeTool(toolId, params) {
|
|
703
|
+
return this.client.executeTool(toolId, params);
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Get current subscriber info and usage
|
|
707
|
+
*/
|
|
708
|
+
async getMe() {
|
|
709
|
+
return this.client.getMe();
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Get current rate limit info
|
|
713
|
+
*/
|
|
714
|
+
getRateLimitInfo() {
|
|
715
|
+
return this.client.getRateLimitInfo();
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
// src/cli/index.ts
|
|
720
|
+
var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".rainfall");
|
|
721
|
+
var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
|
|
722
|
+
function loadConfig() {
|
|
723
|
+
if (!(0, import_fs.existsSync)(CONFIG_FILE)) {
|
|
724
|
+
return {};
|
|
725
|
+
}
|
|
726
|
+
try {
|
|
727
|
+
return JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf8"));
|
|
728
|
+
} catch {
|
|
729
|
+
return {};
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function saveConfig(config) {
|
|
733
|
+
if (!(0, import_fs.existsSync)(CONFIG_DIR)) {
|
|
734
|
+
(0, import_fs.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
735
|
+
}
|
|
736
|
+
(0, import_fs.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
737
|
+
}
|
|
738
|
+
function getRainfall() {
|
|
739
|
+
const config = loadConfig();
|
|
740
|
+
if (!config.apiKey) {
|
|
741
|
+
console.error("Error: No API key configured. Run: rainfall auth login");
|
|
742
|
+
process.exit(1);
|
|
743
|
+
}
|
|
744
|
+
return new Rainfall({
|
|
745
|
+
apiKey: config.apiKey,
|
|
746
|
+
baseUrl: config.baseUrl
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
function printHelp() {
|
|
750
|
+
console.log(`
|
|
751
|
+
Rainfall CLI - 200+ tools, one key
|
|
752
|
+
|
|
753
|
+
Usage:
|
|
754
|
+
rainfall <command> [options]
|
|
755
|
+
|
|
756
|
+
Commands:
|
|
757
|
+
auth login Store API key
|
|
758
|
+
auth logout Remove stored API key
|
|
759
|
+
auth status Check authentication status
|
|
760
|
+
|
|
761
|
+
tools list List all available tools
|
|
762
|
+
tools describe <tool> Show tool schema and description
|
|
763
|
+
tools search <query> Search for tools
|
|
764
|
+
|
|
765
|
+
run <tool> [options] Execute a tool
|
|
766
|
+
|
|
767
|
+
me Show account info and usage
|
|
768
|
+
|
|
769
|
+
config get [key] Get configuration value
|
|
770
|
+
config set <key> <value> Set configuration value
|
|
771
|
+
|
|
772
|
+
help Show this help message
|
|
773
|
+
|
|
774
|
+
Options for 'run':
|
|
775
|
+
--params, -p <json> Tool parameters as JSON
|
|
776
|
+
--file, -f <path> Read parameters from file
|
|
777
|
+
--raw Output raw JSON
|
|
778
|
+
|
|
779
|
+
Examples:
|
|
780
|
+
rainfall auth login
|
|
781
|
+
rainfall tools list
|
|
782
|
+
rainfall tools describe github-create-issue
|
|
783
|
+
rainfall run exa-web-search -p '{"query": "AI news"}'
|
|
784
|
+
rainfall run article-summarize -f ./article.json
|
|
785
|
+
echo '{"query": "hello"}' | rainfall run exa-web-search
|
|
786
|
+
`);
|
|
787
|
+
}
|
|
788
|
+
async function authLogin(args) {
|
|
789
|
+
const apiKey = args[0] || process.env.RAINFALL_API_KEY;
|
|
790
|
+
if (!apiKey) {
|
|
791
|
+
console.error("Error: API key required. Provide as argument or set RAINFALL_API_KEY environment variable.");
|
|
792
|
+
console.error("\nUsage: rainfall auth login <api-key>");
|
|
793
|
+
process.exit(1);
|
|
794
|
+
}
|
|
795
|
+
try {
|
|
796
|
+
const rainfall = new Rainfall({ apiKey });
|
|
797
|
+
const me = await rainfall.getMe();
|
|
798
|
+
saveConfig({ apiKey });
|
|
799
|
+
console.log(`\u2713 Authenticated as ${me.email}`);
|
|
800
|
+
console.log(` Plan: ${me.plan}`);
|
|
801
|
+
console.log(` Usage: ${me.usage.callsThisMonth.toLocaleString()} / ${me.usage.callsLimit.toLocaleString()} calls this month`);
|
|
802
|
+
} catch (error) {
|
|
803
|
+
console.error("Error: Invalid API key");
|
|
804
|
+
process.exit(1);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
function authLogout() {
|
|
808
|
+
saveConfig({});
|
|
809
|
+
console.log("\u2713 Logged out");
|
|
810
|
+
}
|
|
811
|
+
async function authStatus() {
|
|
812
|
+
const config = loadConfig();
|
|
813
|
+
if (!config.apiKey) {
|
|
814
|
+
console.log("Not authenticated");
|
|
815
|
+
console.log("Run: rainfall auth login <api-key>");
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
try {
|
|
819
|
+
const rainfall = new Rainfall({ apiKey: config.apiKey });
|
|
820
|
+
const me = await rainfall.getMe();
|
|
821
|
+
console.log(`Authenticated as ${me.email}`);
|
|
822
|
+
console.log(`Plan: ${me.plan}`);
|
|
823
|
+
console.log(`Usage: ${me.usage.callsThisMonth.toLocaleString()} / ${me.usage.callsLimit.toLocaleString()} calls this month`);
|
|
824
|
+
} catch (error) {
|
|
825
|
+
console.log("Authentication expired or invalid");
|
|
826
|
+
console.log("Run: rainfall auth login <api-key>");
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
async function listTools() {
|
|
830
|
+
const rainfall = getRainfall();
|
|
831
|
+
const tools = await rainfall.listTools();
|
|
832
|
+
const byCategory = /* @__PURE__ */ new Map();
|
|
833
|
+
for (const tool of tools) {
|
|
834
|
+
const category = tool.category || "uncategorized";
|
|
835
|
+
if (!byCategory.has(category)) {
|
|
836
|
+
byCategory.set(category, []);
|
|
837
|
+
}
|
|
838
|
+
byCategory.get(category).push(tool);
|
|
839
|
+
}
|
|
840
|
+
console.log(`Available tools (${tools.length} total):
|
|
841
|
+
`);
|
|
842
|
+
for (const [category, categoryTools] of byCategory) {
|
|
843
|
+
console.log(`${category}:`);
|
|
844
|
+
for (const tool of categoryTools) {
|
|
845
|
+
console.log(` ${tool.id.padEnd(30)} ${tool.description.slice(0, 50)}${tool.description.length > 50 ? "..." : ""}`);
|
|
846
|
+
}
|
|
847
|
+
console.log();
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
async function describeTool(args) {
|
|
851
|
+
const toolId = args[0];
|
|
852
|
+
if (!toolId) {
|
|
853
|
+
console.error("Error: Tool ID required");
|
|
854
|
+
console.error("\nUsage: rainfall tools describe <tool-id>");
|
|
855
|
+
process.exit(1);
|
|
856
|
+
}
|
|
857
|
+
const rainfall = getRainfall();
|
|
858
|
+
try {
|
|
859
|
+
const schema = await rainfall.getToolSchema(toolId);
|
|
860
|
+
console.log(`Tool: ${schema.name}`);
|
|
861
|
+
console.log(`Description: ${schema.description}`);
|
|
862
|
+
console.log(`Category: ${schema.category}`);
|
|
863
|
+
console.log(`
|
|
864
|
+
Parameters:`);
|
|
865
|
+
console.log(JSON.stringify(schema.parameters, null, 2));
|
|
866
|
+
console.log(`
|
|
867
|
+
Output:`);
|
|
868
|
+
console.log(JSON.stringify(schema.output, null, 2));
|
|
869
|
+
} catch (error) {
|
|
870
|
+
console.error(`Error: Tool '${toolId}' not found`);
|
|
871
|
+
process.exit(1);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
async function searchTools(args) {
|
|
875
|
+
const query = args[0];
|
|
876
|
+
if (!query) {
|
|
877
|
+
console.error("Error: Search query required");
|
|
878
|
+
console.error("\nUsage: rainfall tools search <query>");
|
|
879
|
+
process.exit(1);
|
|
880
|
+
}
|
|
881
|
+
const rainfall = getRainfall();
|
|
882
|
+
const tools = await rainfall.listTools();
|
|
883
|
+
const lowerQuery = query.toLowerCase();
|
|
884
|
+
const matches = tools.filter(
|
|
885
|
+
(t) => t.id.toLowerCase().includes(lowerQuery) || t.description.toLowerCase().includes(lowerQuery) || t.category.toLowerCase().includes(lowerQuery)
|
|
886
|
+
);
|
|
887
|
+
if (matches.length === 0) {
|
|
888
|
+
console.log(`No tools found matching '${query}'`);
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
console.log(`Found ${matches.length} tool(s) matching '${query}':
|
|
892
|
+
`);
|
|
893
|
+
for (const tool of matches) {
|
|
894
|
+
console.log(` ${tool.id.padEnd(30)} ${tool.description.slice(0, 50)}${tool.description.length > 50 ? "..." : ""}`);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
async function runTool(args) {
|
|
898
|
+
const toolId = args[0];
|
|
899
|
+
if (!toolId) {
|
|
900
|
+
console.error("Error: Tool ID required");
|
|
901
|
+
console.error("\nUsage: rainfall run <tool-id> [options]");
|
|
902
|
+
process.exit(1);
|
|
903
|
+
}
|
|
904
|
+
let params = {};
|
|
905
|
+
for (let i = 1; i < args.length; i++) {
|
|
906
|
+
const arg = args[i];
|
|
907
|
+
if (arg === "--params" || arg === "-p") {
|
|
908
|
+
const json = args[++i];
|
|
909
|
+
if (!json) {
|
|
910
|
+
console.error("Error: --params requires a JSON string");
|
|
911
|
+
process.exit(1);
|
|
912
|
+
}
|
|
913
|
+
try {
|
|
914
|
+
params = JSON.parse(json);
|
|
915
|
+
} catch {
|
|
916
|
+
console.error("Error: Invalid JSON for --params");
|
|
917
|
+
process.exit(1);
|
|
918
|
+
}
|
|
919
|
+
} else if (arg === "--file" || arg === "-f") {
|
|
920
|
+
const filePath = args[++i];
|
|
921
|
+
if (!filePath) {
|
|
922
|
+
console.error("Error: --file requires a file path");
|
|
923
|
+
process.exit(1);
|
|
924
|
+
}
|
|
925
|
+
try {
|
|
926
|
+
params = JSON.parse((0, import_fs.readFileSync)(filePath, "utf8"));
|
|
927
|
+
} catch {
|
|
928
|
+
console.error(`Error: Could not read or parse file: ${filePath}`);
|
|
929
|
+
process.exit(1);
|
|
930
|
+
}
|
|
931
|
+
} else if (arg === "--raw") {
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
if (!process.stdin.isTTY) {
|
|
935
|
+
const chunks = [];
|
|
936
|
+
for await (const chunk of process.stdin) {
|
|
937
|
+
chunks.push(chunk);
|
|
938
|
+
}
|
|
939
|
+
if (chunks.length > 0) {
|
|
940
|
+
try {
|
|
941
|
+
const piped = JSON.parse(Buffer.concat(chunks).toString());
|
|
942
|
+
params = { ...params, ...piped };
|
|
943
|
+
} catch {
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
const rainfall = getRainfall();
|
|
948
|
+
try {
|
|
949
|
+
const result = await rainfall.executeTool(toolId, params);
|
|
950
|
+
if (args.includes("--raw")) {
|
|
951
|
+
console.log(JSON.stringify(result));
|
|
952
|
+
} else {
|
|
953
|
+
console.log(JSON.stringify(result, null, 2));
|
|
954
|
+
}
|
|
955
|
+
} catch (error) {
|
|
956
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
957
|
+
console.error(`Error: ${message}`);
|
|
958
|
+
process.exit(1);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
async function showMe() {
|
|
962
|
+
const rainfall = getRainfall();
|
|
963
|
+
const me = await rainfall.getMe();
|
|
964
|
+
console.log(`Account: ${me.email}`);
|
|
965
|
+
console.log(`ID: ${me.id}`);
|
|
966
|
+
console.log(`Plan: ${me.plan}`);
|
|
967
|
+
console.log(`Usage: ${me.usage.callsThisMonth.toLocaleString()} / ${me.usage.callsLimit.toLocaleString()} calls this month`);
|
|
968
|
+
console.log(`Remaining: ${(me.usage.callsLimit - me.usage.callsThisMonth).toLocaleString()} calls`);
|
|
969
|
+
}
|
|
970
|
+
function configGet(args) {
|
|
971
|
+
const key = args[0];
|
|
972
|
+
const config = loadConfig();
|
|
973
|
+
if (key) {
|
|
974
|
+
console.log(config[key] || "");
|
|
975
|
+
} else {
|
|
976
|
+
console.log(JSON.stringify(config, null, 2));
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
function configSet(args) {
|
|
980
|
+
const key = args[0];
|
|
981
|
+
const value = args[1];
|
|
982
|
+
if (!key || !value) {
|
|
983
|
+
console.error("Error: Both key and value required");
|
|
984
|
+
console.error("\nUsage: rainfall config set <key> <value>");
|
|
985
|
+
process.exit(1);
|
|
986
|
+
}
|
|
987
|
+
const config = loadConfig();
|
|
988
|
+
config[key] = value;
|
|
989
|
+
saveConfig(config);
|
|
990
|
+
console.log(`\u2713 Set ${key} = ${value}`);
|
|
991
|
+
}
|
|
992
|
+
async function main() {
|
|
993
|
+
const args = process.argv.slice(2);
|
|
994
|
+
const command = args[0];
|
|
995
|
+
const subcommand = args[1];
|
|
996
|
+
const rest = args.slice(2);
|
|
997
|
+
switch (command) {
|
|
998
|
+
case "auth":
|
|
999
|
+
switch (subcommand) {
|
|
1000
|
+
case "login":
|
|
1001
|
+
await authLogin(rest);
|
|
1002
|
+
break;
|
|
1003
|
+
case "logout":
|
|
1004
|
+
authLogout();
|
|
1005
|
+
break;
|
|
1006
|
+
case "status":
|
|
1007
|
+
await authStatus();
|
|
1008
|
+
break;
|
|
1009
|
+
default:
|
|
1010
|
+
console.error("Error: Unknown auth subcommand");
|
|
1011
|
+
console.error("\nUsage: rainfall auth <login|logout|status>");
|
|
1012
|
+
process.exit(1);
|
|
1013
|
+
}
|
|
1014
|
+
break;
|
|
1015
|
+
case "tools":
|
|
1016
|
+
switch (subcommand) {
|
|
1017
|
+
case "list":
|
|
1018
|
+
await listTools();
|
|
1019
|
+
break;
|
|
1020
|
+
case "describe":
|
|
1021
|
+
await describeTool(rest);
|
|
1022
|
+
break;
|
|
1023
|
+
case "search":
|
|
1024
|
+
await searchTools(rest);
|
|
1025
|
+
break;
|
|
1026
|
+
default:
|
|
1027
|
+
console.error("Error: Unknown tools subcommand");
|
|
1028
|
+
console.error("\nUsage: rainfall tools <list|describe|search>");
|
|
1029
|
+
process.exit(1);
|
|
1030
|
+
}
|
|
1031
|
+
break;
|
|
1032
|
+
case "run":
|
|
1033
|
+
await runTool(rest);
|
|
1034
|
+
break;
|
|
1035
|
+
case "me":
|
|
1036
|
+
await showMe();
|
|
1037
|
+
break;
|
|
1038
|
+
case "config":
|
|
1039
|
+
switch (subcommand) {
|
|
1040
|
+
case "get":
|
|
1041
|
+
configGet(rest);
|
|
1042
|
+
break;
|
|
1043
|
+
case "set":
|
|
1044
|
+
configSet(rest);
|
|
1045
|
+
break;
|
|
1046
|
+
default:
|
|
1047
|
+
console.error("Error: Unknown config subcommand");
|
|
1048
|
+
console.error("\nUsage: rainfall config <get|set>");
|
|
1049
|
+
process.exit(1);
|
|
1050
|
+
}
|
|
1051
|
+
break;
|
|
1052
|
+
case "help":
|
|
1053
|
+
case "--help":
|
|
1054
|
+
case "-h":
|
|
1055
|
+
case void 0:
|
|
1056
|
+
printHelp();
|
|
1057
|
+
break;
|
|
1058
|
+
default:
|
|
1059
|
+
console.error(`Error: Unknown command '${command}'`);
|
|
1060
|
+
console.error("\nRun `rainfall help` for usage information.");
|
|
1061
|
+
process.exit(1);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
main().catch((error) => {
|
|
1065
|
+
console.error("Unexpected error:", error);
|
|
1066
|
+
process.exit(1);
|
|
1067
|
+
});
|