@caravo/cli 0.2.1 → 0.2.3

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,8 @@ 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)
26
+ logout Disconnect account and switch to x402 wallet payments
25
27
  wallet Show wallet + balance info
26
28
  fetch [METHOD] <url> Raw x402 HTTP request
27
29
 
@@ -178,7 +180,7 @@ function parseArgs(argv) {
178
180
  }
179
181
  return args;
180
182
  }
181
- const VERSION = "0.2.1";
183
+ const VERSION = "0.2.2";
182
184
  async function main() {
183
185
  const args = parseArgs(process.argv.slice(2));
184
186
  if (args.version) {
@@ -282,6 +284,16 @@ async function main() {
282
284
  await runReqUpvote(args.positional[0], args.exec, auth, args.compact);
283
285
  break;
284
286
  }
287
+ case "login": {
288
+ const { runLogin } = await import("./commands/login.js");
289
+ await runLogin(auth.baseUrl);
290
+ break;
291
+ }
292
+ case "logout": {
293
+ const { runLogout } = await import("./commands/logout.js");
294
+ runLogout();
295
+ break;
296
+ }
285
297
  case "wallet": {
286
298
  const { run } = await import("./commands/wallet-cmd.js");
287
299
  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
+ }
@@ -0,0 +1,30 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
2
+ import { homedir } from "os";
3
+ import { join } from "path";
4
+ const CONFIG_DIR = join(homedir(), ".caravo");
5
+ const CONFIG_FILE = join(CONFIG_DIR, "config.json");
6
+ function loadConfig() {
7
+ try {
8
+ if (!existsSync(CONFIG_FILE))
9
+ return {};
10
+ return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
11
+ }
12
+ catch {
13
+ return {};
14
+ }
15
+ }
16
+ function saveConfig(data) {
17
+ mkdirSync(CONFIG_DIR, { recursive: true });
18
+ writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), { mode: 0o600 });
19
+ }
20
+ export function runLogout() {
21
+ const config = loadConfig();
22
+ if (!config.api_key) {
23
+ process.stdout.write("Not logged in — already using x402 wallet payments.\n");
24
+ return;
25
+ }
26
+ delete config.api_key;
27
+ saveConfig(config);
28
+ process.stdout.write(`✓ Logged out. API key removed from ${CONFIG_FILE}\n`);
29
+ process.stdout.write(`Now using x402 wallet payments.\n`);
30
+ }
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.3",
4
4
  "description": "Caravo CLI — search, execute, and review tools with API key or x402 USDC payments",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,16 @@
17
17
  "typescript": "^5.8.2",
18
18
  "@types/node": "^22"
19
19
  },
20
- "keywords": ["caravo", "marketplace", "cli", "x402", "usdc", "base", "agent", "mcp"],
20
+ "keywords": [
21
+ "caravo",
22
+ "marketplace",
23
+ "cli",
24
+ "x402",
25
+ "usdc",
26
+ "base",
27
+ "agent",
28
+ "mcp"
29
+ ],
21
30
  "repository": {
22
31
  "type": "git",
23
32
  "url": "https://github.com/Caravo-AI/Caravo-CLI"