test: migrate webfetch tool tests to effect runner (#27171)
This commit is contained in:
@@ -1,15 +1,14 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect } from "bun:test"
|
||||||
import path from "path"
|
|
||||||
import { Effect, Layer } from "effect"
|
import { Effect, Layer } from "effect"
|
||||||
import { FetchHttpClient } from "effect/unstable/http"
|
import { FetchHttpClient } from "effect/unstable/http"
|
||||||
import { Agent } from "../../src/agent/agent"
|
import { Agent } from "../../src/agent/agent"
|
||||||
import { Truncate } from "@/tool/truncate"
|
import { Truncate } from "@/tool/truncate"
|
||||||
import { Instance } from "../../src/project/instance"
|
|
||||||
import { WithInstance } from "../../src/project/with-instance"
|
|
||||||
import { WebFetchTool } from "../../src/tool/webfetch"
|
import { WebFetchTool } from "../../src/tool/webfetch"
|
||||||
import { SessionID, MessageID } from "../../src/session/schema"
|
import { SessionID, MessageID } from "../../src/session/schema"
|
||||||
|
import { Tool } from "@/tool/tool"
|
||||||
|
import { testEffect } from "../lib/effect"
|
||||||
|
|
||||||
const projectRoot = path.join(import.meta.dir, "../..")
|
const it = testEffect(Layer.mergeAll(FetchHttpClient.layer, Truncate.defaultLayer, Agent.defaultLayer))
|
||||||
|
|
||||||
const ctx = {
|
const ctx = {
|
||||||
sessionID: SessionID.make("ses_test"),
|
sessionID: SessionID.make("ses_test"),
|
||||||
@@ -22,30 +21,31 @@ const ctx = {
|
|||||||
ask: () => Effect.void,
|
ask: () => Effect.void,
|
||||||
}
|
}
|
||||||
|
|
||||||
async function withFetch(fetch: (req: Request) => Response | Promise<Response>, fn: (url: URL) => Promise<void>) {
|
const withFetch = <A, E, R>(
|
||||||
using server = Bun.serve({ port: 0, fetch })
|
fetch: (req: Request) => Response | Promise<Response>,
|
||||||
await fn(server.url)
|
fn: (url: URL) => Effect.Effect<A, E, R>,
|
||||||
}
|
) =>
|
||||||
|
Effect.acquireUseRelease(
|
||||||
function exec(args: { url: string; format: "text" | "markdown" | "html" }) {
|
Effect.sync(() => Bun.serve({ port: 0, fetch })),
|
||||||
return WebFetchTool.pipe(
|
(server) => fn(server.url),
|
||||||
Effect.flatMap((info) => info.init()),
|
(server) => Effect.sync(() => server.stop(true)),
|
||||||
Effect.flatMap((tool) => tool.execute(args, ctx)),
|
|
||||||
Effect.provide(Layer.mergeAll(FetchHttpClient.layer, Truncate.defaultLayer, Agent.defaultLayer)),
|
|
||||||
Effect.runPromise,
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
const exec = Effect.fn("WebFetchToolTest.exec")(function* (args: Tool.InferParameters<typeof WebFetchTool>) {
|
||||||
|
const info = yield* WebFetchTool
|
||||||
|
const tool = yield* info.init()
|
||||||
|
return yield* tool.execute(args, ctx)
|
||||||
|
})
|
||||||
|
|
||||||
describe("tool.webfetch", () => {
|
describe("tool.webfetch", () => {
|
||||||
test("returns image responses as file attachments", async () => {
|
it.instance("returns image responses as file attachments", () =>
|
||||||
const bytes = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10])
|
Effect.gen(function* () {
|
||||||
await withFetch(
|
const bytes = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10])
|
||||||
() => new Response(bytes, { status: 200, headers: { "content-type": "IMAGE/PNG; charset=binary" } }),
|
yield* withFetch(
|
||||||
async (url) => {
|
() => new Response(bytes, { status: 200, headers: { "content-type": "IMAGE/PNG; charset=binary" } }),
|
||||||
await WithInstance.provide({
|
(url) =>
|
||||||
directory: projectRoot,
|
Effect.gen(function* () {
|
||||||
fn: async () => {
|
const result = yield* exec({ url: new URL("/image.png", url).toString(), format: "markdown" })
|
||||||
const result = await exec({ url: new URL("/image.png", url).toString(), format: "markdown" })
|
|
||||||
expect(result.output).toBe("Image fetched successfully")
|
expect(result.output).toBe("Image fetched successfully")
|
||||||
expect(result.attachments).toBeDefined()
|
expect(result.attachments).toBeDefined()
|
||||||
expect(result.attachments?.length).toBe(1)
|
expect(result.attachments?.length).toBe(1)
|
||||||
@@ -55,50 +55,40 @@ describe("tool.webfetch", () => {
|
|||||||
expect(result.attachments?.[0]).not.toHaveProperty("id")
|
expect(result.attachments?.[0]).not.toHaveProperty("id")
|
||||||
expect(result.attachments?.[0]).not.toHaveProperty("sessionID")
|
expect(result.attachments?.[0]).not.toHaveProperty("sessionID")
|
||||||
expect(result.attachments?.[0]).not.toHaveProperty("messageID")
|
expect(result.attachments?.[0]).not.toHaveProperty("messageID")
|
||||||
},
|
}),
|
||||||
})
|
)
|
||||||
},
|
}),
|
||||||
)
|
)
|
||||||
})
|
|
||||||
|
|
||||||
test("keeps svg as text output", async () => {
|
it.instance("keeps svg as text output", () =>
|
||||||
const svg = '<svg xmlns="http://www.w3.org/2000/svg"><text>hello</text></svg>'
|
withFetch(
|
||||||
await withFetch(
|
|
||||||
() =>
|
() =>
|
||||||
new Response(svg, {
|
new Response('<svg xmlns="http://www.w3.org/2000/svg"><text>hello</text></svg>', {
|
||||||
status: 200,
|
status: 200,
|
||||||
headers: { "content-type": "image/svg+xml; charset=UTF-8" },
|
headers: { "content-type": "image/svg+xml; charset=UTF-8" },
|
||||||
}),
|
}),
|
||||||
async (url) => {
|
(url) =>
|
||||||
await WithInstance.provide({
|
Effect.gen(function* () {
|
||||||
directory: projectRoot,
|
const result = yield* exec({ url: new URL("/image.svg", url).toString(), format: "html" })
|
||||||
fn: async () => {
|
expect(result.output).toContain("<svg")
|
||||||
const result = await exec({ url: new URL("/image.svg", url).toString(), format: "html" })
|
expect(result.attachments).toBeUndefined()
|
||||||
expect(result.output).toContain("<svg")
|
}),
|
||||||
expect(result.attachments).toBeUndefined()
|
),
|
||||||
},
|
)
|
||||||
})
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("keeps text responses as text output", async () => {
|
it.instance("keeps text responses as text output", () =>
|
||||||
await withFetch(
|
withFetch(
|
||||||
() =>
|
() =>
|
||||||
new Response("hello from webfetch", {
|
new Response("hello from webfetch", {
|
||||||
status: 200,
|
status: 200,
|
||||||
headers: { "content-type": "text/plain; charset=utf-8" },
|
headers: { "content-type": "text/plain; charset=utf-8" },
|
||||||
}),
|
}),
|
||||||
async (url) => {
|
(url) =>
|
||||||
await WithInstance.provide({
|
Effect.gen(function* () {
|
||||||
directory: projectRoot,
|
const result = yield* exec({ url: new URL("/file.txt", url).toString(), format: "text" })
|
||||||
fn: async () => {
|
expect(result.output).toBe("hello from webfetch")
|
||||||
const result = await exec({ url: new URL("/file.txt", url).toString(), format: "text" })
|
expect(result.attachments).toBeUndefined()
|
||||||
expect(result.output).toBe("hello from webfetch")
|
}),
|
||||||
expect(result.attachments).toBeUndefined()
|
),
|
||||||
},
|
)
|
||||||
})
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user