feat(FN-3758): align web fetch test coverage and documentation
Aligns web fetch tool test coverage across multiple test suites and updates the agents documentation, with a patch changeset for `@runfusion/fusion`. Fusion-Task-Id: FN-3758
This commit is contained in:
43
packages/cli/src/__tests__/extension-web-fetch.test.ts
Normal file
43
packages/cli/src/__tests__/extension-web-fetch.test.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
const fetchWebContentMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("@fusion/engine", () => ({
|
||||
fetchWebContent: fetchWebContentMock,
|
||||
}));
|
||||
|
||||
import kbExtension from "../extension.js";
|
||||
|
||||
describe("extension fn_web_fetch", () => {
|
||||
it("registers and executes fn_web_fetch", async () => {
|
||||
const tools = new Map<string, any>();
|
||||
const api = {
|
||||
registerTool(def: any) {
|
||||
tools.set(def.name, def);
|
||||
},
|
||||
registerCommand: vi.fn(),
|
||||
registerShortcut: vi.fn(),
|
||||
registerFlag: vi.fn(),
|
||||
on: vi.fn(),
|
||||
} as any;
|
||||
|
||||
fetchWebContentMock.mockResolvedValue({
|
||||
finalUrl: "https://example.com/final",
|
||||
status: 200,
|
||||
contentType: "text/plain",
|
||||
title: "Example",
|
||||
content: "hello world",
|
||||
truncated: false,
|
||||
bytesRead: 11,
|
||||
});
|
||||
|
||||
kbExtension(api);
|
||||
const tool = tools.get("fn_web_fetch");
|
||||
expect(tool).toBeTruthy();
|
||||
|
||||
const result = await tool.execute("id", { url: "https://example.com" }, undefined, undefined, { cwd: process.cwd() });
|
||||
expect(fetchWebContentMock).toHaveBeenCalledWith("https://example.com", { timeoutMs: undefined, maxBytes: undefined });
|
||||
expect(result.content[0].text).toContain("https://example.com/final");
|
||||
expect(result.details.status).toBe(200);
|
||||
});
|
||||
});
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
isGhAvailable,
|
||||
runGhJsonAsync,
|
||||
} from "@fusion/core/gh-cli";
|
||||
import { fetchWebContent } from "@fusion/engine";
|
||||
import { resolve, basename, extname, join } from "node:path";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { existsSync } from "node:fs";
|
||||
@@ -1363,6 +1364,54 @@ export default function kbExtension(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
pi.registerTool({
|
||||
name: "fn_web_fetch",
|
||||
label: "fn: Web Fetch",
|
||||
description: "Lightweight URL fetch (no JS rendering). Use agent-browser skill for JS-heavy pages.",
|
||||
parameters: Type.Object({
|
||||
url: Type.String({ description: "URL to fetch (http/https)" }),
|
||||
prompt: Type.Optional(Type.String({ description: "Optional extraction hint for downstream summarization" })),
|
||||
timeoutMs: Type.Optional(Type.Number({ description: "Timeout in milliseconds (default: 30000)" })),
|
||||
maxBytes: Type.Optional(Type.Number({ description: "Max bytes to return (default: 512000)" })),
|
||||
}),
|
||||
promptSnippet: "Fetch and extract readable text from a webpage URL",
|
||||
promptGuidelines: [
|
||||
"Use for lightweight GET requests where JS rendering is not required.",
|
||||
"For JS-rendered pages or complex browsing flows, use agent-browser skill instead.",
|
||||
],
|
||||
async execute(_toolCallId, params) {
|
||||
const result = await fetchWebContent(params.url, {
|
||||
timeoutMs: params.timeoutMs,
|
||||
maxBytes: params.maxBytes,
|
||||
});
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: [
|
||||
`URL: ${result.finalUrl}`,
|
||||
`Status: ${result.status}`,
|
||||
`Content-Type: ${result.contentType}`,
|
||||
params.prompt ? `Prompt: ${params.prompt}` : undefined,
|
||||
result.title ? `Title: ${result.title}` : undefined,
|
||||
"",
|
||||
result.content,
|
||||
result.truncated ? "\n[truncated to maxBytes]" : "",
|
||||
].filter(Boolean).join("\n"),
|
||||
}],
|
||||
details: {
|
||||
finalUrl: result.finalUrl,
|
||||
status: result.status,
|
||||
contentType: result.contentType,
|
||||
title: result.title,
|
||||
truncated: result.truncated,
|
||||
bytesRead: result.bytesRead,
|
||||
promptSnippet: params.prompt ? params.prompt.slice(0, 200) : undefined,
|
||||
promptGuidelines: "Lightweight fetch only; for JS-rendered pages, use agent-browser skill.",
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
// ── Research Tools ──────────────────────────────────────────────
|
||||
|
||||
pi.registerTool({
|
||||
|
||||
Reference in New Issue
Block a user