agent-control-plane 0.1.0 → 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/README.md +1 -1
- package/package.json +5 -5
- package/tools/bin/check-skill-contracts.sh +1 -1
- package/tools/tests/test-agent-control-plane-npm-cli.sh +2 -1
- package/tools/tests/test-package-public-metadata.sh +3 -3
- package/tools/tests/test-public-repo-docs.sh +4 -2
- package/tools/tests/test-vendored-codex-quota-claude-oauth-only.sh +38 -0
- package/tools/vendor/codex-quota/README.md +8 -16
- package/tools/vendor/codex-quota/lib/claude-accounts.js +2 -68
- package/tools/vendor/codex-quota/lib/claude-usage.js +76 -667
- package/tools/vendor/codex-quota/lib/display.js +6 -14
- package/tools/vendor/codex-quota/lib/handlers.js +32 -117
- package/tools/vendor/codex-quota/lib/sync.js +9 -14
|
@@ -553,7 +553,7 @@ Usage:
|
|
|
553
553
|
|
|
554
554
|
Commands:
|
|
555
555
|
quota [label] Check Claude usage (default command)
|
|
556
|
-
add [label] Add a Claude credential
|
|
556
|
+
add [label] Add a Claude credential via OAuth
|
|
557
557
|
reauth <label> Re-authenticate an existing Claude account via OAuth
|
|
558
558
|
switch <label> Switch Claude Code, OpenCode, and pi credentials
|
|
559
559
|
sync Sync activeLabel to Claude Code, OpenCode, and pi
|
|
@@ -564,14 +564,13 @@ Options:
|
|
|
564
564
|
--json Output result in JSON format
|
|
565
565
|
--dry-run Preview sync without writing files
|
|
566
566
|
--oauth Use OAuth browser authentication (recommended)
|
|
567
|
-
--manual Use manual token entry
|
|
568
567
|
--no-browser Print OAuth URL instead of opening browser
|
|
569
568
|
--help, -h Show this help
|
|
570
569
|
|
|
571
570
|
Examples:
|
|
572
571
|
${PRIMARY_CMD} claude Check Claude usage
|
|
573
572
|
${PRIMARY_CMD} claude quota work Check Claude usage for "work"
|
|
574
|
-
${PRIMARY_CMD} claude add Add Claude credential
|
|
573
|
+
${PRIMARY_CMD} claude add Add Claude credential via OAuth
|
|
575
574
|
${PRIMARY_CMD} claude add work --oauth Add via OAuth browser flow
|
|
576
575
|
${PRIMARY_CMD} claude reauth work Re-authenticate "work" account
|
|
577
576
|
${PRIMARY_CMD} claude switch work Switch Claude Code/OpenCode/pi to "work"
|
|
@@ -582,7 +581,7 @@ Examples:
|
|
|
582
581
|
|
|
583
582
|
Notes:
|
|
584
583
|
- switch and sync update activeLabel in ~/.claude-accounts.json when available
|
|
585
|
-
-
|
|
584
|
+
- Claude accounts are OAuth-only in the bundled public package
|
|
586
585
|
`);
|
|
587
586
|
}
|
|
588
587
|
|
|
@@ -598,8 +597,6 @@ Arguments:
|
|
|
598
597
|
Options:
|
|
599
598
|
--oauth Use OAuth browser authentication (recommended)
|
|
600
599
|
Opens browser for secure authentication
|
|
601
|
-
--manual Use manual token entry
|
|
602
|
-
Paste sessionKey or OAuth token directly
|
|
603
600
|
--no-browser Print OAuth URL instead of opening browser
|
|
604
601
|
Use this in headless/SSH environments
|
|
605
602
|
--json Output result in JSON format
|
|
@@ -608,18 +605,14 @@ Options:
|
|
|
608
605
|
Description:
|
|
609
606
|
Adds a Claude credential to ~/.claude-accounts.json.
|
|
610
607
|
|
|
611
|
-
OAuth flow
|
|
608
|
+
OAuth flow:
|
|
612
609
|
1. Opens browser for authentication at claude.ai
|
|
613
610
|
2. User copies code#state from browser
|
|
614
611
|
3. Tool exchanges code for tokens automatically
|
|
615
|
-
|
|
616
|
-
Manual flow:
|
|
617
|
-
Prompts for sessionKey or OAuth token (one is required).
|
|
618
612
|
|
|
619
613
|
Examples:
|
|
620
|
-
${PRIMARY_CMD} claude add Interactive
|
|
614
|
+
${PRIMARY_CMD} claude add Interactive OAuth flow
|
|
621
615
|
${PRIMARY_CMD} claude add work --oauth OAuth browser flow
|
|
622
|
-
${PRIMARY_CMD} claude add work --manual Manual token entry
|
|
623
616
|
${PRIMARY_CMD} claude add work --oauth --no-browser OAuth without opening browser
|
|
624
617
|
${PRIMARY_CMD} claude add work --json JSON output for scripting
|
|
625
618
|
`);
|
|
@@ -787,8 +780,7 @@ Options:
|
|
|
787
780
|
|
|
788
781
|
Description:
|
|
789
782
|
Displays usage statistics for Claude accounts. Tokens are refreshed when
|
|
790
|
-
available. Uses OAuth credentials
|
|
791
|
-
session credentials.
|
|
783
|
+
available. Uses OAuth credentials only.
|
|
792
784
|
OAuth-based accounts are checked for divergence in Claude CLI stores.
|
|
793
785
|
Use --local to suppress harness checks and only use stored account files.
|
|
794
786
|
|
|
@@ -71,7 +71,6 @@ import {
|
|
|
71
71
|
getClaudeLabels,
|
|
72
72
|
getClaudeActiveLabelInfo,
|
|
73
73
|
readClaudeActiveStoreContainer,
|
|
74
|
-
findClaudeSessionKey,
|
|
75
74
|
} from "./claude-accounts.js";
|
|
76
75
|
import {
|
|
77
76
|
updateOpencodeAuth,
|
|
@@ -92,9 +91,7 @@ import {
|
|
|
92
91
|
loadClaudeOAuthFromOpenCode,
|
|
93
92
|
loadClaudeOAuthFromEnv,
|
|
94
93
|
loadAllClaudeOAuthAccounts,
|
|
95
|
-
fetchClaudeOAuthUsage,
|
|
96
94
|
fetchClaudeOAuthUsageForAccount,
|
|
97
|
-
fetchClaudeUsage,
|
|
98
95
|
deduplicateClaudeOAuthAccounts,
|
|
99
96
|
deduplicateClaudeResultsByUsage,
|
|
100
97
|
} from "./claude-usage.js";
|
|
@@ -832,7 +829,7 @@ export async function handleClaudeList(flags) {
|
|
|
832
829
|
accounts: claudeAccounts.map(account => ({
|
|
833
830
|
label: account.label,
|
|
834
831
|
source: account.source,
|
|
835
|
-
|
|
832
|
+
authType: account.oauthToken ? "oauth" : "unsupported",
|
|
836
833
|
hasOauthToken: Boolean(account.oauthToken),
|
|
837
834
|
orgId: account.orgId ?? null,
|
|
838
835
|
isActive: activeLabel !== null && account.label === activeLabel,
|
|
@@ -873,14 +870,7 @@ export async function handleClaudeList(flags) {
|
|
|
873
870
|
const isActive = activeLabel !== null && account.label === activeLabel;
|
|
874
871
|
const marker = isActive ? "*" : " ";
|
|
875
872
|
const statusText = isActive ? " [active]" : "";
|
|
876
|
-
const
|
|
877
|
-
if (account.sessionKey ?? findClaudeSessionKey(account.cookies)) {
|
|
878
|
-
authParts.push("sessionKey");
|
|
879
|
-
}
|
|
880
|
-
if (account.oauthToken) {
|
|
881
|
-
authParts.push("oauthToken");
|
|
882
|
-
}
|
|
883
|
-
const authDisplay = authParts.length ? authParts.join("+") : "unknown";
|
|
873
|
+
const authDisplay = account.oauthToken ? "oauthToken" : "unsupported";
|
|
884
874
|
claudeLines.push(`${marker} ${account.label}${statusText}`);
|
|
885
875
|
claudeLines.push(` Auth: ${authDisplay} | ${shortenPath(account.source)}`);
|
|
886
876
|
if (i < claudeAccounts.length - 1) {
|
|
@@ -1428,6 +1418,9 @@ export async function handleClaudeAdd(args, flags) {
|
|
|
1428
1418
|
if (flags.oauth && flags.manual) {
|
|
1429
1419
|
throw new Error("Cannot use both --oauth and --manual flags. Choose one authentication method.");
|
|
1430
1420
|
}
|
|
1421
|
+
if (flags.manual) {
|
|
1422
|
+
throw new Error("Manual Claude credential entry is no longer supported. Use OAuth authentication instead.");
|
|
1423
|
+
}
|
|
1431
1424
|
|
|
1432
1425
|
const existingAccounts = loadClaudeAccounts();
|
|
1433
1426
|
const existingLabels = new Set(existingAccounts.map(a => a.label));
|
|
@@ -1446,74 +1439,18 @@ export async function handleClaudeAdd(args, flags) {
|
|
|
1446
1439
|
throw new Error(`Label "${label}" already exists. Choose a different label.`);
|
|
1447
1440
|
}
|
|
1448
1441
|
|
|
1449
|
-
// Determine authentication method
|
|
1450
|
-
let useOAuth = flags.oauth;
|
|
1451
|
-
if (!flags.oauth && !flags.manual) {
|
|
1452
|
-
// Prompt for choice
|
|
1453
|
-
console.log("\nChoose authentication method:");
|
|
1454
|
-
console.log(" [1] OAuth (recommended) - Authenticate via browser");
|
|
1455
|
-
console.log(" [2] Manual - Paste sessionKey/token directly\n");
|
|
1456
|
-
const choice = (await promptInput("Enter choice (1 or 2): ")).trim();
|
|
1457
|
-
useOAuth = choice === "1";
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
1442
|
let newAccount;
|
|
1461
1443
|
let viaMethod;
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
oauthScopes: tokens.scopes,
|
|
1473
|
-
cfClearance: null,
|
|
1474
|
-
orgId: null,
|
|
1475
|
-
};
|
|
1476
|
-
viaMethod = "via OAuth";
|
|
1477
|
-
} else {
|
|
1478
|
-
// Manual entry flow
|
|
1479
|
-
console.log("\nPaste your Claude sessionKey or OAuth token.");
|
|
1480
|
-
const sessionKeyInput = await promptInput("sessionKey (sk-ant-...): ", { allowEmpty: true });
|
|
1481
|
-
const oauthTokenInput = await promptInput("oauthToken (optional): ", { allowEmpty: true });
|
|
1482
|
-
const cfClearanceInput = await promptInput("cfClearance (optional): ", { allowEmpty: true });
|
|
1483
|
-
const orgIdInput = await promptInput("orgId (optional): ", { allowEmpty: true });
|
|
1484
|
-
|
|
1485
|
-
let parsedInput = null;
|
|
1486
|
-
if (sessionKeyInput && sessionKeyInput.trim().startsWith("{")) {
|
|
1487
|
-
try {
|
|
1488
|
-
parsedInput = JSON.parse(sessionKeyInput);
|
|
1489
|
-
} catch {
|
|
1490
|
-
parsedInput = null;
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
const sessionKey = findClaudeSessionKey(parsedInput ?? sessionKeyInput) ?? null;
|
|
1495
|
-
const oauthToken = oauthTokenInput?.trim()
|
|
1496
|
-
|| parsedInput?.claudeAiOauth?.accessToken
|
|
1497
|
-
|| parsedInput?.claude_ai_oauth?.accessToken
|
|
1498
|
-
|| parsedInput?.accessToken
|
|
1499
|
-
|| parsedInput?.access_token
|
|
1500
|
-
|| null;
|
|
1501
|
-
const cfClearance = cfClearanceInput?.trim() || null;
|
|
1502
|
-
const orgId = orgIdInput?.trim() || null;
|
|
1503
|
-
|
|
1504
|
-
if (!sessionKey && !oauthToken) {
|
|
1505
|
-
throw new Error("Provide at least a sessionKey or an OAuth token.");
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
newAccount = {
|
|
1509
|
-
label,
|
|
1510
|
-
sessionKey,
|
|
1511
|
-
oauthToken,
|
|
1512
|
-
cfClearance,
|
|
1513
|
-
orgId,
|
|
1514
|
-
};
|
|
1515
|
-
viaMethod = "";
|
|
1516
|
-
}
|
|
1444
|
+
const tokens = await handleClaudeOAuthFlow({ noBrowser: flags.noBrowser });
|
|
1445
|
+
newAccount = {
|
|
1446
|
+
label,
|
|
1447
|
+
oauthToken: tokens.accessToken,
|
|
1448
|
+
oauthRefreshToken: tokens.refreshToken,
|
|
1449
|
+
oauthExpiresAt: tokens.expiresAt,
|
|
1450
|
+
oauthScopes: tokens.scopes,
|
|
1451
|
+
orgId: null,
|
|
1452
|
+
};
|
|
1453
|
+
viaMethod = "via OAuth";
|
|
1517
1454
|
|
|
1518
1455
|
const { path: targetPath, container } = readClaudeActiveStoreContainer();
|
|
1519
1456
|
const accounts = [...container.accounts, newAccount];
|
|
@@ -1521,11 +1458,11 @@ export async function handleClaudeAdd(args, flags) {
|
|
|
1521
1458
|
|
|
1522
1459
|
if (flags.json) {
|
|
1523
1460
|
console.log(JSON.stringify({
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1461
|
+
success: true,
|
|
1462
|
+
label,
|
|
1463
|
+
method: "oauth",
|
|
1464
|
+
source: targetPath,
|
|
1465
|
+
}, null, 2));
|
|
1529
1466
|
return;
|
|
1530
1467
|
}
|
|
1531
1468
|
|
|
@@ -1887,42 +1824,21 @@ export async function handleQuota(args, flags, scope = "all") {
|
|
|
1887
1824
|
filteredOauthAccounts.map(account => fetchClaudeOAuthUsageForAccount(account))
|
|
1888
1825
|
);
|
|
1889
1826
|
claudeResults = deduplicateClaudeResultsByUsage(rawResults);
|
|
1890
|
-
} else {
|
|
1891
|
-
const
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
filteredClaudeAccounts.map(account => fetchClaudeUsageForCredentials(account))
|
|
1899
|
-
);
|
|
1900
|
-
claudeResults = deduplicateClaudeResultsByUsage(rawResults);
|
|
1901
|
-
} else if (wantsClaudeLabel) {
|
|
1902
|
-
const availableLabels = new Set([
|
|
1903
|
-
...oauthAccounts.map(account => account.label),
|
|
1904
|
-
...claudeAccounts.map(account => account.label),
|
|
1905
|
-
]);
|
|
1906
|
-
const labelList = Array.from(availableLabels);
|
|
1907
|
-
if (flags.json) {
|
|
1908
|
-
console.log(JSON.stringify({
|
|
1909
|
-
success: false,
|
|
1910
|
-
error: `Claude account "${labelFilter}" not found`,
|
|
1911
|
-
availableLabels: labelList,
|
|
1912
|
-
}, null, 2));
|
|
1913
|
-
} else {
|
|
1914
|
-
console.error(colorize(`Claude account "${labelFilter}" not found.`, RED));
|
|
1915
|
-
if (labelList.length) {
|
|
1916
|
-
console.error(`Available: ${labelList.join(", ")}`);
|
|
1917
|
-
}
|
|
1918
|
-
}
|
|
1919
|
-
process.exit(1);
|
|
1827
|
+
} else if (wantsClaudeLabel) {
|
|
1828
|
+
const labelList = Array.from(new Set(oauthAccounts.map(account => account.label)));
|
|
1829
|
+
if (flags.json) {
|
|
1830
|
+
console.log(JSON.stringify({
|
|
1831
|
+
success: false,
|
|
1832
|
+
error: `Claude account "${labelFilter}" not found`,
|
|
1833
|
+
availableLabels: labelList,
|
|
1834
|
+
}, null, 2));
|
|
1920
1835
|
} else {
|
|
1921
|
-
|
|
1922
|
-
if (
|
|
1923
|
-
|
|
1836
|
+
console.error(colorize(`Claude account "${labelFilter}" not found.`, RED));
|
|
1837
|
+
if (labelList.length) {
|
|
1838
|
+
console.error(`Available: ${labelList.join(", ")}`);
|
|
1924
1839
|
}
|
|
1925
1840
|
}
|
|
1841
|
+
process.exit(1);
|
|
1926
1842
|
}
|
|
1927
1843
|
}
|
|
1928
1844
|
|
|
@@ -2057,4 +1973,3 @@ export async function handleQuota(args, flags, scope = "all") {
|
|
|
2057
1973
|
}
|
|
2058
1974
|
}
|
|
2059
1975
|
}
|
|
2060
|
-
|
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
getClaudeLabels,
|
|
30
30
|
readClaudeActiveStoreContainer,
|
|
31
31
|
getClaudeActiveLabelInfo,
|
|
32
|
-
findClaudeSessionKey,
|
|
33
32
|
loadClaudeAccountsFromFile,
|
|
34
33
|
} from "./claude-accounts.js";
|
|
35
34
|
import {
|
|
@@ -652,16 +651,14 @@ export async function maybeImportClaudeOauthStores(options = {}) {
|
|
|
652
651
|
console.error(colorize(`Skipping: label "${label}" already exists.`, YELLOW));
|
|
653
652
|
continue;
|
|
654
653
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
orgId: null,
|
|
664
|
-
};
|
|
654
|
+
const newAccount = {
|
|
655
|
+
label,
|
|
656
|
+
oauthToken: store.tokens.access,
|
|
657
|
+
oauthRefreshToken: store.tokens.refresh ?? null,
|
|
658
|
+
oauthExpiresAt: store.tokens.expires ?? null,
|
|
659
|
+
oauthScopes: store.tokens.scopes ?? null,
|
|
660
|
+
orgId: null,
|
|
661
|
+
};
|
|
665
662
|
container.accounts.push(newAccount);
|
|
666
663
|
managedAccounts.push(normalizeClaudeAccount(newAccount, targetPath));
|
|
667
664
|
existingLabels.add(label);
|
|
@@ -1430,9 +1427,7 @@ export async function handleClaudeSync(args, flags) {
|
|
|
1430
1427
|
|
|
1431
1428
|
/**
|
|
1432
1429
|
* Handle Claude add subcommand - add a Claude credential interactively
|
|
1433
|
-
*
|
|
1434
|
-
* - OAuth browser flow (--oauth): Opens browser for authentication
|
|
1435
|
-
* - Manual entry (--manual): Paste sessionKey/token directly
|
|
1430
|
+
* Uses OAuth browser flow for authentication.
|
|
1436
1431
|
* @param {string[]} args - Non-flag arguments (optional label)
|
|
1437
1432
|
* @param {{ json: boolean, noBrowser: boolean, oauth: boolean, manual: boolean }} flags - Parsed flags
|
|
1438
1433
|
*/
|