/** * ollama_corpus_answer — FLAGSHIP TOOL. * * Job-shape: given a NAMED CORPUS and a question, retrieve via * searchCorpus, then synthesize an answer grounded in the retrieved * chunks only. Distinct from ollama_research (which takes source_paths * the caller explicitly hands in). * * Tier: Deep for synthesis; Embed for retrieval (via searchCorpus). * * Laws: * - Retrieved chunks only. The synthesis prompt never receives outside * context, and the system prompt forbids outside knowledge. * - Chunk-grounded citations. The model cites by source number; we * validate every number is in [1, N] and strip the rest, then map * back to (path, chunk_index, heading_path, title) from retrieval. * - Weak retrieval degrades honestly. Zero hits short-circuit without * invoking the model; thin retrieval (< 2 hits) flags `weak: true` * and adds a coverage note so the caller doesn't mistake a narrow * answer for a confident one. * - Raw chunk text never crosses the MCP boundary. Only the structured * citation shape and the final answer are returned. */ import { z } from "zod"; import type { Envelope } from "../envelope.js"; import { type SearchMode, type CorpusHit } from "../corpus/searcher.js"; import type { RunContext } from "../runContext.js"; export declare const corpusAnswerSchema: z.ZodObject<{ corpus: z.ZodString; question: z.ZodString; mode: z.ZodOptional>; top_k: z.ZodOptional; max_words: z.ZodOptional; min_top_score: z.ZodOptional; model: z.ZodOptional; }, z.core.$strip>; export type CorpusAnswerInput = z.infer; export interface CorpusAnswerCitation { path: string; chunk_index: number; heading_path: string[]; title: string | null; /** Retrieval relevance score for this chunk, propagated from the hit. */ score: number; } export interface RetrievalStat { retrieved: number; total_in_corpus: number; top_score: number; weak: boolean; } export interface CorpusAnswerResult { answer: string; citations: CorpusAnswerCitation[]; covered_sources: string[]; omitted_sources: string[]; coverage_notes: string[]; mode: SearchMode; retrieval: RetrievalStat; /** * True when the tool refused to invoke the model because retrieval did * not clear a relevance bar — empty corpus, 0 hits, or top score below * the caller-supplied `min_top_score` floor. Distinct from `weak`: weak * means thin grounding (e.g. 1 hit); abstained means no synthesis at all. */ abstained: boolean; } export declare function validateAndMapCitations(numbers: number[], hits: CorpusHit[]): { valid: CorpusAnswerCitation[]; stripped: number; }; export declare function computeCoverage(hits: CorpusHit[], citations: CorpusAnswerCitation[], weak: boolean, stripped: number): { covered: string[]; omitted: string[]; notes: string[]; }; export declare function handleCorpusAnswer(input: CorpusAnswerInput, ctx: RunContext): Promise>; //# sourceMappingURL=corpusAnswer.d.ts.map