import type { OramaDoc } from "../search/orama-index.ts"; /** A chat message as posted by the Ask AI island (`{ role, content }`). */ export interface AskMessage { content: string; role: string; } /** The current-page hint the island forwards so the endpoint can prioritize it. */ export interface AskPage { path?: string; } /** * The self-contained snapshot the grounded Ask AI endpoint imports. Bundles the * search documents so retrieval works regardless of the configured search * provider and needs no filesystem access at request time. Serialized to * `generated/ask-data.json` and built by {@link buildAskData}. */ export interface AskData { /** * The site's `i18n.defaultLocale`, when i18n is configured. Selects a * word-segmenting Orama tokenizer for every non-Latin script, so retrieval * can match CJK, Cyrillic, Greek, Hebrew, or Devanagari content. */ defaultLocale?: string; documents: OramaDoc[]; site: string | null; } /** * How much retrieved documentation a question carries (the `ai.ask.retrieval` * config). Every field falls back to the built-in default, so a partial object * only changes what it names. Injected characters dominate time-to-first-token * on a self-hosted backend, and the three knobs aren't interchangeable: the * budget caps the total, `excerptChars` decides how deep into one long page the * excerpt reaches, and `maxResults` decides how many pages retrieval adds (the * page the reader is viewing is injected on top of them). */ export interface AskRetrievalOptions { /** Overall cap on injected documentation characters. Defaults to `10000`. */ contextBudget?: number; /** Characters kept per injected excerpt. Defaults to `2000`. */ excerptChars?: number; /** * Documents retrieved per question. Defaults to `6`. The current page is * injected in addition when it isn't among the hits. */ maxResults?: number; } /** * Excerpt the region of `content` most relevant to `query`, not just its head. * * Pages are indexed whole (one document each), so a naive head slice of a long * page returns its intro and misses sections below the fold — the exact failure * where "How does Ask AI work?" retrieves the right page but only sees its * opening paragraph. This centers the window on the densest cluster of query * terms so the injected text is the part that actually answers the question. * Exported for testing; {@link createAskContext} is the runtime entry point. */ export declare const relevantExcerpt: (content: string, query: string, max: number) => string; /** * Build the request-time grounding function for the Ask AI endpoint. * * Lexical retrieval over Orama (the same index/ranking the search dialog and MCP * server use). The index is built once and memoized across requests. Returns a * grounded system prompt — the retrieved excerpts plus the page the user is * viewing — or `undefined` when there is nothing to ground on, so the endpoint * can fall back to its plain prompt. * * `options.instructions` (the `ai.ask.instructions` config) is appended after * the base instruction rather than replacing it: the base carries the * functional contract (answer only from the excerpts, cite pages as Markdown * links) that the panel's citation rendering depends on. * * `options.retrieval` (the `ai.ask.retrieval` config) sizes how much * documentation each question carries; omitted fields keep today's defaults. */ export declare const createAskContext: (data: AskData, options?: { instructions?: string; retrieval?: AskRetrievalOptions; }) => ((messages: AskMessage[], page?: AskPage) => Promise);