| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- import { Npm } from "@opencode-ai/core/npm"
- import type { LanguageModelV3 } from "@ai-sdk/provider"
- import { expect } from "bun:test"
- import { Effect, Layer, Option } from "effect"
- import { Catalog } from "@opencode-ai/core/catalog"
- import { EventV2 } from "@opencode-ai/core/event"
- import { Location } from "@opencode-ai/core/location"
- import { ModelV2 } from "@opencode-ai/core/model"
- import { PluginV2 } from "@opencode-ai/core/plugin"
- import { ProviderV2 } from "@opencode-ai/core/provider"
- import { AbsolutePath } from "@opencode-ai/core/schema"
- import { location } from "../fixture/location"
- import { testEffect } from "../lib/effect"
- export const fixtureProvider = new URL("./fixtures/provider-factory.ts", import.meta.url).href
- const locationLayer = Layer.succeed(
- Location.Service,
- Location.Service.of(location({ directory: AbsolutePath.make("test") })),
- )
- export const npmLayer = Layer.succeed(
- Npm.Service,
- Npm.Service.of({
- add: () => Effect.succeed({ directory: "", entrypoint: Option.none<string>() }),
- install: () => Effect.void,
- which: () => Effect.succeed(Option.none<string>()),
- }),
- )
- export const catalogLayer = Layer.succeed(
- Catalog.Service,
- Catalog.Service.of({
- transform: () => Effect.die("unexpected catalog.transform"),
- provider: {
- get: () => Effect.die("unexpected provider.get"),
- all: () => Effect.succeed([]),
- available: () => Effect.succeed([]),
- },
- model: {
- get: () => Effect.die("unexpected model.get"),
- all: () => Effect.succeed([]),
- available: () => Effect.succeed([]),
- default: () => Effect.succeed(Option.none<ModelV2.Info>()),
- small: () => Effect.succeed(Option.none<ModelV2.Info>()),
- },
- }),
- )
- export const it = testEffect(
- Catalog.locationLayer.pipe(
- Layer.provideMerge(EventV2.defaultLayer),
- Layer.provideMerge(locationLayer),
- Layer.provideMerge(npmLayer),
- ),
- )
- type ProviderInput = Partial<Omit<ProviderV2.Info, "api" | "request">> & {
- api?: ProviderV2.Api
- request?: ProviderV2.Request
- }
- type ModelInput = Partial<Omit<ModelV2.Info, "api" | "request">> & {
- api?: (ProviderV2.Api & { id?: ModelV2.ID }) | { id: ModelV2.ID }
- request?: ModelV2.Info["request"]
- }
- export function provider(providerID: string, options?: ProviderInput) {
- return new ProviderV2.Info({
- ...ProviderV2.Info.empty(ProviderV2.ID.make(providerID)),
- api: options?.api ?? {
- type: "aisdk",
- package: "test-provider",
- },
- ...options,
- request: {
- headers: {},
- body: {},
- ...options?.request,
- },
- })
- }
- export function model(providerID: string, modelID: string, options?: ModelInput) {
- return new ModelV2.Info({
- ...ModelV2.Info.empty(ProviderV2.ID.make(providerID), ModelV2.ID.make(modelID)),
- ...options,
- api:
- options?.api && "type" in options.api
- ? { id: ModelV2.ID.make(modelID), ...options.api }
- : {
- id: ModelV2.ID.make(modelID),
- ...options?.api,
- type: "aisdk",
- package: "test-provider",
- },
- request: {
- headers: {},
- body: {},
- ...options?.request,
- },
- })
- }
- export function withEnv<A, E, R>(vars: Record<string, string | undefined>, fx: () => Effect.Effect<A, E, R>) {
- return Effect.acquireUseRelease(
- Effect.sync(() => {
- const previous = Object.fromEntries(Object.keys(vars).map((key) => [key, process.env[key]]))
- for (const [key, value] of Object.entries(vars)) {
- if (value === undefined) delete process.env[key]
- else process.env[key] = value
- }
- return previous
- }),
- () => fx(),
- (previous) =>
- Effect.sync(() => {
- for (const [key, value] of Object.entries(previous)) {
- if (value === undefined) delete process.env[key]
- else process.env[key] = value
- }
- }),
- )
- }
- export function fakeSelectorSdk(calls: string[]) {
- const make = (method: string) => (id: string) => {
- calls.push(`${method}:${id}`)
- return { modelId: id, provider: method, specificationVersion: "v3" } as unknown as LanguageModelV3
- }
- return {
- responses: make("responses"),
- messages: make("messages"),
- chat: make("chat"),
- languageModel: make("languageModel"),
- }
- }
- export function expectPluginRegistered(ids: string[], id: string) {
- expect(ids).toContain(PluginV2.ID.make(id))
- }
|