mirror of
https://fastgit.cc/https://github.com/anomalyco/opencode
synced 2026-04-23 10:23:09 +08:00
110 lines
3.7 KiB
TypeScript
110 lines
3.7 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import path from "path"
|
|
import { Effect } from "effect"
|
|
import { FetchHttpClient } from "effect/unstable/http"
|
|
import { Instance } from "../../src/project/instance"
|
|
import { WebFetchTool } from "../../src/tool/webfetch"
|
|
import { SessionID, MessageID } from "../../src/session/schema"
|
|
|
|
const projectRoot = path.join(import.meta.dir, "../..")
|
|
|
|
const ctx = {
|
|
sessionID: SessionID.make("ses_test"),
|
|
messageID: MessageID.make("message"),
|
|
callID: "",
|
|
agent: "build",
|
|
abort: AbortSignal.any([]),
|
|
messages: [],
|
|
metadata: () => {},
|
|
ask: () => Effect.void,
|
|
}
|
|
|
|
async function withFetch(fetch: (req: Request) => Response | Promise<Response>, fn: (url: URL) => Promise<void>) {
|
|
using server = Bun.serve({ port: 0, fetch })
|
|
await fn(server.url)
|
|
}
|
|
|
|
function initTool() {
|
|
return WebFetchTool.pipe(
|
|
Effect.flatMap((info) => Effect.promise(() => info.init())),
|
|
Effect.provide(FetchHttpClient.layer),
|
|
Effect.runPromise,
|
|
)
|
|
}
|
|
|
|
describe("tool.webfetch", () => {
|
|
test("returns image responses as file attachments", async () => {
|
|
const bytes = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10])
|
|
await withFetch(
|
|
() => new Response(bytes, { status: 200, headers: { "content-type": "IMAGE/PNG; charset=binary" } }),
|
|
async (url) => {
|
|
await Instance.provide({
|
|
directory: projectRoot,
|
|
fn: async () => {
|
|
const webfetch = await initTool()
|
|
const result = await Effect.runPromise(
|
|
webfetch.execute({ url: new URL("/image.png", url).toString(), format: "markdown" }, ctx),
|
|
)
|
|
expect(result.output).toBe("Image fetched successfully")
|
|
expect(result.attachments).toBeDefined()
|
|
expect(result.attachments?.length).toBe(1)
|
|
expect(result.attachments?.[0].type).toBe("file")
|
|
expect(result.attachments?.[0].mime).toBe("image/png")
|
|
expect(result.attachments?.[0].url.startsWith("data:image/png;base64,")).toBe(true)
|
|
expect(result.attachments?.[0]).not.toHaveProperty("id")
|
|
expect(result.attachments?.[0]).not.toHaveProperty("sessionID")
|
|
expect(result.attachments?.[0]).not.toHaveProperty("messageID")
|
|
},
|
|
})
|
|
},
|
|
)
|
|
})
|
|
|
|
test("keeps svg as text output", async () => {
|
|
const svg = '<svg xmlns="http://www.w3.org/2000/svg"><text>hello</text></svg>'
|
|
await withFetch(
|
|
() =>
|
|
new Response(svg, {
|
|
status: 200,
|
|
headers: { "content-type": "image/svg+xml; charset=UTF-8" },
|
|
}),
|
|
async (url) => {
|
|
await Instance.provide({
|
|
directory: projectRoot,
|
|
fn: async () => {
|
|
const webfetch = await initTool()
|
|
const result = await Effect.runPromise(
|
|
webfetch.execute({ url: new URL("/image.svg", url).toString(), format: "html" }, ctx),
|
|
)
|
|
expect(result.output).toContain("<svg")
|
|
expect(result.attachments).toBeUndefined()
|
|
},
|
|
})
|
|
},
|
|
)
|
|
})
|
|
|
|
test("keeps text responses as text output", async () => {
|
|
await withFetch(
|
|
() =>
|
|
new Response("hello from webfetch", {
|
|
status: 200,
|
|
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
}),
|
|
async (url) => {
|
|
await Instance.provide({
|
|
directory: projectRoot,
|
|
fn: async () => {
|
|
const webfetch = await initTool()
|
|
const result = await Effect.runPromise(
|
|
webfetch.execute({ url: new URL("/file.txt", url).toString(), format: "text" }, ctx),
|
|
)
|
|
expect(result.output).toBe("hello from webfetch")
|
|
expect(result.attachments).toBeUndefined()
|
|
},
|
|
})
|
|
},
|
|
)
|
|
})
|
|
})
|