@eve-horizon/cli 0.2.0 → 0.2.5
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/commands/admin.js +15 -18
- package/dist/commands/auth.js +317 -42
- package/dist/commands/build.js +350 -0
- package/dist/commands/env.js +196 -7
- package/dist/commands/manifest.js +86 -0
- package/dist/commands/org.js +2 -1
- package/dist/commands/profile.js +2 -1
- package/dist/commands/system.js +124 -3
- package/dist/index.js +8 -0
- package/dist/lib/help.js +209 -8
- package/package.json +1 -1
package/dist/commands/admin.js
CHANGED
|
@@ -18,11 +18,26 @@ async function handleAdmin(subcommand, positionals, flags, context) {
|
|
|
18
18
|
if (!['owner', 'admin', 'member'].includes(role)) {
|
|
19
19
|
throw new Error(`Invalid role: ${role}. Must be one of: owner, admin, member`);
|
|
20
20
|
}
|
|
21
|
+
if (!orgId) {
|
|
22
|
+
throw new Error('No org specified. Use --org <org_id> or set a default org in your profile.');
|
|
23
|
+
}
|
|
21
24
|
const results = {
|
|
22
25
|
keys_registered: 0,
|
|
23
26
|
identities: [],
|
|
24
27
|
};
|
|
28
|
+
// Add user to org first - this creates the user if they don't exist
|
|
29
|
+
if (orgId) {
|
|
30
|
+
const membership = await (0, client_1.requestJson)(context, `/orgs/${orgId}/members`, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
body: {
|
|
33
|
+
email,
|
|
34
|
+
role,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
results.membership = membership;
|
|
38
|
+
}
|
|
25
39
|
// Fetch and register GitHub SSH keys if username provided
|
|
40
|
+
// Now that user exists (created via org membership), identity registration will work
|
|
26
41
|
if (githubUsername) {
|
|
27
42
|
const keys = await fetchGitHubKeys(githubUsername);
|
|
28
43
|
if (keys.length === 0) {
|
|
@@ -41,24 +56,6 @@ async function handleAdmin(subcommand, positionals, flags, context) {
|
|
|
41
56
|
results.keys_registered += 1;
|
|
42
57
|
}
|
|
43
58
|
}
|
|
44
|
-
// Add user to org if org_id provided
|
|
45
|
-
if (orgId) {
|
|
46
|
-
// Get user_id from the first registered identity, or look up by email
|
|
47
|
-
let userId;
|
|
48
|
-
if (results.identities.length > 0) {
|
|
49
|
-
userId = results.identities[0].user_id;
|
|
50
|
-
}
|
|
51
|
-
if (userId) {
|
|
52
|
-
const membership = await (0, client_1.requestJson)(context, `/orgs/${orgId}/members`, {
|
|
53
|
-
method: 'POST',
|
|
54
|
-
body: {
|
|
55
|
-
user_id: userId,
|
|
56
|
-
role,
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
results.membership = membership;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
59
|
const summary = [
|
|
63
60
|
`Invited ${email}`,
|
|
64
61
|
results.keys_registered > 0 ? `${results.keys_registered} SSH key(s) registered` : null,
|
package/dist/commands/auth.js
CHANGED
|
@@ -271,15 +271,70 @@ async function handleAuth(subcommand, flags, context, credentials) {
|
|
|
271
271
|
console.log(tokenEntry.access_token);
|
|
272
272
|
return;
|
|
273
273
|
}
|
|
274
|
+
case 'mint': {
|
|
275
|
+
const email = (0, args_1.getStringFlag)(flags, ['email']);
|
|
276
|
+
const orgId = (0, args_1.getStringFlag)(flags, ['org']);
|
|
277
|
+
const projectId = (0, args_1.getStringFlag)(flags, ['project']);
|
|
278
|
+
const role = (0, args_1.getStringFlag)(flags, ['role']) ?? 'member';
|
|
279
|
+
const ttlStr = (0, args_1.getStringFlag)(flags, ['ttl']);
|
|
280
|
+
const ttlDays = ttlStr ? parseInt(ttlStr, 10) : undefined;
|
|
281
|
+
if (ttlDays !== undefined && (isNaN(ttlDays) || ttlDays < 1 || ttlDays > 90)) {
|
|
282
|
+
throw new Error('--ttl must be between 1 and 90 days');
|
|
283
|
+
}
|
|
284
|
+
if (!email) {
|
|
285
|
+
throw new Error('Usage: eve auth mint --email <email> [--org <org_id> | --project <project_id>] [--role <role>]');
|
|
286
|
+
}
|
|
287
|
+
if (!orgId && !projectId) {
|
|
288
|
+
throw new Error('Usage: eve auth mint --email <email> [--org <org_id> | --project <project_id>] [--role <role>]');
|
|
289
|
+
}
|
|
290
|
+
if (!['admin', 'member'].includes(role)) {
|
|
291
|
+
throw new Error(`Invalid role: ${role}. Must be one of: admin, member`);
|
|
292
|
+
}
|
|
293
|
+
const response = await (0, client_1.requestJson)(context, '/auth/mint', {
|
|
294
|
+
method: 'POST',
|
|
295
|
+
body: {
|
|
296
|
+
email,
|
|
297
|
+
org_id: orgId,
|
|
298
|
+
project_id: projectId,
|
|
299
|
+
role,
|
|
300
|
+
ttl_days: ttlDays,
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
if (json) {
|
|
304
|
+
(0, output_1.outputJson)(response, json);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (!response.access_token) {
|
|
308
|
+
throw new Error('Mint response missing access_token');
|
|
309
|
+
}
|
|
310
|
+
// Print only the token to stdout, nothing else
|
|
311
|
+
console.log(response.access_token);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
274
314
|
case 'sync': {
|
|
275
315
|
const claudeOnly = (0, args_1.getBooleanFlag)(flags, ['claude']) ?? false;
|
|
276
316
|
const codexOnly = (0, args_1.getBooleanFlag)(flags, ['codex']) ?? false;
|
|
277
317
|
const dryRun = (0, args_1.getBooleanFlag)(flags, ['dry-run']) ?? false;
|
|
278
|
-
const
|
|
318
|
+
const orgIdFlag = (0, args_1.getStringFlag)(flags, ['org']);
|
|
279
319
|
const projectIdFlag = (0, args_1.getStringFlag)(flags, ['project']);
|
|
280
|
-
|
|
281
|
-
if (
|
|
282
|
-
|
|
320
|
+
let scope;
|
|
321
|
+
if (projectIdFlag) {
|
|
322
|
+
scope = { type: 'project', projectId: projectIdFlag };
|
|
323
|
+
}
|
|
324
|
+
else if (orgIdFlag) {
|
|
325
|
+
scope = { type: 'org', orgId: orgIdFlag };
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
// Default to user scope - need to fetch user ID
|
|
329
|
+
const meResponse = await (0, client_1.requestRaw)(context, '/auth/me', { allowError: true });
|
|
330
|
+
if (!meResponse.ok) {
|
|
331
|
+
throw new Error('Not authenticated. Run "eve auth login" first.');
|
|
332
|
+
}
|
|
333
|
+
const meData = meResponse.data;
|
|
334
|
+
if (!meData.user_id) {
|
|
335
|
+
throw new Error('Could not determine user ID. Try specifying --org or --project instead.');
|
|
336
|
+
}
|
|
337
|
+
scope = { type: 'user', userId: meData.user_id };
|
|
283
338
|
}
|
|
284
339
|
const extractClaude = !codexOnly; // Extract Claude unless --codex is specified
|
|
285
340
|
const extractCodex = !claudeOnly; // Extract Codex unless --claude is specified
|
|
@@ -287,31 +342,42 @@ async function handleAuth(subcommand, flags, context, credentials) {
|
|
|
287
342
|
const platform = process.platform;
|
|
288
343
|
// Extract Claude OAuth tokens
|
|
289
344
|
if (extractClaude) {
|
|
345
|
+
// Try macOS Keychain first
|
|
290
346
|
if (platform === 'darwin') {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
347
|
+
for (const service of ['Claude Code-credentials', 'anthropic.claude']) {
|
|
348
|
+
try {
|
|
349
|
+
const output = (0, node_child_process_1.execSync)(`security find-generic-password -s "${service}" -w`, { encoding: 'utf8' }).trim();
|
|
350
|
+
if (output) {
|
|
351
|
+
extractedTokens.CLAUDE_CODE_OAUTH_TOKEN = output;
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
// Token not found in keychain, continue
|
|
295
357
|
}
|
|
296
|
-
}
|
|
297
|
-
catch (error) {
|
|
298
|
-
// Token not found in keychain, continue
|
|
299
358
|
}
|
|
300
359
|
}
|
|
301
|
-
|
|
302
|
-
|
|
360
|
+
// Check credential files (all platforms)
|
|
361
|
+
if (!extractedTokens.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
303
362
|
const credentialPaths = [
|
|
304
363
|
`${(0, node_os_1.homedir)()}/.claude/.credentials.json`,
|
|
305
364
|
`${(0, node_os_1.homedir)()}/.claude/credentials.json`,
|
|
306
365
|
`${(0, node_os_1.homedir)()}/.config/claude/credentials.json`,
|
|
307
366
|
];
|
|
308
|
-
for (const
|
|
309
|
-
if ((0, node_fs_1.existsSync)(
|
|
367
|
+
for (const credPath of credentialPaths) {
|
|
368
|
+
if ((0, node_fs_1.existsSync)(credPath)) {
|
|
310
369
|
try {
|
|
311
|
-
const content = (0, node_fs_1.readFileSync)(
|
|
370
|
+
const content = (0, node_fs_1.readFileSync)(credPath, 'utf8');
|
|
312
371
|
const creds = JSON.parse(content);
|
|
372
|
+
// Handle nested claudeAiOauth format (current Claude Code format)
|
|
373
|
+
const claudeOauth = creds.claudeAiOauth;
|
|
374
|
+
if (claudeOauth?.accessToken) {
|
|
375
|
+
extractedTokens.CLAUDE_CODE_OAUTH_TOKEN = claudeOauth.accessToken;
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
// Fallback to legacy root-level tokens
|
|
313
379
|
if (creds.oauth_token || creds.access_token) {
|
|
314
|
-
extractedTokens.
|
|
380
|
+
extractedTokens.CLAUDE_CODE_OAUTH_TOKEN = (creds.oauth_token || creds.access_token);
|
|
315
381
|
break;
|
|
316
382
|
}
|
|
317
383
|
}
|
|
@@ -322,48 +388,78 @@ async function handleAuth(subcommand, flags, context, credentials) {
|
|
|
322
388
|
}
|
|
323
389
|
}
|
|
324
390
|
}
|
|
325
|
-
// Extract Codex OAuth tokens
|
|
391
|
+
// Extract Codex/Code OAuth tokens
|
|
326
392
|
if (extractCodex) {
|
|
393
|
+
// Try macOS Keychain first
|
|
327
394
|
if (platform === 'darwin') {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
395
|
+
for (const service of ['openai.codex', 'Code-credentials']) {
|
|
396
|
+
try {
|
|
397
|
+
const output = (0, node_child_process_1.execSync)(`security find-generic-password -s "${service}" -w`, { encoding: 'utf8' }).trim();
|
|
398
|
+
if (output) {
|
|
399
|
+
extractedTokens.CODEX_OAUTH_ACCESS_TOKEN = output;
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
catch {
|
|
404
|
+
// Token not found in keychain, continue
|
|
332
405
|
}
|
|
333
|
-
}
|
|
334
|
-
catch (error) {
|
|
335
|
-
// Token not found in keychain, continue
|
|
336
406
|
}
|
|
337
407
|
}
|
|
338
|
-
// Check ~/.codex/auth.json
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
408
|
+
// Check auth files (all platforms): ~/.codex/auth.json and ~/.code/auth.json
|
|
409
|
+
if (!extractedTokens.CODEX_OAUTH_ACCESS_TOKEN) {
|
|
410
|
+
const codexAuthPaths = [
|
|
411
|
+
`${(0, node_os_1.homedir)()}/.codex/auth.json`,
|
|
412
|
+
`${(0, node_os_1.homedir)()}/.code/auth.json`,
|
|
413
|
+
];
|
|
414
|
+
for (const authPath of codexAuthPaths) {
|
|
415
|
+
if ((0, node_fs_1.existsSync)(authPath)) {
|
|
416
|
+
try {
|
|
417
|
+
const content = (0, node_fs_1.readFileSync)(authPath, 'utf8');
|
|
418
|
+
const auth = JSON.parse(content);
|
|
419
|
+
// Handle nested tokens format (current Codex CLI format)
|
|
420
|
+
const tokens = auth.tokens;
|
|
421
|
+
if (tokens?.access_token) {
|
|
422
|
+
extractedTokens.CODEX_OAUTH_ACCESS_TOKEN = tokens.access_token;
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
// Fallback to root-level tokens
|
|
426
|
+
if (auth.oauth_token || auth.access_token) {
|
|
427
|
+
extractedTokens.CODEX_OAUTH_ACCESS_TOKEN = (auth.oauth_token || auth.access_token);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
// Also check for OPENAI_API_KEY in the auth file
|
|
431
|
+
if (auth.OPENAI_API_KEY && typeof auth.OPENAI_API_KEY === 'string') {
|
|
432
|
+
extractedTokens.OPENAI_API_KEY = auth.OPENAI_API_KEY;
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
// Failed to parse, continue
|
|
438
|
+
}
|
|
346
439
|
}
|
|
347
440
|
}
|
|
348
|
-
catch {
|
|
349
|
-
// Failed to parse, continue
|
|
350
|
-
}
|
|
351
441
|
}
|
|
352
442
|
}
|
|
353
443
|
if (Object.keys(extractedTokens).length === 0) {
|
|
354
444
|
(0, output_1.outputJson)({ extracted: 0, tokens: [] }, json, 'No tokens found on host machine');
|
|
355
445
|
return;
|
|
356
446
|
}
|
|
447
|
+
// Build target label for output
|
|
448
|
+
const targetLabel = scope.type === 'user' ? 'user' :
|
|
449
|
+
scope.type === 'org' ? `org ${scope.orgId}` :
|
|
450
|
+
`project ${scope.projectId}`;
|
|
357
451
|
if (dryRun) {
|
|
358
452
|
const tokenList = Object.keys(extractedTokens).map(key => ({
|
|
359
453
|
name: key,
|
|
360
454
|
value: `${extractedTokens[key].substring(0, 10)}...`,
|
|
361
455
|
}));
|
|
362
|
-
(0, output_1.outputJson)({ dry_run: true, would_set: tokenList, target:
|
|
456
|
+
(0, output_1.outputJson)({ dry_run: true, would_set: tokenList, target: targetLabel, scope }, json, `Would set ${tokenList.length} token(s) on ${targetLabel}:\n${tokenList.map(t => ` - ${t.name}`).join('\n')}`);
|
|
363
457
|
return;
|
|
364
458
|
}
|
|
365
|
-
// Set secrets via API
|
|
366
|
-
const endpoint =
|
|
459
|
+
// Set secrets via API - endpoint depends on scope
|
|
460
|
+
const endpoint = scope.type === 'user' ? `/users/${scope.userId}/secrets` :
|
|
461
|
+
scope.type === 'org' ? `/orgs/${scope.orgId}/secrets` :
|
|
462
|
+
`/projects/${scope.projectId}/secrets`;
|
|
367
463
|
const results = [];
|
|
368
464
|
for (const [name, value] of Object.entries(extractedTokens)) {
|
|
369
465
|
try {
|
|
@@ -387,15 +483,194 @@ async function handleAuth(subcommand, flags, context, credentials) {
|
|
|
387
483
|
const successCount = results.filter(r => r.success).length;
|
|
388
484
|
const failCount = results.filter(r => !r.success).length;
|
|
389
485
|
(0, output_1.outputJson)({
|
|
390
|
-
target:
|
|
486
|
+
target: targetLabel,
|
|
487
|
+
scope,
|
|
391
488
|
results,
|
|
392
489
|
success: successCount,
|
|
393
490
|
failed: failCount,
|
|
394
|
-
}, json, `✓ Set ${successCount} secret(s) on ${
|
|
491
|
+
}, json, `✓ Set ${successCount} secret(s) on ${targetLabel}${failCount > 0 ? ` (${failCount} failed)` : ''}`);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
case 'creds': {
|
|
495
|
+
// Show local credential status without syncing
|
|
496
|
+
const claudeOnly = (0, args_1.getBooleanFlag)(flags, ['claude']) ?? false;
|
|
497
|
+
const codexOnly = (0, args_1.getBooleanFlag)(flags, ['codex']) ?? false;
|
|
498
|
+
const checkClaude = !codexOnly;
|
|
499
|
+
const checkCodex = !claudeOnly;
|
|
500
|
+
const credentials = [];
|
|
501
|
+
const plat = process.platform;
|
|
502
|
+
// Check Claude credentials
|
|
503
|
+
if (checkClaude) {
|
|
504
|
+
let claudeFound = false;
|
|
505
|
+
let claudeSource = '';
|
|
506
|
+
let claudePreview = '';
|
|
507
|
+
let claudeExpires;
|
|
508
|
+
// Try macOS Keychain
|
|
509
|
+
if (plat === 'darwin' && !claudeFound) {
|
|
510
|
+
for (const service of ['Claude Code-credentials', 'anthropic.claude']) {
|
|
511
|
+
try {
|
|
512
|
+
const output = (0, node_child_process_1.execSync)(`security find-generic-password -s "${service}" -w`, { encoding: 'utf8' }).trim();
|
|
513
|
+
if (output) {
|
|
514
|
+
claudeFound = true;
|
|
515
|
+
claudeSource = `macOS Keychain (${service})`;
|
|
516
|
+
claudePreview = output.substring(0, 15) + '...';
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
catch {
|
|
521
|
+
// Not found
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
// Check credential files
|
|
526
|
+
if (!claudeFound) {
|
|
527
|
+
const credentialPaths = [
|
|
528
|
+
`${(0, node_os_1.homedir)()}/.claude/.credentials.json`,
|
|
529
|
+
`${(0, node_os_1.homedir)()}/.claude/credentials.json`,
|
|
530
|
+
`${(0, node_os_1.homedir)()}/.config/claude/credentials.json`,
|
|
531
|
+
];
|
|
532
|
+
for (const credPath of credentialPaths) {
|
|
533
|
+
if ((0, node_fs_1.existsSync)(credPath)) {
|
|
534
|
+
try {
|
|
535
|
+
const content = (0, node_fs_1.readFileSync)(credPath, 'utf8');
|
|
536
|
+
const creds = JSON.parse(content);
|
|
537
|
+
const claudeOauth = creds.claudeAiOauth;
|
|
538
|
+
if (claudeOauth?.accessToken) {
|
|
539
|
+
claudeFound = true;
|
|
540
|
+
claudeSource = credPath.replace((0, node_os_1.homedir)(), '~');
|
|
541
|
+
claudePreview = claudeOauth.accessToken.substring(0, 15) + '...';
|
|
542
|
+
if (claudeOauth.expiresAt) {
|
|
543
|
+
const expDate = new Date(claudeOauth.expiresAt);
|
|
544
|
+
claudeExpires = expDate.toISOString();
|
|
545
|
+
}
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
if (creds.oauth_token || creds.access_token) {
|
|
549
|
+
claudeFound = true;
|
|
550
|
+
claudeSource = credPath.replace((0, node_os_1.homedir)(), '~');
|
|
551
|
+
const token = (creds.oauth_token || creds.access_token);
|
|
552
|
+
claudePreview = token.substring(0, 15) + '...';
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
catch {
|
|
557
|
+
// Failed to parse
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
credentials.push({
|
|
563
|
+
name: 'Claude Code OAuth',
|
|
564
|
+
source: claudeFound ? claudeSource : 'not found',
|
|
565
|
+
found: claudeFound,
|
|
566
|
+
preview: claudePreview || undefined,
|
|
567
|
+
expiresAt: claudeExpires,
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
// Check Codex credentials
|
|
571
|
+
if (checkCodex) {
|
|
572
|
+
let codexFound = false;
|
|
573
|
+
let codexSource = '';
|
|
574
|
+
let codexPreview = '';
|
|
575
|
+
// Try macOS Keychain
|
|
576
|
+
if (plat === 'darwin' && !codexFound) {
|
|
577
|
+
for (const service of ['openai.codex', 'Code-credentials']) {
|
|
578
|
+
try {
|
|
579
|
+
const output = (0, node_child_process_1.execSync)(`security find-generic-password -s "${service}" -w`, { encoding: 'utf8' }).trim();
|
|
580
|
+
if (output) {
|
|
581
|
+
codexFound = true;
|
|
582
|
+
codexSource = `macOS Keychain (${service})`;
|
|
583
|
+
codexPreview = output.substring(0, 15) + '...';
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
catch {
|
|
588
|
+
// Not found
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
// Check auth files
|
|
593
|
+
if (!codexFound) {
|
|
594
|
+
const codexAuthPaths = [
|
|
595
|
+
`${(0, node_os_1.homedir)()}/.codex/auth.json`,
|
|
596
|
+
`${(0, node_os_1.homedir)()}/.code/auth.json`,
|
|
597
|
+
];
|
|
598
|
+
for (const authPath of codexAuthPaths) {
|
|
599
|
+
if ((0, node_fs_1.existsSync)(authPath)) {
|
|
600
|
+
try {
|
|
601
|
+
const content = (0, node_fs_1.readFileSync)(authPath, 'utf8');
|
|
602
|
+
const auth = JSON.parse(content);
|
|
603
|
+
const tokens = auth.tokens;
|
|
604
|
+
if (tokens?.access_token) {
|
|
605
|
+
codexFound = true;
|
|
606
|
+
codexSource = authPath.replace((0, node_os_1.homedir)(), '~');
|
|
607
|
+
codexPreview = tokens.access_token.substring(0, 15) + '...';
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
if (auth.oauth_token || auth.access_token) {
|
|
611
|
+
codexFound = true;
|
|
612
|
+
codexSource = authPath.replace((0, node_os_1.homedir)(), '~');
|
|
613
|
+
const token = (auth.oauth_token || auth.access_token);
|
|
614
|
+
codexPreview = token.substring(0, 15) + '...';
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
if (auth.OPENAI_API_KEY && typeof auth.OPENAI_API_KEY === 'string') {
|
|
618
|
+
codexFound = true;
|
|
619
|
+
codexSource = authPath.replace((0, node_os_1.homedir)(), '~') + ' (API key)';
|
|
620
|
+
codexPreview = auth.OPENAI_API_KEY.substring(0, 10) + '...';
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
catch {
|
|
625
|
+
// Failed to parse
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
credentials.push({
|
|
631
|
+
name: 'Codex/Code OAuth',
|
|
632
|
+
source: codexFound ? codexSource : 'not found',
|
|
633
|
+
found: codexFound,
|
|
634
|
+
preview: codexPreview || undefined,
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
const foundCount = credentials.filter(c => c.found).length;
|
|
638
|
+
if (json) {
|
|
639
|
+
(0, output_1.outputJson)({ credentials, found: foundCount }, json);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
console.log('Local AI Tool Credentials:');
|
|
643
|
+
console.log('');
|
|
644
|
+
for (const cred of credentials) {
|
|
645
|
+
const status = cred.found ? '✓' : '✗';
|
|
646
|
+
console.log(` ${status} ${cred.name}`);
|
|
647
|
+
console.log(` Source: ${cred.source}`);
|
|
648
|
+
if (cred.preview) {
|
|
649
|
+
console.log(` Token: ${cred.preview}`);
|
|
650
|
+
}
|
|
651
|
+
if (cred.expiresAt) {
|
|
652
|
+
const expDate = new Date(cred.expiresAt);
|
|
653
|
+
const now = new Date();
|
|
654
|
+
const isExpired = expDate < now;
|
|
655
|
+
const expLabel = isExpired ? '(expired)' : '';
|
|
656
|
+
console.log(` Expires: ${cred.expiresAt} ${expLabel}`);
|
|
657
|
+
}
|
|
658
|
+
console.log('');
|
|
659
|
+
}
|
|
660
|
+
if (foundCount > 0) {
|
|
661
|
+
console.log(`Found ${foundCount} credential(s). Run 'eve auth sync' to sync to Eve.`);
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
console.log('No local credentials found.');
|
|
665
|
+
console.log('');
|
|
666
|
+
console.log('To set up credentials:');
|
|
667
|
+
console.log(' Claude: Run "claude" CLI and log in');
|
|
668
|
+
console.log(' Codex: Run "codex" CLI and log in');
|
|
669
|
+
}
|
|
395
670
|
return;
|
|
396
671
|
}
|
|
397
672
|
default:
|
|
398
|
-
throw new Error('Usage: eve auth <login|logout|status|whoami|bootstrap|sync|token>');
|
|
673
|
+
throw new Error('Usage: eve auth <login|logout|status|whoami|bootstrap|sync|creds|token>');
|
|
399
674
|
}
|
|
400
675
|
}
|
|
401
676
|
function signNonceWithSsh(keyPath, nonce) {
|