Ctrl K
ComunidadGuías…

packages/ai/test/media-input.test.ts

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

Archivo original ↗Preguntar a KiBot
import { describe, expect, test } from "bun:test"
import { Base64 } from "effect/encoding"
import { ai, AIError, Media, Message } from "../src/effect.js"
import { OpenAI, OpenCode } from "../src/providers.js"

const PNG = Uint8Array.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0, 0, 0, 0])
const PNG_BASE64 = Base64.encode(PNG)
const UNKNOWN = Uint8Array.from([1, 2, 3])

describe("Media.make", () => {
  test("passes assets through", () => {
    const asset = Media.url("https://example.test/a.png")
    expect(Media.make(asset)).toBe(asset)
  })

  test("sniffs bytes and array buffers", () => {
    expect(Media.make(PNG).source).toEqual({ type: "bytes", data: PNG, mediaType: "image/png" })
    expect(Media.make(PNG.slice().buffer).source).toEqual({ type: "bytes", data: PNG, mediaType: "image/png" })
    expect(Media.make(UNKNOWN, "application/x-thing").mediaType).toBe("application/x-thing")
  })

  test("reads the media type from data URLs", () => {
    expect(Media.make(`data:image/png;base64,${PNG_BASE64}`).source).toEqual({
      type: "base64",
      data: PNG_BASE64,
      mediaType: "image/png",
    })
    expect(Media.make(new URL(`data:image/webp;base64,${PNG_BASE64}`)).mediaType).toBe("image/webp")
  })

  test("keeps http(s) and other URLs as url sources", () => {
    expect(Media.make("https://example.test/a.png", "image/png").source).toEqual({
      type: "url",
      url: "https://example.test/a.png",
      mediaType: "image/png",
    })
    expect(Media.make(new URL("gs://bucket/a.pdf")).source).toEqual({ type: "url", url: "gs://bucket/a.pdf" })
  })

  test("treats other strings as base64", () => {
    expect(Media.make(PNG_BASE64).source).toEqual({ type: "base64", data: PNG_BASE64, mediaType: "image/png" })
    expect(Media.make("AQID", "application/pdf").mediaType).toBe("application/pdf")
  })

  test("requires a mediaType when the type cannot be detected", () => {
    expect(() => Media.make(UNKNOWN)).toThrow(AIError)
    expect(() => Media.make("AQID")).toThrow(AIError)
    expect(() => Media.make("data:text/plain,hello")).toThrow(AIError)
  })

  test("rejects strings that are not base64", () => {
    expect(() => Media.make("./photo.png", "image/png")).toThrow("Media.file")
  })

  test("matches the data URL scheme in any case", () => {
    expect(Media.make(`DATA:image/png;base64,${PNG_BASE64}`).mediaType).toBe("image/png")
  })
})

describe("plain file input", () => {
  test("request media parts accept plain data", () => {
    const request = ai.request({
      model: OpenAI.configure({ apiKey: "test" }).chat("gpt-4o-mini"),
      prompt: [
        { type: "text", text: "Describe these" },
        { type: "media", media: PNG, filename: "a.png" },
        { type: "media", media: "AQID", mediaType: "application/pdf" },
        Message.media(new URL("https://example.test/a.png")),
      ],
    })
    const parts = request.messages[0].content
    expect(parts[1]).toEqual({ type: "media", media: Media.bytes(PNG, "image/png"), filename: "a.png" })
    expect(parts[2]).toEqual({ type: "media", media: Media.base64("AQID", "application/pdf") })
    expect(parts[3]).toEqual({ type: "media", media: Media.url("https://example.test/a.png") })
  })

  test("image edit inputs accept plain data", () => {
    const request = ai.image.request({
      model: OpenAI.configure({ apiKey: "test" }).image("gpt-image-2"),
      prompt: "Make it blue",
      images: [PNG, `data:image/png;base64,${PNG_BASE64}`, "https://example.test/a.png"],
    })
    expect(request.images?.map((image) => image.source.type)).toEqual(["bytes", "base64", "url"])
    expect(request.images?.[0].mediaType).toBe("image/png")
  })

  test("decision media parts accept plain data", () => {
    const request = ai.decision.request({
      model: OpenCode.configure({ apiKey: "test" }).decision("jev-1.13"),
      input: [
        { type: "text", text: "Is this a receipt?" },
        { type: "media", media: "AQID", mediaType: "image/png", filename: "a.png" },
      ],
      questions: [{ name: "receipt", type: "predicate", instructions: "Is this a receipt?" }],
    })
    expect(request.input[1]).toEqual({ type: "media", media: Media.base64("AQID", "image/png"), filename: "a.png" })
  })
})