import { type ConversationMessage } from "@threadbase-sh/scanner"; export interface InheritedLink { /** Provider-side id of the conversation this one continues. */ sourceId: string; /** * The cut, as the provider writes it: a LINE ordinal, exclusive. * * Not a message index. In a real rollout, ordinals count every envelope line * — token counts, task events, turn context — while only a fraction render as * messages. Translating one to the other is `countMessagesBeforeOrdinal`, and * skipping that translation is the silent failure this module exists to * prevent. */ ordinalExclusive: number; forkedAt: string | null; } export interface InheritedHistory extends InheritedLink { sourceFilePath: string | null; /** The inherited messages, oldest first. Empty when the source is unreadable. */ messages: ConversationMessage[]; /** Set when the source could not be read; `messages` is then empty. */ unavailableReason: "source_missing" | null; } /** * Read a fork link out of one JSONL line, or null if it carries none. * * Tolerant by construction, like every provider parser here: malformed JSON, a * missing payload, or a partial link (an id with no ordinal) all mean "no * link", never a throw. A conversation that is not a fork is the overwhelmingly * common case and must cost nothing. */ export declare function readForkLinkFromLine(line: string): InheritedLink | null; /** Test seam: the caches are process-global and would otherwise leak across tests. */ export declare function clearInheritedLinkCache(): void; /** * A fork declares itself on its FIRST line, so this reads one line and stops. * Returns null for a file that isn't there — an absent file is not a fork. */ export declare function readForkLink(filePath: string): Promise; /** * The messages of `filePath` that precede line ordinal `ordinalExclusive`. * * The message decision is `parseCodexJsonlLine`, imported rather than * reimplemented: it is the same rule the scanner renders with, so the count * here cannot drift from what the conversation actually shows. Re-deriving it * locally is how a fork ends up displaying turns it never inherited. * * `ordinal` is read off each line, with the line counter as the fallback for a * writer that omits it — in observed rollouts the two are identical (a 331-line * file carries ordinals 0–330), so the fallback is a degrade path, not a guess. */ export declare function readMessagesBeforeOrdinal(filePath: string, ordinalExclusive: number): Promise; /** Test seam: the cache is process-global and would otherwise leak across tests. */ export declare function clearInheritedPrefixCache(): void; export interface ResolveInheritedOptions { /** The conversation being served — the fork, not the source. */ filePath: string; /** Resolve a conversation id to its file, or null when it can't be found. */ locateSource: (conversationId: string) => Promise; } /** * Resolve the full inherited prefix for a conversation, following a chain of * forks oldest-first. * * Returns null when the conversation inherits nothing, which is the normal * case and costs one line read. * * A source that cannot be found does NOT fail the request: the fork's own * messages are still served, with `unavailableReason` set so the client can say * the earlier history is unavailable instead of silently showing a truncated * conversation. That degrade is what makes it safe to keep pointing at the * source file rather than copying it. */ export declare function resolveInheritedHistory(opts: ResolveInheritedOptions): Promise; //# sourceMappingURL=inheritedHistory.d.ts.map