@@ -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 ?? {},
|
||||
|
||||
Reference in New Issue
Block a user