|
|
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
|
|
import { getEnvApiKey } from "../env-api-keys.js";
|
|
|
|
|
import { calculateCost } from "../models.js";
|
|
|
|
|
import type {
|
|
|
|
|
AnthropicMessagesCompat,
|
|
|
|
|
Api,
|
|
|
|
|
AssistantMessage,
|
|
|
|
|
CacheRetention,
|
|
|
|
|
@@ -159,6 +160,15 @@ export type AnthropicEffort = "low" | "medium" | "high" | "xhigh" | "max";
|
|
|
|
|
|
|
|
|
|
export type AnthropicThinkingDisplay = "summarized" | "omitted";
|
|
|
|
|
|
|
|
|
|
const FINE_GRAINED_TOOL_STREAMING_BETA = "fine-grained-tool-streaming-2025-05-14";
|
|
|
|
|
const INTERLEAVED_THINKING_BETA = "interleaved-thinking-2025-05-14";
|
|
|
|
|
|
|
|
|
|
function getAnthropicCompat(model: Model<"anthropic-messages">): Required<AnthropicMessagesCompat> {
|
|
|
|
|
return {
|
|
|
|
|
supportsEagerToolInputStreaming: model.compat?.supportsEagerToolInputStreaming ?? true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface AnthropicOptions extends StreamOptions {
|
|
|
|
|
/**
|
|
|
|
|
* Enable extended thinking.
|
|
|
|
|
@@ -433,6 +443,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages", AnthropicOpti
|
|
|
|
|
model,
|
|
|
|
|
apiKey,
|
|
|
|
|
options?.interleavedThinking ?? true,
|
|
|
|
|
shouldUseFineGrainedToolStreamingBeta(model, context),
|
|
|
|
|
options?.headers,
|
|
|
|
|
copilotDynamicHeaders,
|
|
|
|
|
);
|
|
|
|
|
@@ -728,6 +739,7 @@ function createClient(
|
|
|
|
|
model: Model<"anthropic-messages">,
|
|
|
|
|
apiKey: string,
|
|
|
|
|
interleavedThinking: boolean,
|
|
|
|
|
useFineGrainedToolStreamingBeta: boolean,
|
|
|
|
|
optionsHeaders?: Record<string, string>,
|
|
|
|
|
dynamicHeaders?: Record<string, string>,
|
|
|
|
|
): { client: Anthropic; isOAuthToken: boolean } {
|
|
|
|
|
@@ -735,11 +747,14 @@ function createClient(
|
|
|
|
|
// The beta header is deprecated on Opus 4.6 and redundant on Sonnet 4.6, so skip it.
|
|
|
|
|
const needsInterleavedBeta = interleavedThinking && !supportsAdaptiveThinking(model.id);
|
|
|
|
|
|
|
|
|
|
// Copilot: Bearer auth, selective betas (no fine-grained-tool-streaming)
|
|
|
|
|
// Copilot: Bearer auth, selective betas.
|
|
|
|
|
if (model.provider === "github-copilot") {
|
|
|
|
|
const betaFeatures: string[] = [];
|
|
|
|
|
if (useFineGrainedToolStreamingBeta) {
|
|
|
|
|
betaFeatures.push(FINE_GRAINED_TOOL_STREAMING_BETA);
|
|
|
|
|
}
|
|
|
|
|
if (needsInterleavedBeta) {
|
|
|
|
|
betaFeatures.push("interleaved-thinking-2025-05-14");
|
|
|
|
|
betaFeatures.push(INTERLEAVED_THINKING_BETA);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const client = new Anthropic({
|
|
|
|
|
@@ -763,8 +778,11 @@ function createClient(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const betaFeatures: string[] = [];
|
|
|
|
|
if (useFineGrainedToolStreamingBeta) {
|
|
|
|
|
betaFeatures.push(FINE_GRAINED_TOOL_STREAMING_BETA);
|
|
|
|
|
}
|
|
|
|
|
if (needsInterleavedBeta) {
|
|
|
|
|
betaFeatures.push("interleaved-thinking-2025-05-14");
|
|
|
|
|
betaFeatures.push(INTERLEAVED_THINKING_BETA);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OAuth: Bearer auth, Claude Code identity headers
|
|
|
|
|
@@ -856,7 +874,12 @@ function buildParams(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context.tools) {
|
|
|
|
|
params.tools = convertTools(context.tools, isOAuthToken, cacheControl);
|
|
|
|
|
params.tools = convertTools(
|
|
|
|
|
context.tools,
|
|
|
|
|
isOAuthToken,
|
|
|
|
|
getAnthropicCompat(model).supportsEagerToolInputStreaming,
|
|
|
|
|
cacheControl,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Configure thinking mode: adaptive (Opus 4.6+ and Sonnet 4.6),
|
|
|
|
|
@@ -1078,9 +1101,14 @@ function convertMessages(
|
|
|
|
|
return params;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function shouldUseFineGrainedToolStreamingBeta(model: Model<"anthropic-messages">, context: Context): boolean {
|
|
|
|
|
return !!context.tools?.length && !getAnthropicCompat(model).supportsEagerToolInputStreaming;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function convertTools(
|
|
|
|
|
tools: Tool[],
|
|
|
|
|
isOAuthToken: boolean,
|
|
|
|
|
supportsEagerToolInputStreaming: boolean,
|
|
|
|
|
cacheControl?: CacheControlEphemeral,
|
|
|
|
|
): Anthropic.Messages.Tool[] {
|
|
|
|
|
if (!tools) return [];
|
|
|
|
|
@@ -1091,7 +1119,7 @@ function convertTools(
|
|
|
|
|
return {
|
|
|
|
|
name: isOAuthToken ? toClaudeCodeName(tool.name) : tool.name,
|
|
|
|
|
description: tool.description,
|
|
|
|
|
eager_input_streaming: true,
|
|
|
|
|
...(supportsEagerToolInputStreaming ? { eager_input_streaming: true } : {}),
|
|
|
|
|
input_schema: {
|
|
|
|
|
type: "object",
|
|
|
|
|
properties: schema.properties ?? {},
|
|
|
|
|
|