/** * Slice Z-A (2.8.0) — LLM rerank service (Y2 architecture, zero new deps). * * Receives a fuzzy top-N candidate list (from `searchMemory` / * `MemorySearchResult[]`) and asks an LLM to rerank them by relevance * to the query. Returns the top-K in descending relevance. * * Architecture note (locked decision — see * `.peaks/memory/2026-06-18-peaks-zvec-spike-proposal.md` §Y2): * * - "Active IDE LLM" is a deliberate abstraction: peaks-loop itself * has NO direct LLM API key. The chat call is performed by the * active IDE (Claude Code / Trae / Cursor / Codex / ...) using * its own authentication chain. * * - The current `IdeAdapter` interface has no `chat()` method — * `SubAgentDispatcher` returns IDE-private tool-call descriptors * (sub-agent dispatch, not direct chat). This service therefore * takes a `chat` function INJECTION at the call site. The default * is a no-op that fails-open (returns the original fuzzy order). * * - This is a SPIKE artifact for Z-A. The real chat wiring (either * a new `IdeAdapter.chat()` method, or routing through * `SubAgentDispatcher` with a "rerank" role) is a Z-B prerequisite * and is tracked in the GO/NO-GO report at * `.peaks/memory/memory-search-y2-rerank-2026-06-19-decision.md`. * * Why this is split from `memory-search-service.ts`: * * - The fuzzy kernel is pure + synchronous + 100% testable today. * - The rerank layer is async + IO-bound + 100% fallback. Keeping * it separate means the existing 2800+ fuzzy tests are untouched * and the new spike has its own test surface (per the Z-A * proposal's "不重写 memory-search-service.ts" red line). * * Why 4-bytes-per-token: * * - `BYTES_PER_TOKEN = 4` is the standard rough English-text * approximation (1 token ≈ 4 bytes). It keeps token estimates * stable and comparable in the AC-ZA-5 benchmark. * * Out of scope (YAGNI per Karpathy #2 Simplicity First): * * - No cross-process cache (AC-ZA-6 deferred — only build if * AC-ZA-5 shows a hot path). * - No rerank-prompt optimization beyond the minimal JSON * output format. * - No integration with `memory-search-service.ts` (Z-A is a spike; * the wiring into `peaks memory search` is Z-B). */ import type { MemorySearchResult } from './memory-search-service.js'; import { type RerankChatFn, type RerankOptions, type RerankResult } from './llm-reranker-core.js'; export { applyRerankOrder, estimateTokens, renderRerankPrompt } from './llm-reranker-core.js'; export type { RerankChatFn, RerankChatMessage, RerankOptions, RerankResult, RerankTokenUsage } from './llm-reranker-core.js'; /** * Parse the LLM's raw text response into an ordered list of * candidate indices. Tolerates: * * - Pure JSON arrays: `[3, 0, 4, 1, 2]` * - JSON wrapped in markdown code fences: * ```json * [3, 0, 4, 1, 2] * ``` * - Whitespace and surrounding prose (best-effort: looks for the * first `[...]` block) * * Returns `null` on parse failure (caller falls back to original * fuzzy order per AC-ZA-8 L3). */ export declare function parseRerankResponse(raw: string): readonly number[] | null; /** * The no-op chat function. Used when no real chat injection is * available — the rerank layer fails-open and the caller gets * the original fuzzy order. */ export declare const noopRerankChat: RerankChatFn; /** * Run the LLM rerank. Always returns a result — never throws. * The caller can use `topK` as a drop-in replacement for the * fuzzy top-K regardless of degradation mode. */ export declare function rerank(query: string, candidates: readonly MemorySearchResult[], options?: RerankOptions): Promise;