@caphub/cli 0.1.2 → 0.1.4
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 +8 -2
- package/bin/caphub.js +50 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,10 +16,16 @@ npx @caphub/cli help
|
|
|
16
16
|
|
|
17
17
|
## Auth
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Open the website approval flow:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
caphub auth login
|
|
22
|
+
caphub auth login
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
For headless/cloud agents, put the key in the platform secret manager and expose it as:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
CAPHUB_API_KEY=csk_live_...
|
|
23
29
|
```
|
|
24
30
|
|
|
25
31
|
## Discovery
|
package/bin/caphub.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import { dirname, resolve } from "node:path";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import { createInterface } from "node:readline/promises";
|
|
6
8
|
import { fileURLToPath } from "node:url";
|
|
7
9
|
|
|
8
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -24,7 +26,7 @@ commands:
|
|
|
24
26
|
help <capability> show capability-specific help from the API
|
|
25
27
|
capabilities list live capabilities with short descriptions
|
|
26
28
|
auth show current login state
|
|
27
|
-
auth login website login flow; stores api key locally after approval
|
|
29
|
+
auth login open website login flow; stores api key locally after approval
|
|
28
30
|
auth whoami verify the current api key against the API
|
|
29
31
|
auth logout remove stored api key from local config
|
|
30
32
|
<capability> <json> run a capability directly, e.g. search or search-ideas
|
|
@@ -96,6 +98,27 @@ function fail(message) {
|
|
|
96
98
|
process.exit(1);
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
function openUrl(url) {
|
|
102
|
+
if (process.env.CAPHUB_NO_OPEN === "1") return false;
|
|
103
|
+
|
|
104
|
+
const command = process.platform === "darwin"
|
|
105
|
+
? "open"
|
|
106
|
+
: process.platform === "win32"
|
|
107
|
+
? "cmd"
|
|
108
|
+
: "xdg-open";
|
|
109
|
+
const args = process.platform === "win32"
|
|
110
|
+
? ["/c", "start", "", url]
|
|
111
|
+
: [url];
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const child = spawn(command, args, { detached: true, stdio: "ignore" });
|
|
115
|
+
child.unref();
|
|
116
|
+
return true;
|
|
117
|
+
} catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
99
122
|
function readStdin() {
|
|
100
123
|
return new Promise((resolveInput) => {
|
|
101
124
|
let data = "";
|
|
@@ -135,6 +158,22 @@ async function fetchJson(url, { method = "GET", body, apiKey = "" } = {}) {
|
|
|
135
158
|
return data;
|
|
136
159
|
}
|
|
137
160
|
|
|
161
|
+
async function waitForEnterToOpen(url) {
|
|
162
|
+
if (process.env.CAPHUB_NO_OPEN === "1") return false;
|
|
163
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
164
|
+
|
|
165
|
+
const rl = createInterface({
|
|
166
|
+
input: process.stdin,
|
|
167
|
+
output: process.stdout,
|
|
168
|
+
});
|
|
169
|
+
try {
|
|
170
|
+
await rl.question("Press Enter to open the browser login page, or Ctrl+C to cancel.");
|
|
171
|
+
} finally {
|
|
172
|
+
rl.close();
|
|
173
|
+
}
|
|
174
|
+
return openUrl(url);
|
|
175
|
+
}
|
|
176
|
+
|
|
138
177
|
function parseFlag(args, name) {
|
|
139
178
|
const idx = args.indexOf(name);
|
|
140
179
|
if (idx === -1) return "";
|
|
@@ -317,12 +356,19 @@ async function commandAuth(args) {
|
|
|
317
356
|
process.stdout.write([
|
|
318
357
|
"caphub auth login",
|
|
319
358
|
"",
|
|
320
|
-
"
|
|
321
|
-
started.approval_url,
|
|
322
|
-
"",
|
|
359
|
+
"This will open Caphub in your browser to approve CLI login.",
|
|
323
360
|
`code: ${started.code}`,
|
|
324
361
|
`expires_in_seconds: ${started.expires_in_seconds}`,
|
|
362
|
+
`url: ${started.approval_url}`,
|
|
325
363
|
"",
|
|
364
|
+
].join("\n"));
|
|
365
|
+
|
|
366
|
+
const opened = await waitForEnterToOpen(started.approval_url);
|
|
367
|
+
process.stdout.write([
|
|
368
|
+
process.env.CAPHUB_NO_OPEN === "1"
|
|
369
|
+
? "browser_open: disabled by CAPHUB_NO_OPEN=1"
|
|
370
|
+
: `browser_open: ${opened ? "attempted" : "not attempted"}`,
|
|
371
|
+
opened ? "If the browser did not open, copy the URL above." : "Open the URL above in your browser.",
|
|
326
372
|
"Waiting for website approval...",
|
|
327
373
|
"",
|
|
328
374
|
].join("\n"));
|