@cortexkit/anthropic-auth-core 1.21.0 → 1.23.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.
- package/README.md +1 -1
- package/dist/accounts.d.ts +100 -3
- package/dist/accounts.js +1099 -169
- package/dist/auth.js +6 -10
- package/dist/cachekeep.d.ts +18 -1
- package/dist/cachekeep.js +108 -82
- package/dist/cch.d.ts +23 -9
- package/dist/cch.js +104 -21
- package/dist/claude-code.d.ts +8 -3
- package/dist/claude-code.js +24 -7
- package/dist/claustrum-enrollment-registry.d.ts +17 -0
- package/dist/claustrum-enrollment-registry.js +194 -0
- package/dist/claustrum-enrollment.d.ts +70 -0
- package/dist/claustrum-enrollment.js +485 -0
- package/dist/claustrum-scoped-roster.d.ts +23 -0
- package/dist/claustrum-scoped-roster.js +194 -0
- package/dist/claustrum-scoped-runtime.d.ts +28 -0
- package/dist/claustrum-scoped-runtime.js +230 -0
- package/dist/claustrum-scoped.d.ts +39 -0
- package/dist/claustrum-scoped.js +193 -0
- package/dist/claustrum.d.ts +252 -0
- package/dist/claustrum.js +1471 -0
- package/dist/commands/account.d.ts +43 -11
- package/dist/commands/account.js +147 -4
- package/dist/constants.d.ts +5 -5
- package/dist/constants.js +5 -5
- package/dist/custom-headers.d.ts +3 -0
- package/dist/custom-headers.js +102 -0
- package/dist/dump.js +2 -1
- package/dist/fast.js +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/json.d.ts +1 -0
- package/dist/json.js +10 -0
- package/dist/logger.js +3 -1
- package/dist/mid-conversation-output-config.d.ts +13 -0
- package/dist/mid-conversation-output-config.js +89 -0
- package/dist/model-remap.d.ts +27 -0
- package/dist/model-remap.js +72 -0
- package/dist/models.d.ts +46 -1
- package/dist/models.js +87 -8
- package/dist/network-errors.d.ts +1 -0
- package/dist/network-errors.js +27 -0
- package/dist/oauth-profile.d.ts +2 -1
- package/dist/oauth-profile.js +6 -0
- package/dist/prime.d.ts +11 -3
- package/dist/prime.js +25 -7
- package/dist/quota-header-feed.d.ts +32 -7
- package/dist/quota-header-feed.js +93 -10
- package/dist/quota-headers.js +59 -6
- package/dist/quota-manager.d.ts +20 -2
- package/dist/quota-manager.js +101 -24
- package/dist/relay.d.ts +8 -0
- package/dist/relay.js +72 -12
- package/dist/sticky-routing.d.ts +2 -0
- package/dist/sticky-routing.js +19 -1
- package/dist/thinking-binding.d.ts +7 -0
- package/dist/thinking-binding.js +54 -0
- package/package.json +4 -1
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import type { AccountStorage } from '../accounts.ts';
|
|
1
|
+
import type { AccountStorage, ClaustrumMode, FallbackAccount } from '../accounts.ts';
|
|
2
|
+
import type { ClaustrumDetection, CustodyHandleResolution } from '../claustrum.ts';
|
|
3
|
+
import type { ClaustrumEnrollmentStatus } from '../claustrum-enrollment.ts';
|
|
2
4
|
export declare const CLAUDE_ACCOUNT_COMMAND_NAME = "claude-account";
|
|
3
5
|
export type AccountCommandAction = {
|
|
4
6
|
type: 'status';
|
|
7
|
+
} | {
|
|
8
|
+
type: 'claustrum-mode';
|
|
9
|
+
mode: ClaustrumMode;
|
|
5
10
|
} | {
|
|
6
11
|
type: 'enable';
|
|
7
12
|
id: string;
|
|
@@ -17,6 +22,10 @@ export type AccountCommandAction = {
|
|
|
17
22
|
} | {
|
|
18
23
|
type: 'move-down';
|
|
19
24
|
id: string;
|
|
25
|
+
} | {
|
|
26
|
+
type: 'reset-backoff';
|
|
27
|
+
} | {
|
|
28
|
+
type: 'enrollment-reset';
|
|
20
29
|
} | {
|
|
21
30
|
type: 'add-apikey';
|
|
22
31
|
apiKey: string;
|
|
@@ -32,6 +41,17 @@ export type AccountCommandAction = {
|
|
|
32
41
|
} | {
|
|
33
42
|
type: 'usage';
|
|
34
43
|
};
|
|
44
|
+
export type AccountCommandResult = {
|
|
45
|
+
text: string;
|
|
46
|
+
updated?: {
|
|
47
|
+
id: string;
|
|
48
|
+
action: 'enable' | 'disable' | 'remove' | 'reorder' | 'reset-backoff';
|
|
49
|
+
enabled?: boolean;
|
|
50
|
+
previousOrder?: string[];
|
|
51
|
+
newOrder?: string[];
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export type ClaustrumModeTransition = (mode: ClaustrumMode) => Promise<AccountCommandResult>;
|
|
35
55
|
export declare function parseAccountCommandAction(argumentsText: string): AccountCommandAction;
|
|
36
56
|
export interface AccountListItem {
|
|
37
57
|
id: string;
|
|
@@ -41,17 +61,29 @@ export interface AccountListItem {
|
|
|
41
61
|
quotaPercent: number | null;
|
|
42
62
|
tierLabel?: string;
|
|
43
63
|
}
|
|
64
|
+
export type CustodyStatusState = 'na' | 'off' | 'on-vault-served' | 'on-vault-reauth' | 'on-cold' | 'unknown-identity' | 'on-identity-mismatch' | 'on-corrupt-binding';
|
|
65
|
+
export declare function custodyStatusLabel(state: CustodyStatusState): string;
|
|
66
|
+
export declare function formatEnrollmentStatus(status: ClaustrumEnrollmentStatus, scopedServing?: boolean): string[];
|
|
67
|
+
export type AccountCommandStatusProjection = {
|
|
68
|
+
claustrumDetection: string;
|
|
69
|
+
claustrumEnrollment?: ClaustrumEnrollmentStatus;
|
|
70
|
+
custodyMode?: 'local' | 'claustrum';
|
|
71
|
+
custodyModeKnown?: boolean;
|
|
72
|
+
accounts: Array<AccountListItem & {
|
|
73
|
+
claustrumGate: 'on' | 'off' | 'na';
|
|
74
|
+
vaultServed: boolean;
|
|
75
|
+
vaultReauth: boolean;
|
|
76
|
+
custodyState: CustodyStatusState;
|
|
77
|
+
}>;
|
|
78
|
+
};
|
|
44
79
|
export declare function buildAccountList(storage: AccountStorage): AccountListItem[];
|
|
45
80
|
export declare function executeAccountCommand(input: {
|
|
46
81
|
argumentsText: string;
|
|
47
82
|
storage: AccountStorage;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
newOrder?: string[];
|
|
56
|
-
};
|
|
57
|
-
};
|
|
83
|
+
claustrum?: ClaustrumDetection;
|
|
84
|
+
statusProjection?: AccountCommandStatusProjection;
|
|
85
|
+
resolveCustodyBinding?: (account: FallbackAccount) => CustodyHandleResolution;
|
|
86
|
+
path?: string;
|
|
87
|
+
transition?: ClaustrumModeTransition;
|
|
88
|
+
resetEnrollment?: () => Promise<AccountCommandResult>;
|
|
89
|
+
}): Promise<AccountCommandResult>;
|
package/dist/commands/account.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getClaustrumMode, isOAuthAccount, isOAuthAccountVaultOwned, } from '../accounts.js';
|
|
1
2
|
import { formatOAuthAccountTier } from '../oauth-profile.js';
|
|
2
3
|
export const CLAUDE_ACCOUNT_COMMAND_NAME = 'claude-account';
|
|
3
4
|
export function parseAccountCommandAction(argumentsText) {
|
|
@@ -16,6 +17,16 @@ export function parseAccountCommandAction(argumentsText) {
|
|
|
16
17
|
return { type: 'move-up', id: rest };
|
|
17
18
|
if (action === 'move-down' && rest)
|
|
18
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
|
+
}
|
|
19
30
|
if (action === 'add-apikey' && rest) {
|
|
20
31
|
let remaining = rest;
|
|
21
32
|
let baseURL;
|
|
@@ -81,6 +92,71 @@ export function parseAccountCommandAction(argumentsText) {
|
|
|
81
92
|
}
|
|
82
93
|
return { type: 'usage' };
|
|
83
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
|
+
}
|
|
84
160
|
export function buildAccountList(storage) {
|
|
85
161
|
const list = [];
|
|
86
162
|
const fiveHour = storage.quota?.mainQuota?.five_hour;
|
|
@@ -113,24 +189,52 @@ const USAGE_TEXT = [
|
|
|
113
189
|
' /claude-account enable <id> Enable a fallback account',
|
|
114
190
|
' /claude-account disable <id> Disable a fallback account',
|
|
115
191
|
' /claude-account remove <id> Remove a fallback account',
|
|
192
|
+
' /claude-account claustrum Enable Claustrum mode',
|
|
193
|
+
' /claude-account local Enable local mode',
|
|
116
194
|
' /claude-account move-up <id> Move a fallback account up',
|
|
117
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',
|
|
118
198
|
' /claude-account add-apikey <key> Add an API key fallback account',
|
|
119
199
|
' /claude-account add-oauth-start Start OAuth device flow',
|
|
120
200
|
' /claude-account add-oauth-finish <code> Complete OAuth flow',
|
|
121
201
|
].join('\n');
|
|
122
|
-
export function executeAccountCommand(input) {
|
|
202
|
+
export async function executeAccountCommand(input) {
|
|
123
203
|
const action = parseAccountCommandAction(input.argumentsText);
|
|
124
204
|
const accounts = input.storage.accounts;
|
|
125
205
|
const mainId = 'main';
|
|
126
206
|
if (action.type === 'status') {
|
|
127
|
-
const list = buildAccountList(input.storage);
|
|
128
|
-
const
|
|
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
|
+
];
|
|
129
221
|
for (const a of list) {
|
|
130
222
|
const pct = a.quotaPercent != null ? ` ${Math.round(a.quotaPercent)}%` : '';
|
|
131
223
|
const status = !a.enabled ? ' (disabled)' : '';
|
|
132
224
|
const tier = a.tierLabel ? ` · ${a.tierLabel}` : '';
|
|
133
|
-
|
|
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}`);
|
|
134
238
|
}
|
|
135
239
|
lines.push('', USAGE_TEXT);
|
|
136
240
|
return { text: lines.join('\n') };
|
|
@@ -138,6 +242,23 @@ export function executeAccountCommand(input) {
|
|
|
138
242
|
if (action.type === 'usage') {
|
|
139
243
|
return { text: USAGE_TEXT };
|
|
140
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
|
+
}
|
|
141
262
|
if (action.type === 'add-apikey') {
|
|
142
263
|
return { text: 'add-apikey' };
|
|
143
264
|
}
|
|
@@ -147,6 +268,12 @@ export function executeAccountCommand(input) {
|
|
|
147
268
|
if (action.type === 'add-oauth-finish') {
|
|
148
269
|
return { text: 'add-oauth-finish' };
|
|
149
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
|
+
}
|
|
150
277
|
const id = action.id;
|
|
151
278
|
if (id === mainId) {
|
|
152
279
|
return {
|
|
@@ -172,6 +299,22 @@ export function executeAccountCommand(input) {
|
|
|
172
299
|
if (!target) {
|
|
173
300
|
return { text: `Account "${id}" not found.` };
|
|
174
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
|
+
}
|
|
175
318
|
return {
|
|
176
319
|
text: `Account "${target.label ?? id}" removed.`,
|
|
177
320
|
updated: { id, action: 'remove' },
|
package/dist/constants.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare const AUTHORIZE_URLS: {
|
|
|
5
5
|
};
|
|
6
6
|
export declare const CODE_CALLBACK_URL = "https://platform.claude.com/oauth/code/callback";
|
|
7
7
|
export declare const TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
|
|
8
|
+
export declare const CUSTODY_HANDLE_PATTERN: RegExp;
|
|
8
9
|
export declare const AXIOS_USER_AGENT = "axios/1.15.2";
|
|
9
10
|
export declare const OAUTH_SCOPES: string[];
|
|
10
11
|
export declare const REFRESH_SCOPE = "user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload";
|
|
@@ -18,12 +19,11 @@ export declare const CLAUDE_CODE_IDENTITY = "You are Claude Code, Anthropic's of
|
|
|
18
19
|
export declare const PARALLEL_TOOL_CALLS_SYSTEM_PROMPT: string;
|
|
19
20
|
export declare const CCH_SALT = "59cf53e54c78";
|
|
20
21
|
export declare const CCH_POSITIONS: number[];
|
|
21
|
-
export declare const CLAUDE_CODE_VERSION = "2.1.
|
|
22
|
-
export declare const CLAUDE_CODE_BUILD_HASH = "3bf";
|
|
22
|
+
export declare const CLAUDE_CODE_VERSION = "2.1.280";
|
|
23
23
|
export declare const CLAUDE_CODE_ENTRYPOINT = "cli";
|
|
24
|
-
export declare const CLAUDE_CODE_STAINLESS_PACKAGE_VERSION = "0.
|
|
25
|
-
export declare const CLAUDE_CODE_STAINLESS_RUNTIME_VERSION = "
|
|
26
|
-
export declare const USER_AGENT = "claude-cli/2.1.
|
|
24
|
+
export declare const CLAUDE_CODE_STAINLESS_PACKAGE_VERSION = "0.112.1";
|
|
25
|
+
export declare const CLAUDE_CODE_STAINLESS_RUNTIME_VERSION = "v26.3.0";
|
|
26
|
+
export declare const USER_AGENT = "claude-cli/2.1.280 (external, cli)";
|
|
27
27
|
export declare const CACHE_1H_MODES: readonly ['explicit', 'automatic', 'hybrid'];
|
|
28
28
|
export type Cache1hMode = (typeof CACHE_1H_MODES)[number];
|
|
29
29
|
export declare const DEFAULT_CACHE_1H_MODE: Cache1hMode;
|
package/dist/constants.js
CHANGED
|
@@ -5,6 +5,7 @@ export const AUTHORIZE_URLS = {
|
|
|
5
5
|
};
|
|
6
6
|
export const CODE_CALLBACK_URL = 'https://platform.claude.com/oauth/code/callback';
|
|
7
7
|
export const TOKEN_URL = 'https://platform.claude.com/v1/oauth/token';
|
|
8
|
+
export const CUSTODY_HANDLE_PATTERN = /^ckh_[A-Za-z0-9_-]{43}$/;
|
|
8
9
|
export const AXIOS_USER_AGENT = 'axios/1.15.2';
|
|
9
10
|
export const OAUTH_SCOPES = [
|
|
10
11
|
'org:create_api_key',
|
|
@@ -46,12 +47,11 @@ export const PARALLEL_TOOL_CALLS_SYSTEM_PROMPT = [
|
|
|
46
47
|
].join('\n');
|
|
47
48
|
export const CCH_SALT = '59cf53e54c78';
|
|
48
49
|
export const CCH_POSITIONS = [4, 7, 20];
|
|
49
|
-
export const CLAUDE_CODE_VERSION = '2.1.
|
|
50
|
-
export const CLAUDE_CODE_BUILD_HASH = '3bf';
|
|
50
|
+
export const CLAUDE_CODE_VERSION = '2.1.280';
|
|
51
51
|
export const CLAUDE_CODE_ENTRYPOINT = 'cli';
|
|
52
|
-
export const CLAUDE_CODE_STAINLESS_PACKAGE_VERSION = '0.
|
|
53
|
-
export const CLAUDE_CODE_STAINLESS_RUNTIME_VERSION = '
|
|
54
|
-
export const USER_AGENT =
|
|
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
55
|
export const CACHE_1H_MODES = ['explicit', 'automatic', 'hybrid'];
|
|
56
56
|
export const DEFAULT_CACHE_1H_MODE = 'explicit';
|
|
57
57
|
/**
|
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
}
|
package/dist/dump.js
CHANGED
|
@@ -3,6 +3,7 @@ import { lstat, mkdir, readdir, readFile, rename, unlink, writeFile, } from 'nod
|
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
5
|
import { extractBillingHeaderCCH } from './cch.js';
|
|
6
|
+
import { parseJsonRedacted } from './json.js';
|
|
6
7
|
import { isSecretKey, logger, relayLog } from './logger.js';
|
|
7
8
|
export const CLAUDE_DUMP_COMMAND_NAME = 'claude-dump';
|
|
8
9
|
const DUMP_STATUS_TITLE = '## Claude Dump Status';
|
|
@@ -425,7 +426,7 @@ function diffSummary(previousBodyText, bodyText) {
|
|
|
425
426
|
}
|
|
426
427
|
function parseBody(bodyText) {
|
|
427
428
|
try {
|
|
428
|
-
const parsed =
|
|
429
|
+
const parsed = parseJsonRedacted(bodyText);
|
|
429
430
|
return parsed != null &&
|
|
430
431
|
typeof parsed === 'object' &&
|
|
431
432
|
!Array.isArray(parsed)
|
package/dist/fast.js
CHANGED
|
@@ -32,7 +32,7 @@ export function buildFastModeStatusSummary(input) {
|
|
|
32
32
|
`- Enabled: ${enabled ? 'enabled' : 'disabled'}`,
|
|
33
33
|
'- Persisted: ~/.config/opencode/anthropic-auth.json',
|
|
34
34
|
'- Scope: adds Anthropic fast mode to supported Opus requests',
|
|
35
|
-
'- Supported models: claude-opus-4-6, claude-opus-4-7, claude-opus-4-8, and claude-opus-5',
|
|
35
|
+
'- Supported models: claude-opus-4-6, claude-opus-4-7, claude-opus-4-8, claude-opus-5, and claude-opus-5-5',
|
|
36
36
|
'- Request changes: adds `speed: "fast"` and the `fast-mode-2026-02-01` beta header',
|
|
37
37
|
'- Note: fast and standard speeds do not share prompt-cache prefixes',
|
|
38
38
|
].join('\n');
|
package/dist/index.d.ts
CHANGED
|
@@ -5,13 +5,23 @@ export * from './cachekeep.ts';
|
|
|
5
5
|
export * from './cachekeep-registry.ts';
|
|
6
6
|
export * from './cch.ts';
|
|
7
7
|
export * from './claude-code.ts';
|
|
8
|
+
export * from './claustrum.ts';
|
|
9
|
+
export * from './claustrum-enrollment.ts';
|
|
10
|
+
export * from './claustrum-enrollment-registry.ts';
|
|
11
|
+
export * from './claustrum-scoped.ts';
|
|
12
|
+
export * from './claustrum-scoped-roster.ts';
|
|
13
|
+
export * from './claustrum-scoped-runtime.ts';
|
|
8
14
|
export * from './commands/account.ts';
|
|
9
15
|
export * from './constants.ts';
|
|
16
|
+
export * from './custom-headers.ts';
|
|
10
17
|
export * from './dump.ts';
|
|
11
18
|
export * from './fast.ts';
|
|
19
|
+
export * from './json.ts';
|
|
12
20
|
export * from './killswitch.ts';
|
|
13
21
|
export * from './logger.ts';
|
|
14
22
|
export * from './logging.ts';
|
|
23
|
+
export * from './mid-conversation-output-config.ts';
|
|
24
|
+
export * from './model-remap.ts';
|
|
15
25
|
export * from './models.ts';
|
|
16
26
|
export * from './oauth-profile.ts';
|
|
17
27
|
export * from './pkce.ts';
|
|
@@ -25,3 +35,4 @@ export * from './relay.ts';
|
|
|
25
35
|
export * from './routing.ts';
|
|
26
36
|
export * from './start.ts';
|
|
27
37
|
export * from './sticky-routing.ts';
|
|
38
|
+
export * from './thinking-binding.ts';
|
package/dist/index.js
CHANGED
|
@@ -5,13 +5,23 @@ export * from './cachekeep.js';
|
|
|
5
5
|
export * from './cachekeep-registry.js';
|
|
6
6
|
export * from './cch.js';
|
|
7
7
|
export * from './claude-code.js';
|
|
8
|
+
export * from './claustrum.js';
|
|
9
|
+
export * from './claustrum-enrollment.js';
|
|
10
|
+
export * from './claustrum-enrollment-registry.js';
|
|
11
|
+
export * from './claustrum-scoped.js';
|
|
12
|
+
export * from './claustrum-scoped-roster.js';
|
|
13
|
+
export * from './claustrum-scoped-runtime.js';
|
|
8
14
|
export * from './commands/account.js';
|
|
9
15
|
export * from './constants.js';
|
|
16
|
+
export * from './custom-headers.js';
|
|
10
17
|
export * from './dump.js';
|
|
11
18
|
export * from './fast.js';
|
|
19
|
+
export * from './json.js';
|
|
12
20
|
export * from './killswitch.js';
|
|
13
21
|
export * from './logger.js';
|
|
14
22
|
export * from './logging.js';
|
|
23
|
+
export * from './mid-conversation-output-config.js';
|
|
24
|
+
export * from './model-remap.js';
|
|
15
25
|
export * from './models.js';
|
|
16
26
|
export * from './oauth-profile.js';
|
|
17
27
|
export * from './pkce.js';
|
|
@@ -25,3 +35,4 @@ export * from './relay.js';
|
|
|
25
35
|
export * from './routing.js';
|
|
26
36
|
export * from './start.js';
|
|
27
37
|
export * from './sticky-routing.js';
|
|
38
|
+
export * from './thinking-binding.js';
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function parseJsonRedacted(text: string): unknown;
|
package/dist/json.js
ADDED
package/dist/logger.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as os from 'node:os';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
+
import { CUSTODY_HANDLE_PATTERN } from './constants.js';
|
|
4
5
|
const LEVEL_ORDER = {
|
|
5
6
|
error: 0,
|
|
6
7
|
warn: 1,
|
|
@@ -75,7 +76,7 @@ function rotateLogFile() {
|
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
// -- Redaction ------------------------------------------------------------
|
|
78
|
-
export const SECRET_KEY_EXACT = /^(authorization|x-api-key|cookie|set-cookie|refresh|access|token)$/i;
|
|
79
|
+
export const SECRET_KEY_EXACT = /^(authorization|x-api-key|cookie|set-cookie|refresh|access|token|handle)$/i;
|
|
79
80
|
export function isSecretKey(key) {
|
|
80
81
|
if (SECRET_KEY_EXACT.test(key))
|
|
81
82
|
return true;
|
|
@@ -92,6 +93,7 @@ const REDACT_VALUE_PATTERNS = [
|
|
|
92
93
|
/Bearer\s+\S+/,
|
|
93
94
|
/sk-[A-Za-z0-9-]+/,
|
|
94
95
|
/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/,
|
|
96
|
+
CUSTODY_HANDLE_PATTERN,
|
|
95
97
|
];
|
|
96
98
|
function isRedactableValue(value) {
|
|
97
99
|
if (typeof value !== 'string')
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const MID_CONVERSATION_OUTPUT_CONFIG_BETA = "mid-conversation-output-config-2026-07-01";
|
|
2
|
+
export type AdaptiveEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
3
|
+
export type MidConversationEffortTransition = {
|
|
4
|
+
/** Number of assistant messages preceding the user boundary for this effort. */
|
|
5
|
+
afterAssistantMessages: number;
|
|
6
|
+
effort: AdaptiveEffort;
|
|
7
|
+
};
|
|
8
|
+
export declare function normalizeAdaptiveEffort(value: unknown): AdaptiveEffort | undefined;
|
|
9
|
+
export declare function usesMidConversationOutputConfig(body: Record<string, unknown>): boolean;
|
|
10
|
+
export declare function applyMidConversationOutputConfig(body: Record<string, unknown>, transitions: readonly MidConversationEffortTransition[]): {
|
|
11
|
+
applied: boolean;
|
|
12
|
+
inserted: number;
|
|
13
|
+
};
|