@cortexkit/anthropic-auth-core 1.23.0 → 2.0.1
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 +18 -1
- package/dist/accounts.d.ts +4 -163
- package/dist/cachekeep.d.ts +9 -0
- package/dist/claude-code.d.ts +16 -0
- package/dist/claustrum-enrollment.d.ts +2 -0
- package/dist/claustrum.d.ts +0 -209
- package/dist/commands/account.d.ts +2 -3
- package/dist/index.d.ts +45 -4
- package/dist/index.js +27569 -38
- package/dist/internal-types/LICENSE +21 -0
- package/dist/internal-types/commands/builtins.d.ts +71 -0
- package/dist/internal-types/commands/index.d.ts +10 -0
- package/dist/internal-types/commands/menu.d.ts +61 -0
- package/dist/internal-types/commands/model.d.ts +238 -0
- package/dist/internal-types/commands/pi.d.ts +23 -0
- package/dist/internal-types/commands/seam.d.ts +72 -0
- package/dist/internal-types/fs/refresh-file-lock.d.ts +33 -0
- package/dist/internal-types/logger/capture-sink.d.ts +14 -0
- package/dist/internal-types/logger/engine.d.ts +98 -0
- package/dist/internal-types/logger/index.d.ts +6 -0
- package/dist/internal-types/logger/redact.d.ts +11 -0
- package/dist/internal-types/pi-slot/index.d.ts +3 -0
- package/dist/internal-types/pi-slot/slot.d.ts +51 -0
- package/dist/internal-types/quota/codec.d.ts +11 -0
- package/dist/internal-types/quota/format.d.ts +46 -0
- package/dist/internal-types/quota/index.d.ts +10 -0
- package/dist/internal-types/quota/map.d.ts +63 -0
- package/dist/internal-types/quota/merge.d.ts +48 -0
- package/dist/internal-types/quota/projection.d.ts +64 -0
- package/dist/internal-types/store/attribution.d.ts +28 -0
- package/dist/internal-types/store/errors.d.ts +55 -0
- package/dist/internal-types/store/hooks.d.ts +12 -0
- package/dist/internal-types/store/identity.d.ts +39 -0
- package/dist/internal-types/store/index.d.ts +21 -0
- package/dist/internal-types/store/mutate.d.ts +189 -0
- package/dist/internal-types/store/pool.d.ts +197 -0
- package/dist/internal-types/store/provider-state.d.ts +131 -0
- package/dist/internal-types/store/publication.d.ts +47 -0
- package/dist/internal-types/store/pull.d.ts +36 -0
- package/dist/internal-types/store/refresh-lock.d.ts +67 -0
- package/dist/internal-types/store/refresh.d.ts +72 -0
- package/dist/internal-types/store/rows.d.ts +313 -0
- package/dist/internal-types/store/runtime.d.ts +36 -0
- package/dist/internal-types/store/schema.d.ts +443 -0
- package/dist/internal-types/store/settings.d.ts +63 -0
- package/dist/internal-types/store/torn.d.ts +78 -0
- package/dist/migration-source.d.ts +33 -0
- package/dist/models.d.ts +41 -0
- package/dist/native-account-runtime.d.ts +121 -0
- package/dist/native-account-view.d.ts +126 -0
- package/dist/native-command-effects.d.ts +59 -0
- package/dist/native-credential-validation.d.ts +42 -0
- package/dist/native-custody-activation.d.ts +45 -0
- package/dist/native-custody.d.ts +114 -0
- package/dist/native-enrollment-authority.d.ts +2 -0
- package/dist/native-host-auth-read.d.ts +3 -0
- package/dist/native-host-auth-write.d.ts +51 -0
- package/dist/native-host-auth.d.ts +12 -0
- package/dist/native-local-credential-service.d.ts +76 -0
- package/dist/native-local-runtime-readers.d.ts +22 -0
- package/dist/native-lock-observer.d.ts +12 -0
- package/dist/native-menu-executor.d.ts +243 -0
- package/dist/native-menu-model.d.ts +142 -0
- package/dist/native-migration-proof.d.ts +28 -0
- package/dist/native-migration-source.d.ts +47 -0
- package/dist/native-migration.d.ts +66 -0
- package/dist/native-quota-codec.d.ts +32 -0
- package/dist/native-refresh-coordinator.d.ts +240 -0
- package/dist/native-roster-seed.d.ts +115 -0
- package/dist/native-runtime-registry.d.ts +19 -0
- package/dist/native-runtime.d.ts +204 -0
- package/dist/native-settings.d.ts +6 -0
- package/dist/native-transient-account.d.ts +38 -0
- package/dist/native-ui.d.ts +45 -0
- package/dist/native-usage-publication.d.ts +12 -0
- package/dist/native-vault-admission.d.ts +8 -0
- package/dist/native-vault-connection.d.ts +33 -0
- package/dist/native-vault-paths.d.ts +13 -0
- package/dist/native-vault-runtime.d.ts +102 -0
- package/dist/native-vault-seed.d.ts +16 -0
- package/dist/pool-authority.d.ts +159 -0
- package/dist/pool-binding.d.ts +32 -0
- package/dist/pool-paths.d.ts +21 -0
- package/dist/pool-store.d.ts +32 -0
- package/dist/provider-error.d.ts +139 -0
- package/dist/quota-manager.d.ts +18 -7
- package/dist/relay.d.ts +14 -1
- package/dist/request-history.d.ts +34 -0
- package/dist/routing.d.ts +1 -2
- package/dist/sse.d.ts +81 -0
- package/dist/sticky-routing.d.ts +28 -0
- package/package.json +10 -4
- package/dist/accounts.js +0 -3881
- package/dist/auth.js +0 -185
- package/dist/cache1h.js +0 -97
- package/dist/cachekeep-registry.js +0 -124
- package/dist/cachekeep.js +0 -604
- package/dist/cch.js +0 -172
- package/dist/claude-code.js +0 -403
- package/dist/claustrum-enrollment-registry.d.ts +0 -17
- package/dist/claustrum-enrollment-registry.js +0 -194
- package/dist/claustrum-enrollment.js +0 -485
- package/dist/claustrum-scoped-roster.d.ts +0 -23
- package/dist/claustrum-scoped-roster.js +0 -194
- package/dist/claustrum-scoped-runtime.d.ts +0 -28
- package/dist/claustrum-scoped-runtime.js +0 -230
- package/dist/claustrum-scoped.d.ts +0 -39
- package/dist/claustrum-scoped.js +0 -193
- package/dist/claustrum.js +0 -1471
- package/dist/commands/account.js +0 -368
- package/dist/constants.js +0 -83
- package/dist/custom-headers.js +0 -102
- package/dist/dump.js +0 -616
- package/dist/fast.js +0 -66
- package/dist/json.js +0 -10
- package/dist/killswitch.js +0 -132
- package/dist/logger.js +0 -288
- package/dist/logging.js +0 -59
- package/dist/mid-conversation-output-config.js +0 -89
- package/dist/model-remap.js +0 -72
- package/dist/models.js +0 -177
- package/dist/network-errors.js +0 -27
- package/dist/oauth-profile.js +0 -60
- package/dist/pkce.js +0 -17
- package/dist/prime.js +0 -841
- package/dist/provider.js +0 -0
- package/dist/quota-header-feed.js +0 -331
- package/dist/quota-headers.js +0 -121
- package/dist/quota-manager.js +0 -856
- package/dist/quotas.js +0 -141
- package/dist/relay.js +0 -1303
- package/dist/routing.js +0 -94
- package/dist/start.js +0 -29
- package/dist/sticky-routing.js +0 -541
- package/dist/thinking-binding.js +0 -54
- package/dist/token-fingerprint.js +0 -8
package/dist/commands/account.js
DELETED
|
@@ -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
|
-
];
|
package/dist/custom-headers.js
DELETED
|
@@ -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
|
-
}
|