feat: custom tool renderers

This commit is contained in:
Zoe
2026-09-25 19:46:00 -05:00
parent 3f81f96bda
commit bb5795e00d
18 changed files with 1294 additions and 65 deletions
+36
View File
@@ -0,0 +1,36 @@
import type { Result } from "../../types/result";
import { z } from "zod";
import { Err, Ok } from "../../types/result";
const scrapeResponseSchema = z.object({
success: z.boolean().optional(),
error: z.union([z.string(), z.object({ message: z.string() })]).optional(),
message: z.string().optional(),
data: z.unknown().optional(),
});
export const readFirecrawlResponse = async (response: Response): Promise<Result<string, string>> => {
const context = `Firecrawl scrape (HTTP ${response.status})`;
let body: unknown;
try {
body = await response.json();
} catch {
return Err(`${context}: received a non-JSON or unreadable response.`);
}
const parsed = scrapeResponseSchema.safeParse(body);
if (!parsed.success) {
return Err(`${context}: received an unexpected response format.`);
}
const payload = parsed.data;
const providerError = typeof payload.error === "string" ? payload.error : payload.error?.message;
if (!response.ok || payload.success === false || providerError) {
return Err(`${context}: ${providerError || payload.message || response.statusText || "Scrape failed without an error message."}`);
}
const content = z.object({ markdown: z.string() }).safeParse(payload.data);
if (!content.success || content.data.markdown.trim() === "") {
return Err(`${context}: no Markdown content was returned for this URL.`);
}
return Ok(content.data.markdown);
};