Ctrl K
ComunidadGuías…

packages/ai/test/exports.test.ts

Rama dev · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { describe, expect, test } from "bun:test"
import { Effect, Layer } from "effect"
import {
  ai,
  AIClient,
  AIError,
  DecisionClient,
  EmbeddingClient,
  Generation,
  ImageClient,
  LanguageModel,
  LLMClient,
  LLMEvent,
  Media,
  RawEvent,
} from "@opencode/ai/effect"
import { AI } from "@opencode/ai"
import { Speech, SpeechClient, SpeechEvent, TranscriptionClient, Video, VideoClient } from "@opencode/ai/experimental"
import { Route, Protocol, RequestExecutor, WebSocketTransport } from "@opencode/ai/route"
import {
  Alibaba,
  AssemblyAI,
  Baseten,
  Cartesia,
  CloudflareAIGateway,
  CloudflareWorkersAI,
  Deepgram,
  DeepSeek,
  DigitalOcean,
  ElevenLabs,
  Fireworks,
  Google,
  Meta,
  MiniMax,
  OpenCode,
  OpenAI,
  OpenAICompatible,
  OpenRouter,
  Runway,
  TypeSafeAI,
  VercelAIGateway,
  XAI,
  ZAI,
} from "@opencode/ai/providers"
import {
  AnthropicMessages,
  OpenAIChat,
  OpenAICompatibleChat,
  OpenAICompatibleResponses,
  OpenAIResponses,
  OpenResponses,
  OpenResponsesChannel,
} from "@opencode/ai/protocols"
import { TestLLM } from "@opencode/ai/testing"

describe("public exports", () => {
  test("modality, provider, and protocol entrypoints load first in a fresh process", async () => {
    const results = await Promise.all(
      ["image", "video", "speech", "transcription", "providers", "protocols"].map(async (entry) => {
        const child = Bun.spawn(
          [process.execPath, "-e", `await import(${JSON.stringify(`${import.meta.dir}/../src/${entry}.ts`)})`],
          { stderr: "pipe" },
        )
        return { entry, exitCode: await child.exited, stderr: await new Response(child.stderr).text() }
      }),
    )
    expect(results.filter((result) => result.exitCode !== 0)).toEqual([])
  })

  test("root exposes app-facing runtime APIs", () => {
    expect(ai.request).toBeFunction()
    expect(LLMClient.Service).toBeFunction()
    expect(LLMClient.layer).toBeDefined()
    expect(AIError).toBeFunction()
    expect(LanguageModel.make).toBeFunction()
    expect(Media.bytes).toBeFunction()
    expect(ai.image.generate).toBeFunction()
    expect(Video.start).toBeFunction()
    expect(Video.resume).toBeFunction()
    expect(VideoClient.layer).toBeDefined()
    expect(Speech.generate).toBeFunction()
    expect(Speech.stream).toBeFunction()
    expect(SpeechClient.layer).toBeDefined()
    expect(SpeechEvent.is.audioDelta).toBeFunction()
    expect(Generation).toBeFunction()
    expect(TestLLM.testLayer).toBeFunction()
    expect(TestLLM.Test.of).toBeFunction()
    expect(ai.decision.generate).toBeFunction()
    expect(DecisionClient.layer).toBeDefined()
    expect(DecisionClient.fetchLayer).toBeDefined()
    expect(ai.embedding.generate).toBeFunction()
    expect(EmbeddingClient.layer).toBeDefined()
    expect(AI.ai.embedding.generate).toBeFunction()
  })

  test("both entry points export the raw event type", () => {
    const event: RawEvent = LLMEvent.raw({ data: { type: "ping" } })
    const promiseEvent: AI.RawEvent = event
    expect(RawEvent).toBe(AI.RawEvent)
    expect(LLMEvent.is.raw(promiseEvent)).toBe(true)
  })

  test("AIClient.layerWith shares one executor across every client", async () => {
    let built = 0
    const counting = Layer.effect(
      RequestExecutor.Service,
      Effect.sync(() => {
        built++
        return RequestExecutor.Service.of({ execute: () => Effect.die("unexpected request") })
      }),
    )
    await Effect.runPromise(
      Effect.gen(function* () {
        yield* LLMClient.Service
        yield* ImageClient.Service
        yield* VideoClient.Service
        yield* SpeechClient.Service
        yield* TranscriptionClient.Service
        yield* DecisionClient.Service
        yield* EmbeddingClient.Service
        yield* RequestExecutor.Service
      }).pipe(Effect.provide(AIClient.layerWith(counting))),
    )
    expect(built).toBe(1)
  })

  test("route barrel exposes route-authoring APIs", () => {
    expect(Route.make).toBeFunction()
    expect(Protocol.make).toBeFunction()
    expect(WebSocketTransport.makeDirect).toBeFunction()
  })

  test("provider barrels expose user-facing facades", async () => {
    const { OpenAICompatibleResponses } = await import("@opencode/ai/providers")

    expect(OpenAI.model).toBeFunction()
    expect(OpenAI.embedding).toBeFunction()
    expect(OpenAI.provider.responses).toBe(OpenAI.responses)
    expect(OpenAI.configure({ apiKey: "fixture" }).responses).toBeFunction()
    for (const provider of [Baseten, DeepSeek, Fireworks]) {
      expect(provider.configure).toBeFunction()
      expect(provider.model).toBeFunction()
    }
    for (const name of ["baseten", "cerebras", "deepinfra", "deepseek", "fireworks", "groq", "togetherai"]) {
      expect(OpenAICompatible).not.toHaveProperty(name)
    }
    expect(
      OpenAICompatibleResponses.configure({ baseURL: "https://responses.test/v1" }).model("fixture").route.id,
    ).toBe("openai-compatible-responses")
    expect(CloudflareAIGateway.configure).toBeFunction()
    expect(CloudflareAIGateway.configure({ accountId: "fixture", gatewayApiKey: "fixture" }).model).toBeFunction()
    expect(CloudflareWorkersAI.configure).toBeFunction()
    expect(CloudflareWorkersAI.configure({ accountId: "fixture", apiKey: "fixture" }).model).toBeFunction()
    expect(OpenRouter.model).toBeFunction()
    expect(OpenRouter.decision).toBeFunction()
    expect(TypeSafeAI.decision).toBeFunction()
    expect(OpenCode.decision).toBeFunction()
    expect(VercelAIGateway.decision("typesafe-ai/jev").route.id).toBe("openai-decisions")
    expect(Baseten.decision).toBeFunction()
    expect(DigitalOcean.decision).toBeFunction()
    expect(OpenAI.decision("gpt-6-luna").route.id).toBe("openai-decisions")
    expect(XAI.model).toBeFunction()
    expect(XAI.provider.responses).toBe(XAI.responses)
    expect(XAI.provider.chat).toBe(XAI.chat)
    expect(XAI.configure({ apiKey: "fixture" }).responses("grok-4.3").route.id).toBe("xai-responses")
    expect(XAI.configure({ apiKey: "fixture" }).chat("grok-4.3").route.id).toBe("xai-chat")
    expect(OpenAI.configure({ apiKey: "fixture" }).image("gpt-image-2").route.id).toBe("openai-images")
    expect(OpenAI.provider.image).toBe(OpenAI.image)
    expect(Google.configure({ apiKey: "fixture" }).image("imagen-4.0-generate-001").route.id).toBe("google-images")
    expect(Google.provider.image).toBe(Google.image)
    expect(XAI.configure({ apiKey: "fixture" }).image("grok-imagine-image").route.id).toBe("xai-images")
    expect(XAI.provider.image).toBe(XAI.image)
    expect(Meta.configure({ apiKey: "fixture" }).image("muse-image").route.id).toBe("meta-images")
    expect(Meta.provider.image).toBe(Meta.image)
    expect(ZAI.configure({ apiKey: "fixture" }).image("glm-image").route.id).toBe("zai-images")
    expect(ZAI.provider.image).toBe(ZAI.image)
    expect(MiniMax.configure({ apiKey: "fixture" }).image("image-01").route.id).toBe("minimax-images")
    expect(MiniMax.provider.image).toBe(MiniMax.image)
    expect(Alibaba.configure({ region: "ap-southeast-1", apiKey: "fixture" }).image("qwen-image-2.0").route.id).toBe(
      "alibaba-images",
    )
    expect(VercelAIGateway.configure({ apiKey: "fixture" }).image("meta/muse-image-1.0").route.id).toBe("openai-images")
    expect(VercelAIGateway.provider.image).toBe(VercelAIGateway.image)
    expect(
      CloudflareWorkersAI.configure({ accountId: "fixture", apiKey: "fixture" }).image(
        "@cf/black-forest-labs/flux-1-schnell",
      ).route.id,
    ).toBe("cloudflare-workers-ai-images")
    expect(XAI.configure({ apiKey: "fixture" }).video("grok-imagine-video-1.5").route.id).toBe("xai-video")
    expect(XAI.provider.video).toBe(XAI.video)
    expect(Google.configure({ apiKey: "fixture" }).video("veo-3.1-generate-preview").route.id).toBe("google-video")
    expect(Google.provider.video).toBe(Google.video)
    expect(Runway.configure({ apiKey: "fixture" }).video("gen4.5").route.id).toBe("runway-video")
    expect(Runway.provider.video).toBe(Runway.video)
    expect(OpenAI.configure({ apiKey: "fixture" }).speech("gpt-4o-mini-tts").route.id).toBe("openai-speech")
    expect(Google.configure({ apiKey: "fixture" }).speech("gemini-2.5-flash-preview-tts").route.id).toBe(
      "google-speech",
    )
    expect(ElevenLabs.configure({ apiKey: "fixture" }).speech("eleven_flash_v2_5").route.id).toBe("elevenlabs-speech")
    expect(Cartesia.configure({ apiKey: "fixture" }).speech("sonic-3").route.id).toBe("cartesia-speech")
    expect(Deepgram.configure({ apiKey: "fixture" }).speech("aura-2-thalia-en").route.id).toBe("deepgram-speech")
    expect(OpenAI.configure({ apiKey: "fixture" }).transcription("gpt-transcribe").route.kind).toBe("stream")
    expect(Google.configure({ apiKey: "fixture" }).transcription("gemini-3.5-transcribe").route.kind).toBe("stream")
    expect(Deepgram.configure({ apiKey: "fixture" }).transcription("nova-3").route.kind).toBe("inline")
    expect(AssemblyAI.configure({ apiKey: "fixture" }).transcription("universal-3-5-pro").route.kind).toBe("queued")
    expect(ElevenLabs.configure({ apiKey: "fixture" }).transcription("scribe_v2").route.id).toBe(
      "elevenlabs-transcription",
    )
    expect(ElevenLabs.configure({ apiKey: "fixture" }).transcription("scribe_v2").route.kind).toBe("inline")
    expect(ElevenLabs.provider.transcription).toBe(ElevenLabs.transcription)
  })

  test("protocol barrels expose supported low-level routes", () => {
    expect(OpenAIChat.route.id).toBe("openai-chat")
    expect(OpenAICompatibleChat.route.id).toBe("openai-compatible-chat")
    expect(OpenResponses.protocol.id).toBe("open-responses")
    expect(OpenResponsesChannel.transport).toBeFunction()
    expect(OpenAICompatibleResponses.route.id).toBe("openai-compatible-responses")
    expect(OpenAICompatibleResponses.route.protocol).toBe("open-responses")
    expect(OpenAIResponses.route.id).toBe("openai-responses")
    expect(AnthropicMessages.route.id).toBe("anthropic-messages")
  })
})