/** * Cold-resume-lean: natural-language auto-resume for OpenCode. * * When the user's first message shows resume intent ("continue the token-optimizer * work", "what we discussed last session"), inject a FULL lean reconstruction of * the right same-project prior session — no command, no id. * * Token-free: pure SQLite + in-memory reads; no LLM, no subprocess. * * Port from Python: skills/token-optimizer/scripts/measure.py * Functions ported: _resume_intent, _RESUME_INTENT_RE, _RESUME_TOPIC_STOPWORDS, * _resume_topic_score, _checkpoint_in_project, _continuity_resume_block, * build_lean_resume_context, _resume_lean_already_credited, _log_resume_lean_savings. * * Key structural difference from Python: opencode stores checkpoints in per-session * SQLite DBs (session_store.ts checkpoints table) — NOT in JSON sidecar files. The * sidecar fields (active_task, continuation, open_questions, recent_reads, git, * quality) don't exist; we reconstruct from what IS available: active_files[] * (JSON), decisions[] (JSON), and the content text. The "thin tier" is therefore * more common here. Savings use tokens_cache_write (closest proxy to Python's * cache_create tokens) or rawBytes fallback. */ import type { TrendsStore } from "../storage/trends.js"; /** * Matches natural-language cues that the user wants to pick up prior work. * Kept tight to avoid firing on incidental "continue to the next file". * MUST NOT match bare "continue" without a contextual modifier. */ export declare const RESUME_INTENT_RE: RegExp; /** True when the prompt asks to continue/recall prior work. */ export declare function resumeIntent(text: string): boolean; /** * Generic glue words that carry no topic once the resume cue is removed. * Keeping them would let "session"/"work" falsely match every checkpoint. * * Note: opencode's scoreRelevance in matcher.ts already strips STOP_WORDS and * uses pure keyword precision, but it would short-circuit on "continue"/"resume" * inflating every checkpoint to a high score. We compute residual precision * against the checkpoint's stored content instead. */ export declare const RESUME_TOPIC_STOPWORDS: Set; /** Set-overlap keep/drop rule. KEEP iff < 3 distinctive tokens * (inconclusive) OR nonempty intersection with keepTokens; DROP iff >= 3 * tokens AND zero overlap. No float threshold. Exported for the parity * fixture test. */ export declare function keepRecoveredItem(itemText: string, keepTokens: Set): boolean; /** True when file path ``p`` is an attributable absolute path that does NOT * live under ``cwd`` — a cross-project file. The set-overlap * tokenizer treats a full path as a SINGLE token (the regex includes slashes) * so it has < 3 distinctive tokens and would always be kept by * ``keepRecoveredItem``; this rule drops such paths at the file-filter sites * regardless of token overlap, using the EXISTING ``pathUnderRoots`` prefix * check. Relative/basenames fall through to the token rule. cwd absent -> * never drop (legacy callers stay unfiltered). */ export declare function crossProjectFileDrop(p: string, cwd: string): boolean; /** * Precision of the prompt's RESIDUAL topic words (after removing resume cues) * against a checkpoint's content text. * * Unlike scoreRelevance (matcher.ts), this does NOT short-circuit on bare * "continue"/"resume" cues, so a named topic ("the keepwarm one") scores * higher than a vague "continue last session" → residual empty → score 0.0. * * @param prompt The user's first message. * @param content The checkpoint's full content string from the DB. */ export declare function resumeTopicScore(prompt: string, content: string): number; /** * True when a checkpoint's working set lives under the current project dir. * * In opencode, active_files is a JSON-encoded string[] column from the * checkpoints table. We use it as the "recent_reads + modified_files" * equivalent. Path-prefix based, no DB join needed. */ export declare function checkpointInProject(activeFilesJson: string, cwd: string): boolean; /** Topic bar: above this, the prompt names a topic (keyword winner); below it, most-recent. */ export declare const RESUME_TOPIC_BAR: number; /** * A DB row from the checkpoints table, enriched with the session DB file path * and mtime (for recency ordering). */ export interface CheckpointRow { session_id: string; trigger: string; mode: string; quality_score: number | null; fill_pct: number | null; active_files: string; decisions: string; content: string; created_at: number; /** Path of the session DB file that holds this checkpoint (for dedup) */ dbPath: string; } /** * Build a LEAN context block from a checkpoint row. * * Faithful tier (checkpoint present): active files, decisions, topic summary, * quality, mode. Thin tier (no decisions / empty content): clearly flagged. * Fenced as RECOVERED DATA so a fresh session treats it as context, not instructions. * * DEVIATION from Python: Python's sidecar has rich fields (active_task, * continuation, open_questions, recent_reads, git). opencode's checkpoint DB * stores (active_files[], decisions[], content text, mode, quality_score, * fill_pct). We surface what we have; the "thin tier" is hit more often here. */ export declare function buildLeanResumeContext(cp: CheckpointRow, sessionId: string, maxChars?: number, promptText?: string, cwd?: string): string; /** * When the user asks to continue prior work, return a FULL lean reconstruction * of the right same-project session, or "" to fall through to the lightweight * hint (or no-op when no match). * * Selection ("both", per spec): * - best residual score >= RESUME_TOPIC_BAR → keyword winner (recency breaks ties) * - else → most-recent same-project checkpoint * * Returns [block, targetSessionId] or ["", ""] on no match. */ export declare function buildResumeLeanBlock(userPrompt: string, dataDir: string, currentSessionId: string, cwd: string, retentionDays?: number, maxCandidates?: number, /** Optional: scopes the scan to one project's session subdirectory. Appended * last so existing call sites keep their argument order. */ projectSlug?: string): [string, string]; /** * Credit the cold-resume cost avoided by reconstructing a session lean instead * of a full --resume cold-rewrite. * * Avoided cost (in priority order, matching Python's _log_resume_lean_savings): * 1. tokens_cache_write from session_log (the real cold-rewrite cost, closest * proxy to Python's cache_create_1h_tokens + cache_create_5m_tokens). * 2. checkpointRawBytes / CHARS_PER_TOKEN (conservative byte-size proxy). * 3. If neither is available: credit 0. NO generous heuristic (e.g. lean*10). * Per PRIME DIRECTIVE: never-overcount wins every tradeoff. * * Cross-session dedup: calls TrendsStore.hasRecentSavingsEvent to ensure the * same cold session is credited at most once per 6h window, even if reopened * from two different fresh sessions. Mirrors Python's _resume_lean_already_credited * which dedups on the TARGET session_uuid within 6h. * * Idempotent per target session within ~6h. Best-effort: never breaks injection. */ export declare function logResumeLeanSavings(trendsStore: TrendsStore, targetSessionId: string, leanBlock: string, checkpointRawBytes?: number): void; //# sourceMappingURL=resume-lean.d.ts.map