web-fetch.ts

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: GPL-3.0-or-later
 4
 5import { Type } from "@sinclair/typebox";
 6import type { AgentTool } from "@mariozechner/pi-agent-core";
 7import Tabstack from "@tabstack/sdk";
 8import { FetchError, ToolInputError } from "../../util/errors.js";
 9
10export interface WebFetchResult {
11  content: string;
12  url: string;
13}
14
15const FetchSchema = Type.Object({
16  url: Type.String({ description: "URL to fetch" }),
17  nocache: Type.Optional(Type.Boolean({ description: "Bypass cache and fetch fresh content" })),
18});
19
20export function createWebFetchTool(apiKey: string): AgentTool {
21  return {
22    name: "web_fetch",
23    label: "Web Fetch",
24    description: "Fetch a URL and return its content as markdown.",
25    parameters: FetchSchema as any,
26    execute: async (_toolCallId: string, params: any) => {
27      if (!apiKey) {
28        throw new ToolInputError("Web fetch is not configured");
29      }
30
31      const client = new Tabstack({ apiKey });
32
33      try {
34        const result = await client.extract.markdown({
35          url: params.url,
36          nocache: params.nocache ?? false,
37        });
38
39        return {
40          content: [{ type: "text", text: result.content ?? "" }],
41          details: { url: params.url, length: result.content?.length ?? 0 },
42        };
43      } catch (error: any) {
44        throw new FetchError(params.url, error?.message ?? String(error));
45      }
46    },
47  };
48}