53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
import type { Result } from "../../types/result";
|
|
import { z } from "zod";
|
|
import { Err, Ok } from "../../types/result";
|
|
|
|
const searchResponseSchema = z.object({
|
|
results: z.array(z.object({
|
|
title: z.string(),
|
|
url: z.string(),
|
|
content: z.string().optional().default(""),
|
|
})),
|
|
unresponsive_engines: z.array(z.tuple([z.string(), z.string()])).optional().default([]),
|
|
});
|
|
|
|
export const searchInputSchema = z.object({
|
|
query: z.string(),
|
|
results: z.number().int().positive().describe("Number of search results to return; choose this for every search."),
|
|
});
|
|
|
|
export const searchOutputSchema = z.object({
|
|
results: z.array(z.object({
|
|
title: z.string(),
|
|
link: z.string(),
|
|
snippet: z.string(),
|
|
})),
|
|
warnings: z.array(z.object({ engine: z.string(), reason: z.string() })),
|
|
});
|
|
|
|
type SearchOutput = z.infer<typeof searchOutputSchema>;
|
|
|
|
export const limitSearchResults = (output: SearchOutput, results: number): SearchOutput => ({
|
|
results: output.results.slice(0, results),
|
|
warnings: output.warnings,
|
|
});
|
|
|
|
export const readSearchResponse = (body: unknown): Result<SearchOutput, string> => {
|
|
const parsed = searchResponseSchema.safeParse(body);
|
|
if (!parsed.success) {
|
|
return Err("Search returned an unexpected response format.");
|
|
}
|
|
const warnings = parsed.data.unresponsive_engines.map(([engine, reason]) => ({ engine, reason }));
|
|
if (parsed.data.results.length === 0 && warnings.length > 0) {
|
|
return Err(`Search returned no results because engines failed: ${warnings.map(warning => `${warning.engine}: ${warning.reason}`).join("; ")}`);
|
|
}
|
|
return Ok({
|
|
results: parsed.data.results.map(item => ({
|
|
title: item.title,
|
|
link: item.url,
|
|
snippet: item.content,
|
|
})),
|
|
warnings,
|
|
});
|
|
};
|