@buildautomaton/cli 0.1.78 → 0.1.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/files/browser/activity-shared.ts", "../src/files/browser/activity-types.ts", "../src/files/browser/counts.ts", "../src/files/browser/publish.ts", "../src/files/browser/listeners.ts", "../src/files/read/cancel-background-resolve-priming.ts", "../src/files/browser/begin-end.ts", "../src/files/browser/status.ts", "../src/files/browser/activity-tracker.ts", "../src/runtime/yield-to-event-loop.ts", "../src/code-nav/symbol-index/deferred-indexing.ts", "../src/files/browser/idle-yield.ts", "../src/files/browser/in-flight.ts", "../src/cli-log-level.ts", "../src/log.ts", "../src/sqlite/sqlite-errors.ts", "../src/sqlite/sqlite-lock-path.ts", "../src/sqlite/code-nav-cache/code-nav-cache-paths.ts", "../src/sqlite/code-nav-cache/code-nav-cache-log.ts", "../src/runtime/cli-process-interrupt.ts", "../src/sqlite/code-nav-cache/code-nav-cache-availability.ts", "../src/code-nav/symbol-index/worker/shutdown-state.ts", "../src/sqlite/code-nav-cache/code-nav-cache-access-depth.ts", "../src/sqlite/sqlite-lock-retry.ts", "../src/sqlite/access/bindings.ts", "../src/sqlite/sqlite-pragmas.ts", "../src/sqlite/access/open.ts", "../src/sqlite/access/with-async.ts", "../src/sqlite/access/with-sync.ts", "../src/sqlite/access/index.ts", "../src/sqlite/read-migration-sql.ts", "../src/sqlite/run-sqlite-migrations.ts", "../src/sqlite/code-nav-cache/migrate-code-nav-cache-sqlite.ts", "../src/sqlite/code-nav-cache/code-nav-cache-sqlite-work-lock.ts", "../src/sqlite/code-nav-cache/code-nav-cache-wrapped-access.ts", "../src/sqlite/code-nav-cache/instance.ts", "../src/sqlite/code-nav-cache/database.ts", "../src/paths/normalize-resolved-path.ts", "../src/sqlite/code-nav-cache/code-nav-cache-sqlite-transaction.ts", "../src/code-nav/yield-during-work.ts", "../src/sqlite/cli-sqlite-paths.ts", "../src/files/index/constants.ts", "../src/prompt-turn-queue/paths.ts", "../src/sqlite/legacy_migration/archive-to-old-version.ts", "../src/sqlite/legacy_migration/archive-file-index-json.ts", "../src/sqlite/legacy_migration/import-agent-sessions-from-disk.ts", "../src/sqlite/legacy_migration/parse-persisted-queue-json.ts", "../src/sqlite/legacy_migration/import-prompt-queues-from-disk.ts", "../src/sqlite/legacy_migration/import-cli-legacy-disk-data.ts", "../src/sqlite/migrate-cli-sqlite.ts", "../src/sqlite/cli-database.ts", "../src/files/index/walk-workspace-tree.ts", "../../../node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js", "../src/code-nav/gitignore-filter.ts", "../src/code-nav/language-registry.ts", "../src/code-nav/walk-code-nav-files.ts", "../src/code-nav/symbol-index/sqlite/symbol-index-version.ts", "../src/files/cwd/bridge-root.ts", "../src/files/index/paths.ts", "../src/code-nav/symbol-index/sqlite/parent-path.ts", "../src/code-nav/symbol-index/storage/content-hash-check.ts", "../src/code-nav/symbol-index/storage/insert-symbol-content.ts", "../src/code-nav/symbol-index/storage/parent-file-map.ts", "../src/code-nav/symbol-index/storage/symbol-content-index.ts", "../src/code-nav/symbol-index/storage/effective-content.ts", "../src/code-nav/symbol-index/persistence/symbol-file-content-hash.ts", "../src/code-nav/symbol-index/sqlite/file-data-persistence.ts", "../src/code-nav/symbol-index/sqlite/population.ts", "../src/code-nav/symbol-index/sqlite/symbol-index-sqlite.ts", "../src/code-nav/symbol-index/sqlite/symbol-index-sqlite-lock.ts", "../src/code-nav/symbol-index/query/tag-query-shared.ts", "../src/code-nav/symbol-index/storage/file-content-load.ts", "../src/code-nav/symbol-index/storage/symbol-parent-file-map.ts", "../src/code-nav/symbol-index/build/load-indexed-file-entry.ts", "../src/code-nav/symbol-index/query/list-direct-import-targets.ts", "../src/code-nav/symbol-index/lifecycle/symbol-index-file-ready.ts", "../src/code-nav/symbol-index/imports/star-reexport-names.ts", "../src/code-nav/symbol-index/imports/star-reexport-upstream.ts", "../src/code-nav/symbol-index/imports/expand-star-reexports.ts", "../src/code-nav/symbol-index/persistence/persist-single-file.ts", "../src/code-nav/resolve-module-import-path.ts", "../src/code-nav/enrich-tag-module-paths.ts", "../src/code-nav/enrich-tag-module-paths-async.ts", "../src/code-nav/augment-function-type-param-references.ts", "../src/code-nav/augment-type-reference-tags.ts", "../src/code-nav/scope-chain.ts", "../src/code-nav/enrich-tag-scope.ts", "../src/code-nav/member-access/c.ts", "../src/code-nav/member-access/cpp.ts", "../src/code-nav/member-access/go.ts", "../src/code-nav/member-access/javascript.ts", "../src/code-nav/member-access/java.ts", "../src/code-nav/member-access/python.ts", "../src/code-nav/member-access/ruby.ts", "../src/code-nav/member-access/rust.ts", "../src/code-nav/member-access/tsx.ts", "../src/code-nav/member-access/typescript.ts", "../src/code-nav/member-access/registry.ts", "../src/code-nav/member-access/types.ts", "../src/code-nav/member-access/shared.ts", "../src/code-nav/member-access/index.ts", "../src/code-nav/tree-sitter-assets-dir.ts", "../src/code-nav/parser/tree-sitter-runtime.ts", "../src/code-nav/parser/parse-source-root.ts", "../src/code-nav/parser/run-tags-query.ts", "../src/code-nav/parser/tags-from-matches.ts", "../src/code-nav/parser/tags-from-matches-async.ts", "../src/code-nav/parser/extract-tags.ts", "../src/code-nav/parser-runtime.ts", "../src/code-nav/symbol-index/imports/shared.ts", "../src/code-nav/symbol-index/imports/c.ts", "../src/code-nav/symbol-index/imports/cpp.ts", "../src/code-nav/symbol-index/imports/ecma-script-imports.ts", "../src/code-nav/symbol-index/imports/ecma-script-exports.ts", "../src/code-nav/symbol-index/imports/ecma-script.ts", "../src/code-nav/symbol-index/imports/go.ts", "../src/code-nav/symbol-index/imports/java.ts", "../src/code-nav/symbol-index/imports/python.ts", "../src/code-nav/symbol-index/imports/ruby.ts", "../src/code-nav/symbol-index/imports/rust.ts", "../src/code-nav/symbol-index/imports/index.ts", "../src/code-nav/symbol-index/build/read-index-source.ts", "../src/code-nav/symbol-index/build/workspace-files.ts", "../src/code-nav/symbol-index/build/extract-file-symbol-data.ts", "../src/code-nav/symbol-index/build/index-one-symbol-file-for-build.ts", "../src/code-nav/symbol-index/build/normalize-symbol-index-rel-path.ts", "../src/code-nav/symbol-index/build/ensure-symbol-index-file-impl.ts", "../src/code-nav/symbol-index/build/build-symbol-index-impl.ts", "../src/code-nav/symbol-index/build/build-symbol-index-host.ts", "../src/code-nav/symbol-index/build/ensure-symbol-index-file-host.ts", "../src/code-nav/symbol-index/lifecycle/normalize-symbol-index-path.ts", "../src/code-nav/symbol-index/build/update-symbol-index-file-impl.ts", "../src/code-nav/symbol-index/build/update-symbol-index-file-host.ts", "../src/code-nav/symbol-index/worker/post-message.ts", "../src/code-nav/symbol-index/worker/index-handlers.ts", "../src/code-nav/symbol-index/scheduler/task-priority-heap.ts", "../src/code-nav/symbol-index/scheduler/task-queue-types.ts", "../src/code-nav/symbol-index/scheduler/task-queue-store.ts", "../src/code-nav/symbol-index/scheduler/task-queue-core.ts", "../src/code-nav/symbol-index/scheduler/task-queue-worker.ts", "../src/code-nav/symbol-index/worker/queue-handlers.ts", "../src/code-nav/symbol-index/build/register-symbol-index-parent.ts", "../src/code-nav/symbol-index/scheduler/symbol-index-warmup-host.ts", "../src/code-nav/symbol-index/worker/setup-handlers.ts", "../src/code-nav/symbol-index/worker/handle-message.ts", "../src/code-nav/symbol-index/worker/host.ts", "../src/code-nav/symbol-index/worker/entry.ts"],
4
- "sourcesContent": ["const ACTIVITY_INDEX_REQUESTS = 0;\nconst ACTIVITY_INDEX_READS = 1;\n/** Unix seconds \u2014 fits Int32 until ~2038; sufficient for browse cooldown checks. */\nconst ACTIVITY_INDEX_LAST_ACTIVITY_SEC = 2;\n\nconst activitySharedBuffer = new SharedArrayBuffer(3 * Int32Array.BYTES_PER_ELEMENT);\nconst mainActivityView = new Int32Array(activitySharedBuffer);\n\nlet workerActivityView: Int32Array | null = null;\n\nexport function getFileBrowserActivitySharedBuffer(): SharedArrayBuffer {\n return activitySharedBuffer;\n}\n\nexport function bindFileBrowserActivitySharedBuffer(buffer: SharedArrayBuffer): void {\n workerActivityView = new Int32Array(buffer);\n}\n\nexport function syncFileBrowserActivityToShared(params: {\n inFlightRequests: number;\n inFlightReads: number;\n lastActivityAt: number;\n}): void {\n Atomics.store(mainActivityView, ACTIVITY_INDEX_REQUESTS, params.inFlightRequests);\n Atomics.store(mainActivityView, ACTIVITY_INDEX_READS, params.inFlightReads);\n Atomics.store(\n mainActivityView,\n ACTIVITY_INDEX_LAST_ACTIVITY_SEC,\n Math.floor(params.lastActivityAt / 1000),\n );\n}\n\nexport function readFileBrowserActivityFromShared(): {\n inFlightRequests: number;\n inFlightReads: number;\n lastActivityAt: number;\n} {\n const view = workerActivityView ?? mainActivityView;\n return {\n inFlightRequests: Atomics.load(view, ACTIVITY_INDEX_REQUESTS),\n inFlightReads: Atomics.load(view, ACTIVITY_INDEX_READS),\n lastActivityAt: Atomics.load(view, ACTIVITY_INDEX_LAST_ACTIVITY_SEC) * 1000,\n };\n}\n", "/** Pause symbol indexing briefly after file browser activity so reads are not blocked mid-parse. */\nexport const BROWSE_INDEX_COOLDOWN_MS = 2_500;\n\nexport type FileBrowserActivitySnapshot = {\n inFlightRequests: number;\n inFlightReads: number;\n lastActivityAt: number;\n};\n", "import type { FileBrowserActivitySnapshot } from './activity-types.js';\n\nlet inFlightRequests = 0;\nlet inFlightReads = 0;\n/** Browse list/request activity only \u2014 not updated for reads (avoids extending browse cooldown). */\nlet lastBrowseRequestActivityAt = 0;\n\n/** Worker mirror updated from the main thread over postMessage. */\nlet workerMirror: FileBrowserActivitySnapshot = {\n inFlightRequests: 0,\n inFlightReads: 0,\n lastActivityAt: 0,\n};\n\nexport function touchBrowseRequestActivity(): void {\n lastBrowseRequestActivityAt = Date.now();\n}\n\nexport function snapshotFromMain(): FileBrowserActivitySnapshot {\n return {\n inFlightRequests,\n inFlightReads,\n lastActivityAt: lastBrowseRequestActivityAt,\n };\n}\n\nexport function getWorkerMirror(): FileBrowserActivitySnapshot {\n return workerMirror;\n}\n\nexport function setWorkerMirror(snapshot: FileBrowserActivitySnapshot): void {\n workerMirror = snapshot;\n}\n\nexport function incrementInFlightRequests(): void {\n inFlightRequests += 1;\n touchBrowseRequestActivity();\n}\n\nexport function decrementInFlightRequests(): void {\n inFlightRequests = Math.max(0, inFlightRequests - 1);\n touchBrowseRequestActivity();\n}\n\nexport function incrementInFlightReads(): void {\n inFlightReads += 1;\n}\n\nexport function decrementInFlightReads(): void {\n inFlightReads = Math.max(0, inFlightReads - 1);\n}\n", "import { isMainThread } from 'node:worker_threads';\nimport {\n readFileBrowserActivityFromShared,\n syncFileBrowserActivityToShared,\n} from './activity-shared.js';\nimport type { FileBrowserActivitySnapshot } from './activity-types.js';\nimport { snapshotFromMain, setWorkerMirror } from './counts.js';\n\nlet activityPublisher: ((snapshot: FileBrowserActivitySnapshot) => void) | null = null;\n\nexport function registerFileBrowserActivityPublisher(\n publisher: (snapshot: FileBrowserActivitySnapshot) => void,\n): void {\n activityPublisher = publisher;\n}\n\nexport function applyFileBrowserActivityFromMain(snapshot: FileBrowserActivitySnapshot): void {\n setWorkerMirror(snapshot);\n}\n\nexport function syncMainActivityToShared(): void {\n syncFileBrowserActivityToShared(snapshotFromMain());\n}\n\nexport function currentFileBrowserActivity(): FileBrowserActivitySnapshot {\n if (isMainThread) return snapshotFromMain();\n return readFileBrowserActivityFromShared();\n}\n\nfunction publishActivityToWorker(): void {\n if (!isMainThread) return;\n activityPublisher?.(snapshotFromMain());\n}\n\n/** Sync current browse/read activity to the symbol index worker (after DB init). */\nexport function publishFileBrowserActivityToWorker(): void {\n publishActivityToWorker();\n}\n\nexport function getFileBrowserActivitySnapshot(): FileBrowserActivitySnapshot {\n return snapshotFromMain();\n}\n\nexport function publishAfterActivityChange(): void {\n syncMainActivityToShared();\n publishActivityToWorker();\n}\n", "const activityListeners = new Set<() => void>();\nconst requestStartListeners = new Set<() => void>();\nconst readStartListeners = new Set<() => void>();\n\nexport function registerFileBrowserActivityListener(listener: () => void): () => void {\n activityListeners.add(listener);\n return () => {\n activityListeners.delete(listener);\n };\n}\n\nexport function registerFileBrowserRequestStartListener(listener: () => void): () => void {\n requestStartListeners.add(listener);\n return () => {\n requestStartListeners.delete(listener);\n };\n}\n\nexport function registerFileBrowserReadStartListener(listener: () => void): () => void {\n readStartListeners.add(listener);\n return () => {\n readStartListeners.delete(listener);\n };\n}\n\nexport function notifyFileBrowserActivity(): void {\n for (const listener of activityListeners) listener();\n}\n\nexport function notifyFileBrowserRequestStart(): void {\n for (const listener of requestStartListeners) listener();\n}\n\nexport function notifyFileBrowserReadStart(): void {\n for (const listener of readStartListeners) listener();\n}\n", "let primeResolveEpoch = 0;\n\n/** Bumped when interactive reads start so list priming stops immediately. */\nexport function cancelBackgroundResolvePriming(): number {\n primeResolveEpoch += 1;\n return primeResolveEpoch;\n}\n\nexport function currentBackgroundResolvePrimingEpoch(): number {\n return primeResolveEpoch;\n}\n\n/** @internal Test helper. */\nexport function resetBackgroundResolvePrimingForTests(): void {\n primeResolveEpoch = 0;\n}\n", "import { cancelBackgroundResolvePriming } from '../read/cancel-background-resolve-priming.js';\nimport {\n decrementInFlightReads,\n decrementInFlightRequests,\n incrementInFlightReads,\n incrementInFlightRequests,\n} from './counts.js';\nimport {\n notifyFileBrowserActivity,\n notifyFileBrowserReadStart,\n notifyFileBrowserRequestStart,\n} from './listeners.js';\nimport { publishAfterActivityChange } from './publish.js';\n\nfunction beginFileBrowserActivity(\n kind: 'request' | 'read',\n notifyStart: () => void,\n): void {\n if (kind === 'request') {\n incrementInFlightRequests();\n } else {\n incrementInFlightReads();\n cancelBackgroundResolvePriming();\n }\n publishAfterActivityChange();\n notifyStart();\n notifyFileBrowserActivity();\n}\n\nfunction endFileBrowserActivity(kind: 'request' | 'read'): void {\n if (kind === 'request') {\n decrementInFlightRequests();\n } else {\n decrementInFlightReads();\n }\n publishAfterActivityChange();\n}\n\nexport function beginFileBrowserRequest(): void {\n beginFileBrowserActivity('request', notifyFileBrowserRequestStart);\n}\n\nexport function endFileBrowserRequest(): void {\n endFileBrowserActivity('request');\n}\n\nexport function beginFileBrowserRead(): void {\n beginFileBrowserActivity('read', notifyFileBrowserReadStart);\n}\n\nexport function endFileBrowserRead(): void {\n endFileBrowserActivity('read');\n}\n", "import { currentFileBrowserActivity } from './publish.js';\n\nexport function fileBrowserRequestInFlight(): boolean {\n return currentFileBrowserActivity().inFlightRequests > 0;\n}\n\nexport function getFileBrowserInFlightReadCount(): number {\n return currentFileBrowserActivity().inFlightReads;\n}\n\nexport function fileBrowserReadInFlight(): boolean {\n return getFileBrowserInFlightReadCount() > 0;\n}\n", "export { applyFileBrowserActivityFromMain } from './publish.js';\nexport {\n registerFileBrowserActivityListener,\n registerFileBrowserReadStartListener,\n registerFileBrowserRequestStartListener,\n} from './listeners.js';\nexport {\n getFileBrowserActivitySnapshot,\n publishFileBrowserActivityToWorker,\n registerFileBrowserActivityPublisher,\n} from './publish.js';\nexport {\n beginFileBrowserRead,\n beginFileBrowserRequest,\n endFileBrowserRead,\n endFileBrowserRequest,\n} from './begin-end.js';\nexport {\n fileBrowserReadInFlight,\n fileBrowserRequestInFlight,\n getFileBrowserInFlightReadCount,\n} from './status.js';\n\nexport { currentFileBrowserActivity } from './publish.js';\n", "/**\n * Resolves after the current stack clears so other I/O, timers, and WebSocket\n * callbacks can run. Prefer this over long synchronous loops on the bridge path.\n */\nexport function yieldToEventLoop(): Promise<void> {\n return new Promise((resolve) => setImmediate(resolve));\n}\n", "/** Thrown when background indexing should yield to an in-flight file browser request. */\nexport class SymbolIndexDeferredError extends Error {\n constructor() {\n super('Symbol indexing deferred for file browser');\n this.name = 'SymbolIndexDeferredError';\n }\n}\n\nexport function isSymbolIndexDeferredError(err: unknown): err is SymbolIndexDeferredError {\n return err instanceof SymbolIndexDeferredError;\n}\n", "import { isMainThread } from 'node:worker_threads';\nimport { yieldToEventLoop } from '../../runtime/yield-to-event-loop.js';\nimport { SymbolIndexDeferredError } from '../../code-nav/symbol-index/deferred-indexing.js';\nimport { BROWSE_INDEX_COOLDOWN_MS } from './activity-types.js';\nimport {\n currentFileBrowserActivity,\n getFileBrowserInFlightReadCount,\n} from './activity-tracker.js';\n\n/** True while browse/read is active or browse recently finished \u2014 pause background indexing. */\nexport function isBridgeBrowseInteractiveActive(): boolean {\n const { inFlightRequests, inFlightReads, lastActivityAt } = currentFileBrowserActivity();\n if (inFlightRequests > 0) return true;\n if (inFlightReads > 0) return true;\n if (lastActivityAt === 0) return false;\n return Date.now() - lastActivityAt < BROWSE_INDEX_COOLDOWN_MS;\n}\n\n/** Throw when file browser work should preempt background indexing (e.g. before sync tree-sitter). */\nexport function assertBackgroundIndexingAllowed(): void {\n if (isBridgeBrowseInteractiveActive()) throw new SymbolIndexDeferredError();\n}\n\n/** Wait until no file reads are in flight. */\nexport async function yieldUntilFileBrowserReadsIdle(pollMs = 5): Promise<void> {\n while (getFileBrowserInFlightReadCount() > 0) {\n await yieldToEventLoop();\n if (getFileBrowserInFlightReadCount() > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, pollMs));\n }\n }\n}\n\n/** Wait until browse requests finish and browse cooldown has elapsed (ignores in-flight reads). */\nexport async function yieldUntilFileBrowserBrowseIdle(pollMs = 5): Promise<void> {\n while (true) {\n const { inFlightRequests, lastActivityAt } = currentFileBrowserActivity();\n const browseCooldownDone =\n lastActivityAt === 0 || Date.now() - lastActivityAt >= BROWSE_INDEX_COOLDOWN_MS;\n if (inFlightRequests === 0 && browseCooldownDone) return;\n await yieldToEventLoop();\n await new Promise<void>((resolve) => setTimeout(resolve, pollMs));\n }\n}\n\n/** @deprecated Prefer {@link yieldUntilFileBrowserBrowseIdle} or {@link yieldUntilBackgroundIndexingAllowed}. */\nexport async function yieldUntilFileBrowserIdle(pollMs = 5): Promise<void> {\n await yieldUntilBackgroundIndexingAllowed(pollMs);\n}\n\n/** Wait until reads, browse, and browse cooldown allow background indexing/file walks. */\nexport async function yieldUntilBackgroundIndexingAllowed(pollMs = 5): Promise<void> {\n await yieldUntilFileBrowserReadsIdle(pollMs);\n await yieldUntilFileBrowserBrowseIdle(pollMs);\n}\n\n/** Yield to the event loop, then pause background work while file browser reads/browse are active. */\nexport async function yieldForBridgeInteractivePriority(): Promise<void> {\n await yieldToEventLoop();\n if (isMainThread) {\n await yieldUntilBackgroundIndexingAllowed();\n return;\n }\n assertBackgroundIndexingAllowed();\n}\n", "export {\n bindFileBrowserActivitySharedBuffer,\n getFileBrowserActivitySharedBuffer,\n} from './activity-shared.js';\n\nexport { BROWSE_INDEX_COOLDOWN_MS, type FileBrowserActivitySnapshot } from './activity-types.js';\n\nexport {\n applyFileBrowserActivityFromMain,\n beginFileBrowserRead,\n beginFileBrowserRequest,\n endFileBrowserRead,\n endFileBrowserRequest,\n fileBrowserReadInFlight,\n fileBrowserRequestInFlight,\n getFileBrowserActivitySnapshot,\n getFileBrowserInFlightReadCount,\n publishFileBrowserActivityToWorker,\n registerFileBrowserActivityListener,\n registerFileBrowserActivityPublisher,\n registerFileBrowserReadStartListener,\n registerFileBrowserRequestStartListener,\n} from './activity-tracker.js';\n\nexport {\n assertBackgroundIndexingAllowed,\n isBridgeBrowseInteractiveActive,\n yieldForBridgeInteractivePriority,\n yieldUntilBackgroundIndexingAllowed,\n yieldUntilFileBrowserBrowseIdle,\n yieldUntilFileBrowserIdle,\n yieldUntilFileBrowserReadsIdle,\n} from './idle-yield.js';\n", "export type CliLogVerbosity = 'info' | 'debug' | 'trace';\n\nlet verbosity: CliLogVerbosity = 'info';\n\nexport function setCliLogVerbosity(level: CliLogVerbosity): void {\n verbosity = level;\n}\n\nexport function getCliLogVerbosity(): CliLogVerbosity {\n return verbosity;\n}\n\nexport function isCliDebugOrTrace(): boolean {\n return verbosity === 'debug' || verbosity === 'trace';\n}\n\nexport function isCliTrace(): boolean {\n return verbosity === 'trace';\n}\n", "/**\n * Shared CLI logging: timestamped lines to stdout.\n */\n\nimport { getCliLogVerbosity } from './cli-log-level.js';\n\nexport type LogFn = (line: string) => void;\n\nfunction timestampPrefix(): string {\n const time = new Date().toISOString().slice(11, 19);\n return `[${time}]`;\n}\n\n/**\n * Log a line with a [HH:mm:ss] prefix to stdout.\n */\nexport function log(line: string): void {\n console.log(`${timestampPrefix()} ${line}`);\n}\n\n/** Same timestamp format as `log`, written synchronously to stdout (avoids delay before TTY flush). */\nexport function logImmediate(line: string): void {\n process.stdout.write(`${timestampPrefix()} ${line}\\n`);\n}\n\n/** Debug-level line (shown with `--debug` or `--trace`). */\nexport function logDebug(line: string): void {\n const v = getCliLogVerbosity();\n if (v !== 'debug' && v !== 'trace') return;\n console.log(`${timestampPrefix()} [debug] ${line}`);\n}\n\n/** Trace-level line (shown only with `--trace`), e.g. git subprocess output. */\nexport function logTrace(line: string): void {\n if (getCliLogVerbosity() !== 'trace') return;\n console.log(`${timestampPrefix()} [trace] ${line}`);\n}\n", "/** Thrown when {@link requestCliImmediateShutdown} was set (Ctrl+C / bridge close). */\nexport class CliSqliteInterrupted extends Error {\n override readonly name = 'CliSqliteInterrupted';\n constructor() {\n super('CLI SQLite interrupted (shutdown)');\n }\n}\n\nexport function isCliSqliteLockError(e: unknown): boolean {\n if (e instanceof CliSqliteInterrupted) return false;\n const msg = e instanceof Error ? e.message : String(e);\n const lower = msg.toLowerCase();\n return (\n lower.includes('database is locked') ||\n lower.includes('sqlite_busy') ||\n lower.includes('sqlite3_busy') ||\n lower.includes('.lock') ||\n lower.includes('eexist') ||\n lower.includes('file exists') ||\n lower.includes('resource busy') ||\n lower.includes('unable to acquire') ||\n lower.includes('could not open') ||\n lower.includes('failed to open') ||\n (lower.includes('database') && lower.includes('locked'))\n );\n}\n", "import fs from 'node:fs';\nimport { logImmediate } from '../log.js';\n\n/** node-sqlite3-wasm advisory lock directory for a database file path. */\nexport function getSqliteLockPath(dbPath: string): string {\n return `${dbPath}.lock`;\n}\n\n/** Best-effort removal of a stale node-sqlite3-wasm lock directory (or file). */\nexport function removeSqliteLockPathIfPresent(dbPath: string): void {\n const lockPath = getSqliteLockPath(dbPath);\n try {\n fs.rmSync(lockPath, { recursive: true, force: true });\n } catch {\n /* ignore \u2014 teardown must not throw */\n }\n}\n\nexport function logStaleSqliteLockIntervention(dbPath: string): void {\n const lockPath = getSqliteLockPath(dbPath);\n logImmediate(\n `SQLite database locked after retries; if no other buildautomaton CLI is running, remove stale lock: ${lockPath}`,\n );\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\n/**\n * Path to the CLI code-navigation cache SQLite database (file index + symbol index).\n * Override with `BUILDAMATON_CODE_NAV_CACHE_SQLITE_PATH` for tests or custom layouts.\n * Safe to delete \u2014 only caches; the main CLI database is unaffected.\n */\nexport function getCodeNavCacheSqlitePath(): string {\n const override = process.env.BUILDAMATON_CODE_NAV_CACHE_SQLITE_PATH?.trim();\n if (override) return path.resolve(override);\n return path.join(os.homedir(), '.buildautomaton', 'code-nav-cache.sqlite');\n}\n\nexport function ensureCodeNavCacheSqliteParentDir(sqlitePath: string): void {\n const dir = path.dirname(sqlitePath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n", "import fs from 'node:fs';\nimport { isMainThread } from 'node:worker_threads';\nimport type { LogFn } from '../../log.js';\nimport { logImmediate } from '../../log.js';\nimport { isCliSqliteLockError } from '../sqlite-errors.js';\nimport { getSqliteLockPath } from '../sqlite-lock-path.js';\nimport { getCodeNavCacheSqlitePath } from './code-nav-cache-paths.js';\n\ntype CodeNavCacheDiagnosticSink = (line: string) => void;\n\nlet diagnosticSink: CodeNavCacheDiagnosticSink = logImmediate;\nlet lastDiagnosticKey: string | null = null;\n\nexport function setCodeNavCacheDiagnosticSink(sink: CodeNavCacheDiagnosticSink): void {\n diagnosticSink = sink;\n}\n\nexport function resetCodeNavCacheLogForTests(): void {\n lastDiagnosticKey = null;\n diagnosticSink = logImmediate;\n}\n\nfunction codeNavCacheLockPath(): string {\n return getSqliteLockPath(getCodeNavCacheSqlitePath());\n}\n\nfunction lockDirectoryPresent(): boolean {\n try {\n return fs.existsSync(codeNavCacheLockPath());\n } catch {\n return false;\n }\n}\n\nfunction emitCodeNavCacheDiagnostic(key: string, line: string): void {\n if (lastDiagnosticKey === key) return;\n lastDiagnosticKey = key;\n diagnosticSink(line);\n}\n\nfunction formatLockBlockedLine(detail: string): string {\n const lockPath = codeNavCacheLockPath();\n const dbPath = getCodeNavCacheSqlitePath();\n if (lockDirectoryPresent()) {\n return `[code-nav] Code navigation cache blocked (${detail}). Remove stale lock when no other buildautomaton CLI is running: ${lockPath}`;\n }\n return `[code-nav] Code navigation cache blocked (${detail}). Database: ${dbPath} Lock: ${lockPath}`;\n}\n\n/** Log once at bridge startup when a stale lock directory is already present. */\nexport function logCodeNavCacheLockPresentAtStartup(log: LogFn = logImmediate): void {\n if (!lockDirectoryPresent()) return;\n const lockPath = codeNavCacheLockPath();\n log(\n `[code-nav] Code navigation cache lock directory exists at startup (${lockPath}). Indexing will retry briefly; remove this directory if no other buildautomaton CLI is running.`,\n );\n}\n\n/** Log SQLite lock/contention for the code-nav cache (main thread or worker via diagnostic sink). */\nexport function reportCodeNavCacheLockContention(\n detail: string,\n opts?: { attempt?: number; maxAttempts?: number; final?: boolean },\n): void {\n const attemptSuffix =\n opts?.attempt != null && opts?.maxAttempts != null\n ? ` [attempt ${opts.attempt}/${opts.maxAttempts}${opts.final ? ', giving up' : ''}]`\n : opts?.final\n ? ' [giving up]'\n : '';\n emitCodeNavCacheDiagnostic(\n `lock:${detail}:${opts?.attempt ?? 0}:${opts?.final ?? false}`,\n `${formatLockBlockedLine(detail)}${attemptSuffix}`,\n );\n}\n\nexport function logCodeNavCacheUnavailableFromError(log: LogFn, err: unknown): void {\n const detail = err instanceof Error ? err.message : String(err);\n log(`${formatLockBlockedLine(detail)}`);\n lastDiagnosticKey = `unavailable:${detail}`;\n}\n\nexport function maybeLogCodeNavCacheWorkerError(message: string): void {\n const err = new Error(message);\n if (\n isCliSqliteLockError(err) ||\n message.toLowerCase().includes('code navigation cache') ||\n message.toLowerCase().includes('unavailable')\n ) {\n reportCodeNavCacheLockContention(`symbol index worker: ${message}`, { final: true });\n }\n}\n\n/** True when worker-thread diagnostics should post to the main CLI log. */\nexport function isCodeNavCacheDiagnosticWorkerThread(): boolean {\n return !isMainThread;\n}\n", "/**\n * Process-wide \"shutting down\" flag set on SIGINT/SIGTERM (and when closing the bridge).\n * SQLite and other subsystems consult this to bail out of retry loops and long waits immediately.\n */\n\nlet cliImmediateShutdownRequested = false;\nlet symbolIndexShutdownPromise: Promise<void> | null = null;\n\n/** Set once (idempotent). Call from signal handlers and bridge `close()` as early as possible. */\nexport function requestCliImmediateShutdown(): void {\n if (cliImmediateShutdownRequested) return;\n cliImmediateShutdownRequested = true;\n symbolIndexShutdownPromise = import('../code-nav/symbol-index/worker/lifecycle.js')\n .then(({ terminateSymbolIndexWorker }) => terminateSymbolIndexWorker())\n .catch(() => {\n /* worker module may not be loaded yet */\n });\n}\n\nexport function isCliImmediateShutdownRequested(): boolean {\n return cliImmediateShutdownRequested;\n}\n\n/** Wait for symbol index worker shutdown and code-nav SQLite lock cleanup. */\nexport async function awaitSymbolIndexWorkerShutdown(): Promise<void> {\n if (symbolIndexShutdownPromise != null) {\n await symbolIndexShutdownPromise;\n return;\n }\n if (cliImmediateShutdownRequested) {\n const { terminateSymbolIndexWorker } = await import('../code-nav/symbol-index/worker/lifecycle.js');\n await terminateSymbolIndexWorker();\n }\n}\n\n/** Vitest / teardown: clear interrupt state for a clean worker. */\nexport function resetCliImmediateShutdownForTests(): void {\n cliImmediateShutdownRequested = false;\n symbolIndexShutdownPromise = null;\n}\n\n/**\n * Sleep up to `ms`, checking shutdown every ~50ms. Resolves `false` when interrupted, `true` when the full delay elapsed.\n */\nexport async function delayMsUnlessShutdownRequested(ms: number): Promise<boolean> {\n if (ms <= 0) return true;\n const end = Date.now() + ms;\n while (Date.now() < end) {\n if (isCliImmediateShutdownRequested()) return false;\n const chunk = Math.min(50, end - Date.now());\n if (chunk <= 0) break;\n await new Promise<void>((r) => setTimeout(r, chunk));\n }\n return !isCliImmediateShutdownRequested();\n}\n", "import type { LogFn } from '../../log.js';\nimport { logImmediate } from '../../log.js';\nimport { publishFileBrowserActivityToWorker } from '../../files/browser/in-flight.js';\nimport { CliSqliteInterrupted } from '../sqlite-errors.js';\nimport {\n logCodeNavCacheLockPresentAtStartup,\n logCodeNavCacheUnavailableFromError,\n} from './code-nav-cache-log.js';\n\ntype CodeNavCacheInitState = 'idle' | 'pending' | 'ready' | 'unavailable';\n\nlet initState: CodeNavCacheInitState = 'idle';\nlet initPromise: Promise<boolean> | null = null;\n\nexport class CodeNavCacheUnavailableError extends Error {\n override readonly name = 'CodeNavCacheUnavailableError';\n constructor() {\n super('Code navigation cache unavailable');\n }\n}\n\nexport function isCodeNavCacheReady(): boolean {\n return initState === 'ready';\n}\n\nexport function isCodeNavCacheUnavailable(): boolean {\n return initState === 'unavailable';\n}\n\nexport function getCodeNavCacheInitPromise(): Promise<boolean> | null {\n return initPromise;\n}\n\n/** Kick off code-nav SQLite init without blocking bridge connection setup. */\nexport function startCodeNavCacheInitialization(log: LogFn = logImmediate): Promise<boolean> {\n if (initState === 'ready') return Promise.resolve(true);\n if (initState === 'unavailable') return Promise.resolve(false);\n if (initPromise != null) return initPromise;\n\n logCodeNavCacheLockPresentAtStartup(log);\n\n initState = 'pending';\n initPromise = (async () => {\n try {\n const { ensureCodeNavCacheSqliteInitialized } = await import('./database.js');\n await ensureCodeNavCacheSqliteInitialized();\n initState = 'ready';\n publishFileBrowserActivityToWorker();\n return true;\n } catch (e) {\n if (e instanceof CliSqliteInterrupted) {\n initState = 'idle';\n initPromise = null;\n throw e;\n }\n initState = 'unavailable';\n logCodeNavCacheUnavailableFromError(log, e);\n return false;\n }\n })();\n return initPromise;\n}\n\n/** Await background init; returns false when indexing is disabled. */\nexport async function awaitCodeNavCacheInitialization(): Promise<boolean> {\n if (initState === 'ready') return true;\n if (initState === 'unavailable') return false;\n if (initPromise != null) return initPromise;\n return false;\n}\n\nexport function resetCodeNavCacheAvailabilityForTests(): void {\n initState = 'idle';\n initPromise = null;\n}\n", "/** Worker-thread shutdown flag (main-thread {@link isCliImmediateShutdownRequested} is not visible in workers). */\nlet symbolIndexWorkerShutdownRequested = false;\n\nexport function requestSymbolIndexWorkerShutdown(): void {\n symbolIndexWorkerShutdownRequested = true;\n}\n\nexport function isSymbolIndexWorkerShutdownRequested(): boolean {\n return symbolIndexWorkerShutdownRequested;\n}\n\nexport function resetSymbolIndexWorkerShutdownForTests(): void {\n symbolIndexWorkerShutdownRequested = false;\n}\n\n/** True when symbol-index work should stop (main Ctrl+C or worker shutdown message). */\nexport function isSymbolIndexWorkInterrupted(): boolean {\n return symbolIndexWorkerShutdownRequested;\n}\n", "import { yieldToEventLoop } from '../../runtime/yield-to-event-loop.js';\nimport {\n isCliImmediateShutdownRequested,\n} from '../../runtime/cli-process-interrupt.js';\nimport { isSymbolIndexWorkerShutdownRequested } from '../../code-nav/symbol-index/worker/shutdown-state.js';\nimport { CliSqliteInterrupted } from '../sqlite-errors.js';\n\n/** Nested code-nav SQLite opens on the same stack (reentrant work lock). */\nlet codeNavCacheAccessDepth = 0;\n\nasync function waitForOuterCodeNavCacheAccessAsync(): Promise<void> {\n while (codeNavCacheAccessDepth > 0) {\n if (isCliImmediateShutdownRequested() || isSymbolIndexWorkerShutdownRequested()) {\n throw new CliSqliteInterrupted();\n }\n await new Promise<void>((resolve) => setTimeout(resolve, 5));\n await yieldToEventLoop();\n }\n}\n\nfunction waitForOuterCodeNavCacheAccessSync(): void {\n while (codeNavCacheAccessDepth > 0) {\n if (isCliImmediateShutdownRequested() || isSymbolIndexWorkerShutdownRequested()) {\n throw new CliSqliteInterrupted();\n }\n const end = Date.now() + 5;\n while (Date.now() < end) {\n if (isCliImmediateShutdownRequested() || isSymbolIndexWorkerShutdownRequested()) {\n throw new CliSqliteInterrupted();\n }\n }\n }\n}\n\nexport function getCodeNavCacheAccessDepth(): number {\n return codeNavCacheAccessDepth;\n}\n\nexport function incrementCodeNavCacheAccessDepth(): void {\n codeNavCacheAccessDepth += 1;\n}\n\nexport function decrementCodeNavCacheAccessDepth(): void {\n codeNavCacheAccessDepth = Math.max(0, codeNavCacheAccessDepth - 1);\n}\n\nexport async function waitForOuterCodeNavCacheAccessIfNeededAsync(nested: boolean): Promise<void> {\n if (!nested) await waitForOuterCodeNavCacheAccessAsync();\n}\n\nexport function waitForOuterCodeNavCacheAccessIfNeededSync(nested: boolean): void {\n if (!nested) waitForOuterCodeNavCacheAccessSync();\n}\n\nexport function resetCodeNavCacheAccessDepth(): void {\n codeNavCacheAccessDepth = 0;\n}\n", "import { isCliImmediateShutdownRequested } from '../runtime/cli-process-interrupt.js';\nimport { yieldToEventLoop } from '../runtime/yield-to-event-loop.js';\nimport { CliSqliteInterrupted } from './sqlite-errors.js';\n\nexport const SYNC_RETRY_MAX = 40;\nexport const ASYNC_RETRY_MAX = 60;\nexport const ASYNC_PROBE_RETRY_MAX = 2;\n\nexport const ASYNC_BASE_DELAY_MS = 20;\n\n/**\n * Brief synchronous wait for SQLite lock retries inside `withSync`.\n * Uses short chunks so SIGINT/shutdown checks run frequently; prefer `withAsync` on background paths.\n */\nexport function syncSleepMs(ms: number): void {\n if (ms <= 0) return;\n const deadline = Date.now() + ms;\n while (Date.now() < deadline) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n const chunk = Math.min(10, deadline - Date.now());\n if (chunk <= 0) break;\n try {\n const sab = new SharedArrayBuffer(4);\n const ia = new Int32Array(sab);\n Atomics.wait(ia, 0, 0, chunk);\n } catch {\n const end = Date.now() + chunk;\n while (Date.now() < end) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n }\n }\n }\n}\n\nexport async function asyncDelayMsInterruptible(ms: number): Promise<void> {\n const end = Date.now() + ms;\n while (Date.now() < end) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n const chunk = Math.min(50, end - Date.now());\n if (chunk <= 0) break;\n await new Promise<void>((r) => setTimeout(r, chunk));\n await yieldToEventLoop();\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport sqliteWasm from 'node-sqlite3-wasm';\n\nexport const SqliteDatabaseConstructor = (sqliteWasm as unknown as {\n Database: new (filename?: string, options?: { fileMustExist?: boolean; readOnly?: boolean }) => Database;\n}).Database;\n\nexport type SqliteMigrateState = {\n migrateDoneForPath: string | null;\n};\n\nexport function createSqliteMigrateState(): SqliteMigrateState {\n return { migrateDoneForPath: null };\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport function applySqliteConcurrencyPragmas(db: Database): void {\n try {\n db.run('PRAGMA foreign_keys = ON');\n } catch {\n /* ignore */\n }\n try {\n db.exec('PRAGMA journal_mode = WAL');\n } catch {\n /* ignore */\n }\n try {\n db.run('PRAGMA synchronous = NORMAL');\n } catch {\n /* ignore */\n }\n try {\n db.run('PRAGMA busy_timeout = 500');\n } catch {\n /* ignore */\n }\n}\n\nexport function applySqliteMemoryPragmas(db: Database): void {\n try {\n db.run('PRAGMA cache_size = -8192');\n db.run('PRAGMA temp_store = FILE');\n } catch {\n /* ignore */\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { isCliImmediateShutdownRequested } from '../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../sqlite-errors.js';\nimport { applySqliteConcurrencyPragmas, applySqliteMemoryPragmas } from '../sqlite-pragmas.js';\nimport type { SqliteDatabaseAccessOptions } from '../database-access-types.js';\nimport { SqliteDatabaseConstructor, type SqliteMigrateState } from './bindings.js';\n\nexport function safeCloseSqliteDatabase(db: Database | null | undefined): void {\n if (db == null) return;\n try {\n if (db.isOpen) db.close();\n } catch {\n /* ignore */\n }\n}\n\nfunction shouldSkipMigrate(sqlitePath: string, db: Database, migrateState: SqliteMigrateState): boolean {\n if (migrateState.migrateDoneForPath !== sqlitePath) return false;\n try {\n const row = db.get(\n \"SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='__migrations' LIMIT 1\",\n ) as { ok: number } | null;\n return row != null;\n } catch {\n return false;\n }\n}\n\nexport function openSqliteConnection<OpenOptions>(\n config: SqliteDatabaseAccessOptions<OpenOptions>,\n migrateState: SqliteMigrateState,\n options?: OpenOptions,\n): Database {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n const sqlitePath = config.getPath();\n config.ensureParentDir(sqlitePath);\n const db = new SqliteDatabaseConstructor(sqlitePath);\n try {\n applySqliteConcurrencyPragmas(db);\n applySqliteMemoryPragmas(db);\n if (!shouldSkipMigrate(sqlitePath, db, migrateState)) {\n config.migrate(db);\n migrateState.migrateDoneForPath = sqlitePath;\n }\n config.afterOpen?.(db, options);\n } catch (e) {\n safeCloseSqliteDatabase(db);\n throw e;\n }\n return db;\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { yieldToEventLoop } from '../../runtime/yield-to-event-loop.js';\nimport { isCliImmediateShutdownRequested } from '../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted, isCliSqliteLockError } from '../sqlite-errors.js';\nimport { logStaleSqliteLockIntervention } from '../sqlite-lock-path.js';\nimport {\n ASYNC_BASE_DELAY_MS,\n ASYNC_RETRY_MAX,\n asyncDelayMsInterruptible,\n} from '../sqlite-lock-retry.js';\nimport type { SqliteDatabaseAccessOptions } from '../database-access-types.js';\n\nexport async function runSqliteWithAsync<OpenOptions, T>(\n config: SqliteDatabaseAccessOptions<OpenOptions>,\n openConnection: (options?: OpenOptions) => Database,\n safeClose: (db: Database | null | undefined) => void,\n fn: (db: Database) => T | Promise<T>,\n options?: OpenOptions,\n maxAttempts = ASYNC_RETRY_MAX,\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n let db: Database | undefined;\n try {\n db = openConnection(options);\n try {\n return await Promise.resolve(fn(db));\n } finally {\n safeClose(db);\n }\n } catch (e) {\n lastError = e;\n safeClose(db);\n if (e instanceof CliSqliteInterrupted) throw e;\n if (!isCliSqliteLockError(e)) throw e;\n config.onLockRetry?.({\n dbPath: config.getPath(),\n attempt,\n maxAttempts,\n final: attempt === maxAttempts,\n });\n if (attempt === maxAttempts) {\n logStaleSqliteLockIntervention(config.getPath());\n throw e;\n }\n const delayMs = Math.min(600, ASYNC_BASE_DELAY_MS * attempt);\n await asyncDelayMsInterruptible(delayMs);\n await yieldToEventLoop();\n }\n }\n if (lastError instanceof Error) throw lastError;\n throw new Error(String(lastError));\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { isCliImmediateShutdownRequested } from '../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted, isCliSqliteLockError } from '../sqlite-errors.js';\nimport { logStaleSqliteLockIntervention } from '../sqlite-lock-path.js';\nimport { SYNC_RETRY_MAX, syncSleepMs } from '../sqlite-lock-retry.js';\nimport type { SqliteDatabaseAccessOptions } from '../database-access-types.js';\n\nexport function runSqliteWithSync<OpenOptions, T>(\n config: SqliteDatabaseAccessOptions<OpenOptions>,\n openConnection: (options?: OpenOptions) => Database,\n safeClose: (db: Database | null | undefined) => void,\n fn: (db: Database) => T,\n options?: OpenOptions,\n): T {\n for (let attempt = 1; attempt <= SYNC_RETRY_MAX; attempt++) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n let db: Database | undefined;\n try {\n db = openConnection(options);\n try {\n return fn(db);\n } finally {\n safeClose(db);\n }\n } catch (e) {\n safeClose(db);\n if (e instanceof CliSqliteInterrupted) throw e;\n if (!isCliSqliteLockError(e)) throw e;\n config.onLockRetry?.({\n dbPath: config.getPath(),\n attempt,\n maxAttempts: SYNC_RETRY_MAX,\n final: attempt === SYNC_RETRY_MAX,\n });\n if (attempt === SYNC_RETRY_MAX) {\n logStaleSqliteLockIntervention(config.getPath());\n throw e;\n }\n syncSleepMs(Math.min(500, 12 * attempt));\n }\n }\n throw new Error('withSqliteSync: exhausted retries');\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { removeSqliteLockPathIfPresent } from '../sqlite-lock-path.js';\nimport type { SqliteDatabaseAccess, SqliteDatabaseAccessOptions } from '../database-access-types.js';\nimport { ASYNC_PROBE_RETRY_MAX } from '../sqlite-lock-retry.js';\nimport { createSqliteMigrateState } from './bindings.js';\nimport { openSqliteConnection, safeCloseSqliteDatabase } from './open.js';\nimport { runSqliteWithAsync } from './with-async.js';\nimport { runSqliteWithSync } from './with-sync.js';\n\nexport type { SqliteDatabaseAccess, SqliteDatabaseAccessOptions } from '../database-access-types.js';\n\nexport function createSqliteDatabaseAccess<OpenOptions = void>(\n config: SqliteDatabaseAccessOptions<OpenOptions>,\n): SqliteDatabaseAccess<OpenOptions> {\n const migrateState = createSqliteMigrateState();\n\n function safeClose(db: Database | null | undefined): void {\n safeCloseSqliteDatabase(db);\n }\n\n function openConnection(options?: OpenOptions): Database {\n return openSqliteConnection(config, migrateState, options);\n }\n\n function withSync<T>(fn: (db: Database) => T, options?: OpenOptions): T {\n return runSqliteWithSync(config, openConnection, safeClose, fn, options);\n }\n\n async function withAsync<T>(\n fn: (db: Database) => T | Promise<T>,\n options?: OpenOptions,\n maxAttempts?: number,\n ): Promise<T> {\n return runSqliteWithAsync(config, openConnection, safeClose, fn, options, maxAttempts);\n }\n\n async function withAsyncProbe<T>(\n fn: (db: Database) => T | Promise<T>,\n options?: OpenOptions,\n ): Promise<T> {\n return runSqliteWithAsync(\n config,\n openConnection,\n safeClose,\n fn,\n options,\n ASYNC_PROBE_RETRY_MAX,\n );\n }\n\n async function ensureInitialized(options?: OpenOptions): Promise<void> {\n await withAsync(() => undefined, options);\n }\n\n function closeAllConnections(): void {\n migrateState.migrateDoneForPath = null;\n removeSqliteLockPathIfPresent(config.getPath());\n }\n\n return {\n safeClose,\n openConnection,\n withSync,\n withAsync,\n withAsyncProbe,\n ensureInitialized,\n closeAllConnections,\n };\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Read a migration SQL file. `searchSubdirs` are tried relative to this module and common dist layouts\n * (e.g. `migrations` for the main CLI DB, `code-nav-cache-migrations` for the cache DB).\n */\nexport function readMigrationSql(filename: string, ...searchSubdirs: string[]): string {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n const candidates = searchSubdirs.flatMap((sub) => [\n join(moduleDir, sub, filename),\n join(moduleDir, '..', sub, filename),\n join(moduleDir, '..', '..', 'dist', sub, filename),\n ]);\n const resolved = candidates.find((path) => existsSync(path));\n if (!resolved) {\n throw new Error(`Missing SQLite migration SQL: ${filename} (searched ${searchSubdirs.join(', ')})`);\n }\n return readFileSync(resolved, 'utf8');\n}\n\n/** @alias {@link readMigrationSql} with `migrations` search dir (main CLI DB). */\nexport function readCliSqliteMigrationSql(filename: string): string {\n return readMigrationSql(filename, 'migrations');\n}\n\n/** @alias {@link readMigrationSql} with code-nav cache migration search dirs. */\nexport function readCodeNavCacheMigrationSql(filename: string): string {\n return readMigrationSql(filename, 'code-nav-cache-migrations', 'code-nav-cache/migrations');\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport interface SqliteMigration {\n name: string;\n migrate: (db: Database) => void;\n alreadyApplied?: (db: Database) => boolean;\n checkpoint?: boolean;\n replacesLegacyMigrations?: readonly string[];\n}\n\nfunction checkpointSatisfiedByLegacyChain(\n applied: ReadonlySet<string>,\n replacesLegacyMigrations: readonly string[] | undefined,\n): boolean {\n return (\n Array.isArray(replacesLegacyMigrations) &&\n replacesLegacyMigrations.length > 0 &&\n replacesLegacyMigrations.every((n) => applied.has(n))\n );\n}\n\nfunction recordMigrationAndPruneCheckpointLegacy(\n db: Database,\n migration: SqliteMigration,\n applied: Set<string>,\n): void {\n db.run('INSERT INTO __migrations (name) VALUES (?)', [migration.name]);\n applied.add(migration.name);\n if (migration.checkpoint !== true) return;\n const legacy = migration.replacesLegacyMigrations;\n if (!legacy?.length) return;\n for (const legacyName of legacy) {\n if (legacyName === migration.name) continue;\n db.run('DELETE FROM __migrations WHERE name = ?', [legacyName]);\n applied.delete(legacyName);\n }\n}\n\nexport function runSqliteMigrations(\n db: Database,\n migrations: readonly SqliteMigration[],\n bootstrapSql: string,\n label: string,\n): void {\n db.exec(bootstrapSql);\n\n const appliedRows = db.all('SELECT name FROM __migrations') as Array<{ name: string }>;\n const applied = new Set(appliedRows.map((r) => r.name));\n\n for (const migration of migrations) {\n if (applied.has(migration.name)) continue;\n if (\n migration.checkpoint === true &&\n checkpointSatisfiedByLegacyChain(applied, migration.replacesLegacyMigrations)\n ) {\n recordMigrationAndPruneCheckpointLegacy(db, migration, applied);\n continue;\n }\n if (migration.alreadyApplied?.(db)) {\n recordMigrationAndPruneCheckpointLegacy(db, migration, applied);\n continue;\n }\n try {\n migration.migrate(db);\n recordMigrationAndPruneCheckpointLegacy(db, migration, applied);\n } catch (e) {\n console.error(`[${label}] Migration failed: ${migration.name}`, e);\n throw e;\n }\n }\n}\n", "/**\n * Versioned schema changes for the code-navigation cache SQLite DB (file index + symbol index).\n */\n\nimport type { Database } from 'node-sqlite3-wasm';\nimport { readCodeNavCacheMigrationSql } from '../read-migration-sql.js';\nimport { runSqliteMigrations, type SqliteMigration } from '../run-sqlite-migrations.js';\n\nexport type CodeNavCacheSqliteMigration = SqliteMigration;\n\nconst CHECKPOINT_V1 = '001_code_nav_cache_checkpoint_v1';\nconst CHECKPOINT_V1_SQL = readCodeNavCacheMigrationSql('001_code_nav_cache_checkpoint_v1.sql');\nconst MIGRATION_002 = '002_content_hash_symbol_index';\nconst MIGRATION_002_SQL = readCodeNavCacheMigrationSql('002_content_hash_symbol_index.sql');\nconst MIGRATION_003 = '003_content_hash_tag_rows';\nconst MIGRATION_003_SQL = readCodeNavCacheMigrationSql('003_content_hash_tag_rows.sql');\n\nexport const CODE_NAV_CACHE_SQLITE_MIGRATIONS: CodeNavCacheSqliteMigration[] = [\n {\n name: CHECKPOINT_V1,\n checkpoint: true,\n migrate: (db) => {\n db.exec(CHECKPOINT_V1_SQL);\n },\n alreadyApplied: (db) => {\n const row = db.get(\n `SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='file_index_parent_path' LIMIT 1`,\n ) as { ok: number } | null;\n return row != null;\n },\n },\n {\n name: MIGRATION_002,\n migrate: (db) => {\n db.exec(MIGRATION_002_SQL);\n },\n alreadyApplied: (db) => {\n const row = db.get(\n `SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_file_blob' LIMIT 1`,\n ) as { ok: number } | null;\n return row != null;\n },\n },\n {\n name: MIGRATION_003,\n migrate: (db) => {\n db.exec(MIGRATION_003_SQL);\n },\n alreadyApplied: (db) => {\n const row = db.get(\n `SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_index_tag' LIMIT 1`,\n ) as { ok: number } | null;\n if (row == null) return false;\n const blob = db.get(\n `SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_file_blob' LIMIT 1`,\n ) as { ok: number } | null;\n return blob == null;\n },\n },\n];\n\nexport function migrateCodeNavCacheSqlite(db: Database): void {\n runSqliteMigrations(\n db,\n CODE_NAV_CACHE_SQLITE_MIGRATIONS,\n readCodeNavCacheMigrationSql('000_bootstrap_migrations_table.sql'),\n 'code-nav-cache',\n );\n}\n", "import fs from 'node:fs';\nimport { getCodeNavCacheSqlitePath } from './code-nav-cache-paths.js';\n\nfunction isSqliteCorruptError(e: unknown): boolean {\n const msg = e instanceof Error ? e.message : String(e);\n return msg.includes('malformed') || msg.includes('database disk image is malformed') || msg.includes('corrupt');\n}\n\n/**\n * Serialize all code-nav-cache SQLite work (file index + symbol index) within this CLI process.\n * Reentrant: nested calls on the same async stack run inline without re-queuing (avoids deadlocks).\n */\nlet chain: Promise<unknown> = Promise.resolve();\nlet workLockDepth = 0;\n\nexport function resetCodeNavCacheSqliteWorkLock(): void {\n chain = Promise.resolve();\n workLockDepth = 0;\n}\n\nexport function withCodeNavCacheSqliteWorkLock<T>(fn: () => T | Promise<T>): Promise<T> {\n if (workLockDepth > 0) {\n return Promise.resolve(fn());\n }\n\n const run = async (): Promise<T> => {\n workLockDepth += 1;\n try {\n return await Promise.resolve(fn());\n } finally {\n workLockDepth = Math.max(0, workLockDepth - 1);\n }\n };\n\n const runWithCorruptRecovery = async (): Promise<T> => {\n try {\n return await run();\n } catch (e) {\n if (!isSqliteCorruptError(e)) throw e;\n try {\n fs.unlinkSync(getCodeNavCacheSqlitePath());\n } catch {\n /* ignore */\n }\n chain = Promise.resolve();\n return await run();\n }\n };\n\n const next = chain.then(runWithCorruptRecovery);\n chain = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { createSqliteDatabaseAccess } from '../access/index.js';\nimport { isCliSqliteLockError } from '../sqlite-errors.js';\nimport { ensureCodeNavCacheSqliteParentDir, getCodeNavCacheSqlitePath } from './code-nav-cache-paths.js';\nimport { migrateCodeNavCacheSqlite } from './migrate-code-nav-cache-sqlite.js';\nimport { reportCodeNavCacheLockContention } from './code-nav-cache-log.js';\nimport {\n resetCodeNavCacheSqliteWorkLock,\n withCodeNavCacheSqliteWorkLock,\n} from './code-nav-cache-sqlite-work-lock.js';\nimport {\n decrementCodeNavCacheAccessDepth,\n getCodeNavCacheAccessDepth,\n incrementCodeNavCacheAccessDepth,\n resetCodeNavCacheAccessDepth,\n waitForOuterCodeNavCacheAccessIfNeededAsync,\n waitForOuterCodeNavCacheAccessIfNeededSync,\n} from './code-nav-cache-access-depth.js';\n\nexport const codeNavCacheSqlite = createSqliteDatabaseAccess({\n getPath: getCodeNavCacheSqlitePath,\n ensureParentDir: ensureCodeNavCacheSqliteParentDir,\n migrate: migrateCodeNavCacheSqlite,\n onLockRetry: ({ attempt, maxAttempts, final }) => {\n if (attempt === 1 || final) {\n reportCodeNavCacheLockContention('SQLite open', { attempt, maxAttempts, final });\n }\n },\n});\n\nexport async function withCodeNavCacheSqliteWorkLockWrapped<T>(\n fn: (db: Database) => T | Promise<T>,\n): Promise<T> {\n return withCodeNavCacheSqliteWorkLock(async () => {\n const nested = getCodeNavCacheAccessDepth() > 0;\n await waitForOuterCodeNavCacheAccessIfNeededAsync(nested);\n incrementCodeNavCacheAccessDepth();\n try {\n return await codeNavCacheSqlite.withAsync(fn);\n } finally {\n decrementCodeNavCacheAccessDepth();\n }\n });\n}\n\nexport async function withCodeNavCacheSqliteWorkLockProbeWrapped<T>(\n fn: (db: Database) => T | Promise<T>,\n): Promise<T | undefined> {\n try {\n return await withCodeNavCacheSqliteWorkLock(async () => {\n const nested = getCodeNavCacheAccessDepth() > 0;\n await waitForOuterCodeNavCacheAccessIfNeededAsync(nested);\n incrementCodeNavCacheAccessDepth();\n try {\n return await codeNavCacheSqlite.withAsyncProbe(fn);\n } finally {\n decrementCodeNavCacheAccessDepth();\n }\n });\n } catch (e) {\n if (isCliSqliteLockError(e)) return undefined;\n throw e;\n }\n}\n\nexport function withCodeNavCacheSqliteSyncWrapped<T>(fn: (db: Database) => T): T {\n const nested = getCodeNavCacheAccessDepth() > 0;\n waitForOuterCodeNavCacheAccessIfNeededSync(nested);\n incrementCodeNavCacheAccessDepth();\n try {\n return codeNavCacheSqlite.withSync(fn);\n } finally {\n decrementCodeNavCacheAccessDepth();\n }\n}\n\nexport function closeAllCodeNavCacheSqliteConnections(): void {\n codeNavCacheSqlite.closeAllConnections();\n resetCodeNavCacheSqliteWorkLock();\n resetCodeNavCacheAccessDepth();\n}\n", "import { resetCliImmediateShutdownForTests } from '../../runtime/cli-process-interrupt.js';\nimport { resetSymbolIndexWorkerShutdownForTests } from '../../code-nav/symbol-index/worker/shutdown-state.js';\nimport { resetCodeNavCacheAvailabilityForTests } from './code-nav-cache-availability.js';\nimport { resetCodeNavCacheLogForTests } from './code-nav-cache-log.js';\nimport { resetCodeNavCacheAccessDepth } from './code-nav-cache-access-depth.js';\nimport {\n closeAllCodeNavCacheSqliteConnections,\n withCodeNavCacheSqliteSyncWrapped,\n withCodeNavCacheSqliteWorkLockProbeWrapped,\n withCodeNavCacheSqliteWorkLockWrapped,\n} from './code-nav-cache-wrapped-access.js';\n\nexport {\n codeNavCacheSqlite,\n closeAllCodeNavCacheSqliteConnections,\n withCodeNavCacheSqliteSyncWrapped,\n withCodeNavCacheSqliteWorkLockProbeWrapped,\n withCodeNavCacheSqliteWorkLockWrapped,\n} from './code-nav-cache-wrapped-access.js';\n\nexport function closeCodeNavCacheDatabaseForTests(): void {\n resetCliImmediateShutdownForTests();\n closeAllCodeNavCacheSqliteConnections();\n resetCodeNavCacheAccessDepth();\n resetCodeNavCacheAvailabilityForTests();\n resetCodeNavCacheLogForTests();\n resetSymbolIndexWorkerShutdownForTests();\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport {\n CodeNavCacheUnavailableError,\n getCodeNavCacheInitPromise,\n isCodeNavCacheUnavailable,\n} from './code-nav-cache-availability.js';\nimport {\n codeNavCacheSqlite,\n withCodeNavCacheSqliteSyncWrapped,\n withCodeNavCacheSqliteWorkLockProbeWrapped,\n withCodeNavCacheSqliteWorkLockWrapped,\n} from './instance.js';\n\nexport { CliSqliteInterrupted } from '../sqlite-errors.js';\n\nexport const safeCloseCodeNavCacheSqliteDatabase = codeNavCacheSqlite.safeClose;\n\nexport {\n closeAllCodeNavCacheSqliteConnections,\n closeCodeNavCacheDatabaseForTests,\n} from './instance.js';\n\nexport const openCodeNavCacheSqliteConnection = codeNavCacheSqlite.openConnection;\n\nexport async function withCodeNavCacheSqlite<T>(\n fn: (db: Database) => T | Promise<T>,\n): Promise<T> {\n if (isCodeNavCacheUnavailable()) throw new CodeNavCacheUnavailableError();\n const initPromise = getCodeNavCacheInitPromise();\n if (initPromise != null) {\n const ok = await initPromise;\n if (!ok) throw new CodeNavCacheUnavailableError();\n }\n\n return withCodeNavCacheSqliteWorkLockWrapped(fn);\n}\n\n/** Fast SQLite probe for interactive paths; returns undefined when locked or unavailable. */\nexport async function withCodeNavCacheSqliteProbe<T>(\n fn: (db: Database) => T | Promise<T>,\n): Promise<T | undefined> {\n if (isCodeNavCacheUnavailable()) return undefined;\n const initPromise = getCodeNavCacheInitPromise();\n if (initPromise != null) {\n const ok = await initPromise;\n if (!ok) return undefined;\n }\n\n return withCodeNavCacheSqliteWorkLockProbeWrapped(fn);\n}\n\n/**\n * Prefer {@link withCodeNavCacheSqlite}. Serialized with async access; reentrant on nested calls.\n */\nexport function withCodeNavCacheSqliteSync<T>(fn: (db: Database) => T): T {\n if (isCodeNavCacheUnavailable()) throw new CodeNavCacheUnavailableError();\n return withCodeNavCacheSqliteSyncWrapped(fn);\n}\n\nexport async function ensureCodeNavCacheSqliteInitialized(): Promise<void> {\n await codeNavCacheSqlite.withAsync(() => undefined);\n}\n\nexport { startCodeNavCacheInitialization, awaitCodeNavCacheInitialization } from './code-nav-cache-availability.js';\nexport { CodeNavCacheUnavailableError } from './code-nav-cache-availability.js';\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Canonical absolute path for stable SQLite parent keys (resolves /private/var vs /var on macOS). */\nexport function normalizeResolvedPath(resolved: string): string {\n const abs = path.resolve(resolved);\n try {\n return fs.realpathSync.native(abs);\n } catch {\n return abs;\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport function runCodeNavCacheWriteTransaction<T>(db: Database, fn: () => T): T {\n db.run('BEGIN IMMEDIATE');\n try {\n const result = fn();\n db.run('COMMIT');\n return result;\n } catch (e) {\n try {\n db.run('ROLLBACK');\n } catch {\n /* ignore */\n }\n throw e;\n }\n}\n", "import { isCliImmediateShutdownRequested } from '../runtime/cli-process-interrupt.js';\nimport { yieldForBridgeInteractivePriority } from '../files/browser/in-flight.js';\nimport { CliSqliteInterrupted } from '../sqlite/code-nav-cache/database.js';\n\n/** Yield while walking, parsing, or resolving symbols (keeps bridge responsive). */\nexport const CODE_NAV_YIELD_EVERY = 64;\n\nexport type CodeNavYieldState = { n: number };\n\nexport function createCodeNavYieldState(): CodeNavYieldState {\n return { n: 0 };\n}\n\n/** Yield periodically and throw {@link CliSqliteInterrupted} when shutdown is requested. */\nexport async function yieldDuringCodeNavWork(state: CodeNavYieldState): Promise<void> {\n state.n++;\n if (state.n % CODE_NAV_YIELD_EVERY !== 0) return;\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n await yieldForBridgeInteractivePriority();\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\n/**\n * Path to the CLI's local SQLite database (WASM-backed).\n * Override with `BUILDAMATON_CLI_SQLITE_PATH` for tests or custom layouts.\n */\nexport function getCliSqlitePath(): string {\n const override = process.env.BUILDAMATON_CLI_SQLITE_PATH?.trim();\n if (override) return path.resolve(override);\n return path.join(os.homedir(), '.buildautomaton', 'cli.sqlite');\n}\n\nexport function ensureCliSqliteParentDir(sqlitePath: string): void {\n const dir = path.dirname(sqlitePath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n", "import path from 'node:path';\nimport os from 'node:os';\n\n/** Yield while walking paths or inserting rows (keeps bridge responsive). */\nexport const INDEX_WORK_YIELD_EVERY = 128;\n\nexport const INDEX_DIR = path.join(os.homedir(), '.buildautomaton');\nexport const INDEX_HASH_LEN = 16;\n", "import crypto from 'node:crypto';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;\n\n/**\n * Stable filename segment for a queue key: 64-char hex keys use as-is (lowercased);\n * other keys (e.g. legacy work-queue strings) use SHA-256 hex so paths stay safe and unique.\n * (Still used for tests and stable naming; queue state lives in CLI SQLite.)\n */\nexport function queueStateFileSlug(queueKey: string): string {\n if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();\n return crypto.createHash('sha256').update(queueKey, 'utf8').digest('hex');\n}\n\n/** `~/.buildautomaton/queues` \u2014 legacy JSON location (migration reads from here once). */\nexport function getPromptQueuesDirectory(): string {\n const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();\n if (override) return path.resolve(override);\n return path.join(os.homedir(), '.buildautomaton', 'queues');\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { INDEX_DIR } from '../../files/index/constants.js';\n\n/** Pre-SQLite CLI files are moved here (not deleted) for easier testing / rollback. */\nexport const OLD_VERSION_DIR = path.join(INDEX_DIR, 'old-version');\n\nexport type LegacyArchiveCategory = 'file-index' | 'agent-sessions' | 'queues';\n\nexport function moveLegacyFileToOldVersionBackup(category: LegacyArchiveCategory, sourcePath: string): void {\n const destDir = path.join(OLD_VERSION_DIR, category);\n fs.mkdirSync(destDir, { recursive: true });\n const base = path.basename(sourcePath);\n let dest = path.join(destDir, base);\n if (fs.existsSync(dest)) {\n const ext = path.extname(base);\n const stem = ext ? base.slice(0, -ext.length) : base;\n dest = path.join(destDir, `${stem}-${Date.now()}${ext}`);\n }\n fs.renameSync(sourcePath, dest);\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { INDEX_DIR } from '../../files/index/constants.js';\nimport { moveLegacyFileToOldVersionBackup } from './archive-to-old-version.js';\n\n/** Move legacy `.file-index-*.json` from the BuildAutomaton data dir into `old-version/file-index/`. */\nexport function archiveLegacyFileIndexJsonFiles(): void {\n try {\n if (!fs.existsSync(INDEX_DIR)) return;\n for (const name of fs.readdirSync(INDEX_DIR)) {\n if (name.startsWith('.file-index-') && name.endsWith('.json')) {\n const full = path.join(INDEX_DIR, name);\n try {\n moveLegacyFileToOldVersionBackup('file-index', full);\n } catch (err) {\n console.error(`[cli-sqlite] legacy import: could not archive ${name}`, err);\n }\n }\n }\n } catch (e) {\n console.error('[cli-sqlite] legacy import: archive file-index json failed', e);\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport type { Database } from 'node-sqlite3-wasm';\nimport { moveLegacyFileToOldVersionBackup } from './archive-to-old-version.js';\n\nexport const LEGACY_AGENT_SESSION_DIR = path.join(os.homedir(), '.buildautomaton', 'agent-sessions');\n\n/** Import `~/.buildautomaton/agent-sessions/*.json` into `agent_session`, then archive each file. */\nexport function importLegacyAgentSessionsFromDisk(db: Database): void {\n try {\n if (!fs.existsSync(LEGACY_AGENT_SESSION_DIR)) return;\n const names = fs.readdirSync(LEGACY_AGENT_SESSION_DIR).filter((n) => n.endsWith('.json'));\n for (const name of names) {\n const sessionKey = name.slice(0, -'.json'.length);\n const full = path.join(LEGACY_AGENT_SESSION_DIR, name);\n let raw: string;\n try {\n raw = fs.readFileSync(full, 'utf8');\n } catch {\n continue;\n }\n let parsed: {\n v?: unknown;\n acpSessionId?: unknown;\n backendAgentType?: unknown;\n configOptions?: unknown;\n updatedAt?: unknown;\n };\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch {\n continue;\n }\n if (parsed.v !== 1) continue;\n const acpSessionId = typeof parsed.acpSessionId === 'string' ? parsed.acpSessionId : null;\n const backendAgentType = typeof parsed.backendAgentType === 'string' ? parsed.backendAgentType : null;\n const configOptionsJson =\n Array.isArray(parsed.configOptions) ? JSON.stringify(parsed.configOptions) : null;\n const updatedAt =\n typeof parsed.updatedAt === 'string' ? parsed.updatedAt : new Date().toISOString();\n db.run(\n `INSERT OR REPLACE INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)\n VALUES (?, ?, ?, ?, ?)`,\n [sessionKey, acpSessionId, backendAgentType, configOptionsJson, updatedAt],\n );\n try {\n moveLegacyFileToOldVersionBackup('agent-sessions', full);\n } catch {\n /* ignore */\n }\n }\n } catch (e) {\n console.error('[cli-sqlite] legacy import: agent_sessions from disk failed', e);\n }\n}\n", "export type ParsedPersistedQueueFile = {\n queueKey: string;\n updatedAt: string;\n turns: unknown[];\n};\n\nexport function parsePersistedQueueFromJson(raw: string): ParsedPersistedQueueFile | null {\n try {\n const o = JSON.parse(raw) as Record<string, unknown>;\n const queueKey =\n typeof o.queueKey === 'string'\n ? o.queueKey\n : typeof o.queueKeyHash === 'string'\n ? o.queueKeyHash\n : null;\n if (!queueKey || typeof o.updatedAt !== 'string' || !Array.isArray(o.turns)) return null;\n return { queueKey, updatedAt: o.updatedAt, turns: o.turns };\n } catch {\n return null;\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Database } from 'node-sqlite3-wasm';\nimport { getPromptQueuesDirectory } from '../../prompt-turn-queue/paths.js';\nimport { moveLegacyFileToOldVersionBackup } from './archive-to-old-version.js';\nimport { parsePersistedQueueFromJson } from './parse-persisted-queue-json.js';\n\n/** Import per-queue JSON from the legacy queues directory into `prompt_queue`, then archive each file. */\nexport function importLegacyPromptQueuesFromDisk(db: Database): void {\n try {\n const dir = getPromptQueuesDirectory();\n if (!fs.existsSync(dir)) return;\n for (const name of fs.readdirSync(dir)) {\n if (!name.endsWith('.json')) continue;\n const full = path.join(dir, name);\n let raw: string;\n try {\n raw = fs.readFileSync(full, 'utf8');\n } catch {\n continue;\n }\n const file = parsePersistedQueueFromJson(raw);\n if (!file) continue;\n db.run(\n `INSERT OR REPLACE INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)`,\n [file.queueKey, file.updatedAt, JSON.stringify(file.turns)],\n );\n try {\n moveLegacyFileToOldVersionBackup('queues', full);\n } catch {\n /* ignore */\n }\n }\n } catch (e) {\n console.error('[cli-sqlite] legacy import: prompt queues from disk failed', e);\n }\n}\n", "/**\n * One-time style import from pre-SQLite on-disk layouts into an already-open, migrated CLI DB.\n * Runs after {@link migrateCliSqlite}; not part of `__migrations` (schema vs data separation).\n * Idempotent: missing dirs/files are skipped; safe to run on every open.\n */\n\nimport fs from 'node:fs';\nimport type { Database } from 'node-sqlite3-wasm';\nimport { INDEX_DIR } from '../../files/index/constants.js';\nimport type { LogFn } from '../../log.js';\nimport { getPromptQueuesDirectory } from '../../prompt-turn-queue/paths.js';\nimport { archiveLegacyFileIndexJsonFiles } from './archive-file-index-json.js';\nimport {\n importLegacyAgentSessionsFromDisk,\n LEGACY_AGENT_SESSION_DIR,\n} from './import-agent-sessions-from-disk.js';\nimport { importLegacyPromptQueuesFromDisk } from './import-prompt-queues-from-disk.js';\n\n/**\n * True when on-disk legacy JSON still exists that {@link importCliSqliteLegacyDiskData} will try to process.\n * Used to log migration start/finish only when that path actually runs.\n */\nexport function legacyCliDiskMigrationIsPending(): boolean {\n try {\n if (fs.existsSync(INDEX_DIR)) {\n for (const name of fs.readdirSync(INDEX_DIR)) {\n if (name.startsWith('.file-index-') && name.endsWith('.json')) return true;\n }\n }\n } catch {\n /* treat as no pending file-index legacy */\n }\n try {\n if (fs.existsSync(LEGACY_AGENT_SESSION_DIR)) {\n if (fs.readdirSync(LEGACY_AGENT_SESSION_DIR).some((n) => n.endsWith('.json'))) return true;\n }\n } catch {\n /* ignore */\n }\n try {\n const dir = getPromptQueuesDirectory();\n if (fs.existsSync(dir) && fs.readdirSync(dir).some((n) => n.endsWith('.json'))) return true;\n } catch {\n /* ignore */\n }\n return false;\n}\n\n/**\n * Import legacy JSON on disk into SQLite and archive originals under `~/.buildautomaton/old-version/`.\n * Call only after schema migrations have created the target tables.\n *\n * When `log` is set and legacy work is pending, logs one line before and one after the import steps.\n */\nexport function importCliSqliteLegacyDiskData(db: Database, log?: LogFn): void {\n const pending = legacyCliDiskMigrationIsPending();\n if (pending && log) {\n log('Migrating legacy on-disk CLI data to SQLite\u2026');\n }\n archiveLegacyFileIndexJsonFiles();\n importLegacyAgentSessionsFromDisk(db);\n importLegacyPromptQueuesFromDisk(db);\n if (pending && log) {\n log('Legacy on-disk CLI data migration finished.');\n }\n}\n", "/**\n * Versioned schema changes for the CLI local SQLite DB, modeled after {@link migrateDurableObject}\n * in `packages/durable-objects`: ordered migrations, `__migrations` bookkeeping, optional checkpoints.\n *\n * SQL lives under `./migrations/*.sql` (see {@link readCliSqliteMigrationSql}).\n * Legacy on-disk JSON \u2192 SQLite import is **not** done here; see `importCliSqliteLegacyDiskData` in\n * `legacy_migration/import-cli-legacy-disk-data.ts` after the DB is opened and migrations have run.\n */\n\nimport type { Database } from 'node-sqlite3-wasm';\nimport { readCliSqliteMigrationSql } from './read-migration-sql.js';\nimport { runSqliteMigrations, type SqliteMigration } from './run-sqlite-migrations.js';\n\nexport type CliSqliteMigration = SqliteMigration;\n\nconst CHECKPOINT_V1 = '001_cli_sqlite_checkpoint_v1';\n\nconst CHECKPOINT_V1_SQL = readCliSqliteMigrationSql('001_cli_sqlite_checkpoint_v1.sql');\nconst AGENT_CAPABILITIES_SQL = readCliSqliteMigrationSql('002_agent_capabilities.sql');\nconst DROP_CACHE_TABLES_SQL = readCliSqliteMigrationSql('006_drop_cache_tables.sql');\n\nfunction agentCapabilitiesTableState(db: Database): 'new' | 'legacy' | 'current' {\n const rows = db.all(\n `SELECT name FROM sqlite_master WHERE type='table' AND name IN ('agent_capabilities', 'agent_capability_cache')`,\n ) as Array<{ name: string }>;\n const names = new Set(rows.map((r) => r.name));\n if (names.has('agent_capabilities')) return 'current';\n if (names.has('agent_capability_cache')) return 'legacy';\n return 'new';\n}\n\nexport const CLI_SQLITE_MIGRATIONS: CliSqliteMigration[] = [\n {\n name: CHECKPOINT_V1,\n checkpoint: true,\n migrate: (db) => {\n db.exec(CHECKPOINT_V1_SQL);\n },\n },\n {\n name: '002_agent_capabilities',\n migrate: (db) => {\n const state = agentCapabilitiesTableState(db);\n if (state === 'current') return;\n if (state === 'legacy') {\n db.exec(`\n ALTER TABLE agent_capability_cache RENAME TO agent_capabilities;\n DROP INDEX IF EXISTS idx_agent_capability_cache_workspace;\n CREATE INDEX IF NOT EXISTS idx_agent_capabilities_workspace ON agent_capabilities(workspace_id);\n `);\n return;\n }\n db.exec(AGENT_CAPABILITIES_SQL);\n },\n alreadyApplied: (db) => agentCapabilitiesTableState(db) === 'current',\n },\n {\n name: '006_drop_cache_tables',\n migrate: (db) => {\n db.exec(DROP_CACHE_TABLES_SQL);\n },\n alreadyApplied: (db) => {\n const row = db.get(\n `SELECT 1 as ok FROM sqlite_master\n WHERE type='table' AND name IN ('file_index_parent_path', 'file_index_child_path', 'file_index_path')\n LIMIT 1`,\n ) as { ok: number } | null;\n return row == null;\n },\n },\n];\n\nexport function migrateCliSqlite(db: Database): void {\n runSqliteMigrations(\n db,\n CLI_SQLITE_MIGRATIONS,\n readCliSqliteMigrationSql('000_bootstrap_migrations_table.sql'),\n 'cli-sqlite',\n );\n}\n", "import type { LogFn } from '../log.js';\nimport { resetCliImmediateShutdownForTests } from '../runtime/cli-process-interrupt.js';\nimport { ensureCliSqliteParentDir, getCliSqlitePath } from './cli-sqlite-paths.js';\nimport { createSqliteDatabaseAccess } from './access/index.js';\nimport { importCliSqliteLegacyDiskData } from './legacy_migration/import-cli-legacy-disk-data.js';\nimport { migrateCliSqlite } from './migrate-cli-sqlite.js';\nexport { CliSqliteInterrupted, isCliSqliteLockError } from './sqlite-errors.js';\n\nexport type GetCliDatabaseOptions = {\n /** When opening the DB, emit start/finish lines around legacy disk import only if legacy files are pending. */\n logLegacyMigration?: LogFn;\n};\n\nlet legacyImportDoneForPath: string | null = null;\n\nconst cliSqlite = createSqliteDatabaseAccess<GetCliDatabaseOptions>({\n getPath: getCliSqlitePath,\n ensureParentDir: ensureCliSqliteParentDir,\n migrate: migrateCliSqlite,\n afterOpen: (db, options) => {\n const sqlitePath = getCliSqlitePath();\n if (legacyImportDoneForPath === sqlitePath) return;\n importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);\n legacyImportDoneForPath = sqlitePath;\n },\n});\n\n/** Close a WASM SQLite handle without throwing (node-sqlite3-wasm can throw on double-close or bad state). */\nexport const safeCloseCliSqliteDatabase = cliSqlite.safeClose;\n\n/** No-op: fresh connection per access call. Kept for bridge shutdown, corrupt-index recovery, and tests. */\nexport function closeAllCliSqliteConnections(): void {\n legacyImportDoneForPath = null;\n cliSqlite.closeAllConnections();\n}\n\n/** @alias Vitest and callers that only need teardown semantics */\nexport function closeCliDatabaseForTests(): void {\n legacyImportDoneForPath = null;\n resetCliImmediateShutdownForTests();\n}\n\nexport const openCliSqliteConnection = cliSqlite.openConnection;\nexport const withCliSqliteSync = cliSqlite.withSync;\nexport const withCliSqlite = cliSqlite.withAsync;\nexport const ensureCliSqliteInitialized = cliSqlite.ensureInitialized;\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { yieldForBridgeInteractivePriority, fileBrowserReadInFlight, yieldUntilFileBrowserReadsIdle } from '../../files/browser/in-flight.js';\nimport { isCliImmediateShutdownRequested } from '../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../../sqlite/cli-database.js';\nimport { INDEX_WORK_YIELD_EVERY } from './constants.js';\n\nconst DEPENDENCY_INSTALL_DIR_NAMES = new Set([\n 'node_modules',\n 'bower_components',\n 'vendor',\n 'Pods',\n 'Carthage',\n 'DerivedData',\n '.yarn',\n '.pnpm-store',\n]);\n\n/** Skip dependency trees that should not be indexed for search. Hidden files are searchable. */\nexport function shouldSkipWorkspaceWalkEntry(name: string): boolean {\n return DEPENDENCY_INSTALL_DIR_NAMES.has(name);\n}\n\nexport function walkWorkspaceTreeSync(dir: string, baseDir: string, onFile: (relativePath: string) => void): void {\n let names: string[];\n try {\n names = fs.readdirSync(dir);\n } catch {\n return;\n }\n for (const name of names) {\n if (shouldSkipWorkspaceWalkEntry(name)) continue;\n const full = path.join(dir, name);\n let stat: fs.Stats;\n try {\n stat = fs.statSync(full);\n } catch {\n continue;\n }\n const relative = path.relative(baseDir, full).replace(/\\\\/g, '/');\n if (stat.isDirectory()) {\n walkWorkspaceTreeSync(full, baseDir, onFile);\n } else if (stat.isFile()) {\n onFile(relative);\n }\n }\n}\n\ninterface WalkYieldState {\n n: number;\n}\n\n/**\n * Recursive crawl like {@link walkWorkspaceTreeSync}, yielding every {@link INDEX_WORK_YIELD_EVERY}\n * filesystem entries so the event loop stays responsive during large trees.\n */\nexport async function walkWorkspaceTreeAsync(\n dir: string,\n baseDir: string,\n onFile: (relativePath: string) => void,\n state: WalkYieldState,\n): Promise<void> {\n let names: string[];\n try {\n names = await fs.promises.readdir(dir);\n } catch {\n return;\n }\n for (const name of names) {\n if (shouldSkipWorkspaceWalkEntry(name)) continue;\n if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n await yieldForBridgeInteractivePriority();\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n }\n if (fileBrowserReadInFlight()) {\n await yieldUntilFileBrowserReadsIdle();\n }\n state.n++;\n const full = path.join(dir, name);\n let stat: fs.Stats;\n try {\n stat = await fs.promises.stat(full);\n } catch {\n continue;\n }\n const relative = path.relative(baseDir, full).replace(/\\\\/g, '/');\n if (stat.isDirectory()) {\n await walkWorkspaceTreeAsync(full, baseDir, onFile, state);\n } else if (stat.isFile()) {\n onFile(relative);\n }\n }\n}\n\nexport function createWalkYieldState(): WalkYieldState {\n return { n: 0 };\n}\n", "// A simple implementation of make-array\nfunction makeArray (subject) {\n return Array.isArray(subject)\n ? subject\n : [subject]\n}\n\nconst UNDEFINED = undefined\nconst EMPTY = ''\nconst SPACE = ' '\nconst ESCAPE = '\\\\'\nconst REGEX_TEST_BLANK_LINE = /^\\s+$/\nconst REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\\\]|^)\\\\$/\nconst REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\\\!/\nconst REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\\\#/\nconst REGEX_SPLITALL_CRLF = /\\r?\\n/g\n\n// Invalid:\n// - /foo,\n// - ./foo,\n// - ../foo,\n// - .\n// - ..\n// Valid:\n// - .foo\nconst REGEX_TEST_INVALID_PATH = /^\\.{0,2}\\/|^\\.{1,2}$/\n\nconst REGEX_TEST_TRAILING_SLASH = /\\/$/\n\nconst SLASH = '/'\n\n// Do not use ternary expression here, since \"istanbul ignore next\" is buggy\nlet TMP_KEY_IGNORE = 'node-ignore'\n/* istanbul ignore else */\nif (typeof Symbol !== 'undefined') {\n TMP_KEY_IGNORE = Symbol.for('node-ignore')\n}\nconst KEY_IGNORE = TMP_KEY_IGNORE\n\nconst define = (object, key, value) => {\n Object.defineProperty(object, key, {value})\n return value\n}\n\nconst REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g\n\nconst RETURN_FALSE = () => false\n\n// Sanitize the range of a regular expression\n// The cases are complicated, see test cases for details\nconst sanitizeRange = range => range.replace(\n REGEX_REGEXP_RANGE,\n (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)\n ? match\n // Invalid range (out of order) which is ok for gitignore rules but\n // fatal for JavaScript regular expression, so eliminate it.\n : EMPTY\n)\n\n// See fixtures #59\nconst cleanRangeBackSlash = slashes => {\n const {length} = slashes\n return slashes.slice(0, length - length % 2)\n}\n\n// > If the pattern ends with a slash,\n// > it is removed for the purpose of the following description,\n// > but it would only find a match with a directory.\n// > In other words, foo/ will match a directory foo and paths underneath it,\n// > but will not match a regular file or a symbolic link foo\n// > (this is consistent with the way how pathspec works in general in Git).\n// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'\n// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call\n// you could use option `mark: true` with `glob`\n\n// '`foo/`' should not continue with the '`..`'\nconst REPLACERS = [\n\n [\n // Remove BOM\n // TODO:\n // Other similar zero-width characters?\n /^\\uFEFF/,\n () => EMPTY\n ],\n\n // > Trailing spaces are ignored unless they are quoted with backslash (\"\\\")\n [\n // (a\\ ) -> (a )\n // (a ) -> (a)\n // (a ) -> (a)\n // (a \\ ) -> (a )\n /((?:\\\\\\\\)*?)(\\\\?\\s+)$/,\n (_, m1, m2) => m1 + (\n m2.indexOf('\\\\') === 0\n ? SPACE\n : EMPTY\n )\n ],\n\n // Replace (\\ ) with ' '\n // (\\ ) -> ' '\n // (\\\\ ) -> '\\\\ '\n // (\\\\\\ ) -> '\\\\ '\n [\n /(\\\\+?)\\s/g,\n (_, m1) => {\n const {length} = m1\n return m1.slice(0, length - length % 2) + SPACE\n }\n ],\n\n // Escape metacharacters\n // which is written down by users but means special for regular expressions.\n\n // > There are 12 characters with special meanings:\n // > - the backslash \\,\n // > - the caret ^,\n // > - the dollar sign $,\n // > - the period or dot .,\n // > - the vertical bar or pipe symbol |,\n // > - the question mark ?,\n // > - the asterisk or star *,\n // > - the plus sign +,\n // > - the opening parenthesis (,\n // > - the closing parenthesis ),\n // > - and the opening square bracket [,\n // > - the opening curly brace {,\n // > These special characters are often called \"metacharacters\".\n [\n /[\\\\$.|*+(){^]/g,\n match => `\\\\${match}`\n ],\n\n [\n // > a question mark (?) matches a single character\n /(?!\\\\)\\?/g,\n () => '[^/]'\n ],\n\n // leading slash\n [\n\n // > A leading slash matches the beginning of the pathname.\n // > For example, \"/*.c\" matches \"cat-file.c\" but not \"mozilla-sha1/sha1.c\".\n // A leading slash matches the beginning of the pathname\n /^\\//,\n () => '^'\n ],\n\n // replace special metacharacter slash after the leading slash\n [\n /\\//g,\n () => '\\\\/'\n ],\n\n [\n // > A leading \"**\" followed by a slash means match in all directories.\n // > For example, \"**/foo\" matches file or directory \"foo\" anywhere,\n // > the same as pattern \"foo\".\n // > \"**/foo/bar\" matches file or directory \"bar\" anywhere that is directly\n // > under directory \"foo\".\n // Notice that the '*'s have been replaced as '\\\\*'\n /^\\^*\\\\\\*\\\\\\*\\\\\\//,\n\n // '**/foo' <-> 'foo'\n () => '^(?:.*\\\\/)?'\n ],\n\n // starting\n [\n // there will be no leading '/'\n // (which has been replaced by section \"leading slash\")\n // If starts with '**', adding a '^' to the regular expression also works\n /^(?=[^^])/,\n function startingReplacer () {\n // If has a slash `/` at the beginning or middle\n return !/\\/(?!$)/.test(this)\n // > Prior to 2.22.1\n // > If the pattern does not contain a slash /,\n // > Git treats it as a shell glob pattern\n // Actually, if there is only a trailing slash,\n // git also treats it as a shell glob pattern\n\n // After 2.22.1 (compatible but clearer)\n // > If there is a separator at the beginning or middle (or both)\n // > of the pattern, then the pattern is relative to the directory\n // > level of the particular .gitignore file itself.\n // > Otherwise the pattern may also match at any level below\n // > the .gitignore level.\n ? '(?:^|\\\\/)'\n\n // > Otherwise, Git treats the pattern as a shell glob suitable for\n // > consumption by fnmatch(3)\n : '^'\n }\n ],\n\n // two globstars\n [\n // Use lookahead assertions so that we could match more than one `'/**'`\n /\\\\\\/\\\\\\*\\\\\\*(?=\\\\\\/|$)/g,\n\n // Zero, one or several directories\n // should not use '*', or it will be replaced by the next replacer\n\n // Check if it is not the last `'/**'`\n (_, index, str) => index + 6 < str.length\n\n // case: /**/\n // > A slash followed by two consecutive asterisks then a slash matches\n // > zero or more directories.\n // > For example, \"a/**/b\" matches \"a/b\", \"a/x/b\", \"a/x/y/b\" and so on.\n // '/**/'\n ? '(?:\\\\/[^\\\\/]+)*'\n\n // case: /**\n // > A trailing `\"/**\"` matches everything inside.\n\n // #21: everything inside but it should not include the current folder\n : '\\\\/.+'\n ],\n\n // normal intermediate wildcards\n [\n // Never replace escaped '*'\n // ignore rule '\\*' will match the path '*'\n\n // 'abc.*/' -> go\n // 'abc.*' -> skip this rule,\n // coz trailing single wildcard will be handed by [trailing wildcard]\n /(^|[^\\\\]+)(\\\\\\*)+(?=.+)/g,\n\n // '*.js' matches '.js'\n // '*.js' doesn't match 'abc'\n (_, p1, p2) => {\n // 1.\n // > An asterisk \"*\" matches anything except a slash.\n // 2.\n // > Other consecutive asterisks are considered regular asterisks\n // > and will match according to the previous rules.\n const unescaped = p2.replace(/\\\\\\*/g, '[^\\\\/]*')\n return p1 + unescaped\n }\n ],\n\n [\n // unescape, revert step 3 except for back slash\n // For example, if a user escape a '\\\\*',\n // after step 3, the result will be '\\\\\\\\\\\\*'\n /\\\\\\\\\\\\(?=[$.|*+(){^])/g,\n () => ESCAPE\n ],\n\n [\n // '\\\\\\\\' -> '\\\\'\n /\\\\\\\\/g,\n () => ESCAPE\n ],\n\n [\n // > The range notation, e.g. [a-zA-Z],\n // > can be used to match one of the characters in a range.\n\n // `\\` is escaped by step 3\n /(\\\\)?\\[([^\\]/]*?)(\\\\*)($|\\])/g,\n (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE\n // '\\\\[bar]' -> '\\\\\\\\[bar\\\\]'\n ? `\\\\[${range}${cleanRangeBackSlash(endEscape)}${close}`\n : close === ']'\n ? endEscape.length % 2 === 0\n // A normal case, and it is a range notation\n // '[bar]'\n // '[bar\\\\\\\\]'\n ? `[${sanitizeRange(range)}${endEscape}]`\n // Invalid range notaton\n // '[bar\\\\]' -> '[bar\\\\\\\\]'\n : '[]'\n : '[]'\n ],\n\n // ending\n [\n // 'js' will not match 'js.'\n // 'ab' will not match 'abc'\n /(?:[^*])$/,\n\n // WTF!\n // https://git-scm.com/docs/gitignore\n // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)\n // which re-fixes #24, #38\n\n // > If there is a separator at the end of the pattern then the pattern\n // > will only match directories, otherwise the pattern can match both\n // > files and directories.\n\n // 'js*' will not match 'a.js'\n // 'js/' will not match 'a.js'\n // 'js' will match 'a.js' and 'a.js/'\n match => /\\/$/.test(match)\n // foo/ will not match 'foo'\n ? `${match}$`\n // foo matches 'foo' and 'foo/'\n : `${match}(?=$|\\\\/$)`\n ]\n]\n\nconst REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\\\\/)?\\\\\\*$/\nconst MODE_IGNORE = 'regex'\nconst MODE_CHECK_IGNORE = 'checkRegex'\nconst UNDERSCORE = '_'\n\nconst TRAILING_WILD_CARD_REPLACERS = {\n [MODE_IGNORE] (_, p1) {\n const prefix = p1\n // '\\^':\n // '/*' does not match EMPTY\n // '/*' does not match everything\n\n // '\\\\\\/':\n // 'abc/*' does not match 'abc/'\n ? `${p1}[^/]+`\n\n // 'a*' matches 'a'\n // 'a*' matches 'aa'\n : '[^/]*'\n\n return `${prefix}(?=$|\\\\/$)`\n },\n\n [MODE_CHECK_IGNORE] (_, p1) {\n // When doing `git check-ignore`\n const prefix = p1\n // '\\\\\\/':\n // 'abc/*' DOES match 'abc/' !\n ? `${p1}[^/]*`\n\n // 'a*' matches 'a'\n // 'a*' matches 'aa'\n : '[^/]*'\n\n return `${prefix}(?=$|\\\\/$)`\n }\n}\n\n// @param {pattern}\nconst makeRegexPrefix = pattern => REPLACERS.reduce(\n (prev, [matcher, replacer]) =>\n prev.replace(matcher, replacer.bind(pattern)),\n pattern\n)\n\nconst isString = subject => typeof subject === 'string'\n\n// > A blank line matches no files, so it can serve as a separator for readability.\nconst checkPattern = pattern => pattern\n && isString(pattern)\n && !REGEX_TEST_BLANK_LINE.test(pattern)\n && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)\n\n // > A line starting with # serves as a comment.\n && pattern.indexOf('#') !== 0\n\nconst splitPattern = pattern => pattern\n.split(REGEX_SPLITALL_CRLF)\n.filter(Boolean)\n\nclass IgnoreRule {\n constructor (\n pattern,\n mark,\n body,\n ignoreCase,\n negative,\n prefix\n ) {\n this.pattern = pattern\n this.mark = mark\n this.negative = negative\n\n define(this, 'body', body)\n define(this, 'ignoreCase', ignoreCase)\n define(this, 'regexPrefix', prefix)\n }\n\n get regex () {\n const key = UNDERSCORE + MODE_IGNORE\n\n if (this[key]) {\n return this[key]\n }\n\n return this._make(MODE_IGNORE, key)\n }\n\n get checkRegex () {\n const key = UNDERSCORE + MODE_CHECK_IGNORE\n\n if (this[key]) {\n return this[key]\n }\n\n return this._make(MODE_CHECK_IGNORE, key)\n }\n\n _make (mode, key) {\n const str = this.regexPrefix.replace(\n REGEX_REPLACE_TRAILING_WILDCARD,\n\n // It does not need to bind pattern\n TRAILING_WILD_CARD_REPLACERS[mode]\n )\n\n const regex = this.ignoreCase\n ? new RegExp(str, 'i')\n : new RegExp(str)\n\n return define(this, key, regex)\n }\n}\n\nconst createRule = ({\n pattern,\n mark\n}, ignoreCase) => {\n let negative = false\n let body = pattern\n\n // > An optional prefix \"!\" which negates the pattern;\n if (body.indexOf('!') === 0) {\n negative = true\n body = body.substr(1)\n }\n\n body = body\n // > Put a backslash (\"\\\") in front of the first \"!\" for patterns that\n // > begin with a literal \"!\", for example, `\"\\!important!.txt\"`.\n .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')\n // > Put a backslash (\"\\\") in front of the first hash for patterns that\n // > begin with a hash.\n .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#')\n\n const regexPrefix = makeRegexPrefix(body)\n\n return new IgnoreRule(\n pattern,\n mark,\n body,\n ignoreCase,\n negative,\n regexPrefix\n )\n}\n\nclass RuleManager {\n constructor (ignoreCase) {\n this._ignoreCase = ignoreCase\n this._rules = []\n }\n\n _add (pattern) {\n // #32\n if (pattern && pattern[KEY_IGNORE]) {\n this._rules = this._rules.concat(pattern._rules._rules)\n this._added = true\n return\n }\n\n if (isString(pattern)) {\n pattern = {\n pattern\n }\n }\n\n if (checkPattern(pattern.pattern)) {\n const rule = createRule(pattern, this._ignoreCase)\n this._added = true\n this._rules.push(rule)\n }\n }\n\n // @param {Array<string> | string | Ignore} pattern\n add (pattern) {\n this._added = false\n\n makeArray(\n isString(pattern)\n ? splitPattern(pattern)\n : pattern\n ).forEach(this._add, this)\n\n return this._added\n }\n\n // Test one single path without recursively checking parent directories\n //\n // - checkUnignored `boolean` whether should check if the path is unignored,\n // setting `checkUnignored` to `false` could reduce additional\n // path matching.\n // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`\n\n // @returns {TestResult} true if a file is ignored\n test (path, checkUnignored, mode) {\n let ignored = false\n let unignored = false\n let matchedRule\n\n this._rules.forEach(rule => {\n const {negative} = rule\n\n // | ignored : unignored\n // -------- | ---------------------------------------\n // negative | 0:0 | 0:1 | 1:0 | 1:1\n // -------- | ------- | ------- | ------- | --------\n // 0 | TEST | TEST | SKIP | X\n // 1 | TESTIF | SKIP | TEST | X\n\n // - SKIP: always skip\n // - TEST: always test\n // - TESTIF: only test if checkUnignored\n // - X: that never happen\n if (\n unignored === negative && ignored !== unignored\n || negative && !ignored && !unignored && !checkUnignored\n ) {\n return\n }\n\n const matched = rule[mode].test(path)\n\n if (!matched) {\n return\n }\n\n ignored = !negative\n unignored = negative\n\n matchedRule = negative\n ? UNDEFINED\n : rule\n })\n\n const ret = {\n ignored,\n unignored\n }\n\n if (matchedRule) {\n ret.rule = matchedRule\n }\n\n return ret\n }\n}\n\nconst throwError = (message, Ctor) => {\n throw new Ctor(message)\n}\n\nconst checkPath = (path, originalPath, doThrow) => {\n if (!isString(path)) {\n return doThrow(\n `path must be a string, but got \\`${originalPath}\\``,\n TypeError\n )\n }\n\n // We don't know if we should ignore EMPTY, so throw\n if (!path) {\n return doThrow(`path must not be empty`, TypeError)\n }\n\n // Check if it is a relative path\n if (checkPath.isNotRelative(path)) {\n const r = '`path.relative()`d'\n return doThrow(\n `path should be a ${r} string, but got \"${originalPath}\"`,\n RangeError\n )\n }\n\n return true\n}\n\nconst isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path)\n\ncheckPath.isNotRelative = isNotRelative\n\n// On windows, the following function will be replaced\n/* istanbul ignore next */\ncheckPath.convert = p => p\n\n\nclass Ignore {\n constructor ({\n ignorecase = true,\n ignoreCase = ignorecase,\n allowRelativePaths = false\n } = {}) {\n define(this, KEY_IGNORE, true)\n\n this._rules = new RuleManager(ignoreCase)\n this._strictPathCheck = !allowRelativePaths\n this._initCache()\n }\n\n _initCache () {\n // A cache for the result of `.ignores()`\n this._ignoreCache = Object.create(null)\n\n // A cache for the result of `.test()`\n this._testCache = Object.create(null)\n }\n\n add (pattern) {\n if (this._rules.add(pattern)) {\n // Some rules have just added to the ignore,\n // making the behavior changed,\n // so we need to re-initialize the result cache\n this._initCache()\n }\n\n return this\n }\n\n // legacy\n addPattern (pattern) {\n return this.add(pattern)\n }\n\n // @returns {TestResult}\n _test (originalPath, cache, checkUnignored, slices) {\n const path = originalPath\n // Supports nullable path\n && checkPath.convert(originalPath)\n\n checkPath(\n path,\n originalPath,\n this._strictPathCheck\n ? throwError\n : RETURN_FALSE\n )\n\n return this._t(path, cache, checkUnignored, slices)\n }\n\n checkIgnore (path) {\n // If the path doest not end with a slash, `.ignores()` is much equivalent\n // to `git check-ignore`\n if (!REGEX_TEST_TRAILING_SLASH.test(path)) {\n return this.test(path)\n }\n\n const slices = path.split(SLASH).filter(Boolean)\n slices.pop()\n\n if (slices.length) {\n const parent = this._t(\n slices.join(SLASH) + SLASH,\n this._testCache,\n true,\n slices\n )\n\n if (parent.ignored) {\n return parent\n }\n }\n\n return this._rules.test(path, false, MODE_CHECK_IGNORE)\n }\n\n _t (\n // The path to be tested\n path,\n\n // The cache for the result of a certain checking\n cache,\n\n // Whether should check if the path is unignored\n checkUnignored,\n\n // The path slices\n slices\n ) {\n if (path in cache) {\n return cache[path]\n }\n\n if (!slices) {\n // path/to/a.js\n // ['path', 'to', 'a.js']\n slices = path.split(SLASH).filter(Boolean)\n }\n\n slices.pop()\n\n // If the path has no parent directory, just test it\n if (!slices.length) {\n return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE)\n }\n\n const parent = this._t(\n slices.join(SLASH) + SLASH,\n cache,\n checkUnignored,\n slices\n )\n\n // If the path contains a parent directory, check the parent first\n return cache[path] = parent.ignored\n // > It is not possible to re-include a file if a parent directory of\n // > that file is excluded.\n ? parent\n : this._rules.test(path, checkUnignored, MODE_IGNORE)\n }\n\n ignores (path) {\n return this._test(path, this._ignoreCache, false).ignored\n }\n\n createFilter () {\n return path => !this.ignores(path)\n }\n\n filter (paths) {\n return makeArray(paths).filter(this.createFilter())\n }\n\n // @returns {TestResult}\n test (path) {\n return this._test(path, this._testCache, true)\n }\n}\n\nconst factory = options => new Ignore(options)\n\nconst isPathValid = path =>\n checkPath(path && checkPath.convert(path), path, RETURN_FALSE)\n\n/* istanbul ignore next */\nconst setupWindows = () => {\n /* eslint no-control-regex: \"off\" */\n const makePosix = str => /^\\\\\\\\\\?\\\\/.test(str)\n || /[\"<>|\\u0000-\\u001F]+/u.test(str)\n ? str\n : str.replace(/\\\\/g, '/')\n\n checkPath.convert = makePosix\n\n // 'C:\\\\foo' <- 'C:\\\\foo' has been converted to 'C:/'\n // 'd:\\\\foo'\n const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\\//i\n checkPath.isNotRelative = path =>\n REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path)\n || isNotRelative(path)\n}\n\n\n// Windows\n// --------------------------------------------------------------\n/* istanbul ignore next */\nif (\n // Detect `process` so that it can run in browsers.\n typeof process !== 'undefined'\n && process.platform === 'win32'\n) {\n setupWindows()\n}\n\n// COMMONJS_EXPORTS ////////////////////////////////////////////////////////////\n\nmodule.exports = factory\n\n// Although it is an anti-pattern,\n// it is still widely misused by a lot of libraries in github\n// Ref: https://github.com/search?q=ignore.default%28%29&type=code\nfactory.default = factory\n\nmodule.exports.isPathValid = isPathValid\n\n// For testing purposes\ndefine(module.exports, Symbol.for('setupWindows'), setupWindows)\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport ignore, { type Ignore } from 'ignore';\n\ntype IgnoreLayer = {\n dirRel: string;\n ig: Ignore;\n};\n\nconst DEFAULT_IGNORED = ['.git', '.git/**'];\n\nfunction normalizeRelPath(relPath: string): string {\n return relPath.replace(/\\\\/g, '/');\n}\n\nexport class GitignoreFilter {\n private layers: IgnoreLayer[] = [{ dirRel: '', ig: ignore().add(DEFAULT_IGNORED) }];\n\n /** Load `.gitignore` in `absDir` and push a layer when the file exists. */\n async enterDirectory(absDir: string, dirRel: string): Promise<void> {\n try {\n const content = await fs.promises.readFile(path.join(absDir, '.gitignore'), 'utf8');\n this.layers.push({ dirRel, ig: ignore().add(content) });\n } catch {\n /* no .gitignore in this directory */\n }\n }\n\n /** Pop the ignore layer for `dirRel` when leaving that directory during a walk. */\n leaveDirectory(dirRel: string): void {\n const top = this.layers[this.layers.length - 1];\n if (top != null && top.dirRel === dirRel) {\n this.layers.pop();\n }\n }\n\n isIgnored(relPath: string, opts?: { directory?: boolean }): boolean {\n const normalized = normalizeRelPath(relPath);\n const checkPath =\n opts?.directory && !normalized.endsWith('/') ? `${normalized}/` : normalized;\n\n for (const layer of this.layers) {\n if (layer.dirRel !== '' && !isUnderDir(normalized, layer.dirRel)) continue;\n const local = layer.dirRel === '' ? checkPath : checkPath.slice(layer.dirRel.length + 1);\n if (local !== '' && layer.ig.ignores(local)) return true;\n }\n return false;\n }\n}\n\nfunction isUnderDir(relPath: string, dirRel: string): boolean {\n return relPath === dirRel || relPath.startsWith(`${dirRel}/`);\n}\n\n/** Build an ignore filter from root through the parent directories of `relPath`. */\nexport async function createGitignoreFilterForRelativePath(\n root: string,\n relPath: string,\n): Promise<GitignoreFilter> {\n const filter = new GitignoreFilter();\n await filter.enterDirectory(root, '');\n\n const dirRel = normalizeRelPath(path.dirname(relPath));\n if (dirRel === '.' || dirRel === '') return filter;\n\n let abs = root;\n let rel = '';\n for (const segment of dirRel.split('/')) {\n abs = path.join(abs, segment);\n rel = rel ? `${rel}/${segment}` : segment;\n await filter.enterDirectory(abs, rel);\n }\n return filter;\n}\n\nexport async function isPathGitIgnored(root: string, relPath: string): Promise<boolean> {\n const normalized = normalizeRelPath(relPath);\n const filter = await createGitignoreFilterForRelativePath(root, normalized);\n return filter.isIgnored(normalized);\n}\n", "import path from 'node:path';\n\nexport type CodeNavLanguageSpec = {\n wasmFile: string;\n tagsQueryFile: string;\n};\n\nconst EXT_TO_LANGUAGE_KEY: Record<string, string> = {\n js: 'javascript',\n jsx: 'javascript',\n mjs: 'javascript',\n cjs: 'javascript',\n ts: 'typescript',\n tsx: 'tsx',\n py: 'python',\n go: 'go',\n rs: 'rust',\n rb: 'ruby',\n java: 'java',\n c: 'c',\n h: 'c',\n cpp: 'cpp',\n cc: 'cpp',\n cxx: 'cpp',\n hpp: 'cpp',\n};\n\nfunction languageAssetPaths(key: string, wasmFile: string): CodeNavLanguageSpec {\n return {\n wasmFile,\n tagsQueryFile: `tree-sitter-${key}/tags.scm`,\n };\n}\n\nconst LANGUAGE_SPECS: Record<string, CodeNavLanguageSpec> = {\n javascript: languageAssetPaths('javascript', 'tree-sitter-javascript.wasm'),\n typescript: languageAssetPaths('typescript', 'tree-sitter-typescript.wasm'),\n tsx: languageAssetPaths('typescript', 'tree-sitter-tsx.wasm'),\n python: languageAssetPaths('python', 'tree-sitter-python.wasm'),\n go: languageAssetPaths('go', 'tree-sitter-go.wasm'),\n rust: languageAssetPaths('rust', 'tree-sitter-rust.wasm'),\n ruby: languageAssetPaths('ruby', 'tree-sitter-ruby.wasm'),\n java: languageAssetPaths('java', 'tree-sitter-java.wasm'),\n c: languageAssetPaths('c', 'tree-sitter-c.wasm'),\n cpp: languageAssetPaths('cpp', 'tree-sitter-cpp.wasm'),\n};\n\nexport function getLanguageKeyForFilePath(filePath: string): string | null {\n const ext = path.extname(filePath).replace(/^\\./, '').toLowerCase();\n if (!ext) return null;\n return EXT_TO_LANGUAGE_KEY[ext] ?? null;\n}\n\nexport function getLanguageSpec(languageKey: string): CodeNavLanguageSpec | null {\n return LANGUAGE_SPECS[languageKey] ?? null;\n}\n\nexport function isCodeNavSupportedPath(filePath: string): boolean {\n const key = getLanguageKeyForFilePath(filePath);\n return key != null && getLanguageSpec(key) != null;\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport {\n createWalkYieldState,\n shouldSkipWorkspaceWalkEntry,\n} from '../files/index/walk-workspace-tree.js';\nimport {\n fileBrowserReadInFlight,\n yieldForBridgeInteractivePriority,\n yieldUntilFileBrowserReadsIdle,\n} from '../files/browser/in-flight.js';\nimport { isCliImmediateShutdownRequested } from '../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../sqlite/cli-database.js';\nimport { INDEX_WORK_YIELD_EVERY } from '../files/index/constants.js';\nimport { GitignoreFilter } from './gitignore-filter.js';\nimport { isCodeNavSupportedPath } from './language-registry.js';\n\ntype WalkYieldState = ReturnType<typeof createWalkYieldState>;\n\nexport { createWalkYieldState };\n\nasync function walkCodeNavFilesInDirectory(\n dir: string,\n baseDir: string,\n relDir: string,\n filter: GitignoreFilter,\n onFile: (relativePath: string) => void | Promise<void>,\n state: WalkYieldState,\n): Promise<void> {\n await filter.enterDirectory(dir, relDir);\n\n let names: string[];\n try {\n names = await fs.promises.readdir(dir);\n } catch {\n filter.leaveDirectory(relDir);\n return;\n }\n\n for (const name of names) {\n if (shouldSkipWorkspaceWalkEntry(name)) continue;\n if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n await yieldForBridgeInteractivePriority();\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n }\n if (fileBrowserReadInFlight()) {\n await yieldUntilFileBrowserReadsIdle();\n }\n state.n++;\n\n const relPath = relDir ? `${relDir}/${name}` : name;\n const full = path.join(dir, name);\n let stat: fs.Stats;\n try {\n stat = await fs.promises.stat(full);\n } catch {\n continue;\n }\n\n if (stat.isDirectory()) {\n if (filter.isIgnored(relPath, { directory: true })) continue;\n await walkCodeNavFilesInDirectory(full, baseDir, relPath, filter, onFile, state);\n continue;\n }\n\n if (!stat.isFile()) continue;\n if (filter.isIgnored(relPath)) continue;\n if (!isCodeNavSupportedPath(relPath)) continue;\n await Promise.resolve(onFile(relPath));\n }\n\n filter.leaveDirectory(relDir);\n}\n\nexport async function walkCodeNavFilesAsync(\n rootDir: string,\n onFile: (relativePath: string) => void | Promise<void>,\n state: WalkYieldState = createWalkYieldState(),\n): Promise<void> {\n const resolved = path.resolve(rootDir);\n const filter = new GitignoreFilter();\n await walkCodeNavFilesInDirectory(resolved, resolved, '', filter, onFile, state);\n}\n", "export const SYMBOL_INDEX_VERSION = 11;\n", "import * as path from 'node:path';\nimport { normalizeResolvedPath } from '../../paths/normalize-resolved-path.js';\n\n/**\n * **Bridge root**: directory the bridge uses for git repos, skills, file index, and `bridge_root` sessions.\n * Defaults to where the CLI was started, then `process.chdir` from `--bridge-root` / legacy `--cwd`.\n *\n * Call {@link initBridgeRoot} once at startup after applying those options so all bridge paths agree.\n */\nlet bridgeRootPath: string | null = null;\n\n/** Capture `process.cwd()` after startup / `chdir` (idempotent). */\nexport function initBridgeRoot(): void {\n bridgeRootPath = normalizeResolvedPath(process.cwd());\n}\n\n/**\n * Absolute bridge root. Prefer {@link initBridgeRoot} at startup; otherwise falls back to `process.cwd()`\n * (e.g. tests).\n */\nexport function getBridgeRoot(): string {\n if (bridgeRootPath == null) {\n bridgeRootPath = normalizeResolvedPath(process.cwd());\n }\n return bridgeRootPath;\n}\n\n/** Test-only: clear cached bridge root so `initBridgeRoot` can rebind cwd. */\nexport function resetBridgeRootForTests(): void {\n bridgeRootPath = null;\n}\n", "import path from 'node:path';\nimport crypto from 'node:crypto';\nimport { INDEX_HASH_LEN } from './constants.js';\n\n/** Stable short hash for a file-index parent path (matches legacy JSON index hash length). */\nexport function getCwdHashForFileIndex(resolvedCwd: string): string {\n return crypto.createHash('sha256').update(path.resolve(resolvedCwd)).digest('hex').slice(0, INDEX_HASH_LEN);\n}\n", "import { getBridgeRoot } from '../../../files/cwd/bridge-root.js';\nimport { getCwdHashForFileIndex } from '../../../files/index/paths.js';\nimport { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport type { Database } from 'node-sqlite3-wasm';\nimport type { SymbolIndexParentContext } from '../storage/parent-context.js';\nimport { withCodeNavCacheSqliteSync } from '../../../sqlite/code-nav-cache/database.js';\nimport { SYMBOL_INDEX_VERSION } from './symbol-index-version.js';\n\nexport type SymbolIndexParentRow = SymbolIndexParentContext & {\n path: string;\n};\n\nfunction normalizeParentPath(resolved: string): string {\n return normalizeResolvedPath(resolved);\n}\n\nfunction resolveParentKind(resolved: string): 'base' | 'overlay' {\n return normalizeParentPath(resolved) === normalizeParentPath(getBridgeRoot()) ? 'base' : 'overlay';\n}\n\nfunction ensureBaseParentId(db: Database): number {\n const bridgeRoot = normalizeParentPath(getBridgeRoot());\n const existing = db.get('SELECT id FROM symbol_index_parent_path WHERE path = ?', [bridgeRoot]) as\n | { id: number | bigint }\n | null;\n if (existing != null) return Number(existing.id);\n return upsertSymbolIndexParentPath(db, bridgeRoot);\n}\n\nexport function upsertSymbolIndexParentPath(db: Database, resolved: string): number {\n const normalized = normalizeParentPath(resolved);\n const now = new Date().toISOString();\n const kind = resolveParentKind(normalized);\n const baseParentId = kind === 'overlay' ? ensureBaseParentId(db) : null;\n\n db.run(\n `INSERT INTO symbol_index_parent_path (path, path_hash, updated_at, index_version, kind, base_parent_id)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(path) DO UPDATE SET\n path_hash = excluded.path_hash,\n updated_at = excluded.updated_at,\n index_version = excluded.index_version,\n kind = excluded.kind,\n base_parent_id = excluded.base_parent_id`,\n [normalized, getCwdHashForFileIndex(normalized), now, SYMBOL_INDEX_VERSION, kind, baseParentId],\n );\n const row = db.get('SELECT id FROM symbol_index_parent_path WHERE path = ?', [normalized]) as\n | { id: number | bigint }\n | null;\n if (row == null) throw new Error(`Failed to upsert symbol index parent path: ${normalized}`);\n return Number(row.id);\n}\n\nfunction rowToSymbolIndexParentContext(\n row: { id: number | bigint; path: string; kind: 'base' | 'overlay'; base_parent_id: number | bigint | null },\n): SymbolIndexParentRow {\n return {\n parentId: Number(row.id),\n path: row.path,\n kind: row.kind,\n baseParentId: row.base_parent_id != null ? Number(row.base_parent_id) : null,\n };\n}\n\nexport function getSymbolIndexParentContextById(db: Database, parentId: number): SymbolIndexParentRow | null {\n const row = db.get(\n `SELECT id, path, kind, base_parent_id\n FROM symbol_index_parent_path\n WHERE id = ?`,\n [parentId],\n ) as\n | { id: number | bigint; path: string; kind: 'base' | 'overlay'; base_parent_id: number | bigint | null }\n | null;\n if (row == null) return null;\n return rowToSymbolIndexParentContext(row);\n}\n\nexport function getSymbolIndexParentContext(db: Database, resolvedParentPath: string): SymbolIndexParentRow | null {\n const row = db.get(\n `SELECT id, path, kind, base_parent_id\n FROM symbol_index_parent_path\n WHERE path = ?`,\n [normalizeParentPath(resolvedParentPath)],\n ) as\n | { id: number | bigint; path: string; kind: 'base' | 'overlay'; base_parent_id: number | bigint | null }\n | null;\n if (row == null) return null;\n return rowToSymbolIndexParentContext(row);\n}\n\nexport function getSymbolIndexParentId(resolvedParentPath: string): number | null {\n return withCodeNavCacheSqliteSync((db) => {\n const ctx = getSymbolIndexParentContext(db, resolvedParentPath);\n return ctx?.parentId ?? null;\n });\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport function contentHashFileHasTags(db: Database, contentHash: string, filePath: string): boolean {\n const row = db.get(\n 'SELECT 1 as ok FROM symbol_index_tag WHERE content_hash = ? AND file_path = ? LIMIT 1',\n [contentHash, filePath],\n ) as { ok: number } | null;\n return row != null;\n}\n\nexport function contentHashFileHasImports(db: Database, contentHash: string, filePath: string): boolean {\n const row = db.get(\n 'SELECT 1 as ok FROM symbol_index_import WHERE content_hash = ? AND file_path = ? LIMIT 1',\n [contentHash, filePath],\n ) as { ok: number } | null;\n return row != null;\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\n\nexport function insertSymbolTagsForContent(\n db: Database,\n contentHash: string,\n filePath: string,\n tags: readonly SymbolTag[],\n): void {\n const ins = db.prepare(\n `INSERT OR IGNORE INTO symbol_index_tag\n (content_hash, file_path, name, role, kind, start_line, start_column, end_line, end_column,\n scope_start_line, scope_start_column, parent_scope_start_line, parent_scope_start_column,\n nav_target_path, scope_chain)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n );\n try {\n for (const tag of tags) {\n ins.run([\n contentHash,\n filePath,\n tag.name,\n tag.role,\n tag.kind,\n tag.startLine,\n tag.startColumn,\n tag.endLine,\n tag.endColumn,\n tag.scopeStartLine ?? null,\n tag.scopeStartColumn ?? null,\n tag.parentScopeStartLine ?? null,\n tag.parentScopeStartColumn ?? null,\n tag.navTargetPath ?? null,\n tag.scopeChain ?? null,\n ]);\n }\n } finally {\n ins.finalize();\n }\n}\n\nexport function insertSymbolImportsForContent(\n db: Database,\n contentHash: string,\n filePath: string,\n imports: readonly SymbolImportBinding[],\n): void {\n const ins = db.prepare(\n `INSERT OR IGNORE INTO symbol_index_import\n (content_hash, file_path, local_name, source_name, module_specifier, source_file_path, import_kind, start_line, start_column)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n );\n try {\n for (const binding of imports) {\n ins.run([\n contentHash,\n filePath,\n binding.localName,\n binding.sourceName,\n binding.moduleSpecifier,\n binding.sourceFilePath,\n binding.importKind,\n binding.startLine,\n binding.startColumn,\n ]);\n }\n } finally {\n ins.finalize();\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport function getParentFileMapHash(\n db: Database,\n parentId: number,\n filePath: string,\n): string | null | undefined {\n const row = db.get(\n 'SELECT content_hash FROM symbol_parent_file_map WHERE parent_id = ? AND file_path = ?',\n [parentId, filePath],\n ) as { content_hash: string | null } | null;\n if (row == null) return undefined;\n return row.content_hash;\n}\n\nexport function countParentFileMapRefs(db: Database, contentHash: string): number {\n const row = db.get('SELECT COUNT(*) as n FROM symbol_parent_file_map WHERE content_hash = ?', [\n contentHash,\n ]) as { n: number | bigint };\n return Number(row.n);\n}\n\nexport function setParentFileMapEntry(\n db: Database,\n parentId: number,\n filePath: string,\n contentHash: string | null,\n): string | null {\n const previous = getParentFileMapHash(db, parentId, filePath);\n if (contentHash == null) {\n db.run(\n `INSERT INTO symbol_parent_file_map (parent_id, file_path, content_hash)\n VALUES (?, ?, NULL)\n ON CONFLICT(parent_id, file_path) DO UPDATE SET content_hash = NULL`,\n [parentId, filePath],\n );\n } else {\n db.run(\n `INSERT INTO symbol_parent_file_map (parent_id, file_path, content_hash)\n VALUES (?, ?, ?)\n ON CONFLICT(parent_id, file_path) DO UPDATE SET content_hash = excluded.content_hash`,\n [parentId, filePath, contentHash],\n );\n }\n return previous === undefined ? null : previous;\n}\n\nexport function removeParentFileMapEntry(db: Database, parentId: number, filePath: string): string | null {\n const previous = getParentFileMapHash(db, parentId, filePath);\n db.run('DELETE FROM symbol_parent_file_map WHERE parent_id = ? AND file_path = ?', [parentId, filePath]);\n return previous === undefined ? null : previous;\n}\n\nexport function clearParentFileMap(db: Database, parentId: number): string[] {\n const rows = db.all('SELECT content_hash FROM symbol_parent_file_map WHERE parent_id = ? AND content_hash IS NOT NULL', [\n parentId,\n ]) as Array<{ content_hash: string }>;\n db.run('DELETE FROM symbol_parent_file_map WHERE parent_id = ?', [parentId]);\n return rows.map((row) => row.content_hash);\n}\n\nexport function clearParentFileMapBatch(\n db: Database,\n parentId: number,\n limit: number,\n): { released: string[]; remaining: boolean } {\n const rows = db.all(\n `SELECT file_path, content_hash\n FROM symbol_parent_file_map\n WHERE parent_id = ?\n LIMIT ?`,\n [parentId, limit],\n ) as Array<{ file_path: string; content_hash: string | null }>;\n if (rows.length === 0) return { released: [], remaining: false };\n\n const del = db.prepare('DELETE FROM symbol_parent_file_map WHERE parent_id = ? AND file_path = ?');\n try {\n for (const row of rows) {\n del.run([parentId, row.file_path]);\n }\n } finally {\n del.finalize();\n }\n\n return {\n released: rows.flatMap((row) => (row.content_hash == null ? [] : [row.content_hash])),\n remaining: rows.length >= limit,\n };\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport { contentHashFileHasImports, contentHashFileHasTags } from './content-hash-check.js';\nimport { insertSymbolImportsForContent, insertSymbolTagsForContent } from './insert-symbol-content.js';\nimport { countParentFileMapRefs } from './parent-file-map.js';\n\nexport function upsertSymbolContentIndex(\n db: Database,\n contentHash: string,\n filePath: string,\n tags: readonly SymbolTag[],\n imports: readonly SymbolImportBinding[],\n): void {\n if (tags.length > 0 && !contentHashFileHasTags(db, contentHash, filePath)) {\n insertSymbolTagsForContent(db, contentHash, filePath, tags);\n }\n if (imports.length > 0 && !contentHashFileHasImports(db, contentHash, filePath)) {\n insertSymbolImportsForContent(db, contentHash, filePath, imports);\n }\n}\n\nexport function deleteSymbolContentIfUnreferenced(db: Database, contentHash: string): void {\n if (countParentFileMapRefs(db, contentHash) > 0) return;\n db.run('DELETE FROM symbol_index_tag WHERE content_hash = ?', [contentHash]);\n db.run('DELETE FROM symbol_index_import WHERE content_hash = ?', [contentHash]);\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { getParentFileMapHash } from './parent-file-map.js';\nimport type { SymbolIndexParentContext } from './parent-context.js';\n\n/** Resolved content hash for a file, or null when absent / tombstoned. */\nexport function getEffectiveContentHash(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n): string | null {\n const overlayHash = getParentFileMapHash(db, ctx.parentId, filePath);\n if (overlayHash !== undefined) return overlayHash;\n if (ctx.baseParentId == null) return null;\n const baseHash = getParentFileMapHash(db, ctx.baseParentId, filePath);\n if (baseHash === undefined) return null;\n return baseHash;\n}\n\nexport function listEffectiveIndexedFilePaths(db: Database, ctx: SymbolIndexParentContext): string[] {\n const paths = new Set<string>();\n if (ctx.baseParentId != null) {\n const baseRows = db.all('SELECT file_path FROM symbol_parent_file_map WHERE parent_id = ? AND content_hash IS NOT NULL', [\n ctx.baseParentId,\n ]) as Array<{ file_path: string }>;\n for (const row of baseRows) paths.add(row.file_path);\n }\n\n const overlayRows = db.all('SELECT file_path, content_hash FROM symbol_parent_file_map WHERE parent_id = ?', [\n ctx.parentId,\n ]) as Array<{ file_path: string; content_hash: string | null }>;\n for (const row of overlayRows) {\n if (row.content_hash == null) paths.delete(row.file_path);\n else paths.add(row.file_path);\n }\n\n if (ctx.baseParentId == null) {\n const ownRows = db.all('SELECT file_path FROM symbol_parent_file_map WHERE parent_id = ? AND content_hash IS NOT NULL', [\n ctx.parentId,\n ]) as Array<{ file_path: string }>;\n for (const row of ownRows) paths.add(row.file_path);\n }\n\n return [...paths];\n}\n", "import crypto from 'node:crypto';\n\n/** Stable content hash for a source file body (empty string when unreadable). */\nexport function hashSymbolFileContent(source: string | null | undefined): string {\n return crypto.createHash('sha256').update(source ?? '').digest('hex');\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport { deleteSymbolContentIfUnreferenced, upsertSymbolContentIndex } from '../storage/symbol-content-index.js';\nimport { getEffectiveContentHash } from '../storage/effective-content.js';\nimport {\n clearParentFileMap,\n clearParentFileMapBatch,\n getParentFileMapHash,\n removeParentFileMapEntry,\n setParentFileMapEntry,\n} from '../storage/parent-file-map.js';\nimport type { SymbolIndexParentContext } from '../storage/parent-context.js';\nimport { hashSymbolFileContent } from '../persistence/symbol-file-content-hash.js';\n\nfunction gcReleasedHashes(db: Database, hashes: Iterable<string | null | undefined>): void {\n for (const hash of hashes) {\n if (hash != null) deleteSymbolContentIfUnreferenced(db, hash);\n }\n}\n\nfunction persistFileSymbolData(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n contentHash: string,\n tags: SymbolTag[],\n imports: SymbolImportBinding[],\n): void {\n upsertSymbolContentIndex(db, contentHash, filePath, tags, imports);\n\n if (ctx.kind === 'overlay' && ctx.baseParentId != null) {\n const baseHash = getParentFileMapHash(db, ctx.baseParentId, filePath);\n if (baseHash === contentHash) {\n const released = removeParentFileMapEntry(db, ctx.parentId, filePath);\n gcReleasedHashes(db, [released]);\n return;\n }\n }\n\n const released = setParentFileMapEntry(db, ctx.parentId, filePath, contentHash);\n gcReleasedHashes(db, [released]);\n}\n\nexport function persistSymbolIndexFileData(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n source: string | null,\n tags: SymbolTag[],\n imports: SymbolImportBinding[],\n): void {\n const contentHash = hashSymbolFileContent(source);\n persistFileSymbolData(db, ctx, filePath, contentHash, tags, imports);\n}\n\nexport function removeSymbolIndexFileData(db: Database, ctx: SymbolIndexParentContext, filePath: string): void {\n if (ctx.kind === 'overlay') {\n const released = setParentFileMapEntry(db, ctx.parentId, filePath, null);\n gcReleasedHashes(db, [released]);\n return;\n }\n\n const released = removeParentFileMapEntry(db, ctx.parentId, filePath);\n gcReleasedHashes(db, [released]);\n}\n\nexport function clearSymbolIndexParentData(db: Database, ctx: SymbolIndexParentContext): void {\n const released = clearParentFileMap(db, ctx.parentId);\n gcReleasedHashes(db, released);\n}\n\nexport function clearSymbolIndexParentDataBatch(\n db: Database,\n ctx: SymbolIndexParentContext,\n limit: number,\n): boolean {\n const { released, remaining } = clearParentFileMapBatch(db, ctx.parentId, limit);\n gcReleasedHashes(db, released);\n return remaining;\n}\n\nexport function parentHasIndexedFile(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n): boolean {\n return getEffectiveContentHash(db, ctx, filePath) != null;\n}\n", "import { withCodeNavCacheSqliteSync } from '../../../sqlite/code-nav-cache/database.js';\nimport { getSymbolIndexParentContext } from './parent-path.js';\nimport { SYMBOL_INDEX_VERSION } from './symbol-index-version.js';\n\nexport function symbolIndexIsPopulated(resolvedParentPath: string): boolean {\n return withCodeNavCacheSqliteSync((db) => {\n const ctx = getSymbolIndexParentContext(db, resolvedParentPath);\n if (ctx == null) return false;\n\n const versionRow = db.get('SELECT index_version FROM symbol_index_parent_path WHERE id = ?', [\n ctx.parentId,\n ]) as { index_version: number } | null;\n if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return false;\n\n const ownRow = db.get(\n `SELECT 1 as ok FROM symbol_parent_file_map\n WHERE parent_id = ? AND content_hash IS NOT NULL\n LIMIT 1`,\n [ctx.parentId],\n ) as { ok: number } | null;\n if (ownRow != null) return true;\n\n if (ctx.baseParentId == null) return false;\n const baseRow = db.get(\n `SELECT index_version FROM symbol_index_parent_path WHERE id = ?`,\n [ctx.baseParentId],\n ) as { index_version: number } | null;\n if (baseRow == null || baseRow.index_version < SYMBOL_INDEX_VERSION) return false;\n\n const baseMapRow = db.get(\n `SELECT 1 as ok FROM symbol_parent_file_map\n WHERE parent_id = ? AND content_hash IS NOT NULL\n LIMIT 1`,\n [ctx.baseParentId],\n ) as { ok: number } | null;\n return baseMapRow != null;\n });\n}\n", "export { SYMBOL_INDEX_VERSION } from './symbol-index-version.js';\nexport {\n type SymbolIndexParentRow,\n getSymbolIndexParentContextById,\n getSymbolIndexParentContext,\n getSymbolIndexParentId,\n upsertSymbolIndexParentPath,\n} from './parent-path.js';\nexport {\n persistSymbolIndexFileData,\n removeSymbolIndexFileData,\n clearSymbolIndexParentData,\n clearSymbolIndexParentDataBatch,\n parentHasIndexedFile,\n} from './file-data-persistence.js';\nexport { symbolIndexIsPopulated } from './population.js';\n", "import { withCodeNavCacheSqliteWorkLock } from '../../../sqlite/code-nav-cache/code-nav-cache-sqlite-work-lock.js';\n\nexport function withSymbolIndexSqliteLock<T>(fn: () => T | Promise<T>): Promise<T> {\n return withCodeNavCacheSqliteWorkLock(fn);\n}\n", "import type { DbTagRow } from '../../resolution/types.js';\nimport type { CodeNavLocation } from '../../types.js';\n\nexport const TAG_SELECT = `file_path, name, role, kind, start_line, start_column, end_line, end_column,\n scope_start_line, scope_start_column, parent_scope_start_line, parent_scope_start_column, nav_target_path, scope_chain`;\n\nexport function rowToLocation(row: DbTagRow): CodeNavLocation {\n return {\n path: row.file_path,\n line: row.start_line + 1,\n column: row.start_column,\n kind: row.kind,\n role: row.role === 'def' ? 'definition' : 'reference',\n };\n}\n\nexport function modulePathLocation(row: DbTagRow): CodeNavLocation {\n return {\n path: row.nav_target_path!,\n line: 1,\n column: 0,\n kind: 'module',\n role: 'reference',\n };\n}\n\nexport function emptyRefRow(filePath: string): DbTagRow {\n return {\n file_path: filePath,\n name: '',\n role: 'ref',\n kind: '',\n start_line: 0,\n start_column: 0,\n end_line: 0,\n end_column: 0,\n scope_start_line: null,\n scope_start_column: null,\n parent_scope_start_line: null,\n parent_scope_start_column: null,\n nav_target_path: null,\n scope_chain: null,\n };\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { DbTagRow } from '../../resolution/types.js';\nimport type { DbImportRow } from '../sqlite/symbol-index-import-sqlite.js';\nimport { TAG_SELECT } from '../query/tag-query-shared.js';\nimport { getEffectiveContentHash, listEffectiveIndexedFilePaths } from './effective-content.js';\nimport type { SymbolIndexParentContext } from './parent-context.js';\n\nexport function loadFileTags(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n): DbTagRow[] {\n const contentHash = getEffectiveContentHash(db, ctx, filePath);\n if (contentHash == null) return [];\n return db.all(\n `SELECT ${TAG_SELECT}\n FROM symbol_index_tag\n WHERE content_hash = ? AND file_path = ?\n ORDER BY start_line, start_column`,\n [contentHash, filePath],\n ) as DbTagRow[];\n}\n\nexport function loadFileImports(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n): DbImportRow[] {\n const contentHash = getEffectiveContentHash(db, ctx, filePath);\n if (contentHash == null) return [];\n return db.all(\n `SELECT file_path, local_name, source_name, module_specifier, source_file_path, import_kind, start_line, start_column\n FROM symbol_index_import\n WHERE content_hash = ? AND file_path = ?\n ORDER BY start_line, start_column`,\n [contentHash, filePath],\n ) as DbImportRow[];\n}\n\nexport function findTagsByName(db: Database, ctx: SymbolIndexParentContext, name: string): DbTagRow[] {\n const filePaths = listEffectiveIndexedFilePaths(db, ctx);\n const rows: DbTagRow[] = [];\n for (const filePath of filePaths) {\n const contentHash = getEffectiveContentHash(db, ctx, filePath);\n if (contentHash == null) continue;\n const matches = db.all(\n `SELECT ${TAG_SELECT}\n FROM symbol_index_tag\n WHERE content_hash = ? AND file_path = ? AND name = ?\n ORDER BY start_line, start_column`,\n [contentHash, filePath, name],\n ) as DbTagRow[];\n rows.push(...matches);\n }\n rows.sort((a, b) =>\n a.file_path.localeCompare(b.file_path) ||\n a.start_line - b.start_line ||\n a.start_column - b.start_column,\n );\n return rows;\n}\n", "export type { SymbolIndexParentContext } from './parent-context.js';\nexport {\n getParentFileMapHash,\n countParentFileMapRefs,\n setParentFileMapEntry,\n removeParentFileMapEntry,\n clearParentFileMap,\n clearParentFileMapBatch,\n} from './parent-file-map.js';\nexport { getEffectiveContentHash, listEffectiveIndexedFilePaths } from './effective-content.js';\nexport { loadFileTags, loadFileImports, findTagsByName } from './file-content-load.js';\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { DbTagRow } from '../../resolution/types.js';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport type { DbImportRow } from '../sqlite/symbol-index-import-sqlite.js';\nimport { loadFileImports, loadFileTags, type SymbolIndexParentContext } from '../storage/symbol-parent-file-map.js';\nimport type { SymbolIndexFileEntry } from './collect-file-entries.js';\n\nfunction dbTagToSymbolTag(row: DbTagRow): SymbolTag {\n return {\n name: row.name,\n role: row.role as SymbolTag['role'],\n kind: row.kind,\n startLine: row.start_line,\n startColumn: row.start_column,\n endLine: row.end_line,\n endColumn: row.end_column,\n scopeStartLine: row.scope_start_line ?? undefined,\n scopeStartColumn: row.scope_start_column ?? undefined,\n parentScopeStartLine: row.parent_scope_start_line ?? undefined,\n parentScopeStartColumn: row.parent_scope_start_column ?? undefined,\n navTargetPath: row.nav_target_path ?? undefined,\n scopeChain: row.scope_chain ?? undefined,\n };\n}\n\nfunction dbImportToSymbolImport(row: DbImportRow): SymbolImportBinding {\n return {\n localName: row.local_name,\n sourceName: row.source_name,\n moduleSpecifier: row.module_specifier,\n sourceFilePath: row.source_file_path,\n importKind: row.import_kind as SymbolImportBinding['importKind'],\n startLine: row.start_line,\n startColumn: row.start_column,\n };\n}\n\nexport function loadIndexedFileEntry(\n db: Database,\n ctx: SymbolIndexParentContext,\n relPath: string,\n): SymbolIndexFileEntry | undefined {\n const tags = loadFileTags(db, ctx, relPath);\n const imports = loadFileImports(db, ctx, relPath);\n if (tags.length === 0 && imports.length === 0) return undefined;\n return {\n relPath,\n source: null,\n tags: tags.map(dbTagToSymbolTag),\n imports: imports.map(dbImportToSymbolImport),\n };\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport {\n withCodeNavCacheSqlite,\n withCodeNavCacheSqliteSync,\n} from '../../../sqlite/code-nav-cache/database.js';\nimport { loadIndexedFileEntry } from '../build/load-indexed-file-entry.js';\nimport { getSymbolIndexParentContext } from '../sqlite/symbol-index-sqlite.js';\n\nfunction normalizeRelPath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n}\n\nfunction listDirectImportTargetsWithDb(db: Database, resolved: string, relPath: string): string[] {\n const ctx = getSymbolIndexParentContext(db, resolved);\n if (ctx == null) return [];\n const entry = loadIndexedFileEntry(db, ctx, relPath);\n if (entry == null) return [];\n const paths = new Set<string>();\n for (const binding of entry.imports) {\n if (binding.sourceFilePath) paths.add(binding.sourceFilePath);\n }\n return Array.from(paths);\n}\n\nexport async function listDirectImportTargetsForFileAsync(parentPath: string, filePath: string): Promise<string[]> {\n const resolved = normalizeResolvedPath(parentPath);\n const relPath = normalizeRelPath(filePath);\n if (!relPath) return [];\n\n return withCodeNavCacheSqlite((db) => listDirectImportTargetsWithDb(db, resolved, relPath));\n}\n\n/** @deprecated Prefer {@link listDirectImportTargetsForFileAsync}. */\nexport function listDirectImportTargetsForFile(parentPath: string, filePath: string): string[] {\n const resolved = normalizeResolvedPath(parentPath);\n const relPath = normalizeRelPath(filePath);\n if (!relPath) return [];\n\n return withCodeNavCacheSqliteSync((db) => listDirectImportTargetsWithDb(db, resolved, relPath));\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { withCodeNavCacheSqlite, withCodeNavCacheSqliteProbe } from '../../../sqlite/code-nav-cache/database.js';\nimport { getSymbolIndexParentContext, SYMBOL_INDEX_VERSION } from '../sqlite/symbol-index-sqlite.js';\nimport { getEffectiveContentHash, listEffectiveIndexedFilePaths } from '../storage/symbol-parent-file-map.js';\n\nfunction symbolIndexFileIsReadyWithDb(db: Database, parentPath: string, filePath: string): boolean {\n const normalizedParent = normalizeResolvedPath(parentPath);\n const normalizedFile = filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!normalizedFile) return false;\n\n const ctx = getSymbolIndexParentContext(db, normalizedParent);\n if (ctx == null) return false;\n\n const versionRow = db.get('SELECT index_version FROM symbol_index_parent_path WHERE id = ?', [\n ctx.parentId,\n ]) as { index_version: number } | null;\n if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return false;\n\n return getEffectiveContentHash(db, ctx, normalizedFile) != null;\n}\n\n/** True when the effective file map resolves to indexed content for this parent + path. */\nexport async function symbolIndexFileIsReadyAsync(parentPath: string, filePath: string): Promise<boolean> {\n return withCodeNavCacheSqlite((db) => symbolIndexFileIsReadyWithDb(db, parentPath, filePath));\n}\n\n/** Non-blocking readiness probe for interactive code-nav (no long SQLite lock retries). */\nexport async function symbolIndexFileIsReadyProbe(parentPath: string, filePath: string): Promise<boolean> {\n const ready = await withCodeNavCacheSqliteProbe((db) =>\n symbolIndexFileIsReadyWithDb(db, parentPath, filePath),\n );\n return ready === true;\n}\n\n/** All indexed relative paths for a parent (one SQLite round-trip for warmup scheduling). */\nexport async function loadSymbolIndexReadyFileSet(parentPath: string): Promise<Set<string>> {\n const normalizedParent = normalizeResolvedPath(parentPath);\n const paths = await withCodeNavCacheSqlite((db) => {\n const ctx = getSymbolIndexParentContext(db, normalizedParent);\n if (ctx == null) return [] as string[];\n\n const versionRow = db.get('SELECT index_version FROM symbol_index_parent_path WHERE id = ?', [\n ctx.parentId,\n ]) as { index_version: number } | null;\n if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return [] as string[];\n\n return listEffectiveIndexedFilePaths(db, ctx);\n });\n return new Set(paths);\n}\n", "import type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport type { SymbolIndexFileEntry } from '../build/collect-file-entries.js';\n\nconst STAR_LOCAL_NAME = '*';\n\nfunction isModuleLevelDef(tag: SymbolTag): boolean {\n return tag.role === 'def' && tag.parentScopeStartLine == null && tag.parentScopeStartColumn == null;\n}\n\nfunction collectExportableNamesFromTags(tags: readonly SymbolTag[]): Map<string, string> {\n const names = new Map<string, string>();\n for (const tag of tags) {\n if (!isModuleLevelDef(tag)) continue;\n if (!names.has(tag.name)) names.set(tag.name, tag.name);\n }\n return names;\n}\n\nexport function existingLocalNames(imports: readonly SymbolImportBinding[]): Set<string> {\n return new Set(imports.map((binding) => binding.localName));\n}\n\nexport function resolveExportableNames(\n filePath: string,\n entriesByPath: ReadonlyMap<string, SymbolIndexFileEntry>,\n visited: Set<string>,\n): Map<string, { sourceName: string; sourceFilePath: string }> {\n if (visited.has(filePath)) return new Map();\n visited.add(filePath);\n\n const entry = entriesByPath.get(filePath);\n if (!entry) return new Map();\n\n const out = collectExportableNamesFromTags(entry.tags);\n const resolved = new Map<string, { sourceName: string; sourceFilePath: string }>();\n for (const [name, sourceName] of out) {\n resolved.set(name, { sourceName, sourceFilePath: filePath });\n }\n\n for (const binding of entry.imports) {\n if (binding.importKind !== 'star' || !binding.sourceFilePath) continue;\n const upstream = resolveExportableNames(binding.sourceFilePath, entriesByPath, visited);\n for (const [name, info] of upstream) {\n if (!resolved.has(name)) resolved.set(name, info);\n }\n }\n\n for (const binding of entry.imports) {\n if (binding.importKind !== 'reexport' && binding.importKind !== 'type') continue;\n if (!binding.sourceFilePath) continue;\n if (!resolved.has(binding.localName)) {\n resolved.set(binding.localName, {\n sourceName: binding.sourceName,\n sourceFilePath: binding.sourceFilePath,\n });\n }\n }\n\n return resolved;\n}\n\nexport { STAR_LOCAL_NAME };\n", "import type { SymbolIndexFileEntry } from '../build/collect-file-entries.js';\n\nexport function collectUpstreamEntries(\n entry: SymbolIndexFileEntry,\n resolveEntry: (filePath: string) => SymbolIndexFileEntry | undefined,\n): SymbolIndexFileEntry[] {\n const entriesByPath = new Map<string, SymbolIndexFileEntry>();\n entriesByPath.set(entry.relPath, entry);\n\n const visit = (filePath: string, visited: Set<string>): void => {\n if (visited.has(filePath)) return;\n visited.add(filePath);\n const resolved = resolveEntry(filePath);\n if (resolved == null) return;\n entriesByPath.set(filePath, resolved);\n for (const binding of resolved.imports) {\n if (binding.sourceFilePath) visit(binding.sourceFilePath, visited);\n }\n };\n\n for (const star of entry.imports) {\n if (star.importKind !== 'star' || !star.sourceFilePath) continue;\n visit(star.sourceFilePath, new Set());\n }\n\n return [...entriesByPath.values()];\n}\n", "import type { SymbolImportBinding } from '../../types.js';\nimport type { SymbolIndexFileEntry } from '../build/collect-file-entries.js';\nimport { existingLocalNames, resolveExportableNames, STAR_LOCAL_NAME } from './star-reexport-names.js';\nimport { collectUpstreamEntries } from './star-reexport-upstream.js';\n\n/** Expand star re-exports for one file using lazily resolved upstream entries. */\nexport function expandStarReexportForFile(\n entry: SymbolIndexFileEntry,\n resolveEntry: (filePath: string) => SymbolIndexFileEntry | undefined,\n): SymbolIndexFileEntry {\n const collected = collectUpstreamEntries(entry, resolveEntry);\n return expandStarReexportBindings(collected).find((row) => row.relPath === entry.relPath) ?? entry;\n}\n\n/** Materialize `export * from` bindings as explicit re-export rows for each exported symbol. */\nexport function expandStarReexportBindings(collected: SymbolIndexFileEntry[]): SymbolIndexFileEntry[] {\n const entriesByPath = new Map(collected.map((entry) => [entry.relPath, entry]));\n\n return collected.map((entry) => {\n const stars = entry.imports.filter((binding) => binding.importKind === 'star');\n if (stars.length === 0) return entry;\n\n const localNames = existingLocalNames(entry.imports);\n const materialized: SymbolImportBinding[] = [];\n\n for (const star of stars) {\n if (!star.sourceFilePath) continue;\n const exportable = resolveExportableNames(star.sourceFilePath, entriesByPath, new Set());\n for (const [localName, info] of exportable) {\n if (localName === STAR_LOCAL_NAME || localNames.has(localName)) continue;\n localNames.add(localName);\n materialized.push({\n localName,\n sourceName: info.sourceName,\n moduleSpecifier: star.moduleSpecifier,\n sourceFilePath: info.sourceFilePath,\n importKind: star.importKind === 'type' ? 'type' : 'reexport',\n startLine: star.startLine,\n startColumn: star.startColumn,\n });\n }\n }\n\n if (materialized.length === 0) return entry;\n return { ...entry, imports: [...entry.imports, ...materialized] };\n });\n}\n", "import type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { runCodeNavCacheWriteTransaction } from '../../../sqlite/code-nav-cache/code-nav-cache-sqlite-transaction.js';\nimport {\n getSymbolIndexParentContext,\n persistSymbolIndexFileData,\n removeSymbolIndexFileData,\n upsertSymbolIndexParentPath,\n} from '../sqlite/symbol-index-sqlite.js';\n\nexport async function persistSymbolIndexFileAsync(\n resolved: string,\n relPath: string,\n source: string | null,\n tags: SymbolTag[],\n imports: SymbolImportBinding[],\n): Promise<void> {\n await withCodeNavCacheSqlite(async (db) => {\n runCodeNavCacheWriteTransaction(db, () => {\n upsertSymbolIndexParentPath(db, resolved);\n const ctx = getSymbolIndexParentContext(db, resolved);\n if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);\n persistSymbolIndexFileData(db, ctx, relPath, source, tags, imports);\n });\n });\n}\n\n/** @deprecated Prefer {@link persistSymbolIndexFileAsync}. */\nexport function persistSymbolIndexFile(\n resolved: string,\n relPath: string,\n source: string | null,\n tags: SymbolTag[],\n imports: SymbolImportBinding[],\n): void {\n void persistSymbolIndexFileAsync(resolved, relPath, source, tags, imports);\n}\n\nexport async function removeSymbolIndexFileAsync(resolved: string, relPath: string): Promise<void> {\n await withCodeNavCacheSqlite(async (db) => {\n runCodeNavCacheWriteTransaction(db, () => {\n upsertSymbolIndexParentPath(db, resolved);\n const ctx = getSymbolIndexParentContext(db, resolved);\n if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);\n removeSymbolIndexFileData(db, ctx, relPath);\n });\n });\n}\n\n/** @deprecated Prefer {@link removeSymbolIndexFileAsync}. */\nexport function removeSymbolIndexFile(resolved: string, relPath: string): void {\n void removeSymbolIndexFileAsync(resolved, relPath);\n}\n", "import path from 'node:path';\nimport { getLanguageKeyForFilePath } from './language-registry.js';\n\nconst TS_JS_EXTENSIONS = ['', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '/index.ts', '/index.tsx', '/index.js', '/index.jsx'];\nconst PYTHON_EXTENSIONS = ['.py', '/__init__.py'];\nconst C_CPP_EXTENSIONS = ['', '.h', '.hpp', '.hh', '.hxx', '.c', '.cpp', '.cc', '.cxx'];\n\nfunction normalizeWorkspacePath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n}\n\nfunction isRelativeModuleSpecifier(specifier: string): boolean {\n return specifier.startsWith('./') || specifier.startsWith('../') || specifier.startsWith('/');\n}\n\nfunction firstExistingPath(candidates: string[], workspaceFiles: ReadonlySet<string>): string | null {\n for (const candidate of candidates) {\n const normalized = normalizeWorkspacePath(candidate);\n if (workspaceFiles.has(normalized)) return normalized;\n }\n return null;\n}\n\nfunction withSuffixes(basePath: string, suffixes: readonly string[]): string[] {\n return suffixes.map((suffix) => basePath + suffix);\n}\n\n/** Candidates for TS/JS imports, including ESM `.js` specifiers that refer to `.ts` sources. */\nfunction tsJsImportCandidates(joined: string): string[] {\n const candidates = withSuffixes(joined, TS_JS_EXTENSIONS);\n\n const extensionRewrites: ReadonlyArray<[string, readonly string[]]> = [\n ['.js', ['.ts', '.tsx', '.js', '.jsx']],\n ['.jsx', ['.tsx', '.ts', '.jsx', '.js']],\n ['.mjs', ['.mts', '.ts', '.mjs', '.js']],\n ['.cjs', ['.cts', '.ts', '.cjs', '.js']],\n ];\n for (const [fromExt, toExts] of extensionRewrites) {\n if (!joined.endsWith(fromExt)) continue;\n const stem = joined.slice(0, -fromExt.length);\n for (const toExt of toExts) {\n candidates.unshift(stem + toExt);\n }\n for (const indexSuffix of ['/index.ts', '/index.tsx', '/index.js', '/index.jsx']) {\n candidates.unshift(stem + indexSuffix);\n }\n }\n\n return candidates;\n}\n\n/**\n * Resolve a relative TS/JS module specifier to a workspace-relative file path using the indexed file list.\n */\nexport function resolveModuleImportPath(\n importerFilePath: string,\n moduleSpecifier: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const spec = moduleSpecifier.trim();\n if (!spec || !isRelativeModuleSpecifier(spec)) return null;\n\n const importerDir = path.posix.dirname(normalizeWorkspacePath(importerFilePath));\n const joined = normalizeWorkspacePath(path.posix.normalize(path.posix.join(importerDir, spec)));\n\n return firstExistingPath(tsJsImportCandidates(joined), workspaceFiles);\n}\n\nfunction resolvePythonModulePath(\n importerFilePath: string,\n moduleSpecifier: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const moduleName = moduleSpecifier.trim().replace(/\\s+/g, '');\n if (!moduleName) return null;\n\n const importerDir = path.posix.dirname(normalizeWorkspacePath(importerFilePath));\n\n if (moduleName.startsWith('.')) {\n const dotMatch = /^(\\.+)(.*)$/.exec(moduleName);\n const dotCount = dotMatch?.[1]?.length ?? 1;\n const rest = (dotMatch?.[2] ?? '').replace(/^\\./, '');\n let baseDir = importerDir;\n for (let i = 1; i < dotCount; i++) {\n baseDir = path.posix.dirname(baseDir);\n }\n const dottedPath = rest ? rest.split('.').join('/') : '';\n const relativeBase = dottedPath ? path.posix.join(baseDir, dottedPath) : baseDir;\n return firstExistingPath(\n [\n ...withSuffixes(relativeBase, PYTHON_EXTENSIONS),\n ...withSuffixes(path.posix.join(relativeBase, '__init__'), ['.py']),\n ],\n workspaceFiles,\n );\n }\n\n const dottedPath = moduleName.split('.').join('/');\n\n return firstExistingPath(\n [\n ...withSuffixes(dottedPath, PYTHON_EXTENSIONS),\n ...withSuffixes(path.posix.join(importerDir, dottedPath), PYTHON_EXTENSIONS),\n ],\n workspaceFiles,\n );\n}\n\nfunction resolveIncludePath(\n importerFilePath: string,\n includePath: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const spec = includePath.trim().replace(/^[\"']|[\"']$/g, '');\n if (!spec) return null;\n\n const importerDir = path.posix.dirname(normalizeWorkspacePath(importerFilePath));\n const joined = normalizeWorkspacePath(\n path.posix.normalize(path.posix.join(importerDir, spec.replace(/\\\\/g, '/'))),\n );\n\n if (workspaceFiles.has(joined)) return joined;\n return firstExistingPath(withSuffixes(joined, C_CPP_EXTENSIONS), workspaceFiles);\n}\n\nfunction resolveJavaImportPath(moduleSpecifier: string, workspaceFiles: ReadonlySet<string>): string | null {\n const spec = moduleSpecifier.trim();\n if (!spec) return null;\n\n const pathLike = `${spec.replace(/\\./g, '/')}.java`;\n if (workspaceFiles.has(pathLike)) return pathLike;\n\n for (const file of workspaceFiles) {\n if (file === pathLike || file.endsWith(`/${pathLike}`)) return file;\n }\n return null;\n}\n\nfunction resolveGoImportPath(\n importerFilePath: string,\n moduleSpecifier: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const spec = moduleSpecifier.trim();\n if (!spec) return null;\n\n if (isRelativeModuleSpecifier(spec)) {\n const importerDir = path.posix.dirname(normalizeWorkspacePath(importerFilePath));\n const joined = normalizeWorkspacePath(path.posix.normalize(path.posix.join(importerDir, spec)));\n if (workspaceFiles.has(joined)) return joined;\n return firstExistingPath(withSuffixes(joined, ['.go']), workspaceFiles);\n }\n\n const leaf = spec.split('/').filter(Boolean).at(-1);\n if (!leaf) return null;\n for (const file of workspaceFiles) {\n if (file.endsWith(`/${leaf}.go`) || file === `${leaf}.go`) return file;\n }\n return null;\n}\n\n/** Resolve an import/include specifier to a workspace-relative source file path. */\nexport function resolveImportSourcePath(\n importerFilePath: string,\n moduleSpecifier: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const spec = moduleSpecifier.trim();\n if (!spec) return null;\n\n const tsResult = resolveModuleImportPath(importerFilePath, spec, workspaceFiles);\n if (tsResult) return tsResult;\n\n const languageKey = getLanguageKeyForFilePath(importerFilePath);\n switch (languageKey) {\n case 'python':\n return resolvePythonModulePath(importerFilePath, spec, workspaceFiles);\n case 'c':\n case 'cpp':\n return resolveIncludePath(importerFilePath, spec, workspaceFiles);\n case 'java':\n return resolveJavaImportPath(spec, workspaceFiles);\n case 'go':\n return resolveGoImportPath(importerFilePath, spec, workspaceFiles);\n default:\n return null;\n }\n}\n\nexport function isModulePathSpecifier(name: string): boolean {\n return isRelativeModuleSpecifier(name.trim());\n}\n", "import path from 'node:path';\nimport type { SymbolTag } from './types.js';\nimport { isModulePathSpecifier, resolveModuleImportPath } from './resolve-module-import-path.js';\n\nexport function enrichTagsWithModulePaths(\n tags: readonly SymbolTag[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolTag[] {\n return tags.map((tag) => {\n if (tag.kind !== 'module' || tag.role !== 'ref' || !isModulePathSpecifier(tag.name)) {\n return tag;\n }\n const resolved = resolveModuleImportPath(filePath, tag.name, workspaceFiles);\n if (!resolved) return tag;\n return { ...tag, navTargetPath: resolved };\n });\n}\n\nexport function workspaceFilesFromCollected(collected: ReadonlyArray<{ relPath: string }>): Set<string> {\n return new Set(collected.map((entry) => entry.relPath.replace(/\\\\/g, '/')));\n}\n\nexport function workspaceFilesFromParent(parentPath: string, relPaths: readonly string[]): Set<string> {\n return new Set(relPaths.map((rel) => path.posix.normalize(rel.replace(/\\\\/g, '/'))));\n}\n", "import type { CodeNavYieldState } from './yield-during-work.js';\nimport { yieldDuringCodeNavWork } from './yield-during-work.js';\nimport type { SymbolTag } from './types.js';\nimport { enrichTagsWithModulePaths } from './enrich-tag-module-paths.js';\n\n/** Enrich module path tags in chunks so large files can yield to the event loop. */\nexport async function enrichTagsWithModulePathsAsync(\n tags: readonly SymbolTag[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n state: CodeNavYieldState,\n): Promise<SymbolTag[]> {\n const chunkSize = 64;\n const enriched: SymbolTag[] = [];\n\n for (let i = 0; i < tags.length; i += chunkSize) {\n await yieldDuringCodeNavWork(state);\n const chunk = tags.slice(i, i + chunkSize);\n enriched.push(...enrichTagsWithModulePaths(chunk, filePath, workspaceFiles));\n }\n\n return enriched;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from './types.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from './yield-during-work.js';\n\nconst PARAM_NODE_TYPES = new Set(['required_parameter', 'optional_parameter']);\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\nfunction collectParamNames(functionTypeNode: SyntaxNode): Set<string> {\n const names = new Set<string>();\n const parameters = functionTypeNode.childForFieldName('parameters');\n if (!parameters) return names;\n\n function walk(node: SyntaxNode): void {\n if (PARAM_NODE_TYPES.has(node.type)) {\n const nameNode = node.childForFieldName('pattern') ?? node.namedChildren.find((c) => c.type === 'identifier');\n if (nameNode?.type === 'identifier') names.add(nameNode.text);\n return;\n }\n for (const child of node.namedChildren) walk(child);\n }\n\n walk(parameters);\n return names;\n}\n\nfunction isDefinitionName(node: SyntaxNode): boolean {\n const parent = node.parent;\n if (!parent) return false;\n if (PARAM_NODE_TYPES.has(parent.type)) return true;\n if (parent.type === 'type_parameter' && parent.childForFieldName('name') === node) return true;\n return false;\n}\n\nfunction tagFromIdentifierNode(node: SyntaxNode): SymbolTag {\n return {\n name: node.text,\n role: 'ref',\n kind: 'variable',\n startLine: node.startPosition.row,\n startColumn: node.startPosition.column,\n endLine: node.endPosition.row,\n endColumn: node.endPosition.column,\n };\n}\n\nfunction enclosingFunctionTypes(node: SyntaxNode): SyntaxNode[] {\n const types: SyntaxNode[] = [];\n let current: SyntaxNode | null = node.parent;\n while (current) {\n if (current.type === 'function_type') types.push(current);\n current = current.parent;\n }\n return types;\n}\n\nfunction isFunctionTypeParamReference(node: SyntaxNode): boolean {\n if (node.type !== 'identifier' || isDefinitionName(node)) return false;\n\n for (const functionType of enclosingFunctionTypes(node)) {\n const returnType = functionType.childForFieldName('return_type');\n if (!returnType?.descendantsOfType('identifier').some((desc) => desc.id === node.id)) continue;\n if (collectParamNames(functionType).has(node.text)) return true;\n }\n return false;\n}\n\n/** Capture callback-type parameter references in return types (e.g. type predicates). */\nexport async function augmentFunctionTypeParamReferenceTags(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n root: SyntaxNode,\n): Promise<SymbolTag[]> {\n const seen = new Set(tags.map(tagDedupeKey));\n const out = [...tags];\n const state = createCodeNavYieldState();\n\n async function walk(node: SyntaxNode): Promise<void> {\n if (isFunctionTypeParamReference(node)) {\n const tag = tagFromIdentifierNode(node);\n const key = tagDedupeKey(tag);\n if (!seen.has(key)) {\n seen.add(key);\n out.push(tag);\n nameNodes.set(`${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`, node);\n }\n }\n for (const child of node.children) {\n await yieldDuringCodeNavWork(state);\n await walk(child);\n }\n }\n\n await walk(root);\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from './types.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from './yield-during-work.js';\n\nconst TYPE_DEFINITION_CONTAINER_TYPES = new Set([\n 'function_declaration',\n 'function_signature',\n 'generator_function_declaration',\n 'class_declaration',\n 'abstract_class_declaration',\n 'interface_declaration',\n 'type_alias_declaration',\n 'enum_declaration',\n 'module',\n 'type_parameter',\n 'method_definition',\n 'method_signature',\n 'abstract_method_signature',\n 'property_signature',\n 'public_field_definition',\n]);\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\nfunction isTypeDefinitionName(node: SyntaxNode): boolean {\n const parent = node.parent;\n if (!parent) return false;\n return TYPE_DEFINITION_CONTAINER_TYPES.has(parent.type) && parent.childForFieldName('name') === node;\n}\n\nfunction tagFromTypeIdentifierNode(node: SyntaxNode): SymbolTag {\n return {\n name: node.text,\n role: 'ref',\n kind: 'type',\n startLine: node.startPosition.row,\n startColumn: node.startPosition.column,\n endLine: node.endPosition.row,\n endColumn: node.endPosition.column,\n };\n}\n\n/** Capture type_identifier uses that tags.scm patterns miss (unions, arrays, etc.). */\nexport async function augmentTypeReferenceTags(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n root: SyntaxNode,\n): Promise<SymbolTag[]> {\n const seen = new Set(tags.map(tagDedupeKey));\n const out = [...tags];\n const state = createCodeNavYieldState();\n\n async function walk(node: SyntaxNode): Promise<void> {\n if (node.type === 'type_identifier' && !isTypeDefinitionName(node)) {\n const tag = tagFromTypeIdentifierNode(node);\n const key = tagDedupeKey(tag);\n if (!seen.has(key)) {\n seen.add(key);\n out.push(tag);\n nameNodes.set(`${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`, node);\n }\n }\n for (const child of node.children) {\n await yieldDuringCodeNavWork(state);\n await walk(child);\n }\n }\n\n await walk(root);\n return out;\n}\n", "export type ScopeAnchor = { startLine: number; startColumn: number };\n\nexport function scopeAnchorKey(anchor: ScopeAnchor | null | undefined): string | null {\n if (anchor == null) return null;\n return `${anchor.startLine}:${anchor.startColumn}`;\n}\n\nexport function serializeScopeChain(chain: readonly ScopeAnchor[]): string | null {\n if (chain.length === 0) return null;\n return chain.map((anchor) => `${anchor.startLine}:${anchor.startColumn}`).join(',');\n}\n\nexport function parseScopeChain(raw: string | null | undefined): ScopeAnchor[] {\n if (!raw) return [];\n const out: ScopeAnchor[] = [];\n for (const part of raw.split(',')) {\n if (!part) continue;\n const colon = part.indexOf(':');\n if (colon < 0) continue;\n const startLine = Number(part.slice(0, colon));\n const startColumn = Number(part.slice(colon + 1));\n if (!Number.isFinite(startLine) || !Number.isFinite(startColumn)) continue;\n out.push({ startLine, startColumn });\n }\n return out;\n}\n\nexport function scopeChainKeys(chain: readonly ScopeAnchor[]): string[] {\n return chain.map((anchor) => scopeAnchorKey(anchor)!).filter(Boolean);\n}\n\nexport function anchorInScopeChain(\n line: number | null | undefined,\n column: number | null | undefined,\n chain: readonly ScopeAnchor[],\n): boolean {\n if (line == null || column == null) return chain.length === 0;\n return chain.some((anchor) => anchor.startLine === line && anchor.startColumn === column);\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from './types.js';\nimport type { ScopeAnchor } from './scope-chain.js';\nimport { serializeScopeChain } from './scope-chain.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from './yield-during-work.js';\n\nconst SCOPE_CONTAINER_TYPES = new Set([\n 'function_declaration',\n 'function_expression',\n 'generator_function',\n 'generator_function_declaration',\n 'method_definition',\n 'method_signature',\n 'abstract_method_signature',\n 'class_declaration',\n 'abstract_class_declaration',\n 'interface_declaration',\n 'module',\n 'arrow_function',\n 'function_type',\n 'function_item',\n 'impl_item',\n 'function_definition',\n 'class_definition',\n]);\n\nfunction scopeAnchorFromNode(node: SyntaxNode): ScopeAnchor {\n const nameNode = node.childForFieldName('name');\n if (nameNode) {\n return {\n startLine: nameNode.startPosition.row,\n startColumn: nameNode.startPosition.column,\n };\n }\n return {\n startLine: node.startPosition.row,\n startColumn: node.startPosition.column,\n };\n}\n\nexport function findEnclosingScopeChain(nameNode: SyntaxNode): ScopeAnchor[] {\n const chain: ScopeAnchor[] = [];\n let current: SyntaxNode | null = nameNode.parent;\n\n while (current) {\n if (SCOPE_CONTAINER_TYPES.has(current.type)) {\n chain.push(scopeAnchorFromNode(current));\n }\n current = current.parent;\n }\n\n return chain;\n}\n\nexport function findEnclosingScopes(nameNode: SyntaxNode): {\n scope: ScopeAnchor | null;\n parentScope: ScopeAnchor | null;\n scopeChain: ScopeAnchor[];\n} {\n const scopeChain = findEnclosingScopeChain(nameNode);\n return {\n scope: scopeChain[0] ?? null,\n parentScope: scopeChain[1] ?? null,\n scopeChain,\n };\n}\n\nexport async function enrichTagsWithEnclosingScope(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n): Promise<SymbolTag[]> {\n const state = createCodeNavYieldState();\n const out: SymbolTag[] = [];\n for (const tag of tags) {\n await yieldDuringCodeNavWork(state);\n const key = `${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`;\n const nameNode = nameNodes.get(key);\n if (!nameNode) {\n out.push(tag);\n continue;\n }\n const { scope, parentScope, scopeChain } = findEnclosingScopes(nameNode);\n if (!scope) {\n out.push(tag);\n continue;\n }\n out.push({\n ...tag,\n scopeStartLine: scope.startLine,\n scopeStartColumn: scope.startColumn,\n parentScopeStartLine: parentScope?.startLine,\n parentScopeStartColumn: parentScope?.startColumn,\n scopeChain: serializeScopeChain(scopeChain) ?? undefined,\n });\n }\n return out;\n}\n\nexport function scopeKey(scope: ScopeAnchor | null | undefined): string | null {\n if (scope == null) return null;\n return `${scope.startLine}:${scope.startColumn}`;\n}\n\nexport function scopesMatch(\n aLine: number | null | undefined,\n aCol: number | null | undefined,\n bLine: number | null | undefined,\n bCol: number | null | undefined,\n): boolean {\n return aLine != null && aCol != null && bLine != null && bCol != null && aLine === bLine && aCol === bCol;\n}\n", "import type { MemberAccessRule } from './types.js';\n\nexport const C_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'field_expression', objectField: 'argument', propertyField: 'field', tagKind: 'member' },\n];\n", "import type { MemberAccessRule } from './types.js';\nimport { C_MEMBER_ACCESS_RULES } from './c.js';\n\nexport const CPP_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n ...C_MEMBER_ACCESS_RULES,\n { parentType: 'qualified_identifier', objectField: 'scope', propertyField: 'name', tagKind: 'member' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const GO_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'selector_expression', objectField: 'operand', propertyField: 'field', tagKind: 'member' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const ECMA_SCRIPT_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'member_expression', objectField: 'object', propertyField: 'property', tagKind: 'member' },\n];\n\nexport const JAVASCRIPT_MEMBER_ACCESS_RULES = ECMA_SCRIPT_MEMBER_ACCESS_RULES;\nexport const TYPESCRIPT_MEMBER_ACCESS_RULES = ECMA_SCRIPT_MEMBER_ACCESS_RULES;\nexport const TSX_MEMBER_ACCESS_RULES = ECMA_SCRIPT_MEMBER_ACCESS_RULES;\n", "import type { MemberAccessRule } from './types.js';\n\nexport const JAVA_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'field_access', objectField: 'object', propertyField: 'field', tagKind: 'member' },\n { parentType: 'method_invocation', objectField: 'object', propertyField: 'name', tagKind: 'call' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const PYTHON_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'attribute', objectField: 'object', propertyField: 'attribute', tagKind: 'member' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const RUBY_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'call', objectField: 'receiver', propertyField: 'method', tagKind: 'call' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const RUST_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'field_expression', objectField: 'value', propertyField: 'field', tagKind: 'member' },\n { parentType: 'scoped_identifier', objectField: 'path', propertyField: 'name', tagKind: 'member' },\n];\n", "export {\n ECMA_SCRIPT_MEMBER_ACCESS_RULES as TSX_MEMBER_ACCESS_RULES,\n} from './javascript.js';\n", "export {\n ECMA_SCRIPT_MEMBER_ACCESS_RULES as TYPESCRIPT_MEMBER_ACCESS_RULES,\n} from './javascript.js';\n", "import { C_MEMBER_ACCESS_RULES } from './c.js';\nimport { CPP_MEMBER_ACCESS_RULES } from './cpp.js';\nimport { GO_MEMBER_ACCESS_RULES } from './go.js';\nimport { JAVASCRIPT_MEMBER_ACCESS_RULES } from './javascript.js';\nimport { JAVA_MEMBER_ACCESS_RULES } from './java.js';\nimport { PYTHON_MEMBER_ACCESS_RULES } from './python.js';\nimport { RUBY_MEMBER_ACCESS_RULES } from './ruby.js';\nimport { RUST_MEMBER_ACCESS_RULES } from './rust.js';\nimport { TSX_MEMBER_ACCESS_RULES } from './tsx.js';\nimport { TYPESCRIPT_MEMBER_ACCESS_RULES } from './typescript.js';\nimport type { MemberAccessRule } from './types.js';\n\nexport const MEMBER_ACCESS_RULES_BY_LANGUAGE_KEY: Readonly<Record<string, readonly MemberAccessRule[]>> = {\n javascript: JAVASCRIPT_MEMBER_ACCESS_RULES,\n typescript: TYPESCRIPT_MEMBER_ACCESS_RULES,\n tsx: TSX_MEMBER_ACCESS_RULES,\n python: PYTHON_MEMBER_ACCESS_RULES,\n go: GO_MEMBER_ACCESS_RULES,\n rust: RUST_MEMBER_ACCESS_RULES,\n ruby: RUBY_MEMBER_ACCESS_RULES,\n java: JAVA_MEMBER_ACCESS_RULES,\n c: C_MEMBER_ACCESS_RULES,\n cpp: CPP_MEMBER_ACCESS_RULES,\n};\n\nexport function memberAccessRulesForLanguageKey(languageKey: string | null): readonly MemberAccessRule[] {\n if (!languageKey) return [];\n return MEMBER_ACCESS_RULES_BY_LANGUAGE_KEY[languageKey] ?? [];\n}\n", "export type ScopeAnchor = {\n startLine: number;\n startColumn: number;\n};\n\nexport type MemberAccessRule = {\n parentType: string;\n objectField: string;\n propertyField: string;\n tagKind?: string;\n};\n\nexport const MEMBER_NAME_NODE_TYPES = new Set([\n 'identifier',\n 'property_identifier',\n 'field_identifier',\n 'type_identifier',\n 'constant',\n 'package_identifier',\n]);\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { MemberAccessRule } from './types.js';\nimport { MEMBER_NAME_NODE_TYPES } from './types.js';\n\nexport function nodesMatch(a: SyntaxNode, b: SyntaxNode): boolean {\n return (\n a.startPosition.row === b.startPosition.row &&\n a.startPosition.column === b.startPosition.column &&\n a.text === b.text\n );\n}\n\nfunction fieldNodeMatches(node: SyntaxNode | null, candidate: SyntaxNode): boolean {\n return node != null && nodesMatch(node, candidate);\n}\n\nexport function isReceiverNameNode(node: SyntaxNode): boolean {\n return (\n MEMBER_NAME_NODE_TYPES.has(node.type) ||\n node.type === 'this' ||\n node.type === 'self' ||\n node.type === 'super'\n );\n}\n\nexport function objectNodeFromAccessNode(accessNode: SyntaxNode, rule: MemberAccessRule): SyntaxNode | null {\n const objectNode = accessNode.childForFieldName(rule.objectField);\n if (!objectNode || !isReceiverNameNode(objectNode)) return null;\n return objectNode;\n}\n\nexport function isMemberAccessPropertyNameNode(nameNode: SyntaxNode, rules: readonly MemberAccessRule[]): boolean {\n const parent = nameNode.parent;\n if (!parent) return false;\n\n for (const rule of rules) {\n if (parent.type !== rule.parentType) continue;\n if (fieldNodeMatches(parent.childForFieldName(rule.propertyField), nameNode)) return true;\n }\n\n return false;\n}\n\nexport function propertyNodeFromAccessNode(accessNode: SyntaxNode, rule: MemberAccessRule): SyntaxNode | null {\n const propertyNode = accessNode.childForFieldName(rule.propertyField);\n if (!propertyNode || !MEMBER_NAME_NODE_TYPES.has(propertyNode.type)) return null;\n return propertyNode;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from '../types.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../yield-during-work.js';\nimport { memberAccessRulesForLanguageKey } from './registry.js';\nimport { isMemberAccessPropertyNameNode, objectNodeFromAccessNode } from './shared.js';\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\nfunction tagFromReceiverNode(node: SyntaxNode): SymbolTag {\n return {\n name: node.text,\n role: 'ref',\n kind: 'variable',\n startLine: node.startPosition.row,\n startColumn: node.startPosition.column,\n endLine: node.endPosition.row,\n endColumn: node.endPosition.column,\n };\n}\n\nfunction lookupNameNode(\n nameNodes: Map<string, SyntaxNode>,\n tag: SymbolTag,\n): SyntaxNode | null {\n const key = `${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`;\n if (nameNodes.has(key)) return nameNodes.get(key)!;\n\n for (const node of nameNodes.values()) {\n if (\n node.text === tag.name &&\n node.startPosition.row === tag.startLine &&\n node.startPosition.column === tag.startColumn\n ) {\n return node;\n }\n }\n return null;\n}\n\n/** Drop member-access property/call targets \u2014 only the receiver object should be navigable. */\nexport function filterMemberAccessPropertyTags(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n languageKey: string | null,\n): SymbolTag[] {\n const rules = memberAccessRulesForLanguageKey(languageKey);\n if (rules.length === 0) return tags;\n\n return tags.filter((tag) => {\n if (tag.role !== 'ref') return true;\n const nameNode = lookupNameNode(nameNodes, tag);\n if (!nameNode) return true;\n return !isMemberAccessPropertyNameNode(nameNode, rules);\n });\n}\n\n/** Tag the object/receiver identifier in member-access expressions when missing from queries. */\nexport async function augmentMemberReceiverTags(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n root: SyntaxNode,\n languageKey: string | null,\n): Promise<SymbolTag[]> {\n const rules = memberAccessRulesForLanguageKey(languageKey);\n if (rules.length === 0) return tags;\n\n const seen = new Set(tags.map(tagDedupeKey));\n const seenRefPositions = new Set(\n tags.filter((tag) => tag.role === 'ref').map((tag) => `${tag.startLine}:${tag.startColumn}:${tag.name}`),\n );\n const out = [...tags];\n const state = createCodeNavYieldState();\n\n for (const rule of rules) {\n for (const accessNode of root.descendantsOfType(rule.parentType)) {\n await yieldDuringCodeNavWork(state);\n const receiverNode = objectNodeFromAccessNode(accessNode, rule);\n if (!receiverNode) continue;\n\n const refPositionKey = `${receiverNode.startPosition.row}:${receiverNode.startPosition.column}:${receiverNode.text}`;\n if (seenRefPositions.has(refPositionKey)) continue;\n\n const tag = tagFromReceiverNode(receiverNode);\n const key = tagDedupeKey(tag);\n if (seen.has(key)) continue;\n\n seen.add(key);\n seenRefPositions.add(refPositionKey);\n out.push(tag);\n nameNodes.set(`${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`, receiverNode);\n }\n }\n\n return out;\n}\n", "import { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nfunction repoNodeModulesDir(fromDir: string): string {\n return join(fromDir, '..', '..', '..', 'node_modules');\n}\n\nfunction firstDirWithWebTreeSitterWasm(candidates: string[]): string | null {\n for (const dir of candidates) {\n if (existsSync(join(dir, 'web-tree-sitter.wasm'))) return dir;\n }\n return null;\n}\n\n/** Directory containing copied `web-tree-sitter.wasm` and language `.wasm` / `tags.scm` assets. */\nexport function getTreeSitterAssetsDir(): string {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n const fromModule = firstDirWithWebTreeSitterWasm([\n join(moduleDir, 'tree-sitter'),\n join(moduleDir, '..', 'tree-sitter'),\n join(moduleDir, '..', '..', 'dist', 'tree-sitter'),\n ]);\n if (fromModule) return fromModule;\n\n const fromNodeModules = firstDirWithWebTreeSitterWasm([join(repoNodeModulesDir(moduleDir), 'web-tree-sitter')]);\n if (fromNodeModules) return fromNodeModules;\n\n throw new Error(\n 'Missing web-tree-sitter.wasm. Run `pnpm build` in packages/cli to copy tree-sitter assets into dist/tree-sitter.',\n );\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Parser, Language, Query, LANGUAGE_VERSION, MIN_COMPATIBLE_VERSION } from 'web-tree-sitter';\nimport { getTreeSitterAssetsDir } from '../tree-sitter-assets-dir.js';\nimport { getLanguageSpec } from '../language-registry.js';\n\nexport type LoadedLanguage = {\n language: Language;\n query: Query;\n};\n\nlet initPromise: Promise<void> | null = null;\nconst loadedByKey = new Map<string, LoadedLanguage>();\nconst failedLanguageKeys = new Set<string>();\nlet runtimeChain: Promise<unknown> = Promise.resolve();\n\nexport function withTreeSitterRuntimeLock<T>(fn: () => T | Promise<T>): Promise<T> {\n const next = runtimeChain.then(() => Promise.resolve(fn()));\n runtimeChain = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n}\n\nexport async function ensureParserInit(): Promise<void> {\n if (!initPromise) {\n const assetsDir = getTreeSitterAssetsDir();\n initPromise = Parser.init({\n locateFile: (scriptName: string) => join(assetsDir, scriptName),\n }).catch((e) => {\n initPromise = null;\n throw e;\n });\n }\n await initPromise;\n}\n\nfunction resolveWasmPath(assetsDir: string, wasmFile: string): string {\n const candidates = [\n join(assetsDir, wasmFile),\n join(assetsDir, '..', '..', 'dist', 'tree-sitter', wasmFile),\n join(assetsDir, '..', '..', '..', 'node_modules', wasmFile.replace('.wasm', ''), wasmFile),\n ];\n const hit = candidates.find((p) => existsSync(p));\n if (!hit) throw new Error(`Missing tree-sitter wasm: ${wasmFile}`);\n return hit;\n}\n\nconst CODE_NAV_QUERIES_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', 'queries');\n\nfunction resolveTagsPath(assetsDir: string, tagsQueryFile: string): string {\n const pkgName = tagsQueryFile.split('/')[0] ?? '';\n const candidates = [\n join(CODE_NAV_QUERIES_ROOT, tagsQueryFile),\n join(assetsDir, tagsQueryFile),\n join(assetsDir, '..', '..', 'dist', 'tree-sitter', tagsQueryFile),\n join(assetsDir, '..', '..', '..', 'node_modules', pkgName, 'queries', 'tags.scm'),\n ];\n const hit = candidates.find((p) => existsSync(p));\n if (!hit) throw new Error(`Missing tags query: ${tagsQueryFile}`);\n return hit;\n}\n\nexport async function loadLanguage(languageKey: string): Promise<LoadedLanguage | null> {\n const spec = getLanguageSpec(languageKey);\n if (!spec) return null;\n if (failedLanguageKeys.has(languageKey)) return null;\n const cached = loadedByKey.get(languageKey);\n if (cached) return cached;\n await ensureParserInit();\n const assetsDir = getTreeSitterAssetsDir();\n const language = await Language.load(resolveWasmPath(assetsDir, spec.wasmFile));\n const abiVersion = language.abiVersion;\n if (abiVersion < MIN_COMPATIBLE_VERSION || abiVersion > LANGUAGE_VERSION) {\n failedLanguageKeys.add(languageKey);\n throw new Error(\n `Incompatible tree-sitter ABI for ${languageKey}: grammar=${abiVersion}, runtime=${MIN_COMPATIBLE_VERSION}-${LANGUAGE_VERSION}`,\n );\n }\n const tagsSource = readFileSync(resolveTagsPath(assetsDir, spec.tagsQueryFile), 'utf8');\n const query = new Query(language, tagsSource);\n const loaded = { language, query };\n loadedByKey.set(languageKey, loaded);\n return loaded;\n}\n", "import { Parser, type SyntaxNode } from 'web-tree-sitter';\nimport {\n assertBackgroundIndexingAllowed,\n yieldForBridgeInteractivePriority,\n} from '../../files/browser/in-flight.js';\nimport { isSymbolIndexDeferredError } from '../symbol-index/deferred-indexing.js';\nimport { getLanguageKeyForFilePath } from '../language-registry.js';\nimport { loadLanguage, withTreeSitterRuntimeLock, type LoadedLanguage } from './tree-sitter-runtime.js';\n\nexport type ParsedSourceRoot = {\n root: SyntaxNode;\n loaded: LoadedLanguage;\n cleanup: () => void;\n};\n\nexport async function parseSourceRoot(filePath: string, source: string): Promise<ParsedSourceRoot | null> {\n const languageKey = getLanguageKeyForFilePath(filePath);\n if (!languageKey) return null;\n\n return withTreeSitterRuntimeLock(async () => {\n await yieldForBridgeInteractivePriority();\n let loaded: LoadedLanguage | null;\n try {\n loaded = await loadLanguage(languageKey);\n } catch {\n return null;\n }\n if (!loaded) return null;\n\n const parser = new Parser();\n parser.setLanguage(loaded.language);\n let tree: ReturnType<Parser['parse']> = null;\n try {\n await yieldForBridgeInteractivePriority();\n assertBackgroundIndexingAllowed();\n tree = parser.parse(source);\n assertBackgroundIndexingAllowed();\n await yieldForBridgeInteractivePriority();\n if (!tree) return null;\n return {\n root: tree.rootNode,\n loaded,\n cleanup: () => {\n tree?.delete();\n parser.delete();\n },\n };\n } catch (err) {\n tree?.delete();\n parser.delete();\n if (isSymbolIndexDeferredError(err)) throw err;\n return null;\n }\n });\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport { assertBackgroundIndexingAllowed, yieldForBridgeInteractivePriority } from '../../files/browser/in-flight.js';\nimport type { LoadedLanguage } from './tree-sitter-runtime.js';\n\n/** Run a tree-sitter tags query, yielding before the blocking native work. */\nexport async function runTagsQuery(loaded: LoadedLanguage, root: SyntaxNode) {\n await yieldForBridgeInteractivePriority();\n assertBackgroundIndexingAllowed();\n const matches = loaded.query.matches(root);\n assertBackgroundIndexingAllowed();\n await yieldForBridgeInteractivePriority();\n return matches;\n}\n", "import type { QueryMatch, SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from '../types.js';\n\nfunction parseCaptureRole(captureName: string): { role: 'def' | 'ref'; kind: string } | null {\n if (captureName === 'name') return null;\n const dot = captureName.indexOf('.');\n if (dot < 0) return null;\n const prefix = captureName.slice(0, dot);\n const kind = captureName.slice(dot + 1);\n if (prefix === 'definition') return { role: 'def', kind };\n if (prefix === 'reference') return { role: 'ref', kind };\n return null;\n}\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\nexport function tagsFromMatches(matches: QueryMatch[]): { tags: SymbolTag[]; nameNodes: Map<string, SyntaxNode> } {\n const tags: SymbolTag[] = [];\n const nameNodes = new Map<string, SyntaxNode>();\n const seen = new Set<string>();\n for (const match of matches) {\n let name: string | null = null;\n let nameNode: QueryMatch['captures'][number]['node'] | null = null;\n const roleNodes: Array<{ role: 'def' | 'ref'; kind: string; node: QueryMatch['captures'][number]['node'] }> = [];\n for (const capture of match.captures) {\n if (capture.name === 'name') {\n name = capture.node.text;\n nameNode = capture.node;\n continue;\n }\n const parsed = parseCaptureRole(capture.name);\n if (parsed) roleNodes.push({ ...parsed, node: capture.node });\n }\n if (!name || !nameNode || roleNodes.length === 0) continue;\n for (const roleNode of roleNodes) {\n const tag: SymbolTag = {\n name,\n role: roleNode.role,\n kind: roleNode.kind,\n startLine: nameNode.startPosition.row,\n startColumn: nameNode.startPosition.column,\n endLine: nameNode.endPosition.row,\n endColumn: nameNode.endPosition.column,\n };\n const key = tagDedupeKey(tag);\n if (seen.has(key)) continue;\n seen.add(key);\n tags.push(tag);\n nameNodes.set(`${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`, nameNode);\n }\n }\n return { tags, nameNodes };\n}\n", "import type { QueryMatch, SyntaxNode } from 'web-tree-sitter';\nimport type { CodeNavYieldState } from '../yield-during-work.js';\nimport { yieldDuringCodeNavWork } from '../yield-during-work.js';\nimport type { SymbolTag } from '../types.js';\nimport { tagsFromMatches } from './tags-from-matches.js';\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\n/** Process one match at a time so tag extraction can yield to the event loop. */\nexport async function tagsFromMatchesAsync(\n matches: QueryMatch[],\n state: CodeNavYieldState,\n): Promise<{ tags: SymbolTag[]; nameNodes: Map<string, SyntaxNode> }> {\n const tags: SymbolTag[] = [];\n const nameNodes = new Map<string, SyntaxNode>();\n const seen = new Set<string>();\n\n for (const match of matches) {\n await yieldDuringCodeNavWork(state);\n const partial = tagsFromMatches([match]);\n for (const tag of partial.tags) {\n const key = tagDedupeKey(tag);\n if (seen.has(key)) continue;\n seen.add(key);\n tags.push(tag);\n }\n for (const [key, node] of partial.nameNodes) nameNodes.set(key, node);\n }\n\n return { tags, nameNodes };\n}\n", "import { getLanguageKeyForFilePath } from '../language-registry.js';\nimport { augmentFunctionTypeParamReferenceTags } from '../augment-function-type-param-references.js';\nimport { augmentTypeReferenceTags } from '../augment-type-reference-tags.js';\nimport { enrichTagsWithEnclosingScope } from '../enrich-tag-scope.js';\nimport { filterMemberAccessPropertyTags, augmentMemberReceiverTags } from '../member-access/index.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../yield-during-work.js';\nimport { yieldForBridgeInteractivePriority } from '../../files/browser/in-flight.js';\nimport { isSymbolIndexDeferredError } from '../symbol-index/deferred-indexing.js';\nimport type { SymbolTag } from '../types.js';\nimport { parseSourceRoot } from './parse-source-root.js';\nimport { runTagsQuery } from './run-tags-query.js';\nimport { tagsFromMatchesAsync } from './tags-from-matches-async.js';\n\nexport async function extractTagsFromSource(filePath: string, source: string): Promise<SymbolTag[]> {\n const languageKey = getLanguageKeyForFilePath(filePath);\n await yieldForBridgeInteractivePriority();\n const parsed = await parseSourceRoot(filePath, source);\n if (!parsed) return [];\n try {\n const yieldState = createCodeNavYieldState();\n const matches = await runTagsQuery(parsed.loaded, parsed.root);\n const { tags, nameNodes } = await tagsFromMatchesAsync(matches, yieldState);\n await yieldDuringCodeNavWork(yieldState);\n const filtered = filterMemberAccessPropertyTags(tags, nameNodes, languageKey);\n const withTypes = await augmentTypeReferenceTags(filtered, nameNodes, parsed.root);\n await yieldDuringCodeNavWork(yieldState);\n const withFunctionTypeParamRefs = await augmentFunctionTypeParamReferenceTags(withTypes, nameNodes, parsed.root);\n await yieldDuringCodeNavWork(yieldState);\n const withReceivers = await augmentMemberReceiverTags(withFunctionTypeParamRefs, nameNodes, parsed.root, languageKey);\n await yieldDuringCodeNavWork(yieldState);\n return await enrichTagsWithEnclosingScope(withReceivers, nameNodes);\n } catch (err) {\n if (isSymbolIndexDeferredError(err)) throw err;\n return [];\n } finally {\n parsed.cleanup();\n }\n}\n", "export { extractTagsFromSource } from './parser/extract-tags.js';\nexport { parseSourceRoot, type ParsedSourceRoot } from './parser/parse-source-root.js';\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport { resolveImportSourcePath } from '../../resolve-module-import-path.js';\nimport type { SymbolImportBinding, SymbolImportKind } from '../../types.js';\n\nexport function pushBinding(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n moduleSpecifier: string,\n localName: string,\n sourceName: string,\n importKind: SymbolImportKind,\n nameNode: SyntaxNode,\n): void {\n if (!localName) return;\n out.push({\n localName,\n sourceName,\n moduleSpecifier,\n sourceFilePath: resolveImportSourcePath(filePath, moduleSpecifier, workspaceFiles),\n importKind,\n startLine: nameNode.startPosition.row,\n startColumn: nameNode.startPosition.column,\n });\n}\n\nexport function stripQuotes(text: string): string {\n const trimmed = text.trim();\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nexport function stringLiteralText(node: SyntaxNode): string {\n const fragment = node.descendantsOfType('string_fragment')[0];\n return stripQuotes(fragment?.text ?? node.text);\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nexport function extractCIncludeBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('preproc_include')) {\n const pathNode = node.childForFieldName('path');\n if (!pathNode) continue;\n const includePath = stringLiteralText(pathNode);\n const localName = includePath.split('/').filter(Boolean).at(-1)?.replace(/\\.(h|hpp)$/, '') ?? includePath;\n pushBinding(out, filePath, workspaceFiles, includePath, localName, localName, 'default', pathNode);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { extractCIncludeBindings } from './c.js';\n\nexport function extractCppImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n return extractCIncludeBindings(root, filePath, workspaceFiles);\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding, SymbolImportKind } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nfunction importKindForSpecifier(specifier: SyntaxNode, statementKind: SymbolImportKind): SymbolImportKind {\n if (specifier.children.some((child) => child.type === 'type')) return 'type';\n return statementKind;\n}\n\nfunction collectFromImportSpecifier(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n moduleSpecifier: string,\n importKind: SymbolImportKind,\n specifier: SyntaxNode,\n): void {\n const nameNode = specifier.childForFieldName('name');\n const aliasNode = specifier.childForFieldName('alias');\n if (!nameNode) return;\n const sourceName = nameNode.text;\n const localName = aliasNode?.text ?? sourceName;\n const effectiveKind = importKindForSpecifier(specifier, importKind);\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, localName, sourceName, effectiveKind, aliasNode ?? nameNode);\n}\n\nfunction collectFromImportClause(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n moduleSpecifier: string,\n importKind: SymbolImportKind,\n clause: SyntaxNode,\n): void {\n const defaultName = clause.childForFieldName('name');\n if (defaultName) {\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, defaultName.text, defaultName.text, 'default', defaultName);\n }\n\n for (const child of clause.children) {\n if (child.type === 'named_imports') {\n for (const spec of child.children) {\n if (spec.type === 'import_specifier') {\n collectFromImportSpecifier(out, filePath, workspaceFiles, moduleSpecifier, importKind, spec);\n }\n }\n }\n if (child.type === 'import_specifier') {\n collectFromImportSpecifier(out, filePath, workspaceFiles, moduleSpecifier, importKind, child);\n }\n if (child.type === 'namespace_import') {\n const alias = child.childForFieldName('name') ?? child.namedChildren.find((n) => n.type === 'identifier');\n if (alias) {\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, alias.text, alias.text, 'namespace', alias);\n }\n }\n }\n}\n\nfunction moduleSpecifierFromImport(node: SyntaxNode): string | null {\n const source = node.childForFieldName('source');\n if (!source) return null;\n return stringLiteralText(source);\n}\n\nexport function collectFromImportStatement(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n const moduleSpecifier = moduleSpecifierFromImport(node);\n if (!moduleSpecifier) return;\n\n const isTypeImport = node.children.some((child) => child.type === 'type');\n const importKind: SymbolImportKind = isTypeImport ? 'type' : 'named';\n\n const clause = node.children.find((child) => child.type === 'import_clause');\n if (clause) {\n collectFromImportClause(out, filePath, workspaceFiles, moduleSpecifier, importKind, clause);\n }\n}\n\nexport function extractEcmaScriptImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('import_statement')) {\n collectFromImportStatement(out, filePath, workspaceFiles, node);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding, SymbolImportKind } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nfunction exportKindForSpecifier(specifier: SyntaxNode, statementKind: SymbolImportKind): SymbolImportKind {\n if (specifier.children.some((child) => child.type === 'type')) return 'type';\n return statementKind;\n}\n\nfunction collectFromExportSpecifier(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n moduleSpecifier: string,\n exportKind: SymbolImportKind,\n specifier: SyntaxNode,\n): void {\n const nameNode = specifier.childForFieldName('name');\n const aliasNode = specifier.childForFieldName('alias');\n if (!nameNode) return;\n const sourceName = nameNode.text;\n const localName = aliasNode?.text ?? sourceName;\n const effectiveKind = exportKindForSpecifier(specifier, exportKind);\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, localName, sourceName, effectiveKind, aliasNode ?? nameNode);\n}\n\nfunction moduleSpecifierFromExport(node: SyntaxNode): string | null {\n const source = node.childForFieldName('source');\n if (!source) return null;\n return stringLiteralText(source);\n}\n\nfunction isStarReexport(node: SyntaxNode): boolean {\n if (!moduleSpecifierFromExport(node)) return false;\n if (node.descendantsOfType('export_specifier').length > 0) return false;\n if (node.descendantsOfType('namespace_export').length > 0) return false;\n if (node.childForFieldName('declaration')) return false;\n return node.text.includes('*');\n}\n\n/** Collect re-export bindings from `export \u2026 from 'module'` statements. */\nexport function extractEcmaScriptReexportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('export_statement')) {\n const moduleSpecifier = moduleSpecifierFromExport(node);\n if (!moduleSpecifier) continue;\n\n const isTypeExport = node.children.some((child) => child.type === 'type');\n const exportKind: SymbolImportKind = isTypeExport ? 'type' : 'reexport';\n\n if (isStarReexport(node)) {\n const anchor = node.childForFieldName('source') ?? node;\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, '*', '*', 'star', anchor);\n continue;\n }\n\n for (const spec of node.descendantsOfType('export_specifier')) {\n collectFromExportSpecifier(out, filePath, workspaceFiles, moduleSpecifier, exportKind, spec);\n }\n\n for (const ns of node.descendantsOfType('namespace_export')) {\n const alias = ns.childForFieldName('name') ?? ns.namedChildren.find((n) => n.type === 'identifier');\n if (alias) {\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, alias.text, alias.text, 'namespace', alias);\n }\n }\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { extractEcmaScriptImportBindings } from './ecma-script-imports.js';\nimport { extractEcmaScriptReexportBindings } from './ecma-script-exports.js';\n\nexport { extractEcmaScriptImportBindings } from './ecma-script-imports.js';\n\n/** Extract import and re-export bindings for ECMAScript modules. */\nexport function extractEcmaScriptBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const imports = extractEcmaScriptImportBindings(root, filePath, workspaceFiles);\n const reexports = extractEcmaScriptReexportBindings(root, filePath, workspaceFiles);\n return [...imports, ...reexports];\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nfunction collectImportSpec(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n spec: SyntaxNode,\n): void {\n const pathNode = spec.childForFieldName('path');\n if (!pathNode) return;\n const modulePath = stringLiteralText(pathNode);\n\n const nameNode = spec.childForFieldName('name');\n if (nameNode) {\n pushBinding(out, filePath, workspaceFiles, modulePath, nameNode.text, nameNode.text, 'namespace', nameNode);\n return;\n }\n\n const localName = modulePath.split('/').filter(Boolean).at(-1) ?? modulePath;\n pushBinding(out, filePath, workspaceFiles, modulePath, localName, localName, 'namespace', pathNode);\n}\n\nexport function extractGoImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('import_declaration')) {\n for (const spec of node.descendantsOfType('import_spec')) {\n collectImportSpec(out, filePath, workspaceFiles, spec);\n }\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding } from './shared.js';\n\nfunction localNameFromImport(nameNode: SyntaxNode): string {\n return nameNode.text.split('.').at(-1) ?? nameNode.text;\n}\n\nfunction collectImportDeclaration(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n for (const child of node.namedChildren) {\n if (child.type === 'scoped_identifier' || child.type === 'identifier') {\n const sourceName = child.text;\n const localName = localNameFromImport(child);\n pushBinding(out, filePath, workspaceFiles, sourceName, localName, sourceName, 'named', child);\n }\n }\n}\n\nexport function extractJavaImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('import_declaration')) {\n collectImportDeclaration(out, filePath, workspaceFiles, node);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding } from './shared.js';\n\nfunction dottedNameText(node: SyntaxNode): string {\n return node.text.replace(/\\s+/g, '');\n}\n\nfunction collectImportStatement(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return;\n const moduleName = dottedNameText(nameNode);\n const localName = moduleName.split('.').at(-1) ?? moduleName;\n pushBinding(out, filePath, workspaceFiles, moduleName, localName, localName, 'namespace', nameNode);\n}\n\nfunction collectImportFromStatement(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n const moduleNode = node.childForFieldName('module_name');\n const moduleName = moduleNode ? dottedNameText(moduleNode) : '';\n for (const child of node.namedChildren) {\n if (child.type !== 'dotted_name' && child.type !== 'aliased_import') continue;\n if (child === moduleNode) continue;\n\n if (child.type === 'dotted_name') {\n const sourceName = dottedNameText(child);\n const localName = sourceName.split('.').at(-1) ?? sourceName;\n pushBinding(out, filePath, workspaceFiles, moduleName, localName, sourceName, 'named', child);\n continue;\n }\n\n const nameNode = child.childForFieldName('name');\n const aliasNode = child.childForFieldName('alias');\n if (!nameNode) continue;\n const sourceName = dottedNameText(nameNode);\n const localName = aliasNode ? aliasNode.text : sourceName.split('.').at(-1) ?? sourceName;\n pushBinding(out, filePath, workspaceFiles, moduleName, localName, sourceName, 'named', aliasNode ?? nameNode);\n }\n}\n\nexport function extractPythonImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('import_statement')) {\n collectImportStatement(out, filePath, workspaceFiles, node);\n }\n for (const node of root.descendantsOfType('import_from_statement')) {\n collectImportFromStatement(out, filePath, workspaceFiles, node);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nfunction collectRequireCall(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n const methodNode = node.childForFieldName('method');\n if (!methodNode || (methodNode.text !== 'require' && methodNode.text !== 'require_relative')) return;\n\n const args = node.childForFieldName('arguments');\n const stringNode = args?.descendantsOfType('string')[0] ?? args?.descendantsOfType('string_content')[0];\n if (!stringNode) return;\n\n const modulePath = stringLiteralText(stringNode);\n const localName = modulePath.split('/').filter(Boolean).at(-1)?.replace(/\\.rb$/, '') ?? modulePath;\n pushBinding(out, filePath, workspaceFiles, modulePath, localName, localName, 'default', stringNode);\n}\n\nexport function extractRubyImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('call')) {\n collectRequireCall(out, filePath, workspaceFiles, node);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding } from './shared.js';\n\nfunction identifierFromUseTree(node: SyntaxNode): SyntaxNode | null {\n if (node.type === 'identifier' || node.type === 'type_identifier') return node;\n const nameNode = node.childForFieldName('name');\n if (nameNode) return nameNode;\n for (const child of node.namedChildren) {\n const hit = identifierFromUseTree(child);\n if (hit) return hit;\n }\n return null;\n}\n\nfunction useDeclarationIsPublic(node: SyntaxNode): boolean {\n return node.children.some((child) => child.type === 'visibility_modifier' && child.text === 'pub');\n}\n\nfunction collectUseTree(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n pathPrefix: string,\n node: SyntaxNode,\n importKind: SymbolImportBinding['importKind'] = 'named',\n): void {\n if (node.type === 'use_as_clause') {\n const pathNode = node.childForFieldName('path');\n const aliasNode = node.childForFieldName('alias');\n if (!pathNode || !aliasNode) return;\n const sourceName = identifierFromUseTree(pathNode)?.text ?? pathNode.text.split('::').at(-1) ?? '';\n pushBinding(out, filePath, workspaceFiles, pathPrefix, aliasNode.text, sourceName, importKind, aliasNode);\n return;\n }\n\n if (node.type === 'identifier' || node.type === 'type_identifier') {\n const sourceName = node.text;\n pushBinding(out, filePath, workspaceFiles, pathPrefix, sourceName, sourceName, importKind, node);\n return;\n }\n\n if (node.type === 'scoped_identifier') {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return;\n const sourceName = nameNode.text;\n pushBinding(out, filePath, workspaceFiles, pathPrefix, sourceName, sourceName, importKind, nameNode);\n return;\n }\n\n if (node.type === 'use_list') {\n for (const child of node.namedChildren) {\n collectUseTree(out, filePath, workspaceFiles, pathPrefix, child, importKind);\n }\n return;\n }\n\n if (node.type === 'scoped_use_list') {\n const pathNode = node.childForFieldName('path');\n const nextPrefix = pathNode ? `${pathPrefix}${pathNode.text}::` : pathPrefix;\n for (const child of node.namedChildren) {\n if (child === pathNode) continue;\n collectUseTree(out, filePath, workspaceFiles, nextPrefix, child, importKind);\n }\n return;\n }\n\n for (const child of node.namedChildren) {\n collectUseTree(out, filePath, workspaceFiles, pathPrefix, child, importKind);\n }\n}\n\nexport function extractRustImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('use_declaration')) {\n const argument = node.childForFieldName('argument');\n if (!argument) continue;\n const importKind = useDeclarationIsPublic(node) ? 'reexport' : 'named';\n collectUseTree(out, filePath, workspaceFiles, '', argument, importKind);\n }\n return out;\n}\n", "import { getLanguageKeyForFilePath } from '../../language-registry.js';\nimport { parseSourceRoot } from '../../parser-runtime.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../../yield-during-work.js';\nimport { yieldToEventLoop } from '../../../runtime/yield-to-event-loop.js';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { extractCIncludeBindings } from './c.js';\nimport { extractCppImportBindings } from './cpp.js';\nimport { extractEcmaScriptBindings } from './ecma-script.js';\nimport { extractGoImportBindings } from './go.js';\nimport { extractJavaImportBindings } from './java.js';\nimport { extractPythonImportBindings } from './python.js';\nimport { extractRubyImportBindings } from './ruby.js';\nimport { extractRustImportBindings } from './rust.js';\n\ntype ImportExtractor = (\n root: import('web-tree-sitter').SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n) => SymbolImportBinding[];\n\nconst EXTRACTORS_BY_LANGUAGE_KEY: Readonly<Record<string, ImportExtractor>> = {\n javascript: extractEcmaScriptBindings,\n typescript: extractEcmaScriptBindings,\n tsx: extractEcmaScriptBindings,\n python: extractPythonImportBindings,\n go: extractGoImportBindings,\n rust: extractRustImportBindings,\n ruby: extractRubyImportBindings,\n java: extractJavaImportBindings,\n c: extractCIncludeBindings,\n cpp: extractCppImportBindings,\n};\n\nexport async function extractImportBindingsFromSource(\n filePath: string,\n source: string,\n workspaceFiles: ReadonlySet<string>,\n): Promise<SymbolImportBinding[]> {\n const languageKey = getLanguageKeyForFilePath(filePath);\n if (!languageKey) return [];\n\n const extract = EXTRACTORS_BY_LANGUAGE_KEY[languageKey];\n if (!extract) return [];\n\n const parsed = await parseSourceRoot(filePath, source);\n if (!parsed) return [];\n try {\n await yieldToEventLoop();\n const yieldState = createCodeNavYieldState();\n await yieldDuringCodeNavWork(yieldState);\n const bindings = extract(parsed.root, filePath, workspaceFiles);\n await yieldDuringCodeNavWork(yieldState);\n return bindings;\n } finally {\n parsed.cleanup();\n }\n}\n", "import fs from 'node:fs';\nimport { isMainThread } from 'node:worker_threads';\nimport { assertBackgroundIndexingAllowed } from '../../../files/browser/in-flight.js';\nimport { isCliImmediateShutdownRequested } from '../../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../../../sqlite/code-nav-cache/database.js';\nimport { isSymbolIndexDeferredError } from '../deferred-indexing.js';\n\nexport const MAX_INDEX_FILE_BYTES = 512 * 1024;\n\nexport function assertSymbolIndexNotShutdown(): void {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n}\n\nfunction readIndexSourceFileSync(absPath: string): string | null {\n assertSymbolIndexNotShutdown();\n assertBackgroundIndexingAllowed();\n const stat = fs.statSync(absPath);\n if (!stat.isFile() || stat.size > MAX_INDEX_FILE_BYTES) return null;\n assertBackgroundIndexingAllowed();\n return fs.readFileSync(absPath, 'utf8');\n}\n\nexport async function readIndexSourceFile(absPath: string): Promise<string | null> {\n try {\n if (!isMainThread) {\n return readIndexSourceFileSync(absPath);\n }\n assertSymbolIndexNotShutdown();\n assertBackgroundIndexingAllowed();\n const stat = await fs.promises.stat(absPath);\n if (!stat.isFile() || stat.size > MAX_INDEX_FILE_BYTES) return null;\n assertBackgroundIndexingAllowed();\n return await fs.promises.readFile(absPath, 'utf8');\n } catch (err) {\n if (isSymbolIndexDeferredError(err)) throw err;\n return null;\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { getSymbolIndexParentContext } from '../sqlite/symbol-index-sqlite.js';\nimport { listEffectiveIndexedFilePaths } from '../storage/symbol-parent-file-map.js';\n\nexport function listWorkspaceFiles(db: Database, workspacePath: string, includePath: string): Set<string> {\n const files = new Set<string>([includePath.replace(/\\\\/g, '/')]);\n\n const normalizedWorkspace = normalizeResolvedPath(workspacePath);\n const parentRow = db.get('SELECT id FROM file_index_parent_path WHERE path = ?', [normalizedWorkspace]) as\n | { id: number | bigint }\n | null;\n if (parentRow != null) {\n const fromIndex = db.all('SELECT path FROM file_index_child_path WHERE parent_id = ?', [\n Number(parentRow.id),\n ]) as Array<{ path: string }>;\n for (const row of fromIndex) files.add(row.path.replace(/\\\\/g, '/'));\n }\n\n const ctx = getSymbolIndexParentContext(db, normalizedWorkspace);\n if (ctx != null) {\n for (const filePath of listEffectiveIndexedFilePaths(db, ctx)) {\n files.add(filePath.replace(/\\\\/g, '/'));\n }\n }\n\n return files;\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { isMainThread } from 'node:worker_threads';\nimport {\n assertBackgroundIndexingAllowed,\n yieldForBridgeInteractivePriority,\n} from '../../../files/browser/in-flight.js';\nimport { isSymbolIndexDeferredError } from '../deferred-indexing.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { enrichTagsWithModulePathsAsync } from '../../enrich-tag-module-paths-async.js';\nimport { isPathGitIgnored } from '../../gitignore-filter.js';\nimport { isCodeNavSupportedPath } from '../../language-registry.js';\nimport { extractTagsFromSource } from '../../parser-runtime.js';\nimport { createCodeNavYieldState } from '../../yield-during-work.js';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport { extractImportBindingsFromSource } from '../imports/index.js';\nimport { MAX_INDEX_FILE_BYTES } from './read-index-source.js';\nimport { listWorkspaceFiles } from './workspace-files.js';\n\nexport type FileSymbolData = {\n source: string | null;\n tags: SymbolTag[];\n imports: SymbolImportBinding[];\n};\n\nexport async function extractFileSymbolData(\n resolved: string,\n relPath: string,\n workspaceFilesOverride?: ReadonlySet<string>,\n): Promise<FileSymbolData> {\n await yieldForBridgeInteractivePriority();\n const absPath = path.join(resolved, relPath);\n\n let tags: SymbolTag[] = [];\n let source: string | null = null;\n if (isCodeNavSupportedPath(relPath) && !(await isPathGitIgnored(resolved, relPath))) {\n try {\n assertBackgroundIndexingAllowed();\n let fileSource: string | null = null;\n if (isMainThread) {\n const stat = await fs.promises.stat(absPath);\n if (stat.isFile() && stat.size <= MAX_INDEX_FILE_BYTES) {\n assertBackgroundIndexingAllowed();\n fileSource = await fs.promises.readFile(absPath, 'utf8');\n }\n } else {\n const stat = fs.statSync(absPath);\n if (stat.isFile() && stat.size <= MAX_INDEX_FILE_BYTES) {\n assertBackgroundIndexingAllowed();\n fileSource = fs.readFileSync(absPath, 'utf8');\n }\n }\n source = fileSource;\n if (source != null) {\n await yieldForBridgeInteractivePriority();\n tags = await extractTagsFromSource(relPath, source);\n }\n } catch (err) {\n if (isSymbolIndexDeferredError(err)) throw err;\n tags = [];\n source = null;\n }\n }\n\n await yieldForBridgeInteractivePriority();\n const workspaceFiles =\n workspaceFilesOverride ??\n (await withCodeNavCacheSqlite((db) => listWorkspaceFiles(db, resolved, relPath)));\n const imports =\n source != null ? await extractImportBindingsFromSource(relPath, source, workspaceFiles) : [];\n\n const yieldState = createCodeNavYieldState();\n return {\n source,\n tags: await enrichTagsWithModulePathsAsync(tags, relPath, workspaceFiles, yieldState),\n imports,\n };\n}\n", "import { yieldForBridgeInteractivePriority } from '../../../files/browser/in-flight.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { expandStarReexportForFile } from '../imports/expand-star-reexports.js';\nimport { persistSymbolIndexFileAsync } from '../persistence/persist-single-file.js';\nimport { getSymbolIndexParentContext, upsertSymbolIndexParentPath } from '../sqlite/symbol-index-sqlite.js';\nimport { withSymbolIndexSqliteLock } from '../sqlite/symbol-index-sqlite-lock.js';\nimport type { SymbolIndexFileEntry } from './collect-file-entries.js';\nimport { extractFileSymbolData } from './extract-file-symbol-data.js';\nimport { loadIndexedFileEntry } from './load-indexed-file-entry.js';\n\nexport async function indexOneSymbolFileForBuild(\n resolved: string,\n relPath: string,\n workspaceFiles?: ReadonlySet<string>,\n): Promise<void> {\n await yieldForBridgeInteractivePriority();\n const data = await extractFileSymbolData(resolved, relPath, workspaceFiles);\n let entry: SymbolIndexFileEntry = {\n relPath,\n source: data.source,\n tags: data.tags,\n imports: data.imports,\n };\n\n if (data.imports.some((binding) => binding.importKind === 'star')) {\n await yieldForBridgeInteractivePriority();\n entry = await withCodeNavCacheSqlite((db) => {\n const ctx = getSymbolIndexParentContext(db, resolved);\n if (ctx == null) return entry;\n const resolveEntry = (filePath: string) => loadIndexedFileEntry(db, ctx, filePath);\n return expandStarReexportForFile(entry, resolveEntry);\n });\n entry.source = data.source;\n }\n\n await withSymbolIndexSqliteLock(async () => {\n await yieldForBridgeInteractivePriority();\n await persistSymbolIndexFileAsync(resolved, relPath, entry.source, entry.tags, entry.imports);\n });\n}\n", "export function normalizeSymbolIndexRelPath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { listDirectImportTargetsForFileAsync } from '../query/list-direct-import-targets.js';\nimport { symbolIndexFileIsReadyAsync } from '../lifecycle/symbol-index-file-ready.js';\nimport { upsertSymbolIndexParentPath } from '../sqlite/symbol-index-sqlite.js';\nimport { indexOneSymbolFileForBuild } from './index-one-symbol-file-for-build.js';\nimport { normalizeSymbolIndexRelPath } from './normalize-symbol-index-rel-path.js';\n\nexport { indexOneSymbolFileForBuild } from './index-one-symbol-file-for-build.js';\n\nconst MAX_IMPORT_PREFETCH_DEPTH = 1;\nconst MAX_IMPORT_PREFETCH_COUNT = 8;\n\n/**\n * Index a single file (and a shallow import closure) on demand.\n * Returns true when the requested file is ready for queries.\n */\nexport async function ensureSymbolIndexFileImpl(\n parentPath: string,\n filePath: string,\n opts?: { importDepth?: number },\n): Promise<boolean> {\n const resolved = normalizeResolvedPath(parentPath);\n const relPath = normalizeSymbolIndexRelPath(filePath);\n if (!relPath) return false;\n\n const importDepth = opts?.importDepth ?? 0;\n\n await withCodeNavCacheSqlite((db) => {\n upsertSymbolIndexParentPath(db, resolved);\n });\n\n if (!(await symbolIndexFileIsReadyAsync(resolved, relPath))) {\n await indexOneSymbolFileForBuild(resolved, relPath, undefined);\n }\n\n if (importDepth > 0 && (await symbolIndexFileIsReadyAsync(resolved, relPath))) {\n const targets = (await listDirectImportTargetsForFileAsync(resolved, relPath)).slice(\n 0,\n MAX_IMPORT_PREFETCH_COUNT,\n );\n for (const target of targets) {\n if (!(await symbolIndexFileIsReadyAsync(resolved, target))) {\n await ensureSymbolIndexFileImpl(resolved, target, { importDepth: importDepth - 1 });\n }\n }\n }\n\n return await symbolIndexFileIsReadyAsync(resolved, relPath);\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { runCodeNavCacheWriteTransaction } from '../../../sqlite/code-nav-cache/code-nav-cache-sqlite-transaction.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../../yield-during-work.js';\nimport { createWalkYieldState, walkCodeNavFilesAsync } from '../../walk-code-nav-files.js';\nimport {\n clearSymbolIndexParentDataBatch,\n getSymbolIndexParentContext,\n upsertSymbolIndexParentPath,\n} from '../sqlite/symbol-index-sqlite.js';\nimport { withSymbolIndexSqliteLock } from '../sqlite/symbol-index-sqlite-lock.js';\nimport { indexOneSymbolFileForBuild } from './ensure-symbol-index-file-impl.js';\n\nconst SYMBOL_PARENT_CLEAR_BATCH_SIZE = 256;\n\n/**\n * Stream one file at a time \u2014 workspace paths kept in a string Set only (not full tag arrays).\n */\nexport async function buildSymbolIndexImpl(parentPath: string): Promise<{ fileCount: number; tagCount: number }> {\n const resolved = normalizeResolvedPath(parentPath);\n\n let clearRemaining = true;\n while (clearRemaining) {\n await withSymbolIndexSqliteLock(async () => {\n clearRemaining = await withCodeNavCacheSqlite((db) =>\n runCodeNavCacheWriteTransaction(db, () => {\n upsertSymbolIndexParentPath(db, resolved);\n const ctx = getSymbolIndexParentContext(db, resolved);\n return ctx == null ? false : clearSymbolIndexParentDataBatch(db, ctx, SYMBOL_PARENT_CLEAR_BATCH_SIZE);\n }),\n );\n });\n }\n\n const workspaceFiles = new Set<string>();\n const walkState = createWalkYieldState();\n const yieldState = createCodeNavYieldState();\n\n await walkCodeNavFilesAsync(\n resolved,\n async (relPath) => {\n await yieldDuringCodeNavWork(yieldState);\n workspaceFiles.add(relPath);\n },\n walkState,\n );\n\n let fileCount = 0;\n await walkCodeNavFilesAsync(\n resolved,\n async (relPath) => {\n await yieldDuringCodeNavWork(yieldState);\n await indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles);\n fileCount += 1;\n },\n walkState,\n );\n\n return { fileCount, tagCount: 0 };\n}\n", "export { buildSymbolIndexImpl as buildSymbolIndexInWorkerHost } from './build-symbol-index-impl.js';\n", "export {\n ensureSymbolIndexFileImpl as ensureSymbolIndexFileInWorkerHost,\n indexOneSymbolFileForBuild,\n} from './ensure-symbol-index-file-impl.js';\n", "import path from 'node:path';\n\nexport function normalizeSymbolIndexRelPath(parentPath: string, changedPath: string): string | null {\n const resolvedParent = path.resolve(parentPath);\n const abs = path.isAbsolute(changedPath) ? path.resolve(changedPath) : path.resolve(resolvedParent, changedPath);\n const rel = path.relative(resolvedParent, abs).replace(/\\\\/g, '/');\n if (rel.startsWith('..') || path.isAbsolute(rel)) return null;\n return rel;\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { yieldToEventLoop } from '../../../runtime/yield-to-event-loop.js';\nimport { normalizeSymbolIndexRelPath } from '../lifecycle/normalize-symbol-index-path.js';\nimport {\n persistSymbolIndexFileAsync,\n removeSymbolIndexFileAsync,\n} from '../persistence/persist-single-file.js';\nimport { withSymbolIndexSqliteLock } from '../sqlite/symbol-index-sqlite-lock.js';\nimport { extractFileSymbolData } from './extract-file-symbol-data.js';\n\nexport async function updateSymbolIndexForFileImpl(\n parentPath: string,\n changedPath: string,\n): Promise<void> {\n const relPath = normalizeSymbolIndexRelPath(parentPath, changedPath);\n if (relPath == null) return;\n\n const resolved = normalizeResolvedPath(parentPath);\n const { source, tags, imports } = await extractFileSymbolData(resolved, relPath);\n await yieldToEventLoop();\n\n await withSymbolIndexSqliteLock(async () => {\n await persistSymbolIndexFileAsync(resolved, relPath, source, tags, imports);\n });\n}\n\nexport async function removeSymbolIndexForFileImpl(parentPath: string, changedPath: string): Promise<void> {\n const relPath = normalizeSymbolIndexRelPath(parentPath, changedPath);\n if (relPath == null) return;\n const resolved = normalizeResolvedPath(parentPath);\n await withSymbolIndexSqliteLock(async () => {\n await removeSymbolIndexFileAsync(resolved, relPath);\n });\n}\n\n/** Worker host entry when the caller already has a normalized relative path. */\nexport async function updateSymbolIndexRelPathImpl(parentPath: string, relPath: string): Promise<void> {\n const normalizedRel = relPath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!normalizedRel) return;\n const resolved = normalizeResolvedPath(parentPath);\n const { source, tags, imports } = await extractFileSymbolData(resolved, normalizedRel);\n await yieldToEventLoop();\n await withSymbolIndexSqliteLock(async () => {\n await persistSymbolIndexFileAsync(resolved, normalizedRel, source, tags, imports);\n });\n}\n\n/** Worker host entry when the caller already has a normalized relative path. */\nexport async function removeSymbolIndexRelPathImpl(parentPath: string, relPath: string): Promise<void> {\n const normalizedRel = relPath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!normalizedRel) return;\n const resolved = normalizeResolvedPath(parentPath);\n await withSymbolIndexSqliteLock(async () => {\n await removeSymbolIndexFileAsync(resolved, normalizedRel);\n });\n}\n", "export {\n removeSymbolIndexRelPathImpl as removeSymbolIndexForFileInWorkerHost,\n updateSymbolIndexRelPathImpl as updateSymbolIndexForFileInWorkerHost,\n} from './update-symbol-index-file-impl.js';\n", "import type { SymbolIndexWorkerOutMessage, SymbolIndexWorkerPort } from './protocol.js';\n\nexport function postSafe(port: SymbolIndexWorkerPort, message: SymbolIndexWorkerOutMessage): void {\n try {\n port.postMessage(message);\n } catch {\n /* worker/client may be gone during shutdown */\n }\n}\n", "import { isCliImmediateShutdownRequested } from '../../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../../../sqlite/sqlite-errors.js';\nimport { buildSymbolIndexInWorkerHost } from '../build/build-symbol-index-host.js';\nimport { ensureSymbolIndexFileInWorkerHost } from '../build/ensure-symbol-index-file-host.js';\nimport {\n removeSymbolIndexForFileInWorkerHost,\n updateSymbolIndexForFileInWorkerHost,\n} from '../build/update-symbol-index-file-host.js';\nimport { postSafe } from './post-message.js';\nimport type { SymbolIndexWorkerInMessage, SymbolIndexWorkerPort } from './protocol.js';\n\nimport { isSymbolIndexWorkerShutdownRequested } from './shutdown-state.js';\n\nfunction postWorkerError(port: SymbolIndexWorkerPort, requestId: string, err: unknown): void {\n if (\n isCliImmediateShutdownRequested() ||\n isSymbolIndexWorkerShutdownRequested() ||\n err instanceof CliSqliteInterrupted\n ) {\n postSafe(port, {\n type: 'error',\n requestId,\n message: new CliSqliteInterrupted().message,\n });\n return;\n }\n postSafe(port, {\n type: 'error',\n requestId,\n message: err instanceof Error ? err.message : String(err),\n });\n}\n\nexport async function handleIndexWorkerMessage(\n port: SymbolIndexWorkerPort,\n msg: SymbolIndexWorkerInMessage,\n): Promise<void> {\n switch (msg.type) {\n case 'buildFull': {\n try {\n const result = await buildSymbolIndexInWorkerHost(msg.parentPath);\n postSafe(port, { type: 'buildComplete', requestId: msg.requestId, ...result });\n } catch (err) {\n postWorkerError(port, msg.requestId, err);\n }\n return;\n }\n case 'updateFile': {\n try {\n await updateSymbolIndexForFileInWorkerHost(msg.parentPath, msg.relPath);\n postSafe(port, { type: 'updateComplete', requestId: msg.requestId });\n } catch (err) {\n postWorkerError(port, msg.requestId, err);\n }\n return;\n }\n case 'removeFile': {\n try {\n await removeSymbolIndexForFileInWorkerHost(msg.parentPath, msg.relPath);\n postSafe(port, { type: 'removeComplete', requestId: msg.requestId });\n } catch (err) {\n postWorkerError(port, msg.requestId, err);\n }\n return;\n }\n case 'ensureFile': {\n try {\n const ready = await ensureSymbolIndexFileInWorkerHost(msg.parentPath, msg.filePath, {\n importDepth: msg.importDepth,\n });\n postSafe(port, { type: 'ensureComplete', requestId: msg.requestId, ready });\n } catch (err) {\n postWorkerError(port, msg.requestId, err);\n }\n return;\n }\n default:\n return;\n }\n}\n", "import type { PendingSymbolIndexTask } from './task-queue-types.js';\n\nfunction higherPriority(a: PendingSymbolIndexTask, b: PendingSymbolIndexTask): boolean {\n return a.priority > b.priority;\n}\n\nexport class SymbolIndexTaskPriorityHeap {\n private readonly heap: PendingSymbolIndexTask[] = [];\n\n clear(): void {\n this.heap.length = 0;\n }\n\n push(task: PendingSymbolIndexTask): void {\n this.heap.push(task);\n let i = this.heap.length - 1;\n while (i > 0) {\n const parent = Math.floor((i - 1) / 2);\n if (!higherPriority(this.heap[i]!, this.heap[parent]!)) break;\n this.swap(i, parent);\n i = parent;\n }\n }\n\n pop(): PendingSymbolIndexTask | undefined {\n if (this.heap.length === 0) return undefined;\n const top = this.heap[0]!;\n const last = this.heap.pop()!;\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.sink(0);\n }\n return top;\n }\n\n get size(): number {\n return this.heap.length;\n }\n\n private sink(start: number): void {\n let i = start;\n while (true) {\n const left = i * 2 + 1;\n const right = left + 1;\n let best = i;\n if (left < this.heap.length && higherPriority(this.heap[left]!, this.heap[best]!)) best = left;\n if (right < this.heap.length && higherPriority(this.heap[right]!, this.heap[best]!)) best = right;\n if (best === i) break;\n this.swap(i, best);\n i = best;\n }\n }\n\n private swap(i: number, j: number): void {\n const tmp = this.heap[i]!;\n this.heap[i] = this.heap[j]!;\n this.heap[j] = tmp;\n }\n}\n", "export type PendingSymbolIndexTask = {\n parentPath: string;\n filePath: string;\n priority: number;\n sequence?: number;\n};\n\nexport function symbolIndexTaskKey(parentPath: string, filePath: string): string {\n return `${parentPath}\\0${filePath}`;\n}\n", "import { SymbolIndexTaskPriorityHeap } from './task-priority-heap.js';\nimport { symbolIndexTaskKey, type PendingSymbolIndexTask } from './task-queue-types.js';\n\nexport const pendingSymbolIndexTasks = new Map<string, PendingSymbolIndexTask>();\nexport const symbolIndexTaskHeap = new SymbolIndexTaskPriorityHeap();\nexport const latestActiveSequenceByParent = new Map<string, number>();\nexport let symbolIndexWorkerRunning = false;\n\nexport function setSymbolIndexWorkerRunning(running: boolean): void {\n symbolIndexWorkerRunning = running;\n}\n\nexport function taskMatchesCurrentPending(task: PendingSymbolIndexTask): boolean {\n const current = pendingSymbolIndexTasks.get(symbolIndexTaskKey(task.parentPath, task.filePath));\n return current === task;\n}\n\nexport function pickNextSymbolIndexTask(): PendingSymbolIndexTask | undefined {\n while (symbolIndexTaskHeap.size > 0) {\n const task = symbolIndexTaskHeap.pop();\n if (task == null || !taskMatchesCurrentPending(task)) continue;\n return task;\n }\n return undefined;\n}\n\nexport function addPendingSymbolIndexTask(task: PendingSymbolIndexTask): boolean {\n const key = symbolIndexTaskKey(task.parentPath, task.filePath);\n const existing = pendingSymbolIndexTasks.get(key);\n if (existing != null && existing.priority >= task.priority) return false;\n pendingSymbolIndexTasks.set(key, task);\n symbolIndexTaskHeap.push(task);\n return true;\n}\n\nexport function clearSymbolIndexHeapIfEmpty(): void {\n if (pendingSymbolIndexTasks.size === 0) symbolIndexTaskHeap.clear();\n}\n\n/** @internal Test teardown for worker queue state. */\nexport function resetSymbolIndexTaskQueueForTests(): void {\n pendingSymbolIndexTasks.clear();\n symbolIndexTaskHeap.clear();\n latestActiveSequenceByParent.clear();\n symbolIndexWorkerRunning = false;\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { addPendingSymbolIndexTask, latestActiveSequenceByParent, pendingSymbolIndexTasks, symbolIndexTaskHeap } from './task-queue-store.js';\n\n/** Background warmup and neighbor prefetch sit below interactive code-nav work. */\nexport const SYMBOL_INDEX_BACKGROUND_PRIORITY_MAX = 499_999;\n\nexport function enqueueSymbolIndexTaskInternal(\n parentPath: string,\n filePath: string,\n priority: number,\n sequence?: number,\n): boolean {\n const normalizedParent = normalizeResolvedPath(parentPath);\n const normalizedFile = filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!normalizedFile) return false;\n\n return addPendingSymbolIndexTask({\n parentPath: normalizedParent,\n filePath: normalizedFile,\n priority,\n sequence,\n });\n}\n\nexport function markLatestActiveSymbolIndexTaskInternal(parentPath: string, sequence: number): void {\n const normalizedParent = normalizeResolvedPath(parentPath);\n const existing = latestActiveSequenceByParent.get(normalizedParent);\n if (existing != null && existing >= sequence) return;\n latestActiveSequenceByParent.set(normalizedParent, sequence);\n\n for (const [key, task] of pendingSymbolIndexTasks) {\n if (task.parentPath === normalizedParent && task.sequence != null && task.sequence < sequence) {\n pendingSymbolIndexTasks.delete(key);\n }\n }\n if (pendingSymbolIndexTasks.size === 0) symbolIndexTaskHeap.clear();\n}\n\n/** Drop low-priority queued work when the user starts browsing files. */\nexport function deferBackgroundSymbolIndexTasks(): void {\n if (pendingSymbolIndexTasks.size === 0) return;\n\n for (const [key, task] of pendingSymbolIndexTasks) {\n if (task.priority <= SYMBOL_INDEX_BACKGROUND_PRIORITY_MAX) {\n pendingSymbolIndexTasks.delete(key);\n }\n }\n\n symbolIndexTaskHeap.clear();\n for (const task of pendingSymbolIndexTasks.values()) {\n symbolIndexTaskHeap.push(task);\n }\n}\n\nexport { deferBackgroundSymbolIndexTasks as deferBackgroundSymbolIndexTasksForTests };\n", "import { isSymbolIndexDeferredError } from '../deferred-indexing.js';\nimport { yieldUntilFileBrowserIdle } from '../../../files/browser/in-flight.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../../yield-during-work.js';\nimport { ensureSymbolIndexFileInWorkerHost } from '../build/ensure-symbol-index-file-host.js';\nimport { symbolIndexFileIsReadyAsync } from '../lifecycle/symbol-index-file-ready.js';\nimport {\n addPendingSymbolIndexTask,\n clearSymbolIndexHeapIfEmpty,\n latestActiveSequenceByParent,\n pendingSymbolIndexTasks,\n pickNextSymbolIndexTask,\n setSymbolIndexWorkerRunning,\n symbolIndexTaskHeap,\n symbolIndexWorkerRunning,\n} from './task-queue-store.js';\nimport { symbolIndexTaskKey } from './task-queue-types.js';\n\nasync function runWorkerLoop(): Promise<void> {\n if (symbolIndexWorkerRunning) return;\n setSymbolIndexWorkerRunning(true);\n try {\n const yieldState = createCodeNavYieldState();\n while (pendingSymbolIndexTasks.size > 0) {\n const task = pickNextSymbolIndexTask();\n if (task == null) break;\n pendingSymbolIndexTasks.delete(symbolIndexTaskKey(task.parentPath, task.filePath));\n await yieldUntilFileBrowserIdle();\n await yieldDuringCodeNavWork(yieldState);\n const latestActiveSequence = latestActiveSequenceByParent.get(task.parentPath);\n if (latestActiveSequence != null && task.sequence != null && task.sequence < latestActiveSequence) {\n continue;\n }\n if (!(await symbolIndexFileIsReadyAsync(task.parentPath, task.filePath))) {\n try {\n await ensureSymbolIndexFileInWorkerHost(task.parentPath, task.filePath);\n } catch (err) {\n if (isSymbolIndexDeferredError(err)) {\n if (addPendingSymbolIndexTask(task)) kickSymbolIndexWorkerLoop();\n continue;\n }\n throw err;\n }\n }\n }\n } finally {\n clearSymbolIndexHeapIfEmpty();\n setSymbolIndexWorkerRunning(false);\n if (pendingSymbolIndexTasks.size > 0) void runWorkerLoop();\n }\n}\n\nexport function kickSymbolIndexWorkerLoop(): void {\n void runWorkerLoop();\n}\n\n/** @deprecated Use {@link kickSymbolIndexWorkerLoop}. */\nexport function kickSymbolIndexWorker(): void {\n kickSymbolIndexWorkerLoop();\n}\n", "import { applyFileBrowserActivityFromMain } from '../../../files/browser/in-flight.js';\nimport {\n deferBackgroundSymbolIndexTasks,\n enqueueSymbolIndexTaskInternal,\n markLatestActiveSymbolIndexTaskInternal,\n} from '../scheduler/task-queue-core.js';\nimport { kickSymbolIndexWorkerLoop } from '../scheduler/task-queue-worker.js';\nimport type { SymbolIndexWorkerInMessage } from './protocol.js';\n\nexport function handleQueueWorkerMessage(msg: SymbolIndexWorkerInMessage): void {\n switch (msg.type) {\n case 'enqueue':\n if (enqueueSymbolIndexTaskInternal(msg.parentPath, msg.filePath, msg.priority, msg.sequence)) {\n kickSymbolIndexWorkerLoop();\n }\n return;\n case 'markLatestActive':\n markLatestActiveSymbolIndexTaskInternal(msg.parentPath, msg.sequence);\n return;\n case 'deferBackground':\n deferBackgroundSymbolIndexTasks();\n return;\n case 'fileBrowserActivity':\n applyFileBrowserActivityFromMain({\n inFlightRequests: msg.inFlightRequests,\n inFlightReads: msg.inFlightReads,\n lastActivityAt: msg.lastActivityAt,\n });\n return;\n default:\n return;\n }\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { upsertSymbolIndexParentPath } from '../sqlite/symbol-index-sqlite.js';\n\n/** Register parent row without indexing files (cheap). */\nexport async function registerSymbolIndexParentAsync(parentPath: string): Promise<void> {\n const resolved = normalizeResolvedPath(parentPath);\n await withCodeNavCacheSqlite((db) => {\n upsertSymbolIndexParentPath(db, resolved);\n });\n}\n\n/** @deprecated Prefer {@link registerSymbolIndexParentAsync}. */\nexport function registerSymbolIndexParent(parentPath: string): void {\n void registerSymbolIndexParentAsync(parentPath);\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { isBridgeBrowseInteractiveActive, registerFileBrowserActivityListener } from '../../../files/browser/in-flight.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../../yield-during-work.js';\nimport { createWalkYieldState, walkCodeNavFilesAsync } from '../../walk-code-nav-files.js';\nimport { loadSymbolIndexReadyFileSet } from '../lifecycle/symbol-index-file-ready.js';\nimport { enqueueSymbolIndexTaskInternal } from './task-queue-core.js';\nimport { kickSymbolIndexWorkerLoop } from './task-queue-worker.js';\n\nlet requestSeq = 0;\nlet warmupSeq = 0;\nconst warmupCompleted = new Set<string>();\nconst pendingWarmupParents = new Set<string>();\nconst warmupWalkInProgress = new Set<string>();\n\n/** Delay warmup until the user stops browsing files for this long. */\nconst WARMUP_IDLE_MS = 3_000;\n\nlet warmupIdleTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction scheduleWarmupWhenIdle(): void {\n if (warmupIdleTimer != null) clearTimeout(warmupIdleTimer);\n warmupIdleTimer = setTimeout(() => {\n warmupIdleTimer = null;\n if (isBridgeBrowseInteractiveActive()) {\n scheduleWarmupWhenIdle();\n return;\n }\n for (const parentPath of [...pendingWarmupParents]) {\n void runWarmupWalk(parentPath);\n }\n }, WARMUP_IDLE_MS);\n}\n\nregisterFileBrowserActivityListener(() => {\n if (pendingWarmupParents.size > 0) scheduleWarmupWhenIdle();\n});\n\nasync function runWarmupWalk(resolved: string): Promise<void> {\n if (warmupCompleted.has(resolved) || warmupWalkInProgress.has(resolved)) {\n pendingWarmupParents.delete(resolved);\n return;\n }\n warmupWalkInProgress.add(resolved);\n pendingWarmupParents.delete(resolved);\n try {\n if (isBridgeBrowseInteractiveActive()) {\n pendingWarmupParents.add(resolved);\n scheduleWarmupWhenIdle();\n return;\n }\n const readyFiles = await loadSymbolIndexReadyFileSet(resolved);\n const walkState = createWalkYieldState();\n const yieldState = createCodeNavYieldState();\n await walkCodeNavFilesAsync(\n resolved,\n async (relPath) => {\n await yieldDuringCodeNavWork(yieldState);\n if (!readyFiles.has(relPath)) {\n if (enqueueSymbolIndexTaskInternal(resolved, relPath, ++warmupSeq, requestSeq)) {\n kickSymbolIndexWorkerLoop();\n }\n }\n },\n walkState,\n );\n warmupCompleted.add(resolved);\n } finally {\n warmupWalkInProgress.delete(resolved);\n }\n}\n\n/** Low-priority background fill for remaining unindexed files after browse idle. */\nexport function scheduleSymbolIndexWarmupInWorkerHost(parentPath: string): void {\n const resolved = normalizeResolvedPath(parentPath);\n if (warmupCompleted.has(resolved)) return;\n pendingWarmupParents.add(resolved);\n scheduleWarmupWhenIdle();\n}\n\n/** @internal Exposed for tests. */\nexport function resetSymbolIndexWarmupStateForTests(): void {\n warmupCompleted.clear();\n pendingWarmupParents.clear();\n warmupWalkInProgress.clear();\n if (warmupIdleTimer != null) {\n clearTimeout(warmupIdleTimer);\n warmupIdleTimer = null;\n }\n}\n\nexport function bumpSymbolIndexWarmupRequestSeq(): void {\n requestSeq += 1;\n}\n", "import { registerSymbolIndexParentAsync } from '../build/register-symbol-index-parent.js';\nimport { scheduleSymbolIndexWarmupInWorkerHost } from '../scheduler/symbol-index-warmup-host.js';\nimport type { SymbolIndexWorkerInMessage } from './protocol.js';\n\nexport async function handleSetupWorkerMessage(msg: SymbolIndexWorkerInMessage): Promise<void> {\n switch (msg.type) {\n case 'registerParent':\n await registerSymbolIndexParentAsync(msg.parentPath);\n return;\n case 'scheduleWarmup':\n scheduleSymbolIndexWarmupInWorkerHost(msg.parentPath);\n return;\n default:\n return;\n }\n}\n", "import { isCliImmediateShutdownRequested } from '../../../runtime/cli-process-interrupt.js';\nimport { closeAllCodeNavCacheSqliteConnections } from '../../../sqlite/code-nav-cache/database.js';\nimport { maybeLogCodeNavCacheWorkerError } from '../../../sqlite/code-nav-cache/code-nav-cache-log.js';\nimport { CliSqliteInterrupted } from '../../../sqlite/sqlite-errors.js';\nimport { handleIndexWorkerMessage } from './index-handlers.js';\nimport { postSafe } from './post-message.js';\nimport { handleQueueWorkerMessage } from './queue-handlers.js';\nimport { handleSetupWorkerMessage } from './setup-handlers.js';\nimport type { SymbolIndexWorkerInMessage, SymbolIndexWorkerPort } from './protocol.js';\nimport {\n isSymbolIndexWorkerShutdownRequested,\n requestSymbolIndexWorkerShutdown,\n} from './shutdown-state.js';\n\nlet activeWorkerHandlers = 0;\n\nasync function waitForActiveWorkerHandlersIdle(pollMs = 10): Promise<void> {\n while (activeWorkerHandlers > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, pollMs));\n }\n}\n\nexport async function handleRequestMessage(\n port: SymbolIndexWorkerPort,\n msg: SymbolIndexWorkerInMessage,\n): Promise<void> {\n if (msg.type === 'shutdown') {\n requestSymbolIndexWorkerShutdown();\n await waitForActiveWorkerHandlersIdle();\n closeAllCodeNavCacheSqliteConnections();\n postSafe(port, { type: 'shutdownComplete' });\n return;\n }\n\n if (isCliImmediateShutdownRequested() || isSymbolIndexWorkerShutdownRequested()) return;\n\n activeWorkerHandlers += 1;\n try {\n switch (msg.type) {\n case 'enqueue':\n case 'markLatestActive':\n case 'deferBackground':\n case 'fileBrowserActivity':\n handleQueueWorkerMessage(msg);\n return;\n case 'registerParent':\n case 'scheduleWarmup':\n try {\n await handleSetupWorkerMessage(msg);\n } catch (err) {\n if (!(err instanceof CliSqliteInterrupted)) {\n maybeLogCodeNavCacheWorkerError(err instanceof Error ? err.message : String(err));\n }\n }\n return;\n case 'buildFull':\n case 'updateFile':\n case 'removeFile':\n case 'ensureFile':\n await handleIndexWorkerMessage(port, msg);\n return;\n default:\n return;\n }\n } catch (err) {\n if (err instanceof CliSqliteInterrupted) return;\n throw err;\n } finally {\n activeWorkerHandlers = Math.max(0, activeWorkerHandlers - 1);\n }\n}\n", "import { handleRequestMessage } from './handle-message.js';\nimport { postSafe } from './post-message.js';\nimport type { SymbolIndexWorkerPort } from './protocol.js';\n\nexport function attachSymbolIndexWorkerHost(port: SymbolIndexWorkerPort): void {\n port.onMessage((message) => {\n void handleRequestMessage(port, message);\n });\n postSafe(port, { type: 'ready' });\n}\n", "import { parentPort, workerData } from 'node:worker_threads';\nimport { bindFileBrowserActivitySharedBuffer } from '../../../files/browser/in-flight.js';\nimport { setCodeNavCacheDiagnosticSink } from '../../../sqlite/code-nav-cache/code-nav-cache-log.js';\nimport { attachSymbolIndexWorkerHost } from './host.js';\nimport type { SymbolIndexWorkerInMessage, SymbolIndexWorkerOutMessage } from './protocol.js';\n\nif (parentPort == null) {\n throw new Error('symbol index worker must run as a worker thread');\n}\n\nsetCodeNavCacheDiagnosticSink((line) => {\n parentPort!.postMessage({ type: 'cliLog', line } satisfies SymbolIndexWorkerOutMessage);\n});\n\nconst activityBuffer = (workerData as { fileBrowserActivityBuffer?: SharedArrayBuffer } | undefined)\n ?.fileBrowserActivityBuffer;\nif (activityBuffer instanceof SharedArrayBuffer) {\n bindFileBrowserActivitySharedBuffer(activityBuffer);\n}\n\nattachSymbolIndexWorkerHost({\n postMessage(message: SymbolIndexWorkerOutMessage) {\n parentPort!.postMessage(message);\n },\n onMessage(handler: (message: SymbolIndexWorkerInMessage) => void) {\n parentPort!.on('message', handler);\n },\n});\n"],
4
+ "sourcesContent": ["const ACTIVITY_INDEX_REQUESTS = 0;\nconst ACTIVITY_INDEX_READS = 1;\n/** Unix seconds \u2014 fits Int32 until ~2038; sufficient for browse cooldown checks. */\nconst ACTIVITY_INDEX_LAST_ACTIVITY_SEC = 2;\n\nconst activitySharedBuffer = new SharedArrayBuffer(3 * Int32Array.BYTES_PER_ELEMENT);\nconst mainActivityView = new Int32Array(activitySharedBuffer);\n\nlet workerActivityView: Int32Array | null = null;\n\nexport function getFileBrowserActivitySharedBuffer(): SharedArrayBuffer {\n return activitySharedBuffer;\n}\n\nexport function bindFileBrowserActivitySharedBuffer(buffer: SharedArrayBuffer): void {\n workerActivityView = new Int32Array(buffer);\n}\n\nexport function syncFileBrowserActivityToShared(params: {\n inFlightRequests: number;\n inFlightReads: number;\n lastActivityAt: number;\n}): void {\n Atomics.store(mainActivityView, ACTIVITY_INDEX_REQUESTS, params.inFlightRequests);\n Atomics.store(mainActivityView, ACTIVITY_INDEX_READS, params.inFlightReads);\n Atomics.store(\n mainActivityView,\n ACTIVITY_INDEX_LAST_ACTIVITY_SEC,\n Math.floor(params.lastActivityAt / 1000),\n );\n}\n\nexport function readFileBrowserActivityFromShared(): {\n inFlightRequests: number;\n inFlightReads: number;\n lastActivityAt: number;\n} {\n const view = workerActivityView ?? mainActivityView;\n return {\n inFlightRequests: Atomics.load(view, ACTIVITY_INDEX_REQUESTS),\n inFlightReads: Atomics.load(view, ACTIVITY_INDEX_READS),\n lastActivityAt: Atomics.load(view, ACTIVITY_INDEX_LAST_ACTIVITY_SEC) * 1000,\n };\n}\n", "/** Pause symbol indexing briefly after file browser activity so reads are not blocked mid-parse. */\nexport const BROWSE_INDEX_COOLDOWN_MS = 2_500;\n\nexport type FileBrowserActivitySnapshot = {\n inFlightRequests: number;\n inFlightReads: number;\n lastActivityAt: number;\n};\n", "import type { FileBrowserActivitySnapshot } from './activity-types.js';\n\nlet inFlightRequests = 0;\nlet inFlightReads = 0;\n/** Browse list/request activity only \u2014 not updated for reads (avoids extending browse cooldown). */\nlet lastBrowseRequestActivityAt = 0;\n\n/** Worker mirror updated from the main thread over postMessage. */\nlet workerMirror: FileBrowserActivitySnapshot = {\n inFlightRequests: 0,\n inFlightReads: 0,\n lastActivityAt: 0,\n};\n\nexport function touchBrowseRequestActivity(): void {\n lastBrowseRequestActivityAt = Date.now();\n}\n\nexport function snapshotFromMain(): FileBrowserActivitySnapshot {\n return {\n inFlightRequests,\n inFlightReads,\n lastActivityAt: lastBrowseRequestActivityAt,\n };\n}\n\nexport function getWorkerMirror(): FileBrowserActivitySnapshot {\n return workerMirror;\n}\n\nexport function setWorkerMirror(snapshot: FileBrowserActivitySnapshot): void {\n workerMirror = snapshot;\n}\n\nexport function incrementInFlightRequests(): void {\n inFlightRequests += 1;\n touchBrowseRequestActivity();\n}\n\nexport function decrementInFlightRequests(): void {\n inFlightRequests = Math.max(0, inFlightRequests - 1);\n touchBrowseRequestActivity();\n}\n\nexport function incrementInFlightReads(): void {\n inFlightReads += 1;\n}\n\nexport function decrementInFlightReads(): void {\n inFlightReads = Math.max(0, inFlightReads - 1);\n}\n", "import { isMainThread } from 'node:worker_threads';\nimport {\n readFileBrowserActivityFromShared,\n syncFileBrowserActivityToShared,\n} from './activity-shared.js';\nimport type { FileBrowserActivitySnapshot } from './activity-types.js';\nimport { snapshotFromMain, setWorkerMirror } from './counts.js';\n\nlet activityPublisher: ((snapshot: FileBrowserActivitySnapshot) => void) | null = null;\n\nexport function registerFileBrowserActivityPublisher(\n publisher: (snapshot: FileBrowserActivitySnapshot) => void,\n): void {\n activityPublisher = publisher;\n}\n\nexport function applyFileBrowserActivityFromMain(snapshot: FileBrowserActivitySnapshot): void {\n setWorkerMirror(snapshot);\n}\n\nexport function syncMainActivityToShared(): void {\n syncFileBrowserActivityToShared(snapshotFromMain());\n}\n\nexport function currentFileBrowserActivity(): FileBrowserActivitySnapshot {\n if (isMainThread) return snapshotFromMain();\n return readFileBrowserActivityFromShared();\n}\n\nfunction publishActivityToWorker(): void {\n if (!isMainThread) return;\n activityPublisher?.(snapshotFromMain());\n}\n\n/** Sync current browse/read activity to the symbol index worker (after DB init). */\nexport function publishFileBrowserActivityToWorker(): void {\n publishActivityToWorker();\n}\n\nexport function getFileBrowserActivitySnapshot(): FileBrowserActivitySnapshot {\n return snapshotFromMain();\n}\n\nexport function publishAfterActivityChange(): void {\n syncMainActivityToShared();\n publishActivityToWorker();\n}\n", "const activityListeners = new Set<() => void>();\nconst requestStartListeners = new Set<() => void>();\nconst readStartListeners = new Set<() => void>();\n\nexport function registerFileBrowserActivityListener(listener: () => void): () => void {\n activityListeners.add(listener);\n return () => {\n activityListeners.delete(listener);\n };\n}\n\nexport function registerFileBrowserRequestStartListener(listener: () => void): () => void {\n requestStartListeners.add(listener);\n return () => {\n requestStartListeners.delete(listener);\n };\n}\n\nexport function registerFileBrowserReadStartListener(listener: () => void): () => void {\n readStartListeners.add(listener);\n return () => {\n readStartListeners.delete(listener);\n };\n}\n\nexport function notifyFileBrowserActivity(): void {\n for (const listener of activityListeners) listener();\n}\n\nexport function notifyFileBrowserRequestStart(): void {\n for (const listener of requestStartListeners) listener();\n}\n\nexport function notifyFileBrowserReadStart(): void {\n for (const listener of readStartListeners) listener();\n}\n", "let primeResolveEpoch = 0;\n\n/** Bumped when interactive reads start so list priming stops immediately. */\nexport function cancelBackgroundResolvePriming(): number {\n primeResolveEpoch += 1;\n return primeResolveEpoch;\n}\n\nexport function currentBackgroundResolvePrimingEpoch(): number {\n return primeResolveEpoch;\n}\n\n/** @internal Test helper. */\nexport function resetBackgroundResolvePrimingForTests(): void {\n primeResolveEpoch = 0;\n}\n", "import { cancelBackgroundResolvePriming } from '../read/cancel-background-resolve-priming.js';\nimport {\n decrementInFlightReads,\n decrementInFlightRequests,\n incrementInFlightReads,\n incrementInFlightRequests,\n} from './counts.js';\nimport {\n notifyFileBrowserActivity,\n notifyFileBrowserReadStart,\n notifyFileBrowserRequestStart,\n} from './listeners.js';\nimport { publishAfterActivityChange } from './publish.js';\n\nfunction beginFileBrowserActivity(\n kind: 'request' | 'read',\n notifyStart: () => void,\n): void {\n if (kind === 'request') {\n incrementInFlightRequests();\n } else {\n incrementInFlightReads();\n cancelBackgroundResolvePriming();\n }\n publishAfterActivityChange();\n notifyStart();\n notifyFileBrowserActivity();\n}\n\nfunction endFileBrowserActivity(kind: 'request' | 'read'): void {\n if (kind === 'request') {\n decrementInFlightRequests();\n } else {\n decrementInFlightReads();\n }\n publishAfterActivityChange();\n}\n\nexport function beginFileBrowserRequest(): void {\n beginFileBrowserActivity('request', notifyFileBrowserRequestStart);\n}\n\nexport function endFileBrowserRequest(): void {\n endFileBrowserActivity('request');\n}\n\nexport function beginFileBrowserRead(): void {\n beginFileBrowserActivity('read', notifyFileBrowserReadStart);\n}\n\nexport function endFileBrowserRead(): void {\n endFileBrowserActivity('read');\n}\n", "import { currentFileBrowserActivity } from './publish.js';\n\nexport function fileBrowserRequestInFlight(): boolean {\n return currentFileBrowserActivity().inFlightRequests > 0;\n}\n\nexport function getFileBrowserInFlightReadCount(): number {\n return currentFileBrowserActivity().inFlightReads;\n}\n\nexport function fileBrowserReadInFlight(): boolean {\n return getFileBrowserInFlightReadCount() > 0;\n}\n", "export { applyFileBrowserActivityFromMain } from './publish.js';\nexport {\n registerFileBrowserActivityListener,\n registerFileBrowserReadStartListener,\n registerFileBrowserRequestStartListener,\n} from './listeners.js';\nexport {\n getFileBrowserActivitySnapshot,\n publishFileBrowserActivityToWorker,\n registerFileBrowserActivityPublisher,\n} from './publish.js';\nexport {\n beginFileBrowserRead,\n beginFileBrowserRequest,\n endFileBrowserRead,\n endFileBrowserRequest,\n} from './begin-end.js';\nexport {\n fileBrowserReadInFlight,\n fileBrowserRequestInFlight,\n getFileBrowserInFlightReadCount,\n} from './status.js';\n\nexport { currentFileBrowserActivity } from './publish.js';\n", "/**\n * Resolves after the current stack clears so other I/O, timers, and WebSocket\n * callbacks can run. Prefer this over long synchronous loops on the bridge path.\n */\nexport function yieldToEventLoop(): Promise<void> {\n return new Promise((resolve) => setImmediate(resolve));\n}\n", "/** Thrown when background indexing should yield to an in-flight file browser request. */\nexport class SymbolIndexDeferredError extends Error {\n constructor() {\n super('Symbol indexing deferred for file browser');\n this.name = 'SymbolIndexDeferredError';\n }\n}\n\nexport function isSymbolIndexDeferredError(err: unknown): err is SymbolIndexDeferredError {\n return err instanceof SymbolIndexDeferredError;\n}\n", "import { isMainThread } from 'node:worker_threads';\nimport { yieldToEventLoop } from '../../runtime/yield-to-event-loop.js';\nimport { SymbolIndexDeferredError } from '../../code-nav/symbol-index/deferred-indexing.js';\nimport { BROWSE_INDEX_COOLDOWN_MS } from './activity-types.js';\nimport {\n currentFileBrowserActivity,\n getFileBrowserInFlightReadCount,\n} from './activity-tracker.js';\n\n/** True while browse/read is active or browse recently finished \u2014 pause background indexing. */\nexport function isBridgeBrowseInteractiveActive(): boolean {\n const { inFlightRequests, inFlightReads, lastActivityAt } = currentFileBrowserActivity();\n if (inFlightRequests > 0) return true;\n if (inFlightReads > 0) return true;\n if (lastActivityAt === 0) return false;\n return Date.now() - lastActivityAt < BROWSE_INDEX_COOLDOWN_MS;\n}\n\n/** Throw when file browser work should preempt background indexing (e.g. before sync tree-sitter). */\nexport function assertBackgroundIndexingAllowed(): void {\n if (isBridgeBrowseInteractiveActive()) throw new SymbolIndexDeferredError();\n}\n\n/** Wait until no file reads are in flight. */\nexport async function yieldUntilFileBrowserReadsIdle(pollMs = 5): Promise<void> {\n while (getFileBrowserInFlightReadCount() > 0) {\n await yieldToEventLoop();\n if (getFileBrowserInFlightReadCount() > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, pollMs));\n }\n }\n}\n\n/** Wait until browse requests finish and browse cooldown has elapsed (ignores in-flight reads). */\nexport async function yieldUntilFileBrowserBrowseIdle(pollMs = 5): Promise<void> {\n while (true) {\n const { inFlightRequests, lastActivityAt } = currentFileBrowserActivity();\n const browseCooldownDone =\n lastActivityAt === 0 || Date.now() - lastActivityAt >= BROWSE_INDEX_COOLDOWN_MS;\n if (inFlightRequests === 0 && browseCooldownDone) return;\n await yieldToEventLoop();\n await new Promise<void>((resolve) => setTimeout(resolve, pollMs));\n }\n}\n\n/** @deprecated Prefer {@link yieldUntilFileBrowserBrowseIdle} or {@link yieldUntilBackgroundIndexingAllowed}. */\nexport async function yieldUntilFileBrowserIdle(pollMs = 5): Promise<void> {\n await yieldUntilBackgroundIndexingAllowed(pollMs);\n}\n\n/** Wait until reads, browse, and browse cooldown allow background indexing/file walks. */\nexport async function yieldUntilBackgroundIndexingAllowed(pollMs = 5): Promise<void> {\n await yieldUntilFileBrowserReadsIdle(pollMs);\n await yieldUntilFileBrowserBrowseIdle(pollMs);\n}\n\n/** Yield to the event loop, then pause background work while file browser reads/browse are active. */\nexport async function yieldForBridgeInteractivePriority(): Promise<void> {\n await yieldToEventLoop();\n if (isMainThread) {\n await yieldUntilBackgroundIndexingAllowed();\n return;\n }\n assertBackgroundIndexingAllowed();\n}\n", "export {\n bindFileBrowserActivitySharedBuffer,\n getFileBrowserActivitySharedBuffer,\n} from './activity-shared.js';\n\nexport { BROWSE_INDEX_COOLDOWN_MS, type FileBrowserActivitySnapshot } from './activity-types.js';\n\nexport {\n applyFileBrowserActivityFromMain,\n beginFileBrowserRead,\n beginFileBrowserRequest,\n endFileBrowserRead,\n endFileBrowserRequest,\n fileBrowserReadInFlight,\n fileBrowserRequestInFlight,\n getFileBrowserActivitySnapshot,\n getFileBrowserInFlightReadCount,\n publishFileBrowserActivityToWorker,\n registerFileBrowserActivityListener,\n registerFileBrowserActivityPublisher,\n registerFileBrowserReadStartListener,\n registerFileBrowserRequestStartListener,\n} from './activity-tracker.js';\n\nexport {\n assertBackgroundIndexingAllowed,\n isBridgeBrowseInteractiveActive,\n yieldForBridgeInteractivePriority,\n yieldUntilBackgroundIndexingAllowed,\n yieldUntilFileBrowserBrowseIdle,\n yieldUntilFileBrowserIdle,\n yieldUntilFileBrowserReadsIdle,\n} from './idle-yield.js';\n", "export type CliLogVerbosity = 'info' | 'debug' | 'trace';\n\nlet verbosity: CliLogVerbosity = 'info';\n\nexport function setCliLogVerbosity(level: CliLogVerbosity): void {\n verbosity = level;\n}\n\nexport function getCliLogVerbosity(): CliLogVerbosity {\n return verbosity;\n}\n\nexport function isCliDebugOrTrace(): boolean {\n return verbosity === 'debug' || verbosity === 'trace';\n}\n\nexport function isCliTrace(): boolean {\n return verbosity === 'trace';\n}\n", "/**\n * Shared CLI logging: timestamped lines to stdout.\n */\n\nimport { getCliLogVerbosity } from './cli-log-level.js';\n\nexport type LogFn = (line: string) => void;\n\nfunction timestampPrefix(): string {\n const time = new Date().toISOString().slice(11, 19);\n return `[${time}]`;\n}\n\n/**\n * Log a line with a [HH:mm:ss] prefix to stdout.\n */\nexport function log(line: string): void {\n console.log(`${timestampPrefix()} ${line}`);\n}\n\n/** Same timestamp format as `log`, written synchronously to stdout (avoids delay before TTY flush). */\nexport function logImmediate(line: string): void {\n process.stdout.write(`${timestampPrefix()} ${line}\\n`);\n}\n\n/** Debug-level line (shown with `--debug` or `--trace`). */\nexport function logDebug(line: string): void {\n const v = getCliLogVerbosity();\n if (v !== 'debug' && v !== 'trace') return;\n console.log(`${timestampPrefix()} [debug] ${line}`);\n}\n\n/** Trace-level line (shown only with `--trace`), e.g. git subprocess output. */\nexport function logTrace(line: string): void {\n if (getCliLogVerbosity() !== 'trace') return;\n console.log(`${timestampPrefix()} [trace] ${line}`);\n}\n", "/** Thrown when {@link requestCliImmediateShutdown} was set (Ctrl+C / bridge close). */\nexport class CliSqliteInterrupted extends Error {\n override readonly name = 'CliSqliteInterrupted';\n constructor() {\n super('CLI SQLite interrupted (shutdown)');\n }\n}\n\nexport function isCliSqliteLockError(e: unknown): boolean {\n if (e instanceof CliSqliteInterrupted) return false;\n const msg = e instanceof Error ? e.message : String(e);\n const lower = msg.toLowerCase();\n return (\n lower.includes('database is locked') ||\n lower.includes('sqlite_busy') ||\n lower.includes('sqlite3_busy') ||\n lower.includes('.lock') ||\n lower.includes('eexist') ||\n lower.includes('file exists') ||\n lower.includes('resource busy') ||\n lower.includes('unable to acquire') ||\n lower.includes('could not open') ||\n lower.includes('failed to open') ||\n (lower.includes('database') && lower.includes('locked'))\n );\n}\n", "import fs from 'node:fs';\nimport { logImmediate } from '../log.js';\n\n/** node-sqlite3-wasm advisory lock directory for a database file path. */\nexport function getSqliteLockPath(dbPath: string): string {\n return `${dbPath}.lock`;\n}\n\n/** Best-effort removal of a stale node-sqlite3-wasm lock directory (or file). */\nexport function removeSqliteLockPathIfPresent(dbPath: string): void {\n const lockPath = getSqliteLockPath(dbPath);\n try {\n fs.rmSync(lockPath, { recursive: true, force: true });\n } catch {\n /* ignore \u2014 teardown must not throw */\n }\n}\n\nexport function logStaleSqliteLockIntervention(dbPath: string): void {\n const lockPath = getSqliteLockPath(dbPath);\n logImmediate(\n `SQLite database locked after retries; if no other buildautomaton CLI is running, remove stale lock: ${lockPath}`,\n );\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\n/**\n * Path to the CLI code-navigation cache SQLite database (file index + symbol index).\n * Override with `BUILDAMATON_CODE_NAV_CACHE_SQLITE_PATH` for tests or custom layouts.\n * Safe to delete \u2014 only caches; the main CLI database is unaffected.\n */\nexport function getCodeNavCacheSqlitePath(): string {\n const override = process.env.BUILDAMATON_CODE_NAV_CACHE_SQLITE_PATH?.trim();\n if (override) return path.resolve(override);\n return path.join(os.homedir(), '.buildautomaton', 'code-nav-cache.sqlite');\n}\n\nexport function ensureCodeNavCacheSqliteParentDir(sqlitePath: string): void {\n const dir = path.dirname(sqlitePath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n", "import fs from 'node:fs';\nimport { isMainThread } from 'node:worker_threads';\nimport type { LogFn } from '../../log.js';\nimport { logImmediate } from '../../log.js';\nimport { isCliSqliteLockError } from '../sqlite-errors.js';\nimport { getSqliteLockPath } from '../sqlite-lock-path.js';\nimport { getCodeNavCacheSqlitePath } from './code-nav-cache-paths.js';\n\ntype CodeNavCacheDiagnosticSink = (line: string) => void;\n\nlet diagnosticSink: CodeNavCacheDiagnosticSink = logImmediate;\nlet lastDiagnosticKey: string | null = null;\n\nexport function setCodeNavCacheDiagnosticSink(sink: CodeNavCacheDiagnosticSink): void {\n diagnosticSink = sink;\n}\n\nexport function resetCodeNavCacheLogForTests(): void {\n lastDiagnosticKey = null;\n diagnosticSink = logImmediate;\n}\n\nfunction codeNavCacheLockPath(): string {\n return getSqliteLockPath(getCodeNavCacheSqlitePath());\n}\n\nfunction lockDirectoryPresent(): boolean {\n try {\n return fs.existsSync(codeNavCacheLockPath());\n } catch {\n return false;\n }\n}\n\nfunction emitCodeNavCacheDiagnostic(key: string, line: string): void {\n if (lastDiagnosticKey === key) return;\n lastDiagnosticKey = key;\n diagnosticSink(line);\n}\n\nfunction formatLockBlockedLine(detail: string): string {\n const lockPath = codeNavCacheLockPath();\n const dbPath = getCodeNavCacheSqlitePath();\n if (lockDirectoryPresent()) {\n return `[code-nav] Code navigation cache blocked (${detail}). Remove stale lock when no other buildautomaton CLI is running: ${lockPath}`;\n }\n return `[code-nav] Code navigation cache blocked (${detail}). Database: ${dbPath} Lock: ${lockPath}`;\n}\n\n/** Log once at bridge startup when a stale lock directory is already present. */\nexport function logCodeNavCacheLockPresentAtStartup(log: LogFn = logImmediate): void {\n if (!lockDirectoryPresent()) return;\n const lockPath = codeNavCacheLockPath();\n log(\n `[code-nav] Code navigation cache lock directory exists at startup (${lockPath}). Indexing will retry briefly; remove this directory if no other buildautomaton CLI is running.`,\n );\n}\n\n/** Log SQLite lock/contention for the code-nav cache (main thread or worker via diagnostic sink). */\nexport function reportCodeNavCacheLockContention(\n detail: string,\n opts?: { attempt?: number; maxAttempts?: number; final?: boolean },\n): void {\n const attemptSuffix =\n opts?.attempt != null && opts?.maxAttempts != null\n ? ` [attempt ${opts.attempt}/${opts.maxAttempts}${opts.final ? ', giving up' : ''}]`\n : opts?.final\n ? ' [giving up]'\n : '';\n emitCodeNavCacheDiagnostic(\n `lock:${detail}:${opts?.attempt ?? 0}:${opts?.final ?? false}`,\n `${formatLockBlockedLine(detail)}${attemptSuffix}`,\n );\n}\n\nexport function logCodeNavCacheUnavailableFromError(log: LogFn, err: unknown): void {\n const detail = err instanceof Error ? err.message : String(err);\n log(`${formatLockBlockedLine(detail)}`);\n lastDiagnosticKey = `unavailable:${detail}`;\n}\n\nexport function maybeLogCodeNavCacheWorkerError(message: string): void {\n const err = new Error(message);\n if (\n isCliSqliteLockError(err) ||\n message.toLowerCase().includes('code navigation cache') ||\n message.toLowerCase().includes('unavailable')\n ) {\n reportCodeNavCacheLockContention(`symbol index worker: ${message}`, { final: true });\n }\n}\n\n/** True when worker-thread diagnostics should post to the main CLI log. */\nexport function isCodeNavCacheDiagnosticWorkerThread(): boolean {\n return !isMainThread;\n}\n", "/**\n * Process-wide \"shutting down\" flag set on SIGINT/SIGTERM (and when closing the bridge).\n * SQLite and other subsystems consult this to bail out of retry loops and long waits immediately.\n */\n\nlet cliImmediateShutdownRequested = false;\nlet symbolIndexShutdownPromise: Promise<void> | null = null;\n\n/** Set once (idempotent). Call from signal handlers and bridge `close()` as early as possible. */\nexport function requestCliImmediateShutdown(): void {\n if (cliImmediateShutdownRequested) return;\n cliImmediateShutdownRequested = true;\n symbolIndexShutdownPromise = import('../code-nav/symbol-index/worker/lifecycle.js')\n .then(({ terminateSymbolIndexWorker }) => terminateSymbolIndexWorker())\n .catch(() => {\n /* worker module may not be loaded yet */\n });\n}\n\nexport function isCliImmediateShutdownRequested(): boolean {\n return cliImmediateShutdownRequested;\n}\n\n/** Wait for symbol index worker shutdown and code-nav SQLite lock cleanup. */\nexport async function awaitSymbolIndexWorkerShutdown(): Promise<void> {\n if (symbolIndexShutdownPromise != null) {\n await symbolIndexShutdownPromise;\n return;\n }\n if (cliImmediateShutdownRequested) {\n const { terminateSymbolIndexWorker } = await import('../code-nav/symbol-index/worker/lifecycle.js');\n await terminateSymbolIndexWorker();\n }\n}\n\n/**\n * Clear the process-wide shutdown flag so a new bridge session can start (e.g. after\n * auth-invalid close + browser re-link). Awaits any in-flight symbol-index terminate first.\n */\nexport async function clearCliImmediateShutdown(): Promise<void> {\n if (symbolIndexShutdownPromise != null) {\n try {\n await symbolIndexShutdownPromise;\n } catch {\n /* ignore */\n }\n }\n cliImmediateShutdownRequested = false;\n symbolIndexShutdownPromise = null;\n}\n\n/** Vitest / teardown: clear interrupt state for a clean worker. */\nexport function resetCliImmediateShutdownForTests(): void {\n cliImmediateShutdownRequested = false;\n symbolIndexShutdownPromise = null;\n}\n\n/**\n * Sleep up to `ms`, checking shutdown every ~50ms. Resolves `false` when interrupted, `true` when the full delay elapsed.\n */\nexport async function delayMsUnlessShutdownRequested(ms: number): Promise<boolean> {\n if (ms <= 0) return true;\n const end = Date.now() + ms;\n while (Date.now() < end) {\n if (isCliImmediateShutdownRequested()) return false;\n const chunk = Math.min(50, end - Date.now());\n if (chunk <= 0) break;\n await new Promise<void>((r) => setTimeout(r, chunk));\n }\n return !isCliImmediateShutdownRequested();\n}\n", "import type { LogFn } from '../../log.js';\nimport { logImmediate } from '../../log.js';\nimport { publishFileBrowserActivityToWorker } from '../../files/browser/in-flight.js';\nimport { CliSqliteInterrupted } from '../sqlite-errors.js';\nimport {\n logCodeNavCacheLockPresentAtStartup,\n logCodeNavCacheUnavailableFromError,\n} from './code-nav-cache-log.js';\n\ntype CodeNavCacheInitState = 'idle' | 'pending' | 'ready' | 'unavailable';\n\nlet initState: CodeNavCacheInitState = 'idle';\nlet initPromise: Promise<boolean> | null = null;\n\nexport class CodeNavCacheUnavailableError extends Error {\n override readonly name = 'CodeNavCacheUnavailableError';\n constructor() {\n super('Code navigation cache unavailable');\n }\n}\n\nexport function isCodeNavCacheReady(): boolean {\n return initState === 'ready';\n}\n\nexport function isCodeNavCacheUnavailable(): boolean {\n return initState === 'unavailable';\n}\n\nexport function getCodeNavCacheInitPromise(): Promise<boolean> | null {\n return initPromise;\n}\n\n/** Kick off code-nav SQLite init without blocking bridge connection setup. */\nexport function startCodeNavCacheInitialization(log: LogFn = logImmediate): Promise<boolean> {\n if (initState === 'ready') return Promise.resolve(true);\n if (initState === 'unavailable') return Promise.resolve(false);\n if (initPromise != null) return initPromise;\n\n logCodeNavCacheLockPresentAtStartup(log);\n\n initState = 'pending';\n initPromise = (async () => {\n try {\n const { ensureCodeNavCacheSqliteInitialized } = await import('./database.js');\n await ensureCodeNavCacheSqliteInitialized();\n initState = 'ready';\n publishFileBrowserActivityToWorker();\n return true;\n } catch (e) {\n if (e instanceof CliSqliteInterrupted) {\n initState = 'idle';\n initPromise = null;\n throw e;\n }\n initState = 'unavailable';\n logCodeNavCacheUnavailableFromError(log, e);\n return false;\n }\n })();\n return initPromise;\n}\n\n/** Await background init; returns false when indexing is disabled. */\nexport async function awaitCodeNavCacheInitialization(): Promise<boolean> {\n if (initState === 'ready') return true;\n if (initState === 'unavailable') return false;\n if (initPromise != null) return initPromise;\n return false;\n}\n\nexport function resetCodeNavCacheAvailabilityForTests(): void {\n initState = 'idle';\n initPromise = null;\n}\n", "/** Worker-thread shutdown flag (main-thread {@link isCliImmediateShutdownRequested} is not visible in workers). */\nlet symbolIndexWorkerShutdownRequested = false;\n\nexport function requestSymbolIndexWorkerShutdown(): void {\n symbolIndexWorkerShutdownRequested = true;\n}\n\nexport function isSymbolIndexWorkerShutdownRequested(): boolean {\n return symbolIndexWorkerShutdownRequested;\n}\n\nexport function resetSymbolIndexWorkerShutdownForTests(): void {\n symbolIndexWorkerShutdownRequested = false;\n}\n\n/** True when symbol-index work should stop (main Ctrl+C or worker shutdown message). */\nexport function isSymbolIndexWorkInterrupted(): boolean {\n return symbolIndexWorkerShutdownRequested;\n}\n", "import { yieldToEventLoop } from '../../runtime/yield-to-event-loop.js';\nimport {\n isCliImmediateShutdownRequested,\n} from '../../runtime/cli-process-interrupt.js';\nimport { isSymbolIndexWorkerShutdownRequested } from '../../code-nav/symbol-index/worker/shutdown-state.js';\nimport { CliSqliteInterrupted } from '../sqlite-errors.js';\n\n/** Nested code-nav SQLite opens on the same stack (reentrant work lock). */\nlet codeNavCacheAccessDepth = 0;\n\nasync function waitForOuterCodeNavCacheAccessAsync(): Promise<void> {\n while (codeNavCacheAccessDepth > 0) {\n if (isCliImmediateShutdownRequested() || isSymbolIndexWorkerShutdownRequested()) {\n throw new CliSqliteInterrupted();\n }\n await new Promise<void>((resolve) => setTimeout(resolve, 5));\n await yieldToEventLoop();\n }\n}\n\nfunction waitForOuterCodeNavCacheAccessSync(): void {\n while (codeNavCacheAccessDepth > 0) {\n if (isCliImmediateShutdownRequested() || isSymbolIndexWorkerShutdownRequested()) {\n throw new CliSqliteInterrupted();\n }\n const end = Date.now() + 5;\n while (Date.now() < end) {\n if (isCliImmediateShutdownRequested() || isSymbolIndexWorkerShutdownRequested()) {\n throw new CliSqliteInterrupted();\n }\n }\n }\n}\n\nexport function getCodeNavCacheAccessDepth(): number {\n return codeNavCacheAccessDepth;\n}\n\nexport function incrementCodeNavCacheAccessDepth(): void {\n codeNavCacheAccessDepth += 1;\n}\n\nexport function decrementCodeNavCacheAccessDepth(): void {\n codeNavCacheAccessDepth = Math.max(0, codeNavCacheAccessDepth - 1);\n}\n\nexport async function waitForOuterCodeNavCacheAccessIfNeededAsync(nested: boolean): Promise<void> {\n if (!nested) await waitForOuterCodeNavCacheAccessAsync();\n}\n\nexport function waitForOuterCodeNavCacheAccessIfNeededSync(nested: boolean): void {\n if (!nested) waitForOuterCodeNavCacheAccessSync();\n}\n\nexport function resetCodeNavCacheAccessDepth(): void {\n codeNavCacheAccessDepth = 0;\n}\n", "import { isCliImmediateShutdownRequested } from '../runtime/cli-process-interrupt.js';\nimport { yieldToEventLoop } from '../runtime/yield-to-event-loop.js';\nimport { CliSqliteInterrupted } from './sqlite-errors.js';\n\nexport const SYNC_RETRY_MAX = 40;\nexport const ASYNC_RETRY_MAX = 60;\nexport const ASYNC_PROBE_RETRY_MAX = 2;\n\nexport const ASYNC_BASE_DELAY_MS = 20;\n\n/**\n * Brief synchronous wait for SQLite lock retries inside `withSync`.\n * Uses short chunks so SIGINT/shutdown checks run frequently; prefer `withAsync` on background paths.\n */\nexport function syncSleepMs(ms: number): void {\n if (ms <= 0) return;\n const deadline = Date.now() + ms;\n while (Date.now() < deadline) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n const chunk = Math.min(10, deadline - Date.now());\n if (chunk <= 0) break;\n try {\n const sab = new SharedArrayBuffer(4);\n const ia = new Int32Array(sab);\n Atomics.wait(ia, 0, 0, chunk);\n } catch {\n const end = Date.now() + chunk;\n while (Date.now() < end) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n }\n }\n }\n}\n\nexport async function asyncDelayMsInterruptible(ms: number): Promise<void> {\n const end = Date.now() + ms;\n while (Date.now() < end) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n const chunk = Math.min(50, end - Date.now());\n if (chunk <= 0) break;\n await new Promise<void>((r) => setTimeout(r, chunk));\n await yieldToEventLoop();\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport sqliteWasm from 'node-sqlite3-wasm';\n\nexport const SqliteDatabaseConstructor = (sqliteWasm as unknown as {\n Database: new (filename?: string, options?: { fileMustExist?: boolean; readOnly?: boolean }) => Database;\n}).Database;\n\nexport type SqliteMigrateState = {\n migrateDoneForPath: string | null;\n};\n\nexport function createSqliteMigrateState(): SqliteMigrateState {\n return { migrateDoneForPath: null };\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport function applySqliteConcurrencyPragmas(db: Database): void {\n try {\n db.run('PRAGMA foreign_keys = ON');\n } catch {\n /* ignore */\n }\n try {\n db.exec('PRAGMA journal_mode = WAL');\n } catch {\n /* ignore */\n }\n try {\n db.run('PRAGMA synchronous = NORMAL');\n } catch {\n /* ignore */\n }\n try {\n db.run('PRAGMA busy_timeout = 500');\n } catch {\n /* ignore */\n }\n}\n\nexport function applySqliteMemoryPragmas(db: Database): void {\n try {\n db.run('PRAGMA cache_size = -8192');\n db.run('PRAGMA temp_store = FILE');\n } catch {\n /* ignore */\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { isCliImmediateShutdownRequested } from '../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../sqlite-errors.js';\nimport { applySqliteConcurrencyPragmas, applySqliteMemoryPragmas } from '../sqlite-pragmas.js';\nimport type { SqliteDatabaseAccessOptions } from '../database-access-types.js';\nimport { SqliteDatabaseConstructor, type SqliteMigrateState } from './bindings.js';\n\nexport function safeCloseSqliteDatabase(db: Database | null | undefined): void {\n if (db == null) return;\n try {\n if (db.isOpen) db.close();\n } catch {\n /* ignore */\n }\n}\n\nfunction shouldSkipMigrate(sqlitePath: string, db: Database, migrateState: SqliteMigrateState): boolean {\n if (migrateState.migrateDoneForPath !== sqlitePath) return false;\n try {\n const row = db.get(\n \"SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='__migrations' LIMIT 1\",\n ) as { ok: number } | null;\n return row != null;\n } catch {\n return false;\n }\n}\n\nexport function openSqliteConnection<OpenOptions>(\n config: SqliteDatabaseAccessOptions<OpenOptions>,\n migrateState: SqliteMigrateState,\n options?: OpenOptions,\n): Database {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n const sqlitePath = config.getPath();\n config.ensureParentDir(sqlitePath);\n const db = new SqliteDatabaseConstructor(sqlitePath);\n try {\n applySqliteConcurrencyPragmas(db);\n applySqliteMemoryPragmas(db);\n if (!shouldSkipMigrate(sqlitePath, db, migrateState)) {\n config.migrate(db);\n migrateState.migrateDoneForPath = sqlitePath;\n }\n config.afterOpen?.(db, options);\n } catch (e) {\n safeCloseSqliteDatabase(db);\n throw e;\n }\n return db;\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { yieldToEventLoop } from '../../runtime/yield-to-event-loop.js';\nimport { isCliImmediateShutdownRequested } from '../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted, isCliSqliteLockError } from '../sqlite-errors.js';\nimport { logStaleSqliteLockIntervention } from '../sqlite-lock-path.js';\nimport {\n ASYNC_BASE_DELAY_MS,\n ASYNC_RETRY_MAX,\n asyncDelayMsInterruptible,\n} from '../sqlite-lock-retry.js';\nimport type { SqliteDatabaseAccessOptions } from '../database-access-types.js';\n\nexport async function runSqliteWithAsync<OpenOptions, T>(\n config: SqliteDatabaseAccessOptions<OpenOptions>,\n openConnection: (options?: OpenOptions) => Database,\n safeClose: (db: Database | null | undefined) => void,\n fn: (db: Database) => T | Promise<T>,\n options?: OpenOptions,\n maxAttempts = ASYNC_RETRY_MAX,\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n let db: Database | undefined;\n try {\n db = openConnection(options);\n try {\n return await Promise.resolve(fn(db));\n } finally {\n safeClose(db);\n }\n } catch (e) {\n lastError = e;\n safeClose(db);\n if (e instanceof CliSqliteInterrupted) throw e;\n if (!isCliSqliteLockError(e)) throw e;\n config.onLockRetry?.({\n dbPath: config.getPath(),\n attempt,\n maxAttempts,\n final: attempt === maxAttempts,\n });\n if (attempt === maxAttempts) {\n logStaleSqliteLockIntervention(config.getPath());\n throw e;\n }\n const delayMs = Math.min(600, ASYNC_BASE_DELAY_MS * attempt);\n await asyncDelayMsInterruptible(delayMs);\n await yieldToEventLoop();\n }\n }\n if (lastError instanceof Error) throw lastError;\n throw new Error(String(lastError));\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { isCliImmediateShutdownRequested } from '../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted, isCliSqliteLockError } from '../sqlite-errors.js';\nimport { logStaleSqliteLockIntervention } from '../sqlite-lock-path.js';\nimport { SYNC_RETRY_MAX, syncSleepMs } from '../sqlite-lock-retry.js';\nimport type { SqliteDatabaseAccessOptions } from '../database-access-types.js';\n\nexport function runSqliteWithSync<OpenOptions, T>(\n config: SqliteDatabaseAccessOptions<OpenOptions>,\n openConnection: (options?: OpenOptions) => Database,\n safeClose: (db: Database | null | undefined) => void,\n fn: (db: Database) => T,\n options?: OpenOptions,\n): T {\n for (let attempt = 1; attempt <= SYNC_RETRY_MAX; attempt++) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n let db: Database | undefined;\n try {\n db = openConnection(options);\n try {\n return fn(db);\n } finally {\n safeClose(db);\n }\n } catch (e) {\n safeClose(db);\n if (e instanceof CliSqliteInterrupted) throw e;\n if (!isCliSqliteLockError(e)) throw e;\n config.onLockRetry?.({\n dbPath: config.getPath(),\n attempt,\n maxAttempts: SYNC_RETRY_MAX,\n final: attempt === SYNC_RETRY_MAX,\n });\n if (attempt === SYNC_RETRY_MAX) {\n logStaleSqliteLockIntervention(config.getPath());\n throw e;\n }\n syncSleepMs(Math.min(500, 12 * attempt));\n }\n }\n throw new Error('withSqliteSync: exhausted retries');\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { removeSqliteLockPathIfPresent } from '../sqlite-lock-path.js';\nimport type { SqliteDatabaseAccess, SqliteDatabaseAccessOptions } from '../database-access-types.js';\nimport { ASYNC_PROBE_RETRY_MAX } from '../sqlite-lock-retry.js';\nimport { createSqliteMigrateState } from './bindings.js';\nimport { openSqliteConnection, safeCloseSqliteDatabase } from './open.js';\nimport { runSqliteWithAsync } from './with-async.js';\nimport { runSqliteWithSync } from './with-sync.js';\n\nexport type { SqliteDatabaseAccess, SqliteDatabaseAccessOptions } from '../database-access-types.js';\n\nexport function createSqliteDatabaseAccess<OpenOptions = void>(\n config: SqliteDatabaseAccessOptions<OpenOptions>,\n): SqliteDatabaseAccess<OpenOptions> {\n const migrateState = createSqliteMigrateState();\n\n function safeClose(db: Database | null | undefined): void {\n safeCloseSqliteDatabase(db);\n }\n\n function openConnection(options?: OpenOptions): Database {\n return openSqliteConnection(config, migrateState, options);\n }\n\n function withSync<T>(fn: (db: Database) => T, options?: OpenOptions): T {\n return runSqliteWithSync(config, openConnection, safeClose, fn, options);\n }\n\n async function withAsync<T>(\n fn: (db: Database) => T | Promise<T>,\n options?: OpenOptions,\n maxAttempts?: number,\n ): Promise<T> {\n return runSqliteWithAsync(config, openConnection, safeClose, fn, options, maxAttempts);\n }\n\n async function withAsyncProbe<T>(\n fn: (db: Database) => T | Promise<T>,\n options?: OpenOptions,\n ): Promise<T> {\n return runSqliteWithAsync(\n config,\n openConnection,\n safeClose,\n fn,\n options,\n ASYNC_PROBE_RETRY_MAX,\n );\n }\n\n async function ensureInitialized(options?: OpenOptions): Promise<void> {\n await withAsync(() => undefined, options);\n }\n\n function closeAllConnections(): void {\n migrateState.migrateDoneForPath = null;\n removeSqliteLockPathIfPresent(config.getPath());\n }\n\n return {\n safeClose,\n openConnection,\n withSync,\n withAsync,\n withAsyncProbe,\n ensureInitialized,\n closeAllConnections,\n };\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Read a migration SQL file. `searchSubdirs` are tried relative to this module and common dist layouts\n * (e.g. `migrations` for the main CLI DB, `code-nav-cache-migrations` for the cache DB).\n */\nexport function readMigrationSql(filename: string, ...searchSubdirs: string[]): string {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n const candidates = searchSubdirs.flatMap((sub) => [\n join(moduleDir, sub, filename),\n join(moduleDir, '..', sub, filename),\n join(moduleDir, '..', '..', 'dist', sub, filename),\n ]);\n const resolved = candidates.find((path) => existsSync(path));\n if (!resolved) {\n throw new Error(`Missing SQLite migration SQL: ${filename} (searched ${searchSubdirs.join(', ')})`);\n }\n return readFileSync(resolved, 'utf8');\n}\n\n/** @alias {@link readMigrationSql} with `migrations` search dir (main CLI DB). */\nexport function readCliSqliteMigrationSql(filename: string): string {\n return readMigrationSql(filename, 'migrations');\n}\n\n/** @alias {@link readMigrationSql} with code-nav cache migration search dirs. */\nexport function readCodeNavCacheMigrationSql(filename: string): string {\n return readMigrationSql(filename, 'code-nav-cache-migrations', 'code-nav-cache/migrations');\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport interface SqliteMigration {\n name: string;\n migrate: (db: Database) => void;\n alreadyApplied?: (db: Database) => boolean;\n checkpoint?: boolean;\n replacesLegacyMigrations?: readonly string[];\n}\n\nfunction checkpointSatisfiedByLegacyChain(\n applied: ReadonlySet<string>,\n replacesLegacyMigrations: readonly string[] | undefined,\n): boolean {\n return (\n Array.isArray(replacesLegacyMigrations) &&\n replacesLegacyMigrations.length > 0 &&\n replacesLegacyMigrations.every((n) => applied.has(n))\n );\n}\n\nfunction recordMigrationAndPruneCheckpointLegacy(\n db: Database,\n migration: SqliteMigration,\n applied: Set<string>,\n): void {\n db.run('INSERT INTO __migrations (name) VALUES (?)', [migration.name]);\n applied.add(migration.name);\n if (migration.checkpoint !== true) return;\n const legacy = migration.replacesLegacyMigrations;\n if (!legacy?.length) return;\n for (const legacyName of legacy) {\n if (legacyName === migration.name) continue;\n db.run('DELETE FROM __migrations WHERE name = ?', [legacyName]);\n applied.delete(legacyName);\n }\n}\n\nexport function runSqliteMigrations(\n db: Database,\n migrations: readonly SqliteMigration[],\n bootstrapSql: string,\n label: string,\n): void {\n db.exec(bootstrapSql);\n\n const appliedRows = db.all('SELECT name FROM __migrations') as Array<{ name: string }>;\n const applied = new Set(appliedRows.map((r) => r.name));\n\n for (const migration of migrations) {\n if (applied.has(migration.name)) continue;\n if (\n migration.checkpoint === true &&\n checkpointSatisfiedByLegacyChain(applied, migration.replacesLegacyMigrations)\n ) {\n recordMigrationAndPruneCheckpointLegacy(db, migration, applied);\n continue;\n }\n if (migration.alreadyApplied?.(db)) {\n recordMigrationAndPruneCheckpointLegacy(db, migration, applied);\n continue;\n }\n try {\n migration.migrate(db);\n recordMigrationAndPruneCheckpointLegacy(db, migration, applied);\n } catch (e) {\n console.error(`[${label}] Migration failed: ${migration.name}`, e);\n throw e;\n }\n }\n}\n", "/**\n * Versioned schema changes for the code-navigation cache SQLite DB (file index + symbol index).\n */\n\nimport type { Database } from 'node-sqlite3-wasm';\nimport { readCodeNavCacheMigrationSql } from '../read-migration-sql.js';\nimport { runSqliteMigrations, type SqliteMigration } from '../run-sqlite-migrations.js';\n\nexport type CodeNavCacheSqliteMigration = SqliteMigration;\n\nconst CHECKPOINT_V1 = '001_code_nav_cache_checkpoint_v1';\nconst CHECKPOINT_V1_SQL = readCodeNavCacheMigrationSql('001_code_nav_cache_checkpoint_v1.sql');\nconst MIGRATION_002 = '002_content_hash_symbol_index';\nconst MIGRATION_002_SQL = readCodeNavCacheMigrationSql('002_content_hash_symbol_index.sql');\nconst MIGRATION_003 = '003_content_hash_tag_rows';\nconst MIGRATION_003_SQL = readCodeNavCacheMigrationSql('003_content_hash_tag_rows.sql');\n\nexport const CODE_NAV_CACHE_SQLITE_MIGRATIONS: CodeNavCacheSqliteMigration[] = [\n {\n name: CHECKPOINT_V1,\n checkpoint: true,\n migrate: (db) => {\n db.exec(CHECKPOINT_V1_SQL);\n },\n alreadyApplied: (db) => {\n const row = db.get(\n `SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='file_index_parent_path' LIMIT 1`,\n ) as { ok: number } | null;\n return row != null;\n },\n },\n {\n name: MIGRATION_002,\n migrate: (db) => {\n db.exec(MIGRATION_002_SQL);\n },\n alreadyApplied: (db) => {\n const row = db.get(\n `SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_file_blob' LIMIT 1`,\n ) as { ok: number } | null;\n return row != null;\n },\n },\n {\n name: MIGRATION_003,\n migrate: (db) => {\n db.exec(MIGRATION_003_SQL);\n },\n alreadyApplied: (db) => {\n const row = db.get(\n `SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_index_tag' LIMIT 1`,\n ) as { ok: number } | null;\n if (row == null) return false;\n const blob = db.get(\n `SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='symbol_file_blob' LIMIT 1`,\n ) as { ok: number } | null;\n return blob == null;\n },\n },\n];\n\nexport function migrateCodeNavCacheSqlite(db: Database): void {\n runSqliteMigrations(\n db,\n CODE_NAV_CACHE_SQLITE_MIGRATIONS,\n readCodeNavCacheMigrationSql('000_bootstrap_migrations_table.sql'),\n 'code-nav-cache',\n );\n}\n", "import fs from 'node:fs';\nimport { getCodeNavCacheSqlitePath } from './code-nav-cache-paths.js';\n\nfunction isSqliteCorruptError(e: unknown): boolean {\n const msg = e instanceof Error ? e.message : String(e);\n return msg.includes('malformed') || msg.includes('database disk image is malformed') || msg.includes('corrupt');\n}\n\n/**\n * Serialize all code-nav-cache SQLite work (file index + symbol index) within this CLI process.\n * Reentrant: nested calls on the same async stack run inline without re-queuing (avoids deadlocks).\n */\nlet chain: Promise<unknown> = Promise.resolve();\nlet workLockDepth = 0;\n\nexport function resetCodeNavCacheSqliteWorkLock(): void {\n chain = Promise.resolve();\n workLockDepth = 0;\n}\n\nexport function withCodeNavCacheSqliteWorkLock<T>(fn: () => T | Promise<T>): Promise<T> {\n if (workLockDepth > 0) {\n return Promise.resolve(fn());\n }\n\n const run = async (): Promise<T> => {\n workLockDepth += 1;\n try {\n return await Promise.resolve(fn());\n } finally {\n workLockDepth = Math.max(0, workLockDepth - 1);\n }\n };\n\n const runWithCorruptRecovery = async (): Promise<T> => {\n try {\n return await run();\n } catch (e) {\n if (!isSqliteCorruptError(e)) throw e;\n try {\n fs.unlinkSync(getCodeNavCacheSqlitePath());\n } catch {\n /* ignore */\n }\n chain = Promise.resolve();\n return await run();\n }\n };\n\n const next = chain.then(runWithCorruptRecovery);\n chain = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { createSqliteDatabaseAccess } from '../access/index.js';\nimport { isCliSqliteLockError } from '../sqlite-errors.js';\nimport { ensureCodeNavCacheSqliteParentDir, getCodeNavCacheSqlitePath } from './code-nav-cache-paths.js';\nimport { migrateCodeNavCacheSqlite } from './migrate-code-nav-cache-sqlite.js';\nimport { reportCodeNavCacheLockContention } from './code-nav-cache-log.js';\nimport {\n resetCodeNavCacheSqliteWorkLock,\n withCodeNavCacheSqliteWorkLock,\n} from './code-nav-cache-sqlite-work-lock.js';\nimport {\n decrementCodeNavCacheAccessDepth,\n getCodeNavCacheAccessDepth,\n incrementCodeNavCacheAccessDepth,\n resetCodeNavCacheAccessDepth,\n waitForOuterCodeNavCacheAccessIfNeededAsync,\n waitForOuterCodeNavCacheAccessIfNeededSync,\n} from './code-nav-cache-access-depth.js';\n\nexport const codeNavCacheSqlite = createSqliteDatabaseAccess({\n getPath: getCodeNavCacheSqlitePath,\n ensureParentDir: ensureCodeNavCacheSqliteParentDir,\n migrate: migrateCodeNavCacheSqlite,\n onLockRetry: ({ attempt, maxAttempts, final }) => {\n if (attempt === 1 || final) {\n reportCodeNavCacheLockContention('SQLite open', { attempt, maxAttempts, final });\n }\n },\n});\n\nexport async function withCodeNavCacheSqliteWorkLockWrapped<T>(\n fn: (db: Database) => T | Promise<T>,\n): Promise<T> {\n return withCodeNavCacheSqliteWorkLock(async () => {\n const nested = getCodeNavCacheAccessDepth() > 0;\n await waitForOuterCodeNavCacheAccessIfNeededAsync(nested);\n incrementCodeNavCacheAccessDepth();\n try {\n return await codeNavCacheSqlite.withAsync(fn);\n } finally {\n decrementCodeNavCacheAccessDepth();\n }\n });\n}\n\nexport async function withCodeNavCacheSqliteWorkLockProbeWrapped<T>(\n fn: (db: Database) => T | Promise<T>,\n): Promise<T | undefined> {\n try {\n return await withCodeNavCacheSqliteWorkLock(async () => {\n const nested = getCodeNavCacheAccessDepth() > 0;\n await waitForOuterCodeNavCacheAccessIfNeededAsync(nested);\n incrementCodeNavCacheAccessDepth();\n try {\n return await codeNavCacheSqlite.withAsyncProbe(fn);\n } finally {\n decrementCodeNavCacheAccessDepth();\n }\n });\n } catch (e) {\n if (isCliSqliteLockError(e)) return undefined;\n throw e;\n }\n}\n\nexport function withCodeNavCacheSqliteSyncWrapped<T>(fn: (db: Database) => T): T {\n const nested = getCodeNavCacheAccessDepth() > 0;\n waitForOuterCodeNavCacheAccessIfNeededSync(nested);\n incrementCodeNavCacheAccessDepth();\n try {\n return codeNavCacheSqlite.withSync(fn);\n } finally {\n decrementCodeNavCacheAccessDepth();\n }\n}\n\nexport function closeAllCodeNavCacheSqliteConnections(): void {\n codeNavCacheSqlite.closeAllConnections();\n resetCodeNavCacheSqliteWorkLock();\n resetCodeNavCacheAccessDepth();\n}\n", "import { resetCliImmediateShutdownForTests } from '../../runtime/cli-process-interrupt.js';\nimport { resetSymbolIndexWorkerShutdownForTests } from '../../code-nav/symbol-index/worker/shutdown-state.js';\nimport { resetCodeNavCacheAvailabilityForTests } from './code-nav-cache-availability.js';\nimport { resetCodeNavCacheLogForTests } from './code-nav-cache-log.js';\nimport { resetCodeNavCacheAccessDepth } from './code-nav-cache-access-depth.js';\nimport {\n closeAllCodeNavCacheSqliteConnections,\n withCodeNavCacheSqliteSyncWrapped,\n withCodeNavCacheSqliteWorkLockProbeWrapped,\n withCodeNavCacheSqliteWorkLockWrapped,\n} from './code-nav-cache-wrapped-access.js';\n\nexport {\n codeNavCacheSqlite,\n closeAllCodeNavCacheSqliteConnections,\n withCodeNavCacheSqliteSyncWrapped,\n withCodeNavCacheSqliteWorkLockProbeWrapped,\n withCodeNavCacheSqliteWorkLockWrapped,\n} from './code-nav-cache-wrapped-access.js';\n\nexport function closeCodeNavCacheDatabaseForTests(): void {\n resetCliImmediateShutdownForTests();\n closeAllCodeNavCacheSqliteConnections();\n resetCodeNavCacheAccessDepth();\n resetCodeNavCacheAvailabilityForTests();\n resetCodeNavCacheLogForTests();\n resetSymbolIndexWorkerShutdownForTests();\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport {\n CodeNavCacheUnavailableError,\n getCodeNavCacheInitPromise,\n isCodeNavCacheUnavailable,\n} from './code-nav-cache-availability.js';\nimport {\n codeNavCacheSqlite,\n withCodeNavCacheSqliteSyncWrapped,\n withCodeNavCacheSqliteWorkLockProbeWrapped,\n withCodeNavCacheSqliteWorkLockWrapped,\n} from './instance.js';\n\nexport { CliSqliteInterrupted } from '../sqlite-errors.js';\n\nexport const safeCloseCodeNavCacheSqliteDatabase = codeNavCacheSqlite.safeClose;\n\nexport {\n closeAllCodeNavCacheSqliteConnections,\n closeCodeNavCacheDatabaseForTests,\n} from './instance.js';\n\nexport const openCodeNavCacheSqliteConnection = codeNavCacheSqlite.openConnection;\n\nexport async function withCodeNavCacheSqlite<T>(\n fn: (db: Database) => T | Promise<T>,\n): Promise<T> {\n if (isCodeNavCacheUnavailable()) throw new CodeNavCacheUnavailableError();\n const initPromise = getCodeNavCacheInitPromise();\n if (initPromise != null) {\n const ok = await initPromise;\n if (!ok) throw new CodeNavCacheUnavailableError();\n }\n\n return withCodeNavCacheSqliteWorkLockWrapped(fn);\n}\n\n/** Fast SQLite probe for interactive paths; returns undefined when locked or unavailable. */\nexport async function withCodeNavCacheSqliteProbe<T>(\n fn: (db: Database) => T | Promise<T>,\n): Promise<T | undefined> {\n if (isCodeNavCacheUnavailable()) return undefined;\n const initPromise = getCodeNavCacheInitPromise();\n if (initPromise != null) {\n const ok = await initPromise;\n if (!ok) return undefined;\n }\n\n return withCodeNavCacheSqliteWorkLockProbeWrapped(fn);\n}\n\n/**\n * Prefer {@link withCodeNavCacheSqlite}. Serialized with async access; reentrant on nested calls.\n */\nexport function withCodeNavCacheSqliteSync<T>(fn: (db: Database) => T): T {\n if (isCodeNavCacheUnavailable()) throw new CodeNavCacheUnavailableError();\n return withCodeNavCacheSqliteSyncWrapped(fn);\n}\n\nexport async function ensureCodeNavCacheSqliteInitialized(): Promise<void> {\n await codeNavCacheSqlite.withAsync(() => undefined);\n}\n\nexport { startCodeNavCacheInitialization, awaitCodeNavCacheInitialization } from './code-nav-cache-availability.js';\nexport { CodeNavCacheUnavailableError } from './code-nav-cache-availability.js';\n", "import fs from 'node:fs';\nimport path from 'node:path';\n\n/** Canonical absolute path for stable SQLite parent keys (resolves /private/var vs /var on macOS). */\nexport function normalizeResolvedPath(resolved: string): string {\n const abs = path.resolve(resolved);\n try {\n return fs.realpathSync.native(abs);\n } catch {\n return abs;\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport function runCodeNavCacheWriteTransaction<T>(db: Database, fn: () => T): T {\n db.run('BEGIN IMMEDIATE');\n try {\n const result = fn();\n db.run('COMMIT');\n return result;\n } catch (e) {\n try {\n db.run('ROLLBACK');\n } catch {\n /* ignore */\n }\n throw e;\n }\n}\n", "import { isCliImmediateShutdownRequested } from '../runtime/cli-process-interrupt.js';\nimport { yieldForBridgeInteractivePriority } from '../files/browser/in-flight.js';\nimport { CliSqliteInterrupted } from '../sqlite/code-nav-cache/database.js';\n\n/** Yield while walking, parsing, or resolving symbols (keeps bridge responsive). */\nexport const CODE_NAV_YIELD_EVERY = 64;\n\nexport type CodeNavYieldState = { n: number };\n\nexport function createCodeNavYieldState(): CodeNavYieldState {\n return { n: 0 };\n}\n\n/** Yield periodically and throw {@link CliSqliteInterrupted} when shutdown is requested. */\nexport async function yieldDuringCodeNavWork(state: CodeNavYieldState): Promise<void> {\n state.n++;\n if (state.n % CODE_NAV_YIELD_EVERY !== 0) return;\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n await yieldForBridgeInteractivePriority();\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\n/**\n * Path to the CLI's local SQLite database (WASM-backed).\n * Override with `BUILDAMATON_CLI_SQLITE_PATH` for tests or custom layouts.\n */\nexport function getCliSqlitePath(): string {\n const override = process.env.BUILDAMATON_CLI_SQLITE_PATH?.trim();\n if (override) return path.resolve(override);\n return path.join(os.homedir(), '.buildautomaton', 'cli.sqlite');\n}\n\nexport function ensureCliSqliteParentDir(sqlitePath: string): void {\n const dir = path.dirname(sqlitePath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n", "import path from 'node:path';\nimport os from 'node:os';\n\n/** Yield while walking paths or inserting rows (keeps bridge responsive). */\nexport const INDEX_WORK_YIELD_EVERY = 128;\n\nexport const INDEX_DIR = path.join(os.homedir(), '.buildautomaton');\nexport const INDEX_HASH_LEN = 16;\n", "import crypto from 'node:crypto';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst QUEUE_KEY_HEX_64 = /^[a-f0-9]{64}$/i;\n\n/**\n * Stable filename segment for a queue key: 64-char hex keys use as-is (lowercased);\n * other keys (e.g. legacy work-queue strings) use SHA-256 hex so paths stay safe and unique.\n * (Still used for tests and stable naming; queue state lives in CLI SQLite.)\n */\nexport function queueStateFileSlug(queueKey: string): string {\n if (QUEUE_KEY_HEX_64.test(queueKey)) return queueKey.toLowerCase();\n return crypto.createHash('sha256').update(queueKey, 'utf8').digest('hex');\n}\n\n/** `~/.buildautomaton/queues` \u2014 legacy JSON location (migration reads from here once). */\nexport function getPromptQueuesDirectory(): string {\n const override = process.env.BUILDAMATON_PROMPT_QUEUES_DIR?.trim();\n if (override) return path.resolve(override);\n return path.join(os.homedir(), '.buildautomaton', 'queues');\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { INDEX_DIR } from '../../files/index/constants.js';\n\n/** Pre-SQLite CLI files are moved here (not deleted) for easier testing / rollback. */\nexport const OLD_VERSION_DIR = path.join(INDEX_DIR, 'old-version');\n\nexport type LegacyArchiveCategory = 'file-index' | 'agent-sessions' | 'queues';\n\nexport function moveLegacyFileToOldVersionBackup(category: LegacyArchiveCategory, sourcePath: string): void {\n const destDir = path.join(OLD_VERSION_DIR, category);\n fs.mkdirSync(destDir, { recursive: true });\n const base = path.basename(sourcePath);\n let dest = path.join(destDir, base);\n if (fs.existsSync(dest)) {\n const ext = path.extname(base);\n const stem = ext ? base.slice(0, -ext.length) : base;\n dest = path.join(destDir, `${stem}-${Date.now()}${ext}`);\n }\n fs.renameSync(sourcePath, dest);\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { INDEX_DIR } from '../../files/index/constants.js';\nimport { moveLegacyFileToOldVersionBackup } from './archive-to-old-version.js';\n\n/** Move legacy `.file-index-*.json` from the BuildAutomaton data dir into `old-version/file-index/`. */\nexport function archiveLegacyFileIndexJsonFiles(): void {\n try {\n if (!fs.existsSync(INDEX_DIR)) return;\n for (const name of fs.readdirSync(INDEX_DIR)) {\n if (name.startsWith('.file-index-') && name.endsWith('.json')) {\n const full = path.join(INDEX_DIR, name);\n try {\n moveLegacyFileToOldVersionBackup('file-index', full);\n } catch (err) {\n console.error(`[cli-sqlite] legacy import: could not archive ${name}`, err);\n }\n }\n }\n } catch (e) {\n console.error('[cli-sqlite] legacy import: archive file-index json failed', e);\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport type { Database } from 'node-sqlite3-wasm';\nimport { moveLegacyFileToOldVersionBackup } from './archive-to-old-version.js';\n\nexport const LEGACY_AGENT_SESSION_DIR = path.join(os.homedir(), '.buildautomaton', 'agent-sessions');\n\n/** Import `~/.buildautomaton/agent-sessions/*.json` into `agent_session`, then archive each file. */\nexport function importLegacyAgentSessionsFromDisk(db: Database): void {\n try {\n if (!fs.existsSync(LEGACY_AGENT_SESSION_DIR)) return;\n const names = fs.readdirSync(LEGACY_AGENT_SESSION_DIR).filter((n) => n.endsWith('.json'));\n for (const name of names) {\n const sessionKey = name.slice(0, -'.json'.length);\n const full = path.join(LEGACY_AGENT_SESSION_DIR, name);\n let raw: string;\n try {\n raw = fs.readFileSync(full, 'utf8');\n } catch {\n continue;\n }\n let parsed: {\n v?: unknown;\n acpSessionId?: unknown;\n backendAgentType?: unknown;\n configOptions?: unknown;\n updatedAt?: unknown;\n };\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch {\n continue;\n }\n if (parsed.v !== 1) continue;\n const acpSessionId = typeof parsed.acpSessionId === 'string' ? parsed.acpSessionId : null;\n const backendAgentType = typeof parsed.backendAgentType === 'string' ? parsed.backendAgentType : null;\n const configOptionsJson =\n Array.isArray(parsed.configOptions) ? JSON.stringify(parsed.configOptions) : null;\n const updatedAt =\n typeof parsed.updatedAt === 'string' ? parsed.updatedAt : new Date().toISOString();\n db.run(\n `INSERT OR REPLACE INTO agent_session (session_key, acp_session_id, backend_agent_type, config_options_json, updated_at)\n VALUES (?, ?, ?, ?, ?)`,\n [sessionKey, acpSessionId, backendAgentType, configOptionsJson, updatedAt],\n );\n try {\n moveLegacyFileToOldVersionBackup('agent-sessions', full);\n } catch {\n /* ignore */\n }\n }\n } catch (e) {\n console.error('[cli-sqlite] legacy import: agent_sessions from disk failed', e);\n }\n}\n", "export type ParsedPersistedQueueFile = {\n queueKey: string;\n updatedAt: string;\n turns: unknown[];\n};\n\nexport function parsePersistedQueueFromJson(raw: string): ParsedPersistedQueueFile | null {\n try {\n const o = JSON.parse(raw) as Record<string, unknown>;\n const queueKey =\n typeof o.queueKey === 'string'\n ? o.queueKey\n : typeof o.queueKeyHash === 'string'\n ? o.queueKeyHash\n : null;\n if (!queueKey || typeof o.updatedAt !== 'string' || !Array.isArray(o.turns)) return null;\n return { queueKey, updatedAt: o.updatedAt, turns: o.turns };\n } catch {\n return null;\n }\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Database } from 'node-sqlite3-wasm';\nimport { getPromptQueuesDirectory } from '../../prompt-turn-queue/paths.js';\nimport { moveLegacyFileToOldVersionBackup } from './archive-to-old-version.js';\nimport { parsePersistedQueueFromJson } from './parse-persisted-queue-json.js';\n\n/** Import per-queue JSON from the legacy queues directory into `prompt_queue`, then archive each file. */\nexport function importLegacyPromptQueuesFromDisk(db: Database): void {\n try {\n const dir = getPromptQueuesDirectory();\n if (!fs.existsSync(dir)) return;\n for (const name of fs.readdirSync(dir)) {\n if (!name.endsWith('.json')) continue;\n const full = path.join(dir, name);\n let raw: string;\n try {\n raw = fs.readFileSync(full, 'utf8');\n } catch {\n continue;\n }\n const file = parsePersistedQueueFromJson(raw);\n if (!file) continue;\n db.run(\n `INSERT OR REPLACE INTO prompt_queue (queue_key, updated_at, turns_json) VALUES (?, ?, ?)`,\n [file.queueKey, file.updatedAt, JSON.stringify(file.turns)],\n );\n try {\n moveLegacyFileToOldVersionBackup('queues', full);\n } catch {\n /* ignore */\n }\n }\n } catch (e) {\n console.error('[cli-sqlite] legacy import: prompt queues from disk failed', e);\n }\n}\n", "/**\n * One-time style import from pre-SQLite on-disk layouts into an already-open, migrated CLI DB.\n * Runs after {@link migrateCliSqlite}; not part of `__migrations` (schema vs data separation).\n * Idempotent: missing dirs/files are skipped; safe to run on every open.\n */\n\nimport fs from 'node:fs';\nimport type { Database } from 'node-sqlite3-wasm';\nimport { INDEX_DIR } from '../../files/index/constants.js';\nimport type { LogFn } from '../../log.js';\nimport { getPromptQueuesDirectory } from '../../prompt-turn-queue/paths.js';\nimport { archiveLegacyFileIndexJsonFiles } from './archive-file-index-json.js';\nimport {\n importLegacyAgentSessionsFromDisk,\n LEGACY_AGENT_SESSION_DIR,\n} from './import-agent-sessions-from-disk.js';\nimport { importLegacyPromptQueuesFromDisk } from './import-prompt-queues-from-disk.js';\n\n/**\n * True when on-disk legacy JSON still exists that {@link importCliSqliteLegacyDiskData} will try to process.\n * Used to log migration start/finish only when that path actually runs.\n */\nexport function legacyCliDiskMigrationIsPending(): boolean {\n try {\n if (fs.existsSync(INDEX_DIR)) {\n for (const name of fs.readdirSync(INDEX_DIR)) {\n if (name.startsWith('.file-index-') && name.endsWith('.json')) return true;\n }\n }\n } catch {\n /* treat as no pending file-index legacy */\n }\n try {\n if (fs.existsSync(LEGACY_AGENT_SESSION_DIR)) {\n if (fs.readdirSync(LEGACY_AGENT_SESSION_DIR).some((n) => n.endsWith('.json'))) return true;\n }\n } catch {\n /* ignore */\n }\n try {\n const dir = getPromptQueuesDirectory();\n if (fs.existsSync(dir) && fs.readdirSync(dir).some((n) => n.endsWith('.json'))) return true;\n } catch {\n /* ignore */\n }\n return false;\n}\n\n/**\n * Import legacy JSON on disk into SQLite and archive originals under `~/.buildautomaton/old-version/`.\n * Call only after schema migrations have created the target tables.\n *\n * When `log` is set and legacy work is pending, logs one line before and one after the import steps.\n */\nexport function importCliSqliteLegacyDiskData(db: Database, log?: LogFn): void {\n const pending = legacyCliDiskMigrationIsPending();\n if (pending && log) {\n log('Migrating legacy on-disk CLI data to SQLite\u2026');\n }\n archiveLegacyFileIndexJsonFiles();\n importLegacyAgentSessionsFromDisk(db);\n importLegacyPromptQueuesFromDisk(db);\n if (pending && log) {\n log('Legacy on-disk CLI data migration finished.');\n }\n}\n", "/**\n * Versioned schema changes for the CLI local SQLite DB, modeled after {@link migrateDurableObject}\n * in `packages/durable-objects`: ordered migrations, `__migrations` bookkeeping, optional checkpoints.\n *\n * SQL lives under `./migrations/*.sql` (see {@link readCliSqliteMigrationSql}).\n * Legacy on-disk JSON \u2192 SQLite import is **not** done here; see `importCliSqliteLegacyDiskData` in\n * `legacy_migration/import-cli-legacy-disk-data.ts` after the DB is opened and migrations have run.\n */\n\nimport type { Database } from 'node-sqlite3-wasm';\nimport { readCliSqliteMigrationSql } from './read-migration-sql.js';\nimport { runSqliteMigrations, type SqliteMigration } from './run-sqlite-migrations.js';\n\nexport type CliSqliteMigration = SqliteMigration;\n\nconst CHECKPOINT_V1 = '001_cli_sqlite_checkpoint_v1';\n\nconst CHECKPOINT_V1_SQL = readCliSqliteMigrationSql('001_cli_sqlite_checkpoint_v1.sql');\nconst AGENT_CAPABILITIES_SQL = readCliSqliteMigrationSql('002_agent_capabilities.sql');\nconst DROP_CACHE_TABLES_SQL = readCliSqliteMigrationSql('006_drop_cache_tables.sql');\n\nfunction agentCapabilitiesTableState(db: Database): 'new' | 'legacy' | 'current' {\n const rows = db.all(\n `SELECT name FROM sqlite_master WHERE type='table' AND name IN ('agent_capabilities', 'agent_capability_cache')`,\n ) as Array<{ name: string }>;\n const names = new Set(rows.map((r) => r.name));\n if (names.has('agent_capabilities')) return 'current';\n if (names.has('agent_capability_cache')) return 'legacy';\n return 'new';\n}\n\nexport const CLI_SQLITE_MIGRATIONS: CliSqliteMigration[] = [\n {\n name: CHECKPOINT_V1,\n checkpoint: true,\n migrate: (db) => {\n db.exec(CHECKPOINT_V1_SQL);\n },\n },\n {\n name: '002_agent_capabilities',\n migrate: (db) => {\n const state = agentCapabilitiesTableState(db);\n if (state === 'current') return;\n if (state === 'legacy') {\n db.exec(`\n ALTER TABLE agent_capability_cache RENAME TO agent_capabilities;\n DROP INDEX IF EXISTS idx_agent_capability_cache_workspace;\n CREATE INDEX IF NOT EXISTS idx_agent_capabilities_workspace ON agent_capabilities(workspace_id);\n `);\n return;\n }\n db.exec(AGENT_CAPABILITIES_SQL);\n },\n alreadyApplied: (db) => agentCapabilitiesTableState(db) === 'current',\n },\n {\n name: '006_drop_cache_tables',\n migrate: (db) => {\n db.exec(DROP_CACHE_TABLES_SQL);\n },\n alreadyApplied: (db) => {\n const row = db.get(\n `SELECT 1 as ok FROM sqlite_master\n WHERE type='table' AND name IN ('file_index_parent_path', 'file_index_child_path', 'file_index_path')\n LIMIT 1`,\n ) as { ok: number } | null;\n return row == null;\n },\n },\n];\n\nexport function migrateCliSqlite(db: Database): void {\n runSqliteMigrations(\n db,\n CLI_SQLITE_MIGRATIONS,\n readCliSqliteMigrationSql('000_bootstrap_migrations_table.sql'),\n 'cli-sqlite',\n );\n}\n", "import type { LogFn } from '../log.js';\nimport { resetCliImmediateShutdownForTests } from '../runtime/cli-process-interrupt.js';\nimport { ensureCliSqliteParentDir, getCliSqlitePath } from './cli-sqlite-paths.js';\nimport { createSqliteDatabaseAccess } from './access/index.js';\nimport { importCliSqliteLegacyDiskData } from './legacy_migration/import-cli-legacy-disk-data.js';\nimport { migrateCliSqlite } from './migrate-cli-sqlite.js';\nexport { CliSqliteInterrupted, isCliSqliteLockError } from './sqlite-errors.js';\n\nexport type GetCliDatabaseOptions = {\n /** When opening the DB, emit start/finish lines around legacy disk import only if legacy files are pending. */\n logLegacyMigration?: LogFn;\n};\n\nlet legacyImportDoneForPath: string | null = null;\n\nconst cliSqlite = createSqliteDatabaseAccess<GetCliDatabaseOptions>({\n getPath: getCliSqlitePath,\n ensureParentDir: ensureCliSqliteParentDir,\n migrate: migrateCliSqlite,\n afterOpen: (db, options) => {\n const sqlitePath = getCliSqlitePath();\n if (legacyImportDoneForPath === sqlitePath) return;\n importCliSqliteLegacyDiskData(db, options?.logLegacyMigration);\n legacyImportDoneForPath = sqlitePath;\n },\n});\n\n/** Close a WASM SQLite handle without throwing (node-sqlite3-wasm can throw on double-close or bad state). */\nexport const safeCloseCliSqliteDatabase = cliSqlite.safeClose;\n\n/** No-op: fresh connection per access call. Kept for bridge shutdown, corrupt-index recovery, and tests. */\nexport function closeAllCliSqliteConnections(): void {\n legacyImportDoneForPath = null;\n cliSqlite.closeAllConnections();\n}\n\n/** @alias Vitest and callers that only need teardown semantics */\nexport function closeCliDatabaseForTests(): void {\n legacyImportDoneForPath = null;\n resetCliImmediateShutdownForTests();\n}\n\nexport const openCliSqliteConnection = cliSqlite.openConnection;\nexport const withCliSqliteSync = cliSqlite.withSync;\nexport const withCliSqlite = cliSqlite.withAsync;\nexport const ensureCliSqliteInitialized = cliSqlite.ensureInitialized;\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { yieldForBridgeInteractivePriority, fileBrowserReadInFlight, yieldUntilFileBrowserReadsIdle } from '../../files/browser/in-flight.js';\nimport { isCliImmediateShutdownRequested } from '../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../../sqlite/cli-database.js';\nimport { INDEX_WORK_YIELD_EVERY } from './constants.js';\n\nconst DEPENDENCY_INSTALL_DIR_NAMES = new Set([\n 'node_modules',\n 'bower_components',\n 'vendor',\n 'Pods',\n 'Carthage',\n 'DerivedData',\n '.yarn',\n '.pnpm-store',\n]);\n\n/** Skip dependency trees that should not be indexed for search. Hidden files are searchable. */\nexport function shouldSkipWorkspaceWalkEntry(name: string): boolean {\n return DEPENDENCY_INSTALL_DIR_NAMES.has(name);\n}\n\nexport function walkWorkspaceTreeSync(dir: string, baseDir: string, onFile: (relativePath: string) => void): void {\n let names: string[];\n try {\n names = fs.readdirSync(dir);\n } catch {\n return;\n }\n for (const name of names) {\n if (shouldSkipWorkspaceWalkEntry(name)) continue;\n const full = path.join(dir, name);\n let stat: fs.Stats;\n try {\n stat = fs.statSync(full);\n } catch {\n continue;\n }\n const relative = path.relative(baseDir, full).replace(/\\\\/g, '/');\n if (stat.isDirectory()) {\n walkWorkspaceTreeSync(full, baseDir, onFile);\n } else if (stat.isFile()) {\n onFile(relative);\n }\n }\n}\n\ninterface WalkYieldState {\n n: number;\n}\n\n/**\n * Recursive crawl like {@link walkWorkspaceTreeSync}, yielding every {@link INDEX_WORK_YIELD_EVERY}\n * filesystem entries so the event loop stays responsive during large trees.\n */\nexport async function walkWorkspaceTreeAsync(\n dir: string,\n baseDir: string,\n onFile: (relativePath: string) => void,\n state: WalkYieldState,\n): Promise<void> {\n let names: string[];\n try {\n names = await fs.promises.readdir(dir);\n } catch {\n return;\n }\n for (const name of names) {\n if (shouldSkipWorkspaceWalkEntry(name)) continue;\n if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n await yieldForBridgeInteractivePriority();\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n }\n if (fileBrowserReadInFlight()) {\n await yieldUntilFileBrowserReadsIdle();\n }\n state.n++;\n const full = path.join(dir, name);\n let stat: fs.Stats;\n try {\n stat = await fs.promises.stat(full);\n } catch {\n continue;\n }\n const relative = path.relative(baseDir, full).replace(/\\\\/g, '/');\n if (stat.isDirectory()) {\n await walkWorkspaceTreeAsync(full, baseDir, onFile, state);\n } else if (stat.isFile()) {\n onFile(relative);\n }\n }\n}\n\nexport function createWalkYieldState(): WalkYieldState {\n return { n: 0 };\n}\n", "// A simple implementation of make-array\nfunction makeArray (subject) {\n return Array.isArray(subject)\n ? subject\n : [subject]\n}\n\nconst UNDEFINED = undefined\nconst EMPTY = ''\nconst SPACE = ' '\nconst ESCAPE = '\\\\'\nconst REGEX_TEST_BLANK_LINE = /^\\s+$/\nconst REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\\\]|^)\\\\$/\nconst REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\\\!/\nconst REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\\\#/\nconst REGEX_SPLITALL_CRLF = /\\r?\\n/g\n\n// Invalid:\n// - /foo,\n// - ./foo,\n// - ../foo,\n// - .\n// - ..\n// Valid:\n// - .foo\nconst REGEX_TEST_INVALID_PATH = /^\\.{0,2}\\/|^\\.{1,2}$/\n\nconst REGEX_TEST_TRAILING_SLASH = /\\/$/\n\nconst SLASH = '/'\n\n// Do not use ternary expression here, since \"istanbul ignore next\" is buggy\nlet TMP_KEY_IGNORE = 'node-ignore'\n/* istanbul ignore else */\nif (typeof Symbol !== 'undefined') {\n TMP_KEY_IGNORE = Symbol.for('node-ignore')\n}\nconst KEY_IGNORE = TMP_KEY_IGNORE\n\nconst define = (object, key, value) => {\n Object.defineProperty(object, key, {value})\n return value\n}\n\nconst REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g\n\nconst RETURN_FALSE = () => false\n\n// Sanitize the range of a regular expression\n// The cases are complicated, see test cases for details\nconst sanitizeRange = range => range.replace(\n REGEX_REGEXP_RANGE,\n (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)\n ? match\n // Invalid range (out of order) which is ok for gitignore rules but\n // fatal for JavaScript regular expression, so eliminate it.\n : EMPTY\n)\n\n// See fixtures #59\nconst cleanRangeBackSlash = slashes => {\n const {length} = slashes\n return slashes.slice(0, length - length % 2)\n}\n\n// > If the pattern ends with a slash,\n// > it is removed for the purpose of the following description,\n// > but it would only find a match with a directory.\n// > In other words, foo/ will match a directory foo and paths underneath it,\n// > but will not match a regular file or a symbolic link foo\n// > (this is consistent with the way how pathspec works in general in Git).\n// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'\n// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call\n// you could use option `mark: true` with `glob`\n\n// '`foo/`' should not continue with the '`..`'\nconst REPLACERS = [\n\n [\n // Remove BOM\n // TODO:\n // Other similar zero-width characters?\n /^\\uFEFF/,\n () => EMPTY\n ],\n\n // > Trailing spaces are ignored unless they are quoted with backslash (\"\\\")\n [\n // (a\\ ) -> (a )\n // (a ) -> (a)\n // (a ) -> (a)\n // (a \\ ) -> (a )\n /((?:\\\\\\\\)*?)(\\\\?\\s+)$/,\n (_, m1, m2) => m1 + (\n m2.indexOf('\\\\') === 0\n ? SPACE\n : EMPTY\n )\n ],\n\n // Replace (\\ ) with ' '\n // (\\ ) -> ' '\n // (\\\\ ) -> '\\\\ '\n // (\\\\\\ ) -> '\\\\ '\n [\n /(\\\\+?)\\s/g,\n (_, m1) => {\n const {length} = m1\n return m1.slice(0, length - length % 2) + SPACE\n }\n ],\n\n // Escape metacharacters\n // which is written down by users but means special for regular expressions.\n\n // > There are 12 characters with special meanings:\n // > - the backslash \\,\n // > - the caret ^,\n // > - the dollar sign $,\n // > - the period or dot .,\n // > - the vertical bar or pipe symbol |,\n // > - the question mark ?,\n // > - the asterisk or star *,\n // > - the plus sign +,\n // > - the opening parenthesis (,\n // > - the closing parenthesis ),\n // > - and the opening square bracket [,\n // > - the opening curly brace {,\n // > These special characters are often called \"metacharacters\".\n [\n /[\\\\$.|*+(){^]/g,\n match => `\\\\${match}`\n ],\n\n [\n // > a question mark (?) matches a single character\n /(?!\\\\)\\?/g,\n () => '[^/]'\n ],\n\n // leading slash\n [\n\n // > A leading slash matches the beginning of the pathname.\n // > For example, \"/*.c\" matches \"cat-file.c\" but not \"mozilla-sha1/sha1.c\".\n // A leading slash matches the beginning of the pathname\n /^\\//,\n () => '^'\n ],\n\n // replace special metacharacter slash after the leading slash\n [\n /\\//g,\n () => '\\\\/'\n ],\n\n [\n // > A leading \"**\" followed by a slash means match in all directories.\n // > For example, \"**/foo\" matches file or directory \"foo\" anywhere,\n // > the same as pattern \"foo\".\n // > \"**/foo/bar\" matches file or directory \"bar\" anywhere that is directly\n // > under directory \"foo\".\n // Notice that the '*'s have been replaced as '\\\\*'\n /^\\^*\\\\\\*\\\\\\*\\\\\\//,\n\n // '**/foo' <-> 'foo'\n () => '^(?:.*\\\\/)?'\n ],\n\n // starting\n [\n // there will be no leading '/'\n // (which has been replaced by section \"leading slash\")\n // If starts with '**', adding a '^' to the regular expression also works\n /^(?=[^^])/,\n function startingReplacer () {\n // If has a slash `/` at the beginning or middle\n return !/\\/(?!$)/.test(this)\n // > Prior to 2.22.1\n // > If the pattern does not contain a slash /,\n // > Git treats it as a shell glob pattern\n // Actually, if there is only a trailing slash,\n // git also treats it as a shell glob pattern\n\n // After 2.22.1 (compatible but clearer)\n // > If there is a separator at the beginning or middle (or both)\n // > of the pattern, then the pattern is relative to the directory\n // > level of the particular .gitignore file itself.\n // > Otherwise the pattern may also match at any level below\n // > the .gitignore level.\n ? '(?:^|\\\\/)'\n\n // > Otherwise, Git treats the pattern as a shell glob suitable for\n // > consumption by fnmatch(3)\n : '^'\n }\n ],\n\n // two globstars\n [\n // Use lookahead assertions so that we could match more than one `'/**'`\n /\\\\\\/\\\\\\*\\\\\\*(?=\\\\\\/|$)/g,\n\n // Zero, one or several directories\n // should not use '*', or it will be replaced by the next replacer\n\n // Check if it is not the last `'/**'`\n (_, index, str) => index + 6 < str.length\n\n // case: /**/\n // > A slash followed by two consecutive asterisks then a slash matches\n // > zero or more directories.\n // > For example, \"a/**/b\" matches \"a/b\", \"a/x/b\", \"a/x/y/b\" and so on.\n // '/**/'\n ? '(?:\\\\/[^\\\\/]+)*'\n\n // case: /**\n // > A trailing `\"/**\"` matches everything inside.\n\n // #21: everything inside but it should not include the current folder\n : '\\\\/.+'\n ],\n\n // normal intermediate wildcards\n [\n // Never replace escaped '*'\n // ignore rule '\\*' will match the path '*'\n\n // 'abc.*/' -> go\n // 'abc.*' -> skip this rule,\n // coz trailing single wildcard will be handed by [trailing wildcard]\n /(^|[^\\\\]+)(\\\\\\*)+(?=.+)/g,\n\n // '*.js' matches '.js'\n // '*.js' doesn't match 'abc'\n (_, p1, p2) => {\n // 1.\n // > An asterisk \"*\" matches anything except a slash.\n // 2.\n // > Other consecutive asterisks are considered regular asterisks\n // > and will match according to the previous rules.\n const unescaped = p2.replace(/\\\\\\*/g, '[^\\\\/]*')\n return p1 + unescaped\n }\n ],\n\n [\n // unescape, revert step 3 except for back slash\n // For example, if a user escape a '\\\\*',\n // after step 3, the result will be '\\\\\\\\\\\\*'\n /\\\\\\\\\\\\(?=[$.|*+(){^])/g,\n () => ESCAPE\n ],\n\n [\n // '\\\\\\\\' -> '\\\\'\n /\\\\\\\\/g,\n () => ESCAPE\n ],\n\n [\n // > The range notation, e.g. [a-zA-Z],\n // > can be used to match one of the characters in a range.\n\n // `\\` is escaped by step 3\n /(\\\\)?\\[([^\\]/]*?)(\\\\*)($|\\])/g,\n (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE\n // '\\\\[bar]' -> '\\\\\\\\[bar\\\\]'\n ? `\\\\[${range}${cleanRangeBackSlash(endEscape)}${close}`\n : close === ']'\n ? endEscape.length % 2 === 0\n // A normal case, and it is a range notation\n // '[bar]'\n // '[bar\\\\\\\\]'\n ? `[${sanitizeRange(range)}${endEscape}]`\n // Invalid range notaton\n // '[bar\\\\]' -> '[bar\\\\\\\\]'\n : '[]'\n : '[]'\n ],\n\n // ending\n [\n // 'js' will not match 'js.'\n // 'ab' will not match 'abc'\n /(?:[^*])$/,\n\n // WTF!\n // https://git-scm.com/docs/gitignore\n // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)\n // which re-fixes #24, #38\n\n // > If there is a separator at the end of the pattern then the pattern\n // > will only match directories, otherwise the pattern can match both\n // > files and directories.\n\n // 'js*' will not match 'a.js'\n // 'js/' will not match 'a.js'\n // 'js' will match 'a.js' and 'a.js/'\n match => /\\/$/.test(match)\n // foo/ will not match 'foo'\n ? `${match}$`\n // foo matches 'foo' and 'foo/'\n : `${match}(?=$|\\\\/$)`\n ]\n]\n\nconst REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\\\\/)?\\\\\\*$/\nconst MODE_IGNORE = 'regex'\nconst MODE_CHECK_IGNORE = 'checkRegex'\nconst UNDERSCORE = '_'\n\nconst TRAILING_WILD_CARD_REPLACERS = {\n [MODE_IGNORE] (_, p1) {\n const prefix = p1\n // '\\^':\n // '/*' does not match EMPTY\n // '/*' does not match everything\n\n // '\\\\\\/':\n // 'abc/*' does not match 'abc/'\n ? `${p1}[^/]+`\n\n // 'a*' matches 'a'\n // 'a*' matches 'aa'\n : '[^/]*'\n\n return `${prefix}(?=$|\\\\/$)`\n },\n\n [MODE_CHECK_IGNORE] (_, p1) {\n // When doing `git check-ignore`\n const prefix = p1\n // '\\\\\\/':\n // 'abc/*' DOES match 'abc/' !\n ? `${p1}[^/]*`\n\n // 'a*' matches 'a'\n // 'a*' matches 'aa'\n : '[^/]*'\n\n return `${prefix}(?=$|\\\\/$)`\n }\n}\n\n// @param {pattern}\nconst makeRegexPrefix = pattern => REPLACERS.reduce(\n (prev, [matcher, replacer]) =>\n prev.replace(matcher, replacer.bind(pattern)),\n pattern\n)\n\nconst isString = subject => typeof subject === 'string'\n\n// > A blank line matches no files, so it can serve as a separator for readability.\nconst checkPattern = pattern => pattern\n && isString(pattern)\n && !REGEX_TEST_BLANK_LINE.test(pattern)\n && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)\n\n // > A line starting with # serves as a comment.\n && pattern.indexOf('#') !== 0\n\nconst splitPattern = pattern => pattern\n.split(REGEX_SPLITALL_CRLF)\n.filter(Boolean)\n\nclass IgnoreRule {\n constructor (\n pattern,\n mark,\n body,\n ignoreCase,\n negative,\n prefix\n ) {\n this.pattern = pattern\n this.mark = mark\n this.negative = negative\n\n define(this, 'body', body)\n define(this, 'ignoreCase', ignoreCase)\n define(this, 'regexPrefix', prefix)\n }\n\n get regex () {\n const key = UNDERSCORE + MODE_IGNORE\n\n if (this[key]) {\n return this[key]\n }\n\n return this._make(MODE_IGNORE, key)\n }\n\n get checkRegex () {\n const key = UNDERSCORE + MODE_CHECK_IGNORE\n\n if (this[key]) {\n return this[key]\n }\n\n return this._make(MODE_CHECK_IGNORE, key)\n }\n\n _make (mode, key) {\n const str = this.regexPrefix.replace(\n REGEX_REPLACE_TRAILING_WILDCARD,\n\n // It does not need to bind pattern\n TRAILING_WILD_CARD_REPLACERS[mode]\n )\n\n const regex = this.ignoreCase\n ? new RegExp(str, 'i')\n : new RegExp(str)\n\n return define(this, key, regex)\n }\n}\n\nconst createRule = ({\n pattern,\n mark\n}, ignoreCase) => {\n let negative = false\n let body = pattern\n\n // > An optional prefix \"!\" which negates the pattern;\n if (body.indexOf('!') === 0) {\n negative = true\n body = body.substr(1)\n }\n\n body = body\n // > Put a backslash (\"\\\") in front of the first \"!\" for patterns that\n // > begin with a literal \"!\", for example, `\"\\!important!.txt\"`.\n .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')\n // > Put a backslash (\"\\\") in front of the first hash for patterns that\n // > begin with a hash.\n .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#')\n\n const regexPrefix = makeRegexPrefix(body)\n\n return new IgnoreRule(\n pattern,\n mark,\n body,\n ignoreCase,\n negative,\n regexPrefix\n )\n}\n\nclass RuleManager {\n constructor (ignoreCase) {\n this._ignoreCase = ignoreCase\n this._rules = []\n }\n\n _add (pattern) {\n // #32\n if (pattern && pattern[KEY_IGNORE]) {\n this._rules = this._rules.concat(pattern._rules._rules)\n this._added = true\n return\n }\n\n if (isString(pattern)) {\n pattern = {\n pattern\n }\n }\n\n if (checkPattern(pattern.pattern)) {\n const rule = createRule(pattern, this._ignoreCase)\n this._added = true\n this._rules.push(rule)\n }\n }\n\n // @param {Array<string> | string | Ignore} pattern\n add (pattern) {\n this._added = false\n\n makeArray(\n isString(pattern)\n ? splitPattern(pattern)\n : pattern\n ).forEach(this._add, this)\n\n return this._added\n }\n\n // Test one single path without recursively checking parent directories\n //\n // - checkUnignored `boolean` whether should check if the path is unignored,\n // setting `checkUnignored` to `false` could reduce additional\n // path matching.\n // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`\n\n // @returns {TestResult} true if a file is ignored\n test (path, checkUnignored, mode) {\n let ignored = false\n let unignored = false\n let matchedRule\n\n this._rules.forEach(rule => {\n const {negative} = rule\n\n // | ignored : unignored\n // -------- | ---------------------------------------\n // negative | 0:0 | 0:1 | 1:0 | 1:1\n // -------- | ------- | ------- | ------- | --------\n // 0 | TEST | TEST | SKIP | X\n // 1 | TESTIF | SKIP | TEST | X\n\n // - SKIP: always skip\n // - TEST: always test\n // - TESTIF: only test if checkUnignored\n // - X: that never happen\n if (\n unignored === negative && ignored !== unignored\n || negative && !ignored && !unignored && !checkUnignored\n ) {\n return\n }\n\n const matched = rule[mode].test(path)\n\n if (!matched) {\n return\n }\n\n ignored = !negative\n unignored = negative\n\n matchedRule = negative\n ? UNDEFINED\n : rule\n })\n\n const ret = {\n ignored,\n unignored\n }\n\n if (matchedRule) {\n ret.rule = matchedRule\n }\n\n return ret\n }\n}\n\nconst throwError = (message, Ctor) => {\n throw new Ctor(message)\n}\n\nconst checkPath = (path, originalPath, doThrow) => {\n if (!isString(path)) {\n return doThrow(\n `path must be a string, but got \\`${originalPath}\\``,\n TypeError\n )\n }\n\n // We don't know if we should ignore EMPTY, so throw\n if (!path) {\n return doThrow(`path must not be empty`, TypeError)\n }\n\n // Check if it is a relative path\n if (checkPath.isNotRelative(path)) {\n const r = '`path.relative()`d'\n return doThrow(\n `path should be a ${r} string, but got \"${originalPath}\"`,\n RangeError\n )\n }\n\n return true\n}\n\nconst isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path)\n\ncheckPath.isNotRelative = isNotRelative\n\n// On windows, the following function will be replaced\n/* istanbul ignore next */\ncheckPath.convert = p => p\n\n\nclass Ignore {\n constructor ({\n ignorecase = true,\n ignoreCase = ignorecase,\n allowRelativePaths = false\n } = {}) {\n define(this, KEY_IGNORE, true)\n\n this._rules = new RuleManager(ignoreCase)\n this._strictPathCheck = !allowRelativePaths\n this._initCache()\n }\n\n _initCache () {\n // A cache for the result of `.ignores()`\n this._ignoreCache = Object.create(null)\n\n // A cache for the result of `.test()`\n this._testCache = Object.create(null)\n }\n\n add (pattern) {\n if (this._rules.add(pattern)) {\n // Some rules have just added to the ignore,\n // making the behavior changed,\n // so we need to re-initialize the result cache\n this._initCache()\n }\n\n return this\n }\n\n // legacy\n addPattern (pattern) {\n return this.add(pattern)\n }\n\n // @returns {TestResult}\n _test (originalPath, cache, checkUnignored, slices) {\n const path = originalPath\n // Supports nullable path\n && checkPath.convert(originalPath)\n\n checkPath(\n path,\n originalPath,\n this._strictPathCheck\n ? throwError\n : RETURN_FALSE\n )\n\n return this._t(path, cache, checkUnignored, slices)\n }\n\n checkIgnore (path) {\n // If the path doest not end with a slash, `.ignores()` is much equivalent\n // to `git check-ignore`\n if (!REGEX_TEST_TRAILING_SLASH.test(path)) {\n return this.test(path)\n }\n\n const slices = path.split(SLASH).filter(Boolean)\n slices.pop()\n\n if (slices.length) {\n const parent = this._t(\n slices.join(SLASH) + SLASH,\n this._testCache,\n true,\n slices\n )\n\n if (parent.ignored) {\n return parent\n }\n }\n\n return this._rules.test(path, false, MODE_CHECK_IGNORE)\n }\n\n _t (\n // The path to be tested\n path,\n\n // The cache for the result of a certain checking\n cache,\n\n // Whether should check if the path is unignored\n checkUnignored,\n\n // The path slices\n slices\n ) {\n if (path in cache) {\n return cache[path]\n }\n\n if (!slices) {\n // path/to/a.js\n // ['path', 'to', 'a.js']\n slices = path.split(SLASH).filter(Boolean)\n }\n\n slices.pop()\n\n // If the path has no parent directory, just test it\n if (!slices.length) {\n return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE)\n }\n\n const parent = this._t(\n slices.join(SLASH) + SLASH,\n cache,\n checkUnignored,\n slices\n )\n\n // If the path contains a parent directory, check the parent first\n return cache[path] = parent.ignored\n // > It is not possible to re-include a file if a parent directory of\n // > that file is excluded.\n ? parent\n : this._rules.test(path, checkUnignored, MODE_IGNORE)\n }\n\n ignores (path) {\n return this._test(path, this._ignoreCache, false).ignored\n }\n\n createFilter () {\n return path => !this.ignores(path)\n }\n\n filter (paths) {\n return makeArray(paths).filter(this.createFilter())\n }\n\n // @returns {TestResult}\n test (path) {\n return this._test(path, this._testCache, true)\n }\n}\n\nconst factory = options => new Ignore(options)\n\nconst isPathValid = path =>\n checkPath(path && checkPath.convert(path), path, RETURN_FALSE)\n\n/* istanbul ignore next */\nconst setupWindows = () => {\n /* eslint no-control-regex: \"off\" */\n const makePosix = str => /^\\\\\\\\\\?\\\\/.test(str)\n || /[\"<>|\\u0000-\\u001F]+/u.test(str)\n ? str\n : str.replace(/\\\\/g, '/')\n\n checkPath.convert = makePosix\n\n // 'C:\\\\foo' <- 'C:\\\\foo' has been converted to 'C:/'\n // 'd:\\\\foo'\n const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\\//i\n checkPath.isNotRelative = path =>\n REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path)\n || isNotRelative(path)\n}\n\n\n// Windows\n// --------------------------------------------------------------\n/* istanbul ignore next */\nif (\n // Detect `process` so that it can run in browsers.\n typeof process !== 'undefined'\n && process.platform === 'win32'\n) {\n setupWindows()\n}\n\n// COMMONJS_EXPORTS ////////////////////////////////////////////////////////////\n\nmodule.exports = factory\n\n// Although it is an anti-pattern,\n// it is still widely misused by a lot of libraries in github\n// Ref: https://github.com/search?q=ignore.default%28%29&type=code\nfactory.default = factory\n\nmodule.exports.isPathValid = isPathValid\n\n// For testing purposes\ndefine(module.exports, Symbol.for('setupWindows'), setupWindows)\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport ignore, { type Ignore } from 'ignore';\n\ntype IgnoreLayer = {\n dirRel: string;\n ig: Ignore;\n};\n\nconst DEFAULT_IGNORED = ['.git', '.git/**'];\n\nfunction normalizeRelPath(relPath: string): string {\n return relPath.replace(/\\\\/g, '/');\n}\n\nexport class GitignoreFilter {\n private layers: IgnoreLayer[] = [{ dirRel: '', ig: ignore().add(DEFAULT_IGNORED) }];\n\n /** Load `.gitignore` in `absDir` and push a layer when the file exists. */\n async enterDirectory(absDir: string, dirRel: string): Promise<void> {\n try {\n const content = await fs.promises.readFile(path.join(absDir, '.gitignore'), 'utf8');\n this.layers.push({ dirRel, ig: ignore().add(content) });\n } catch {\n /* no .gitignore in this directory */\n }\n }\n\n /** Pop the ignore layer for `dirRel` when leaving that directory during a walk. */\n leaveDirectory(dirRel: string): void {\n const top = this.layers[this.layers.length - 1];\n if (top != null && top.dirRel === dirRel) {\n this.layers.pop();\n }\n }\n\n isIgnored(relPath: string, opts?: { directory?: boolean }): boolean {\n const normalized = normalizeRelPath(relPath);\n const checkPath =\n opts?.directory && !normalized.endsWith('/') ? `${normalized}/` : normalized;\n\n for (const layer of this.layers) {\n if (layer.dirRel !== '' && !isUnderDir(normalized, layer.dirRel)) continue;\n const local = layer.dirRel === '' ? checkPath : checkPath.slice(layer.dirRel.length + 1);\n if (local !== '' && layer.ig.ignores(local)) return true;\n }\n return false;\n }\n}\n\nfunction isUnderDir(relPath: string, dirRel: string): boolean {\n return relPath === dirRel || relPath.startsWith(`${dirRel}/`);\n}\n\n/** Build an ignore filter from root through the parent directories of `relPath`. */\nexport async function createGitignoreFilterForRelativePath(\n root: string,\n relPath: string,\n): Promise<GitignoreFilter> {\n const filter = new GitignoreFilter();\n await filter.enterDirectory(root, '');\n\n const dirRel = normalizeRelPath(path.dirname(relPath));\n if (dirRel === '.' || dirRel === '') return filter;\n\n let abs = root;\n let rel = '';\n for (const segment of dirRel.split('/')) {\n abs = path.join(abs, segment);\n rel = rel ? `${rel}/${segment}` : segment;\n await filter.enterDirectory(abs, rel);\n }\n return filter;\n}\n\nexport async function isPathGitIgnored(root: string, relPath: string): Promise<boolean> {\n const normalized = normalizeRelPath(relPath);\n const filter = await createGitignoreFilterForRelativePath(root, normalized);\n return filter.isIgnored(normalized);\n}\n", "import path from 'node:path';\n\nexport type CodeNavLanguageSpec = {\n wasmFile: string;\n tagsQueryFile: string;\n};\n\nconst EXT_TO_LANGUAGE_KEY: Record<string, string> = {\n js: 'javascript',\n jsx: 'javascript',\n mjs: 'javascript',\n cjs: 'javascript',\n ts: 'typescript',\n tsx: 'tsx',\n py: 'python',\n go: 'go',\n rs: 'rust',\n rb: 'ruby',\n java: 'java',\n c: 'c',\n h: 'c',\n cpp: 'cpp',\n cc: 'cpp',\n cxx: 'cpp',\n hpp: 'cpp',\n};\n\nfunction languageAssetPaths(key: string, wasmFile: string): CodeNavLanguageSpec {\n return {\n wasmFile,\n tagsQueryFile: `tree-sitter-${key}/tags.scm`,\n };\n}\n\nconst LANGUAGE_SPECS: Record<string, CodeNavLanguageSpec> = {\n javascript: languageAssetPaths('javascript', 'tree-sitter-javascript.wasm'),\n typescript: languageAssetPaths('typescript', 'tree-sitter-typescript.wasm'),\n tsx: languageAssetPaths('typescript', 'tree-sitter-tsx.wasm'),\n python: languageAssetPaths('python', 'tree-sitter-python.wasm'),\n go: languageAssetPaths('go', 'tree-sitter-go.wasm'),\n rust: languageAssetPaths('rust', 'tree-sitter-rust.wasm'),\n ruby: languageAssetPaths('ruby', 'tree-sitter-ruby.wasm'),\n java: languageAssetPaths('java', 'tree-sitter-java.wasm'),\n c: languageAssetPaths('c', 'tree-sitter-c.wasm'),\n cpp: languageAssetPaths('cpp', 'tree-sitter-cpp.wasm'),\n};\n\nexport function getLanguageKeyForFilePath(filePath: string): string | null {\n const ext = path.extname(filePath).replace(/^\\./, '').toLowerCase();\n if (!ext) return null;\n return EXT_TO_LANGUAGE_KEY[ext] ?? null;\n}\n\nexport function getLanguageSpec(languageKey: string): CodeNavLanguageSpec | null {\n return LANGUAGE_SPECS[languageKey] ?? null;\n}\n\nexport function isCodeNavSupportedPath(filePath: string): boolean {\n const key = getLanguageKeyForFilePath(filePath);\n return key != null && getLanguageSpec(key) != null;\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport {\n createWalkYieldState,\n shouldSkipWorkspaceWalkEntry,\n} from '../files/index/walk-workspace-tree.js';\nimport {\n fileBrowserReadInFlight,\n yieldForBridgeInteractivePriority,\n yieldUntilFileBrowserReadsIdle,\n} from '../files/browser/in-flight.js';\nimport { isCliImmediateShutdownRequested } from '../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../sqlite/cli-database.js';\nimport { INDEX_WORK_YIELD_EVERY } from '../files/index/constants.js';\nimport { GitignoreFilter } from './gitignore-filter.js';\nimport { isCodeNavSupportedPath } from './language-registry.js';\n\ntype WalkYieldState = ReturnType<typeof createWalkYieldState>;\n\nexport { createWalkYieldState };\n\nasync function walkCodeNavFilesInDirectory(\n dir: string,\n baseDir: string,\n relDir: string,\n filter: GitignoreFilter,\n onFile: (relativePath: string) => void | Promise<void>,\n state: WalkYieldState,\n): Promise<void> {\n await filter.enterDirectory(dir, relDir);\n\n let names: string[];\n try {\n names = await fs.promises.readdir(dir);\n } catch {\n filter.leaveDirectory(relDir);\n return;\n }\n\n for (const name of names) {\n if (shouldSkipWorkspaceWalkEntry(name)) continue;\n if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n await yieldForBridgeInteractivePriority();\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n }\n if (fileBrowserReadInFlight()) {\n await yieldUntilFileBrowserReadsIdle();\n }\n state.n++;\n\n const relPath = relDir ? `${relDir}/${name}` : name;\n const full = path.join(dir, name);\n let stat: fs.Stats;\n try {\n stat = await fs.promises.stat(full);\n } catch {\n continue;\n }\n\n if (stat.isDirectory()) {\n if (filter.isIgnored(relPath, { directory: true })) continue;\n await walkCodeNavFilesInDirectory(full, baseDir, relPath, filter, onFile, state);\n continue;\n }\n\n if (!stat.isFile()) continue;\n if (filter.isIgnored(relPath)) continue;\n if (!isCodeNavSupportedPath(relPath)) continue;\n await Promise.resolve(onFile(relPath));\n }\n\n filter.leaveDirectory(relDir);\n}\n\nexport async function walkCodeNavFilesAsync(\n rootDir: string,\n onFile: (relativePath: string) => void | Promise<void>,\n state: WalkYieldState = createWalkYieldState(),\n): Promise<void> {\n const resolved = path.resolve(rootDir);\n const filter = new GitignoreFilter();\n await walkCodeNavFilesInDirectory(resolved, resolved, '', filter, onFile, state);\n}\n", "export const SYMBOL_INDEX_VERSION = 11;\n", "import * as path from 'node:path';\nimport { normalizeResolvedPath } from '../../paths/normalize-resolved-path.js';\n\n/**\n * **Bridge root**: directory the bridge uses for git repos, skills, file index, and `bridge_root` sessions.\n * Defaults to where the CLI was started, then `process.chdir` from `--bridge-root` / legacy `--cwd`.\n *\n * Call {@link initBridgeRoot} once at startup after applying those options so all bridge paths agree.\n */\nlet bridgeRootPath: string | null = null;\n\n/** Capture `process.cwd()` after startup / `chdir` (idempotent). */\nexport function initBridgeRoot(): void {\n bridgeRootPath = normalizeResolvedPath(process.cwd());\n}\n\n/**\n * Absolute bridge root. Prefer {@link initBridgeRoot} at startup; otherwise falls back to `process.cwd()`\n * (e.g. tests).\n */\nexport function getBridgeRoot(): string {\n if (bridgeRootPath == null) {\n bridgeRootPath = normalizeResolvedPath(process.cwd());\n }\n return bridgeRootPath;\n}\n\n/** Test-only: clear cached bridge root so `initBridgeRoot` can rebind cwd. */\nexport function resetBridgeRootForTests(): void {\n bridgeRootPath = null;\n}\n", "import path from 'node:path';\nimport crypto from 'node:crypto';\nimport { INDEX_HASH_LEN } from './constants.js';\n\n/** Stable short hash for a file-index parent path (matches legacy JSON index hash length). */\nexport function getCwdHashForFileIndex(resolvedCwd: string): string {\n return crypto.createHash('sha256').update(path.resolve(resolvedCwd)).digest('hex').slice(0, INDEX_HASH_LEN);\n}\n", "import { getBridgeRoot } from '../../../files/cwd/bridge-root.js';\nimport { getCwdHashForFileIndex } from '../../../files/index/paths.js';\nimport { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport type { Database } from 'node-sqlite3-wasm';\nimport type { SymbolIndexParentContext } from '../storage/parent-context.js';\nimport { withCodeNavCacheSqliteSync } from '../../../sqlite/code-nav-cache/database.js';\nimport { SYMBOL_INDEX_VERSION } from './symbol-index-version.js';\n\nexport type SymbolIndexParentRow = SymbolIndexParentContext & {\n path: string;\n};\n\nfunction normalizeParentPath(resolved: string): string {\n return normalizeResolvedPath(resolved);\n}\n\nfunction resolveParentKind(resolved: string): 'base' | 'overlay' {\n return normalizeParentPath(resolved) === normalizeParentPath(getBridgeRoot()) ? 'base' : 'overlay';\n}\n\nfunction ensureBaseParentId(db: Database): number {\n const bridgeRoot = normalizeParentPath(getBridgeRoot());\n const existing = db.get('SELECT id FROM symbol_index_parent_path WHERE path = ?', [bridgeRoot]) as\n | { id: number | bigint }\n | null;\n if (existing != null) return Number(existing.id);\n return upsertSymbolIndexParentPath(db, bridgeRoot);\n}\n\nexport function upsertSymbolIndexParentPath(db: Database, resolved: string): number {\n const normalized = normalizeParentPath(resolved);\n const now = new Date().toISOString();\n const kind = resolveParentKind(normalized);\n const baseParentId = kind === 'overlay' ? ensureBaseParentId(db) : null;\n\n db.run(\n `INSERT INTO symbol_index_parent_path (path, path_hash, updated_at, index_version, kind, base_parent_id)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(path) DO UPDATE SET\n path_hash = excluded.path_hash,\n updated_at = excluded.updated_at,\n index_version = excluded.index_version,\n kind = excluded.kind,\n base_parent_id = excluded.base_parent_id`,\n [normalized, getCwdHashForFileIndex(normalized), now, SYMBOL_INDEX_VERSION, kind, baseParentId],\n );\n const row = db.get('SELECT id FROM symbol_index_parent_path WHERE path = ?', [normalized]) as\n | { id: number | bigint }\n | null;\n if (row == null) throw new Error(`Failed to upsert symbol index parent path: ${normalized}`);\n return Number(row.id);\n}\n\nfunction rowToSymbolIndexParentContext(\n row: { id: number | bigint; path: string; kind: 'base' | 'overlay'; base_parent_id: number | bigint | null },\n): SymbolIndexParentRow {\n return {\n parentId: Number(row.id),\n path: row.path,\n kind: row.kind,\n baseParentId: row.base_parent_id != null ? Number(row.base_parent_id) : null,\n };\n}\n\nexport function getSymbolIndexParentContextById(db: Database, parentId: number): SymbolIndexParentRow | null {\n const row = db.get(\n `SELECT id, path, kind, base_parent_id\n FROM symbol_index_parent_path\n WHERE id = ?`,\n [parentId],\n ) as\n | { id: number | bigint; path: string; kind: 'base' | 'overlay'; base_parent_id: number | bigint | null }\n | null;\n if (row == null) return null;\n return rowToSymbolIndexParentContext(row);\n}\n\nexport function getSymbolIndexParentContext(db: Database, resolvedParentPath: string): SymbolIndexParentRow | null {\n const row = db.get(\n `SELECT id, path, kind, base_parent_id\n FROM symbol_index_parent_path\n WHERE path = ?`,\n [normalizeParentPath(resolvedParentPath)],\n ) as\n | { id: number | bigint; path: string; kind: 'base' | 'overlay'; base_parent_id: number | bigint | null }\n | null;\n if (row == null) return null;\n return rowToSymbolIndexParentContext(row);\n}\n\nexport function getSymbolIndexParentId(resolvedParentPath: string): number | null {\n return withCodeNavCacheSqliteSync((db) => {\n const ctx = getSymbolIndexParentContext(db, resolvedParentPath);\n return ctx?.parentId ?? null;\n });\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport function contentHashFileHasTags(db: Database, contentHash: string, filePath: string): boolean {\n const row = db.get(\n 'SELECT 1 as ok FROM symbol_index_tag WHERE content_hash = ? AND file_path = ? LIMIT 1',\n [contentHash, filePath],\n ) as { ok: number } | null;\n return row != null;\n}\n\nexport function contentHashFileHasImports(db: Database, contentHash: string, filePath: string): boolean {\n const row = db.get(\n 'SELECT 1 as ok FROM symbol_index_import WHERE content_hash = ? AND file_path = ? LIMIT 1',\n [contentHash, filePath],\n ) as { ok: number } | null;\n return row != null;\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\n\nexport function insertSymbolTagsForContent(\n db: Database,\n contentHash: string,\n filePath: string,\n tags: readonly SymbolTag[],\n): void {\n const ins = db.prepare(\n `INSERT OR IGNORE INTO symbol_index_tag\n (content_hash, file_path, name, role, kind, start_line, start_column, end_line, end_column,\n scope_start_line, scope_start_column, parent_scope_start_line, parent_scope_start_column,\n nav_target_path, scope_chain)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n );\n try {\n for (const tag of tags) {\n ins.run([\n contentHash,\n filePath,\n tag.name,\n tag.role,\n tag.kind,\n tag.startLine,\n tag.startColumn,\n tag.endLine,\n tag.endColumn,\n tag.scopeStartLine ?? null,\n tag.scopeStartColumn ?? null,\n tag.parentScopeStartLine ?? null,\n tag.parentScopeStartColumn ?? null,\n tag.navTargetPath ?? null,\n tag.scopeChain ?? null,\n ]);\n }\n } finally {\n ins.finalize();\n }\n}\n\nexport function insertSymbolImportsForContent(\n db: Database,\n contentHash: string,\n filePath: string,\n imports: readonly SymbolImportBinding[],\n): void {\n const ins = db.prepare(\n `INSERT OR IGNORE INTO symbol_index_import\n (content_hash, file_path, local_name, source_name, module_specifier, source_file_path, import_kind, start_line, start_column)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n );\n try {\n for (const binding of imports) {\n ins.run([\n contentHash,\n filePath,\n binding.localName,\n binding.sourceName,\n binding.moduleSpecifier,\n binding.sourceFilePath,\n binding.importKind,\n binding.startLine,\n binding.startColumn,\n ]);\n }\n } finally {\n ins.finalize();\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\n\nexport function getParentFileMapHash(\n db: Database,\n parentId: number,\n filePath: string,\n): string | null | undefined {\n const row = db.get(\n 'SELECT content_hash FROM symbol_parent_file_map WHERE parent_id = ? AND file_path = ?',\n [parentId, filePath],\n ) as { content_hash: string | null } | null;\n if (row == null) return undefined;\n return row.content_hash;\n}\n\nexport function countParentFileMapRefs(db: Database, contentHash: string): number {\n const row = db.get('SELECT COUNT(*) as n FROM symbol_parent_file_map WHERE content_hash = ?', [\n contentHash,\n ]) as { n: number | bigint };\n return Number(row.n);\n}\n\nexport function setParentFileMapEntry(\n db: Database,\n parentId: number,\n filePath: string,\n contentHash: string | null,\n): string | null {\n const previous = getParentFileMapHash(db, parentId, filePath);\n if (contentHash == null) {\n db.run(\n `INSERT INTO symbol_parent_file_map (parent_id, file_path, content_hash)\n VALUES (?, ?, NULL)\n ON CONFLICT(parent_id, file_path) DO UPDATE SET content_hash = NULL`,\n [parentId, filePath],\n );\n } else {\n db.run(\n `INSERT INTO symbol_parent_file_map (parent_id, file_path, content_hash)\n VALUES (?, ?, ?)\n ON CONFLICT(parent_id, file_path) DO UPDATE SET content_hash = excluded.content_hash`,\n [parentId, filePath, contentHash],\n );\n }\n return previous === undefined ? null : previous;\n}\n\nexport function removeParentFileMapEntry(db: Database, parentId: number, filePath: string): string | null {\n const previous = getParentFileMapHash(db, parentId, filePath);\n db.run('DELETE FROM symbol_parent_file_map WHERE parent_id = ? AND file_path = ?', [parentId, filePath]);\n return previous === undefined ? null : previous;\n}\n\nexport function clearParentFileMap(db: Database, parentId: number): string[] {\n const rows = db.all('SELECT content_hash FROM symbol_parent_file_map WHERE parent_id = ? AND content_hash IS NOT NULL', [\n parentId,\n ]) as Array<{ content_hash: string }>;\n db.run('DELETE FROM symbol_parent_file_map WHERE parent_id = ?', [parentId]);\n return rows.map((row) => row.content_hash);\n}\n\nexport function clearParentFileMapBatch(\n db: Database,\n parentId: number,\n limit: number,\n): { released: string[]; remaining: boolean } {\n const rows = db.all(\n `SELECT file_path, content_hash\n FROM symbol_parent_file_map\n WHERE parent_id = ?\n LIMIT ?`,\n [parentId, limit],\n ) as Array<{ file_path: string; content_hash: string | null }>;\n if (rows.length === 0) return { released: [], remaining: false };\n\n const del = db.prepare('DELETE FROM symbol_parent_file_map WHERE parent_id = ? AND file_path = ?');\n try {\n for (const row of rows) {\n del.run([parentId, row.file_path]);\n }\n } finally {\n del.finalize();\n }\n\n return {\n released: rows.flatMap((row) => (row.content_hash == null ? [] : [row.content_hash])),\n remaining: rows.length >= limit,\n };\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport { contentHashFileHasImports, contentHashFileHasTags } from './content-hash-check.js';\nimport { insertSymbolImportsForContent, insertSymbolTagsForContent } from './insert-symbol-content.js';\nimport { countParentFileMapRefs } from './parent-file-map.js';\n\nexport function upsertSymbolContentIndex(\n db: Database,\n contentHash: string,\n filePath: string,\n tags: readonly SymbolTag[],\n imports: readonly SymbolImportBinding[],\n): void {\n if (tags.length > 0 && !contentHashFileHasTags(db, contentHash, filePath)) {\n insertSymbolTagsForContent(db, contentHash, filePath, tags);\n }\n if (imports.length > 0 && !contentHashFileHasImports(db, contentHash, filePath)) {\n insertSymbolImportsForContent(db, contentHash, filePath, imports);\n }\n}\n\nexport function deleteSymbolContentIfUnreferenced(db: Database, contentHash: string): void {\n if (countParentFileMapRefs(db, contentHash) > 0) return;\n db.run('DELETE FROM symbol_index_tag WHERE content_hash = ?', [contentHash]);\n db.run('DELETE FROM symbol_index_import WHERE content_hash = ?', [contentHash]);\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { getParentFileMapHash } from './parent-file-map.js';\nimport type { SymbolIndexParentContext } from './parent-context.js';\n\n/** Resolved content hash for a file, or null when absent / tombstoned. */\nexport function getEffectiveContentHash(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n): string | null {\n const overlayHash = getParentFileMapHash(db, ctx.parentId, filePath);\n if (overlayHash !== undefined) return overlayHash;\n if (ctx.baseParentId == null) return null;\n const baseHash = getParentFileMapHash(db, ctx.baseParentId, filePath);\n if (baseHash === undefined) return null;\n return baseHash;\n}\n\nexport function listEffectiveIndexedFilePaths(db: Database, ctx: SymbolIndexParentContext): string[] {\n const paths = new Set<string>();\n if (ctx.baseParentId != null) {\n const baseRows = db.all('SELECT file_path FROM symbol_parent_file_map WHERE parent_id = ? AND content_hash IS NOT NULL', [\n ctx.baseParentId,\n ]) as Array<{ file_path: string }>;\n for (const row of baseRows) paths.add(row.file_path);\n }\n\n const overlayRows = db.all('SELECT file_path, content_hash FROM symbol_parent_file_map WHERE parent_id = ?', [\n ctx.parentId,\n ]) as Array<{ file_path: string; content_hash: string | null }>;\n for (const row of overlayRows) {\n if (row.content_hash == null) paths.delete(row.file_path);\n else paths.add(row.file_path);\n }\n\n if (ctx.baseParentId == null) {\n const ownRows = db.all('SELECT file_path FROM symbol_parent_file_map WHERE parent_id = ? AND content_hash IS NOT NULL', [\n ctx.parentId,\n ]) as Array<{ file_path: string }>;\n for (const row of ownRows) paths.add(row.file_path);\n }\n\n return [...paths];\n}\n", "import crypto from 'node:crypto';\n\n/** Stable content hash for a source file body (empty string when unreadable). */\nexport function hashSymbolFileContent(source: string | null | undefined): string {\n return crypto.createHash('sha256').update(source ?? '').digest('hex');\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport { deleteSymbolContentIfUnreferenced, upsertSymbolContentIndex } from '../storage/symbol-content-index.js';\nimport { getEffectiveContentHash } from '../storage/effective-content.js';\nimport {\n clearParentFileMap,\n clearParentFileMapBatch,\n getParentFileMapHash,\n removeParentFileMapEntry,\n setParentFileMapEntry,\n} from '../storage/parent-file-map.js';\nimport type { SymbolIndexParentContext } from '../storage/parent-context.js';\nimport { hashSymbolFileContent } from '../persistence/symbol-file-content-hash.js';\n\nfunction gcReleasedHashes(db: Database, hashes: Iterable<string | null | undefined>): void {\n for (const hash of hashes) {\n if (hash != null) deleteSymbolContentIfUnreferenced(db, hash);\n }\n}\n\nfunction persistFileSymbolData(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n contentHash: string,\n tags: SymbolTag[],\n imports: SymbolImportBinding[],\n): void {\n upsertSymbolContentIndex(db, contentHash, filePath, tags, imports);\n\n if (ctx.kind === 'overlay' && ctx.baseParentId != null) {\n const baseHash = getParentFileMapHash(db, ctx.baseParentId, filePath);\n if (baseHash === contentHash) {\n const released = removeParentFileMapEntry(db, ctx.parentId, filePath);\n gcReleasedHashes(db, [released]);\n return;\n }\n }\n\n const released = setParentFileMapEntry(db, ctx.parentId, filePath, contentHash);\n gcReleasedHashes(db, [released]);\n}\n\nexport function persistSymbolIndexFileData(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n source: string | null,\n tags: SymbolTag[],\n imports: SymbolImportBinding[],\n): void {\n const contentHash = hashSymbolFileContent(source);\n persistFileSymbolData(db, ctx, filePath, contentHash, tags, imports);\n}\n\nexport function removeSymbolIndexFileData(db: Database, ctx: SymbolIndexParentContext, filePath: string): void {\n if (ctx.kind === 'overlay') {\n const released = setParentFileMapEntry(db, ctx.parentId, filePath, null);\n gcReleasedHashes(db, [released]);\n return;\n }\n\n const released = removeParentFileMapEntry(db, ctx.parentId, filePath);\n gcReleasedHashes(db, [released]);\n}\n\nexport function clearSymbolIndexParentData(db: Database, ctx: SymbolIndexParentContext): void {\n const released = clearParentFileMap(db, ctx.parentId);\n gcReleasedHashes(db, released);\n}\n\nexport function clearSymbolIndexParentDataBatch(\n db: Database,\n ctx: SymbolIndexParentContext,\n limit: number,\n): boolean {\n const { released, remaining } = clearParentFileMapBatch(db, ctx.parentId, limit);\n gcReleasedHashes(db, released);\n return remaining;\n}\n\nexport function parentHasIndexedFile(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n): boolean {\n return getEffectiveContentHash(db, ctx, filePath) != null;\n}\n", "import { withCodeNavCacheSqliteSync } from '../../../sqlite/code-nav-cache/database.js';\nimport { getSymbolIndexParentContext } from './parent-path.js';\nimport { SYMBOL_INDEX_VERSION } from './symbol-index-version.js';\n\nexport function symbolIndexIsPopulated(resolvedParentPath: string): boolean {\n return withCodeNavCacheSqliteSync((db) => {\n const ctx = getSymbolIndexParentContext(db, resolvedParentPath);\n if (ctx == null) return false;\n\n const versionRow = db.get('SELECT index_version FROM symbol_index_parent_path WHERE id = ?', [\n ctx.parentId,\n ]) as { index_version: number } | null;\n if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return false;\n\n const ownRow = db.get(\n `SELECT 1 as ok FROM symbol_parent_file_map\n WHERE parent_id = ? AND content_hash IS NOT NULL\n LIMIT 1`,\n [ctx.parentId],\n ) as { ok: number } | null;\n if (ownRow != null) return true;\n\n if (ctx.baseParentId == null) return false;\n const baseRow = db.get(\n `SELECT index_version FROM symbol_index_parent_path WHERE id = ?`,\n [ctx.baseParentId],\n ) as { index_version: number } | null;\n if (baseRow == null || baseRow.index_version < SYMBOL_INDEX_VERSION) return false;\n\n const baseMapRow = db.get(\n `SELECT 1 as ok FROM symbol_parent_file_map\n WHERE parent_id = ? AND content_hash IS NOT NULL\n LIMIT 1`,\n [ctx.baseParentId],\n ) as { ok: number } | null;\n return baseMapRow != null;\n });\n}\n", "export { SYMBOL_INDEX_VERSION } from './symbol-index-version.js';\nexport {\n type SymbolIndexParentRow,\n getSymbolIndexParentContextById,\n getSymbolIndexParentContext,\n getSymbolIndexParentId,\n upsertSymbolIndexParentPath,\n} from './parent-path.js';\nexport {\n persistSymbolIndexFileData,\n removeSymbolIndexFileData,\n clearSymbolIndexParentData,\n clearSymbolIndexParentDataBatch,\n parentHasIndexedFile,\n} from './file-data-persistence.js';\nexport { symbolIndexIsPopulated } from './population.js';\n", "import { withCodeNavCacheSqliteWorkLock } from '../../../sqlite/code-nav-cache/code-nav-cache-sqlite-work-lock.js';\n\nexport function withSymbolIndexSqliteLock<T>(fn: () => T | Promise<T>): Promise<T> {\n return withCodeNavCacheSqliteWorkLock(fn);\n}\n", "import type { DbTagRow } from '../../resolution/types.js';\nimport type { CodeNavLocation } from '../../types.js';\n\nexport const TAG_SELECT = `file_path, name, role, kind, start_line, start_column, end_line, end_column,\n scope_start_line, scope_start_column, parent_scope_start_line, parent_scope_start_column, nav_target_path, scope_chain`;\n\nexport function rowToLocation(row: DbTagRow): CodeNavLocation {\n return {\n path: row.file_path,\n line: row.start_line + 1,\n column: row.start_column,\n kind: row.kind,\n role: row.role === 'def' ? 'definition' : 'reference',\n };\n}\n\nexport function modulePathLocation(row: DbTagRow): CodeNavLocation {\n return {\n path: row.nav_target_path!,\n line: 1,\n column: 0,\n kind: 'module',\n role: 'reference',\n };\n}\n\nexport function emptyRefRow(filePath: string): DbTagRow {\n return {\n file_path: filePath,\n name: '',\n role: 'ref',\n kind: '',\n start_line: 0,\n start_column: 0,\n end_line: 0,\n end_column: 0,\n scope_start_line: null,\n scope_start_column: null,\n parent_scope_start_line: null,\n parent_scope_start_column: null,\n nav_target_path: null,\n scope_chain: null,\n };\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { DbTagRow } from '../../resolution/types.js';\nimport type { DbImportRow } from '../sqlite/symbol-index-import-sqlite.js';\nimport { TAG_SELECT } from '../query/tag-query-shared.js';\nimport { getEffectiveContentHash, listEffectiveIndexedFilePaths } from './effective-content.js';\nimport type { SymbolIndexParentContext } from './parent-context.js';\n\nexport function loadFileTags(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n): DbTagRow[] {\n const contentHash = getEffectiveContentHash(db, ctx, filePath);\n if (contentHash == null) return [];\n return db.all(\n `SELECT ${TAG_SELECT}\n FROM symbol_index_tag\n WHERE content_hash = ? AND file_path = ?\n ORDER BY start_line, start_column`,\n [contentHash, filePath],\n ) as DbTagRow[];\n}\n\nexport function loadFileImports(\n db: Database,\n ctx: SymbolIndexParentContext,\n filePath: string,\n): DbImportRow[] {\n const contentHash = getEffectiveContentHash(db, ctx, filePath);\n if (contentHash == null) return [];\n return db.all(\n `SELECT file_path, local_name, source_name, module_specifier, source_file_path, import_kind, start_line, start_column\n FROM symbol_index_import\n WHERE content_hash = ? AND file_path = ?\n ORDER BY start_line, start_column`,\n [contentHash, filePath],\n ) as DbImportRow[];\n}\n\nexport function findTagsByName(db: Database, ctx: SymbolIndexParentContext, name: string): DbTagRow[] {\n const filePaths = listEffectiveIndexedFilePaths(db, ctx);\n const rows: DbTagRow[] = [];\n for (const filePath of filePaths) {\n const contentHash = getEffectiveContentHash(db, ctx, filePath);\n if (contentHash == null) continue;\n const matches = db.all(\n `SELECT ${TAG_SELECT}\n FROM symbol_index_tag\n WHERE content_hash = ? AND file_path = ? AND name = ?\n ORDER BY start_line, start_column`,\n [contentHash, filePath, name],\n ) as DbTagRow[];\n rows.push(...matches);\n }\n rows.sort((a, b) =>\n a.file_path.localeCompare(b.file_path) ||\n a.start_line - b.start_line ||\n a.start_column - b.start_column,\n );\n return rows;\n}\n", "export type { SymbolIndexParentContext } from './parent-context.js';\nexport {\n getParentFileMapHash,\n countParentFileMapRefs,\n setParentFileMapEntry,\n removeParentFileMapEntry,\n clearParentFileMap,\n clearParentFileMapBatch,\n} from './parent-file-map.js';\nexport { getEffectiveContentHash, listEffectiveIndexedFilePaths } from './effective-content.js';\nexport { loadFileTags, loadFileImports, findTagsByName } from './file-content-load.js';\n", "import type { Database } from 'node-sqlite3-wasm';\nimport type { DbTagRow } from '../../resolution/types.js';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport type { DbImportRow } from '../sqlite/symbol-index-import-sqlite.js';\nimport { loadFileImports, loadFileTags, type SymbolIndexParentContext } from '../storage/symbol-parent-file-map.js';\nimport type { SymbolIndexFileEntry } from './collect-file-entries.js';\n\nfunction dbTagToSymbolTag(row: DbTagRow): SymbolTag {\n return {\n name: row.name,\n role: row.role as SymbolTag['role'],\n kind: row.kind,\n startLine: row.start_line,\n startColumn: row.start_column,\n endLine: row.end_line,\n endColumn: row.end_column,\n scopeStartLine: row.scope_start_line ?? undefined,\n scopeStartColumn: row.scope_start_column ?? undefined,\n parentScopeStartLine: row.parent_scope_start_line ?? undefined,\n parentScopeStartColumn: row.parent_scope_start_column ?? undefined,\n navTargetPath: row.nav_target_path ?? undefined,\n scopeChain: row.scope_chain ?? undefined,\n };\n}\n\nfunction dbImportToSymbolImport(row: DbImportRow): SymbolImportBinding {\n return {\n localName: row.local_name,\n sourceName: row.source_name,\n moduleSpecifier: row.module_specifier,\n sourceFilePath: row.source_file_path,\n importKind: row.import_kind as SymbolImportBinding['importKind'],\n startLine: row.start_line,\n startColumn: row.start_column,\n };\n}\n\nexport function loadIndexedFileEntry(\n db: Database,\n ctx: SymbolIndexParentContext,\n relPath: string,\n): SymbolIndexFileEntry | undefined {\n const tags = loadFileTags(db, ctx, relPath);\n const imports = loadFileImports(db, ctx, relPath);\n if (tags.length === 0 && imports.length === 0) return undefined;\n return {\n relPath,\n source: null,\n tags: tags.map(dbTagToSymbolTag),\n imports: imports.map(dbImportToSymbolImport),\n };\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport {\n withCodeNavCacheSqlite,\n withCodeNavCacheSqliteSync,\n} from '../../../sqlite/code-nav-cache/database.js';\nimport { loadIndexedFileEntry } from '../build/load-indexed-file-entry.js';\nimport { getSymbolIndexParentContext } from '../sqlite/symbol-index-sqlite.js';\n\nfunction normalizeRelPath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n}\n\nfunction listDirectImportTargetsWithDb(db: Database, resolved: string, relPath: string): string[] {\n const ctx = getSymbolIndexParentContext(db, resolved);\n if (ctx == null) return [];\n const entry = loadIndexedFileEntry(db, ctx, relPath);\n if (entry == null) return [];\n const paths = new Set<string>();\n for (const binding of entry.imports) {\n if (binding.sourceFilePath) paths.add(binding.sourceFilePath);\n }\n return Array.from(paths);\n}\n\nexport async function listDirectImportTargetsForFileAsync(parentPath: string, filePath: string): Promise<string[]> {\n const resolved = normalizeResolvedPath(parentPath);\n const relPath = normalizeRelPath(filePath);\n if (!relPath) return [];\n\n return withCodeNavCacheSqlite((db) => listDirectImportTargetsWithDb(db, resolved, relPath));\n}\n\n/** @deprecated Prefer {@link listDirectImportTargetsForFileAsync}. */\nexport function listDirectImportTargetsForFile(parentPath: string, filePath: string): string[] {\n const resolved = normalizeResolvedPath(parentPath);\n const relPath = normalizeRelPath(filePath);\n if (!relPath) return [];\n\n return withCodeNavCacheSqliteSync((db) => listDirectImportTargetsWithDb(db, resolved, relPath));\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { withCodeNavCacheSqlite, withCodeNavCacheSqliteProbe } from '../../../sqlite/code-nav-cache/database.js';\nimport { getSymbolIndexParentContext, SYMBOL_INDEX_VERSION } from '../sqlite/symbol-index-sqlite.js';\nimport { getEffectiveContentHash, listEffectiveIndexedFilePaths } from '../storage/symbol-parent-file-map.js';\n\nfunction symbolIndexFileIsReadyWithDb(db: Database, parentPath: string, filePath: string): boolean {\n const normalizedParent = normalizeResolvedPath(parentPath);\n const normalizedFile = filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!normalizedFile) return false;\n\n const ctx = getSymbolIndexParentContext(db, normalizedParent);\n if (ctx == null) return false;\n\n const versionRow = db.get('SELECT index_version FROM symbol_index_parent_path WHERE id = ?', [\n ctx.parentId,\n ]) as { index_version: number } | null;\n if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return false;\n\n return getEffectiveContentHash(db, ctx, normalizedFile) != null;\n}\n\n/** True when the effective file map resolves to indexed content for this parent + path. */\nexport async function symbolIndexFileIsReadyAsync(parentPath: string, filePath: string): Promise<boolean> {\n return withCodeNavCacheSqlite((db) => symbolIndexFileIsReadyWithDb(db, parentPath, filePath));\n}\n\n/** Non-blocking readiness probe for interactive code-nav (no long SQLite lock retries). */\nexport async function symbolIndexFileIsReadyProbe(parentPath: string, filePath: string): Promise<boolean> {\n const ready = await withCodeNavCacheSqliteProbe((db) =>\n symbolIndexFileIsReadyWithDb(db, parentPath, filePath),\n );\n return ready === true;\n}\n\n/** All indexed relative paths for a parent (one SQLite round-trip for warmup scheduling). */\nexport async function loadSymbolIndexReadyFileSet(parentPath: string): Promise<Set<string>> {\n const normalizedParent = normalizeResolvedPath(parentPath);\n const paths = await withCodeNavCacheSqlite((db) => {\n const ctx = getSymbolIndexParentContext(db, normalizedParent);\n if (ctx == null) return [] as string[];\n\n const versionRow = db.get('SELECT index_version FROM symbol_index_parent_path WHERE id = ?', [\n ctx.parentId,\n ]) as { index_version: number } | null;\n if (versionRow == null || versionRow.index_version < SYMBOL_INDEX_VERSION) return [] as string[];\n\n return listEffectiveIndexedFilePaths(db, ctx);\n });\n return new Set(paths);\n}\n", "import type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport type { SymbolIndexFileEntry } from '../build/collect-file-entries.js';\n\nconst STAR_LOCAL_NAME = '*';\n\nfunction isModuleLevelDef(tag: SymbolTag): boolean {\n return tag.role === 'def' && tag.parentScopeStartLine == null && tag.parentScopeStartColumn == null;\n}\n\nfunction collectExportableNamesFromTags(tags: readonly SymbolTag[]): Map<string, string> {\n const names = new Map<string, string>();\n for (const tag of tags) {\n if (!isModuleLevelDef(tag)) continue;\n if (!names.has(tag.name)) names.set(tag.name, tag.name);\n }\n return names;\n}\n\nexport function existingLocalNames(imports: readonly SymbolImportBinding[]): Set<string> {\n return new Set(imports.map((binding) => binding.localName));\n}\n\nexport function resolveExportableNames(\n filePath: string,\n entriesByPath: ReadonlyMap<string, SymbolIndexFileEntry>,\n visited: Set<string>,\n): Map<string, { sourceName: string; sourceFilePath: string }> {\n if (visited.has(filePath)) return new Map();\n visited.add(filePath);\n\n const entry = entriesByPath.get(filePath);\n if (!entry) return new Map();\n\n const out = collectExportableNamesFromTags(entry.tags);\n const resolved = new Map<string, { sourceName: string; sourceFilePath: string }>();\n for (const [name, sourceName] of out) {\n resolved.set(name, { sourceName, sourceFilePath: filePath });\n }\n\n for (const binding of entry.imports) {\n if (binding.importKind !== 'star' || !binding.sourceFilePath) continue;\n const upstream = resolveExportableNames(binding.sourceFilePath, entriesByPath, visited);\n for (const [name, info] of upstream) {\n if (!resolved.has(name)) resolved.set(name, info);\n }\n }\n\n for (const binding of entry.imports) {\n if (binding.importKind !== 'reexport' && binding.importKind !== 'type') continue;\n if (!binding.sourceFilePath) continue;\n if (!resolved.has(binding.localName)) {\n resolved.set(binding.localName, {\n sourceName: binding.sourceName,\n sourceFilePath: binding.sourceFilePath,\n });\n }\n }\n\n return resolved;\n}\n\nexport { STAR_LOCAL_NAME };\n", "import type { SymbolIndexFileEntry } from '../build/collect-file-entries.js';\n\nexport function collectUpstreamEntries(\n entry: SymbolIndexFileEntry,\n resolveEntry: (filePath: string) => SymbolIndexFileEntry | undefined,\n): SymbolIndexFileEntry[] {\n const entriesByPath = new Map<string, SymbolIndexFileEntry>();\n entriesByPath.set(entry.relPath, entry);\n\n const visit = (filePath: string, visited: Set<string>): void => {\n if (visited.has(filePath)) return;\n visited.add(filePath);\n const resolved = resolveEntry(filePath);\n if (resolved == null) return;\n entriesByPath.set(filePath, resolved);\n for (const binding of resolved.imports) {\n if (binding.sourceFilePath) visit(binding.sourceFilePath, visited);\n }\n };\n\n for (const star of entry.imports) {\n if (star.importKind !== 'star' || !star.sourceFilePath) continue;\n visit(star.sourceFilePath, new Set());\n }\n\n return [...entriesByPath.values()];\n}\n", "import type { SymbolImportBinding } from '../../types.js';\nimport type { SymbolIndexFileEntry } from '../build/collect-file-entries.js';\nimport { existingLocalNames, resolveExportableNames, STAR_LOCAL_NAME } from './star-reexport-names.js';\nimport { collectUpstreamEntries } from './star-reexport-upstream.js';\n\n/** Expand star re-exports for one file using lazily resolved upstream entries. */\nexport function expandStarReexportForFile(\n entry: SymbolIndexFileEntry,\n resolveEntry: (filePath: string) => SymbolIndexFileEntry | undefined,\n): SymbolIndexFileEntry {\n const collected = collectUpstreamEntries(entry, resolveEntry);\n return expandStarReexportBindings(collected).find((row) => row.relPath === entry.relPath) ?? entry;\n}\n\n/** Materialize `export * from` bindings as explicit re-export rows for each exported symbol. */\nexport function expandStarReexportBindings(collected: SymbolIndexFileEntry[]): SymbolIndexFileEntry[] {\n const entriesByPath = new Map(collected.map((entry) => [entry.relPath, entry]));\n\n return collected.map((entry) => {\n const stars = entry.imports.filter((binding) => binding.importKind === 'star');\n if (stars.length === 0) return entry;\n\n const localNames = existingLocalNames(entry.imports);\n const materialized: SymbolImportBinding[] = [];\n\n for (const star of stars) {\n if (!star.sourceFilePath) continue;\n const exportable = resolveExportableNames(star.sourceFilePath, entriesByPath, new Set());\n for (const [localName, info] of exportable) {\n if (localName === STAR_LOCAL_NAME || localNames.has(localName)) continue;\n localNames.add(localName);\n materialized.push({\n localName,\n sourceName: info.sourceName,\n moduleSpecifier: star.moduleSpecifier,\n sourceFilePath: info.sourceFilePath,\n importKind: star.importKind === 'type' ? 'type' : 'reexport',\n startLine: star.startLine,\n startColumn: star.startColumn,\n });\n }\n }\n\n if (materialized.length === 0) return entry;\n return { ...entry, imports: [...entry.imports, ...materialized] };\n });\n}\n", "import type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { runCodeNavCacheWriteTransaction } from '../../../sqlite/code-nav-cache/code-nav-cache-sqlite-transaction.js';\nimport {\n getSymbolIndexParentContext,\n persistSymbolIndexFileData,\n removeSymbolIndexFileData,\n upsertSymbolIndexParentPath,\n} from '../sqlite/symbol-index-sqlite.js';\n\nexport async function persistSymbolIndexFileAsync(\n resolved: string,\n relPath: string,\n source: string | null,\n tags: SymbolTag[],\n imports: SymbolImportBinding[],\n): Promise<void> {\n await withCodeNavCacheSqlite(async (db) => {\n runCodeNavCacheWriteTransaction(db, () => {\n upsertSymbolIndexParentPath(db, resolved);\n const ctx = getSymbolIndexParentContext(db, resolved);\n if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);\n persistSymbolIndexFileData(db, ctx, relPath, source, tags, imports);\n });\n });\n}\n\n/** @deprecated Prefer {@link persistSymbolIndexFileAsync}. */\nexport function persistSymbolIndexFile(\n resolved: string,\n relPath: string,\n source: string | null,\n tags: SymbolTag[],\n imports: SymbolImportBinding[],\n): void {\n void persistSymbolIndexFileAsync(resolved, relPath, source, tags, imports);\n}\n\nexport async function removeSymbolIndexFileAsync(resolved: string, relPath: string): Promise<void> {\n await withCodeNavCacheSqlite(async (db) => {\n runCodeNavCacheWriteTransaction(db, () => {\n upsertSymbolIndexParentPath(db, resolved);\n const ctx = getSymbolIndexParentContext(db, resolved);\n if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);\n removeSymbolIndexFileData(db, ctx, relPath);\n });\n });\n}\n\n/** @deprecated Prefer {@link removeSymbolIndexFileAsync}. */\nexport function removeSymbolIndexFile(resolved: string, relPath: string): void {\n void removeSymbolIndexFileAsync(resolved, relPath);\n}\n", "import path from 'node:path';\nimport { getLanguageKeyForFilePath } from './language-registry.js';\n\nconst TS_JS_EXTENSIONS = ['', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '/index.ts', '/index.tsx', '/index.js', '/index.jsx'];\nconst PYTHON_EXTENSIONS = ['.py', '/__init__.py'];\nconst C_CPP_EXTENSIONS = ['', '.h', '.hpp', '.hh', '.hxx', '.c', '.cpp', '.cc', '.cxx'];\n\nfunction normalizeWorkspacePath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n}\n\nfunction isRelativeModuleSpecifier(specifier: string): boolean {\n return specifier.startsWith('./') || specifier.startsWith('../') || specifier.startsWith('/');\n}\n\nfunction firstExistingPath(candidates: string[], workspaceFiles: ReadonlySet<string>): string | null {\n for (const candidate of candidates) {\n const normalized = normalizeWorkspacePath(candidate);\n if (workspaceFiles.has(normalized)) return normalized;\n }\n return null;\n}\n\nfunction withSuffixes(basePath: string, suffixes: readonly string[]): string[] {\n return suffixes.map((suffix) => basePath + suffix);\n}\n\n/** Candidates for TS/JS imports, including ESM `.js` specifiers that refer to `.ts` sources. */\nfunction tsJsImportCandidates(joined: string): string[] {\n const candidates = withSuffixes(joined, TS_JS_EXTENSIONS);\n\n const extensionRewrites: ReadonlyArray<[string, readonly string[]]> = [\n ['.js', ['.ts', '.tsx', '.js', '.jsx']],\n ['.jsx', ['.tsx', '.ts', '.jsx', '.js']],\n ['.mjs', ['.mts', '.ts', '.mjs', '.js']],\n ['.cjs', ['.cts', '.ts', '.cjs', '.js']],\n ];\n for (const [fromExt, toExts] of extensionRewrites) {\n if (!joined.endsWith(fromExt)) continue;\n const stem = joined.slice(0, -fromExt.length);\n for (const toExt of toExts) {\n candidates.unshift(stem + toExt);\n }\n for (const indexSuffix of ['/index.ts', '/index.tsx', '/index.js', '/index.jsx']) {\n candidates.unshift(stem + indexSuffix);\n }\n }\n\n return candidates;\n}\n\n/**\n * Resolve a relative TS/JS module specifier to a workspace-relative file path using the indexed file list.\n */\nexport function resolveModuleImportPath(\n importerFilePath: string,\n moduleSpecifier: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const spec = moduleSpecifier.trim();\n if (!spec || !isRelativeModuleSpecifier(spec)) return null;\n\n const importerDir = path.posix.dirname(normalizeWorkspacePath(importerFilePath));\n const joined = normalizeWorkspacePath(path.posix.normalize(path.posix.join(importerDir, spec)));\n\n return firstExistingPath(tsJsImportCandidates(joined), workspaceFiles);\n}\n\nfunction resolvePythonModulePath(\n importerFilePath: string,\n moduleSpecifier: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const moduleName = moduleSpecifier.trim().replace(/\\s+/g, '');\n if (!moduleName) return null;\n\n const importerDir = path.posix.dirname(normalizeWorkspacePath(importerFilePath));\n\n if (moduleName.startsWith('.')) {\n const dotMatch = /^(\\.+)(.*)$/.exec(moduleName);\n const dotCount = dotMatch?.[1]?.length ?? 1;\n const rest = (dotMatch?.[2] ?? '').replace(/^\\./, '');\n let baseDir = importerDir;\n for (let i = 1; i < dotCount; i++) {\n baseDir = path.posix.dirname(baseDir);\n }\n const dottedPath = rest ? rest.split('.').join('/') : '';\n const relativeBase = dottedPath ? path.posix.join(baseDir, dottedPath) : baseDir;\n return firstExistingPath(\n [\n ...withSuffixes(relativeBase, PYTHON_EXTENSIONS),\n ...withSuffixes(path.posix.join(relativeBase, '__init__'), ['.py']),\n ],\n workspaceFiles,\n );\n }\n\n const dottedPath = moduleName.split('.').join('/');\n\n return firstExistingPath(\n [\n ...withSuffixes(dottedPath, PYTHON_EXTENSIONS),\n ...withSuffixes(path.posix.join(importerDir, dottedPath), PYTHON_EXTENSIONS),\n ],\n workspaceFiles,\n );\n}\n\nfunction resolveIncludePath(\n importerFilePath: string,\n includePath: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const spec = includePath.trim().replace(/^[\"']|[\"']$/g, '');\n if (!spec) return null;\n\n const importerDir = path.posix.dirname(normalizeWorkspacePath(importerFilePath));\n const joined = normalizeWorkspacePath(\n path.posix.normalize(path.posix.join(importerDir, spec.replace(/\\\\/g, '/'))),\n );\n\n if (workspaceFiles.has(joined)) return joined;\n return firstExistingPath(withSuffixes(joined, C_CPP_EXTENSIONS), workspaceFiles);\n}\n\nfunction resolveJavaImportPath(moduleSpecifier: string, workspaceFiles: ReadonlySet<string>): string | null {\n const spec = moduleSpecifier.trim();\n if (!spec) return null;\n\n const pathLike = `${spec.replace(/\\./g, '/')}.java`;\n if (workspaceFiles.has(pathLike)) return pathLike;\n\n for (const file of workspaceFiles) {\n if (file === pathLike || file.endsWith(`/${pathLike}`)) return file;\n }\n return null;\n}\n\nfunction resolveGoImportPath(\n importerFilePath: string,\n moduleSpecifier: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const spec = moduleSpecifier.trim();\n if (!spec) return null;\n\n if (isRelativeModuleSpecifier(spec)) {\n const importerDir = path.posix.dirname(normalizeWorkspacePath(importerFilePath));\n const joined = normalizeWorkspacePath(path.posix.normalize(path.posix.join(importerDir, spec)));\n if (workspaceFiles.has(joined)) return joined;\n return firstExistingPath(withSuffixes(joined, ['.go']), workspaceFiles);\n }\n\n const leaf = spec.split('/').filter(Boolean).at(-1);\n if (!leaf) return null;\n for (const file of workspaceFiles) {\n if (file.endsWith(`/${leaf}.go`) || file === `${leaf}.go`) return file;\n }\n return null;\n}\n\n/** Resolve an import/include specifier to a workspace-relative source file path. */\nexport function resolveImportSourcePath(\n importerFilePath: string,\n moduleSpecifier: string,\n workspaceFiles: ReadonlySet<string>,\n): string | null {\n const spec = moduleSpecifier.trim();\n if (!spec) return null;\n\n const tsResult = resolveModuleImportPath(importerFilePath, spec, workspaceFiles);\n if (tsResult) return tsResult;\n\n const languageKey = getLanguageKeyForFilePath(importerFilePath);\n switch (languageKey) {\n case 'python':\n return resolvePythonModulePath(importerFilePath, spec, workspaceFiles);\n case 'c':\n case 'cpp':\n return resolveIncludePath(importerFilePath, spec, workspaceFiles);\n case 'java':\n return resolveJavaImportPath(spec, workspaceFiles);\n case 'go':\n return resolveGoImportPath(importerFilePath, spec, workspaceFiles);\n default:\n return null;\n }\n}\n\nexport function isModulePathSpecifier(name: string): boolean {\n return isRelativeModuleSpecifier(name.trim());\n}\n", "import path from 'node:path';\nimport type { SymbolTag } from './types.js';\nimport { isModulePathSpecifier, resolveModuleImportPath } from './resolve-module-import-path.js';\n\nexport function enrichTagsWithModulePaths(\n tags: readonly SymbolTag[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolTag[] {\n return tags.map((tag) => {\n if (tag.kind !== 'module' || tag.role !== 'ref' || !isModulePathSpecifier(tag.name)) {\n return tag;\n }\n const resolved = resolveModuleImportPath(filePath, tag.name, workspaceFiles);\n if (!resolved) return tag;\n return { ...tag, navTargetPath: resolved };\n });\n}\n\nexport function workspaceFilesFromCollected(collected: ReadonlyArray<{ relPath: string }>): Set<string> {\n return new Set(collected.map((entry) => entry.relPath.replace(/\\\\/g, '/')));\n}\n\nexport function workspaceFilesFromParent(parentPath: string, relPaths: readonly string[]): Set<string> {\n return new Set(relPaths.map((rel) => path.posix.normalize(rel.replace(/\\\\/g, '/'))));\n}\n", "import type { CodeNavYieldState } from './yield-during-work.js';\nimport { yieldDuringCodeNavWork } from './yield-during-work.js';\nimport type { SymbolTag } from './types.js';\nimport { enrichTagsWithModulePaths } from './enrich-tag-module-paths.js';\n\n/** Enrich module path tags in chunks so large files can yield to the event loop. */\nexport async function enrichTagsWithModulePathsAsync(\n tags: readonly SymbolTag[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n state: CodeNavYieldState,\n): Promise<SymbolTag[]> {\n const chunkSize = 64;\n const enriched: SymbolTag[] = [];\n\n for (let i = 0; i < tags.length; i += chunkSize) {\n await yieldDuringCodeNavWork(state);\n const chunk = tags.slice(i, i + chunkSize);\n enriched.push(...enrichTagsWithModulePaths(chunk, filePath, workspaceFiles));\n }\n\n return enriched;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from './types.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from './yield-during-work.js';\n\nconst PARAM_NODE_TYPES = new Set(['required_parameter', 'optional_parameter']);\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\nfunction collectParamNames(functionTypeNode: SyntaxNode): Set<string> {\n const names = new Set<string>();\n const parameters = functionTypeNode.childForFieldName('parameters');\n if (!parameters) return names;\n\n function walk(node: SyntaxNode): void {\n if (PARAM_NODE_TYPES.has(node.type)) {\n const nameNode = node.childForFieldName('pattern') ?? node.namedChildren.find((c) => c.type === 'identifier');\n if (nameNode?.type === 'identifier') names.add(nameNode.text);\n return;\n }\n for (const child of node.namedChildren) walk(child);\n }\n\n walk(parameters);\n return names;\n}\n\nfunction isDefinitionName(node: SyntaxNode): boolean {\n const parent = node.parent;\n if (!parent) return false;\n if (PARAM_NODE_TYPES.has(parent.type)) return true;\n if (parent.type === 'type_parameter' && parent.childForFieldName('name') === node) return true;\n return false;\n}\n\nfunction tagFromIdentifierNode(node: SyntaxNode): SymbolTag {\n return {\n name: node.text,\n role: 'ref',\n kind: 'variable',\n startLine: node.startPosition.row,\n startColumn: node.startPosition.column,\n endLine: node.endPosition.row,\n endColumn: node.endPosition.column,\n };\n}\n\nfunction enclosingFunctionTypes(node: SyntaxNode): SyntaxNode[] {\n const types: SyntaxNode[] = [];\n let current: SyntaxNode | null = node.parent;\n while (current) {\n if (current.type === 'function_type') types.push(current);\n current = current.parent;\n }\n return types;\n}\n\nfunction isFunctionTypeParamReference(node: SyntaxNode): boolean {\n if (node.type !== 'identifier' || isDefinitionName(node)) return false;\n\n for (const functionType of enclosingFunctionTypes(node)) {\n const returnType = functionType.childForFieldName('return_type');\n if (!returnType?.descendantsOfType('identifier').some((desc) => desc.id === node.id)) continue;\n if (collectParamNames(functionType).has(node.text)) return true;\n }\n return false;\n}\n\n/** Capture callback-type parameter references in return types (e.g. type predicates). */\nexport async function augmentFunctionTypeParamReferenceTags(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n root: SyntaxNode,\n): Promise<SymbolTag[]> {\n const seen = new Set(tags.map(tagDedupeKey));\n const out = [...tags];\n const state = createCodeNavYieldState();\n\n async function walk(node: SyntaxNode): Promise<void> {\n if (isFunctionTypeParamReference(node)) {\n const tag = tagFromIdentifierNode(node);\n const key = tagDedupeKey(tag);\n if (!seen.has(key)) {\n seen.add(key);\n out.push(tag);\n nameNodes.set(`${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`, node);\n }\n }\n for (const child of node.children) {\n await yieldDuringCodeNavWork(state);\n await walk(child);\n }\n }\n\n await walk(root);\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from './types.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from './yield-during-work.js';\n\nconst TYPE_DEFINITION_CONTAINER_TYPES = new Set([\n 'function_declaration',\n 'function_signature',\n 'generator_function_declaration',\n 'class_declaration',\n 'abstract_class_declaration',\n 'interface_declaration',\n 'type_alias_declaration',\n 'enum_declaration',\n 'module',\n 'type_parameter',\n 'method_definition',\n 'method_signature',\n 'abstract_method_signature',\n 'property_signature',\n 'public_field_definition',\n]);\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\nfunction isTypeDefinitionName(node: SyntaxNode): boolean {\n const parent = node.parent;\n if (!parent) return false;\n return TYPE_DEFINITION_CONTAINER_TYPES.has(parent.type) && parent.childForFieldName('name') === node;\n}\n\nfunction tagFromTypeIdentifierNode(node: SyntaxNode): SymbolTag {\n return {\n name: node.text,\n role: 'ref',\n kind: 'type',\n startLine: node.startPosition.row,\n startColumn: node.startPosition.column,\n endLine: node.endPosition.row,\n endColumn: node.endPosition.column,\n };\n}\n\n/** Capture type_identifier uses that tags.scm patterns miss (unions, arrays, etc.). */\nexport async function augmentTypeReferenceTags(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n root: SyntaxNode,\n): Promise<SymbolTag[]> {\n const seen = new Set(tags.map(tagDedupeKey));\n const out = [...tags];\n const state = createCodeNavYieldState();\n\n async function walk(node: SyntaxNode): Promise<void> {\n if (node.type === 'type_identifier' && !isTypeDefinitionName(node)) {\n const tag = tagFromTypeIdentifierNode(node);\n const key = tagDedupeKey(tag);\n if (!seen.has(key)) {\n seen.add(key);\n out.push(tag);\n nameNodes.set(`${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`, node);\n }\n }\n for (const child of node.children) {\n await yieldDuringCodeNavWork(state);\n await walk(child);\n }\n }\n\n await walk(root);\n return out;\n}\n", "export type ScopeAnchor = { startLine: number; startColumn: number };\n\nexport function scopeAnchorKey(anchor: ScopeAnchor | null | undefined): string | null {\n if (anchor == null) return null;\n return `${anchor.startLine}:${anchor.startColumn}`;\n}\n\nexport function serializeScopeChain(chain: readonly ScopeAnchor[]): string | null {\n if (chain.length === 0) return null;\n return chain.map((anchor) => `${anchor.startLine}:${anchor.startColumn}`).join(',');\n}\n\nexport function parseScopeChain(raw: string | null | undefined): ScopeAnchor[] {\n if (!raw) return [];\n const out: ScopeAnchor[] = [];\n for (const part of raw.split(',')) {\n if (!part) continue;\n const colon = part.indexOf(':');\n if (colon < 0) continue;\n const startLine = Number(part.slice(0, colon));\n const startColumn = Number(part.slice(colon + 1));\n if (!Number.isFinite(startLine) || !Number.isFinite(startColumn)) continue;\n out.push({ startLine, startColumn });\n }\n return out;\n}\n\nexport function scopeChainKeys(chain: readonly ScopeAnchor[]): string[] {\n return chain.map((anchor) => scopeAnchorKey(anchor)!).filter(Boolean);\n}\n\nexport function anchorInScopeChain(\n line: number | null | undefined,\n column: number | null | undefined,\n chain: readonly ScopeAnchor[],\n): boolean {\n if (line == null || column == null) return chain.length === 0;\n return chain.some((anchor) => anchor.startLine === line && anchor.startColumn === column);\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from './types.js';\nimport type { ScopeAnchor } from './scope-chain.js';\nimport { serializeScopeChain } from './scope-chain.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from './yield-during-work.js';\n\nconst SCOPE_CONTAINER_TYPES = new Set([\n 'function_declaration',\n 'function_expression',\n 'generator_function',\n 'generator_function_declaration',\n 'method_definition',\n 'method_signature',\n 'abstract_method_signature',\n 'class_declaration',\n 'abstract_class_declaration',\n 'interface_declaration',\n 'module',\n 'arrow_function',\n 'function_type',\n 'function_item',\n 'impl_item',\n 'function_definition',\n 'class_definition',\n]);\n\nfunction scopeAnchorFromNode(node: SyntaxNode): ScopeAnchor {\n const nameNode = node.childForFieldName('name');\n if (nameNode) {\n return {\n startLine: nameNode.startPosition.row,\n startColumn: nameNode.startPosition.column,\n };\n }\n return {\n startLine: node.startPosition.row,\n startColumn: node.startPosition.column,\n };\n}\n\nexport function findEnclosingScopeChain(nameNode: SyntaxNode): ScopeAnchor[] {\n const chain: ScopeAnchor[] = [];\n let current: SyntaxNode | null = nameNode.parent;\n\n while (current) {\n if (SCOPE_CONTAINER_TYPES.has(current.type)) {\n chain.push(scopeAnchorFromNode(current));\n }\n current = current.parent;\n }\n\n return chain;\n}\n\nexport function findEnclosingScopes(nameNode: SyntaxNode): {\n scope: ScopeAnchor | null;\n parentScope: ScopeAnchor | null;\n scopeChain: ScopeAnchor[];\n} {\n const scopeChain = findEnclosingScopeChain(nameNode);\n return {\n scope: scopeChain[0] ?? null,\n parentScope: scopeChain[1] ?? null,\n scopeChain,\n };\n}\n\nexport async function enrichTagsWithEnclosingScope(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n): Promise<SymbolTag[]> {\n const state = createCodeNavYieldState();\n const out: SymbolTag[] = [];\n for (const tag of tags) {\n await yieldDuringCodeNavWork(state);\n const key = `${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`;\n const nameNode = nameNodes.get(key);\n if (!nameNode) {\n out.push(tag);\n continue;\n }\n const { scope, parentScope, scopeChain } = findEnclosingScopes(nameNode);\n if (!scope) {\n out.push(tag);\n continue;\n }\n out.push({\n ...tag,\n scopeStartLine: scope.startLine,\n scopeStartColumn: scope.startColumn,\n parentScopeStartLine: parentScope?.startLine,\n parentScopeStartColumn: parentScope?.startColumn,\n scopeChain: serializeScopeChain(scopeChain) ?? undefined,\n });\n }\n return out;\n}\n\nexport function scopeKey(scope: ScopeAnchor | null | undefined): string | null {\n if (scope == null) return null;\n return `${scope.startLine}:${scope.startColumn}`;\n}\n\nexport function scopesMatch(\n aLine: number | null | undefined,\n aCol: number | null | undefined,\n bLine: number | null | undefined,\n bCol: number | null | undefined,\n): boolean {\n return aLine != null && aCol != null && bLine != null && bCol != null && aLine === bLine && aCol === bCol;\n}\n", "import type { MemberAccessRule } from './types.js';\n\nexport const C_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'field_expression', objectField: 'argument', propertyField: 'field', tagKind: 'member' },\n];\n", "import type { MemberAccessRule } from './types.js';\nimport { C_MEMBER_ACCESS_RULES } from './c.js';\n\nexport const CPP_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n ...C_MEMBER_ACCESS_RULES,\n { parentType: 'qualified_identifier', objectField: 'scope', propertyField: 'name', tagKind: 'member' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const GO_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'selector_expression', objectField: 'operand', propertyField: 'field', tagKind: 'member' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const ECMA_SCRIPT_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'member_expression', objectField: 'object', propertyField: 'property', tagKind: 'member' },\n];\n\nexport const JAVASCRIPT_MEMBER_ACCESS_RULES = ECMA_SCRIPT_MEMBER_ACCESS_RULES;\nexport const TYPESCRIPT_MEMBER_ACCESS_RULES = ECMA_SCRIPT_MEMBER_ACCESS_RULES;\nexport const TSX_MEMBER_ACCESS_RULES = ECMA_SCRIPT_MEMBER_ACCESS_RULES;\n", "import type { MemberAccessRule } from './types.js';\n\nexport const JAVA_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'field_access', objectField: 'object', propertyField: 'field', tagKind: 'member' },\n { parentType: 'method_invocation', objectField: 'object', propertyField: 'name', tagKind: 'call' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const PYTHON_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'attribute', objectField: 'object', propertyField: 'attribute', tagKind: 'member' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const RUBY_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'call', objectField: 'receiver', propertyField: 'method', tagKind: 'call' },\n];\n", "import type { MemberAccessRule } from './types.js';\n\nexport const RUST_MEMBER_ACCESS_RULES: MemberAccessRule[] = [\n { parentType: 'field_expression', objectField: 'value', propertyField: 'field', tagKind: 'member' },\n { parentType: 'scoped_identifier', objectField: 'path', propertyField: 'name', tagKind: 'member' },\n];\n", "export {\n ECMA_SCRIPT_MEMBER_ACCESS_RULES as TSX_MEMBER_ACCESS_RULES,\n} from './javascript.js';\n", "export {\n ECMA_SCRIPT_MEMBER_ACCESS_RULES as TYPESCRIPT_MEMBER_ACCESS_RULES,\n} from './javascript.js';\n", "import { C_MEMBER_ACCESS_RULES } from './c.js';\nimport { CPP_MEMBER_ACCESS_RULES } from './cpp.js';\nimport { GO_MEMBER_ACCESS_RULES } from './go.js';\nimport { JAVASCRIPT_MEMBER_ACCESS_RULES } from './javascript.js';\nimport { JAVA_MEMBER_ACCESS_RULES } from './java.js';\nimport { PYTHON_MEMBER_ACCESS_RULES } from './python.js';\nimport { RUBY_MEMBER_ACCESS_RULES } from './ruby.js';\nimport { RUST_MEMBER_ACCESS_RULES } from './rust.js';\nimport { TSX_MEMBER_ACCESS_RULES } from './tsx.js';\nimport { TYPESCRIPT_MEMBER_ACCESS_RULES } from './typescript.js';\nimport type { MemberAccessRule } from './types.js';\n\nexport const MEMBER_ACCESS_RULES_BY_LANGUAGE_KEY: Readonly<Record<string, readonly MemberAccessRule[]>> = {\n javascript: JAVASCRIPT_MEMBER_ACCESS_RULES,\n typescript: TYPESCRIPT_MEMBER_ACCESS_RULES,\n tsx: TSX_MEMBER_ACCESS_RULES,\n python: PYTHON_MEMBER_ACCESS_RULES,\n go: GO_MEMBER_ACCESS_RULES,\n rust: RUST_MEMBER_ACCESS_RULES,\n ruby: RUBY_MEMBER_ACCESS_RULES,\n java: JAVA_MEMBER_ACCESS_RULES,\n c: C_MEMBER_ACCESS_RULES,\n cpp: CPP_MEMBER_ACCESS_RULES,\n};\n\nexport function memberAccessRulesForLanguageKey(languageKey: string | null): readonly MemberAccessRule[] {\n if (!languageKey) return [];\n return MEMBER_ACCESS_RULES_BY_LANGUAGE_KEY[languageKey] ?? [];\n}\n", "export type ScopeAnchor = {\n startLine: number;\n startColumn: number;\n};\n\nexport type MemberAccessRule = {\n parentType: string;\n objectField: string;\n propertyField: string;\n tagKind?: string;\n};\n\nexport const MEMBER_NAME_NODE_TYPES = new Set([\n 'identifier',\n 'property_identifier',\n 'field_identifier',\n 'type_identifier',\n 'constant',\n 'package_identifier',\n]);\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { MemberAccessRule } from './types.js';\nimport { MEMBER_NAME_NODE_TYPES } from './types.js';\n\nexport function nodesMatch(a: SyntaxNode, b: SyntaxNode): boolean {\n return (\n a.startPosition.row === b.startPosition.row &&\n a.startPosition.column === b.startPosition.column &&\n a.text === b.text\n );\n}\n\nfunction fieldNodeMatches(node: SyntaxNode | null, candidate: SyntaxNode): boolean {\n return node != null && nodesMatch(node, candidate);\n}\n\nexport function isReceiverNameNode(node: SyntaxNode): boolean {\n return (\n MEMBER_NAME_NODE_TYPES.has(node.type) ||\n node.type === 'this' ||\n node.type === 'self' ||\n node.type === 'super'\n );\n}\n\nexport function objectNodeFromAccessNode(accessNode: SyntaxNode, rule: MemberAccessRule): SyntaxNode | null {\n const objectNode = accessNode.childForFieldName(rule.objectField);\n if (!objectNode || !isReceiverNameNode(objectNode)) return null;\n return objectNode;\n}\n\nexport function isMemberAccessPropertyNameNode(nameNode: SyntaxNode, rules: readonly MemberAccessRule[]): boolean {\n const parent = nameNode.parent;\n if (!parent) return false;\n\n for (const rule of rules) {\n if (parent.type !== rule.parentType) continue;\n if (fieldNodeMatches(parent.childForFieldName(rule.propertyField), nameNode)) return true;\n }\n\n return false;\n}\n\nexport function propertyNodeFromAccessNode(accessNode: SyntaxNode, rule: MemberAccessRule): SyntaxNode | null {\n const propertyNode = accessNode.childForFieldName(rule.propertyField);\n if (!propertyNode || !MEMBER_NAME_NODE_TYPES.has(propertyNode.type)) return null;\n return propertyNode;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from '../types.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../yield-during-work.js';\nimport { memberAccessRulesForLanguageKey } from './registry.js';\nimport { isMemberAccessPropertyNameNode, objectNodeFromAccessNode } from './shared.js';\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\nfunction tagFromReceiverNode(node: SyntaxNode): SymbolTag {\n return {\n name: node.text,\n role: 'ref',\n kind: 'variable',\n startLine: node.startPosition.row,\n startColumn: node.startPosition.column,\n endLine: node.endPosition.row,\n endColumn: node.endPosition.column,\n };\n}\n\nfunction lookupNameNode(\n nameNodes: Map<string, SyntaxNode>,\n tag: SymbolTag,\n): SyntaxNode | null {\n const key = `${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`;\n if (nameNodes.has(key)) return nameNodes.get(key)!;\n\n for (const node of nameNodes.values()) {\n if (\n node.text === tag.name &&\n node.startPosition.row === tag.startLine &&\n node.startPosition.column === tag.startColumn\n ) {\n return node;\n }\n }\n return null;\n}\n\n/** Drop member-access property/call targets \u2014 only the receiver object should be navigable. */\nexport function filterMemberAccessPropertyTags(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n languageKey: string | null,\n): SymbolTag[] {\n const rules = memberAccessRulesForLanguageKey(languageKey);\n if (rules.length === 0) return tags;\n\n return tags.filter((tag) => {\n if (tag.role !== 'ref') return true;\n const nameNode = lookupNameNode(nameNodes, tag);\n if (!nameNode) return true;\n return !isMemberAccessPropertyNameNode(nameNode, rules);\n });\n}\n\n/** Tag the object/receiver identifier in member-access expressions when missing from queries. */\nexport async function augmentMemberReceiverTags(\n tags: SymbolTag[],\n nameNodes: Map<string, SyntaxNode>,\n root: SyntaxNode,\n languageKey: string | null,\n): Promise<SymbolTag[]> {\n const rules = memberAccessRulesForLanguageKey(languageKey);\n if (rules.length === 0) return tags;\n\n const seen = new Set(tags.map(tagDedupeKey));\n const seenRefPositions = new Set(\n tags.filter((tag) => tag.role === 'ref').map((tag) => `${tag.startLine}:${tag.startColumn}:${tag.name}`),\n );\n const out = [...tags];\n const state = createCodeNavYieldState();\n\n for (const rule of rules) {\n for (const accessNode of root.descendantsOfType(rule.parentType)) {\n await yieldDuringCodeNavWork(state);\n const receiverNode = objectNodeFromAccessNode(accessNode, rule);\n if (!receiverNode) continue;\n\n const refPositionKey = `${receiverNode.startPosition.row}:${receiverNode.startPosition.column}:${receiverNode.text}`;\n if (seenRefPositions.has(refPositionKey)) continue;\n\n const tag = tagFromReceiverNode(receiverNode);\n const key = tagDedupeKey(tag);\n if (seen.has(key)) continue;\n\n seen.add(key);\n seenRefPositions.add(refPositionKey);\n out.push(tag);\n nameNodes.set(`${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`, receiverNode);\n }\n }\n\n return out;\n}\n", "import { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nfunction repoNodeModulesDir(fromDir: string): string {\n return join(fromDir, '..', '..', '..', 'node_modules');\n}\n\nfunction firstDirWithWebTreeSitterWasm(candidates: string[]): string | null {\n for (const dir of candidates) {\n if (existsSync(join(dir, 'web-tree-sitter.wasm'))) return dir;\n }\n return null;\n}\n\n/** Directory containing copied `web-tree-sitter.wasm` and language `.wasm` / `tags.scm` assets. */\nexport function getTreeSitterAssetsDir(): string {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n const fromModule = firstDirWithWebTreeSitterWasm([\n join(moduleDir, 'tree-sitter'),\n join(moduleDir, '..', 'tree-sitter'),\n join(moduleDir, '..', '..', 'dist', 'tree-sitter'),\n ]);\n if (fromModule) return fromModule;\n\n const fromNodeModules = firstDirWithWebTreeSitterWasm([join(repoNodeModulesDir(moduleDir), 'web-tree-sitter')]);\n if (fromNodeModules) return fromNodeModules;\n\n throw new Error(\n 'Missing web-tree-sitter.wasm. Run `pnpm build` in packages/cli to copy tree-sitter assets into dist/tree-sitter.',\n );\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Parser, Language, Query, LANGUAGE_VERSION, MIN_COMPATIBLE_VERSION } from 'web-tree-sitter';\nimport { getTreeSitterAssetsDir } from '../tree-sitter-assets-dir.js';\nimport { getLanguageSpec } from '../language-registry.js';\n\nexport type LoadedLanguage = {\n language: Language;\n query: Query;\n};\n\nlet initPromise: Promise<void> | null = null;\nconst loadedByKey = new Map<string, LoadedLanguage>();\nconst failedLanguageKeys = new Set<string>();\nlet runtimeChain: Promise<unknown> = Promise.resolve();\n\nexport function withTreeSitterRuntimeLock<T>(fn: () => T | Promise<T>): Promise<T> {\n const next = runtimeChain.then(() => Promise.resolve(fn()));\n runtimeChain = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n}\n\nexport async function ensureParserInit(): Promise<void> {\n if (!initPromise) {\n const assetsDir = getTreeSitterAssetsDir();\n initPromise = Parser.init({\n locateFile: (scriptName: string) => join(assetsDir, scriptName),\n }).catch((e) => {\n initPromise = null;\n throw e;\n });\n }\n await initPromise;\n}\n\nfunction resolveWasmPath(assetsDir: string, wasmFile: string): string {\n const candidates = [\n join(assetsDir, wasmFile),\n join(assetsDir, '..', '..', 'dist', 'tree-sitter', wasmFile),\n join(assetsDir, '..', '..', '..', 'node_modules', wasmFile.replace('.wasm', ''), wasmFile),\n ];\n const hit = candidates.find((p) => existsSync(p));\n if (!hit) throw new Error(`Missing tree-sitter wasm: ${wasmFile}`);\n return hit;\n}\n\nconst CODE_NAV_QUERIES_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', 'queries');\n\nfunction resolveTagsPath(assetsDir: string, tagsQueryFile: string): string {\n const pkgName = tagsQueryFile.split('/')[0] ?? '';\n const candidates = [\n join(CODE_NAV_QUERIES_ROOT, tagsQueryFile),\n join(assetsDir, tagsQueryFile),\n join(assetsDir, '..', '..', 'dist', 'tree-sitter', tagsQueryFile),\n join(assetsDir, '..', '..', '..', 'node_modules', pkgName, 'queries', 'tags.scm'),\n ];\n const hit = candidates.find((p) => existsSync(p));\n if (!hit) throw new Error(`Missing tags query: ${tagsQueryFile}`);\n return hit;\n}\n\nexport async function loadLanguage(languageKey: string): Promise<LoadedLanguage | null> {\n const spec = getLanguageSpec(languageKey);\n if (!spec) return null;\n if (failedLanguageKeys.has(languageKey)) return null;\n const cached = loadedByKey.get(languageKey);\n if (cached) return cached;\n await ensureParserInit();\n const assetsDir = getTreeSitterAssetsDir();\n const language = await Language.load(resolveWasmPath(assetsDir, spec.wasmFile));\n const abiVersion = language.abiVersion;\n if (abiVersion < MIN_COMPATIBLE_VERSION || abiVersion > LANGUAGE_VERSION) {\n failedLanguageKeys.add(languageKey);\n throw new Error(\n `Incompatible tree-sitter ABI for ${languageKey}: grammar=${abiVersion}, runtime=${MIN_COMPATIBLE_VERSION}-${LANGUAGE_VERSION}`,\n );\n }\n const tagsSource = readFileSync(resolveTagsPath(assetsDir, spec.tagsQueryFile), 'utf8');\n const query = new Query(language, tagsSource);\n const loaded = { language, query };\n loadedByKey.set(languageKey, loaded);\n return loaded;\n}\n", "import { Parser, type SyntaxNode } from 'web-tree-sitter';\nimport {\n assertBackgroundIndexingAllowed,\n yieldForBridgeInteractivePriority,\n} from '../../files/browser/in-flight.js';\nimport { isSymbolIndexDeferredError } from '../symbol-index/deferred-indexing.js';\nimport { getLanguageKeyForFilePath } from '../language-registry.js';\nimport { loadLanguage, withTreeSitterRuntimeLock, type LoadedLanguage } from './tree-sitter-runtime.js';\n\nexport type ParsedSourceRoot = {\n root: SyntaxNode;\n loaded: LoadedLanguage;\n cleanup: () => void;\n};\n\nexport async function parseSourceRoot(filePath: string, source: string): Promise<ParsedSourceRoot | null> {\n const languageKey = getLanguageKeyForFilePath(filePath);\n if (!languageKey) return null;\n\n return withTreeSitterRuntimeLock(async () => {\n await yieldForBridgeInteractivePriority();\n let loaded: LoadedLanguage | null;\n try {\n loaded = await loadLanguage(languageKey);\n } catch {\n return null;\n }\n if (!loaded) return null;\n\n const parser = new Parser();\n parser.setLanguage(loaded.language);\n let tree: ReturnType<Parser['parse']> = null;\n try {\n await yieldForBridgeInteractivePriority();\n assertBackgroundIndexingAllowed();\n tree = parser.parse(source);\n assertBackgroundIndexingAllowed();\n await yieldForBridgeInteractivePriority();\n if (!tree) return null;\n return {\n root: tree.rootNode,\n loaded,\n cleanup: () => {\n tree?.delete();\n parser.delete();\n },\n };\n } catch (err) {\n tree?.delete();\n parser.delete();\n if (isSymbolIndexDeferredError(err)) throw err;\n return null;\n }\n });\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport { assertBackgroundIndexingAllowed, yieldForBridgeInteractivePriority } from '../../files/browser/in-flight.js';\nimport type { LoadedLanguage } from './tree-sitter-runtime.js';\n\n/** Run a tree-sitter tags query, yielding before the blocking native work. */\nexport async function runTagsQuery(loaded: LoadedLanguage, root: SyntaxNode) {\n await yieldForBridgeInteractivePriority();\n assertBackgroundIndexingAllowed();\n const matches = loaded.query.matches(root);\n assertBackgroundIndexingAllowed();\n await yieldForBridgeInteractivePriority();\n return matches;\n}\n", "import type { QueryMatch, SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolTag } from '../types.js';\n\nfunction parseCaptureRole(captureName: string): { role: 'def' | 'ref'; kind: string } | null {\n if (captureName === 'name') return null;\n const dot = captureName.indexOf('.');\n if (dot < 0) return null;\n const prefix = captureName.slice(0, dot);\n const kind = captureName.slice(dot + 1);\n if (prefix === 'definition') return { role: 'def', kind };\n if (prefix === 'reference') return { role: 'ref', kind };\n return null;\n}\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\nexport function tagsFromMatches(matches: QueryMatch[]): { tags: SymbolTag[]; nameNodes: Map<string, SyntaxNode> } {\n const tags: SymbolTag[] = [];\n const nameNodes = new Map<string, SyntaxNode>();\n const seen = new Set<string>();\n for (const match of matches) {\n let name: string | null = null;\n let nameNode: QueryMatch['captures'][number]['node'] | null = null;\n const roleNodes: Array<{ role: 'def' | 'ref'; kind: string; node: QueryMatch['captures'][number]['node'] }> = [];\n for (const capture of match.captures) {\n if (capture.name === 'name') {\n name = capture.node.text;\n nameNode = capture.node;\n continue;\n }\n const parsed = parseCaptureRole(capture.name);\n if (parsed) roleNodes.push({ ...parsed, node: capture.node });\n }\n if (!name || !nameNode || roleNodes.length === 0) continue;\n for (const roleNode of roleNodes) {\n const tag: SymbolTag = {\n name,\n role: roleNode.role,\n kind: roleNode.kind,\n startLine: nameNode.startPosition.row,\n startColumn: nameNode.startPosition.column,\n endLine: nameNode.endPosition.row,\n endColumn: nameNode.endPosition.column,\n };\n const key = tagDedupeKey(tag);\n if (seen.has(key)) continue;\n seen.add(key);\n tags.push(tag);\n nameNodes.set(`${tag.startLine}:${tag.startColumn}:${tag.name}:${tag.role}:${tag.kind}`, nameNode);\n }\n }\n return { tags, nameNodes };\n}\n", "import type { QueryMatch, SyntaxNode } from 'web-tree-sitter';\nimport type { CodeNavYieldState } from '../yield-during-work.js';\nimport { yieldDuringCodeNavWork } from '../yield-during-work.js';\nimport type { SymbolTag } from '../types.js';\nimport { tagsFromMatches } from './tags-from-matches.js';\n\nfunction tagDedupeKey(tag: SymbolTag): string {\n return `${tag.startLine}:${tag.startColumn}:${tag.endLine}:${tag.endColumn}:${tag.role}:${tag.kind}:${tag.name}`;\n}\n\n/** Process one match at a time so tag extraction can yield to the event loop. */\nexport async function tagsFromMatchesAsync(\n matches: QueryMatch[],\n state: CodeNavYieldState,\n): Promise<{ tags: SymbolTag[]; nameNodes: Map<string, SyntaxNode> }> {\n const tags: SymbolTag[] = [];\n const nameNodes = new Map<string, SyntaxNode>();\n const seen = new Set<string>();\n\n for (const match of matches) {\n await yieldDuringCodeNavWork(state);\n const partial = tagsFromMatches([match]);\n for (const tag of partial.tags) {\n const key = tagDedupeKey(tag);\n if (seen.has(key)) continue;\n seen.add(key);\n tags.push(tag);\n }\n for (const [key, node] of partial.nameNodes) nameNodes.set(key, node);\n }\n\n return { tags, nameNodes };\n}\n", "import { getLanguageKeyForFilePath } from '../language-registry.js';\nimport { augmentFunctionTypeParamReferenceTags } from '../augment-function-type-param-references.js';\nimport { augmentTypeReferenceTags } from '../augment-type-reference-tags.js';\nimport { enrichTagsWithEnclosingScope } from '../enrich-tag-scope.js';\nimport { filterMemberAccessPropertyTags, augmentMemberReceiverTags } from '../member-access/index.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../yield-during-work.js';\nimport { yieldForBridgeInteractivePriority } from '../../files/browser/in-flight.js';\nimport { isSymbolIndexDeferredError } from '../symbol-index/deferred-indexing.js';\nimport type { SymbolTag } from '../types.js';\nimport { parseSourceRoot } from './parse-source-root.js';\nimport { runTagsQuery } from './run-tags-query.js';\nimport { tagsFromMatchesAsync } from './tags-from-matches-async.js';\n\nexport async function extractTagsFromSource(filePath: string, source: string): Promise<SymbolTag[]> {\n const languageKey = getLanguageKeyForFilePath(filePath);\n await yieldForBridgeInteractivePriority();\n const parsed = await parseSourceRoot(filePath, source);\n if (!parsed) return [];\n try {\n const yieldState = createCodeNavYieldState();\n const matches = await runTagsQuery(parsed.loaded, parsed.root);\n const { tags, nameNodes } = await tagsFromMatchesAsync(matches, yieldState);\n await yieldDuringCodeNavWork(yieldState);\n const filtered = filterMemberAccessPropertyTags(tags, nameNodes, languageKey);\n const withTypes = await augmentTypeReferenceTags(filtered, nameNodes, parsed.root);\n await yieldDuringCodeNavWork(yieldState);\n const withFunctionTypeParamRefs = await augmentFunctionTypeParamReferenceTags(withTypes, nameNodes, parsed.root);\n await yieldDuringCodeNavWork(yieldState);\n const withReceivers = await augmentMemberReceiverTags(withFunctionTypeParamRefs, nameNodes, parsed.root, languageKey);\n await yieldDuringCodeNavWork(yieldState);\n return await enrichTagsWithEnclosingScope(withReceivers, nameNodes);\n } catch (err) {\n if (isSymbolIndexDeferredError(err)) throw err;\n return [];\n } finally {\n parsed.cleanup();\n }\n}\n", "export { extractTagsFromSource } from './parser/extract-tags.js';\nexport { parseSourceRoot, type ParsedSourceRoot } from './parser/parse-source-root.js';\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport { resolveImportSourcePath } from '../../resolve-module-import-path.js';\nimport type { SymbolImportBinding, SymbolImportKind } from '../../types.js';\n\nexport function pushBinding(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n moduleSpecifier: string,\n localName: string,\n sourceName: string,\n importKind: SymbolImportKind,\n nameNode: SyntaxNode,\n): void {\n if (!localName) return;\n out.push({\n localName,\n sourceName,\n moduleSpecifier,\n sourceFilePath: resolveImportSourcePath(filePath, moduleSpecifier, workspaceFiles),\n importKind,\n startLine: nameNode.startPosition.row,\n startColumn: nameNode.startPosition.column,\n });\n}\n\nexport function stripQuotes(text: string): string {\n const trimmed = text.trim();\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nexport function stringLiteralText(node: SyntaxNode): string {\n const fragment = node.descendantsOfType('string_fragment')[0];\n return stripQuotes(fragment?.text ?? node.text);\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nexport function extractCIncludeBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('preproc_include')) {\n const pathNode = node.childForFieldName('path');\n if (!pathNode) continue;\n const includePath = stringLiteralText(pathNode);\n const localName = includePath.split('/').filter(Boolean).at(-1)?.replace(/\\.(h|hpp)$/, '') ?? includePath;\n pushBinding(out, filePath, workspaceFiles, includePath, localName, localName, 'default', pathNode);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { extractCIncludeBindings } from './c.js';\n\nexport function extractCppImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n return extractCIncludeBindings(root, filePath, workspaceFiles);\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding, SymbolImportKind } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nfunction importKindForSpecifier(specifier: SyntaxNode, statementKind: SymbolImportKind): SymbolImportKind {\n if (specifier.children.some((child) => child.type === 'type')) return 'type';\n return statementKind;\n}\n\nfunction collectFromImportSpecifier(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n moduleSpecifier: string,\n importKind: SymbolImportKind,\n specifier: SyntaxNode,\n): void {\n const nameNode = specifier.childForFieldName('name');\n const aliasNode = specifier.childForFieldName('alias');\n if (!nameNode) return;\n const sourceName = nameNode.text;\n const localName = aliasNode?.text ?? sourceName;\n const effectiveKind = importKindForSpecifier(specifier, importKind);\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, localName, sourceName, effectiveKind, aliasNode ?? nameNode);\n}\n\nfunction collectFromImportClause(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n moduleSpecifier: string,\n importKind: SymbolImportKind,\n clause: SyntaxNode,\n): void {\n const defaultName = clause.childForFieldName('name');\n if (defaultName) {\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, defaultName.text, defaultName.text, 'default', defaultName);\n }\n\n for (const child of clause.children) {\n if (child.type === 'named_imports') {\n for (const spec of child.children) {\n if (spec.type === 'import_specifier') {\n collectFromImportSpecifier(out, filePath, workspaceFiles, moduleSpecifier, importKind, spec);\n }\n }\n }\n if (child.type === 'import_specifier') {\n collectFromImportSpecifier(out, filePath, workspaceFiles, moduleSpecifier, importKind, child);\n }\n if (child.type === 'namespace_import') {\n const alias = child.childForFieldName('name') ?? child.namedChildren.find((n) => n.type === 'identifier');\n if (alias) {\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, alias.text, alias.text, 'namespace', alias);\n }\n }\n }\n}\n\nfunction moduleSpecifierFromImport(node: SyntaxNode): string | null {\n const source = node.childForFieldName('source');\n if (!source) return null;\n return stringLiteralText(source);\n}\n\nexport function collectFromImportStatement(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n const moduleSpecifier = moduleSpecifierFromImport(node);\n if (!moduleSpecifier) return;\n\n const isTypeImport = node.children.some((child) => child.type === 'type');\n const importKind: SymbolImportKind = isTypeImport ? 'type' : 'named';\n\n const clause = node.children.find((child) => child.type === 'import_clause');\n if (clause) {\n collectFromImportClause(out, filePath, workspaceFiles, moduleSpecifier, importKind, clause);\n }\n}\n\nexport function extractEcmaScriptImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('import_statement')) {\n collectFromImportStatement(out, filePath, workspaceFiles, node);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding, SymbolImportKind } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nfunction exportKindForSpecifier(specifier: SyntaxNode, statementKind: SymbolImportKind): SymbolImportKind {\n if (specifier.children.some((child) => child.type === 'type')) return 'type';\n return statementKind;\n}\n\nfunction collectFromExportSpecifier(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n moduleSpecifier: string,\n exportKind: SymbolImportKind,\n specifier: SyntaxNode,\n): void {\n const nameNode = specifier.childForFieldName('name');\n const aliasNode = specifier.childForFieldName('alias');\n if (!nameNode) return;\n const sourceName = nameNode.text;\n const localName = aliasNode?.text ?? sourceName;\n const effectiveKind = exportKindForSpecifier(specifier, exportKind);\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, localName, sourceName, effectiveKind, aliasNode ?? nameNode);\n}\n\nfunction moduleSpecifierFromExport(node: SyntaxNode): string | null {\n const source = node.childForFieldName('source');\n if (!source) return null;\n return stringLiteralText(source);\n}\n\nfunction isStarReexport(node: SyntaxNode): boolean {\n if (!moduleSpecifierFromExport(node)) return false;\n if (node.descendantsOfType('export_specifier').length > 0) return false;\n if (node.descendantsOfType('namespace_export').length > 0) return false;\n if (node.childForFieldName('declaration')) return false;\n return node.text.includes('*');\n}\n\n/** Collect re-export bindings from `export \u2026 from 'module'` statements. */\nexport function extractEcmaScriptReexportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('export_statement')) {\n const moduleSpecifier = moduleSpecifierFromExport(node);\n if (!moduleSpecifier) continue;\n\n const isTypeExport = node.children.some((child) => child.type === 'type');\n const exportKind: SymbolImportKind = isTypeExport ? 'type' : 'reexport';\n\n if (isStarReexport(node)) {\n const anchor = node.childForFieldName('source') ?? node;\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, '*', '*', 'star', anchor);\n continue;\n }\n\n for (const spec of node.descendantsOfType('export_specifier')) {\n collectFromExportSpecifier(out, filePath, workspaceFiles, moduleSpecifier, exportKind, spec);\n }\n\n for (const ns of node.descendantsOfType('namespace_export')) {\n const alias = ns.childForFieldName('name') ?? ns.namedChildren.find((n) => n.type === 'identifier');\n if (alias) {\n pushBinding(out, filePath, workspaceFiles, moduleSpecifier, alias.text, alias.text, 'namespace', alias);\n }\n }\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { extractEcmaScriptImportBindings } from './ecma-script-imports.js';\nimport { extractEcmaScriptReexportBindings } from './ecma-script-exports.js';\n\nexport { extractEcmaScriptImportBindings } from './ecma-script-imports.js';\n\n/** Extract import and re-export bindings for ECMAScript modules. */\nexport function extractEcmaScriptBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const imports = extractEcmaScriptImportBindings(root, filePath, workspaceFiles);\n const reexports = extractEcmaScriptReexportBindings(root, filePath, workspaceFiles);\n return [...imports, ...reexports];\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nfunction collectImportSpec(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n spec: SyntaxNode,\n): void {\n const pathNode = spec.childForFieldName('path');\n if (!pathNode) return;\n const modulePath = stringLiteralText(pathNode);\n\n const nameNode = spec.childForFieldName('name');\n if (nameNode) {\n pushBinding(out, filePath, workspaceFiles, modulePath, nameNode.text, nameNode.text, 'namespace', nameNode);\n return;\n }\n\n const localName = modulePath.split('/').filter(Boolean).at(-1) ?? modulePath;\n pushBinding(out, filePath, workspaceFiles, modulePath, localName, localName, 'namespace', pathNode);\n}\n\nexport function extractGoImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('import_declaration')) {\n for (const spec of node.descendantsOfType('import_spec')) {\n collectImportSpec(out, filePath, workspaceFiles, spec);\n }\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding } from './shared.js';\n\nfunction localNameFromImport(nameNode: SyntaxNode): string {\n return nameNode.text.split('.').at(-1) ?? nameNode.text;\n}\n\nfunction collectImportDeclaration(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n for (const child of node.namedChildren) {\n if (child.type === 'scoped_identifier' || child.type === 'identifier') {\n const sourceName = child.text;\n const localName = localNameFromImport(child);\n pushBinding(out, filePath, workspaceFiles, sourceName, localName, sourceName, 'named', child);\n }\n }\n}\n\nexport function extractJavaImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('import_declaration')) {\n collectImportDeclaration(out, filePath, workspaceFiles, node);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding } from './shared.js';\n\nfunction dottedNameText(node: SyntaxNode): string {\n return node.text.replace(/\\s+/g, '');\n}\n\nfunction collectImportStatement(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return;\n const moduleName = dottedNameText(nameNode);\n const localName = moduleName.split('.').at(-1) ?? moduleName;\n pushBinding(out, filePath, workspaceFiles, moduleName, localName, localName, 'namespace', nameNode);\n}\n\nfunction collectImportFromStatement(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n const moduleNode = node.childForFieldName('module_name');\n const moduleName = moduleNode ? dottedNameText(moduleNode) : '';\n for (const child of node.namedChildren) {\n if (child.type !== 'dotted_name' && child.type !== 'aliased_import') continue;\n if (child === moduleNode) continue;\n\n if (child.type === 'dotted_name') {\n const sourceName = dottedNameText(child);\n const localName = sourceName.split('.').at(-1) ?? sourceName;\n pushBinding(out, filePath, workspaceFiles, moduleName, localName, sourceName, 'named', child);\n continue;\n }\n\n const nameNode = child.childForFieldName('name');\n const aliasNode = child.childForFieldName('alias');\n if (!nameNode) continue;\n const sourceName = dottedNameText(nameNode);\n const localName = aliasNode ? aliasNode.text : sourceName.split('.').at(-1) ?? sourceName;\n pushBinding(out, filePath, workspaceFiles, moduleName, localName, sourceName, 'named', aliasNode ?? nameNode);\n }\n}\n\nexport function extractPythonImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('import_statement')) {\n collectImportStatement(out, filePath, workspaceFiles, node);\n }\n for (const node of root.descendantsOfType('import_from_statement')) {\n collectImportFromStatement(out, filePath, workspaceFiles, node);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding, stringLiteralText } from './shared.js';\n\nfunction collectRequireCall(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n node: SyntaxNode,\n): void {\n const methodNode = node.childForFieldName('method');\n if (!methodNode || (methodNode.text !== 'require' && methodNode.text !== 'require_relative')) return;\n\n const args = node.childForFieldName('arguments');\n const stringNode = args?.descendantsOfType('string')[0] ?? args?.descendantsOfType('string_content')[0];\n if (!stringNode) return;\n\n const modulePath = stringLiteralText(stringNode);\n const localName = modulePath.split('/').filter(Boolean).at(-1)?.replace(/\\.rb$/, '') ?? modulePath;\n pushBinding(out, filePath, workspaceFiles, modulePath, localName, localName, 'default', stringNode);\n}\n\nexport function extractRubyImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('call')) {\n collectRequireCall(out, filePath, workspaceFiles, node);\n }\n return out;\n}\n", "import type { SyntaxNode } from 'web-tree-sitter';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { pushBinding } from './shared.js';\n\nfunction identifierFromUseTree(node: SyntaxNode): SyntaxNode | null {\n if (node.type === 'identifier' || node.type === 'type_identifier') return node;\n const nameNode = node.childForFieldName('name');\n if (nameNode) return nameNode;\n for (const child of node.namedChildren) {\n const hit = identifierFromUseTree(child);\n if (hit) return hit;\n }\n return null;\n}\n\nfunction useDeclarationIsPublic(node: SyntaxNode): boolean {\n return node.children.some((child) => child.type === 'visibility_modifier' && child.text === 'pub');\n}\n\nfunction collectUseTree(\n out: SymbolImportBinding[],\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n pathPrefix: string,\n node: SyntaxNode,\n importKind: SymbolImportBinding['importKind'] = 'named',\n): void {\n if (node.type === 'use_as_clause') {\n const pathNode = node.childForFieldName('path');\n const aliasNode = node.childForFieldName('alias');\n if (!pathNode || !aliasNode) return;\n const sourceName = identifierFromUseTree(pathNode)?.text ?? pathNode.text.split('::').at(-1) ?? '';\n pushBinding(out, filePath, workspaceFiles, pathPrefix, aliasNode.text, sourceName, importKind, aliasNode);\n return;\n }\n\n if (node.type === 'identifier' || node.type === 'type_identifier') {\n const sourceName = node.text;\n pushBinding(out, filePath, workspaceFiles, pathPrefix, sourceName, sourceName, importKind, node);\n return;\n }\n\n if (node.type === 'scoped_identifier') {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return;\n const sourceName = nameNode.text;\n pushBinding(out, filePath, workspaceFiles, pathPrefix, sourceName, sourceName, importKind, nameNode);\n return;\n }\n\n if (node.type === 'use_list') {\n for (const child of node.namedChildren) {\n collectUseTree(out, filePath, workspaceFiles, pathPrefix, child, importKind);\n }\n return;\n }\n\n if (node.type === 'scoped_use_list') {\n const pathNode = node.childForFieldName('path');\n const nextPrefix = pathNode ? `${pathPrefix}${pathNode.text}::` : pathPrefix;\n for (const child of node.namedChildren) {\n if (child === pathNode) continue;\n collectUseTree(out, filePath, workspaceFiles, nextPrefix, child, importKind);\n }\n return;\n }\n\n for (const child of node.namedChildren) {\n collectUseTree(out, filePath, workspaceFiles, pathPrefix, child, importKind);\n }\n}\n\nexport function extractRustImportBindings(\n root: SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n): SymbolImportBinding[] {\n const out: SymbolImportBinding[] = [];\n for (const node of root.descendantsOfType('use_declaration')) {\n const argument = node.childForFieldName('argument');\n if (!argument) continue;\n const importKind = useDeclarationIsPublic(node) ? 'reexport' : 'named';\n collectUseTree(out, filePath, workspaceFiles, '', argument, importKind);\n }\n return out;\n}\n", "import { getLanguageKeyForFilePath } from '../../language-registry.js';\nimport { parseSourceRoot } from '../../parser-runtime.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../../yield-during-work.js';\nimport { yieldToEventLoop } from '../../../runtime/yield-to-event-loop.js';\nimport type { SymbolImportBinding } from '../../types.js';\nimport { extractCIncludeBindings } from './c.js';\nimport { extractCppImportBindings } from './cpp.js';\nimport { extractEcmaScriptBindings } from './ecma-script.js';\nimport { extractGoImportBindings } from './go.js';\nimport { extractJavaImportBindings } from './java.js';\nimport { extractPythonImportBindings } from './python.js';\nimport { extractRubyImportBindings } from './ruby.js';\nimport { extractRustImportBindings } from './rust.js';\n\ntype ImportExtractor = (\n root: import('web-tree-sitter').SyntaxNode,\n filePath: string,\n workspaceFiles: ReadonlySet<string>,\n) => SymbolImportBinding[];\n\nconst EXTRACTORS_BY_LANGUAGE_KEY: Readonly<Record<string, ImportExtractor>> = {\n javascript: extractEcmaScriptBindings,\n typescript: extractEcmaScriptBindings,\n tsx: extractEcmaScriptBindings,\n python: extractPythonImportBindings,\n go: extractGoImportBindings,\n rust: extractRustImportBindings,\n ruby: extractRubyImportBindings,\n java: extractJavaImportBindings,\n c: extractCIncludeBindings,\n cpp: extractCppImportBindings,\n};\n\nexport async function extractImportBindingsFromSource(\n filePath: string,\n source: string,\n workspaceFiles: ReadonlySet<string>,\n): Promise<SymbolImportBinding[]> {\n const languageKey = getLanguageKeyForFilePath(filePath);\n if (!languageKey) return [];\n\n const extract = EXTRACTORS_BY_LANGUAGE_KEY[languageKey];\n if (!extract) return [];\n\n const parsed = await parseSourceRoot(filePath, source);\n if (!parsed) return [];\n try {\n await yieldToEventLoop();\n const yieldState = createCodeNavYieldState();\n await yieldDuringCodeNavWork(yieldState);\n const bindings = extract(parsed.root, filePath, workspaceFiles);\n await yieldDuringCodeNavWork(yieldState);\n return bindings;\n } finally {\n parsed.cleanup();\n }\n}\n", "import fs from 'node:fs';\nimport { isMainThread } from 'node:worker_threads';\nimport { assertBackgroundIndexingAllowed } from '../../../files/browser/in-flight.js';\nimport { isCliImmediateShutdownRequested } from '../../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../../../sqlite/code-nav-cache/database.js';\nimport { isSymbolIndexDeferredError } from '../deferred-indexing.js';\n\nexport const MAX_INDEX_FILE_BYTES = 512 * 1024;\n\nexport function assertSymbolIndexNotShutdown(): void {\n if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();\n}\n\nfunction readIndexSourceFileSync(absPath: string): string | null {\n assertSymbolIndexNotShutdown();\n assertBackgroundIndexingAllowed();\n const stat = fs.statSync(absPath);\n if (!stat.isFile() || stat.size > MAX_INDEX_FILE_BYTES) return null;\n assertBackgroundIndexingAllowed();\n return fs.readFileSync(absPath, 'utf8');\n}\n\nexport async function readIndexSourceFile(absPath: string): Promise<string | null> {\n try {\n if (!isMainThread) {\n return readIndexSourceFileSync(absPath);\n }\n assertSymbolIndexNotShutdown();\n assertBackgroundIndexingAllowed();\n const stat = await fs.promises.stat(absPath);\n if (!stat.isFile() || stat.size > MAX_INDEX_FILE_BYTES) return null;\n assertBackgroundIndexingAllowed();\n return await fs.promises.readFile(absPath, 'utf8');\n } catch (err) {\n if (isSymbolIndexDeferredError(err)) throw err;\n return null;\n }\n}\n", "import type { Database } from 'node-sqlite3-wasm';\nimport { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { getSymbolIndexParentContext } from '../sqlite/symbol-index-sqlite.js';\nimport { listEffectiveIndexedFilePaths } from '../storage/symbol-parent-file-map.js';\n\nexport function listWorkspaceFiles(db: Database, workspacePath: string, includePath: string): Set<string> {\n const files = new Set<string>([includePath.replace(/\\\\/g, '/')]);\n\n const normalizedWorkspace = normalizeResolvedPath(workspacePath);\n const parentRow = db.get('SELECT id FROM file_index_parent_path WHERE path = ?', [normalizedWorkspace]) as\n | { id: number | bigint }\n | null;\n if (parentRow != null) {\n const fromIndex = db.all('SELECT path FROM file_index_child_path WHERE parent_id = ?', [\n Number(parentRow.id),\n ]) as Array<{ path: string }>;\n for (const row of fromIndex) files.add(row.path.replace(/\\\\/g, '/'));\n }\n\n const ctx = getSymbolIndexParentContext(db, normalizedWorkspace);\n if (ctx != null) {\n for (const filePath of listEffectiveIndexedFilePaths(db, ctx)) {\n files.add(filePath.replace(/\\\\/g, '/'));\n }\n }\n\n return files;\n}\n", "import fs from 'node:fs';\nimport path from 'node:path';\nimport { isMainThread } from 'node:worker_threads';\nimport {\n assertBackgroundIndexingAllowed,\n yieldForBridgeInteractivePriority,\n} from '../../../files/browser/in-flight.js';\nimport { isSymbolIndexDeferredError } from '../deferred-indexing.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { enrichTagsWithModulePathsAsync } from '../../enrich-tag-module-paths-async.js';\nimport { isPathGitIgnored } from '../../gitignore-filter.js';\nimport { isCodeNavSupportedPath } from '../../language-registry.js';\nimport { extractTagsFromSource } from '../../parser-runtime.js';\nimport { createCodeNavYieldState } from '../../yield-during-work.js';\nimport type { SymbolImportBinding, SymbolTag } from '../../types.js';\nimport { extractImportBindingsFromSource } from '../imports/index.js';\nimport { MAX_INDEX_FILE_BYTES } from './read-index-source.js';\nimport { listWorkspaceFiles } from './workspace-files.js';\n\nexport type FileSymbolData = {\n source: string | null;\n tags: SymbolTag[];\n imports: SymbolImportBinding[];\n};\n\nexport async function extractFileSymbolData(\n resolved: string,\n relPath: string,\n workspaceFilesOverride?: ReadonlySet<string>,\n): Promise<FileSymbolData> {\n await yieldForBridgeInteractivePriority();\n const absPath = path.join(resolved, relPath);\n\n let tags: SymbolTag[] = [];\n let source: string | null = null;\n if (isCodeNavSupportedPath(relPath) && !(await isPathGitIgnored(resolved, relPath))) {\n try {\n assertBackgroundIndexingAllowed();\n let fileSource: string | null = null;\n if (isMainThread) {\n const stat = await fs.promises.stat(absPath);\n if (stat.isFile() && stat.size <= MAX_INDEX_FILE_BYTES) {\n assertBackgroundIndexingAllowed();\n fileSource = await fs.promises.readFile(absPath, 'utf8');\n }\n } else {\n const stat = fs.statSync(absPath);\n if (stat.isFile() && stat.size <= MAX_INDEX_FILE_BYTES) {\n assertBackgroundIndexingAllowed();\n fileSource = fs.readFileSync(absPath, 'utf8');\n }\n }\n source = fileSource;\n if (source != null) {\n await yieldForBridgeInteractivePriority();\n tags = await extractTagsFromSource(relPath, source);\n }\n } catch (err) {\n if (isSymbolIndexDeferredError(err)) throw err;\n tags = [];\n source = null;\n }\n }\n\n await yieldForBridgeInteractivePriority();\n const workspaceFiles =\n workspaceFilesOverride ??\n (await withCodeNavCacheSqlite((db) => listWorkspaceFiles(db, resolved, relPath)));\n const imports =\n source != null ? await extractImportBindingsFromSource(relPath, source, workspaceFiles) : [];\n\n const yieldState = createCodeNavYieldState();\n return {\n source,\n tags: await enrichTagsWithModulePathsAsync(tags, relPath, workspaceFiles, yieldState),\n imports,\n };\n}\n", "import { yieldForBridgeInteractivePriority } from '../../../files/browser/in-flight.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { expandStarReexportForFile } from '../imports/expand-star-reexports.js';\nimport { persistSymbolIndexFileAsync } from '../persistence/persist-single-file.js';\nimport { getSymbolIndexParentContext, upsertSymbolIndexParentPath } from '../sqlite/symbol-index-sqlite.js';\nimport { withSymbolIndexSqliteLock } from '../sqlite/symbol-index-sqlite-lock.js';\nimport type { SymbolIndexFileEntry } from './collect-file-entries.js';\nimport { extractFileSymbolData } from './extract-file-symbol-data.js';\nimport { loadIndexedFileEntry } from './load-indexed-file-entry.js';\n\nexport async function indexOneSymbolFileForBuild(\n resolved: string,\n relPath: string,\n workspaceFiles?: ReadonlySet<string>,\n): Promise<void> {\n await yieldForBridgeInteractivePriority();\n const data = await extractFileSymbolData(resolved, relPath, workspaceFiles);\n let entry: SymbolIndexFileEntry = {\n relPath,\n source: data.source,\n tags: data.tags,\n imports: data.imports,\n };\n\n if (data.imports.some((binding) => binding.importKind === 'star')) {\n await yieldForBridgeInteractivePriority();\n entry = await withCodeNavCacheSqlite((db) => {\n const ctx = getSymbolIndexParentContext(db, resolved);\n if (ctx == null) return entry;\n const resolveEntry = (filePath: string) => loadIndexedFileEntry(db, ctx, filePath);\n return expandStarReexportForFile(entry, resolveEntry);\n });\n entry.source = data.source;\n }\n\n await withSymbolIndexSqliteLock(async () => {\n await yieldForBridgeInteractivePriority();\n await persistSymbolIndexFileAsync(resolved, relPath, entry.source, entry.tags, entry.imports);\n });\n}\n", "export function normalizeSymbolIndexRelPath(filePath: string): string {\n return filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { listDirectImportTargetsForFileAsync } from '../query/list-direct-import-targets.js';\nimport { symbolIndexFileIsReadyAsync } from '../lifecycle/symbol-index-file-ready.js';\nimport { upsertSymbolIndexParentPath } from '../sqlite/symbol-index-sqlite.js';\nimport { indexOneSymbolFileForBuild } from './index-one-symbol-file-for-build.js';\nimport { normalizeSymbolIndexRelPath } from './normalize-symbol-index-rel-path.js';\n\nexport { indexOneSymbolFileForBuild } from './index-one-symbol-file-for-build.js';\n\nconst MAX_IMPORT_PREFETCH_DEPTH = 1;\nconst MAX_IMPORT_PREFETCH_COUNT = 8;\n\n/**\n * Index a single file (and a shallow import closure) on demand.\n * Returns true when the requested file is ready for queries.\n */\nexport async function ensureSymbolIndexFileImpl(\n parentPath: string,\n filePath: string,\n opts?: { importDepth?: number },\n): Promise<boolean> {\n const resolved = normalizeResolvedPath(parentPath);\n const relPath = normalizeSymbolIndexRelPath(filePath);\n if (!relPath) return false;\n\n const importDepth = opts?.importDepth ?? 0;\n\n await withCodeNavCacheSqlite((db) => {\n upsertSymbolIndexParentPath(db, resolved);\n });\n\n if (!(await symbolIndexFileIsReadyAsync(resolved, relPath))) {\n await indexOneSymbolFileForBuild(resolved, relPath, undefined);\n }\n\n if (importDepth > 0 && (await symbolIndexFileIsReadyAsync(resolved, relPath))) {\n const targets = (await listDirectImportTargetsForFileAsync(resolved, relPath)).slice(\n 0,\n MAX_IMPORT_PREFETCH_COUNT,\n );\n for (const target of targets) {\n if (!(await symbolIndexFileIsReadyAsync(resolved, target))) {\n await ensureSymbolIndexFileImpl(resolved, target, { importDepth: importDepth - 1 });\n }\n }\n }\n\n return await symbolIndexFileIsReadyAsync(resolved, relPath);\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { runCodeNavCacheWriteTransaction } from '../../../sqlite/code-nav-cache/code-nav-cache-sqlite-transaction.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../../yield-during-work.js';\nimport { createWalkYieldState, walkCodeNavFilesAsync } from '../../walk-code-nav-files.js';\nimport {\n clearSymbolIndexParentDataBatch,\n getSymbolIndexParentContext,\n upsertSymbolIndexParentPath,\n} from '../sqlite/symbol-index-sqlite.js';\nimport { withSymbolIndexSqliteLock } from '../sqlite/symbol-index-sqlite-lock.js';\nimport { indexOneSymbolFileForBuild } from './ensure-symbol-index-file-impl.js';\n\nconst SYMBOL_PARENT_CLEAR_BATCH_SIZE = 256;\n\n/**\n * Stream one file at a time \u2014 workspace paths kept in a string Set only (not full tag arrays).\n */\nexport async function buildSymbolIndexImpl(parentPath: string): Promise<{ fileCount: number; tagCount: number }> {\n const resolved = normalizeResolvedPath(parentPath);\n\n let clearRemaining = true;\n while (clearRemaining) {\n await withSymbolIndexSqliteLock(async () => {\n clearRemaining = await withCodeNavCacheSqlite((db) =>\n runCodeNavCacheWriteTransaction(db, () => {\n upsertSymbolIndexParentPath(db, resolved);\n const ctx = getSymbolIndexParentContext(db, resolved);\n return ctx == null ? false : clearSymbolIndexParentDataBatch(db, ctx, SYMBOL_PARENT_CLEAR_BATCH_SIZE);\n }),\n );\n });\n }\n\n const workspaceFiles = new Set<string>();\n const walkState = createWalkYieldState();\n const yieldState = createCodeNavYieldState();\n\n await walkCodeNavFilesAsync(\n resolved,\n async (relPath) => {\n await yieldDuringCodeNavWork(yieldState);\n workspaceFiles.add(relPath);\n },\n walkState,\n );\n\n let fileCount = 0;\n await walkCodeNavFilesAsync(\n resolved,\n async (relPath) => {\n await yieldDuringCodeNavWork(yieldState);\n await indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles);\n fileCount += 1;\n },\n walkState,\n );\n\n return { fileCount, tagCount: 0 };\n}\n", "export { buildSymbolIndexImpl as buildSymbolIndexInWorkerHost } from './build-symbol-index-impl.js';\n", "export {\n ensureSymbolIndexFileImpl as ensureSymbolIndexFileInWorkerHost,\n indexOneSymbolFileForBuild,\n} from './ensure-symbol-index-file-impl.js';\n", "import path from 'node:path';\n\nexport function normalizeSymbolIndexRelPath(parentPath: string, changedPath: string): string | null {\n const resolvedParent = path.resolve(parentPath);\n const abs = path.isAbsolute(changedPath) ? path.resolve(changedPath) : path.resolve(resolvedParent, changedPath);\n const rel = path.relative(resolvedParent, abs).replace(/\\\\/g, '/');\n if (rel.startsWith('..') || path.isAbsolute(rel)) return null;\n return rel;\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { yieldToEventLoop } from '../../../runtime/yield-to-event-loop.js';\nimport { normalizeSymbolIndexRelPath } from '../lifecycle/normalize-symbol-index-path.js';\nimport {\n persistSymbolIndexFileAsync,\n removeSymbolIndexFileAsync,\n} from '../persistence/persist-single-file.js';\nimport { withSymbolIndexSqliteLock } from '../sqlite/symbol-index-sqlite-lock.js';\nimport { extractFileSymbolData } from './extract-file-symbol-data.js';\n\nexport async function updateSymbolIndexForFileImpl(\n parentPath: string,\n changedPath: string,\n): Promise<void> {\n const relPath = normalizeSymbolIndexRelPath(parentPath, changedPath);\n if (relPath == null) return;\n\n const resolved = normalizeResolvedPath(parentPath);\n const { source, tags, imports } = await extractFileSymbolData(resolved, relPath);\n await yieldToEventLoop();\n\n await withSymbolIndexSqliteLock(async () => {\n await persistSymbolIndexFileAsync(resolved, relPath, source, tags, imports);\n });\n}\n\nexport async function removeSymbolIndexForFileImpl(parentPath: string, changedPath: string): Promise<void> {\n const relPath = normalizeSymbolIndexRelPath(parentPath, changedPath);\n if (relPath == null) return;\n const resolved = normalizeResolvedPath(parentPath);\n await withSymbolIndexSqliteLock(async () => {\n await removeSymbolIndexFileAsync(resolved, relPath);\n });\n}\n\n/** Worker host entry when the caller already has a normalized relative path. */\nexport async function updateSymbolIndexRelPathImpl(parentPath: string, relPath: string): Promise<void> {\n const normalizedRel = relPath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!normalizedRel) return;\n const resolved = normalizeResolvedPath(parentPath);\n const { source, tags, imports } = await extractFileSymbolData(resolved, normalizedRel);\n await yieldToEventLoop();\n await withSymbolIndexSqliteLock(async () => {\n await persistSymbolIndexFileAsync(resolved, normalizedRel, source, tags, imports);\n });\n}\n\n/** Worker host entry when the caller already has a normalized relative path. */\nexport async function removeSymbolIndexRelPathImpl(parentPath: string, relPath: string): Promise<void> {\n const normalizedRel = relPath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!normalizedRel) return;\n const resolved = normalizeResolvedPath(parentPath);\n await withSymbolIndexSqliteLock(async () => {\n await removeSymbolIndexFileAsync(resolved, normalizedRel);\n });\n}\n", "export {\n removeSymbolIndexRelPathImpl as removeSymbolIndexForFileInWorkerHost,\n updateSymbolIndexRelPathImpl as updateSymbolIndexForFileInWorkerHost,\n} from './update-symbol-index-file-impl.js';\n", "import type { SymbolIndexWorkerOutMessage, SymbolIndexWorkerPort } from './protocol.js';\n\nexport function postSafe(port: SymbolIndexWorkerPort, message: SymbolIndexWorkerOutMessage): void {\n try {\n port.postMessage(message);\n } catch {\n /* worker/client may be gone during shutdown */\n }\n}\n", "import { isCliImmediateShutdownRequested } from '../../../runtime/cli-process-interrupt.js';\nimport { CliSqliteInterrupted } from '../../../sqlite/sqlite-errors.js';\nimport { buildSymbolIndexInWorkerHost } from '../build/build-symbol-index-host.js';\nimport { ensureSymbolIndexFileInWorkerHost } from '../build/ensure-symbol-index-file-host.js';\nimport {\n removeSymbolIndexForFileInWorkerHost,\n updateSymbolIndexForFileInWorkerHost,\n} from '../build/update-symbol-index-file-host.js';\nimport { postSafe } from './post-message.js';\nimport type { SymbolIndexWorkerInMessage, SymbolIndexWorkerPort } from './protocol.js';\n\nimport { isSymbolIndexWorkerShutdownRequested } from './shutdown-state.js';\n\nfunction postWorkerError(port: SymbolIndexWorkerPort, requestId: string, err: unknown): void {\n if (\n isCliImmediateShutdownRequested() ||\n isSymbolIndexWorkerShutdownRequested() ||\n err instanceof CliSqliteInterrupted\n ) {\n postSafe(port, {\n type: 'error',\n requestId,\n message: new CliSqliteInterrupted().message,\n });\n return;\n }\n postSafe(port, {\n type: 'error',\n requestId,\n message: err instanceof Error ? err.message : String(err),\n });\n}\n\nexport async function handleIndexWorkerMessage(\n port: SymbolIndexWorkerPort,\n msg: SymbolIndexWorkerInMessage,\n): Promise<void> {\n switch (msg.type) {\n case 'buildFull': {\n try {\n const result = await buildSymbolIndexInWorkerHost(msg.parentPath);\n postSafe(port, { type: 'buildComplete', requestId: msg.requestId, ...result });\n } catch (err) {\n postWorkerError(port, msg.requestId, err);\n }\n return;\n }\n case 'updateFile': {\n try {\n await updateSymbolIndexForFileInWorkerHost(msg.parentPath, msg.relPath);\n postSafe(port, { type: 'updateComplete', requestId: msg.requestId });\n } catch (err) {\n postWorkerError(port, msg.requestId, err);\n }\n return;\n }\n case 'removeFile': {\n try {\n await removeSymbolIndexForFileInWorkerHost(msg.parentPath, msg.relPath);\n postSafe(port, { type: 'removeComplete', requestId: msg.requestId });\n } catch (err) {\n postWorkerError(port, msg.requestId, err);\n }\n return;\n }\n case 'ensureFile': {\n try {\n const ready = await ensureSymbolIndexFileInWorkerHost(msg.parentPath, msg.filePath, {\n importDepth: msg.importDepth,\n });\n postSafe(port, { type: 'ensureComplete', requestId: msg.requestId, ready });\n } catch (err) {\n postWorkerError(port, msg.requestId, err);\n }\n return;\n }\n default:\n return;\n }\n}\n", "import type { PendingSymbolIndexTask } from './task-queue-types.js';\n\nfunction higherPriority(a: PendingSymbolIndexTask, b: PendingSymbolIndexTask): boolean {\n return a.priority > b.priority;\n}\n\nexport class SymbolIndexTaskPriorityHeap {\n private readonly heap: PendingSymbolIndexTask[] = [];\n\n clear(): void {\n this.heap.length = 0;\n }\n\n push(task: PendingSymbolIndexTask): void {\n this.heap.push(task);\n let i = this.heap.length - 1;\n while (i > 0) {\n const parent = Math.floor((i - 1) / 2);\n if (!higherPriority(this.heap[i]!, this.heap[parent]!)) break;\n this.swap(i, parent);\n i = parent;\n }\n }\n\n pop(): PendingSymbolIndexTask | undefined {\n if (this.heap.length === 0) return undefined;\n const top = this.heap[0]!;\n const last = this.heap.pop()!;\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.sink(0);\n }\n return top;\n }\n\n get size(): number {\n return this.heap.length;\n }\n\n private sink(start: number): void {\n let i = start;\n while (true) {\n const left = i * 2 + 1;\n const right = left + 1;\n let best = i;\n if (left < this.heap.length && higherPriority(this.heap[left]!, this.heap[best]!)) best = left;\n if (right < this.heap.length && higherPriority(this.heap[right]!, this.heap[best]!)) best = right;\n if (best === i) break;\n this.swap(i, best);\n i = best;\n }\n }\n\n private swap(i: number, j: number): void {\n const tmp = this.heap[i]!;\n this.heap[i] = this.heap[j]!;\n this.heap[j] = tmp;\n }\n}\n", "export type PendingSymbolIndexTask = {\n parentPath: string;\n filePath: string;\n priority: number;\n sequence?: number;\n};\n\nexport function symbolIndexTaskKey(parentPath: string, filePath: string): string {\n return `${parentPath}\\0${filePath}`;\n}\n", "import { SymbolIndexTaskPriorityHeap } from './task-priority-heap.js';\nimport { symbolIndexTaskKey, type PendingSymbolIndexTask } from './task-queue-types.js';\n\nexport const pendingSymbolIndexTasks = new Map<string, PendingSymbolIndexTask>();\nexport const symbolIndexTaskHeap = new SymbolIndexTaskPriorityHeap();\nexport const latestActiveSequenceByParent = new Map<string, number>();\nexport let symbolIndexWorkerRunning = false;\n\nexport function setSymbolIndexWorkerRunning(running: boolean): void {\n symbolIndexWorkerRunning = running;\n}\n\nexport function taskMatchesCurrentPending(task: PendingSymbolIndexTask): boolean {\n const current = pendingSymbolIndexTasks.get(symbolIndexTaskKey(task.parentPath, task.filePath));\n return current === task;\n}\n\nexport function pickNextSymbolIndexTask(): PendingSymbolIndexTask | undefined {\n while (symbolIndexTaskHeap.size > 0) {\n const task = symbolIndexTaskHeap.pop();\n if (task == null || !taskMatchesCurrentPending(task)) continue;\n return task;\n }\n return undefined;\n}\n\nexport function addPendingSymbolIndexTask(task: PendingSymbolIndexTask): boolean {\n const key = symbolIndexTaskKey(task.parentPath, task.filePath);\n const existing = pendingSymbolIndexTasks.get(key);\n if (existing != null && existing.priority >= task.priority) return false;\n pendingSymbolIndexTasks.set(key, task);\n symbolIndexTaskHeap.push(task);\n return true;\n}\n\nexport function clearSymbolIndexHeapIfEmpty(): void {\n if (pendingSymbolIndexTasks.size === 0) symbolIndexTaskHeap.clear();\n}\n\n/** @internal Test teardown for worker queue state. */\nexport function resetSymbolIndexTaskQueueForTests(): void {\n pendingSymbolIndexTasks.clear();\n symbolIndexTaskHeap.clear();\n latestActiveSequenceByParent.clear();\n symbolIndexWorkerRunning = false;\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { addPendingSymbolIndexTask, latestActiveSequenceByParent, pendingSymbolIndexTasks, symbolIndexTaskHeap } from './task-queue-store.js';\n\n/** Background warmup and neighbor prefetch sit below interactive code-nav work. */\nexport const SYMBOL_INDEX_BACKGROUND_PRIORITY_MAX = 499_999;\n\nexport function enqueueSymbolIndexTaskInternal(\n parentPath: string,\n filePath: string,\n priority: number,\n sequence?: number,\n): boolean {\n const normalizedParent = normalizeResolvedPath(parentPath);\n const normalizedFile = filePath.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!normalizedFile) return false;\n\n return addPendingSymbolIndexTask({\n parentPath: normalizedParent,\n filePath: normalizedFile,\n priority,\n sequence,\n });\n}\n\nexport function markLatestActiveSymbolIndexTaskInternal(parentPath: string, sequence: number): void {\n const normalizedParent = normalizeResolvedPath(parentPath);\n const existing = latestActiveSequenceByParent.get(normalizedParent);\n if (existing != null && existing >= sequence) return;\n latestActiveSequenceByParent.set(normalizedParent, sequence);\n\n for (const [key, task] of pendingSymbolIndexTasks) {\n if (task.parentPath === normalizedParent && task.sequence != null && task.sequence < sequence) {\n pendingSymbolIndexTasks.delete(key);\n }\n }\n if (pendingSymbolIndexTasks.size === 0) symbolIndexTaskHeap.clear();\n}\n\n/** Drop low-priority queued work when the user starts browsing files. */\nexport function deferBackgroundSymbolIndexTasks(): void {\n if (pendingSymbolIndexTasks.size === 0) return;\n\n for (const [key, task] of pendingSymbolIndexTasks) {\n if (task.priority <= SYMBOL_INDEX_BACKGROUND_PRIORITY_MAX) {\n pendingSymbolIndexTasks.delete(key);\n }\n }\n\n symbolIndexTaskHeap.clear();\n for (const task of pendingSymbolIndexTasks.values()) {\n symbolIndexTaskHeap.push(task);\n }\n}\n\nexport { deferBackgroundSymbolIndexTasks as deferBackgroundSymbolIndexTasksForTests };\n", "import { isSymbolIndexDeferredError } from '../deferred-indexing.js';\nimport { yieldUntilFileBrowserIdle } from '../../../files/browser/in-flight.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../../yield-during-work.js';\nimport { ensureSymbolIndexFileInWorkerHost } from '../build/ensure-symbol-index-file-host.js';\nimport { symbolIndexFileIsReadyAsync } from '../lifecycle/symbol-index-file-ready.js';\nimport {\n addPendingSymbolIndexTask,\n clearSymbolIndexHeapIfEmpty,\n latestActiveSequenceByParent,\n pendingSymbolIndexTasks,\n pickNextSymbolIndexTask,\n setSymbolIndexWorkerRunning,\n symbolIndexTaskHeap,\n symbolIndexWorkerRunning,\n} from './task-queue-store.js';\nimport { symbolIndexTaskKey } from './task-queue-types.js';\n\nasync function runWorkerLoop(): Promise<void> {\n if (symbolIndexWorkerRunning) return;\n setSymbolIndexWorkerRunning(true);\n try {\n const yieldState = createCodeNavYieldState();\n while (pendingSymbolIndexTasks.size > 0) {\n const task = pickNextSymbolIndexTask();\n if (task == null) break;\n pendingSymbolIndexTasks.delete(symbolIndexTaskKey(task.parentPath, task.filePath));\n await yieldUntilFileBrowserIdle();\n await yieldDuringCodeNavWork(yieldState);\n const latestActiveSequence = latestActiveSequenceByParent.get(task.parentPath);\n if (latestActiveSequence != null && task.sequence != null && task.sequence < latestActiveSequence) {\n continue;\n }\n if (!(await symbolIndexFileIsReadyAsync(task.parentPath, task.filePath))) {\n try {\n await ensureSymbolIndexFileInWorkerHost(task.parentPath, task.filePath);\n } catch (err) {\n if (isSymbolIndexDeferredError(err)) {\n if (addPendingSymbolIndexTask(task)) kickSymbolIndexWorkerLoop();\n continue;\n }\n throw err;\n }\n }\n }\n } finally {\n clearSymbolIndexHeapIfEmpty();\n setSymbolIndexWorkerRunning(false);\n if (pendingSymbolIndexTasks.size > 0) void runWorkerLoop();\n }\n}\n\nexport function kickSymbolIndexWorkerLoop(): void {\n void runWorkerLoop();\n}\n\n/** @deprecated Use {@link kickSymbolIndexWorkerLoop}. */\nexport function kickSymbolIndexWorker(): void {\n kickSymbolIndexWorkerLoop();\n}\n", "import { applyFileBrowserActivityFromMain } from '../../../files/browser/in-flight.js';\nimport {\n deferBackgroundSymbolIndexTasks,\n enqueueSymbolIndexTaskInternal,\n markLatestActiveSymbolIndexTaskInternal,\n} from '../scheduler/task-queue-core.js';\nimport { kickSymbolIndexWorkerLoop } from '../scheduler/task-queue-worker.js';\nimport type { SymbolIndexWorkerInMessage } from './protocol.js';\n\nexport function handleQueueWorkerMessage(msg: SymbolIndexWorkerInMessage): void {\n switch (msg.type) {\n case 'enqueue':\n if (enqueueSymbolIndexTaskInternal(msg.parentPath, msg.filePath, msg.priority, msg.sequence)) {\n kickSymbolIndexWorkerLoop();\n }\n return;\n case 'markLatestActive':\n markLatestActiveSymbolIndexTaskInternal(msg.parentPath, msg.sequence);\n return;\n case 'deferBackground':\n deferBackgroundSymbolIndexTasks();\n return;\n case 'fileBrowserActivity':\n applyFileBrowserActivityFromMain({\n inFlightRequests: msg.inFlightRequests,\n inFlightReads: msg.inFlightReads,\n lastActivityAt: msg.lastActivityAt,\n });\n return;\n default:\n return;\n }\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { withCodeNavCacheSqlite } from '../../../sqlite/code-nav-cache/database.js';\nimport { upsertSymbolIndexParentPath } from '../sqlite/symbol-index-sqlite.js';\n\n/** Register parent row without indexing files (cheap). */\nexport async function registerSymbolIndexParentAsync(parentPath: string): Promise<void> {\n const resolved = normalizeResolvedPath(parentPath);\n await withCodeNavCacheSqlite((db) => {\n upsertSymbolIndexParentPath(db, resolved);\n });\n}\n\n/** @deprecated Prefer {@link registerSymbolIndexParentAsync}. */\nexport function registerSymbolIndexParent(parentPath: string): void {\n void registerSymbolIndexParentAsync(parentPath);\n}\n", "import { normalizeResolvedPath } from '../../../paths/normalize-resolved-path.js';\nimport { isBridgeBrowseInteractiveActive, registerFileBrowserActivityListener } from '../../../files/browser/in-flight.js';\nimport { createCodeNavYieldState, yieldDuringCodeNavWork } from '../../yield-during-work.js';\nimport { createWalkYieldState, walkCodeNavFilesAsync } from '../../walk-code-nav-files.js';\nimport { loadSymbolIndexReadyFileSet } from '../lifecycle/symbol-index-file-ready.js';\nimport { enqueueSymbolIndexTaskInternal } from './task-queue-core.js';\nimport { kickSymbolIndexWorkerLoop } from './task-queue-worker.js';\n\nlet requestSeq = 0;\nlet warmupSeq = 0;\nconst warmupCompleted = new Set<string>();\nconst pendingWarmupParents = new Set<string>();\nconst warmupWalkInProgress = new Set<string>();\n\n/** Delay warmup until the user stops browsing files for this long. */\nconst WARMUP_IDLE_MS = 3_000;\n\nlet warmupIdleTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction scheduleWarmupWhenIdle(): void {\n if (warmupIdleTimer != null) clearTimeout(warmupIdleTimer);\n warmupIdleTimer = setTimeout(() => {\n warmupIdleTimer = null;\n if (isBridgeBrowseInteractiveActive()) {\n scheduleWarmupWhenIdle();\n return;\n }\n for (const parentPath of [...pendingWarmupParents]) {\n void runWarmupWalk(parentPath);\n }\n }, WARMUP_IDLE_MS);\n}\n\nregisterFileBrowserActivityListener(() => {\n if (pendingWarmupParents.size > 0) scheduleWarmupWhenIdle();\n});\n\nasync function runWarmupWalk(resolved: string): Promise<void> {\n if (warmupCompleted.has(resolved) || warmupWalkInProgress.has(resolved)) {\n pendingWarmupParents.delete(resolved);\n return;\n }\n warmupWalkInProgress.add(resolved);\n pendingWarmupParents.delete(resolved);\n try {\n if (isBridgeBrowseInteractiveActive()) {\n pendingWarmupParents.add(resolved);\n scheduleWarmupWhenIdle();\n return;\n }\n const readyFiles = await loadSymbolIndexReadyFileSet(resolved);\n const walkState = createWalkYieldState();\n const yieldState = createCodeNavYieldState();\n await walkCodeNavFilesAsync(\n resolved,\n async (relPath) => {\n await yieldDuringCodeNavWork(yieldState);\n if (!readyFiles.has(relPath)) {\n if (enqueueSymbolIndexTaskInternal(resolved, relPath, ++warmupSeq, requestSeq)) {\n kickSymbolIndexWorkerLoop();\n }\n }\n },\n walkState,\n );\n warmupCompleted.add(resolved);\n } finally {\n warmupWalkInProgress.delete(resolved);\n }\n}\n\n/** Low-priority background fill for remaining unindexed files after browse idle. */\nexport function scheduleSymbolIndexWarmupInWorkerHost(parentPath: string): void {\n const resolved = normalizeResolvedPath(parentPath);\n if (warmupCompleted.has(resolved)) return;\n pendingWarmupParents.add(resolved);\n scheduleWarmupWhenIdle();\n}\n\n/** @internal Exposed for tests. */\nexport function resetSymbolIndexWarmupStateForTests(): void {\n warmupCompleted.clear();\n pendingWarmupParents.clear();\n warmupWalkInProgress.clear();\n if (warmupIdleTimer != null) {\n clearTimeout(warmupIdleTimer);\n warmupIdleTimer = null;\n }\n}\n\nexport function bumpSymbolIndexWarmupRequestSeq(): void {\n requestSeq += 1;\n}\n", "import { registerSymbolIndexParentAsync } from '../build/register-symbol-index-parent.js';\nimport { scheduleSymbolIndexWarmupInWorkerHost } from '../scheduler/symbol-index-warmup-host.js';\nimport type { SymbolIndexWorkerInMessage } from './protocol.js';\n\nexport async function handleSetupWorkerMessage(msg: SymbolIndexWorkerInMessage): Promise<void> {\n switch (msg.type) {\n case 'registerParent':\n await registerSymbolIndexParentAsync(msg.parentPath);\n return;\n case 'scheduleWarmup':\n scheduleSymbolIndexWarmupInWorkerHost(msg.parentPath);\n return;\n default:\n return;\n }\n}\n", "import { isCliImmediateShutdownRequested } from '../../../runtime/cli-process-interrupt.js';\nimport { closeAllCodeNavCacheSqliteConnections } from '../../../sqlite/code-nav-cache/database.js';\nimport { maybeLogCodeNavCacheWorkerError } from '../../../sqlite/code-nav-cache/code-nav-cache-log.js';\nimport { CliSqliteInterrupted } from '../../../sqlite/sqlite-errors.js';\nimport { handleIndexWorkerMessage } from './index-handlers.js';\nimport { postSafe } from './post-message.js';\nimport { handleQueueWorkerMessage } from './queue-handlers.js';\nimport { handleSetupWorkerMessage } from './setup-handlers.js';\nimport type { SymbolIndexWorkerInMessage, SymbolIndexWorkerPort } from './protocol.js';\nimport {\n isSymbolIndexWorkerShutdownRequested,\n requestSymbolIndexWorkerShutdown,\n} from './shutdown-state.js';\n\nlet activeWorkerHandlers = 0;\n\nasync function waitForActiveWorkerHandlersIdle(pollMs = 10): Promise<void> {\n while (activeWorkerHandlers > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, pollMs));\n }\n}\n\nexport async function handleRequestMessage(\n port: SymbolIndexWorkerPort,\n msg: SymbolIndexWorkerInMessage,\n): Promise<void> {\n if (msg.type === 'shutdown') {\n requestSymbolIndexWorkerShutdown();\n await waitForActiveWorkerHandlersIdle();\n closeAllCodeNavCacheSqliteConnections();\n postSafe(port, { type: 'shutdownComplete' });\n return;\n }\n\n if (isCliImmediateShutdownRequested() || isSymbolIndexWorkerShutdownRequested()) return;\n\n activeWorkerHandlers += 1;\n try {\n switch (msg.type) {\n case 'enqueue':\n case 'markLatestActive':\n case 'deferBackground':\n case 'fileBrowserActivity':\n handleQueueWorkerMessage(msg);\n return;\n case 'registerParent':\n case 'scheduleWarmup':\n try {\n await handleSetupWorkerMessage(msg);\n } catch (err) {\n if (!(err instanceof CliSqliteInterrupted)) {\n maybeLogCodeNavCacheWorkerError(err instanceof Error ? err.message : String(err));\n }\n }\n return;\n case 'buildFull':\n case 'updateFile':\n case 'removeFile':\n case 'ensureFile':\n await handleIndexWorkerMessage(port, msg);\n return;\n default:\n return;\n }\n } catch (err) {\n if (err instanceof CliSqliteInterrupted) return;\n throw err;\n } finally {\n activeWorkerHandlers = Math.max(0, activeWorkerHandlers - 1);\n }\n}\n", "import { handleRequestMessage } from './handle-message.js';\nimport { postSafe } from './post-message.js';\nimport type { SymbolIndexWorkerPort } from './protocol.js';\n\nexport function attachSymbolIndexWorkerHost(port: SymbolIndexWorkerPort): void {\n port.onMessage((message) => {\n void handleRequestMessage(port, message);\n });\n postSafe(port, { type: 'ready' });\n}\n", "import { parentPort, workerData } from 'node:worker_threads';\nimport { bindFileBrowserActivitySharedBuffer } from '../../../files/browser/in-flight.js';\nimport { setCodeNavCacheDiagnosticSink } from '../../../sqlite/code-nav-cache/code-nav-cache-log.js';\nimport { attachSymbolIndexWorkerHost } from './host.js';\nimport type { SymbolIndexWorkerInMessage, SymbolIndexWorkerOutMessage } from './protocol.js';\n\nif (parentPort == null) {\n throw new Error('symbol index worker must run as a worker thread');\n}\n\nsetCodeNavCacheDiagnosticSink((line) => {\n parentPort!.postMessage({ type: 'cliLog', line } satisfies SymbolIndexWorkerOutMessage);\n});\n\nconst activityBuffer = (workerData as { fileBrowserActivityBuffer?: SharedArrayBuffer } | undefined)\n ?.fileBrowserActivityBuffer;\nif (activityBuffer instanceof SharedArrayBuffer) {\n bindFileBrowserActivitySharedBuffer(activityBuffer);\n}\n\nattachSymbolIndexWorkerHost({\n postMessage(message: SymbolIndexWorkerOutMessage) {\n parentPort!.postMessage(message);\n },\n onMessage(handler: (message: SymbolIndexWorkerInMessage) => void) {\n parentPort!.on('message', handler);\n },\n});\n"],
5
5
  "mappings": "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",
6
6
  "names": ["isMainThread", "inFlightRequests", "inFlightReads", "fs", "fs", "path", "fs", "initPromise", "fs", "path", "fs", "path", "os", "path", "os", "path", "os", "fs", "path", "fs", "path", "fs", "path", "os", "fs", "path", "fs", "CHECKPOINT_V1", "CHECKPOINT_V1_SQL", "path", "fs", "path", "ignore", "path", "fs", "path", "path", "init_paths", "init_paths", "crypto", "released", "normalizeRelPath", "path", "dottedPath", "tagDedupeKey", "chain", "chain", "tagDedupeKey", "existsSync", "dirname", "join", "fileURLToPath", "existsSync", "readFileSync", "dirname", "join", "fileURLToPath", "initPromise", "Parser", "tagDedupeKey", "tagDedupeKey", "init_shared", "init_c", "init_shared", "init_cpp", "init_c", "init_shared", "init_shared", "init_go", "init_shared", "init_java", "init_shared", "sourceName", "localName", "init_python", "init_shared", "init_ruby", "init_shared", "init_rust", "init_shared", "init_c", "init_cpp", "init_go", "init_java", "init_python", "init_ruby", "init_rust", "fs", "path", "isMainThread"]
7
7
  }