fix(coding-agent): handle z.ai network_error closes #2313

This commit is contained in:
Mario Zechner
2026-03-17 22:34:49 +01:00
parent bbd8392ef9
commit d914d1c199
4 changed files with 154 additions and 25 deletions

View File

@@ -1,10 +1,23 @@
import { Type } from "@sinclair/typebox";
import { describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { getModel } from "../src/models.js";
import { streamSimple } from "../src/stream.js";
import type { Tool } from "../src/types.js";
const mockState = vi.hoisted(() => ({ lastParams: undefined as unknown }));
const mockState = vi.hoisted(() => ({
lastParams: undefined as unknown,
chunks: undefined as
| Array<{
choices: Array<{ delta: Record<string, unknown>; finish_reason: string | null }>;
usage?: {
prompt_tokens: number;
completion_tokens: number;
prompt_tokens_details: { cached_tokens: number };
completion_tokens_details: { reasoning_tokens: number };
};
}>
| undefined,
}));
vi.mock("openai", () => {
class FakeOpenAI {
@@ -14,15 +27,20 @@ vi.mock("openai", () => {
mockState.lastParams = params;
return {
async *[Symbol.asyncIterator]() {
yield {
choices: [{ delta: {}, finish_reason: "stop" }],
usage: {
prompt_tokens: 1,
completion_tokens: 1,
prompt_tokens_details: { cached_tokens: 0 },
completion_tokens_details: { reasoning_tokens: 0 },
const chunks = mockState.chunks ?? [
{
choices: [{ delta: {}, finish_reason: "stop" }],
usage: {
prompt_tokens: 1,
completion_tokens: 1,
prompt_tokens_details: { cached_tokens: 0 },
completion_tokens_details: { reasoning_tokens: 0 },
},
},
};
];
for (const chunk of chunks) {
yield chunk;
}
},
};
},
@@ -34,6 +52,11 @@ vi.mock("openai", () => {
});
describe("openai-completions tool_choice", () => {
beforeEach(() => {
mockState.lastParams = undefined;
mockState.chunks = undefined;
});
it("forwards toolChoice from simple options to payload", async () => {
const { compat: _compat, ...baseModel } = getModel("openai", "gpt-4o-mini")!;
const model = { ...baseModel, api: "openai-completions" } as const;
@@ -175,4 +198,39 @@ describe("openai-completions tool_choice", () => {
const params = (payload ?? mockState.lastParams) as { reasoning_effort?: string };
expect(params.reasoning_effort).toBe("medium");
});
it("maps non-standard provider finish_reason values to stopReason error", async () => {
mockState.chunks = [
{
choices: [{ delta: { content: "partial" }, finish_reason: null }],
},
{
choices: [{ delta: {}, finish_reason: "network_error" }],
usage: {
prompt_tokens: 1,
completion_tokens: 1,
prompt_tokens_details: { cached_tokens: 0 },
completion_tokens_details: { reasoning_tokens: 0 },
},
},
];
const model = getModel("zai", "glm-5")!;
const response = await streamSimple(
model,
{
messages: [
{
role: "user",
content: "Hi",
timestamp: Date.now(),
},
],
},
{ apiKey: "test" },
).result();
expect(response.stopReason).toBe("error");
expect(response.errorMessage).toBe("Provider finish_reason: network_error");
});
});