Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134import { runWeb } from "./web-errors";import { readBrowserPage, browserProgress } from "./browser-read";import type { BrowserLeaseHooks } from "./browser-session";import { tool } from "ai";import { z } from "zod";import type { BrowserBinding } from "agents/browser";import type { ToolActivityDescriptor } from "./tool-activity";import { readWebUrl } from "./web-read";import { searchWeb } from "./web-search";
// Code Mode includes this schema in the generated method types, so code can// follow sources and branch on failures without guessing the result shape.const webOutput = z.union([ z.object({ ok: z.literal(true), sources: z.array( z.object({ id: z.string(), title: z.string(), requestedUrl: z.string(), finalUrl: z.string(), fetchedAt: z.string(), sourceKind: z.enum(["search", "page", "browser"]), content: z.string(), contentType: z.string().optional(), links: z .array(z.object({ url: z.string(), title: z.string() })) .optional(), truncated: z.boolean(), }), ), generatedSummary: z .object({ text: z.string(), truncated: z.boolean() }) .optional(), }), z.object({ ok: z.literal(false), code: z.string(), message: z.string(), status: z.number().optional(), }),]);
export const webActivityDescriptors: Record<string, ToolActivityDescriptor> = { browser_read: { kind: "browser", label: "Read rendered webpage", outputSummary: () => "Rendered webpage read", outcome: (output) => (output as { ok?: boolean })?.ok === true ? "succeeded" : "failed", progress: (value) => typeof value === "number" && Number.isInteger(value) && value >= 0 && value < browserProgress.length ? { text: browserProgress[value], completed: value, total: browserProgress.length - 1, } : undefined, }, web_search: { kind: "web", label: "Search the web", outputSummary: () => "Web search finished", outcome: (output) => (output as { ok?: boolean })?.ok === true ? "succeeded" : "failed", }, read_url: { kind: "web", label: "Read webpage", outputSummary: () => "Webpage reading finished", outcome: (output) => (output as { ok?: boolean })?.ok === true ? "succeeded" : "failed", },};export function createWebTools( browser: BrowserBinding, ai: Ai, keepAlive: (promise: Promise<unknown>) => void, browserOptions?: { lease: () => BrowserLeaseHooks; progress: (id: string, stage: number) => void; },) { return { browser_read: tool({ outputSchema: webOutput, description: "Render a public HTTP(S) webpage with JavaScript when read_url lacks the needed content. Returns bounded visible text, exact final source URL, and up to 20 links for follow-up calls. Optionally wait for a CSS selector within a 30-second total deadline. Each call uses a fresh browser; no login, clicks, or persistent session.", inputSchema: z .object({ url: z.string().min(1).max(4096), waitForSelector: z.string().trim().min(1).max(300).optional(), }) .strict(), execute: (input, { abortSignal, toolCallId }) => runWeb( readBrowserPage( browser, input, abortSignal, keepAlive, browserOptions?.lease(), (stage) => browserOptions?.progress(toolCallId, stage), ), abortSignal, ), }), web_search: tool({ outputSchema: webOutput, description: "Search the public web for up to 5 sources using OpenAI through Cloudflare AI Gateway. Returns provider citation URLs and a separately labeled AI-generated summary, not read page content or verbatim excerpts. Requires AI Gateway credits; never treat failures as no results.", inputSchema: z .object({ query: z.string().trim().min(1).max(500), limit: z.number().int().min(1).max(5).default(5), }) .strict(), execute: ({ query, limit }, { abortSignal }) => runWeb(searchWeb(ai, query, limit), abortSignal), }), read_url: tool({ outputSchema: webOutput, description: "Read one public HTTP(S) URL as bounded HTML text, Markdown or plain text. Returns source metadata and content for citation; does not execute JavaScript or read PDFs.", inputSchema: z.object({ url: z.string().min(1).max(4096) }).strict(), execute: ({ url }, options) => runWeb(readWebUrl(url, options), options.abortSignal), }), };}