/** * Personalised retrieval — "which files does this task touch?" * * Lexical search proposes, the graph disposes. A BM25/FTS query produces a set * of seed symbols with scores; those scores become the restart distribution of * a personalised PageRank walk over the wiring graph. The walk then surfaces * what the seeds are structurally attached to: the interface a matched * function implements, the module every matched call site imports, the store * behind the handler that matched by name. * * This is the piece that turns the index from a set of primitives an agent has * to compose by hand — search, then skeleton, then incoming-calls, then read — * into one answer. The composition was previously re-derived by the model on * every task, at the cost of several round trips and a great deal of judgement * spent on plumbing rather than on the problem. * * What comes back is declarations, not source: file, relevance, and the * matching symbols with their signatures and line numbers. Reading the actual * code stays a deliberate `read` — the point is to make that read land in the * right place the first time. */ import type { IndexStore } from './writer.js'; /** One symbol worth showing inside a returned file. */ export interface ContextSymbol { name: string; kind: string; line: number; signature: string; /** True when lexical search matched this symbol directly. */ seed: boolean; } /** One file in the answer, most relevant first. */ export interface ContextEntry { /** Project-relative POSIX path. */ file: string; /** Relevance to this query, normalised so the top entry is 1.0. */ relevance: number; /** Whether any symbol here matched the query lexically. */ matched: boolean; symbols: ContextSymbol[]; } export interface ContextResult { query: string; entries: ContextEntry[]; /** Lexical hits that seeded the walk. Zero means nothing matched. */ seedCount: number; /** Semantic hits that also seeded it. */ semanticSeedCount: number; /** Files the walk reached before truncation to `limit`. */ totalCandidates: number; indexStatus: 'ok' | 'no-index' | 'no-matches' | 'unranked'; } export interface ContextOptions { query: string; /** * Files a semantic search already matched, with their cosine scores. * * Supplied by the caller rather than computed here because the embedding * model lives host-side — functions cannot cross the daemon's IPC boundary, * so only the resulting file scores travel. These become additional restart * mass, letting a query phrased in the problem's vocabulary reach code whose * identifiers never use those words. */ vectorFiles?: ReadonlyArray<{ file: string; score: number; }> | undefined; /** Files to return. */ limit?: number | undefined; /** Symbols to show per file. */ symbolsPerFile?: number | undefined; /** Restrict results to files under this project-relative prefix. */ pathPrefix?: string | undefined; } /** * Lexical hits used as restart mass. More seeds make the walk broader and * blunter; this is enough to cover a multi-word query's separate senses * without letting a common token dominate. */ export declare const SEED_LIMIT = 40; export declare const DEFAULT_LIMIT = 12; export declare const DEFAULT_SYMBOLS_PER_FILE = 4; /** * Run the personalised walk and group the winners into files. * * Returns an empty result rather than throwing whenever the index cannot * answer — an unbuilt index and a query nobody matches are ordinary states, * and `indexStatus` says which one happened. */ export declare function retrieveContext(store: IndexStore, projectRoot: string, indexDir: string | undefined, options: ContextOptions, relativeOf: (file: string) => string): ContextResult; //# sourceMappingURL=context-retrieval.d.ts.map