Files
opencode/packages/ai/test/raw-events.test.ts

76 lines
2.8 KiB
TypeScript

import { describe, expect } from "bun:test"
import { Effect, Stream } from "effect"
import { ai } from "../src/effect.js"
import { Auth, LLMClient } from "../src/route.js"
import { AnthropicMessages } from "../src/protocols/anthropic-messages.js"
import { it } from "./lib/effect.js"
import { fixedResponse } from "./lib/http.js"
import { sseEvents } from "./lib/sse.js"
const model = AnthropicMessages.route
.with({ endpoint: { baseURL: "https://api.anthropic.test/v1/" }, auth: Auth.header("x-api-key", "test") })
.model({ id: "claude-sonnet-4-5" })
const frames = [
{ type: "message_start", message: { usage: { input_tokens: 5 } } },
{ type: "content_block_start", index: 0, content_block: { type: "text", text: "" } },
{ type: "future_event", detail: "unknown to the protocol" },
{ type: "content_block_delta", index: 0, delta: { type: "text_delta", text: "Hello" } },
{ type: "content_block_stop", index: 0 },
{ type: "message_delta", delta: { stop_reason: "end_turn" }, usage: { output_tokens: 1 } },
{ type: "message_stop" },
{ type: "ping" },
]
const layer = fixedResponse(sseEvents(...frames))
describe("raw provider events", () => {
it.effect("stream emits every frame before its own events only when requested", () =>
Effect.gen(function* () {
const raw = Array.from(
yield* LLMClient.stream(ai.request({ model, prompt: "Hi", includeRaw: true })).pipe(
Stream.runCollect,
Effect.provide(layer),
),
)
const plain = Array.from(
yield* LLMClient.stream(ai.request({ model, prompt: "Hi" })).pipe(Stream.runCollect, Effect.provide(layer)),
)
expect(raw.filter((event) => event.type === "raw").map((event) => event.data)).toEqual(frames)
expect(
raw.map((event) => (event.type === "raw" ? `raw:${(event.data as { type: string }).type}` : event.type)),
).toEqual([
"raw:message_start",
"raw:content_block_start",
"step-start",
"text-start",
"raw:future_event",
"raw:content_block_delta",
"text-delta",
"raw:content_block_stop",
"text-end",
"raw:message_delta",
"raw:message_stop",
"step-finish",
"finish",
"raw:ping",
])
expect(raw.filter((event) => event.type !== "raw")).toEqual(plain)
expect(plain.some((event) => event.type === "raw")).toBe(false)
}),
)
it.effect("generate ignores raw events", () =>
Effect.gen(function* () {
const withRaw = yield* LLMClient.generate(ai.request({ model, prompt: "Hi", includeRaw: true })).pipe(
Effect.provide(layer),
)
const plain = yield* LLMClient.generate(ai.request({ model, prompt: "Hi" })).pipe(Effect.provide(layer))
expect(withRaw).toEqual(plain)
expect(withRaw.text).toBe("Hello")
}),
)
})