import { Lang } from "@ast-grep/napi";
import type { CodeGraph, SymbolEdge, SymbolNode } from "../types.js";
import type { GitRefreshTarget } from "./git-state.js";
import { type GraphChangeSummary, type GraphInputRecord, type GraphInputRecorder, type GraphRebuildDecision } from "./graph-inputs.js";
import { type GodotSymbolResolutionContext } from "./graph-symbol-resolution.js";
import { type RustUseBinding } from "./graph-symbols.js";
export { describeGraphBuilder, describeUnresolvedSymbolEdges, findCircularDependencies, generateMermaidDiagram, getFileDependencies, getGraphStats, isGraphBuilderStale, isImportResolutionLow } from "./graph-analysis.js";
/** Progress details for an in-flight graph build operation */
export interface GraphBuildProgress {
    startedAt: number;
    filesTotal: number;
    filesProcessed: number;
    /**
     * Files counted in `filesProcessed` that got no node of their own; an importer
     * may still have created a placeholder for them. Absent until the first skip.
     */
    filesSkipped?: number;
    phase: string;
    error?: string;
}
/** Summary of a completed graph build operation */
export interface GraphBuildCompleted {
    completedAt: number;
    durationMs: number;
    filesProcessed: number;
    /**
     * Files that got no node of their own during this build; an importer may still
     * have created a placeholder for them. Absent when none were skipped.
     */
    filesSkipped?: number;
    nodesCreated: number;
    edgesCreated: number;
    error?: string;
    /**
     * Set when the file-import graph was built and saved but the symbol graph
     * could not be persisted. That half-failure used to be logged and otherwise
     * dropped, so the build reported success while `codebase_impact` silently had
     * nothing to answer with; recording it here is what lets status say so.
     */
    symbolGraphError?: string;
}
/** Check if a graph build is currently in progress for a project */
export declare function isGraphBuildInProgress(projectPath: string): boolean;
/** Get progress details for a graph build currently in progress */
export declare function getGraphBuildProgress(projectPath: string): GraphBuildProgress | null;
/** Get the last completed graph build for a project */
export declare function getLastGraphBuildCompleted(projectPath: string): GraphBuildCompleted | null;
/** Get all projects currently building a graph */
export declare function getGraphBuildInProgressProjects(): string[];
/** Invalidate graph cache for a project (called by watcher on file changes) */
export declare function invalidateGraphCache(projectPath: string): void;
/** A pinned identity can be cached under more than one checkout path; drop them all. */
export declare function invalidateGraphCacheForIdentity(projectId: string): void;
/** Get a cached graph, or load from Qdrant, or build one */
export declare function getOrBuildGraph(projectPath: string, extraExtensions?: Set<string>): Promise<CodeGraph>;
/** Get a cached or persisted graph without creating one when it is absent. */
export declare function getExistingGraph(projectPath: string): Promise<CodeGraph | null>;
/** Options for `rebuildGraph` controlling which layers are rebuilt. */
export interface RebuildGraphOptions {
    /** Storage identity captured by the enclosing index operation. */
    projectId?: string;
    /** Git refreshes require both graph layers to finish for the observed state. */
    target?: GitRefreshTarget;
    /** Extra file extensions to treat as graph nodes. */
    extraExtensions?: Set<string>;
    /**
     * When `true`, skip the symbol-graph extraction + persistence step entirely.
     * The file-import graph is still rebuilt and persisted. The caller is then
     * expected to update the symbol graph incrementally via
     * `updateChangedFilesSymbolGraph` from `symbol-graph-incremental.ts`.
     * Default: `false`.
     */
    skipSymbolGraph?: boolean;
}
/**
 * Whether an incremental update has to rebuild the code graph, and why.
 *
 * The answer comes from the record the last build left behind — the files it
 * read and the settings it read them under — never from a predicate describing
 * which files a graph is built from. There is no such predicate to keep in
 * step, which is the whole reason the build reports its own inputs.
 *
 * Conservative wherever the record cannot settle the question: a project with
 * no usable record rebuilds once and writes one, and so does any addition, any
 * settings change, and any recorded input that moved. Only a change proven to
 * touch nothing the build read is skipped.
 */
export declare function shouldRebuildGraph(projectPath: string, change: GraphChangeSummary, extraExtensions?: Set<string>, projectId?: string): Promise<GraphRebuildDecision>;
/**
 * The parsers this process actually has, as one hash.
 *
 * Read after {@link ensureDynamicLanguages} has run, which every path into the
 * build and the decision does first, so it describes the process answering
 * rather than some other one.
 */
export declare function currentGraphCapabilities(): Promise<string>;
/** Force-rebuild, cache, and persist a graph.
 * If a build is already in progress for this project, returns the existing
 * in-flight promise (deduplication — same as indexer concurrency guard).
 *
 * Backward-compatible: accepts either `extraExtensions` (legacy positional
 * Set) or a `RebuildGraphOptions` object.
 */
export declare function rebuildGraph(projectPath: string, optsOrExtras?: Set<string> | RebuildGraphOptions): Promise<CodeGraph>;
/**
 * Wait for any in-flight graph build to finish for a project.
 * Resolves immediately if no build is in progress.
 * Swallows errors — the caller typically wants to proceed regardless.
 */
export declare function awaitGraphBuild(projectPath: string): Promise<void>;
/** Remove a persisted code graph from Qdrant and clear cache */
export declare function removeGraph(projectPath: string): Promise<void>;
/** Check if a graph exists (in cache or persisted) */
export declare function hasGraph(projectPath: string): Promise<boolean>;
/** Get graph metadata for status display */
export declare function getGraphStatus(projectPath: string): Promise<{
    lastBuiltAt: string;
    nodeCount: number;
    edgeCount: number;
    /** Import specifiers captured across all files, resolved or not. Absent on
     * graphs persisted before this field was recorded. */
    importCount?: number;
    /** SocratiCode version that built this graph, which is not necessarily the
     * one serving it. Absent on graphs persisted before this field was
     * recorded. */
    builtByVersion?: string;
    cached: boolean;
    symbol?: {
        fileCount: number;
        symbolCount: number;
        edgeCount: number;
        unresolvedEdgePct: number;
        builtAt: number;
    };
} | null>;
/** Snapshot of dynamic-language registration state, for diagnostics. */
export interface DynamicLanguageStatus {
    loaded: string[];
    failed: Array<{
        name: string;
        error: string;
    }>;
}
/** Returns which dynamic ast-grep grammars registered successfully and which failed. */
export declare function getDynamicLanguageStatus(): DynamicLanguageStatus;
/**
 * Whether the GDScript tree-sitter parser was successfully registered.
 * tree-sitter-gdscript ships platform-specific prebuilds; on platforms
 * without a compatible artifact (e.g. linux-arm64) this stays false so
 * callers can skip AST processing and use syntax-aware fallback extraction.
 */
export { gdscriptParserAvailable } from "./parser-availability.js";
export declare function ensureDynamicLanguages(): void;
/**
 * Map a file extension to its ast-grep grammar (or null when none). An
 * EXTENSION_LANGUAGE_MAP override is resolved through the target language's
 * canonical extension, so a mapped extension (e.g. `.inc` → php) gets the same
 * grammar a native file of that language would, keeping symbol extraction and
 * AST chunking consistent with the language label.
 */
export declare function getAstGrepLang(ext: string, override?: Map<string, string>): Lang | string | null;
/**
 * Get all source files in a project for graph analysis, with the detected
 * extension of every extensionless file admitted by content detection.
 *
 * Includes files with known AST grammars, mixed Elixir templates handled by their
 * dedicated parsers, and any extra extensions. Extensionless files are head-read
 * here to decide admission, and the extension that decision
 * used is returned in `detectedExts` so the build pass can reuse it instead of
 * reading the head again.
 *
 * `files` is sorted lexicographically. Node documents no readdir ordering, and a
 * depth-first walk additionally interleaves a directory's contents with the
 * sibling entries that sort after it — `a/x.ts` is yielded before `a.ts`.
 * Processing order determines node insertion order, and `buildJvmSuffixMap`'s
 * first-match-wins tie-break for duplicate class paths reads the set in that
 * order directly (`buildCsNamespaceMap` and `buildGoModuleInfo` sort their own
 * filtered views instead). Normalize here rather than leaving it to the traversal.
 */
export declare function getGraphableFiles(projectPath: string, extraExts?: Set<string>, recorder?: GraphInputRecorder): Promise<{
    files: string[];
    detectedExts: Map<string, string>;
}>;
/**
 * Build a code graph for a project using ast-grep for polyglot support.
 * Files with extra extensions (no AST grammar) are included as leaf nodes
 * that can be targets of import edges from other files.
 *
 * Also extracts symbols and call sites in the same pass — returned via
 * `symbolsByFile` / `outgoingCallsByFile` and persisted by `doRebuildGraph`.
 */
export declare function buildCodeGraph(projectPath: string, extraExtensions?: Set<string>, progress?: GraphBuildProgress): Promise<CodeGraph & {
    symbolsByFile: Map<string, SymbolNode[]>;
    outgoingCallsByFile: Map<string, SymbolEdge[]>;
    autoloadTable?: Map<string, string>;
    resToRepoPathMap: Map<string, string>;
    godotContext?: GodotSymbolResolutionContext;
    inferredTypesByFile: Map<string, Map<string, Array<{
        type: string;
        startLine: number;
        endLine: number;
    }>>>;
    memberAssignmentsByFile: Map<string, Array<{
        receiver: string;
        memberName: string;
        valueType: string;
    }>>;
    /** Rust `use` bindings per file — resolution input only, never persisted. */
    rustBindingsByFile: Map<string, RustUseBinding[]>;
    /** Rust file → its crate's directory prefix. Resolution input only. */
    rustCrateRootByFile: Map<string, string>;
    /** Rust file → every target root its parsed Cargo manifest declares. */
    rustCrateRootsByFile: Map<string, string[]>;
    /**
     * The call edges whose qualifier is rooted in an inline `mod` — a scope with
     * no file to name. Resolution leaves them unresolved. Held by identity, so
     * nothing about it reaches an edge or the store.
     */
    rustInlineScopedCalls: Set<SymbolEdge>;
    /**
     * The ids of the Rust symbols declared inside an inline `mod`. A path
     * anchored at a file's own module cannot reach them, so resolution drops
     * them from that path's candidates. Resolution input only, never persisted.
     */
    rustInlineDeclaredSymbols: Map<string, string>;
    /**
     * Every input this build consumed, for the next incremental update to check
     * a change against. Reported from the build rather than described beside it,
     * so no second answer to "does this file contribute to the graph?" exists to
     * drift from this one.
     */
    graphInputs: GraphInputRecord;
}>;
//# sourceMappingURL=code-graph.d.ts.map