/** * `@-mention` context expansion for the CLI chat input. * * When the user types `@path/to/file.ts` inline in their prompt, we * detect those mentions, read the file contents, and inject them as an * "[Attached files]" block prepended to the prompt — same format as the * explicit `/add` command, so the agent sees a single, consistent shape. * * Supported mention forms (case-sensitive `@`): * @src/index.ts → relative-to-project-root file * @./local.ts → relative-to-project-root file too * @/abs/path.ts → absolute path * @"path with space.ts" → quoted (spaces/special chars allowed) * @'path with space.ts' → single-quoted variant * * A `@` immediately followed by whitespace, another `@`, or a non-path * character (e.g. an email like `user@host`, or a GitHub `@handle`) is * left untouched. * * Mentions are resolved against the project root (or cwd when no * project is open). Files larger than `MAX_MENTION_BYTES` are skipped * with a warning rather than silently truncated — the user should * explicitly `/add` very large files if they really want them. */ /** Max file size we'll auto-inline from a mention (100 KB). */ export declare const MAX_MENTION_BYTES: number; /** Result of expanding `@-mentions` in a prompt. */ export interface MentionExpansionResult { /** The prompt with file contents prepended (or the original if no mentions). */ enrichedPrompt: string; /** * The prompt with each mention's `@` sigil removed but WITHOUT the attached * block — i.e. `enrichedPrompt` minus its header. Callers that merge several * expanders into one block need this: parsing the block back out of * `enrichedPrompt` with a regex silently left the file bodies behind and * attached every mentioned file twice. */ strippedPrompt: string; /** Successfully loaded files: `[fullPath, relativePath, content][]`. */ loaded: Array<{ fullPath: string; relativePath: string; content: string; }>; /** Mentions that couldn't be resolved, with a human-readable reason. */ failures: Array<{ mention: string; reason: string; }>; } /** * The raw text of a mention match (without the leading `@`). * Used internally by the tokenizer. */ interface MentionToken { /** Full match including `@`, for replacement. */ raw: string; /** The path portion (without quotes if it was quoted). */ path: string; /** Start index in the source string. */ start: number; /** End index (exclusive). */ end: number; } /** * The single source of truth for "may a mention start after this character?". * `MENTION_RE`'s lookbehind above and the editor's `detectMentionQuery` picker * MUST agree — when they diverged, the picker happily completed mentions * (e.g. after `]`) that the expander then ignored, so the file silently never * got attached. Import this rather than re-spelling the class. */ export declare const MENTION_BOUNDARY: RegExp; /** * Extract all `@-mention` tokens from `text`. Returns them in document * order. Pure (no FS) — testable without touching the disk. */ export declare function extractMentions(text: string): MentionToken[]; export interface MentionExpansionOptions { /** * The root directory relative mentions (`src/a.ts`, `./a.ts`, `.`) are * resolved against. Usually the project root or `process.cwd()`. */ root: string; } /** * Expand all `@-mentions` in `prompt`: load each referenced file, * prepend the contents as an `[Attached files]` block, and strip the * `@path` tokens from the visible prompt (replacing them with a bare * path so the agent still sees what was referenced). * * Failures (missing file, too large, not a file) are collected and * returned rather than thrown — the caller decides how to surface them. */ export declare function expandMentions(prompt: string, opts: MentionExpansionOptions): MentionExpansionResult; /** * Max total bytes of file content we'll inline from a single `@folder` * mention (200 KB). Prevents a huge directory from blowing the context * window — the user can raise this via explicit `/add` if they really * want everything. */ export declare const MAX_FOLDER_BYTES: number; /** One `@folder ` mention match. */ interface FolderToken { /** Full match including `@folder `, for display in failures. */ raw: string; /** The path portion (after `@folder `). */ path: string; /** Start index of the match (pointing at the `@`). */ start: number; /** End index (exclusive). */ end: number; } /** * Extract all `@folder`/`@dir` mentions from `text`. Pure (no FS). * Returns them in document order. */ export declare function extractFolderMentions(text: string): FolderToken[]; /** * Expand all `@folder`/`@dir` mentions in `prompt`: recursively read * every source file under each directory, and return them in the same * shape as `expandMentions` (so the caller can merge the results). * * Skips the same ignored directories (`node_modules`, `.git`, …) and * binary/generated extensions as the autocomplete scanner. Caps total * content per mention at `MAX_FOLDER_BYTES` so a single huge tree * can't blow the context window. * * Sync (filesystem reads only) — call before or after `expandMentions`. */ export declare function expandFolderMentions(prompt: string, opts: MentionExpansionOptions): MentionExpansionResult; /** * Expand both `@folder` and `@file` mentions in one pass, merging the * loaded files into a single `[Attached files]` block (instead of two * separate blocks when called back-to-back). * * `@web` mentions are async and handled separately in `webFetch.ts`. */ export declare function expandFileAndFolderMentions(prompt: string, opts: MentionExpansionOptions): MentionExpansionResult; /** Format the `[Attached files]` block prepended to the enriched prompt. */ export declare function formatFileBlock(files: Array<{ relativePath: string; content: string; }>): string; export interface MentionSuggestion { /** Display label for the picker (e.g. `src/index.ts`). */ label: string; /** The path to insert after `@` when picked. */ insertPath: string; /** A short hint — the file's directory or type. */ detail: string; } export interface SuggestOptions { /** Root directory to scan. */ root: string; /** Filter prefix typed so far (e.g. `src/ind` from `@src/ind`). */ query?: string; /** Max suggestions to return. */ limit?: number; /** Extra directories to skip (merged with the defaults). */ extraIgnoreDirs?: string[]; } /** * Build (or reuse from cache) the flat list of suggestible files under * `root`, then filter by `query`. The scan walks up to `maxScan` files, * skipping ignored directories and binary/generated extensions. */ export declare function suggestMentions(opts: SuggestOptions): MentionSuggestion[]; /** Clear the suggestion cache. Call between tests so fixtures don't leak. */ export declare function clearSuggestionCache(): void; /** * True if `fullPath` looks like it holds secrets, judged by its basename and, * for a symlink, by the basename of the file it points at: a repo can commit * `.env.example -> .env` or `tsconfig.json -> ../.env`, and every read * follows the link. */ export declare function isSensitiveFile(fullPath: string): boolean; /** * True if a file named on its own (an @-mention, or a path smart context * picks out of the prompt) must not be inlined: secrets, and committed `.env` * templates, which can still hold a real value. Both paths use this one rule, * so a mention the user was told is refused never reaches the provider * another way. */ export declare function isRefusedMention(fullPath: string): boolean; /** * True if `text` holds private-key material anywhere. Keys are saved under * any name (`~/.ssh/github`, `deploy/prod`), so the name check alone lets * them through, and a key can sit past the top of a JSON or YAML file. */ export declare function looksLikeKeyMaterial(text: string): boolean; /** * True if `fullPath`, with symlinks resolved, lies inside `dir` (also * resolved). False when either doesn't exist. */ export declare function resolvesWithin(fullPath: string, dir: string): boolean; /** One `@git ` mention match. */ interface GitToken { raw: string; ref: string; start: number; end: number; } /** * Extract all `@git ` mentions from `text`. Pure (no FS / no git). */ export declare function extractGitMentions(text: string): GitToken[]; /** * Expand all `@git ` mentions in `prompt`: resolve each ref to * git content (diff, file-at-ref, or commit patch) and inject it as * a `[Git ref]` block. Sync (git is run via `execSync`). * * The block is appended *after* any `[Attached files]` block from * `@folder`/`@file` expansion, so the final prompt reads: * * [Attached files] … [Git ref] … */ export declare function expandGitMentions(prompt: string, opts: MentionExpansionOptions): Promise; export {};