@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 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.1";
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
- const apiKey = args.apiKey || process.env.CARAVO_API_KEY;
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caravo/cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Caravo CLI — search, execute, and review tools with API key or x402 USDC payments",
5
5
  "type": "module",
6
6
  "bin": {