/** * `fileSearch({ stores, where?, maxResults?, name?, description? })` — agent * tool factory for hosted vector-store retrieval (#B8 Phase 2). * * Wraps OpenAI's native `file_search` tool. The tool object is tagged with * `providerHint: { type: 'file-search', ... }`; the OpenAI adapter's * `toOpenAITools` recognizes the hint and emits the native * `{ type: 'file_search', vector_store_ids, filters, max_num_results }` * block instead of a generic function-call shape. The model runs the search * server-side and the results land in the assistant message — no agent-loop * tool round-trip on the hosted path. * * # Hosted on OpenAI today * * Other providers see the tool as a regular function-call tool with the * placeholder `{ query: string }` schema — without an `execute` they pause * for client tools, which is degraded. Set the {@link FileSearchOptions.fallback} * opt to install an `execute` delegating to `similaritySearch` over a local * pgvector model. * * # Wiring * * ```ts * import { Agent, fileSearch, VectorStores } from '@gemstack/ai-sdk' * * const kb = await VectorStores.get('vs_abc123') * * class SupportAgent extends Agent { * model() { return 'openai/gpt-4o' } * tools() { * return [ * fileSearch({ * stores: [kb.id], * where: { author: 'Alice', year: 2026 }, * maxResults: 10, * }), * ] * } * } * ``` * * # Metadata filter sugar * * `where: { author: 'Alice', year: 2026 }` is shorthand for the typed * OpenAI filter shape `{ type: 'and', filters: [{ type: 'eq', key: 'author', * value: 'Alice' }, { type: 'eq', key: 'year', value: 2026 }] }`. Either * shape works — pass the typed object form for `gt` / `lt` / `or`. */ import type { SimilaritySearchOptions } from './similarity-search.js'; import type { Tool, ToolDefinitionOptions, ToolDefinitionSchema } from './types.js'; /** * Symbol-tagged marker identifying a file-search tool. Mirrors the * `COMPUTER_USE_MARKER` pattern — `Symbol.for(...)` so cross-bundle / * cross-realm checks succeed even when `@gemstack/ai-sdk` loads twice. */ export declare const FILE_SEARCH_MARKER: unique symbol; /** * Default tool name. OpenAI's native `file_search` tool expects calls to * land on a tool literally named `file_search` — the model is trained on * that identifier. Apps can override via `opts.name` but usually shouldn't. */ export declare const FILE_SEARCH_TOOL_NAME = "file_search"; /** OpenAI vector-store metadata filter, typed form. */ export type FileSearchFilter = { type: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte'; key: string; value: string | number | boolean; } | { type: 'and' | 'or'; filters: FileSearchFilter[]; }; /** Sugar shape for `where` — `{ key: value }` pairs lowered to a typed `and` of `eq` filters. */ export type FileSearchWhereSugar = Record; /** * Local pgvector fallback configuration (#B8 Phase 3). When set, the tool * gains an `execute` that delegates to {@link similaritySearch} against * the supplied Model. Forwards every {@link SimilaritySearchOptions} field * except `name` / `description` (those flow from the outer `fileSearch` * call so the agent prompt stays identical across providers). */ export type FileSearchFallback = Omit, 'name' | 'description'>; export interface FileSearchOptions { /** * Vector-store IDs the model should search. At least one required. * Mixing providers (e.g. an OpenAI `vs_...` id with a Gemini cached- * content id) is not supported in v1 — every id must come from the * agent's configured provider. */ stores: string[]; /** * Metadata filter applied server-side. Accepts either the sugar * `{ key: value }` form (lowered to an `and` of `eq` filters) or the * typed {@link FileSearchFilter} shape directly. */ where?: FileSearchWhereSugar | FileSearchFilter; /** Maximum number of result chunks to return. Provider default applies when unset. */ maxResults?: number; /** Override the tool name. Defaults to {@link FILE_SEARCH_TOOL_NAME}. */ name?: string; /** Override the tool description shown to the model. Defaults to a generic phrasing. */ description?: string; /** * Local pgvector fallback (#B8 Phase 3). When set, the returned tool gains * an `execute` that delegates to `similaritySearch` for providers that * don't recognize the `'file-search'` `providerHint`. * * The cascade is automatic. On OpenAI the adapter emits the native * `file_search` block — the search runs server-side, the model never * invokes the function-call tool, and `execute` is dead weight. On any * other provider (Anthropic, Gemini today, others) the tool serializes * as a regular function-call schema, the model calls it, and `execute` * delegates to `similaritySearch` against the local pgvector model. * * Same agent prompt across hosted and self-hosted RAG — ops can swap * deployment targets without retraining. * * @example * ```ts * fileSearch({ * stores: [vs_id], * fallback: { * model: Document, * column: 'embedding', * embedWith: 'openai/text-embedding-3-small', * }, * }) * ``` */ fallback?: FileSearchFallback; } /** * A `fileSearch` tool. Implements {@link Tool}; carries * {@link FILE_SEARCH_MARKER} for typeguarding. * * `execute` is absent on the hosted-only path (no `fallback` opt) — the * provider runs the search natively and the model gets results back * inline. With a `fallback` opt configured (#B8 Phase 3), `execute` is * present and delegates to `similaritySearch` so non-native providers * (Anthropic, Gemini today, others) get a working RAG path against a * local pgvector model. */ export interface FileSearchTool extends Tool<{ query: string; }, unknown> { readonly [FILE_SEARCH_MARKER]: true; readonly definition: ToolDefinitionOptions; toSchema(): ToolDefinitionSchema; } /** Build the agent tool. See module JSDoc for usage. */ export declare function fileSearch(opts: FileSearchOptions): FileSearchTool; /** * Structural typeguard. Mirrors `isComputerUseTool` / `isHandoffTool` — * tools are plain objects tagged with `Symbol.for(...)` markers so the * loop and adapters can detect them without coupling to a class. */ export declare function isFileSearchTool(t: unknown): t is FileSearchTool; /** * Lower the user-friendly `where` shape to OpenAI's typed filter object. * * - `{ author: 'Alice', year: 2026 }` → `{ type: 'and', filters: [eq, eq] }` * - `{ type: 'eq' | ... }` → pass-through * - `{ type: 'and' | 'or', filters }` → pass-through * * A single-key sugar object short-circuits to the bare `eq` (no `and` * wrapper), matching OpenAI's recommended shape. */ export declare function normalizeWhere(where: FileSearchWhereSugar | FileSearchFilter): FileSearchFilter; //# sourceMappingURL=file-search.d.ts.map