socraticode
Version:
SocratiCode — MCP server for local codebase indexing, semantic search, and code dependency graphs. All private, all local via Docker.
287 lines • 15.1 kB
TypeScript
export declare const SOCRATICODE_VERSION: string;
/** File-watcher policy for this MCP process. */
export type WatcherMode = "auto" | "manual" | "off" | "git";
/**
* Resolve SOCRATICODE_WATCHER at call time.
*
* Reading lazily keeps test and embedded-host configuration predictable while
* the startup entry point still validates the value before accepting tools.
* Unknown values fail loudly: silently restoring automatic writes would break
* the user's deliberate snapshot guarantee.
*/
export declare function getWatcherMode(): WatcherMode;
export declare const QDRANT_PORT: number;
export declare const QDRANT_GRPC_PORT: number;
export declare const QDRANT_HOST: string;
export declare const QDRANT_API_KEY: string | undefined;
/** Full URL for remote/cloud Qdrant instances (e.g. https://xyz.aws.cloud.qdrant.io:6333).
* When set, takes precedence over QDRANT_HOST + QDRANT_PORT. */
export declare const QDRANT_URL: string | undefined;
/** `managed` = Docker-managed local Qdrant (default).
* `external` = user-provided remote or cloud Qdrant instance (no Docker management). */
export declare const QDRANT_MODE: "managed" | "external";
export declare const QDRANT_CONTAINER_NAME = "socraticode-qdrant";
export declare const QDRANT_IMAGE = "qdrant/qdrant:v1.17.0";
/**
* Optional prefix prepended to every Qdrant collection name SocratiCode
* creates, queries or deletes. Useful when sharing one Qdrant instance with
* other applications (Open-WebUI, custom RAG tools, etc.) or when running
* multiple SocratiCode instances against one Qdrant for separation between
* projects, environments, or per-user indexes.
*
* Default is the empty string, which keeps every collection name unchanged
* from previous releases — fully backwards compatible.
*
* Validated at module load: Qdrant accepts only `[a-zA-Z0-9_-]` in
* collection names, so the prefix must too. An invalid prefix throws
* before any Qdrant call is made, with a message naming the offending
* value so the misconfiguration is obvious.
*/
export declare const QDRANT_COLLECTION_PREFIX: string;
/**
* Resolve the Qdrant REST port from a URL.
* Returns the explicit port if present (e.g. `:8443`),
* otherwise `443` for `https://` or `6333` for `http://`.
*/
export declare function resolveQdrantPort(url: string): number;
export declare const OLLAMA_PORT: number;
export declare const OLLAMA_HOST: string;
export declare const OLLAMA_CONTAINER_NAME = "socraticode-ollama";
export declare const OLLAMA_IMAGE = "ollama/ollama:latest";
/** Default number of search results returned by codebase_search.
* Override via SEARCH_DEFAULT_LIMIT env var (1-50). */
export declare const SEARCH_DEFAULT_LIMIT: number;
/** Default minimum RRF score threshold.
* Results below this score are filtered out. 0 disables filtering.
* Override via SEARCH_MIN_SCORE env var (0-1). */
export declare const SEARCH_MIN_SCORE: number;
export declare const CHUNK_SIZE = 100;
export declare const CHUNK_OVERLAP = 10;
export declare const INDEX_BATCH_SIZE = 50;
/** Maximum file size in bytes. Files larger than this are skipped during indexing.
* Default: 5 MB. Override via MAX_FILE_SIZE_MB env var. */
export declare const MAX_FILE_BYTES: number;
/** Maximum file size in bytes for code graph AST parsing.
* Graph parsing loads the entire file into memory for AST analysis,
* so the limit is lower than the indexing limit. Default: 1 MB. */
export declare const MAX_GRAPH_FILE_BYTES = 1000000;
/**
* Qdrant's default `service.max_request_size_mb` (32 MiB), in bytes. A request
* body over this is rejected with HTTP 400 before it reaches the collection, so
* it is a hard ceiling on any single upsert, not a tuning knob we control: the
* server enforces it and self-hosted deployments may set it lower.
*/
export declare const QDRANT_MAX_REQUEST_BYTES = 33554432;
/**
* Byte budget we pack a single upsert body up to. Deliberately below
* {@link QDRANT_MAX_REQUEST_BYTES} so the JSON envelope around the points
* (and any server-side accounting that differs slightly from ours) still fits
* under the hard ceiling.
*/
export declare const QDRANT_UPSERT_BUDGET_BYTES = 25165824;
/**
* Maximum average line length (in characters) before a file is treated as
* minified/bundled and switched to character-based chunking. Minified files
* have very long lines that would make line-based chunks exceed the embedding
* model's context window.
*/
export declare const MAX_AVG_LINE_LENGTH = 500;
/**
* Hard character limit per chunk payload — the universal safety net applied
* to every chunk regardless of chunking strategy (AST, line-based, or
* character-based).
*
* Must be kept below CHARS_PER_TOKEN_ESTIMATE × model_context_length so that
* the provider-level pretruncation is not needed, leaving it as the last-resort
* defence rather than a routine one.
* CHARS_PER_TOKEN_ESTIMATE is per provider: 1.0 for ollama, 3.0 for the rest.
* Ollama is therefore the tightest case — a 2048-token context gives a
* 2048-char budget, which is what the 2000 default is sized against.
*
* The cap bounds the chunk body only. `prepareDocumentText` prepends
* `documentPrefix()` and — unless EMBEDDING_DOCUMENT_INCLUDE_PATH turns it off
* — the path and a newline, so the text that reaches the provider is longer
* than the cap by an amount that is not a constant: the prefix is configurable
* and the path length varies per chunk. With the path on, a 2000-char chunk
* under the 17-char default prefix already crosses a 2048-char budget once the
* path exceeds 30 characters. Lower MAX_CHUNK_CHARS when the whole embedded
* text has to stay inside the budget.
*
* Provider pre-truncation still stands behind this, and it always runs: each
* provider substitutes a conservative default when the resolved context length
* is 0, which is what `guessContextLength()` returns for a model outside
* MODEL_CONTEXT_LENGTHS. That default (2048 tokens everywhere except openai's
* 8191) need not match the real model, so set EMBEDDING_CONTEXT_LENGTH to size
* it against the model actually in use.
*
* Override with MAX_CHUNK_CHARS when the embedding model's context is smaller
* than the default assumes.
*
* On a collection indexed as format 2 the cap is a split boundary on every
* path, not a truncation point. A collection stored below that version keeps
* truncating, so its stored representation stays what its profile says.
* `chunkFileContent` and `chunkArtifactContent` both cut by line count
* (CHUNK_SIZE), so a chunk can come out longer than a cap counted in
* characters; `splitToCharCap` then divides it into as many chunks as it needs.
* On format 2 no content is dropped, so a lower cap yields more chunks rather
* than less indexed content. (Chunks still overlap where the strategy that produced them
* overlaps — CHUNK_OVERLAP lines on the line-based path — and a piece holding
* only whitespace is dropped.)
*
* It used to truncate on three of the four paths, and that dropped a great deal
* of content: a window of CHUNK_SIZE lines overflowed as soon as its lines
* averaged more than MAX_CHUNK_CHARS / CHUNK_SIZE characters, which most source
* and nearly all prose does. (A file below CHUNK_SIZE lines becomes one chunk
* and can stay under the cap regardless of its line lengths.) What was cut
* reached neither the vector, nor the payload, nor the BM25 text, and no search
* could retrieve it. Continuations do not overlap their parent — as with
* adjacent AST chunks, which are cut at top-level declaration boundaries and
* leave **no overlap** either.
*
* Raising it beyond CHARS_PER_TOKEN_ESTIMATE × model_context_length gains
* nothing at embed time: the provider pre-truncates, so the extra characters
* reach the stored payload and the BM25 text but are not represented in the
* vector.
*
* Changing this changes the stored chunks. Existing collections retain their
* persisted effective cap until removed and freshly indexed.
*/
export declare const MAX_CHUNK_CHARS: number;
/** Maximum BFS depth for `codebase_impact` (blast radius) queries. */
export declare const MAX_IMPACT_DEPTH = 10;
/** Maximum DFS depth for `codebase_flow` (call-flow tracing) queries. */
export declare const MAX_FLOW_DEPTH = 10;
/** Number of name-index shards (a–z + `_` for everything else). */
export declare const SYMBOL_NAME_SHARDS = 27;
/** Number of reverse-call file-index shards (single-byte SHA1 prefix). */
export declare const SYMBOL_REVERSE_SHARDS = 256;
/** LRU capacity (in files) for lazy-loaded per-file symbol payloads. */
export declare const SYMBOL_FILE_LRU_SIZE = 500;
/**
* Conventional entry-point function names per language. Used by
* `detectEntryPoints()` heuristic #2.
*/
export declare const ENTRY_POINT_NAMES: Record<string, Set<string>>;
/**
* Normalize path separators to forward slashes.
* On POSIX this is a no-op; on Windows it replaces every `\` with `/`.
* Used for graph node keys, fileSet entries, and query inputs so that
* lookups succeed regardless of the host OS separator convention.
*/
export declare function toForwardSlash(p: string): string;
/**
* Hash file content for change detection.
*
* Lives here rather than beside its first caller because two independent
* change detectors now compare against it — the index's own file-hash map and
* the code graph's recorded inputs — and a second implementation of "the hash
* of this file" would let the two disagree about whether a file changed while
* both looked correct.
*/
export declare function hashContent(content: string): string;
/** Mixed templates parsed structurally; only captured expressions are parsed as Elixir. */
export declare const ELIXIR_TEMPLATE_EXTENSIONS: Set<string>;
export declare const SUPPORTED_EXTENSIONS: Set<string>;
/**
* Parse a comma-separated list of file extensions into a Set.
* Normalizes inputs: trims whitespace, ensures leading dot.
* Example: ".tpl, .blade, hbs" → Set([".tpl", ".blade", ".hbs"])
*/
export declare function parseExtraExtensions(value?: string): Set<string>;
/** Extra file extensions from EXTRA_EXTENSIONS env var (global default). */
export declare const EXTRA_EXTENSIONS: Set<string>;
/**
* Merge EXTRA_EXTENSIONS env var with an optional tool parameter value.
* Returns the combined set of extra extensions.
*/
export declare function mergeExtraExtensions(toolParam?: string): Set<string>;
/** Files that are always indexed regardless of extension */
export declare const SPECIAL_FILES: Set<string>;
/**
* Parse the `EXTENSION_LANGUAGE_MAP` env var (format `.inc:php,.module:php`).
* Returns a map of input extension → canonical extension of the target
* language, plus the list of entries that were rejected (malformed, or a
* target language with no AST grammar) so the caller can warn loudly.
* Extensions are normalized (lowercased, leading dot ensured); a repeated
* extension takes its last value.
*/
export declare function parseExtensionLanguageMap(value?: string): {
map: Map<string, string>;
invalid: string[];
};
/**
* Custom extension → canonical extension overrides from EXTENSION_LANGUAGE_MAP.
* Consulted by `getLanguageFromExtension`, `getAstGrepLang`, and the indexable
* checks so a mapped extension is treated as its target language end to end
* (label, AST chunking, symbols, call graph, discovery).
*/
export declare const EXTENSION_LANGUAGE_MAP: Map<string, string>;
/** Entries from EXTENSION_LANGUAGE_MAP that were rejected (warned at startup). */
export declare const EXTENSION_LANGUAGE_MAP_INVALID: string[];
/**
* Map a file extension to a language label. An EXTENSION_LANGUAGE_MAP override
* is resolved through the target language's canonical extension so the label
* matches what a native file of that language would get.
*/
export declare function getLanguageFromExtension(ext: string, override?: Map<string, string>): string;
/**
* Bytes of file head inspected for extensionless language detection. Read by the
* two functions that bound a detection window — `readFileHead` on disk and
* `detectExtensionFromSource` in memory — so every site that decides an
* extensionless file's language scores the same bytes and cannot disagree about it.
*/
export declare const DETECT_HEAD_BYTES = 8192;
/**
* Whether content-based detection of extensionless files is enabled.
* Default ON (strictly additive — only adds files, never removes). `INDEX_EXTENSIONLESS=false` or `=0`
* restores the pre-detection behavior (extensionless files are never indexed
* unless their exact name is in {@link SPECIAL_FILES}). Read lazily so a mixed
* fleet reads one value per scan and tests can toggle it via `vi.stubEnv`.
*/
export declare function indexExtensionlessEnabled(): boolean;
/**
* Detect a canonical file extension for an extensionless file from the first
* ~8 KiB of its content. Returns `.sh`, `.py`, `.js`, `.rb`, `.php`, `.lua`,
* `.txt`, or `null` (not indexable code). PURE — no I/O.
*
* A NUL byte (0x00) survives UTF-8/latin1 decoding as U+0000, so the Stage-0
* binary guard on the decoded string is equivalent to a raw-byte check and
* also rejects UTF-16 (its interleaved NUL bytes).
*/
export declare function detectExtensionlessExtension(contentHead: string): string | null;
/**
* Godot engine classes that are always available without `class_name` or
* `preload`. When a receiver type resolves to one of these, the method call
* is a Godot engine API call — not a project symbol — and should be filtered
* from the unresolved callee list rather than counted against resolution %.
*
* Source: Godot 4.x class reference (finite, documented set).
*/
export declare const GODOT_BUILTIN_CLASSES: Set<string>;
/**
* Godot built-in utility functions available in any GDScript context without
* import or class prefix. Calls to these should not count against resolution %.
*
* Source: Godot 4.x @GlobalScope utility functions.
*/
export declare const GODOT_BUILTIN_FUNCTIONS: Set<string>;
/**
* The leading segment a C# edge keeps for a `global::`-anchored path
* (`global::App.Calc`): the path names members of the global namespace only,
* never a scope the reference sits in. A path written through a `using`
* alias declared in a namespace block carries that namespace as its anchor
* instead (`App.Shop::Billing.Calc`), and is looked up from there outward.
*/
export declare const CS_GLOBAL_ANCHOR = "global::";
/**
* .NET framework and language-level type names a C# file names without the
* project declaring them: `Task`, `List`, `DateTime`, and the conventional
* generic parameter names. Extraction records them like any other type; a
* reference to one that no C# file of the project declares — bare or
* qualified (`System.Threading.Tasks.Task`) — is marked `engine` at
* resolution rather than `unresolved`, as `TS_BUILTIN_TYPES` keeps them out
* for TypeScript, so the unresolved share reads the project's own types. A
* project that declares its own `Task` keeps its references.
*/
export declare const CS_BUILTIN_TYPES: Set<string>;
//# sourceMappingURL=constants.d.ts.map