@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
@@ -1,368 +0,0 @@
1
- import { getClaustrumMode, isOAuthAccount, isOAuthAccountVaultOwned, } from '../accounts.js';
2
- import { formatOAuthAccountTier } from '../oauth-profile.js';
3
- export const CLAUDE_ACCOUNT_COMMAND_NAME = 'claude-account';
4
- export function parseAccountCommandAction(argumentsText) {
5
- const parts = argumentsText.trim().split(/\s+/).filter(Boolean);
6
- if (parts.length === 0)
7
- return { type: 'status' };
8
- const action = parts[0];
9
- const rest = parts.slice(1).join(' ');
10
- if (action === 'enable' && rest)
11
- return { type: 'enable', id: rest };
12
- if (action === 'disable' && rest)
13
- return { type: 'disable', id: rest };
14
- if (action === 'remove' && rest)
15
- return { type: 'remove', id: rest };
16
- if (action === 'move-up' && rest)
17
- return { type: 'move-up', id: rest };
18
- if (action === 'move-down' && rest)
19
- return { type: 'move-down', id: rest };
20
- if (action === 'reset-backoff' && !rest)
21
- return { type: 'reset-backoff' };
22
- if (action === 'enrollment-reset' && !rest)
23
- return { type: 'enrollment-reset' };
24
- if (action === 'claustrum' && !rest) {
25
- return { type: 'claustrum-mode', mode: 'claustrum' };
26
- }
27
- if (action === 'local' && !rest) {
28
- return { type: 'claustrum-mode', mode: 'local' };
29
- }
30
- if (action === 'add-apikey' && rest) {
31
- let remaining = rest;
32
- let baseURL;
33
- let authHeader;
34
- // Parse --base-url flag
35
- const baseUrlMatch = remaining.match(/--base-url\s+(\S+)/);
36
- if (baseUrlMatch) {
37
- baseURL = baseUrlMatch[1];
38
- remaining = remaining.replace(baseUrlMatch[0], '').trim();
39
- }
40
- // Parse --auth-header flag
41
- const authMatch = remaining.match(/--auth-header\s+(authorization-bearer|x-api-key)/);
42
- if (authMatch) {
43
- authHeader = authMatch[1];
44
- remaining = remaining.replace(authMatch[0], '').trim();
45
- }
46
- // Parse --label flag
47
- let label;
48
- const labelMatch = remaining.match(/--label\s+(.+)/);
49
- if (labelMatch) {
50
- label = labelMatch[1]?.trim() || undefined;
51
- remaining = remaining.replace(labelMatch[0], '').trim();
52
- }
53
- // First remaining token is the API key; rest (if any) is label
54
- const firstSpace = remaining.indexOf(' ');
55
- if (firstSpace === -1) {
56
- if (!remaining)
57
- return { type: 'usage' };
58
- return {
59
- type: 'add-apikey',
60
- apiKey: remaining,
61
- baseURL,
62
- authHeader,
63
- label,
64
- };
65
- }
66
- const apiKey = remaining.slice(0, firstSpace);
67
- const tail = remaining.slice(firstSpace + 1).trim();
68
- return {
69
- type: 'add-apikey',
70
- apiKey,
71
- label: label ?? (tail || undefined),
72
- baseURL,
73
- authHeader,
74
- };
75
- }
76
- if (action === 'add-oauth-start')
77
- return { type: 'add-oauth-start' };
78
- if (action === 'add-oauth-finish' && rest) {
79
- let remaining = rest;
80
- // Parse --label flag (mirrors add-apikey). The OAuth code is opaque (may
81
- // contain a #state segment) so the label is collected via the flag, never
82
- // positionally.
83
- let label;
84
- const labelMatch = remaining.match(/--label\s+(.+)/);
85
- if (labelMatch) {
86
- label = labelMatch[1]?.trim() || undefined;
87
- remaining = remaining.replace(labelMatch[0], '').trim();
88
- }
89
- if (!remaining)
90
- return { type: 'usage' };
91
- return { type: 'add-oauth-finish', code: remaining, label };
92
- }
93
- return { type: 'usage' };
94
- }
95
- export function custodyStatusLabel(state) {
96
- switch (state) {
97
- case 'na':
98
- return 'n/a (OpenCode-managed)';
99
- case 'off':
100
- return 'not enrolled';
101
- case 'on-vault-served':
102
- return 'vault-served';
103
- case 'on-vault-reauth':
104
- return 'vault reauth';
105
- case 'on-cold':
106
- return 'vault cold';
107
- case 'unknown-identity':
108
- return 'unknown identity';
109
- case 'on-identity-mismatch':
110
- return 'identity mismatch';
111
- case 'on-corrupt-binding':
112
- return 'corrupt binding';
113
- }
114
- }
115
- export function formatEnrollmentStatus(status, scopedServing = false) {
116
- switch (status.state) {
117
- case 'idle':
118
- return ['- Enrollment: not enrolled'];
119
- case 'busy':
120
- return ['- Enrollment: another plugin process is reconciling'];
121
- case 'unavailable':
122
- return ['- Enrollment: temporarily unavailable'];
123
- case 'pending':
124
- return status.requestId && /^[A-Za-z0-9_-]{1,128}$/.test(status.requestId)
125
- ? [
126
- `- Enrollment: pending approval (${status.requestId})`,
127
- `- Approve: \`ck auth enroll approve --request-id ${status.requestId}\``,
128
- ]
129
- : status.requestId
130
- ? [
131
- '- Enrollment: pending approval; inspect it with `ck auth enroll list`',
132
- ]
133
- : ['- Enrollment: preparing request'];
134
- case 'approved': {
135
- const name = status.approvedName ?? status.proposedName;
136
- return /^[A-Za-z0-9_-]{1,128}$/.test(name)
137
- ? [
138
- `- Enrollment: approved as enrolled:${name} (generation ${status.tokenGeneration}${scopedServing ? '' : '; scoped serving not active yet'})`,
139
- ...(scopedServing
140
- ? []
141
- : [
142
- `- Grant: \`ck auth grant --principal enrolled:${name} --selector-kind category --selector anthropic-native --operation read\``,
143
- ]),
144
- ]
145
- : [
146
- `- Enrollment: approved (generation ${status.tokenGeneration}${scopedServing ? '' : '; scoped serving not active yet'})`,
147
- ...(scopedServing
148
- ? []
149
- : [
150
- '- Inspect the approved name with `ck auth enroll list` before granting access.',
151
- ]),
152
- ];
153
- }
154
- case 'denied':
155
- return ['- Enrollment: denied by operator'];
156
- case 'blocked':
157
- return [`- Enrollment: blocked (${status.code})`];
158
- }
159
- }
160
- export function buildAccountList(storage) {
161
- const list = [];
162
- const fiveHour = storage.quota?.mainQuota?.five_hour;
163
- list.push({
164
- id: 'main',
165
- label: storage.main?.provider === 'anthropic' ? 'OpenCode anthropic' : 'Main',
166
- role: 'main',
167
- enabled: true,
168
- quotaPercent: fiveHour?.usedPercent ?? null,
169
- tierLabel: formatOAuthAccountTier(storage.main?.profile),
170
- });
171
- for (const account of storage.accounts) {
172
- const fiveHourQuota = account.quota?.five_hour;
173
- list.push({
174
- id: account.id,
175
- label: account.label ?? account.id,
176
- role: 'fallback',
177
- enabled: account.enabled !== false,
178
- quotaPercent: fiveHourQuota?.usedPercent ?? null,
179
- tierLabel: account.type === 'oauth'
180
- ? formatOAuthAccountTier(account.profile)
181
- : undefined,
182
- });
183
- }
184
- return list;
185
- }
186
- const USAGE_TEXT = [
187
- 'Usage:',
188
- ' /claude-account Show account list',
189
- ' /claude-account enable <id> Enable a fallback account',
190
- ' /claude-account disable <id> Disable a fallback account',
191
- ' /claude-account remove <id> Remove a fallback account',
192
- ' /claude-account claustrum Enable Claustrum mode',
193
- ' /claude-account local Enable local mode',
194
- ' /claude-account move-up <id> Move a fallback account up',
195
- ' /claude-account move-down <id> Move a fallback account down',
196
- ' /claude-account reset-backoff Clear main OAuth refresh and quota backoff',
197
- ' /claude-account enrollment-reset Retry a denied/blocked enrollment',
198
- ' /claude-account add-apikey <key> Add an API key fallback account',
199
- ' /claude-account add-oauth-start Start OAuth device flow',
200
- ' /claude-account add-oauth-finish <code> Complete OAuth flow',
201
- ].join('\n');
202
- export async function executeAccountCommand(input) {
203
- const action = parseAccountCommandAction(input.argumentsText);
204
- const accounts = input.storage.accounts;
205
- const mainId = 'main';
206
- if (action.type === 'status') {
207
- const list = input.statusProjection?.accounts ?? buildAccountList(input.storage);
208
- const detection = input.statusProjection?.claustrumDetection ??
209
- input.claustrum?.status ??
210
- 'unknown';
211
- const lines = [
212
- '## Claude Accounts',
213
- '',
214
- `- Custody mode: ${getClaustrumMode(input.storage)}`,
215
- `- Claustrum: ${detection}`,
216
- ...(input.statusProjection?.claustrumEnrollment
217
- ? formatEnrollmentStatus(input.statusProjection.claustrumEnrollment)
218
- : []),
219
- '',
220
- ];
221
- for (const a of list) {
222
- const pct = a.quotaPercent != null ? ` ${Math.round(a.quotaPercent)}%` : '';
223
- const status = !a.enabled ? ' (disabled)' : '';
224
- const tier = a.tierLabel ? ` · ${a.tierLabel}` : '';
225
- const projected = input.statusProjection?.accounts.find((account) => account.id === a.id);
226
- const storedAccount = input.storage.accounts.find((account) => account.id === a.id);
227
- const binding = storedAccount
228
- ? input.resolveCustodyBinding?.(storedAccount)
229
- : undefined;
230
- const custody = projected
231
- ? custodyStatusLabel(projected.custodyState)
232
- : a.id !== mainId &&
233
- storedAccount &&
234
- isOAuthAccountVaultOwned(input.storage, storedAccount, binding)
235
- ? custodyStatusLabel('on-cold')
236
- : 'local';
237
- lines.push(`- **${a.label}** [${a.role}]${tier}${status}${pct} · ${custody}`);
238
- }
239
- lines.push('', USAGE_TEXT);
240
- return { text: lines.join('\n') };
241
- }
242
- if (action.type === 'usage') {
243
- return { text: USAGE_TEXT };
244
- }
245
- if (action.type === 'claustrum-mode') {
246
- if (!input.transition) {
247
- return { text: 'Claustrum mode transition is unavailable.' };
248
- }
249
- return input.transition(action.mode);
250
- }
251
- if (action.type === 'enrollment-reset') {
252
- if (getClaustrumMode(input.storage) !== 'claustrum') {
253
- return {
254
- text: 'Claustrum enrollment is available only in Claustrum mode.',
255
- };
256
- }
257
- if (!input.resetEnrollment) {
258
- return { text: 'Claustrum enrollment reset is unavailable.' };
259
- }
260
- return input.resetEnrollment();
261
- }
262
- if (action.type === 'add-apikey') {
263
- return { text: 'add-apikey' };
264
- }
265
- if (action.type === 'add-oauth-start') {
266
- return { text: 'add-oauth-start' };
267
- }
268
- if (action.type === 'add-oauth-finish') {
269
- return { text: 'add-oauth-finish' };
270
- }
271
- if (action.type === 'reset-backoff') {
272
- return {
273
- text: 'Main OAuth refresh and quota backoff cleared.',
274
- updated: { id: 'main', action: 'reset-backoff' },
275
- };
276
- }
277
- const id = action.id;
278
- if (id === mainId) {
279
- return {
280
- text: `Cannot ${action.type} the main account (OpenCode managed).`,
281
- };
282
- }
283
- if (action.type === 'enable' || action.type === 'disable') {
284
- const target = accounts.find((a) => a.id === id);
285
- if (!target) {
286
- return { text: `Account "${id}" not found.` };
287
- }
288
- return {
289
- text: `Account "${target.label ?? id}" ${action.type}d.`,
290
- updated: {
291
- id,
292
- action: action.type,
293
- enabled: action.type === 'enable',
294
- },
295
- };
296
- }
297
- if (action.type === 'remove') {
298
- const target = accounts.find((a) => a.id === id);
299
- if (!target) {
300
- return { text: `Account "${id}" not found.` };
301
- }
302
- if (getClaustrumMode(input.storage) === 'claustrum' &&
303
- isOAuthAccount(target) &&
304
- target.claustrumScopedCredentialId) {
305
- return {
306
- text: `Account "${target.label ?? id}" is managed by Claustrum. Disable it to stop routing, or remove it from the vault.`,
307
- };
308
- }
309
- const binding = input.resolveCustodyBinding?.(target);
310
- if (getClaustrumMode(input.storage) === 'claustrum' &&
311
- isOAuthAccount(target) &&
312
- binding?.status === 'resolved' &&
313
- binding.source === 'manifest') {
314
- return {
315
- text: `Account "${target.label ?? id}" is bound by the Claustrum manifest. Disable it to stop routing, or remove its Claustrum binding before removing the routing row.`,
316
- };
317
- }
318
- return {
319
- text: `Account "${target.label ?? id}" removed.`,
320
- updated: { id, action: 'remove' },
321
- };
322
- }
323
- if (action.type === 'move-up') {
324
- const idx = accounts.findIndex((a) => a.id === id);
325
- if (idx < 0) {
326
- return { text: `Account "${id}" not found.` };
327
- }
328
- if (idx === 0) {
329
- return {
330
- text: `Account "${accounts[idx]?.label ?? id}" is already first.`,
331
- };
332
- }
333
- const previousOrder = accounts.map((a) => a.id);
334
- const newAccounts = [...accounts];
335
- [newAccounts[idx - 1], newAccounts[idx]] = [
336
- newAccounts[idx],
337
- newAccounts[idx - 1],
338
- ];
339
- const newOrder = newAccounts.map((a) => a.id);
340
- return {
341
- text: `Account "${accounts[idx]?.label ?? id}" moved up.`,
342
- updated: { id, action: 'reorder', previousOrder, newOrder },
343
- };
344
- }
345
- if (action.type === 'move-down') {
346
- const idx = accounts.findIndex((a) => a.id === id);
347
- if (idx < 0) {
348
- return { text: `Account "${id}" not found.` };
349
- }
350
- if (idx === accounts.length - 1) {
351
- return {
352
- text: `Account "${accounts[idx]?.label ?? id}" is already last.`,
353
- };
354
- }
355
- const previousOrder = accounts.map((a) => a.id);
356
- const newAccounts = [...accounts];
357
- [newAccounts[idx], newAccounts[idx + 1]] = [
358
- newAccounts[idx + 1],
359
- newAccounts[idx],
360
- ];
361
- const newOrder = newAccounts.map((a) => a.id);
362
- return {
363
- text: `Account "${accounts[idx]?.label ?? id}" moved down.`,
364
- updated: { id, action: 'reorder', previousOrder, newOrder },
365
- };
366
- }
367
- return { text: USAGE_TEXT };
368
- }
package/dist/constants.js DELETED
@@ -1,83 +0,0 @@
1
- export const CLIENT_ID = '9d1c250a-e61b-44d9-88ed-5944d1962f5e';
2
- export const AUTHORIZE_URLS = {
3
- console: 'https://platform.claude.com/oauth/authorize',
4
- max: 'https://claude.com/cai/oauth/authorize',
5
- };
6
- export const CODE_CALLBACK_URL = 'https://platform.claude.com/oauth/code/callback';
7
- export const TOKEN_URL = 'https://platform.claude.com/v1/oauth/token';
8
- export const CUSTODY_HANDLE_PATTERN = /^ckh_[A-Za-z0-9_-]{43}$/;
9
- export const AXIOS_USER_AGENT = 'axios/1.15.2';
10
- export const OAUTH_SCOPES = [
11
- 'org:create_api_key',
12
- 'user:profile',
13
- 'user:inference',
14
- 'user:sessions:claude_code',
15
- 'user:mcp_servers',
16
- 'user:file_upload',
17
- ];
18
- export const REFRESH_SCOPE = 'user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload';
19
- export const TOOL_PREFIX = 'mcp_';
20
- export const REQUIRED_BETAS = [
21
- 'oauth-2025-04-20',
22
- 'interleaved-thinking-2025-05-14',
23
- ];
24
- export const FAST_MODE_BETA = 'fast-mode-2026-02-01';
25
- export function mergeAnthropicBetas(existing, betas) {
26
- const incoming = (existing ?? '')
27
- .split(',')
28
- .map((beta) => beta.trim())
29
- .filter(Boolean);
30
- return [...new Set([...incoming, ...betas])].join(',');
31
- }
32
- export function isFastModeSupportedModel(model) {
33
- return (typeof model === 'string' &&
34
- (model.startsWith('claude-opus-4-6') ||
35
- model.startsWith('claude-opus-4-7') ||
36
- model.startsWith('claude-opus-4-8') ||
37
- model.startsWith('claude-opus-5')));
38
- }
39
- export const OPENCODE_IDENTITY_PREFIX = 'You are OpenCode';
40
- export const CLAUDE_CODE_IDENTITY = "You are Claude Code, Anthropic's official CLI for Claude.";
41
- export const PARALLEL_TOOL_CALLS_SYSTEM_PROMPT = [
42
- '<use_parallel_tool_calls>',
43
- 'For maximum efficiency, whenever you perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially. Prioritize calling independent tools in parallel whenever possible. For example, when reading 3 known files, run 3 tool calls in parallel to read all 3 files into context at the same time. When running multiple independent read-only commands like `ls` or `list_dir`, run all of those commands in parallel. Err on the side of maximizing parallel tool calls for independent work rather than running too many tools sequentially.',
44
- '',
45
- 'Do not parallelize tool calls when one call depends on the output of another call. If a tool call needs an ID, filename, search result, or any other value returned by a previous tool call, run the first call, wait for its result, then run the dependent call using the real returned value. Never invent placeholder IDs, guessed task IDs, or other guessed values for dependent tool calls just to place them in the same parallel block.',
46
- '</use_parallel_tool_calls>',
47
- ].join('\n');
48
- export const CCH_SALT = '59cf53e54c78';
49
- export const CCH_POSITIONS = [4, 7, 20];
50
- export const CLAUDE_CODE_VERSION = '2.1.280';
51
- export const CLAUDE_CODE_ENTRYPOINT = 'cli';
52
- export const CLAUDE_CODE_STAINLESS_PACKAGE_VERSION = '0.112.1';
53
- export const CLAUDE_CODE_STAINLESS_RUNTIME_VERSION = 'v26.3.0';
54
- export const USER_AGENT = `claude-cli/${CLAUDE_CODE_VERSION} (external, ${CLAUDE_CODE_ENTRYPOINT})`;
55
- export const CACHE_1H_MODES = ['explicit', 'automatic', 'hybrid'];
56
- export const DEFAULT_CACHE_1H_MODE = 'explicit';
57
- /**
58
- * Anchors that identify paragraphs to remove from the system prompt.
59
- * Any paragraph (text between blank lines) containing one of these
60
- * strings is removed entirely.
61
- *
62
- * This is resilient to upstream rewording — as long as the anchor
63
- * string (typically a URL) still appears somewhere in the paragraph,
64
- * the removal works regardless of how the surrounding text changes.
65
- */
66
- export const PARAGRAPH_REMOVAL_ANCHORS = [
67
- // Help/feedback block — references the OpenCode GitHub repo
68
- 'github.com/anomalyco/opencode',
69
- // OpenCode docs guidance — references the OpenCode docs URL
70
- 'opencode.ai/docs',
71
- ];
72
- /**
73
- * Inline text replacements applied after paragraph removal.
74
- * These handle cases where "OpenCode" appears inside a paragraph
75
- * we want to keep (so we can't remove the whole paragraph).
76
- */
77
- export const TEXT_REPLACEMENTS = [
78
- { match: 'if OpenCode honestly', replacement: 'if the assistant honestly' },
79
- {
80
- match: 'Here is some useful information about the environment you are running in:',
81
- replacement: 'Environment context you are running in:',
82
- },
83
- ];
@@ -1,102 +0,0 @@
1
- import { parseJsonRedacted } from './json.js';
2
- import { logger } from './logger.js';
3
- export const ANTHROPIC_CUSTOM_HEADERS_ENV = 'ANTHROPIC_CUSTOM_HEADERS';
4
- const CUSTOM_HEADER_CACHE_LIMIT = 64;
5
- const parsedHeadersByRawValue = new Map();
6
- const warnedMalformedRawValues = new Set();
7
- // Proxy-specific metadata is allowed, but custom configuration must never
8
- // replace route authentication, protocol negotiation, body framing, or
9
- // plugin-internal correlation headers after those guards have run.
10
- const PROTECTED_HEADERS = new Set([
11
- 'authorization',
12
- 'proxy-authorization',
13
- 'x-api-key',
14
- 'host',
15
- 'content-length',
16
- 'content-type',
17
- 'connection',
18
- 'transfer-encoding',
19
- 'upgrade',
20
- 'keep-alive',
21
- 'te',
22
- 'trailer',
23
- 'anthropic-version',
24
- 'anthropic-beta',
25
- 'x-parent-session-id',
26
- 'x-session-affinity',
27
- 'x-opencode-session',
28
- 'x-anthropic-effort-plan',
29
- 'x-cortexkit-billing-lineage',
30
- ]);
31
- function cacheParsed(raw, entries) {
32
- parsedHeadersByRawValue.delete(raw);
33
- parsedHeadersByRawValue.set(raw, entries);
34
- while (parsedHeadersByRawValue.size > CUSTOM_HEADER_CACHE_LIMIT) {
35
- const oldest = parsedHeadersByRawValue.keys().next().value;
36
- if (oldest === undefined)
37
- break;
38
- parsedHeadersByRawValue.delete(oldest);
39
- warnedMalformedRawValues.delete(oldest);
40
- }
41
- }
42
- function setCustomHeader(headers, name, value) {
43
- if (PROTECTED_HEADERS.has(name.trim().toLowerCase())) {
44
- throw new TypeError('protected header');
45
- }
46
- headers.set(name, value);
47
- }
48
- export function parseCustomHeaders(raw) {
49
- if (!raw?.trim())
50
- return new Headers();
51
- const cached = parsedHeadersByRawValue.get(raw);
52
- if (cached !== undefined || parsedHeadersByRawValue.has(raw)) {
53
- return new Headers(cached ?? []);
54
- }
55
- try {
56
- const headers = new Headers();
57
- const trimmed = raw.trim();
58
- if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {
59
- for (const entry of trimmed
60
- .split(/\r?\n|,\s*(?=[^,\s:]+:)/)
61
- .map((value) => value.trim())
62
- .filter(Boolean)) {
63
- const separator = entry.indexOf(':');
64
- if (separator <= 0) {
65
- throw new TypeError('invalid header entry');
66
- }
67
- setCustomHeader(headers, entry.slice(0, separator).trim(), entry.slice(separator + 1).trim());
68
- }
69
- }
70
- else {
71
- const parsed = parseJsonRedacted(trimmed);
72
- if (parsed == null ||
73
- typeof parsed !== 'object' ||
74
- Array.isArray(parsed)) {
75
- throw new TypeError('invalid header object');
76
- }
77
- for (const [key, value] of Object.entries(parsed)) {
78
- if (value == null)
79
- continue;
80
- setCustomHeader(headers, key, Array.isArray(value) ? value.map(String).join(', ') : String(value));
81
- }
82
- }
83
- const entries = [...headers.entries()];
84
- cacheParsed(raw, entries);
85
- return new Headers(entries);
86
- }
87
- catch {
88
- cacheParsed(raw, null);
89
- if (!warnedMalformedRawValues.has(raw)) {
90
- warnedMalformedRawValues.add(raw);
91
- logger.warn('custom-headers', 'ignoring malformed ANTHROPIC_CUSTOM_HEADERS', { reason: 'invalid or protected header configuration' });
92
- }
93
- return new Headers();
94
- }
95
- }
96
- export function applyCustomHeaders(headers, raw = process.env[ANTHROPIC_CUSTOM_HEADERS_ENV]) {
97
- const customHeaders = parseCustomHeaders(raw);
98
- customHeaders.forEach((value, key) => {
99
- headers.set(key, value);
100
- });
101
- return headers;
102
- }