
























@@ -533,6 +533,65 @@ describe("anthropic transport stream", () => {
533533expect(result.usage.output).toBe(9);
534534});
535535536+it("recovers orphan text deltas when an Anthropic-compatible provider omits block start", async () => {
537+guardedFetchMock.mockResolvedValueOnce(
538+createSseResponse([
539+{
540+type: "message_start",
541+message: { id: "msg_1", usage: { input_tokens: 6, output_tokens: 0 } },
542+},
543+{
544+type: "content_block_delta",
545+index: 0,
546+delta: { type: "text_delta", text: "你好" },
547+},
548+{
549+type: "content_block_stop",
550+index: 0,
551+},
552+{
553+type: "message_delta",
554+delta: { stop_reason: "end_turn" },
555+usage: { input_tokens: 6, output_tokens: 1 },
556+},
557+]),
558+);
559+const streamFn = createAnthropicMessagesTransportStreamFn();
560+const stream = await Promise.resolve(
561+streamFn(
562+makeAnthropicTransportModel({
563+provider: "kimi-coding",
564+baseUrl: "https://api.kimi.com/coding/",
565+}),
566+{
567+messages: [{ role: "user", content: "hello" }],
568+} as Parameters<typeof streamFn>[1],
569+{
570+apiKey: "kimi-key",
571+} as Parameters<typeof streamFn>[2],
572+),
573+);
574+const events: Array<{ type?: string; delta?: string; content?: string }> = [];
575+for await (const event of stream as AsyncIterable<{
576+type?: string;
577+delta?: string;
578+content?: string;
579+}>) {
580+events.push(event);
581+}
582+const result = await stream.result();
583+584+expect(result.content).toEqual([{ type: "text", text: "你好" }]);
585+expect(result.stopReason).toBe("stop");
586+expect(events).toEqual(
587+expect.arrayContaining([
588+expect.objectContaining({ type: "text_start" }),
589+expect.objectContaining({ type: "text_delta", delta: "你好" }),
590+expect.objectContaining({ type: "text_end", content: "你好" }),
591+]),
592+);
593+});
594+536595it("skips malformed tools when building Anthropic payloads", async () => {
537596await runTransportStream(
538597makeAnthropicTransportModel(),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。