@cortexkit/anthropic-auth-core 1.23.0 → 2.0.0

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.
Files changed (134) hide show
  1. package/README.md +2 -0
  2. package/dist/accounts.d.ts +3 -16
  3. package/dist/cachekeep.d.ts +9 -0
  4. package/dist/claude-code.d.ts +16 -0
  5. package/dist/claustrum-enrollment.d.ts +2 -0
  6. package/dist/claustrum-scoped-roster.d.ts +4 -0
  7. package/dist/claustrum-scoped-runtime.d.ts +3 -0
  8. package/dist/claustrum-scoped.d.ts +14 -0
  9. package/dist/claustrum.d.ts +0 -209
  10. package/dist/commands/account.d.ts +2 -3
  11. package/dist/index.d.ts +44 -1
  12. package/dist/index.js +29700 -38
  13. package/dist/internal-types/LICENSE +21 -0
  14. package/dist/internal-types/commands/builtins.d.ts +71 -0
  15. package/dist/internal-types/commands/index.d.ts +10 -0
  16. package/dist/internal-types/commands/menu.d.ts +61 -0
  17. package/dist/internal-types/commands/model.d.ts +238 -0
  18. package/dist/internal-types/commands/pi.d.ts +23 -0
  19. package/dist/internal-types/commands/seam.d.ts +72 -0
  20. package/dist/internal-types/fs/refresh-file-lock.d.ts +33 -0
  21. package/dist/internal-types/logger/capture-sink.d.ts +14 -0
  22. package/dist/internal-types/logger/engine.d.ts +100 -0
  23. package/dist/internal-types/logger/index.d.ts +6 -0
  24. package/dist/internal-types/logger/redact.d.ts +11 -0
  25. package/dist/internal-types/pi-slot/index.d.ts +3 -0
  26. package/dist/internal-types/pi-slot/slot.d.ts +49 -0
  27. package/dist/internal-types/quota/codec.d.ts +11 -0
  28. package/dist/internal-types/quota/format.d.ts +46 -0
  29. package/dist/internal-types/quota/index.d.ts +10 -0
  30. package/dist/internal-types/quota/map.d.ts +63 -0
  31. package/dist/internal-types/quota/merge.d.ts +48 -0
  32. package/dist/internal-types/quota/projection.d.ts +64 -0
  33. package/dist/internal-types/store/attribution.d.ts +28 -0
  34. package/dist/internal-types/store/errors.d.ts +55 -0
  35. package/dist/internal-types/store/hooks.d.ts +12 -0
  36. package/dist/internal-types/store/identity.d.ts +39 -0
  37. package/dist/internal-types/store/index.d.ts +21 -0
  38. package/dist/internal-types/store/mutate.d.ts +189 -0
  39. package/dist/internal-types/store/pool.d.ts +196 -0
  40. package/dist/internal-types/store/provider-state.d.ts +131 -0
  41. package/dist/internal-types/store/publication.d.ts +47 -0
  42. package/dist/internal-types/store/pull.d.ts +36 -0
  43. package/dist/internal-types/store/refresh-lock.d.ts +63 -0
  44. package/dist/internal-types/store/refresh.d.ts +72 -0
  45. package/dist/internal-types/store/rows.d.ts +313 -0
  46. package/dist/internal-types/store/runtime.d.ts +36 -0
  47. package/dist/internal-types/store/schema.d.ts +443 -0
  48. package/dist/internal-types/store/settings.d.ts +63 -0
  49. package/dist/internal-types/store/torn.d.ts +78 -0
  50. package/dist/migration-source.d.ts +33 -0
  51. package/dist/models.d.ts +41 -0
  52. package/dist/native-account-runtime.d.ts +121 -0
  53. package/dist/native-account-view.d.ts +126 -0
  54. package/dist/native-command-effects.d.ts +59 -0
  55. package/dist/native-credential-validation.d.ts +42 -0
  56. package/dist/native-custody-activation.d.ts +45 -0
  57. package/dist/native-custody.d.ts +114 -0
  58. package/dist/native-enrollment-authority.d.ts +2 -0
  59. package/dist/native-host-auth-read.d.ts +3 -0
  60. package/dist/native-host-auth-write.d.ts +51 -0
  61. package/dist/native-host-auth.d.ts +12 -0
  62. package/dist/native-local-credential-service.d.ts +76 -0
  63. package/dist/native-local-runtime-readers.d.ts +22 -0
  64. package/dist/native-lock-observer.d.ts +12 -0
  65. package/dist/native-menu-executor.d.ts +243 -0
  66. package/dist/native-menu-model.d.ts +142 -0
  67. package/dist/native-migration-proof.d.ts +28 -0
  68. package/dist/native-migration-source.d.ts +47 -0
  69. package/dist/native-migration.d.ts +66 -0
  70. package/dist/native-quota-codec.d.ts +32 -0
  71. package/dist/native-refresh-coordinator.d.ts +240 -0
  72. package/dist/native-roster-seed.d.ts +115 -0
  73. package/dist/native-runtime-registry.d.ts +19 -0
  74. package/dist/native-runtime.d.ts +204 -0
  75. package/dist/native-transient-account.d.ts +38 -0
  76. package/dist/native-ui.d.ts +45 -0
  77. package/dist/native-usage-publication.d.ts +11 -0
  78. package/dist/native-vault-admission.d.ts +8 -0
  79. package/dist/native-vault-connection.d.ts +33 -0
  80. package/dist/native-vault-paths.d.ts +13 -0
  81. package/dist/native-vault-runtime.d.ts +102 -0
  82. package/dist/native-vault-seed.d.ts +16 -0
  83. package/dist/pool-authority.d.ts +159 -0
  84. package/dist/pool-binding.d.ts +32 -0
  85. package/dist/pool-paths.d.ts +21 -0
  86. package/dist/pool-store.d.ts +32 -0
  87. package/dist/provider-error.d.ts +139 -0
  88. package/dist/quota-manager.d.ts +18 -7
  89. package/dist/relay.d.ts +14 -1
  90. package/dist/request-history.d.ts +34 -0
  91. package/dist/sse.d.ts +81 -0
  92. package/dist/sticky-routing.d.ts +27 -0
  93. package/package.json +9 -4
  94. package/dist/accounts.js +0 -3881
  95. package/dist/auth.js +0 -185
  96. package/dist/cache1h.js +0 -97
  97. package/dist/cachekeep-registry.js +0 -124
  98. package/dist/cachekeep.js +0 -604
  99. package/dist/cch.js +0 -172
  100. package/dist/claude-code.js +0 -403
  101. package/dist/claustrum-enrollment-registry.d.ts +0 -17
  102. package/dist/claustrum-enrollment-registry.js +0 -194
  103. package/dist/claustrum-enrollment.js +0 -485
  104. package/dist/claustrum-scoped-roster.js +0 -194
  105. package/dist/claustrum-scoped-runtime.js +0 -230
  106. package/dist/claustrum-scoped.js +0 -193
  107. package/dist/claustrum.js +0 -1471
  108. package/dist/commands/account.js +0 -368
  109. package/dist/constants.js +0 -83
  110. package/dist/custom-headers.js +0 -102
  111. package/dist/dump.js +0 -616
  112. package/dist/fast.js +0 -66
  113. package/dist/json.js +0 -10
  114. package/dist/killswitch.js +0 -132
  115. package/dist/logger.js +0 -288
  116. package/dist/logging.js +0 -59
  117. package/dist/mid-conversation-output-config.js +0 -89
  118. package/dist/model-remap.js +0 -72
  119. package/dist/models.js +0 -177
  120. package/dist/network-errors.js +0 -27
  121. package/dist/oauth-profile.js +0 -60
  122. package/dist/pkce.js +0 -17
  123. package/dist/prime.js +0 -841
  124. package/dist/provider.js +0 -0
  125. package/dist/quota-header-feed.js +0 -331
  126. package/dist/quota-headers.js +0 -121
  127. package/dist/quota-manager.js +0 -856
  128. package/dist/quotas.js +0 -141
  129. package/dist/relay.js +0 -1303
  130. package/dist/routing.js +0 -94
  131. package/dist/start.js +0 -29
  132. package/dist/sticky-routing.js +0 -541
  133. package/dist/thinking-binding.js +0 -54
  134. package/dist/token-fingerprint.js +0 -8
package/dist/cch.js DELETED
@@ -1,172 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import xxhashInit from 'xxhash-wasm';
3
- import { CCH_POSITIONS, CCH_SALT, CLAUDE_CODE_VERSION } from './constants.js';
4
- const ANTHROPIC_REQUEST_ID_PATTERN = /^req_[A-Za-z0-9_-]{8,128}$/;
5
- const PROMPT_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
6
- const BILLING_LINEAGE_FIELD_PATTERN = / cc_(?:prev_req|prompt_id)=[^;\r\n]*;/g;
7
- export function isValidAnthropicRequestId(value) {
8
- return ANTHROPIC_REQUEST_ID_PATTERN.test(value);
9
- }
10
- export function isValidBillingPromptId(value) {
11
- return PROMPT_ID_PATTERN.test(value);
12
- }
13
- const CCH_SEED = 0x4d659218e32a3268n;
14
- const CCH_PLACEHOLDER = 'cch=00000;';
15
- export const CCH_PATTERN = /\bcch=([0-9a-f]{5});/;
16
- const BILLING_HEADER_CCH_PATTERN = /("system":\[\{"type":"text","text":"x-anthropic-billing-header: cc_version=[^;"]+; cc_entrypoint=[^;"]+; )cch=([0-9a-f]{5});/;
17
- const BILLING_HEADER_CCH_PLACEHOLDER_PATTERN = /("system":\[\{"type":"text","text":"x-anthropic-billing-header: cc_version=[^;"]+; cc_entrypoint=[^;"]+; )cch=00000;/;
18
- let xxhashPromise = null;
19
- let xxhash64Raw = null;
20
- async function ensureXxhash() {
21
- if (xxhash64Raw)
22
- return;
23
- xxhashPromise ??= (async () => {
24
- const hasher = await xxhashInit();
25
- xxhash64Raw = hasher.h64Raw;
26
- })();
27
- await xxhashPromise;
28
- }
29
- /**
30
- * Extract the visible prompt from the first user message. Claude Code prepends
31
- * reminder blocks and derives its version suffix from the final text block.
32
- */
33
- export function extractFirstUserMessageText(messages) {
34
- const userMsg = messages.find((message) => message.role === 'user');
35
- if (!userMsg)
36
- return '';
37
- const { content } = userMsg;
38
- if (typeof content === 'string')
39
- return content;
40
- if (Array.isArray(content)) {
41
- const textBlocks = content.filter((block) => block.type === 'text');
42
- const commandBlock = textBlocks.find((block) => block.text?.includes('<command-name>'));
43
- if (commandBlock?.text) {
44
- return commandBlock.text.slice(commandBlock.text.indexOf('<command-name>'));
45
- }
46
- const visibleBlock = textBlocks.findLast((block) => typeof block.text === 'string' && block.text.length > 0);
47
- if (visibleBlock?.text)
48
- return visibleBlock.text;
49
- }
50
- return '';
51
- }
52
- export class ClaudeCodeFirstUserTextTracker {
53
- limit;
54
- #values = new Map();
55
- constructor(limit = 1_000) {
56
- this.limit = limit;
57
- }
58
- resolve(sessionId, messages, pin = true) {
59
- const existing = this.#values.get(sessionId);
60
- if (existing !== undefined) {
61
- this.#values.delete(sessionId);
62
- this.#values.set(sessionId, existing);
63
- return existing;
64
- }
65
- const value = extractFirstUserMessageText(messages);
66
- if (pin) {
67
- if (!this.#values.has(sessionId) && this.#values.size >= this.limit) {
68
- const oldest = this.#values.keys().next().value;
69
- if (oldest !== undefined)
70
- this.#values.delete(oldest);
71
- }
72
- this.#values.set(sessionId, value);
73
- }
74
- return value;
75
- }
76
- has(sessionId) {
77
- return this.#values.has(sessionId);
78
- }
79
- clear() {
80
- this.#values.clear();
81
- }
82
- }
83
- /**
84
- * Compute Claude Code's cch token over the final serialized request body.
85
- *
86
- * Real Claude Code signs the full body bytes with xxHash64 using a fixed seed,
87
- * masks to 20 bits, and writes that value into the billing-header placeholder.
88
- */
89
- export async function computeCCH(bodyBytes) {
90
- await ensureXxhash();
91
- const hash = xxhash64Raw?.(bodyBytes, CCH_SEED) ?? 0n;
92
- return (hash & 0xfffffn).toString(16).padStart(5, '0');
93
- }
94
- export async function computeXxhash64Hex(value) {
95
- await ensureXxhash();
96
- const hash = xxhash64Raw?.(new TextEncoder().encode(value), 0n) ?? 0n;
97
- return hash.toString(16).padStart(16, '0').slice(0, 16);
98
- }
99
- export function resetBillingHeaderCCH(bodyString) {
100
- return bodyString.replace(BILLING_HEADER_CCH_PATTERN, `$1${CCH_PLACEHOLDER}`);
101
- }
102
- export function extractBillingHeaderCCH(bodyString) {
103
- return BILLING_HEADER_CCH_PATTERN.exec(bodyString)?.[2] ?? null;
104
- }
105
- export async function signRequestBody(bodyString) {
106
- if (!BILLING_HEADER_CCH_PATTERN.test(bodyString))
107
- return bodyString;
108
- const unsignedBodyString = resetBillingHeaderCCH(bodyString);
109
- const canonicalBody = JSON.parse(unsignedBodyString);
110
- if ('model' in canonicalBody)
111
- canonicalBody.model = '';
112
- delete canonicalBody.max_tokens;
113
- const token = await computeCCH(new TextEncoder().encode(JSON.stringify(canonicalBody)));
114
- return unsignedBodyString.replace(BILLING_HEADER_CCH_PLACEHOLDER_PATTERN, `$1cch=${token};`);
115
- }
116
- /**
117
- * Compute Claude Code's 3-character suffix for cc_version.
118
- */
119
- export function computeCcVersionSuffix(firstUserText, version = CLAUDE_CODE_VERSION) {
120
- const sampledText = CCH_POSITIONS.map((position) => firstUserText[position] ?? '0').join('');
121
- return createHash('sha256')
122
- .update(`${CCH_SALT}${sampledText}${version}`)
123
- .digest('hex')
124
- .slice(0, 3);
125
- }
126
- /**
127
- * Build the billing header with a cch placeholder.
128
- * signRequestBody() must run after final request serialization to replace it.
129
- */
130
- export function buildBillingHeaderValue(messages, version = CLAUDE_CODE_VERSION, entrypoint, pinnedFirstUserText, lineage) {
131
- const suffix = computeCcVersionSuffix(pinnedFirstUserText ?? extractFirstUserMessageText(messages), version);
132
- let value = 'x-anthropic-billing-header: ' +
133
- `cc_version=${version}.${suffix}; ` +
134
- `cc_entrypoint=${entrypoint}; ` +
135
- 'cch=00000;';
136
- if (lineage?.previousRequestId &&
137
- isValidAnthropicRequestId(lineage.previousRequestId)) {
138
- value += ` cc_prev_req=${lineage.previousRequestId};`;
139
- }
140
- if (lineage?.promptId && isValidBillingPromptId(lineage.promptId)) {
141
- value += ` cc_prompt_id=${lineage.promptId};`;
142
- }
143
- return value;
144
- }
145
- /** Remove request-scoped Claude Code lineage from a billing header string. */
146
- export function stripBillingLineageFields(value) {
147
- return value.replace(BILLING_LINEAGE_FIELD_PATTERN, '');
148
- }
149
- /** Remove request-scoped Claude Code lineage before reusing a request body. */
150
- export function stripBillingLineageFromBody(body) {
151
- if (!body || typeof body !== 'object')
152
- return 0;
153
- const system = body.system;
154
- if (!Array.isArray(system))
155
- return 0;
156
- let stripped = 0;
157
- for (const block of system) {
158
- if (!block || typeof block !== 'object')
159
- continue;
160
- const text = block.text;
161
- if (typeof text !== 'string' ||
162
- !text.startsWith('x-anthropic-billing-header:')) {
163
- continue;
164
- }
165
- const clean = stripBillingLineageFields(text);
166
- if (clean === text)
167
- continue;
168
- block.text = clean;
169
- stripped += 1;
170
- }
171
- return stripped;
172
- }
@@ -1,403 +0,0 @@
1
- import { randomBytes, randomUUID } from 'node:crypto';
2
- import { CLAUDE_CODE_ENTRYPOINT, CLAUDE_CODE_STAINLESS_PACKAGE_VERSION, CLAUDE_CODE_STAINLESS_RUNTIME_VERSION, CLAUDE_CODE_VERSION, FAST_MODE_BETA, USER_AGENT, } from './constants.js';
3
- const IDENTITY_CACHE_LIMIT = 1_000;
4
- const identityCache = new Map();
5
- export function setBounded(map, key, value, limit = IDENTITY_CACHE_LIMIT) {
6
- if (!map.has(key) && map.size >= limit) {
7
- const oldest = map.keys().next().value;
8
- if (oldest !== undefined)
9
- map.delete(oldest);
10
- }
11
- map.set(key, value);
12
- }
13
- function clearCachedAccountUuid(key, identity) {
14
- if (!identity.accountUuid)
15
- return identity;
16
- if (identityCache.get(key) !== identity) {
17
- return { ...identity, accountUuid: undefined };
18
- }
19
- const cleared = { ...identity, accountUuid: undefined };
20
- setBounded(identityCache, key, cleared);
21
- return cleared;
22
- }
23
- export function getClaudeCodeIdentity(seed) {
24
- const cacheKey = seed || 'anonymous';
25
- const cached = identityCache.get(cacheKey);
26
- if (cached)
27
- return cached;
28
- const identity = {
29
- deviceId: randomBytes(32).toString('hex'),
30
- sessionId: randomUUID(),
31
- };
32
- setBounded(identityCache, cacheKey, identity);
33
- return identity;
34
- }
35
- const BOOTSTRAP_IDENTITY_CACHE_TTL_MS = 24 * 60 * 60_000;
36
- const BOOTSTRAP_IDENTITY_NEGATIVE_TTL_MS = 5 * 60_000;
37
- const bootstrapFetches = new Map();
38
- const bootstrapResults = new Map();
39
- export function resetClaudeCodeIdentityCachesForTest() {
40
- identityCache.clear();
41
- bootstrapFetches.clear();
42
- bootstrapResults.clear();
43
- }
44
- function compatibilityCacheKey(accessToken) {
45
- return `compat:${accessToken || 'anonymous'}`;
46
- }
47
- function explicitCacheKey(accountIdentity) {
48
- return `identity:${accountIdentity}`;
49
- }
50
- function accountCacheKey(accountUuid, accountIdentity) {
51
- return `account:${accountUuid}:${accountIdentity}`;
52
- }
53
- function adoptCachedIdentity(cached, accountIdentity, accountUuid) {
54
- if (!cached)
55
- return undefined;
56
- if (cached.accountIdentity !== undefined &&
57
- cached.accountIdentity !== accountIdentity) {
58
- return undefined;
59
- }
60
- if (accountUuid !== undefined &&
61
- cached.accountUuid !== undefined &&
62
- cached.accountUuid !== accountUuid) {
63
- return undefined;
64
- }
65
- if (cached.accountIdentity === accountIdentity &&
66
- (accountUuid === undefined || cached.accountUuid === accountUuid)) {
67
- return cached;
68
- }
69
- return {
70
- ...cached,
71
- accountIdentity,
72
- ...(accountUuid !== undefined && { accountUuid }),
73
- };
74
- }
75
- function cacheAccountIdentity(identity, accountIdentity, accountUuid) {
76
- setBounded(identityCache, explicitCacheKey(accountIdentity), identity);
77
- setBounded(identityCache, accountCacheKey(accountUuid, accountIdentity), identity);
78
- }
79
- async function fetchClaudeCodeAccountUuid(accessToken, model) {
80
- if (!accessToken.startsWith('sk-ant-oat'))
81
- return null;
82
- const controller = new AbortController();
83
- const timeout = setTimeout(() => controller.abort(), 5_000);
84
- try {
85
- const url = new URL('https://api.anthropic.com/api/claude_cli/bootstrap');
86
- url.searchParams.set('entrypoint', CLAUDE_CODE_ENTRYPOINT);
87
- if (model)
88
- url.searchParams.set('model', model);
89
- const response = await fetch(url, {
90
- method: 'GET',
91
- headers: {
92
- accept: 'application/json, text/plain, */*',
93
- authorization: `Bearer ${accessToken}`,
94
- 'content-type': 'application/json',
95
- 'anthropic-beta': 'oauth-2025-04-20',
96
- 'user-agent': `claude-code/${CLAUDE_CODE_VERSION}`,
97
- },
98
- signal: controller.signal,
99
- });
100
- if (!response.ok)
101
- return null;
102
- const data = (await response.json().catch(() => null));
103
- const accountUuid = data?.oauth_account?.account_uuid;
104
- return typeof accountUuid === 'string' && accountUuid
105
- ? accountUuid
106
- : null;
107
- }
108
- catch {
109
- return null;
110
- }
111
- finally {
112
- clearTimeout(timeout);
113
- }
114
- }
115
- /** Use the identity already verified by the credential custodian, without an
116
- * additional bootstrap request carrying a previously authorized token. */
117
- export function getClaudeCodeIdentityForVerifiedAccount(accountIdentity, accountUuid) {
118
- if (!accountIdentity.trim() || !accountUuid.trim()) {
119
- throw new Error('A verified provider account identity is required');
120
- }
121
- const base = identityCache.get(accountCacheKey(accountUuid, accountIdentity)) ??
122
- getClaudeCodeIdentity(explicitCacheKey(accountIdentity));
123
- const identity = { ...base, accountIdentity, accountUuid };
124
- cacheAccountIdentity(identity, accountIdentity, accountUuid);
125
- return identity;
126
- }
127
- export async function resolveClaudeCodeIdentity(accessToken, model, accountIdentity) {
128
- const stableAccountIdentity = accountIdentity?.trim() || undefined;
129
- const cacheKey = stableAccountIdentity
130
- ? explicitCacheKey(stableAccountIdentity)
131
- : compatibilityCacheKey(accessToken);
132
- let identity;
133
- if (stableAccountIdentity) {
134
- const cachedIdentity = adoptCachedIdentity(identityCache.get(cacheKey) ?? identityCache.get(accessToken), stableAccountIdentity);
135
- identity = cachedIdentity ?? getClaudeCodeIdentity(cacheKey);
136
- identity = adoptCachedIdentity(identity, stableAccountIdentity) ?? identity;
137
- setBounded(identityCache, cacheKey, identity);
138
- }
139
- else {
140
- identity =
141
- identityCache.get(cacheKey) ??
142
- identityCache.get(accessToken) ??
143
- getClaudeCodeIdentity(cacheKey);
144
- setBounded(identityCache, cacheKey, identity);
145
- setBounded(identityCache, accessToken, identity);
146
- }
147
- if (!accessToken.startsWith('sk-ant-oat')) {
148
- return clearCachedAccountUuid(cacheKey, identity);
149
- }
150
- const now = Date.now();
151
- // A slot-stable identity survives account replacement; bootstrap is the
152
- // account lookup that must be repeated for each credential presented to it.
153
- const bootstrapKey = `${cacheKey}:${accessToken}`;
154
- const cachedResult = bootstrapResults.get(bootstrapKey);
155
- if (cachedResult && cachedResult.expiresAt > now) {
156
- if (!cachedResult.accountUuid) {
157
- identity = clearCachedAccountUuid(cacheKey, identity);
158
- return identity;
159
- }
160
- if (!stableAccountIdentity) {
161
- if (identity.accountUuid === cachedResult.accountUuid)
162
- return identity;
163
- identity = { ...identity, accountUuid: cachedResult.accountUuid };
164
- setBounded(identityCache, bootstrapKey, identity);
165
- return identity;
166
- }
167
- const cachedAccountIdentity = adoptCachedIdentity(identityCache.get(accountCacheKey(cachedResult.accountUuid, stableAccountIdentity)) ?? identityCache.get(`account:${cachedResult.accountUuid}`), stableAccountIdentity, cachedResult.accountUuid);
168
- if (cachedAccountIdentity) {
169
- identity = cachedAccountIdentity;
170
- cacheAccountIdentity(identity, stableAccountIdentity, cachedResult.accountUuid);
171
- return identity;
172
- }
173
- if (identity.accountUuid === cachedResult.accountUuid)
174
- return identity;
175
- identity = {
176
- ...identity,
177
- accountIdentity: stableAccountIdentity,
178
- accountUuid: cachedResult.accountUuid,
179
- };
180
- cacheAccountIdentity(identity, stableAccountIdentity, cachedResult.accountUuid);
181
- return identity;
182
- }
183
- let fetchPromise = bootstrapFetches.get(bootstrapKey);
184
- if (!fetchPromise) {
185
- fetchPromise = fetchClaudeCodeAccountUuid(accessToken, model);
186
- setBounded(bootstrapFetches, bootstrapKey, fetchPromise);
187
- }
188
- const accountUuid = await fetchPromise.finally(() => {
189
- if (bootstrapFetches.get(bootstrapKey) === fetchPromise) {
190
- bootstrapFetches.delete(bootstrapKey);
191
- }
192
- });
193
- setBounded(bootstrapResults, bootstrapKey, {
194
- accountUuid,
195
- expiresAt: now +
196
- (accountUuid
197
- ? BOOTSTRAP_IDENTITY_CACHE_TTL_MS
198
- : BOOTSTRAP_IDENTITY_NEGATIVE_TTL_MS),
199
- });
200
- if (!accountUuid) {
201
- identity = clearCachedAccountUuid(cacheKey, identity);
202
- return identity;
203
- }
204
- if (!stableAccountIdentity) {
205
- identity = { ...identity, accountUuid };
206
- setBounded(identityCache, bootstrapKey, identity);
207
- return identity;
208
- }
209
- const cachedAccountIdentity = adoptCachedIdentity(identityCache.get(accountCacheKey(accountUuid, stableAccountIdentity)) ??
210
- identityCache.get(`account:${accountUuid}`), stableAccountIdentity, accountUuid);
211
- if (cachedAccountIdentity) {
212
- identity = cachedAccountIdentity;
213
- cacheAccountIdentity(identity, stableAccountIdentity, accountUuid);
214
- return identity;
215
- }
216
- identity = {
217
- ...identity,
218
- accountIdentity: stableAccountIdentity,
219
- accountUuid,
220
- };
221
- cacheAccountIdentity(identity, stableAccountIdentity, accountUuid);
222
- return identity;
223
- }
224
- function isRecord(value) {
225
- return value != null && typeof value === 'object' && !Array.isArray(value);
226
- }
227
- export function buildClaudeCodeMetadataUserId(identity) {
228
- if (!identity.accountUuid)
229
- return null;
230
- return JSON.stringify({
231
- device_id: identity.deviceId,
232
- account_uuid: identity.accountUuid,
233
- session_id: identity.sessionId,
234
- });
235
- }
236
- export function applyClaudeCodeMetadata(body, identity) {
237
- const userId = buildClaudeCodeMetadataUserId(identity);
238
- if (!userId) {
239
- if (isRecord(body.metadata))
240
- delete body.metadata.user_id;
241
- return false;
242
- }
243
- if (!isRecord(body.metadata))
244
- body.metadata = {};
245
- const metadata = body.metadata;
246
- if (isRecord(metadata))
247
- metadata.user_id = userId;
248
- return true;
249
- }
250
- // Claude Code 2.1.258 sends redact-thinking-2026-02-12, but it suppresses
251
- // thinking-block content that OpenCode displays; deliberately omitted after A/B proof on 2026-09-01.
252
- export const CLAUDE_CODE_FULL_AGENT_BETAS = [
253
- 'oauth-2025-04-20',
254
- 'interleaved-thinking-2025-05-14',
255
- 'thinking-token-count-2026-05-13',
256
- 'context-management-2025-06-27',
257
- 'prompt-caching-scope-2026-01-05',
258
- 'claude-code-20250219',
259
- 'advisor-tool-2026-03-01',
260
- 'advanced-tool-use-2025-11-20',
261
- 'mid-conversation-system-2026-04-07',
262
- 'effort-2025-11-24',
263
- 'fallback-credit-2026-06-01',
264
- 'extended-cache-ttl-2025-04-11',
265
- 'cache-diagnosis-2026-04-07',
266
- ];
267
- const CLAUDE_CODE_STRUCTURED_OUTPUT_BETAS = [
268
- 'oauth-2025-04-20',
269
- 'interleaved-thinking-2025-05-14',
270
- 'thinking-token-count-2026-05-13',
271
- 'context-management-2025-06-27',
272
- 'prompt-caching-scope-2026-01-05',
273
- 'advisor-tool-2026-03-01',
274
- 'structured-outputs-2025-12-15',
275
- 'cache-diagnosis-2026-04-07',
276
- ];
277
- const CLAUDE_CODE_BASE_BETAS = [
278
- 'oauth-2025-04-20',
279
- 'interleaved-thinking-2025-05-14',
280
- 'thinking-token-count-2026-05-13',
281
- 'context-management-2025-06-27',
282
- 'prompt-caching-scope-2026-01-05',
283
- 'advisor-tool-2026-03-01',
284
- 'advanced-tool-use-2025-11-20',
285
- 'extended-cache-ttl-2025-04-11',
286
- 'cache-diagnosis-2026-04-07',
287
- ];
288
- function hasStructuredOutput(body) {
289
- const outputConfig = body.output_config;
290
- const format = outputConfig?.format;
291
- return format?.type === 'json_schema';
292
- }
293
- function hasFullAgentShape(body) {
294
- return (Array.isArray(body.tools) &&
295
- body.tools.length > 0 &&
296
- Array.isArray(body.system) &&
297
- isRecord(body.thinking) &&
298
- isRecord(body.context_management) &&
299
- isRecord(body.output_config) &&
300
- isRecord(body.diagnostics));
301
- }
302
- export function selectClaudeCodeBetas(body, extraBetas = []) {
303
- const selected = body
304
- ? hasFullAgentShape(body)
305
- ? [...CLAUDE_CODE_FULL_AGENT_BETAS]
306
- : hasStructuredOutput(body)
307
- ? [...CLAUDE_CODE_STRUCTURED_OUTPUT_BETAS]
308
- : [...CLAUDE_CODE_BASE_BETAS]
309
- : [...CLAUDE_CODE_BASE_BETAS];
310
- if (body?.speed === 'fast')
311
- selected.push(FAST_MODE_BETA);
312
- for (const beta of extraBetas) {
313
- const trimmed = beta.trim();
314
- if (trimmed)
315
- selected.push(trimmed);
316
- }
317
- return [...new Set(selected)].join(',');
318
- }
319
- function stainlessOS() {
320
- switch (process.platform) {
321
- case 'darwin':
322
- return 'MacOS';
323
- case 'win32':
324
- return 'Windows';
325
- case 'linux':
326
- return 'Linux';
327
- case 'freebsd':
328
- return 'FreeBSD';
329
- default:
330
- return 'Unknown';
331
- }
332
- }
333
- function stainlessArch() {
334
- switch (process.arch) {
335
- case 'arm64':
336
- return 'arm64';
337
- case 'x64':
338
- return 'x64';
339
- case 'ia32':
340
- return 'x32';
341
- default:
342
- return process.arch;
343
- }
344
- }
345
- export function applyClaudeCodeHeaders(headers, accessToken, options = {}) {
346
- const identity = options.identity ?? getClaudeCodeIdentity(accessToken);
347
- const incomingBetas = (headers.get('anthropic-beta') ?? '')
348
- .split(',')
349
- .map((beta) => beta.trim())
350
- .filter(Boolean);
351
- const extraBetas = [...incomingBetas, ...(options.extraBetas ?? [])];
352
- headers.set('accept', 'application/json');
353
- headers.set('authorization', `Bearer ${accessToken}`);
354
- headers.set('content-type', 'application/json');
355
- headers.set('user-agent', USER_AGENT);
356
- headers.set('anthropic-beta', selectClaudeCodeBetas(options.body, extraBetas));
357
- headers.set('anthropic-dangerous-direct-browser-access', 'true');
358
- headers.set('anthropic-version', '2023-06-01');
359
- headers.set('x-app', 'cli');
360
- headers.set('x-client-request-id', randomUUID());
361
- headers.set('x-claude-code-session-id', identity.sessionId);
362
- headers.set('x-stainless-arch', stainlessArch());
363
- headers.set('x-stainless-lang', 'js');
364
- headers.set('x-stainless-os', stainlessOS());
365
- headers.set('x-stainless-package-version', CLAUDE_CODE_STAINLESS_PACKAGE_VERSION);
366
- headers.set('x-stainless-retry-count', '0');
367
- headers.set('x-stainless-runtime', 'node');
368
- headers.set('x-stainless-runtime-version', CLAUDE_CODE_STAINLESS_RUNTIME_VERSION);
369
- headers.set('x-stainless-timeout', '600');
370
- headers.delete('x-api-key');
371
- return headers;
372
- }
373
- const BODY_FIELD_ORDER = [
374
- 'model',
375
- 'messages',
376
- 'system',
377
- 'tools',
378
- 'tool_choice',
379
- 'metadata',
380
- 'max_tokens',
381
- 'temperature',
382
- 'thinking',
383
- 'context_management',
384
- 'output_config',
385
- 'diagnostics',
386
- 'stream',
387
- 'speed',
388
- ];
389
- export function orderClaudeCodeBody(body) {
390
- const ordered = {};
391
- for (const key of BODY_FIELD_ORDER) {
392
- if (Object.hasOwn(body, key))
393
- ordered[key] = body[key];
394
- }
395
- for (const [key, value] of Object.entries(body)) {
396
- if (!Object.hasOwn(ordered, key))
397
- ordered[key] = value;
398
- }
399
- return ordered;
400
- }
401
- export function claudeCodeEntrypoint() {
402
- return CLAUDE_CODE_ENTRYPOINT;
403
- }
@@ -1,17 +0,0 @@
1
- import { type ClaustrumEnrollmentConnection, type ClaustrumEnrollmentPaths, type ClaustrumEnrollmentStatus } from './claustrum-enrollment.js';
2
- export declare function getHostClaustrumEnrollmentPaths(host: 'opencode' | 'pi', env?: NodeJS.ProcessEnv, cwd?: string): ClaustrumEnrollmentPaths;
3
- export interface ClaustrumEnrollmentAdoption {
4
- status(): ClaustrumEnrollmentStatus;
5
- reconcileNow(): Promise<void>;
6
- resetTerminal(): Promise<'reset' | 'idle' | 'refused-pending' | 'refused-approved' | 'busy'>;
7
- release(): void;
8
- }
9
- export declare function adoptClaustrumEnrollment(options: {
10
- proposedName: string;
11
- paths: ClaustrumEnrollmentPaths;
12
- connect: () => Promise<ClaustrumEnrollmentConnection>;
13
- onStatus?: (status: ClaustrumEnrollmentStatus) => void;
14
- setTimeoutImpl?: typeof setTimeout;
15
- clearTimeoutImpl?: typeof clearTimeout;
16
- pollIntervalMs?: number;
17
- }): ClaustrumEnrollmentAdoption;