@caphub/cli 0.1.1 → 0.1.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/bin/caphub.js +95 -6
- package/package.json +1 -1
package/bin/caphub.js
CHANGED
|
@@ -23,7 +23,8 @@ commands:
|
|
|
23
23
|
help explain the platform and command layout
|
|
24
24
|
help <capability> show capability-specific help from the API
|
|
25
25
|
capabilities list live capabilities with short descriptions
|
|
26
|
-
auth login
|
|
26
|
+
auth show current login state
|
|
27
|
+
auth login website login flow; stores api key locally after approval
|
|
27
28
|
auth whoami verify the current api key against the API
|
|
28
29
|
auth logout remove stored api key from local config
|
|
29
30
|
<capability> <json> run a capability directly, e.g. search or search-ideas
|
|
@@ -31,18 +32,20 @@ commands:
|
|
|
31
32
|
agent workflow:
|
|
32
33
|
1. caphub capabilities
|
|
33
34
|
2. caphub help <capability>
|
|
34
|
-
3. caphub auth login
|
|
35
|
+
3. caphub auth login
|
|
35
36
|
4. caphub <capability> '<json>'
|
|
36
37
|
|
|
37
38
|
recovery:
|
|
38
|
-
no api key caphub auth login
|
|
39
|
+
no api key caphub auth login
|
|
39
40
|
invalid api key generate a new key in https://caphub.io/dashboard/
|
|
40
41
|
insufficient credits top up in https://caphub.io/dashboard/
|
|
41
42
|
bad json caphub help <capability>
|
|
42
43
|
capability unknown caphub capabilities
|
|
43
44
|
|
|
44
45
|
examples:
|
|
46
|
+
caphub auth
|
|
45
47
|
caphub capabilities
|
|
48
|
+
caphub auth login
|
|
46
49
|
caphub auth login --api-key csk_live_...
|
|
47
50
|
caphub help search
|
|
48
51
|
caphub search '{"queries":["site:github.com awesome ai agents"]}'
|
|
@@ -145,7 +148,7 @@ function buildRecoveryHints(error, context = {}) {
|
|
|
145
148
|
const status = Number(error?.status || 0);
|
|
146
149
|
|
|
147
150
|
if (status === 401 || message.includes("missing x-api-key header")) {
|
|
148
|
-
hints.push("login: caphub auth login
|
|
151
|
+
hints.push("login: caphub auth login");
|
|
149
152
|
}
|
|
150
153
|
|
|
151
154
|
if (status === 403 || message.includes("invalid api key")) {
|
|
@@ -191,6 +194,10 @@ function failWithHints(message, error, context = {}) {
|
|
|
191
194
|
fail(lines.join("\n"));
|
|
192
195
|
}
|
|
193
196
|
|
|
197
|
+
function sleep(ms) {
|
|
198
|
+
return new Promise((resolveWait) => setTimeout(resolveWait, ms));
|
|
199
|
+
}
|
|
200
|
+
|
|
194
201
|
function printCapabilities(payload) {
|
|
195
202
|
const lines = [
|
|
196
203
|
"caphub capabilities",
|
|
@@ -230,7 +237,7 @@ function printCapabilityHelp(payload) {
|
|
|
230
237
|
...(payload.notes_for_agents || []).map((note) => `- ${note}`),
|
|
231
238
|
"",
|
|
232
239
|
"common recovery:",
|
|
233
|
-
"- auth missing: caphub auth login
|
|
240
|
+
"- auth missing: caphub auth login",
|
|
234
241
|
"- auth invalid: generate a new key in https://caphub.io/dashboard/",
|
|
235
242
|
"- low credits: top up in https://caphub.io/dashboard/",
|
|
236
243
|
`- bad payload: caphub help ${payload.capability}`,
|
|
@@ -264,8 +271,90 @@ async function commandAuth(args) {
|
|
|
264
271
|
const sub = args[0];
|
|
265
272
|
const config = readConfig();
|
|
266
273
|
|
|
274
|
+
if (!sub) {
|
|
275
|
+
const apiKey = getApiKey();
|
|
276
|
+
if (!apiKey) {
|
|
277
|
+
process.stdout.write([
|
|
278
|
+
"caphub auth",
|
|
279
|
+
"",
|
|
280
|
+
"status: not logged in",
|
|
281
|
+
"",
|
|
282
|
+
"next:",
|
|
283
|
+
" - caphub auth login",
|
|
284
|
+
" - or for headless/cloud agents: caphub auth login --api-key csk_live_...",
|
|
285
|
+
"",
|
|
286
|
+
].join("\n"));
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
const payload = await fetchJson(`${getApiUrl()}/v1/me`, { apiKey });
|
|
292
|
+
process.stdout.write([
|
|
293
|
+
"caphub auth",
|
|
294
|
+
"",
|
|
295
|
+
"status: logged in",
|
|
296
|
+
`email: ${payload.user.email}`,
|
|
297
|
+
`user_id: ${payload.user.id}`,
|
|
298
|
+
`credits_remaining: ${payload.total_usage.credits_remaining}`,
|
|
299
|
+
`total_credits_used: ${payload.total_usage.total_credits_used}`,
|
|
300
|
+
"",
|
|
301
|
+
"next:",
|
|
302
|
+
" - caphub capabilities",
|
|
303
|
+
" - caphub help search",
|
|
304
|
+
"",
|
|
305
|
+
].join("\n"));
|
|
306
|
+
return;
|
|
307
|
+
} catch (error) {
|
|
308
|
+
failWithHints("stored credentials are not valid", error, { capability: "search" });
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
267
312
|
if (sub === "login") {
|
|
268
|
-
const
|
|
313
|
+
const explicitApiKey = parseFlag(args, "--api-key");
|
|
314
|
+
if (!explicitApiKey && !args.includes("--api-key")) {
|
|
315
|
+
const apiUrl = getApiUrl();
|
|
316
|
+
const started = await fetchJson(`${apiUrl}/v1/auth/cli/start`, { method: "POST", body: {} });
|
|
317
|
+
process.stdout.write([
|
|
318
|
+
"caphub auth login",
|
|
319
|
+
"",
|
|
320
|
+
"Open this URL in your browser and finish sign-in:",
|
|
321
|
+
started.approval_url,
|
|
322
|
+
"",
|
|
323
|
+
`code: ${started.code}`,
|
|
324
|
+
`expires_in_seconds: ${started.expires_in_seconds}`,
|
|
325
|
+
"",
|
|
326
|
+
"Waiting for website approval...",
|
|
327
|
+
"",
|
|
328
|
+
].join("\n"));
|
|
329
|
+
|
|
330
|
+
const deadline = Date.now() + Number(started.expires_in_seconds || 600) * 1000;
|
|
331
|
+
const intervalMs = Number(started.poll_interval_seconds || 2) * 1000;
|
|
332
|
+
while (Date.now() < deadline) {
|
|
333
|
+
const polled = await fetchJson(`${apiUrl}/v1/auth/cli/poll`, {
|
|
334
|
+
method: "POST",
|
|
335
|
+
body: {
|
|
336
|
+
session_id: started.session_id,
|
|
337
|
+
poll_token: started.poll_token,
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
if (polled.status === "approved" && polled.api_key) {
|
|
342
|
+
writeConfig({
|
|
343
|
+
...config,
|
|
344
|
+
api_key: polled.api_key,
|
|
345
|
+
api_url: apiUrl,
|
|
346
|
+
});
|
|
347
|
+
process.stdout.write(`${JSON.stringify({ ok: true, config_path: CONFIG_PATH, api_url: apiUrl }, null, 2)}\n`);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
await sleep(intervalMs);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
fail("Error: login approval timed out.\n\nnext:\n - rerun: caphub auth login\n - or open https://caphub.io/dashboard/");
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const apiKey = explicitApiKey || getApiKey();
|
|
269
358
|
const apiUrl = parseFlag(args, "--api-url") || getApiUrl();
|
|
270
359
|
if (!apiKey) fail("Error: auth login requires --api-key or CAPHUB_API_KEY.\n\nnext:\n - caphub auth login --api-key csk_live_...");
|
|
271
360
|
writeConfig({
|