fix(ai): expand Copilot eager streaming compat

closes #3575
This commit is contained in:
Mario Zechner
2026-04-23 23:43:00 +02:00
parent 76bc605ad1
commit 1312346199
3 changed files with 22 additions and 3 deletions

View File

@@ -66,7 +66,11 @@ const KIMI_STATIC_HEADERS = {
const AI_GATEWAY_MODELS_URL = "https://ai-gateway.vercel.sh/v1";
const AI_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
const ZAI_TOOL_STREAM_UNSUPPORTED_MODELS = new Set(["glm-4.5", "glm-4.5-air", "glm-4.5-flash", "glm-4.5v"]);
const EAGER_TOOL_INPUT_STREAMING_UNSUPPORTED_ANTHROPIC_MODELS = new Set(["github-copilot:claude-haiku-4.5"]);
const EAGER_TOOL_INPUT_STREAMING_UNSUPPORTED_ANTHROPIC_MODELS = new Set([
"github-copilot:claude-haiku-4.5",
"github-copilot:claude-sonnet-4",
"github-copilot:claude-sonnet-4.5",
]);
function getAnthropicMessagesCompat(provider: string, modelId: string): AnthropicMessagesCompat | undefined {
return EAGER_TOOL_INPUT_STREAMING_UNSUPPORTED_ANTHROPIC_MODELS.has(`${provider}:${modelId}`)

View File

@@ -3087,6 +3087,7 @@ export const MODELS = {
provider: "github-copilot",
baseUrl: "https://api.individual.githubcopilot.com",
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
compat: {"supportsEagerToolInputStreaming":false},
reasoning: true,
input: ["text", "image"],
cost: {
@@ -3105,6 +3106,7 @@ export const MODELS = {
provider: "github-copilot",
baseUrl: "https://api.individual.githubcopilot.com",
headers: {"User-Agent":"GitHubCopilotChat/0.35.0","Editor-Version":"vscode/1.107.0","Editor-Plugin-Version":"copilot-chat/0.35.0","Copilot-Integration-Id":"vscode-chat"},
compat: {"supportsEagerToolInputStreaming":false},
reasoning: true,
input: ["text", "image"],
cost: {

View File

@@ -55,6 +55,8 @@ function getProbePriority(model: Model<"anthropic-messages">): number {
// stale Claude 3.x aliases that can remain in catalogs after upstream removal.
if (modelId.includes("haiku") && (modelId.includes("4-5") || modelId.includes("4.5"))) {
priority -= 1000;
} else if (modelId.includes("sonnet") && (modelId.includes("4-") || modelId.includes("4."))) {
priority -= 750;
} else if (modelId.includes("claude") && (modelId.includes("4-") || modelId.includes("4."))) {
priority -= 500;
}
@@ -78,7 +80,10 @@ function selectOneCasePerProvider(cases: AnthropicEagerE2ECase[]): AnthropicEage
);
}
const probeCases = selectOneCasePerProvider(anthropicMessagesCases);
const generatedCompatCases = selectOneCasePerProvider(anthropicMessagesCases);
const forcedEagerProbeCases = selectOneCasePerProvider(
anthropicMessagesCases.filter((testCase) => testCase.model.compat?.supportsEagerToolInputStreaming !== false),
);
function withEagerToolInputStreaming(model: Model<"anthropic-messages">): Model<"anthropic-messages"> {
return {
@@ -127,8 +132,16 @@ describe("Anthropic Messages eager tool input streaming E2E", () => {
expect(anthropicMessagesCases.map((testCase) => testCase.name).sort()).toEqual(expectedModels.sort());
});
describe("generated compatibility settings", () => {
for (const testCase of generatedCompatCases) {
it.skipIf(!testCase.apiKey)(`${testCase.name} accepts configured tool streaming`, { retry: 2 }, async () => {
await expectToolEnabledRequestAccepted(testCase.model, testCase.apiKey);
});
}
});
describe("forced eager_input_streaming probe", () => {
for (const testCase of probeCases) {
for (const testCase of forcedEagerProbeCases) {
const model = withEagerToolInputStreaming(testCase.model);
it.skipIf(!testCase.apiKey)(