67 lines
2.3 KiB
TypeScript
67 lines
2.3 KiB
TypeScript
import { describe, expect } from "bun:test"
|
|
import { Effect } from "effect"
|
|
import { LLM, LLMEvent } from "../../src"
|
|
import * as OpenAICompatible from "../../src/providers/openai-compatible"
|
|
import * as OpenRouter from "../../src/providers/openrouter"
|
|
import { LLMClient } from "../../src/route"
|
|
import { recordedTests } from "../recorded-test"
|
|
|
|
const cases = [
|
|
{
|
|
name: "OpenRouter",
|
|
model: OpenRouter.configure({
|
|
apiKey: process.env.OPENROUTER_API_KEY ?? "fixture",
|
|
providerOptions: { openrouter: { reasoning: { max_tokens: 1024 } } },
|
|
}).model("anthropic/claude-sonnet-4.6"),
|
|
requires: ["OPENROUTER_API_KEY"],
|
|
cassette: "openrouter-reasoning",
|
|
},
|
|
{
|
|
name: "Vercel AI Gateway",
|
|
model: OpenAICompatible.configure({
|
|
provider: "vercel-ai-gateway",
|
|
baseURL: "https://ai-gateway.vercel.sh/v1",
|
|
apiKey: process.env.AI_GATEWAY_API_KEY ?? "fixture",
|
|
http: { body: { reasoning: { enabled: true, max_tokens: 1024 } } },
|
|
}).model("anthropic/claude-sonnet-4.6"),
|
|
requires: ["AI_GATEWAY_API_KEY"],
|
|
cassette: "vercel-ai-gateway-reasoning",
|
|
},
|
|
] as const
|
|
|
|
for (const item of cases) {
|
|
const recorded = recordedTests({
|
|
prefix: "openai-compatible-chat",
|
|
provider: item.model.provider,
|
|
protocol: "openai-chat",
|
|
requires: item.requires,
|
|
tags: ["reasoning"],
|
|
metadata: { model: item.model.id },
|
|
})
|
|
|
|
describe(`${item.name} reasoning recorded`, () => {
|
|
recorded.effect.with(
|
|
"streams scalar reasoning",
|
|
{ cassette: item.cassette },
|
|
() =>
|
|
Effect.gen(function* () {
|
|
const response = yield* LLMClient.generate(
|
|
LLM.request({
|
|
model: item.model,
|
|
system: "Think through the arithmetic, then reply with only the final integer.",
|
|
prompt: "What is 173 multiplied by 219?",
|
|
generation: { maxTokens: 1536, temperature: 0 },
|
|
}),
|
|
)
|
|
|
|
expect(response.text.replaceAll(",", "").trim()).toBe("37887")
|
|
expect(response.reasoning.length).toBeGreaterThan(0)
|
|
expect(response.events.some(LLMEvent.is.reasoningDelta)).toBe(true)
|
|
expect(response.message.content.find((part) => part.type === "reasoning")?.providerMetadata).toEqual({
|
|
openai: { reasoningField: "reasoning" },
|
|
})
|
|
}),
|
|
30_000,
|
|
)
|
|
})
|
|
}
|