SPB Git
4.2 KB · 59 lines typescript
1import "server-only";2import type { ToolDef } from "../ai/types";3import { webSearch, fetchPage } from "./web";4import { runPython } from "./python";5import { searchDocuments } from "./documents";6import { generateImageTool } from "./image";7import { saveMemoryTool } from "./memory";89export type Permission = "auto" | "approval";1011export interface ToolContext { conversationId: string; projectId: string | null; messageId: string; signal?: AbortSignal; allow: Set<string> }12export interface Tool extends ToolDef {13  permission: Permission;14  category: "web" | "code" | "documents" | "media" | "memory";15  run(input: Record<string, unknown>, ctx: ToolContext): Promise<unknown>;16}1718export const TOOLS: Tool[] = [19  {20    name: "web_search", category: "web", permission: "auto",21    description: "Search the web (Tavily). Returns titles, URLs and snippets. Use for current events, facts to verify, sources to cite.",22    inputSchema: { type: "object", properties: { query: { type: "string" }, max_results: { type: "integer", minimum: 1, maximum: 10 }, recency_days: { type: "integer", description: "Only results newer than N days" } }, required: ["query"], additionalProperties: false },23    run: (i) => webSearch(String(i.query), { maxResults: Number(i.max_results ?? 6), recencyDays: i.recency_days ? Number(i.recency_days) : undefined }),24  },25  {26    name: "fetch_page", category: "web", permission: "auto",27    description: "Fetch a public web page and return its readable text (truncated to ~20k chars). Only use on URLs you obtained from search results or the user.",28    inputSchema: { type: "object", properties: { url: { type: "string" } }, required: ["url"], additionalProperties: false },29    run: (i) => fetchPage(String(i.url)),30  },31  {32    name: "python", category: "code", permission: "auto",33    description: "Execute a Python 3 script in an isolated sandbox (no network, 20 s timeout, temp dir). Print results to stdout. numpy/pandas available if installed on the host. Use for calculations, data analysis, simulations.",34    inputSchema: { type: "object", properties: { code: { type: "string" } }, required: ["code"], additionalProperties: false },35    run: (i, ctx) => runPython(String(i.code), ctx.signal),36  },37  {38    name: "search_documents", category: "documents", permission: "auto",39    description: "Semantic + keyword search over the documents attached to this conversation or project. Returns the most relevant passages with file names and pages.",40    inputSchema: { type: "object", properties: { query: { type: "string" }, limit: { type: "integer", minimum: 1, maximum: 12 } }, required: ["query"], additionalProperties: false },41    run: (i, ctx) => searchDocuments(String(i.query), ctx, Number(i.limit ?? 6)),42  },43  {44    name: "generate_image", category: "media", permission: "auto",45    description: "Generate an image with OpenAI gpt-image (verified). Returns an attachment id to display. Keep prompts descriptive.",46    inputSchema: { type: "object", properties: { prompt: { type: "string" }, size: { type: "string", enum: ["1024x1024", "1536x1024", "1024x1536"] }, quality: { type: "string", enum: ["low", "medium", "high"] } }, required: ["prompt"], additionalProperties: false },47    run: (i, ctx) => generateImageTool(String(i.prompt), ctx, { size: i.size as string | undefined, quality: i.quality as string | undefined }),48  },49  {50    name: "save_memory", category: "memory", permission: "auto",51    description: "Propose a durable memory about the owner (preference, project fact, infrastructure detail) for future conversations. Never store secrets, passwords or sensitive personal data.",52    inputSchema: { type: "object", properties: { content: { type: "string" }, category: { type: "string", enum: ["preference", "writing", "research", "project", "infrastructure", "objective", "concept", "context"] } }, required: ["content"], additionalProperties: false },53    run: (i, ctx) => saveMemoryTool(String(i.content), String(i.category ?? "context"), ctx),54  },55];5657export function toolByName(name: string): Tool | undefined { return TOOLS.find(t => t.name === name); }58export function toolDefs(names?: string[]): ToolDef[] { return TOOLS.filter(t => !names || names.includes(t.name)).map(({ name, description, inputSchema }) => ({ name, description, inputSchema })); }59
Files · main
Menu

Theme