@cortexkit/pi-anthropic-auth 1.7.0 → 1.8.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 +3 -1
- package/dist/convert.d.ts +3 -0
- package/dist/convert.js +19 -14
- package/dist/index.js +21 -4
- package/dist/stream.d.ts +4 -0
- package/dist/stream.js +128 -35
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Pi package for CortexKit Anthropic OAuth support. It overrides Pi's built-in `anthropic` provider with a CortexKit provider extension backed by the shared `@cortexkit/anthropic-auth-core` package.
|
|
4
4
|
|
|
5
|
+
The Pi provider catalog includes Claude Fable 5 (`claude-fable-5`), limited-access Claude Mythos 5 (`claude-mythos-5`), Claude Opus 4.8, Claude Opus 4.5, and Claude Sonnet 4.5. Fable/Mythos reasoning uses Anthropic adaptive thinking with `output_config.effort`; the package does not send rejected manual `thinking.budget_tokens` for those models.
|
|
6
|
+
|
|
5
7
|
This package is part of the CortexKit Anthropic Auth monorepo, which supports both OpenCode (`@cortexkit/opencode-anthropic-auth`) and Pi (`@cortexkit/pi-anthropic-auth`) through the same shared core logic.
|
|
6
8
|
|
|
7
9
|
## Install
|
|
@@ -71,7 +73,7 @@ The sidecar uses the same JSON shape as the OpenCode package, including `routing
|
|
|
71
73
|
/claude-quota
|
|
72
74
|
```
|
|
73
75
|
|
|
74
|
-
`/claude-quota` reports sidecar fallback
|
|
76
|
+
`/claude-quota` reports sidecar OAuth fallback quota state from `~/.pi/agent/anthropic-auth.json`. `/claude-routing fallback-first` prefers usable OAuth fallback accounts before the main account; `/claude-routing main-first` restores the default. API-key routes use the same sidecar shape as OpenCode and are sent directly to their configured Anthropic-compatible base URL, such as Kie's `https://api.kie.ai/claude`, but Pi only uses them after the main OAuth model response reports HTTP 429 or a streaming rate-limit error and a live quota check confirms 0% remaining. `/claude-cachekeep HH-HH` keeps recently used hybrid-mode session caches warm during the configured local time window by sending `max_tokens: 0` pre-warm requests about five minutes before the 1-hour TTL expires. `/claude-fast on` adds Anthropic `speed: "fast"` plus the `fast-mode-2026-02-01` beta header for supported Opus models (`claude-opus-4-6`, `claude-opus-4-7`, and `claude-opus-4-8`).
|
|
75
77
|
|
|
76
78
|
## Relay
|
|
77
79
|
|
package/dist/convert.d.ts
CHANGED
package/dist/convert.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyClaudeCodeMetadata, buildBillingHeaderValue, CLAUDE_CODE_ENTRYPOINT, CLAUDE_CODE_IDENTITY, isFastModeSupportedModel, orderClaudeCodeBody, signRequestBody, } from '@cortexkit/anthropic-auth-core';
|
|
1
|
+
import { applyClaudeCodeMetadata, buildBillingHeaderValue, CLAUDE_CODE_ENTRYPOINT, CLAUDE_CODE_IDENTITY, isClaudeFableOrMythos5Model, isFastModeSupportedModel, orderClaudeCodeBody, signRequestBody, } from '@cortexkit/anthropic-auth-core';
|
|
2
2
|
const CLAUDE_CODE_TOOLS = new Map([
|
|
3
3
|
'Read',
|
|
4
4
|
'Write',
|
|
@@ -264,19 +264,24 @@ export async function buildAnthropicRequest(modelId, context, options, cache, fa
|
|
|
264
264
|
body.speed = 'fast';
|
|
265
265
|
}
|
|
266
266
|
if (options?.reasoning) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
267
|
+
if (isClaudeFableOrMythos5Model(modelId)) {
|
|
268
|
+
body.output_config = { effort: options.reasoning };
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
const budgets = {
|
|
272
|
+
minimal: 1024,
|
|
273
|
+
low: 4096,
|
|
274
|
+
medium: 10_240,
|
|
275
|
+
high: 20_480,
|
|
276
|
+
xhigh: 32_000,
|
|
277
|
+
};
|
|
278
|
+
body.thinking = {
|
|
279
|
+
type: 'enabled',
|
|
280
|
+
budget_tokens: options.thinkingBudgets?.[options.reasoning] ??
|
|
281
|
+
budgets[options.reasoning] ??
|
|
282
|
+
10_240,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
280
285
|
}
|
|
281
286
|
addEphemeralCacheControl(body);
|
|
282
287
|
applyCacheMode(body, cache.enabled, cache.mode);
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { authorize, exchange, refreshClaudeOAuthToken, } from '@cortexkit/anthropic-auth-core';
|
|
1
|
+
import { authorize, CLAUDE_FABLE_MYTHOS_5_CONTEXT_WINDOW, CLAUDE_FABLE_MYTHOS_5_MAX_OUTPUT_TOKENS, CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS, CLAUDE_FABLE_MYTHOS_5_PRICING, exchange, refreshClaudeOAuthToken, } from '@cortexkit/anthropic-auth-core';
|
|
2
2
|
import { registerCommands } from "./commands.js";
|
|
3
3
|
import { streamCortexKitAnthropic } from "./stream.js";
|
|
4
4
|
async function loginAnthropic(callbacks) {
|
|
@@ -17,6 +17,9 @@ async function loginAnthropic(callbacks) {
|
|
|
17
17
|
expires: result.expires,
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
+
function textImageInput() {
|
|
21
|
+
return ['text', 'image'];
|
|
22
|
+
}
|
|
20
23
|
async function refreshAnthropicToken(credentials) {
|
|
21
24
|
const refreshed = await refreshClaudeOAuthToken({
|
|
22
25
|
refreshToken: credentials.refresh,
|
|
@@ -34,11 +37,25 @@ export default function cortexKitPiAnthropicAuth(pi) {
|
|
|
34
37
|
baseUrl: 'https://api.anthropic.com',
|
|
35
38
|
api: 'cortexkit-anthropic-messages',
|
|
36
39
|
models: [
|
|
40
|
+
...Object.values(CLAUDE_FABLE_MYTHOS_5_MODEL_SPECS).map((model) => ({
|
|
41
|
+
id: model.id,
|
|
42
|
+
name: model.name,
|
|
43
|
+
reasoning: true,
|
|
44
|
+
input: textImageInput(),
|
|
45
|
+
cost: {
|
|
46
|
+
input: CLAUDE_FABLE_MYTHOS_5_PRICING.input,
|
|
47
|
+
output: CLAUDE_FABLE_MYTHOS_5_PRICING.output,
|
|
48
|
+
cacheRead: CLAUDE_FABLE_MYTHOS_5_PRICING.cacheRead,
|
|
49
|
+
cacheWrite: CLAUDE_FABLE_MYTHOS_5_PRICING.cacheWrite5m,
|
|
50
|
+
},
|
|
51
|
+
contextWindow: CLAUDE_FABLE_MYTHOS_5_CONTEXT_WINDOW,
|
|
52
|
+
maxTokens: CLAUDE_FABLE_MYTHOS_5_MAX_OUTPUT_TOKENS,
|
|
53
|
+
})),
|
|
37
54
|
{
|
|
38
55
|
id: 'claude-opus-4-8',
|
|
39
56
|
name: 'Claude Opus 4.8',
|
|
40
57
|
reasoning: true,
|
|
41
|
-
input:
|
|
58
|
+
input: textImageInput(),
|
|
42
59
|
cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
|
|
43
60
|
contextWindow: 1_000_000,
|
|
44
61
|
maxTokens: 128_000,
|
|
@@ -47,7 +64,7 @@ export default function cortexKitPiAnthropicAuth(pi) {
|
|
|
47
64
|
id: 'claude-opus-4-5',
|
|
48
65
|
name: 'Claude Opus 4.5',
|
|
49
66
|
reasoning: true,
|
|
50
|
-
input:
|
|
67
|
+
input: textImageInput(),
|
|
51
68
|
cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
|
|
52
69
|
contextWindow: 200_000,
|
|
53
70
|
maxTokens: 64_000,
|
|
@@ -56,7 +73,7 @@ export default function cortexKitPiAnthropicAuth(pi) {
|
|
|
56
73
|
id: 'claude-sonnet-4-5',
|
|
57
74
|
name: 'Claude Sonnet 4.5',
|
|
58
75
|
reasoning: true,
|
|
59
|
-
input:
|
|
76
|
+
input: textImageInput(),
|
|
60
77
|
cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
61
78
|
contextWindow: 200_000,
|
|
62
79
|
maxTokens: 64_000,
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
+
import { type ApiKeyAccount } from '@cortexkit/anthropic-auth-core';
|
|
1
2
|
import { type Api, type AssistantMessageEventStream, type Context, type Model, type SimpleStreamOptions } from '@earendil-works/pi-ai';
|
|
3
|
+
export declare function buildExplicitBaseMessagesUrl(baseURL: string): URL;
|
|
4
|
+
export declare function configureApiRouteHeaders(account: ApiKeyAccount, fastMode: boolean): Headers;
|
|
5
|
+
export declare function primaryResponseAllowsApiFallback(preflight: Response | string): boolean;
|
|
2
6
|
export declare function streamCortexKitAnthropic(model: Model<Api>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;
|
package/dist/stream.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyClaudeCodeHeaders, CACHE_KEEP_EXTENDED_TTL_BETA, CacheKeepManager, FAST_MODE_BETA, FallbackAccountManager, getCache1hPersistentMode, getRelayConfig, getRoutingMode, isCache1hPersistentlyEnabled, isCacheKeepHybridActive, isFastModePersistentlyEnabled, loadAccounts, mergeAnthropicBetas, resolveClaudeCodeIdentity, sendViaRelay, shouldFallbackStatus, } from '@cortexkit/anthropic-auth-core';
|
|
1
|
+
import { applyClaudeCodeHeaders, CACHE_KEEP_EXTENDED_TTL_BETA, CacheKeepManager, FAST_MODE_BETA, FallbackAccountManager, getCache1hPersistentMode, getRelayConfig, getRoutingMode, isApiKeyAccount, isCache1hPersistentlyEnabled, isCacheKeepHybridActive, isFastModePersistentlyEnabled, isOAuthAccount, isValidApiBaseURL, loadAccounts, mergeAnthropicBetas, QuotaManager, resolveClaudeCodeIdentity, sendViaRelay, shouldFallbackStatus, } from '@cortexkit/anthropic-auth-core';
|
|
2
2
|
import { calculateCost, createAssistantMessageEventStream, } from '@earendil-works/pi-ai';
|
|
3
3
|
import { buildAnthropicRequest, fromClaudeCodeToolName } from "./convert.js";
|
|
4
4
|
import { getPiAccountStoragePath } from "./paths.js";
|
|
@@ -77,49 +77,89 @@ function updateUsage(model, output, usage) {
|
|
|
77
77
|
output.usage.cacheWrite;
|
|
78
78
|
calculateCost(model, output.usage);
|
|
79
79
|
}
|
|
80
|
+
export function buildExplicitBaseMessagesUrl(baseURL) {
|
|
81
|
+
const url = new URL(baseURL);
|
|
82
|
+
url.pathname = `${url.pathname.replace(/\/$/, '')}/v1/messages`;
|
|
83
|
+
url.searchParams.set('beta', 'true');
|
|
84
|
+
return url;
|
|
85
|
+
}
|
|
86
|
+
export function configureApiRouteHeaders(account, fastMode) {
|
|
87
|
+
const headers = new Headers();
|
|
88
|
+
headers.set('accept', 'application/json');
|
|
89
|
+
headers.set('content-type', 'application/json');
|
|
90
|
+
headers.set('anthropic-version', '2023-06-01');
|
|
91
|
+
headers.set('anthropic-beta', mergeAnthropicBetas(null, []));
|
|
92
|
+
if (account.authHeader === 'x-api-key') {
|
|
93
|
+
headers.set('x-api-key', account.apiKey ?? '');
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
headers.set('authorization', `Bearer ${account.apiKey ?? ''}`);
|
|
97
|
+
}
|
|
98
|
+
if (fastMode) {
|
|
99
|
+
headers.set('anthropic-beta', mergeAnthropicBetas(headers.get('anthropic-beta'), [FAST_MODE_BETA]));
|
|
100
|
+
}
|
|
101
|
+
return headers;
|
|
102
|
+
}
|
|
80
103
|
async function* parseSse(response) {
|
|
81
104
|
if (!response.body)
|
|
82
105
|
return;
|
|
83
106
|
const reader = response.body.getReader();
|
|
84
107
|
const decoder = new TextDecoder();
|
|
85
108
|
let buffer = '';
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
buffer
|
|
95
|
-
boundary = buffer.indexOf('\n\n');
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
109
|
+
let completed = false;
|
|
110
|
+
try {
|
|
111
|
+
while (true) {
|
|
112
|
+
const { done, value } = await reader.read();
|
|
113
|
+
if (done) {
|
|
114
|
+
completed = true;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
buffer += decoder.decode(value, { stream: true });
|
|
118
|
+
let boundary = buffer.indexOf('\n\n');
|
|
119
|
+
while (boundary !== -1) {
|
|
120
|
+
const frame = buffer.slice(0, boundary);
|
|
121
|
+
buffer = buffer.slice(boundary + 2);
|
|
122
|
+
boundary = buffer.indexOf('\n\n');
|
|
123
|
+
for (const line of frame.split('\n')) {
|
|
124
|
+
if (!line.startsWith('data:'))
|
|
125
|
+
continue;
|
|
126
|
+
const data = line.slice(5).trim();
|
|
127
|
+
if (!data || data === '[DONE]')
|
|
128
|
+
continue;
|
|
129
|
+
yield JSON.parse(data);
|
|
130
|
+
}
|
|
103
131
|
}
|
|
104
132
|
}
|
|
105
133
|
}
|
|
134
|
+
finally {
|
|
135
|
+
if (!completed)
|
|
136
|
+
await reader.cancel().catch(() => { });
|
|
137
|
+
reader.releaseLock();
|
|
138
|
+
}
|
|
106
139
|
}
|
|
107
140
|
async function sendAnthropicRequest(options) {
|
|
108
141
|
const storage = await loadAccounts(options.storagePath);
|
|
109
|
-
const identity =
|
|
142
|
+
const identity = options.accessToken
|
|
143
|
+
? await resolveClaudeCodeIdentity(options.accessToken, options.model.id)
|
|
144
|
+
: undefined;
|
|
110
145
|
const { body, bodyText } = await buildAnthropicRequest(options.model.id, options.context, options.streamOptions, {
|
|
111
146
|
enabled: isCache1hPersistentlyEnabled(storage),
|
|
112
147
|
mode: getCache1hPersistentMode(storage),
|
|
113
148
|
}, isFastModePersistentlyEnabled(storage), identity);
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
149
|
+
const fastMode = body.speed === 'fast';
|
|
150
|
+
const headers = options.apiAccount
|
|
151
|
+
? configureApiRouteHeaders(options.apiAccount, fastMode)
|
|
152
|
+
: applyClaudeCodeHeaders(new Headers(), options.accessToken ?? '', {
|
|
153
|
+
body,
|
|
154
|
+
identity,
|
|
155
|
+
});
|
|
156
|
+
if (!options.apiAccount && fastMode) {
|
|
119
157
|
headers.set('anthropic-beta', mergeAnthropicBetas(headers.get('anthropic-beta'), [FAST_MODE_BETA]));
|
|
120
158
|
}
|
|
121
159
|
const relayAffinity = options.streamOptions?.sessionId ?? null;
|
|
122
|
-
const input =
|
|
160
|
+
const input = options.apiAccount
|
|
161
|
+
? buildExplicitBaseMessagesUrl(options.apiAccount.baseURL)
|
|
162
|
+
: new URL('/v1/messages?beta=true', options.model.baseUrl);
|
|
123
163
|
const init = {
|
|
124
164
|
method: 'POST',
|
|
125
165
|
headers,
|
|
@@ -134,6 +174,8 @@ async function sendAnthropicRequest(options) {
|
|
|
134
174
|
storage,
|
|
135
175
|
cacheMode: isCacheKeepHybridActive(storage) ? 'hybrid' : 'disabled',
|
|
136
176
|
});
|
|
177
|
+
if (options.apiAccount)
|
|
178
|
+
return fetch(input, init);
|
|
137
179
|
return sendViaRelay({
|
|
138
180
|
config: getRelayConfig(storage),
|
|
139
181
|
input,
|
|
@@ -144,6 +186,13 @@ async function sendAnthropicRequest(options) {
|
|
|
144
186
|
affinity: relayAffinity,
|
|
145
187
|
});
|
|
146
188
|
}
|
|
189
|
+
function quotaSnapshotIsExhausted(quota) {
|
|
190
|
+
return Object.values(quota ?? {}).some((window) => window && window.remainingPercent <= 0);
|
|
191
|
+
}
|
|
192
|
+
export function primaryResponseAllowsApiFallback(preflight) {
|
|
193
|
+
return (preflight === 'rate_limit_error' ||
|
|
194
|
+
(preflight instanceof Response && preflight.status === 429));
|
|
195
|
+
}
|
|
147
196
|
async function firstStreamingError(response) {
|
|
148
197
|
if (!response.ok)
|
|
149
198
|
return response;
|
|
@@ -168,14 +217,49 @@ async function executeWithFallback(options) {
|
|
|
168
217
|
configPath: options.storagePath,
|
|
169
218
|
});
|
|
170
219
|
const storage = await loadAccounts(options.storagePath);
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
220
|
+
const quotaManager = new QuotaManager({ storage });
|
|
221
|
+
async function primaryQuotaRefreshConfirmsExhausted() {
|
|
222
|
+
try {
|
|
223
|
+
const quota = await quotaManager.refreshMain(options.primaryAccessToken);
|
|
224
|
+
const entry = quotaManager.getMain(options.primaryAccessToken);
|
|
225
|
+
return Boolean(entry &&
|
|
226
|
+
entry.refreshAfter > Date.now() &&
|
|
227
|
+
quotaSnapshotIsExhausted(quota));
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
async function tryFallbackAccounts(routeOptions = {}) {
|
|
234
|
+
const usableOAuth = await manager.getUsableFallbackAccounts(storage);
|
|
235
|
+
const usableOAuthById = new Map(usableOAuth.map((account) => [account.id, account]));
|
|
236
|
+
for (const configured of storage?.accounts ?? []) {
|
|
237
|
+
let response = null;
|
|
238
|
+
const account = isOAuthAccount(configured)
|
|
239
|
+
? usableOAuthById.get(configured.id)
|
|
240
|
+
: configured;
|
|
241
|
+
if (!account)
|
|
242
|
+
continue;
|
|
243
|
+
if (isOAuthAccount(account)) {
|
|
244
|
+
if (!account.access)
|
|
245
|
+
continue;
|
|
246
|
+
response = await sendAnthropicRequest({
|
|
247
|
+
...options,
|
|
248
|
+
accessToken: account.access,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
else if (routeOptions.includeApiRoutes === true &&
|
|
252
|
+
isApiKeyAccount(account) &&
|
|
253
|
+
account.enabled !== false &&
|
|
254
|
+
account.apiKey &&
|
|
255
|
+
isValidApiBaseURL(account.baseURL)) {
|
|
256
|
+
response = await sendAnthropicRequest({
|
|
257
|
+
...options,
|
|
258
|
+
apiAccount: account,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
if (!response)
|
|
174
262
|
continue;
|
|
175
|
-
const response = await sendAnthropicRequest({
|
|
176
|
-
...options,
|
|
177
|
-
accessToken: account.access,
|
|
178
|
-
});
|
|
179
263
|
const preflight = await firstStreamingError(response);
|
|
180
264
|
if (preflight instanceof Response && preflight.ok) {
|
|
181
265
|
await manager.markUsed(account);
|
|
@@ -185,6 +269,7 @@ async function executeWithFallback(options) {
|
|
|
185
269
|
!shouldFallbackStatus(preflight.status, storage)) {
|
|
186
270
|
return preflight;
|
|
187
271
|
}
|
|
272
|
+
await response.body?.cancel().catch(() => { });
|
|
188
273
|
}
|
|
189
274
|
return null;
|
|
190
275
|
}
|
|
@@ -203,10 +288,18 @@ async function executeWithFallback(options) {
|
|
|
203
288
|
if (!shouldFallbackStatus(primaryPreflight.status, storage))
|
|
204
289
|
return primaryPreflight;
|
|
205
290
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
291
|
+
const allowApiFallback = primaryResponseAllowsApiFallback(primaryPreflight) &&
|
|
292
|
+
(await primaryQuotaRefreshConfirmsExhausted());
|
|
293
|
+
if (!fallbackFirst || allowApiFallback) {
|
|
294
|
+
const fallback = await tryFallbackAccounts({
|
|
295
|
+
includeApiRoutes: allowApiFallback,
|
|
296
|
+
});
|
|
297
|
+
if (fallback) {
|
|
298
|
+
if (primaryPreflight instanceof Response) {
|
|
299
|
+
await primaryPreflight.body?.cancel().catch(() => { });
|
|
300
|
+
}
|
|
209
301
|
return fallback;
|
|
302
|
+
}
|
|
210
303
|
}
|
|
211
304
|
return primaryPreflight instanceof Response ? primaryPreflight : primary;
|
|
212
305
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/pi-anthropic-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"prepublishOnly": "bun run build"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cortexkit/anthropic-auth-core": "1.
|
|
39
|
+
"@cortexkit/anthropic-auth-core": "1.8.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@earendil-works/pi-ai": "*",
|