mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-23 02:36:57 -04:00
b6f85c2250
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
112 lines
3.8 KiB
TypeScript
112 lines
3.8 KiB
TypeScript
import { expect } from "bun:test"
|
|
import { LLMClient, LLMEvent, LLMResponse, Model } from "@opencode-ai/ai"
|
|
import { OpenAIChat } from "@opencode-ai/ai/protocols"
|
|
import { AISDK } from "@opencode-ai/core/aisdk"
|
|
import { Catalog } from "@opencode-ai/core/catalog"
|
|
import { Generate } from "@opencode-ai/core/generate"
|
|
import { Integration } from "@opencode-ai/core/integration"
|
|
import { ModelResolver } from "@opencode-ai/core/model-resolver"
|
|
import { ModelV2 } from "@opencode-ai/core/model"
|
|
import { ProviderV2 } from "@opencode-ai/core/provider"
|
|
import { Npm } from "@opencode-ai/util/npm"
|
|
import { Effect, Layer, Stream } from "effect"
|
|
import { testEffect } from "./lib/effect"
|
|
|
|
const selected = ModelV2.Info.make({
|
|
...ModelV2.Info.default(ProviderV2.ID.make("test-provider"), ModelV2.ID.make("gemini")),
|
|
package: ProviderV2.aisdk("@ai-sdk/google"),
|
|
})
|
|
const runtime = Model.make({ id: "gemini", provider: "test-provider", route: OpenAIChat.route })
|
|
|
|
const catalog = Layer.mock(Catalog.Service, {
|
|
provider: {
|
|
get: () => Effect.succeed(undefined),
|
|
all: () => Effect.die("unused"),
|
|
available: () => Effect.die("unused"),
|
|
},
|
|
model: {
|
|
get: () => Effect.succeed(selected),
|
|
all: () => Effect.die("unused"),
|
|
available: () => Effect.die("unused"),
|
|
default: () => Effect.die("unused"),
|
|
small: () => Effect.die("unused"),
|
|
},
|
|
})
|
|
const integrations = Layer.mock(Integration.Service, {
|
|
connection: {
|
|
active: () => Effect.succeed(undefined),
|
|
resolve: () => Effect.die("unused"),
|
|
key: () => Effect.die("unused"),
|
|
update: () => Effect.die("unused"),
|
|
remove: () => Effect.die("unused"),
|
|
},
|
|
oauth: {
|
|
connect: () => Effect.die("unused"),
|
|
status: () => Effect.die("unused"),
|
|
complete: () => Effect.die("unused"),
|
|
cancel: () => Effect.die("unused"),
|
|
},
|
|
command: {
|
|
connect: () => Effect.die("unused"),
|
|
status: () => Effect.die("unused"),
|
|
cancel: () => Effect.die("unused"),
|
|
},
|
|
})
|
|
const npm = Layer.mock(Npm.Service, {
|
|
add: () => Effect.die("unused"),
|
|
install: () => Effect.die("unused"),
|
|
which: () => Effect.die("unused"),
|
|
})
|
|
const aisdk = Layer.mock(AISDK.Service, {
|
|
hook: {
|
|
sdk: () => Effect.die("unused"),
|
|
language: () => Effect.die("unused"),
|
|
},
|
|
model: () => Effect.succeed(runtime),
|
|
})
|
|
const client = Layer.mock(LLMClient.Service)({
|
|
prepare: () => Effect.die("unused"),
|
|
stream: () => Stream.die("unused"),
|
|
generate: () =>
|
|
Effect.sync(() => {
|
|
const response = LLMResponse.fromEvents([
|
|
LLMEvent.textStart({ id: "generate" }),
|
|
LLMEvent.textDelta({ id: "generate", text: "OK" }),
|
|
LLMEvent.textEnd({ id: "generate" }),
|
|
LLMEvent.finish({ reason: "stop" }),
|
|
])
|
|
if (!response) throw new Error("Incomplete generate response")
|
|
return response
|
|
}),
|
|
})
|
|
|
|
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))))
|
|
const resolverIt = testEffect(resolver)
|
|
|
|
it.effect("loads dynamic AI SDK models", () =>
|
|
Effect.gen(function* () {
|
|
const generate = yield* Generate.Service
|
|
const result = yield* generate.text({
|
|
prompt: "Return exactly OK",
|
|
model: ModelV2.Ref.make({ providerID: selected.providerID, id: selected.id }),
|
|
})
|
|
|
|
expect(result).toBe("OK")
|
|
}),
|
|
)
|
|
|
|
resolverIt.effect("resolves dynamic models with their catalog metadata", () =>
|
|
Effect.gen(function* () {
|
|
const resolver = yield* ModelResolver.Service
|
|
const result = yield* resolver.resolve(ModelV2.Ref.make({ providerID: selected.providerID, id: selected.id }))
|
|
|
|
expect(result).toEqual({
|
|
model: runtime,
|
|
ref: ModelV2.Ref.make({ providerID: selected.providerID, id: selected.id }),
|
|
capabilities: selected.capabilities,
|
|
cost: selected.cost,
|
|
})
|
|
}),
|
|
)
|