fix(coding-agent): handle z.ai network_error closes #2313
This commit is contained in:
@@ -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");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user