mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-04 14:19:57 +00:00
test(ai): simplify TestLLM setup
This commit is contained in:
parent
8ce850e142
commit
dc819e04cc
5 changed files with 32 additions and 9 deletions
|
|
@ -214,22 +214,20 @@ the requests sent by code under test:
|
|||
import { Effect } from "effect"
|
||||
import { TestLLM } from "@opencode-ai/ai/testing"
|
||||
|
||||
const testLLM = TestLLM.layer({
|
||||
fallback: TestLLM.text("Hello from the test model", "text-1"),
|
||||
const testLLM = TestLLM.layerWithClient({
|
||||
fallback: TestLLM.text("Hello from the test model"),
|
||||
})
|
||||
|
||||
// TestLLM.clientLayer provides LLMClient.Service and consumes TestLLM.Service.
|
||||
const programWithTestClient = Effect.gen(function* () {
|
||||
const result = yield* program
|
||||
const test = yield* TestLLM.Service
|
||||
console.log(test.requests)
|
||||
console.log(yield* TestLLM.requests)
|
||||
return result
|
||||
}).pipe(Effect.provide(TestLLM.clientLayer), Effect.provide(testLLM))
|
||||
}).pipe(Effect.provide(testLLM))
|
||||
```
|
||||
|
||||
`TestLLM.push(...)` scripts one-shot responses, `TestLLM.always(...)` changes the fallback, and
|
||||
`TestLLM.wait(...)` lets concurrent tests wait until a request has arrived. Every received canonical request is
|
||||
available on the yielded `TestLLM.Service`.
|
||||
available from `TestLLM.requests`.
|
||||
|
||||
## Caching
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const textEvents = (value: string, id: string) => [
|
|||
LLMEvent.textEnd({ id }),
|
||||
]
|
||||
|
||||
export const text = (value: string, id: string) => stop(...textEvents(value, id))
|
||||
export const text = (value: string, id = "text-0") => stop(...textEvents(value, id))
|
||||
|
||||
export const textWithUsage = (value: string, id: string, inputTokens: number) =>
|
||||
complete(
|
||||
|
|
@ -147,6 +147,10 @@ export const clientLayer = Layer.effect(
|
|||
Effect.map(Service, (service) => service.client),
|
||||
)
|
||||
|
||||
export const layerWithClient = (options: LayerOptions = {}) => clientLayer.pipe(Layer.provideMerge(layer(options)))
|
||||
|
||||
export const requests = Service.use((service) => Effect.succeed(service.requests))
|
||||
|
||||
export const push = (...responses: readonly Response[]) => Service.use((service) => service.push(...responses))
|
||||
|
||||
export const always = (response: Response) => Service.use((service) => service.always(response))
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ describe("public exports", () => {
|
|||
expect(Provider.make).toBeFunction()
|
||||
expect(ProviderSubpath.make).toBe(Provider.make)
|
||||
expect(TestLLM.layer).toBeFunction()
|
||||
expect(TestLLM.layerWithClient).toBeFunction()
|
||||
expect(TestLLM.requests).toBeDefined()
|
||||
})
|
||||
|
||||
test("route barrel exposes route-authoring APIs", () => {
|
||||
|
|
|
|||
19
packages/ai/test/testing.test.ts
Normal file
19
packages/ai/test/testing.test.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { LLM, LLMClient, LLMEvent } from "../src"
|
||||
import { OpenAIChat } from "../src/protocols"
|
||||
import { TestLLM } from "../src/testing"
|
||||
import { testEffect } from "./lib/effect"
|
||||
|
||||
const model = OpenAIChat.route.model({ id: "test" })
|
||||
const it = testEffect(TestLLM.layerWithClient({ fallback: TestLLM.text("Hello") }))
|
||||
|
||||
it.effect("provides a client and exposes received requests", () =>
|
||||
Effect.gen(function* () {
|
||||
const response = yield* LLMClient.generate(LLM.request({ model, prompt: "Say hello" }))
|
||||
|
||||
expect(response.text).toBe("Hello")
|
||||
expect(response.events.filter(LLMEvent.is.textDelta)).toEqual([{ type: "text-delta", id: "text-0", text: "Hello" }])
|
||||
expect(yield* TestLLM.requests).toHaveLength(1)
|
||||
}),
|
||||
)
|
||||
|
|
@ -65,7 +65,7 @@ const aisdk = Layer.mock(AISDK.Service, {
|
|||
},
|
||||
model: () => Effect.succeed(runtime),
|
||||
})
|
||||
const client = TestLLM.clientLayer.pipe(Layer.provide(TestLLM.layer({ fallback: TestLLM.text("OK", "generate") })))
|
||||
const client = TestLLM.layerWithClient({ fallback: TestLLM.text("OK") })
|
||||
|
||||
const resolver = ModelResolver.layer.pipe(Layer.provide(Layer.mergeAll(catalog, integrations, npm, aisdk)))
|
||||
const it = testEffect(Generate.layer.pipe(Layer.provide(Layer.merge(resolver, client))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue