@caravo/cli 0.2.1 → 0.2.2
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/cli.js +7 -1
- package/dist/commands/login.js +67 -0
- package/dist/lib/auth.js +17 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -22,6 +22,7 @@ Commands:
|
|
|
22
22
|
request --title <t> --desc <d>
|
|
23
23
|
Submit a tool request
|
|
24
24
|
request-upvote <req-id> Upvote a tool request
|
|
25
|
+
login Connect your Caravo account via browser (saves API key)
|
|
25
26
|
wallet Show wallet + balance info
|
|
26
27
|
fetch [METHOD] <url> Raw x402 HTTP request
|
|
27
28
|
|
|
@@ -178,7 +179,7 @@ function parseArgs(argv) {
|
|
|
178
179
|
}
|
|
179
180
|
return args;
|
|
180
181
|
}
|
|
181
|
-
const VERSION = "0.2.
|
|
182
|
+
const VERSION = "0.2.2";
|
|
182
183
|
async function main() {
|
|
183
184
|
const args = parseArgs(process.argv.slice(2));
|
|
184
185
|
if (args.version) {
|
|
@@ -282,6 +283,11 @@ async function main() {
|
|
|
282
283
|
await runReqUpvote(args.positional[0], args.exec, auth, args.compact);
|
|
283
284
|
break;
|
|
284
285
|
}
|
|
286
|
+
case "login": {
|
|
287
|
+
const { runLogin } = await import("./commands/login.js");
|
|
288
|
+
await runLogin(auth.baseUrl);
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
285
291
|
case "wallet": {
|
|
286
292
|
const { run } = await import("./commands/wallet-cmd.js");
|
|
287
293
|
await run(auth, args.compact);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { exec } from "child_process";
|
|
5
|
+
const CONFIG_DIR = join(homedir(), ".caravo");
|
|
6
|
+
const CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
7
|
+
function loadConfig() {
|
|
8
|
+
try {
|
|
9
|
+
if (!existsSync(CONFIG_FILE))
|
|
10
|
+
return {};
|
|
11
|
+
return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function saveConfig(data) {
|
|
18
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
19
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
20
|
+
}
|
|
21
|
+
function openBrowser(url) {
|
|
22
|
+
const opener = process.platform === "darwin"
|
|
23
|
+
? `open "${url}"`
|
|
24
|
+
: process.platform === "win32"
|
|
25
|
+
? `start "" "${url}"`
|
|
26
|
+
: `xdg-open "${url}"`;
|
|
27
|
+
exec(opener);
|
|
28
|
+
}
|
|
29
|
+
export async function runLogin(baseUrl) {
|
|
30
|
+
// 1. Create session
|
|
31
|
+
process.stdout.write("Opening browser for login...\n");
|
|
32
|
+
const initRes = await fetch(`${baseUrl}/api/auth/mcp-session`, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "Content-Type": "application/json" },
|
|
35
|
+
});
|
|
36
|
+
if (!initRes.ok) {
|
|
37
|
+
process.stderr.write(`[caravo] login: server error ${initRes.status}\n`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
const { token, url } = (await initRes.json());
|
|
41
|
+
// 2. Open browser
|
|
42
|
+
openBrowser(url);
|
|
43
|
+
process.stdout.write(`\nOpened: ${url}\n\nWaiting for login (5 min timeout)...\n`);
|
|
44
|
+
// 3. Poll every 2s
|
|
45
|
+
const deadline = Date.now() + 5 * 60 * 1000;
|
|
46
|
+
while (Date.now() < deadline) {
|
|
47
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
48
|
+
const pollRes = await fetch(`${baseUrl}/api/auth/mcp-session?token=${encodeURIComponent(token)}`);
|
|
49
|
+
const poll = (await pollRes.json());
|
|
50
|
+
if (poll.status === "completed" && poll.api_key) {
|
|
51
|
+
// 4. Save to config
|
|
52
|
+
const existing = loadConfig();
|
|
53
|
+
saveConfig({ ...existing, api_key: poll.api_key });
|
|
54
|
+
process.stdout.write(`\n✓ Logged in! API key saved to ${CONFIG_FILE}\n\n`);
|
|
55
|
+
process.stdout.write(`To use it immediately (this shell session):\n export CARAVO_API_KEY=${poll.api_key}\n\n`);
|
|
56
|
+
process.stdout.write(`To make it permanent, add to your shell profile (~/.zshrc / ~/.bashrc):\n export CARAVO_API_KEY=${poll.api_key}\n`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (poll.status === "expired") {
|
|
60
|
+
process.stderr.write("[caravo] login: session expired. Run `caravo login` again.\n");
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
process.stdout.write(".");
|
|
64
|
+
}
|
|
65
|
+
process.stderr.write("\n[caravo] login: timed out after 5 minutes.\n");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
package/dist/lib/auth.js
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
1
4
|
import { loadOrCreateWallet } from "../wallet.js";
|
|
2
5
|
const DEFAULT_BASE_URL = "https://caravo.ai";
|
|
6
|
+
const CONFIG_FILE = join(homedir(), ".caravo", "config.json");
|
|
7
|
+
function readConfigApiKey() {
|
|
8
|
+
try {
|
|
9
|
+
if (!existsSync(CONFIG_FILE))
|
|
10
|
+
return undefined;
|
|
11
|
+
const c = JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
|
|
12
|
+
return typeof c.api_key === "string" ? c.api_key : undefined;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
3
18
|
export function resolveAuth(args) {
|
|
4
|
-
|
|
19
|
+
// Priority: explicit --api-key flag → CARAVO_API_KEY env → ~/.caravo/config.json
|
|
20
|
+
const apiKey = args.apiKey || process.env.CARAVO_API_KEY || readConfigApiKey();
|
|
5
21
|
const baseUrl = args.baseUrl || process.env.CARAVO_URL || DEFAULT_BASE_URL;
|
|
6
22
|
let cached;
|
|
7
23
|
return {
|