@oh-my-pi/pi-ai 15.10.3 → 15.10.4
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/CHANGELOG.md +11 -0
- package/dist/types/providers/anthropic.d.ts +9 -4
- package/package.json +2 -2
- package/src/providers/anthropic.ts +105 -103
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [15.10.4] - 2026-06-08
|
|
6
|
+
### Added
|
|
7
|
+
|
|
8
|
+
- Added `anthropic-client-platform` (`desktop_app`) and `anthropic-client-version` (`1.11187.4`) headers to the Anthropic request fingerprint for OAuth sessions
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Changed non-built-in tool names sent to Anthropic from `proxy_` prefixing to `_` prefixing (for example `bash` to `_bash`) while built-in tool names remain unchanged
|
|
13
|
+
- Updated the Anthropic OAuth stealth fingerprint to track Claude Code 2.1.165: `claudeCodeVersion` bumped to `2.1.165` (flows into both the `cc_version` billing header and the `claude-cli/<version>` user-agent), `claudeCodeSystemInstruction` changed to `"You are a Claude agent, built on Anthropic's Claude Agent SDK."`, and the billing-header `cc_entrypoint` changed from `cli` to `local-agent`.
|
|
14
|
+
- Clamped the Anthropic request `max_tokens` to `Math.min(CLAUDE_CODE_MAX_OUTPUT_TOKENS, options.maxTokens || model.maxTokens)` (64k) so OAuth requests match Claude Code's requested output cap instead of sending the model's full ceiling (e.g. 128k for Opus 4.8).
|
|
15
|
+
|
|
5
16
|
## [15.10.3] - 2026-06-08
|
|
6
17
|
|
|
7
18
|
### Removed
|
|
@@ -26,9 +26,12 @@ type AnthropicCacheControl = NonNullable<TextBlockParam["cache_control"]>;
|
|
|
26
26
|
*/
|
|
27
27
|
export declare function clearAnthropicFastModeFallback(providerSessionState: Map<string, ProviderSessionState> | undefined): void;
|
|
28
28
|
export declare function isAnthropicFastModeUnsupportedError(error: unknown): boolean;
|
|
29
|
-
export declare const claudeCodeVersion = "2.1.
|
|
29
|
+
export declare const claudeCodeVersion = "2.1.165";
|
|
30
|
+
export declare const claudeAgentSdkVersion = "0.3.165";
|
|
31
|
+
export declare const claudeClientVersion = "1.11187.4";
|
|
30
32
|
export declare const claudeToolPrefix: string;
|
|
31
|
-
export declare const claudeCodeSystemInstruction = "You are Claude
|
|
33
|
+
export declare const claudeCodeSystemInstruction = "You are a Claude agent, built on Anthropic's Claude Agent SDK.";
|
|
34
|
+
export declare const CLAUDE_CODE_MAX_OUTPUT_TOKENS = 64000;
|
|
32
35
|
export declare function mapStainlessOs(platform: string): "MacOS" | "Windows" | "Linux" | "FreeBSD" | `Other::${string}`;
|
|
33
36
|
export declare function mapStainlessArch(arch: string): "x64" | "arm64" | "x86" | `other::${string}`;
|
|
34
37
|
export declare const claudeCodeHeaders: {
|
|
@@ -40,11 +43,13 @@ export declare const claudeCodeHeaders: {
|
|
|
40
43
|
"X-Stainless-Arch": "arm64" | "x64" | "x86" | `other::${string}`;
|
|
41
44
|
"X-Stainless-OS": "FreeBSD" | "Linux" | "MacOS" | "Windows" | `Other::${string}`;
|
|
42
45
|
"X-Stainless-Timeout": string;
|
|
46
|
+
"anthropic-client-platform": string;
|
|
47
|
+
"anthropic-client-version": string;
|
|
43
48
|
};
|
|
44
49
|
export declare function isClaudeCloakingUserId(userId: string): boolean;
|
|
45
50
|
export declare function generateClaudeCloakingUserId(): string;
|
|
46
|
-
export declare const applyClaudeToolPrefix: (name: string
|
|
47
|
-
export declare const stripClaudeToolPrefix: (name: string
|
|
51
|
+
export declare const applyClaudeToolPrefix: (name: string) => string;
|
|
52
|
+
export declare const stripClaudeToolPrefix: (name: string) => string;
|
|
48
53
|
export type AnthropicEffort = "low" | "medium" | "high" | "xhigh" | "max";
|
|
49
54
|
export type AnthropicThinkingDisplay = "summarized" | "omitted";
|
|
50
55
|
export interface AnthropicOptions extends StreamOptions {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "15.10.
|
|
4
|
+
"version": "15.10.4",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@bufbuild/protobuf": "^2.12.0",
|
|
42
|
-
"@oh-my-pi/pi-utils": "15.10.
|
|
42
|
+
"@oh-my-pi/pi-utils": "15.10.4",
|
|
43
43
|
"openai": "^6.39.0",
|
|
44
44
|
"partial-json": "^0.1.7",
|
|
45
45
|
"zod": "4.4.3"
|
|
@@ -196,9 +196,9 @@ const sharedHeaders = {
|
|
|
196
196
|
"Accept-Encoding": "gzip, deflate, br, zstd",
|
|
197
197
|
Connection: "keep-alive",
|
|
198
198
|
"Content-Type": "application/json",
|
|
199
|
-
"
|
|
200
|
-
"
|
|
201
|
-
"
|
|
199
|
+
"anthropic-version": "2023-06-01",
|
|
200
|
+
"anthropic-dangerous-direct-browser-access": "true",
|
|
201
|
+
"x-app": "cli",
|
|
202
202
|
};
|
|
203
203
|
|
|
204
204
|
export function buildAnthropicHeaders(options: AnthropicHeaderOptions): Record<string, string> {
|
|
@@ -216,7 +216,7 @@ export function buildAnthropicHeaders(options: AnthropicHeaderOptions): Record<s
|
|
|
216
216
|
...modelHeaders,
|
|
217
217
|
Accept: acceptHeader,
|
|
218
218
|
...sharedHeaders,
|
|
219
|
-
"
|
|
219
|
+
"anthropic-beta": betaHeader,
|
|
220
220
|
"cf-aig-authorization": `Bearer ${options.apiKey}`,
|
|
221
221
|
};
|
|
222
222
|
}
|
|
@@ -225,14 +225,14 @@ export function buildAnthropicHeaders(options: AnthropicHeaderOptions): Record<s
|
|
|
225
225
|
const incomingUserAgent = getHeaderCaseInsensitive(options.modelHeaders, "User-Agent");
|
|
226
226
|
const userAgent = isClaudeCodeClientUserAgent(incomingUserAgent)
|
|
227
227
|
? incomingUserAgent
|
|
228
|
-
: `claude-cli/${claudeCodeVersion} (external,
|
|
228
|
+
: `claude-cli/${claudeCodeVersion} (external, local-agent, agent-sdk/${claudeAgentSdkVersion})`;
|
|
229
229
|
return {
|
|
230
230
|
...modelHeaders,
|
|
231
231
|
...claudeCodeHeaders,
|
|
232
232
|
Accept: acceptHeader,
|
|
233
233
|
Authorization: `Bearer ${options.apiKey}`,
|
|
234
234
|
...sharedHeaders,
|
|
235
|
-
"
|
|
235
|
+
"anthropic-beta": betaHeader,
|
|
236
236
|
...(options.claudeCodeSessionId ? { "X-Claude-Code-Session-Id": options.claudeCodeSessionId } : {}),
|
|
237
237
|
"x-client-request-id": nodeCrypto.randomUUID(),
|
|
238
238
|
"User-Agent": userAgent,
|
|
@@ -243,14 +243,14 @@ export function buildAnthropicHeaders(options: AnthropicHeaderOptions): Record<s
|
|
|
243
243
|
Accept: acceptHeader,
|
|
244
244
|
Authorization: `Bearer ${options.apiKey}`,
|
|
245
245
|
...sharedHeaders,
|
|
246
|
-
"
|
|
246
|
+
"anthropic-beta": betaHeader,
|
|
247
247
|
};
|
|
248
248
|
} else {
|
|
249
249
|
return {
|
|
250
250
|
...modelHeaders,
|
|
251
251
|
Accept: acceptHeader,
|
|
252
252
|
...sharedHeaders,
|
|
253
|
-
"
|
|
253
|
+
"anthropic-beta": betaHeader,
|
|
254
254
|
"X-Api-Key": options.apiKey,
|
|
255
255
|
};
|
|
256
256
|
}
|
|
@@ -260,12 +260,6 @@ type AnthropicCacheControl = NonNullable<TextBlockParam["cache_control"]>;
|
|
|
260
260
|
|
|
261
261
|
type AnthropicOutputConfig = NonNullable<MessageCreateParamsStreaming["output_config"]>;
|
|
262
262
|
|
|
263
|
-
function getAnthropicOutputConfig(params: MessageCreateParamsStreaming): AnthropicOutputConfig {
|
|
264
|
-
const outputConfig = params.output_config ?? {};
|
|
265
|
-
params.output_config = outputConfig;
|
|
266
|
-
return outputConfig;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
263
|
const ANTHROPIC_STOP_SEQUENCES_MAX = 4;
|
|
270
264
|
let warnedStopSequencesTrim = false;
|
|
271
265
|
|
|
@@ -398,9 +392,14 @@ function getCacheControl(
|
|
|
398
392
|
}
|
|
399
393
|
|
|
400
394
|
// Stealth mode: mimic Claude Code's request fingerprint.
|
|
401
|
-
export const claudeCodeVersion = "2.1.
|
|
402
|
-
export const
|
|
403
|
-
export const
|
|
395
|
+
export const claudeCodeVersion = "2.1.165";
|
|
396
|
+
export const claudeAgentSdkVersion = "0.3.165";
|
|
397
|
+
export const claudeClientVersion = "1.11187.4";
|
|
398
|
+
export const claudeToolPrefix: string = "_";
|
|
399
|
+
export const claudeCodeSystemInstruction = "You are a Claude agent, built on Anthropic's Claude Agent SDK.";
|
|
400
|
+
// Claude Code caps requested output at 64k tokens even when the model ceiling is
|
|
401
|
+
// higher (e.g. Opus 4.8 supports 128k); clamp to match the wire fingerprint.
|
|
402
|
+
export const CLAUDE_CODE_MAX_OUTPUT_TOKENS = 64000;
|
|
404
403
|
|
|
405
404
|
export function mapStainlessOs(platform: string): "MacOS" | "Windows" | "Linux" | "FreeBSD" | `Other::${string}` {
|
|
406
405
|
switch (platform.toLowerCase()) {
|
|
@@ -443,7 +442,9 @@ export const claudeCodeHeaders = {
|
|
|
443
442
|
"X-Stainless-Lang": "js",
|
|
444
443
|
"X-Stainless-Arch": mapStainlessArch(process.arch),
|
|
445
444
|
"X-Stainless-OS": mapStainlessOs(process.platform),
|
|
446
|
-
"X-Stainless-Timeout": "
|
|
445
|
+
"X-Stainless-Timeout": "900",
|
|
446
|
+
"anthropic-client-platform": "desktop_app",
|
|
447
|
+
"anthropic-client-version": claudeClientVersion,
|
|
447
448
|
};
|
|
448
449
|
|
|
449
450
|
const enforcedHeaderKeys = new Set(
|
|
@@ -453,11 +454,11 @@ const enforcedHeaderKeys = new Set(
|
|
|
453
454
|
"Accept-Encoding",
|
|
454
455
|
"Connection",
|
|
455
456
|
"Content-Type",
|
|
456
|
-
"
|
|
457
|
-
"
|
|
458
|
-
"
|
|
457
|
+
"anthropic-version",
|
|
458
|
+
"anthropic-dangerous-direct-browser-access",
|
|
459
|
+
"anthropic-beta",
|
|
459
460
|
"User-Agent",
|
|
460
|
-
"
|
|
461
|
+
"x-app",
|
|
461
462
|
"Authorization",
|
|
462
463
|
"X-Api-Key",
|
|
463
464
|
"X-Claude-Code-Session-Id",
|
|
@@ -480,7 +481,7 @@ function createClaudeBillingHeader(firstUserMessageText: string): string {
|
|
|
480
481
|
.slice(0, 3);
|
|
481
482
|
// cch=00000: placeholder replaced with the real attestation hash by wrapFetchForCch
|
|
482
483
|
// before the request hits the wire (see below).
|
|
483
|
-
return `${CLAUDE_BILLING_HEADER_PREFIX} cc_version=${claudeCodeVersion}.${versionSuffix}; cc_entrypoint=
|
|
484
|
+
return `${CLAUDE_BILLING_HEADER_PREFIX} cc_version=${claudeCodeVersion}.${versionSuffix}; cc_entrypoint=local-agent; ${CCH_PLACEHOLDER_STR};`;
|
|
484
485
|
}
|
|
485
486
|
|
|
486
487
|
// cch attestation: XXHash64(body_with_placeholder, seed) low-20-bits, 5 hex chars.
|
|
@@ -620,19 +621,17 @@ function resolveAnthropicMetadataUserId(
|
|
|
620
621
|
return generateClaudeJsonUserId(sessionId);
|
|
621
622
|
}
|
|
622
623
|
const ANTHROPIC_BUILTIN_TOOL_NAMES = new Set(["web_search", "code_execution", "text_editor", "computer"]);
|
|
623
|
-
export const applyClaudeToolPrefix = (name: string
|
|
624
|
-
if (!
|
|
624
|
+
export const applyClaudeToolPrefix = (name: string): string => {
|
|
625
|
+
if (!claudeToolPrefix) return name;
|
|
625
626
|
if (ANTHROPIC_BUILTIN_TOOL_NAMES.has(name.toLowerCase())) return name;
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
return `${prefixOverride}${name}`;
|
|
627
|
+
if (name.toLowerCase().startsWith(claudeToolPrefix.toLowerCase())) return name;
|
|
628
|
+
return `${claudeToolPrefix}${name}`;
|
|
629
629
|
};
|
|
630
630
|
|
|
631
|
-
export const stripClaudeToolPrefix = (name: string
|
|
632
|
-
if (!
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
return name.slice(prefixOverride.length);
|
|
631
|
+
export const stripClaudeToolPrefix = (name: string): string => {
|
|
632
|
+
if (!claudeToolPrefix) return name;
|
|
633
|
+
if (!name.toLowerCase().startsWith(claudeToolPrefix.toLowerCase())) return name;
|
|
634
|
+
return name.slice(claudeToolPrefix.length);
|
|
636
635
|
};
|
|
637
636
|
|
|
638
637
|
const ANTHROPIC_MANY_IMAGE_THRESHOLD = 20;
|
|
@@ -2285,13 +2284,6 @@ function extractClaudeCodeFirstUserMessageText(messages: readonly Message[]): st
|
|
|
2285
2284
|
return "";
|
|
2286
2285
|
}
|
|
2287
2286
|
|
|
2288
|
-
function applyClaudeCodeContextManagement(params: MessageCreateParamsStreaming, isOAuthToken: boolean): void {
|
|
2289
|
-
if (!isOAuthToken || params.thinking?.type !== "adaptive") return;
|
|
2290
|
-
params.context_management = {
|
|
2291
|
-
edits: [{ type: "clear_thinking_20251015", keep: "all" }],
|
|
2292
|
-
};
|
|
2293
|
-
}
|
|
2294
|
-
|
|
2295
2287
|
function buildParams(
|
|
2296
2288
|
model: Model<"anthropic-messages">,
|
|
2297
2289
|
baseUrl: string,
|
|
@@ -2301,58 +2293,41 @@ function buildParams(
|
|
|
2301
2293
|
disableStrictTools = false,
|
|
2302
2294
|
): MessageCreateParamsStreaming {
|
|
2303
2295
|
const { cacheControl } = getCacheControl(model, baseUrl, options?.cacheRetention, isOAuthToken);
|
|
2304
|
-
const params: MessageCreateParamsStreaming = {
|
|
2305
|
-
model: model.id,
|
|
2306
|
-
messages: convertAnthropicMessages(context.messages, model, isOAuthToken),
|
|
2307
|
-
max_tokens: options?.maxTokens || model.maxTokens,
|
|
2308
|
-
stream: true,
|
|
2309
|
-
};
|
|
2310
|
-
if (options?.temperature !== undefined && !options?.thinkingEnabled) {
|
|
2311
|
-
params.temperature = options.temperature;
|
|
2312
|
-
}
|
|
2313
|
-
|
|
2314
|
-
if (options?.topP !== undefined) {
|
|
2315
|
-
params.top_p = options.topP;
|
|
2316
|
-
}
|
|
2317
|
-
if (options?.topK !== undefined) {
|
|
2318
|
-
params.top_k = options.topK;
|
|
2319
|
-
}
|
|
2320
|
-
if (options?.stopSequences?.length) {
|
|
2321
|
-
const seqs = options.stopSequences;
|
|
2322
|
-
if (seqs.length > ANTHROPIC_STOP_SEQUENCES_MAX && !warnedStopSequencesTrim) {
|
|
2323
|
-
warnedStopSequencesTrim = true;
|
|
2324
|
-
logger.warn("anthropic: stop_sequences exceeds 4; extra entries dropped", {
|
|
2325
|
-
received: seqs.length,
|
|
2326
|
-
kept: ANTHROPIC_STOP_SEQUENCES_MAX,
|
|
2327
|
-
});
|
|
2328
|
-
}
|
|
2329
|
-
params.stop_sequences =
|
|
2330
|
-
seqs.length > ANTHROPIC_STOP_SEQUENCES_MAX ? seqs.slice(0, ANTHROPIC_STOP_SEQUENCES_MAX) : seqs;
|
|
2331
|
-
}
|
|
2332
2296
|
|
|
2333
|
-
//
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2297
|
+
// Pre-compute system blocks so they occupy the right slot in the serialized body.
|
|
2298
|
+
const shouldInjectClaudeCodeInstruction = isOAuthToken && !model.id.startsWith("claude-3-5-haiku");
|
|
2299
|
+
const firstUserMessageText = shouldInjectClaudeCodeInstruction
|
|
2300
|
+
? extractClaudeCodeFirstUserMessageText(context.messages)
|
|
2301
|
+
: "";
|
|
2302
|
+
const systemBlocks = buildAnthropicSystemBlocks(context.systemPrompt, {
|
|
2303
|
+
includeClaudeCodeInstruction: shouldInjectClaudeCodeInstruction,
|
|
2304
|
+
firstUserMessageText,
|
|
2305
|
+
});
|
|
2339
2306
|
|
|
2307
|
+
// Pre-compute tools.
|
|
2308
|
+
let tools: ReturnType<typeof convertTools> | undefined;
|
|
2340
2309
|
if (context.tools) {
|
|
2341
|
-
|
|
2310
|
+
tools = convertTools(
|
|
2342
2311
|
context.tools,
|
|
2343
2312
|
isOAuthToken,
|
|
2344
2313
|
disableStrictTools || model.provider === "github-copilot",
|
|
2345
2314
|
getAnthropicCompat(model).supportsEagerToolInputStreaming,
|
|
2346
2315
|
);
|
|
2347
2316
|
} else if (isOAuthToken) {
|
|
2348
|
-
|
|
2317
|
+
tools = [];
|
|
2349
2318
|
}
|
|
2350
2319
|
|
|
2320
|
+
// Pre-compute metadata.
|
|
2321
|
+
const metadataUserId = resolveAnthropicMetadataUserId(options?.metadata?.user_id, isOAuthToken, options?.sessionId);
|
|
2322
|
+
const metadata = metadataUserId ? { user_id: metadataUserId } : undefined;
|
|
2323
|
+
|
|
2324
|
+
// Pre-compute thinking + output_config effort.
|
|
2325
|
+
let thinking: MessageCreateParamsStreaming["thinking"] | undefined;
|
|
2326
|
+
let outputConfigEffort: AnthropicEffort | undefined;
|
|
2351
2327
|
if (model.reasoning) {
|
|
2352
2328
|
if (options?.thinkingEnabled) {
|
|
2353
2329
|
const mode = model.thinking?.mode;
|
|
2354
2330
|
const effort = resolveAnthropicAdaptiveEffort(model, options);
|
|
2355
|
-
|
|
2356
2331
|
const compat = getAnthropicCompat(model);
|
|
2357
2332
|
if (mode === "anthropic-adaptive" && !compat.disableAdaptiveThinking) {
|
|
2358
2333
|
const adaptive: { type: "adaptive"; display?: AnthropicThinkingDisplay } = { type: "adaptive" };
|
|
@@ -2362,31 +2337,70 @@ function buildParams(
|
|
|
2362
2337
|
if (options.thinkingDisplay !== undefined || supportsAdaptiveThinkingDisplay(model.id)) {
|
|
2363
2338
|
adaptive.display = options.thinkingDisplay ?? "summarized";
|
|
2364
2339
|
}
|
|
2365
|
-
|
|
2366
|
-
if (effort)
|
|
2367
|
-
getAnthropicOutputConfig(params).effort = effort;
|
|
2368
|
-
}
|
|
2340
|
+
thinking = adaptive;
|
|
2341
|
+
if (effort) outputConfigEffort = effort;
|
|
2369
2342
|
} else {
|
|
2370
|
-
|
|
2343
|
+
thinking = {
|
|
2371
2344
|
type: "enabled",
|
|
2372
2345
|
budget_tokens: options.thinkingBudgetTokens || 1024,
|
|
2373
2346
|
display: options.thinkingDisplay ?? "summarized",
|
|
2374
2347
|
};
|
|
2375
|
-
if (mode === "anthropic-budget-effort" && effort)
|
|
2376
|
-
getAnthropicOutputConfig(params).effort = effort;
|
|
2377
|
-
}
|
|
2348
|
+
if (mode === "anthropic-budget-effort" && effort) outputConfigEffort = effort;
|
|
2378
2349
|
}
|
|
2379
2350
|
} else if (options?.thinkingEnabled === false) {
|
|
2380
|
-
|
|
2351
|
+
thinking = { type: "disabled" };
|
|
2381
2352
|
}
|
|
2382
2353
|
}
|
|
2383
2354
|
|
|
2384
|
-
|
|
2385
|
-
|
|
2355
|
+
// Pre-compute context_management (depends on thinking).
|
|
2356
|
+
const contextManagement =
|
|
2357
|
+
isOAuthToken && thinking?.type === "adaptive"
|
|
2358
|
+
? { edits: [{ type: "clear_thinking_20251015" as const, keep: "all" as const }] }
|
|
2359
|
+
: undefined;
|
|
2360
|
+
|
|
2361
|
+
// Pre-compute output_config.
|
|
2362
|
+
const outputConfigEntries: AnthropicOutputConfig = {};
|
|
2363
|
+
if (outputConfigEffort) outputConfigEntries.effort = outputConfigEffort;
|
|
2364
|
+
if (options?.taskBudget) outputConfigEntries.task_budget = options.taskBudget;
|
|
2365
|
+
const outputConfig = Object.keys(outputConfigEntries).length ? outputConfigEntries : undefined;
|
|
2366
|
+
|
|
2367
|
+
// Build params in the canonical field order: model → messages → system → tools →
|
|
2368
|
+
// metadata → max_tokens → thinking → context_management → output_config → stream.
|
|
2369
|
+
const params: MessageCreateParamsStreaming = {
|
|
2370
|
+
model: model.id,
|
|
2371
|
+
messages: convertAnthropicMessages(context.messages, model, isOAuthToken),
|
|
2372
|
+
...(systemBlocks && { system: systemBlocks }),
|
|
2373
|
+
...(tools !== undefined && { tools }),
|
|
2374
|
+
...(metadata && { metadata }),
|
|
2375
|
+
max_tokens: Math.min(CLAUDE_CODE_MAX_OUTPUT_TOKENS, options?.maxTokens || model.maxTokens),
|
|
2376
|
+
...(thinking && { thinking }),
|
|
2377
|
+
...(contextManagement && { context_management: contextManagement }),
|
|
2378
|
+
...(outputConfig && { output_config: outputConfig }),
|
|
2379
|
+
stream: true,
|
|
2380
|
+
};
|
|
2381
|
+
|
|
2382
|
+
// Opus 4.7+ rejects non-default sampling parameters with 400 error.
|
|
2383
|
+
const allowSamplingParams = !hasOpus47ApiRestrictions(model.id);
|
|
2384
|
+
if (allowSamplingParams && options?.temperature !== undefined && !options?.thinkingEnabled) {
|
|
2385
|
+
params.temperature = options.temperature;
|
|
2386
2386
|
}
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2387
|
+
if (allowSamplingParams && options?.topP !== undefined) {
|
|
2388
|
+
params.top_p = options.topP;
|
|
2389
|
+
}
|
|
2390
|
+
if (allowSamplingParams && options?.topK !== undefined) {
|
|
2391
|
+
params.top_k = options.topK;
|
|
2392
|
+
}
|
|
2393
|
+
if (options?.stopSequences?.length) {
|
|
2394
|
+
const seqs = options.stopSequences;
|
|
2395
|
+
if (seqs.length > ANTHROPIC_STOP_SEQUENCES_MAX && !warnedStopSequencesTrim) {
|
|
2396
|
+
warnedStopSequencesTrim = true;
|
|
2397
|
+
logger.warn("anthropic: stop_sequences exceeds 4; extra entries dropped", {
|
|
2398
|
+
received: seqs.length,
|
|
2399
|
+
kept: ANTHROPIC_STOP_SEQUENCES_MAX,
|
|
2400
|
+
});
|
|
2401
|
+
}
|
|
2402
|
+
params.stop_sequences =
|
|
2403
|
+
seqs.length > ANTHROPIC_STOP_SEQUENCES_MAX ? seqs.slice(0, ANTHROPIC_STOP_SEQUENCES_MAX) : seqs;
|
|
2390
2404
|
}
|
|
2391
2405
|
|
|
2392
2406
|
if (resolveServiceTier(options?.serviceTier, model.provider) === "priority") {
|
|
@@ -2403,19 +2417,7 @@ function buildParams(
|
|
|
2403
2417
|
}
|
|
2404
2418
|
}
|
|
2405
2419
|
|
|
2406
|
-
const shouldInjectClaudeCodeInstruction = isOAuthToken && !model.id.startsWith("claude-3-5-haiku");
|
|
2407
|
-
const firstUserMessageText = shouldInjectClaudeCodeInstruction
|
|
2408
|
-
? extractClaudeCodeFirstUserMessageText(context.messages)
|
|
2409
|
-
: "";
|
|
2410
|
-
const systemBlocks = buildAnthropicSystemBlocks(context.systemPrompt, {
|
|
2411
|
-
includeClaudeCodeInstruction: shouldInjectClaudeCodeInstruction,
|
|
2412
|
-
firstUserMessageText,
|
|
2413
|
-
});
|
|
2414
|
-
if (systemBlocks) {
|
|
2415
|
-
params.system = systemBlocks;
|
|
2416
|
-
}
|
|
2417
2420
|
disableThinkingIfToolChoiceForced(params);
|
|
2418
|
-
applyClaudeCodeContextManagement(params, isOAuthToken);
|
|
2419
2421
|
ensureMaxTokensForThinking(params, model);
|
|
2420
2422
|
applyPromptCaching(params, cacheControl);
|
|
2421
2423
|
enforceCacheControlLimit(params, 4);
|