import { type RepoInfo } from "./discovery.js"; /** * State of the cached graph hint envelope. * * - `up_to_date` — at least one repo is indexed and not stale, no refresh in flight * - `refreshing` — at least one repo is currently being analyzed in background * - `may_be_stale` — at least one indexed repo is stale (HEAD drifted) and no refresh active * - `missing` — no repo is indexed at all (envelope is empty, hook should skip injection) */ export type GraphFreshness = "up_to_date" | "refreshing" | "may_be_stale" | "missing"; export interface HintCacheState { envelope: string; freshness: GraphFreshness; updatedAt: number; } /** * Stable opt-in marker the orchestrator writes into a subagent prompt to grant * graph access to that subagent. The plugin's messages.transform hook detects * this marker, prepends the envelope, and strips the marker from the prompt. */ export declare const OPT_IN_MARKER = "[[gitnexus:graph]]"; /** * A per-plugin-instance hint-envelope state container. Each call to * createHintEnvelopeState() returns its own isolated cache and refreshing set, * so two plugin instances sharing the same node process (e.g. two workspaces * loaded simultaneously) cannot overwrite each other's envelopes. */ export interface HintEnvelopeState { /** Mark a repo as being refreshed in the background. */ markRefreshing(repoPath: string): void; /** Clear the refreshing flag for a repo. */ markRefreshDone(repoPath: string): void; /** Read the current cached envelope. */ getHintCache(): HintCacheState; /** Rebuild the cache from an explicit repo list (pure). */ rebuildHintCache(repos: RepoInfo[]): void; /** Discover repos under `scanRoot` and rebuild the cache from the result. */ refreshHintCache(scanRoot: string): void; /** Test helper: reset to initial empty state. */ reset(): void; } export declare function createHintEnvelopeState(): HintEnvelopeState; /** * Idempotency scrubber: remove any leading `...` * blocks (with their trailing newlines) so a stale envelope from a previous * turn or compaction doesn't accumulate when we prepend the fresh one. * * Only matches at start-of-text — envelopes embedded inside user content (e.g. * pasted code) are left alone, since they were not put there by us. */ export declare function scrubPromptGitnexusBlocks(text: string): string; /** * Remove every occurrence of OPT_IN_MARKER from a prompt without touching * any other whitespace. Multi-line structure, indentation, markdown, and * code fences are preserved verbatim. * * If the marker sat alone on its own line, the now-empty line is removed * so the orchestrator can write: * * [[gitnexus:graph]] * real instructions here * * and the subagent sees just `real instructions here` without a leading * blank line. Any other blank lines the user wrote are left intact. */ export declare function stripOptInMarker(text: string): string;