@leanlabsinnov/codegraph 0.1.5 → 0.1.7

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 +0,0 @@
1
- {"version":3,"sources":["../src/config-store.ts","../src/ui.ts","../src/program.ts","../src/commands/config.ts","../src/commands/doctor.ts","../src/ollama.ts","../src/commands/index.ts","../../ingestion/src/parser.ts","../../ingestion/src/extractors/extract.ts","../../ingestion/src/walker.ts","../../ingestion/src/extractors/extract-python.ts","../../ingestion/src/extractors/routes.ts","../../ingestion/src/extractors/resolve.ts","../../ingestion/src/orchestrator.ts","../../ingestion/src/embedder.ts","../../ingestion/src/tsconfig.ts","../../ingestion/src/repo-walker.ts","../src/repo-id.ts","../src/commands/init.ts","../../mcp-server/src/bootstrap.ts","../../mcp-server/src/cache.ts","../../mcp-server/src/config.ts","../../mcp-server/src/server.ts","../../mcp-server/src/tools/affected-by.ts","../../mcp-server/src/tools/util.ts","../../mcp-server/src/tools/blast-radius.ts","../../mcp-server/src/tools/find-callers.ts","../../mcp-server/src/tools/find-file.ts","../../mcp-server/src/tools/get-component-tree.ts","../../mcp-server/src/tools/get-dependencies.ts","../../mcp-server/src/tools/get-file-context.ts","../../mcp-server/src/tools/nl-query.ts","../../mcp-server/src/cypher-guard.ts","../../mcp-server/src/tools/search-semantic.ts","../../mcp-server/src/tools/search-symbol.ts","../../mcp-server/src/tools/index.ts","../../mcp-server/src/viewer-routes.ts","../../mcp-server/src/logger.ts","../src/commands/serve.ts","../src/commands/view.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { type CodegraphConfig, DEFAULT_CONFIG } from \"@codegraph/shared\";\n\nconst CONFIG_DIR = path.join(os.homedir(), \".codegraph\");\nconst CONFIG_FILE = path.join(CONFIG_DIR, \"config.json\");\n\nexport function configPath(): string {\n return CONFIG_FILE;\n}\n\nexport async function loadConfig(): Promise<CodegraphConfig> {\n try {\n const raw = await readFile(CONFIG_FILE, \"utf8\");\n const parsed = JSON.parse(raw) as Partial<CodegraphConfig>;\n return mergeConfig(DEFAULT_CONFIG, parsed);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return DEFAULT_CONFIG;\n }\n throw err;\n }\n}\n\nexport async function saveConfig(config: CodegraphConfig): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n await writeFile(CONFIG_FILE, `${JSON.stringify(config, null, 2)}\\n`, \"utf8\");\n}\n\nfunction mergeConfig(base: CodegraphConfig, override: Partial<CodegraphConfig>): CodegraphConfig {\n return {\n llm: {\n ...base.llm,\n ...(override.llm ?? {}),\n generation: { ...base.llm.generation, ...(override.llm?.generation ?? {}) },\n embeddings: { ...base.llm.embeddings, ...(override.llm?.embeddings ?? {}) },\n },\n server: { ...base.server, ...(override.server ?? {}) },\n data: { ...base.data, ...(override.data ?? {}) },\n };\n}\n","import boxen from \"boxen\";\nimport Table from \"cli-table3\";\nimport kleur from \"kleur\";\nimport ora, { type Ora } from \"ora\";\n\n/**\n * Shared terminal-UI helpers used by every CLI command. Keeping them in one place means\n * the look-and-feel stays consistent and tests can replace them with no-ops if needed.\n */\n\n/** ASCII wordmark printed by the banner box. Roman font, stripped of trailing whitespace. */\nconst ASCII_LOGO = ` ___ _ ___ _\n / __\\\\___ __| | ___ / _ \\\\_ __ __ _ _ __ | |__\n / / / _ \\\\ / _\\` |/ _ \\\\/ /_\\\\/ '__/ _\\` | '_ \\\\| '_ \\\\\n/ /__| (_) | (_| | __/ /_\\\\\\\\| | | (_| | |_) | | | |\n\\\\____/\\\\___/ \\\\__,_|\\\\___\\\\____/|_| \\\\__,_| .__/|_| |_|\n |_|`;\n\nconst TAGLINE = \"Live, queryable knowledge graph for your codebase.\";\n\n/** First-run / --help banner. Quiet in non-TTY contexts so it doesn't pollute pipes. */\nexport function printBanner(): void {\n if (!process.stdout.isTTY) return;\n const body = `${kleur.cyan(ASCII_LOGO)}\\n\\n${kleur.dim(TAGLINE)}`;\n process.stdout.write(\n `${boxen(body, {\n padding: { top: 0, bottom: 0, left: 2, right: 2 },\n margin: { top: 0, bottom: 1, left: 0, right: 0 },\n borderStyle: \"round\",\n borderColor: \"cyan\",\n title: kleur.bold(\"codegraph\"),\n titleAlignment: \"left\",\n })}\\n`,\n );\n}\n\n/**\n * Create an `ora` spinner that disables itself when not on a TTY (so CI logs stay clean)\n * and renders consistent prefix-text formatting.\n */\nexport function makeSpinner(text: string): Ora {\n return ora({\n text,\n color: \"cyan\",\n spinner: \"dots\",\n isEnabled: process.stdout.isTTY === true,\n });\n}\n\n/**\n * Minimal text-mode progress bar. Re-renders in place on the same line; falls back to a\n * dim per-step line in non-TTY contexts (CI logs).\n */\nexport class ProgressBar {\n private lastRender = 0;\n private readonly width: number;\n constructor(\n private readonly label: string,\n private readonly total: number,\n width = 28,\n ) {\n this.width = width;\n }\n\n update(current: number): void {\n if (this.total <= 0) return;\n if (process.stdout.isTTY !== true) {\n // Non-TTY: print every 25th step so logs stay short but show progress.\n if (current === this.total || current - this.lastRender >= 25) {\n process.stdout.write(`${kleur.dim(`${this.label}: ${current}/${this.total}`)}\\n`);\n this.lastRender = current;\n }\n return;\n }\n const ratio = Math.min(1, current / this.total);\n const filled = Math.round(ratio * this.width);\n const bar = `${\"█\".repeat(filled)}${\"░\".repeat(this.width - filled)}`;\n const pct = `${(ratio * 100).toFixed(0).padStart(3)}%`;\n process.stdout.write(\n `\\r${kleur.cyan(this.label.padEnd(10))} ${kleur.cyan(bar)} ${pct} ${current}/${this.total}`,\n );\n if (current >= this.total) process.stdout.write(\"\\n\");\n }\n\n done(): void {\n this.update(this.total);\n }\n}\n\n/** Render the `codegraph status` output as two compact tables plus a coverage line. */\nexport function renderStatusTables(\n repoId: string,\n stats: { nodes: Record<string, number>; edges: Record<string, number>; embeddingCoverage: number },\n): string {\n const nodeTable = new Table({\n head: [kleur.bold(\"Node kind\"), kleur.bold(\"Count\")],\n colAligns: [\"left\", \"right\"],\n style: { head: [], border: [\"grey\"] },\n });\n for (const [kind, count] of Object.entries(stats.nodes)) {\n nodeTable.push([kind, count]);\n }\n const edgeTable = new Table({\n head: [kleur.bold(\"Edge kind\"), kleur.bold(\"Count\")],\n colAligns: [\"left\", \"right\"],\n style: { head: [], border: [\"grey\"] },\n });\n for (const [kind, count] of Object.entries(stats.edges)) {\n edgeTable.push([kind, count]);\n }\n const coverage = `${kleur.bold(\"Embedding coverage:\")} ${kleur.cyan(\n `${(stats.embeddingCoverage * 100).toFixed(1)}%`,\n )}`;\n return [kleur.bold(`Status for ${repoId}`), \"\", nodeTable.toString(), edgeTable.toString(), coverage].join(\"\\n\");\n}\n\n/** Render a pretty error block. Used by the top-level bin.ts catch. */\nexport function renderError(err: unknown, opts: { verbose: boolean } = { verbose: false }): string {\n const message = err instanceof Error ? err.message : String(err);\n const hint = friendlyHint(message);\n const lines = [kleur.red().bold(\"✗ codegraph hit an error\"), \"\", kleur.red(message)];\n if (hint) {\n lines.push(\"\", kleur.yellow(\"hint: \"), kleur.yellow(hint));\n }\n if (opts.verbose && err instanceof Error && err.stack) {\n lines.push(\"\", kleur.dim(err.stack));\n } else if (err instanceof Error) {\n lines.push(\"\", kleur.dim(\"(re-run with --verbose for a full stack trace)\"));\n }\n return boxen(lines.join(\"\\n\"), {\n padding: 1,\n borderColor: \"red\",\n borderStyle: \"round\",\n });\n}\n\n/**\n * Map common error messages to specific, actionable hints. Keeps support load down by\n * answering the most common Slack pings inline.\n */\nfunction friendlyHint(message: string): string | null {\n if (/OPENAI_API_KEY/i.test(message) || /api key/i.test(message)) {\n return \"Set OPENAI_API_KEY in your shell (or switch to local-ollama with `codegraph config llm set local-ollama`).\";\n }\n if (/ANTHROPIC_API_KEY/i.test(message)) {\n return \"Set ANTHROPIC_API_KEY, or switch presets via `codegraph config llm set <preset>`.\";\n }\n if (/GOOGLE_GENERATIVE_AI_API_KEY/i.test(message)) {\n return \"Set GOOGLE_GENERATIVE_AI_API_KEY, or switch presets via `codegraph config llm set <preset>`.\";\n }\n if (/ECONNREFUSED/.test(message) && /11434/.test(message)) {\n return \"Ollama isn't running on :11434. Start it with `ollama serve`, or switch to a hosted provider.\";\n }\n if (/EACCES|permission denied/i.test(message)) {\n return \"Codegraph stores data in ~/.codegraph. Check that the directory is writable.\";\n }\n if (/database is locked/i.test(message) || /Lock file/i.test(message)) {\n return \"Another `codegraph` process holds the Kuzu DB. Stop it (or remove ~/.codegraph/graph/.lock) before retrying.\";\n }\n if (/Unknown preset/i.test(message)) {\n return \"Run `codegraph config llm set` with no args for an interactive prompt.\";\n }\n return null;\n}\n\n/** Highlighted success banner for the serve command. */\nexport function renderServeBanner(url: string, tokenHint: string, viewerUrl?: string): string {\n const lines = [\n `${kleur.green(\"✓\")} codegraph mcp listening on ${kleur.cyan(url)}`,\n ];\n if (viewerUrl) {\n lines.push(`${kleur.green(\"✓\")} graph viewer on ${kleur.cyan(viewerUrl)}`);\n }\n lines.push(\"\", kleur.dim(tokenHint), kleur.dim(\"Ctrl-C to stop.\"));\n return boxen(lines.join(\"\\n\"), {\n padding: { top: 0, bottom: 0, left: 2, right: 2 },\n margin: { top: 1, bottom: 1, left: 0, right: 0 },\n borderColor: \"green\",\n borderStyle: \"round\",\n });\n}\n","import { Command } from \"commander\";\nimport { runConfigLlmSet, runConfigLlmTest, runConfigShow } from \"./commands/config.js\";\nimport { runDoctorCommand } from \"./commands/doctor.js\";\nimport { runIndexCommand, runStatusCommand, runWipeCommand } from \"./commands/index.js\";\nimport { runInitCommand } from \"./commands/init.js\";\nimport { runServeCommand } from \"./commands/serve.js\";\nimport { runViewCommand } from \"./commands/view.js\";\nimport { printBanner } from \"./ui.js\";\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"codegraph\")\n .description(\"Live, queryable knowledge graph for your codebase\")\n .version(\"0.1.3\")\n .option(\"--verbose\", \"Print full stack traces on error\")\n .hook(\"preAction\", (thisCommand) => {\n // Promote `--verbose` to an env var so the top-level error handler in bin.ts can\n // pick it up without threading it through every command.\n const opts = thisCommand.optsWithGlobals();\n if (opts.verbose) process.env.CODEGRAPH_VERBOSE = \"1\";\n });\n\n // Print the banner on bare `codegraph` (no subcommand) and on `--help`.\n program.on(\"--help\", () => {\n printBanner();\n });\n\n program\n .command(\"init\")\n .description(\"Interactive setup wizard — LLM, credentials, index, MCP, client connect\")\n .action(async () => {\n await runInitCommand();\n });\n\n program\n .command(\"index\")\n .description(\"Parse a JS/TS repo into the local embedded graph\")\n .argument(\"<path>\", \"Path to the repo root\")\n .option(\"--no-embed\", \"Skip the embedding pass (faster, no LLM calls)\")\n .action(async (repoPath: string, opts: { embed?: boolean }) => {\n await runIndexCommand({ repoPath, noEmbed: opts.embed === false });\n });\n\n program\n .command(\"status\")\n .description(\"Show node/edge counts and embedding coverage for a repo\")\n .argument(\"<path>\", \"Path to the repo root\")\n .action(async (repoPath: string) => {\n await runStatusCommand({ repoPath });\n });\n\n program\n .command(\"serve\")\n .description(\"Boot the local MCP server (default port 3748)\")\n .option(\"--port <port>\", \"TCP port to bind\", (v) => Number(v))\n .option(\"--host <host>\", \"Host to bind (default 127.0.0.1)\")\n .option(\"--db-path <path>\", \"Override the embedded Kuzu graph directory\")\n .action(async (opts: { port?: number; host?: string; dbPath?: string }) => {\n await runServeCommand({\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.host !== undefined ? { host: opts.host } : {}),\n ...(opts.dbPath !== undefined ? { dbPath: opts.dbPath } : {}),\n });\n });\n\n program\n .command(\"view\")\n .description(\"Open the graph viewer in the browser (requires codegraph serve to be running)\")\n .option(\"--port <port>\", \"MCP server port to check (default 3748)\", (v) => Number(v))\n .option(\"--host <host>\", \"MCP server host (default 127.0.0.1)\")\n .action(async (opts: { port?: number; host?: string }) => {\n await runViewCommand({\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.host !== undefined ? { host: opts.host } : {}),\n });\n });\n\n program\n .command(\"doctor\")\n .description(\"Check environment, config, LLM credentials, and Kuzu DB health\")\n .action(async () => {\n await runDoctorCommand();\n });\n\n program\n .command(\"wipe\")\n .description(\"Delete a single repo's slice (with [path]) or the entire on-disk graph\")\n .argument(\"[path]\", \"Repo path. Omit to wipe the whole graph directory.\")\n .option(\"--yes\", \"Skip the confirmation prompt\", false)\n .action(async (repoPath: string | undefined, opts: { yes?: boolean }) => {\n await runWipeCommand({\n ...(repoPath ? { repoPath } : {}),\n yes: opts.yes === true,\n });\n });\n\n const configCmd = program.command(\"config\").description(\"Manage ~/.codegraph/config.json\");\n configCmd\n .command(\"show\")\n .description(\"Print the resolved config\")\n .action(async () => {\n await runConfigShow();\n });\n const llmCmd = configCmd.command(\"llm\").description(\"Configure the LLM router\");\n llmCmd\n .command(\"set [preset]\")\n .description(\n \"Set LLM preset: managed-stub | byo-openai | byo-anthropic | byo-google | local-ollama. Omit the preset to pick interactively.\",\n )\n .action(async (preset?: string) => {\n await runConfigLlmSet(preset);\n });\n llmCmd\n .command(\"test\")\n .description(\"Run a 5-token generation + 1 embedding call against the current config\")\n .action(async () => {\n await runConfigLlmTest();\n });\n\n return program;\n}\n","import { input, password, select } from \"@inquirer/prompts\";\nimport { createLlmRouter, namespaceLabel } from \"@codegraph/llm-router\";\nimport { LLM_PRESETS } from \"@codegraph/shared\";\nimport kleur from \"kleur\";\nimport { configPath, loadConfig, saveConfig } from \"../config-store.js\";\nimport { makeSpinner } from \"../ui.js\";\n\nexport async function runConfigShow(): Promise<void> {\n const config = await loadConfig();\n console.log(kleur.dim(`config file: ${configPath()}`));\n console.log(JSON.stringify(config, null, 2));\n}\n\n/**\n * If called with a preset arg, applies it non-interactively. Otherwise launches an\n * interactive picker (preset + optional API key) - this is the path the first-run\n * onboarding takes.\n */\nexport async function runConfigLlmSet(presetArg?: string): Promise<void> {\n const presetKeys = Object.keys(LLM_PRESETS);\n let preset = presetArg;\n if (!preset) {\n preset = await select({\n message: \"Which LLM preset?\",\n choices: presetKeys.map((id) => ({\n name: id,\n value: id,\n description: describePreset(id),\n })),\n });\n }\n const lookup = LLM_PRESETS[preset];\n if (!lookup) {\n throw new Error(`Unknown preset \"${preset}\". Available: ${presetKeys.join(\", \")}`);\n }\n const config = await loadConfig();\n config.llm = { ...config.llm, ...lookup };\n // Clear any previously saved custom base URL when switching to a non-custom preset\n if (preset !== \"local-openai-compatible\") {\n config.llm.baseUrl = undefined;\n }\n\n if (!presetArg && preset === \"local-openai-compatible\") {\n const url = await promptBaseUrl();\n if (url) config.llm.baseUrl = url;\n }\n\n await saveConfig(config);\n console.log(kleur.green(`✓ saved preset \"${preset}\" to ${configPath()}`));\n console.log(kleur.dim(`embedding namespace: ${namespaceLabel(config.llm)}`));\n\n if (!presetArg && preset !== \"local-openai-compatible\") {\n await maybePromptForApiKey(preset);\n }\n}\n\n/**\n * Best-effort prompt for the API key the chosen preset needs. We persist it via a stdout\n * hint rather than writing it to disk - shell history / env vars are still the right place\n * for secrets.\n */\nasync function maybePromptForApiKey(preset: string): Promise<void> {\n const envVar = apiKeyEnvVarFor(preset);\n if (!envVar) return;\n if (process.env[envVar]) {\n console.log(kleur.dim(`✓ ${envVar} already set in environment`));\n return;\n }\n const provideNow = await select({\n message: `${envVar} is not set. Provide it now?`,\n choices: [\n { name: \"Yes (paste; I'll print the export line)\", value: \"yes\" },\n { name: \"No, I'll set it later\", value: \"no\" },\n ],\n });\n if (provideNow !== \"yes\") {\n console.log(\n kleur.yellow(`! Set ${envVar} in your shell before running \\`codegraph index\\``),\n );\n return;\n }\n const value = await password({ message: `${envVar} value (input hidden)`, mask: \"*\" });\n if (!value) return;\n console.log(kleur.dim(\"Add this to your ~/.zshrc or ~/.bashrc:\"));\n console.log(kleur.cyan(` export ${envVar}=${value}`));\n}\n\nfunction apiKeyEnvVarFor(preset: string): string | null {\n if (preset === \"byo-openai\" || preset === \"managed-stub\") return \"OPENAI_API_KEY\";\n if (preset === \"byo-anthropic\") return \"ANTHROPIC_API_KEY\";\n if (preset === \"byo-google\") return \"GOOGLE_GENERATIVE_AI_API_KEY\";\n return null; // local-ollama and local-openai-compatible need no API key\n}\n\nfunction describePreset(id: string): string {\n switch (id) {\n case \"managed-stub\":\n return \"Phase-2 placeholder - same as BYO OpenAI\";\n case \"byo-openai\":\n return \"Your own OpenAI key (gpt-4o-mini + text-embedding-3-small)\";\n case \"byo-anthropic\":\n return \"Anthropic for gen, OpenAI for embeddings\";\n case \"byo-google\":\n return \"Gemini for gen + Google embeddings\";\n case \"local-ollama\":\n return \"Fully local via Ollama (qwen2.5-coder:1.5b + nomic-embed-text)\";\n case \"local-openai-compatible\":\n return \"Any OpenAI-compatible server (llama.cpp, LM Studio, vLLM) — you supply the URL\";\n default:\n return \"\";\n }\n}\n\n/**\n * Prompt for the base URL needed by the local-openai-compatible preset.\n * Returns the trimmed URL, or an empty string if the user skips.\n */\nasync function promptBaseUrl(): Promise<string> {\n const url = await input({\n message: \"Server base URL (e.g. http://localhost:8080/v1):\",\n validate: (v) =>\n v.trim() === \"\" || v.trim().startsWith(\"http\")\n ? true\n : \"Must be an http(s) URL (or leave empty to set later)\",\n });\n const trimmed = url.trim();\n if (!trimmed) {\n console.log(\n kleur.yellow(\n \"! No URL saved. Edit ~/.codegraph/config.json to set llm.baseUrl before indexing.\",\n ),\n );\n }\n return trimmed;\n}\n\nexport async function runConfigLlmTest(): Promise<void> {\n const config = await loadConfig();\n console.log(kleur.dim(\"testing llm config:\"));\n console.log(kleur.dim(` mode ${config.llm.mode}`));\n console.log(\n kleur.dim(` generate ${config.llm.generation.provider}:${config.llm.generation.model}`),\n );\n console.log(\n kleur.dim(` embed ${config.llm.embeddings.provider}:${config.llm.embeddings.model}`),\n );\n const spinner = makeSpinner(\"Calling provider\").start();\n try {\n const router = await createLlmRouter({ config: config.llm });\n const result = await router.selfTest();\n spinner.succeed(\"LLM provider reachable\");\n console.log(` embed dims: ${result.embedDims}`);\n console.log(` embed latency: ${result.embedLatencyMs}ms`);\n console.log(` generate latency: ${result.generateLatencyMs}ms`);\n console.log(` namespace: ${namespaceLabel(config.llm)}`);\n } catch (err) {\n spinner.fail(\"LLM provider unreachable\");\n throw err;\n }\n}\n","import { access, constants, mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { defaultDbPath, GraphDb } from \"@codegraph/graph-db\";\nimport { createLlmRouter } from \"@codegraph/llm-router\";\nimport kleur from \"kleur\";\nimport { configPath, loadConfig } from \"../config-store.js\";\nimport { detectOllama, LOCAL_MODELS } from \"../ollama.js\";\n\ninterface Check {\n name: string;\n status: \"ok\" | \"warn\" | \"fail\";\n detail: string;\n}\n\n/**\n * `codegraph doctor` is a one-shot health check: Node version, config presence, LLM\n * provider credentials, Kuzu DB path writability, plus a tiny self-test against the\n * configured LLM. Designed to be the first thing we ask new users to run when they hit\n * a problem - it should print enough context to triage almost anything in support.\n */\nexport async function runDoctorCommand(): Promise<void> {\n const checks: Check[] = [];\n checks.push(checkNodeVersion());\n\n let config: Awaited<ReturnType<typeof loadConfig>> | null = null;\n try {\n config = await loadConfig();\n checks.push({ name: \"config file\", status: \"ok\", detail: configPath() });\n } catch (err) {\n checks.push({\n name: \"config file\",\n status: \"fail\",\n detail: err instanceof Error ? err.message : String(err),\n });\n }\n\n const dbPath = config?.data.dbPath ?? defaultDbPath();\n checks.push(await checkWritable(\"graph dir\", dbPath));\n\n if (config) {\n checks.push(checkApiKey(config.llm.generation.provider));\n if (config.llm.embeddings.provider !== config.llm.generation.provider) {\n checks.push(checkApiKey(config.llm.embeddings.provider));\n }\n }\n\n // Proactive Ollama daemon check — surfaces a clear actionable message before the\n // generic LLM round-trip so users see \"ollama not running\" rather than ECONNREFUSED.\n if (config && config.llm.generation.provider === \"ollama\") {\n checks.push(await checkOllamaDaemon());\n }\n\n if (config) {\n checks.push(await selfTestLlm(config));\n checks.push(await selfTestKuzu(dbPath, config.llm.embeddings.dimension));\n }\n\n let failed = 0;\n let warned = 0;\n for (const c of checks) {\n const icon =\n c.status === \"ok\" ? kleur.green(\"✓\") : c.status === \"warn\" ? kleur.yellow(\"!\") : kleur.red(\"✗\");\n const name = c.name.padEnd(18);\n const detail = c.status === \"ok\" ? kleur.dim(c.detail) : c.detail;\n console.log(`${icon} ${name} ${detail}`);\n if (c.status === \"fail\") failed++;\n if (c.status === \"warn\") warned++;\n }\n console.log();\n if (failed > 0) {\n console.log(kleur.red().bold(`${failed} check(s) failed; codegraph won't work as-is.`));\n process.exitCode = 1;\n return;\n }\n if (warned > 0) {\n console.log(kleur.yellow(`${warned} warning(s); core flows work, optional features may not.`));\n return;\n }\n console.log(kleur.green().bold(\"All checks passed. You're ready to `codegraph index <repo>`.\"));\n}\n\nfunction checkNodeVersion(): Check {\n const version = process.versions.node;\n const major = Number(version.split(\".\")[0] ?? 0);\n if (major >= 20) {\n return { name: \"node version\", status: \"ok\", detail: `v${version}` };\n }\n return {\n name: \"node version\",\n status: \"fail\",\n detail: `v${version} (codegraph requires >= 20)`,\n };\n}\n\nasync function checkWritable(name: string, path: string): Promise<Check> {\n try {\n await mkdir(dirname(path), { recursive: true });\n try {\n await access(path, constants.W_OK);\n } catch {\n // Doesn't exist yet - that's fine as long as the parent is writable.\n await access(dirname(path), constants.W_OK);\n }\n return { name, status: \"ok\", detail: path };\n } catch (err) {\n return {\n name,\n status: \"fail\",\n detail: `${path} (${err instanceof Error ? err.message : String(err)})`,\n };\n }\n}\n\nfunction checkApiKey(provider: string): Check {\n const envVar = providerEnvVar(provider);\n if (envVar === null) {\n return { name: `${provider} key`, status: \"ok\", detail: \"(no key needed)\" };\n }\n if (process.env[envVar]) {\n return { name: envVar, status: \"ok\", detail: \"set\" };\n }\n return {\n name: envVar,\n status: \"fail\",\n detail: `unset (export ${envVar}=... or switch presets)`,\n };\n}\n\nfunction providerEnvVar(provider: string): string | null {\n if (provider === \"openai\") return \"OPENAI_API_KEY\";\n if (provider === \"anthropic\") return \"ANTHROPIC_API_KEY\";\n if (provider === \"google\") return \"GOOGLE_GENERATIVE_AI_API_KEY\";\n return null;\n}\n\nasync function checkOllamaDaemon(): Promise<Check> {\n const s = await detectOllama();\n switch (s.status) {\n case \"ready\":\n return { name: \"ollama daemon\", status: \"ok\", detail: \"running, models present\" };\n case \"running-no-models\":\n return {\n name: \"ollama daemon\",\n status: \"warn\",\n detail: `running — pull missing models: ollama pull ${LOCAL_MODELS.generation} && ollama pull ${LOCAL_MODELS.embeddings}`,\n };\n case \"installed-not-running\":\n return {\n name: \"ollama daemon\",\n status: \"fail\",\n detail: \"installed but not running — start with `ollama serve`\",\n };\n case \"not-installed\":\n return {\n name: \"ollama daemon\",\n status: \"fail\",\n detail: \"not installed — see https://ollama.com\",\n };\n }\n}\n\nasync function selfTestLlm(\n config: Awaited<ReturnType<typeof loadConfig>>,\n): Promise<Check> {\n try {\n const router = await createLlmRouter({ config: config.llm });\n const result = await router.selfTest();\n return {\n name: \"llm round-trip\",\n status: \"ok\",\n detail: `embed=${result.embedLatencyMs}ms gen=${result.generateLatencyMs}ms`,\n };\n } catch (err) {\n return {\n name: \"llm round-trip\",\n status: \"fail\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nasync function selfTestKuzu(dbPath: string, embeddingDimension: number): Promise<Check> {\n const db = new GraphDb({ dbPath, embeddingDimension });\n try {\n await db.connect();\n await db.migrate();\n // Round-trip `array_cosine_similarity` (a core Kuzu function, no extension) so the\n // doctor proves the actual semantic-search code path works, not just basic SQL.\n const result = await db.query<{ ok: boolean; similarity: number }>(\n `RETURN array_cosine_similarity([1.0, 0.0], [1.0, 0.0]) AS similarity, true AS ok`,\n );\n await db.close();\n const row = result.data[0];\n if (row?.ok !== true || typeof row.similarity !== \"number\") {\n return { name: \"kuzu round-trip\", status: \"fail\", detail: \"unexpected result\" };\n }\n return {\n name: \"kuzu round-trip\",\n status: \"ok\",\n detail: \"ok (brute-force semantic search ready)\",\n };\n } catch (err) {\n await db.close().catch(() => {});\n return {\n name: \"kuzu round-trip\",\n status: \"fail\",\n detail: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type OllamaStatus =\n | { status: \"ready\"; models: string[] }\n | { status: \"running-no-models\"; models: string[] }\n | { status: \"installed-not-running\" }\n | { status: \"not-installed\" };\n\n/** Default models used for the local-ollama preset. */\nexport const LOCAL_MODELS = {\n generation: \"qwen2.5-coder:1.5b\",\n embeddings: \"nomic-embed-text\",\n} as const;\n\n/**\n * Probes the local Ollama daemon and binary. Returns one of four states:\n * - ready: running with the required models present\n * - running-no-models: running but required models need to be pulled\n * - installed-not-running: binary found but daemon is not reachable\n * - not-installed: binary not found on PATH\n */\nexport async function detectOllama(): Promise<OllamaStatus> {\n // 1. HTTP probe — fast path, tells us if the daemon is up\n try {\n const res = await fetch(\"http://localhost:11434/api/tags\", {\n signal: AbortSignal.timeout(800),\n });\n if (res.ok) {\n const data = (await res.json()) as { models?: Array<{ name: string }> };\n const models = (data.models ?? []).map((m) => m.name);\n const neededPrefixes = [\n LOCAL_MODELS.generation.split(\":\")[0]!,\n LOCAL_MODELS.embeddings,\n ];\n const hasAll = neededPrefixes.every((prefix) =>\n models.some((m) => m.startsWith(prefix)),\n );\n return hasAll\n ? { status: \"ready\", models }\n : { status: \"running-no-models\", models };\n }\n } catch {\n // fall through to binary check\n }\n\n // 2. Binary check — distinguishes \"installed but not running\" from \"not installed\"\n try {\n await execFileAsync(\"ollama\", [\"--version\"], { timeout: 2000 });\n return { status: \"installed-not-running\" };\n } catch {\n // fall through\n }\n\n return { status: \"not-installed\" };\n}\n","import { rm } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { GraphDb, defaultDbPath } from \"@codegraph/graph-db\";\nimport { indexRepo } from \"@codegraph/ingestion\";\nimport { createLlmRouter } from \"@codegraph/llm-router\";\nimport kleur from \"kleur\";\nimport { loadConfig } from \"../config-store.js\";\nimport { repoIdFromPath } from \"../repo-id.js\";\nimport { ProgressBar, makeSpinner, renderStatusTables } from \"../ui.js\";\n\nexport interface IndexCommandOptions {\n repoPath: string;\n noEmbed?: boolean;\n}\n\n/**\n * Walks a repository, parses it, optionally embeds every symbol, and writes everything\n * into the embedded Kuzu graph. The command is split into three visible phases - walk,\n * parse, embed - each wrapped in an `ora` spinner so the user sees liveness without\n * scrollbar spam.\n */\nexport async function runIndexCommand(opts: IndexCommandOptions): Promise<void> {\n const config = await loadConfig();\n const absolutePath = path.resolve(opts.repoPath);\n const repoId = repoIdFromPath(absolutePath);\n const dbPath = config.data.dbPath ?? defaultDbPath();\n\n console.log(kleur.dim(`repo: ${absolutePath}`));\n console.log(kleur.dim(`id: ${repoId}`));\n console.log(kleur.dim(`graph: ${dbPath}`));\n console.log(\n kleur.dim(\n `llm: ${config.llm.mode} / gen=${config.llm.generation.provider}:${config.llm.generation.model} / embed=${config.llm.embeddings.provider}:${config.llm.embeddings.model}`,\n ),\n );\n console.log();\n\n const graphDb = new GraphDb({\n dbPath,\n embeddingDimension: config.llm.embeddings.dimension,\n });\n\n const connectSpinner = makeSpinner(\"Opening graph\").start();\n try {\n await graphDb.connect();\n await graphDb.migrate();\n connectSpinner.succeed(`Graph ready ${kleur.dim(`(${dbPath})`)}`);\n } catch (err) {\n connectSpinner.fail(\"Failed to open graph\");\n throw err;\n }\n\n let router: Awaited<ReturnType<typeof createLlmRouter>> | undefined;\n if (!opts.noEmbed) {\n const llmSpinner = makeSpinner(\"Initialising LLM router\").start();\n try {\n router = await createLlmRouter({ config: config.llm });\n llmSpinner.succeed(\"LLM router initialised\");\n } catch (err) {\n llmSpinner.warn(\n `LLM router init failed; continuing without embeddings (${err instanceof Error ? err.message : String(err)})`,\n );\n router = undefined;\n }\n }\n\n // Wrapped in a single-element holder so the closure below can mutate the bar without\n // TypeScript narrowing the outer reference to `never` (control-flow analysis can't see\n // through async callbacks reliably; the holder makes the assignment a property write).\n const bars: { parse: ProgressBar | null; embed: ProgressBar | null } = {\n parse: null,\n embed: null,\n };\n\n const result = await indexRepo({\n repoId,\n repoPath: absolutePath,\n graphDb,\n ...(router ? { router } : {}),\n skipEmbeddings: opts.noEmbed === true || router === undefined,\n onProgress: (event) => {\n if (event.type === \"walk\") {\n console.log(kleur.dim(`walked ${event.files} files`));\n }\n if (event.type === \"parse\") {\n if (!bars.parse) bars.parse = new ProgressBar(\"parsing\", event.total);\n bars.parse.update(event.parsed);\n }\n if (event.type === \"upsert\") {\n console.log(\n kleur.dim(`upserted ${event.nodes} nodes, ${event.edges} edges`),\n );\n }\n if (event.type === \"embed\") {\n if (!bars.embed) bars.embed = new ProgressBar(\"embedding\", event.total);\n bars.embed.update(event.embedded);\n }\n },\n });\n\n bars.parse?.done();\n bars.embed?.done();\n await graphDb.close();\n\n console.log();\n console.log(\n kleur.green().bold(\n `✓ Indexed ${result.nodes} nodes, ${result.edges} edges in ${(result.durationMs / 1000).toFixed(2)}s`,\n ),\n );\n console.log(\n kleur.dim(\n ` parsed=${result.parsedFiles} failed=${result.failedFiles} embeddings=${result.embeddings} dropped_edges=${result.droppedEdges}`,\n ),\n );\n}\n\nexport interface StatusCommandOptions {\n repoPath: string;\n}\n\nexport async function runStatusCommand(opts: StatusCommandOptions): Promise<void> {\n const config = await loadConfig();\n const absolutePath = path.resolve(opts.repoPath);\n const repoId = repoIdFromPath(absolutePath);\n const graphDb = new GraphDb({\n dbPath: config.data.dbPath ?? defaultDbPath(),\n embeddingDimension: config.llm.embeddings.dimension,\n });\n const spinner = makeSpinner(\"Reading graph\").start();\n try {\n await graphDb.connect();\n const stats = await graphDb.stats(repoId);\n await graphDb.close();\n spinner.stop();\n console.log(renderStatusTables(repoId, stats));\n } catch (err) {\n spinner.fail(\"Failed to read graph\");\n throw err;\n }\n}\n\nexport interface WipeCommandOptions {\n /** Optional repo path. When supplied we wipe only that repo's slice. */\n repoPath?: string;\n /** Skip the confirmation prompt - used by tests and `--force`. */\n yes?: boolean;\n}\n\n/**\n * Reset the local graph. Two modes:\n * - With `repoPath`: delete the rows for that single repoId via `DETACH DELETE`. Safe,\n * leaves other indexed repos intact, doesn't touch the schema.\n * - Without `repoPath`: nuke the entire on-disk graph directory. Used when a schema\n * change requires a fresh database (e.g. switching embedding dimensions) or when\n * Kuzu's on-disk metadata gets corrupted.\n *\n * Both modes refuse to run unless `yes` is true, so an accidental `codegraph wipe` in\n * a shared shell never silently deletes work.\n */\nexport async function runWipeCommand(opts: WipeCommandOptions): Promise<void> {\n const config = await loadConfig();\n const dbPath = config.data.dbPath ?? defaultDbPath();\n if (opts.repoPath) {\n const absolutePath = path.resolve(opts.repoPath);\n const repoId = repoIdFromPath(absolutePath);\n if (!opts.yes) {\n console.log(\n kleur.yellow(\n `Will delete all graph rows for ${kleur.bold(repoId)} (${absolutePath}). Pass --yes to confirm.`,\n ),\n );\n return;\n }\n const spinner = makeSpinner(`Wiping ${repoId}`).start();\n const graphDb = new GraphDb({\n dbPath,\n embeddingDimension: config.llm.embeddings.dimension,\n });\n try {\n await graphDb.connect();\n await graphDb.migrate();\n await graphDb.deleteByRepo(repoId);\n await graphDb.close();\n spinner.succeed(`Removed ${repoId} from ${dbPath}`);\n } catch (err) {\n spinner.fail(\"Wipe failed\");\n throw err;\n }\n return;\n }\n if (!opts.yes) {\n console.log(\n kleur.yellow(\n `Will delete the entire graph directory at ${kleur.bold(dbPath)}. Pass --yes to confirm.`,\n ),\n );\n return;\n }\n const spinner = makeSpinner(`Removing ${dbPath}`).start();\n try {\n await rm(dbPath, { recursive: true, force: true });\n spinner.succeed(`Graph directory removed. Re-run \\`codegraph index <repo>\\` to rebuild.`);\n } catch (err) {\n spinner.fail(\"Wipe failed\");\n throw err;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { extname, dirname, join } from \"node:path\";\nimport Parser from \"web-tree-sitter\";\nimport type { Language as LanguageKind } from \"@codegraph/shared\";\n\nconst require = createRequire(import.meta.url);\n\n/** Maps our `Language` union to the wasm grammar bundled by `tree-sitter-wasms`. */\nconst GRAMMAR_FILE: Record<LanguageKind, string> = {\n typescript: \"tree-sitter-typescript.wasm\",\n tsx: \"tree-sitter-tsx.wasm\",\n javascript: \"tree-sitter-javascript.wasm\",\n jsx: \"tree-sitter-javascript.wasm\",\n python: \"tree-sitter-python.wasm\",\n};\n\nlet initPromise: Promise<void> | null = null;\nconst languageCache = new Map<LanguageKind, Parser.Language>();\n\nasync function ensureInit(): Promise<void> {\n if (!initPromise) initPromise = Parser.init();\n await initPromise;\n}\n\nfunction grammarPath(lang: LanguageKind): string {\n let pkgRoot: string;\n try {\n pkgRoot = dirname(require.resolve(\"tree-sitter-wasms/package.json\"));\n } catch {\n // Fallback for environments where tree-sitter-wasms is not installed\n pkgRoot = join(dirname(require.resolve(\"web-tree-sitter\")), \"..\", \"tree-sitter-wasms\");\n }\n return join(pkgRoot, \"out\", GRAMMAR_FILE[lang]);\n}\n\nexport async function loadLanguage(lang: LanguageKind): Promise<Parser.Language> {\n await ensureInit();\n const cached = languageCache.get(lang);\n if (cached) return cached;\n const buffer = await readFile(grammarPath(lang));\n // Load from Uint8Array; web-tree-sitter's fetch fallback doesn't work in plain Node.\n const loaded = await Parser.Language.load(new Uint8Array(buffer));\n languageCache.set(lang, loaded);\n return loaded;\n}\n\nexport function detectLanguage(filePath: string): LanguageKind | null {\n const ext = extname(filePath).toLowerCase();\n switch (ext) {\n case \".ts\":\n return \"typescript\";\n case \".tsx\":\n return \"tsx\";\n case \".js\":\n case \".mjs\":\n case \".cjs\":\n return \"javascript\";\n case \".jsx\":\n return \"jsx\";\n case \".py\":\n return \"python\";\n default:\n return null;\n }\n}\n\nexport interface ParsedFile {\n tree: Parser.Tree;\n rootNode: Parser.SyntaxNode;\n language: LanguageKind;\n source: string;\n}\n\nexport async function parseSource(source: string, language: LanguageKind): Promise<ParsedFile> {\n const lang = await loadLanguage(language);\n const parser = new Parser();\n parser.setLanguage(lang);\n const tree = parser.parse(source);\n if (!tree) {\n throw new Error(`tree-sitter failed to parse ${language} source`);\n }\n return {\n tree,\n rootNode: tree.rootNode,\n language,\n source,\n };\n}\n","import { createHash } from \"node:crypto\";\nimport { basename } from \"node:path\";\nimport Parser from \"web-tree-sitter\";\n\ntype SyntaxNode = Parser.SyntaxNode;\nimport {\n type GraphEdge,\n type GraphNode,\n type Language,\n makeFileId,\n makeNodeId,\n} from \"@codegraph/shared\";\nimport { parseSource } from \"../parser.js\";\nimport {\n endLine,\n findChildByType,\n findChildrenByType,\n isPascalCase,\n leadingCommentFor,\n nodeText,\n startLine,\n walk,\n} from \"../walker.js\";\nimport { extractPythonFile } from \"./extract-python.js\";\nimport { detectRoutes } from \"./routes.js\";\n\nexport interface ExtractFileInput {\n repoId: string;\n /** Path of the file *relative to the repo root*. Drives node ids. */\n relativePath: string;\n /** Absolute path on disk, used for ROUTE framework detection. */\n absolutePath: string;\n language: Language;\n source: string;\n}\n\nexport interface ExtractFileResult {\n file: GraphNode;\n nodes: GraphNode[];\n edges: GraphEdge[];\n}\n\n/**\n * Top-level extraction. Returns the file node, every symbol declared in the\n * file, and every edge that can be derived without cross-file knowledge.\n *\n * Some edges (CALLS, INHERITS, RENDERS) are emitted with\n * `unresolvedTargetName` set. The orchestrator resolves them against the\n * full symbol table after all files are parsed.\n *\n * Dispatches to language-specific extractors: Python has a distinct AST and\n * import model from JS/TS, so it lives in its own module.\n */\nexport async function extractFile(input: ExtractFileInput): Promise<ExtractFileResult> {\n if (input.language === \"python\") {\n return extractPythonFile(input);\n }\n return extractJsTsFile(input);\n}\n\nasync function extractJsTsFile(input: ExtractFileInput): Promise<ExtractFileResult> {\n const parsed = await parseSource(input.source, input.language);\n\n const fileId = makeFileId({ repoId: input.repoId, path: input.relativePath });\n const file: GraphNode = {\n id: fileId,\n kind: \"File\",\n repoId: input.repoId,\n name: basename(input.relativePath),\n path: input.relativePath,\n lineStart: 1,\n lineEnd: Math.max(1, parsed.rootNode.endPosition.row + 1),\n language: input.language,\n sizeBytes: Buffer.byteLength(input.source, \"utf8\"),\n contentHash: sha1(input.source),\n };\n\n const nodes: GraphNode[] = [];\n const edges: GraphEdge[] = [];\n\n // Per-file map of declared symbol names -> ids. Lets us resolve\n // intra-file CALLS / RENDERS edges immediately and emit cross-file ones\n // as unresolved.\n const localSymbols = new Map<string, string>();\n\n // Pass 1: symbol declarations + DEFINES + EXPORTS + INHERITS.\n for (const node of walk(parsed.rootNode)) {\n const symbol = extractSymbol(node, input, parsed.source);\n if (!symbol) continue;\n nodes.push(symbol.node);\n localSymbols.set(symbol.node.name, symbol.node.id);\n edges.push({ kind: \"DEFINES\", fromId: fileId, toId: symbol.node.id });\n if (symbol.node.isExported) {\n edges.push({ kind: \"EXPORTS\", fromId: fileId, toId: symbol.node.id });\n }\n if (symbol.parentClass) {\n edges.push({\n kind: \"INHERITS\",\n fromId: symbol.node.id,\n toId: \"\",\n unresolvedTargetName: symbol.parentClass,\n });\n }\n }\n\n // Pass 2: imports - emit IMPORTS edges from the *file* to the resolved\n // target path. The orchestrator turns the path into a target node id.\n for (const node of walk(parsed.rootNode)) {\n if (node.type === \"import_statement\") {\n const src = findChildByType(node, \"string\");\n if (!src) continue;\n const raw = nodeText(src, parsed.source);\n const target = raw.slice(1, -1);\n edges.push({\n kind: \"IMPORTS\",\n fromId: fileId,\n toId: \"\",\n line: startLine(node),\n fromPath: input.relativePath,\n toPath: target,\n unresolvedTargetName: target,\n });\n }\n }\n\n // Pass 3: shallow CALLS edges. We walk every call_expression and emit an\n // edge from the *enclosing* symbol to the callee identifier. Cross-file\n // resolution happens later; here we just record the name.\n for (const node of walk(parsed.rootNode)) {\n if (node.type !== \"call_expression\") continue;\n const callee = node.childForFieldName(\"function\");\n if (!callee) continue;\n const calleeName = extractCalleeName(callee, parsed.source);\n if (!calleeName) continue;\n const enclosing = findEnclosingSymbolId(node, input, parsed.source, localSymbols);\n if (!enclosing) continue;\n edges.push({\n kind: \"CALLS\",\n fromId: enclosing,\n toId: \"\",\n line: startLine(node),\n unresolvedTargetName: calleeName,\n });\n }\n\n // Pass 4: JSX renders edges. PascalCase opening / self-closing elements\n // are component usage; lowercase tags are HTML and are ignored.\n if (input.language === \"tsx\" || input.language === \"jsx\") {\n for (const node of walk(parsed.rootNode)) {\n if (node.type !== \"jsx_opening_element\" && node.type !== \"jsx_self_closing_element\") continue;\n const ident = node.childForFieldName(\"name\") ?? findChildByType(node, \"identifier\");\n if (!ident) continue;\n const tag = nodeText(ident, parsed.source);\n if (!isPascalCase(tag)) continue;\n const enclosing = findEnclosingSymbolId(node, input, parsed.source, localSymbols);\n if (!enclosing) continue;\n edges.push({\n kind: \"RENDERS\",\n fromId: enclosing,\n toId: \"\",\n line: startLine(node),\n unresolvedTargetName: tag,\n });\n }\n }\n\n // Pass 5: route detection (Express handlers + Next.js file-system routes).\n const routes = detectRoutes({\n repoId: input.repoId,\n relativePath: input.relativePath,\n absolutePath: input.absolutePath,\n fileId,\n rootNode: parsed.rootNode,\n source: parsed.source,\n language: input.language,\n });\n for (const route of routes) {\n nodes.push(route);\n edges.push({ kind: \"DEFINES\", fromId: fileId, toId: route.id });\n }\n\n return { file, nodes, edges };\n}\n\ninterface ExtractedSymbol {\n node: GraphNode;\n parentClass?: string;\n}\n\nfunction extractSymbol(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n): ExtractedSymbol | null {\n switch (node.type) {\n case \"function_declaration\":\n case \"generator_function_declaration\":\n return functionFromDeclaration(node, input, source);\n case \"class_declaration\":\n return classFromDeclaration(node, input, source);\n case \"interface_declaration\":\n return interfaceFromDeclaration(node, input, source, \"Interface\");\n case \"type_alias_declaration\":\n return interfaceFromDeclaration(node, input, source, \"Interface\");\n case \"lexical_declaration\":\n case \"variable_declaration\":\n return variableOrArrowFromDeclaration(node, input, source);\n default:\n return null;\n }\n}\n\nfunction functionFromDeclaration(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n): ExtractedSymbol | null {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return null;\n const name = nodeText(nameNode, source);\n const line = startLine(node);\n // PascalCase declared functions that return JSX (e.g. `function Sidebar() { return\n // <nav/> }`) are React function components. The earlier extractor only classified\n // arrow-function components, which meant declared components landed as `Function`\n // and disappeared from `get_component_tree`.\n const isComponent =\n (input.language === \"tsx\" || input.language === \"jsx\") &&\n isPascalCase(name) &&\n containsJsx(node.childForFieldName(\"body\"));\n const kind = isComponent ? \"Component\" : \"Function\";\n const id = makeNodeId({\n repoId: input.repoId,\n kind,\n path: input.relativePath,\n name,\n line,\n });\n return {\n node: {\n id,\n kind,\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(node),\n signature: extractSignature(node, source),\n leadingComment: leadingCommentFor(parentForLeadingComment(node), source),\n isExported: isExported(node),\n ...(kind === \"Function\"\n ? { isAsync: hasAsyncModifier(node, source) }\n : {}),\n },\n };\n}\n\nfunction classFromDeclaration(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n): ExtractedSymbol | null {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return null;\n const name = nodeText(nameNode, source);\n const line = startLine(node);\n const isComponent = looksLikeComponentClass(node, name, source);\n const kind = isComponent ? \"Component\" : \"Class\";\n const id = makeNodeId({\n repoId: input.repoId,\n kind,\n path: input.relativePath,\n name,\n line,\n });\n const parentClass = extractExtendsName(node, source);\n return {\n node: {\n id,\n kind,\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(node),\n signature: `class ${name}${parentClass ? ` extends ${parentClass}` : \"\"}`,\n leadingComment: leadingCommentFor(parentForLeadingComment(node), source),\n isExported: isExported(node),\n },\n ...(parentClass !== undefined ? { parentClass } : {}),\n };\n}\n\nfunction interfaceFromDeclaration(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n kind: \"Interface\",\n): ExtractedSymbol | null {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return null;\n const name = nodeText(nameNode, source);\n const line = startLine(node);\n const id = makeNodeId({\n repoId: input.repoId,\n kind,\n path: input.relativePath,\n name,\n line,\n });\n return {\n node: {\n id,\n kind,\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(node),\n signature: nodeText(node, source).split(\"\\n\")[0]?.slice(0, 200) ?? \"\",\n leadingComment: leadingCommentFor(parentForLeadingComment(node), source),\n isExported: isExported(node),\n },\n };\n}\n\n/**\n * Handles `const x = () => ...` and `const X = () => <jsx/>`. The lexical\n * declaration may contain multiple declarators; we emit one symbol per\n * named declarator. Functions vs Components are distinguished by\n * PascalCase + JSX return value heuristic.\n */\nfunction variableOrArrowFromDeclaration(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n): ExtractedSymbol | null {\n const declarators = findChildrenByType(node, \"variable_declarator\");\n if (declarators.length === 0) return null;\n // We can only return one symbol from this entry point. The walk visits\n // each declarator separately too, so picking the first preserves data\n // for \"const a = 1, b = 2\"-style edge cases.\n const decl = declarators[0];\n if (!decl) return null;\n const nameNode = decl.childForFieldName(\"name\");\n const value = decl.childForFieldName(\"value\");\n if (!nameNode) return null;\n // Destructuring patterns (`const [a, b] = ...`, `const { x } = ...`) produce a\n // composite name node whose text is the literal source slice. Emitting `[a, b]` as\n // the symbol name pollutes the graph and breaks `find_callers` / `affected_by`\n // lookups. Phase-1 simply drops these; the underlying values are still reachable via\n // their parent file's DEFINES edges.\n if (nameNode.type !== \"identifier\" && nameNode.type !== \"property_identifier\") {\n return null;\n }\n const name = nodeText(nameNode, source);\n const line = startLine(decl);\n\n const isArrow = value?.type === \"arrow_function\" || value?.type === \"function_expression\";\n if (isArrow) {\n const isComponent = isPascalCase(name) && containsJsx(value);\n const kind = isComponent ? \"Component\" : \"Function\";\n const id = makeNodeId({\n repoId: input.repoId,\n kind,\n path: input.relativePath,\n name,\n line,\n });\n return {\n node: {\n id,\n kind,\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(decl),\n signature: extractSignature(value, source),\n leadingComment: leadingCommentFor(node, source),\n isExported: isExported(node),\n ...(kind === \"Function\" ? { isArrow: true } : {}),\n },\n };\n }\n\n const id = makeNodeId({\n repoId: input.repoId,\n kind: \"Variable\",\n path: input.relativePath,\n name,\n line,\n });\n return {\n node: {\n id,\n kind: \"Variable\",\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(decl),\n signature: nodeText(decl, source).split(\"\\n\")[0]?.slice(0, 200) ?? \"\",\n leadingComment: leadingCommentFor(node, source),\n isExported: isExported(node),\n },\n };\n}\n\nfunction extractSignature(node: SyntaxNode | null, source: string): string {\n if (!node) return \"\";\n const params = node.childForFieldName(\"parameters\");\n const ret = node.childForFieldName(\"return_type\");\n const name = node.childForFieldName(\"name\");\n const head = name ? nodeText(name, source) : \"\";\n const ps = params ? nodeText(params, source) : \"()\";\n const rs = ret ? ` ${nodeText(ret, source)}` : \"\";\n return `${head}${ps}${rs}`.trim().slice(0, 200);\n}\n\n/**\n * Decide which name a call expression represents. For a bare identifier, the answer is\n * the identifier itself. For member expressions like `api.get(...)` we deliberately\n * surface the *object* identifier (`api`) instead of the method (`get`): in real-world\n * frontends the object is the meaningful symbol (the imported client, store, or hook\n * instance), while the method is a generic verb that collides across the graph.\n * `find_callers(\"api\")` then returns every site that uses the imported `api` client,\n * which is what the agent typically wants.\n *\n * For deep chains (`getApi().query()`, `a.b.c()`) we fall back to the property name -\n * the object is not a simple identifier, so the heuristic above can't apply.\n */\nfunction extractCalleeName(callee: SyntaxNode, source: string): string | null {\n if (callee.type === \"identifier\") return nodeText(callee, source);\n if (callee.type === \"member_expression\") {\n const object = callee.childForFieldName(\"object\");\n if (object && object.type === \"identifier\") {\n return nodeText(object, source);\n }\n const property = callee.childForFieldName(\"property\");\n if (property) return nodeText(property, source);\n }\n return null;\n}\n\nfunction extractExtendsName(classNode: SyntaxNode, source: string): string | undefined {\n const heritage = findChildByType(classNode, \"class_heritage\");\n if (!heritage) return undefined;\n const extendsClause = findChildByType(heritage, \"extends_clause\");\n if (!extendsClause) {\n // tree-sitter-typescript flattens heritage differently; check direct\n // identifier children of class_heritage as a fallback.\n const ident = findChildByType(heritage, \"identifier\");\n if (ident) return nodeText(ident, source);\n return undefined;\n }\n const ident =\n findChildByType(extendsClause, \"identifier\") ??\n findChildByType(extendsClause, \"member_expression\");\n return ident ? nodeText(ident, source) : undefined;\n}\n\nfunction looksLikeComponentClass(classNode: SyntaxNode, name: string, source: string): boolean {\n if (!isPascalCase(name)) return false;\n const parent = extractExtendsName(classNode, source) ?? \"\";\n return /(?:^|\\.)Component$|PureComponent$/.test(parent);\n}\n\nfunction containsJsx(node: SyntaxNode | null): boolean {\n if (!node) return false;\n for (const child of walk(node)) {\n if (\n child.type === \"jsx_element\" ||\n child.type === \"jsx_self_closing_element\" ||\n child.type === \"jsx_fragment\"\n ) {\n return true;\n }\n }\n return false;\n}\n\nfunction hasAsyncModifier(node: SyntaxNode, source: string): boolean {\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i);\n if (!child) continue;\n if (child.type === \"async\" || nodeText(child, source) === \"async\") return true;\n // Stop after we leave the declaration's modifier head.\n if (child.type === \"function\" || child.type === \"class\") return false;\n }\n return false;\n}\n\nfunction isExported(node: SyntaxNode): boolean {\n let cursor: SyntaxNode | null = node.parent;\n while (cursor) {\n if (cursor.type === \"export_statement\") return true;\n if (cursor.type === \"program\") return false;\n cursor = cursor.parent;\n }\n return false;\n}\n\n/**\n * When fetching a leading comment, we want the comment *above* the\n * `export` wrapper, not above the inner declaration. So we hop up to the\n * outermost export_statement before looking for siblings.\n */\nfunction parentForLeadingComment(node: SyntaxNode): SyntaxNode {\n let cursor: SyntaxNode = node;\n while (cursor.parent && cursor.parent.type === \"export_statement\") {\n cursor = cursor.parent;\n }\n return cursor;\n}\n\nfunction findEnclosingSymbolId(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n localSymbols: Map<string, string>,\n): string | null {\n let cursor: SyntaxNode | null = node.parent;\n while (cursor) {\n if (\n cursor.type === \"function_declaration\" ||\n cursor.type === \"method_definition\" ||\n cursor.type === \"class_declaration\" ||\n cursor.type === \"arrow_function\" ||\n cursor.type === \"function_expression\"\n ) {\n const name = enclosingDeclarationName(cursor, source);\n if (name) {\n const id = localSymbols.get(name);\n if (id) return id;\n }\n }\n cursor = cursor.parent;\n }\n // Falls back to the file node so module-level expressions still get a\n // sensible \"from\" endpoint.\n return makeFileId({ repoId: input.repoId, path: input.relativePath });\n}\n\nfunction enclosingDeclarationName(node: SyntaxNode, source: string): string | null {\n const nameField = node.childForFieldName(\"name\");\n if (nameField) return nodeText(nameField, source);\n // Arrow functions and function expressions carry their name on the\n // surrounding variable_declarator.\n let cursor: SyntaxNode | null = node.parent;\n while (cursor) {\n if (cursor.type === \"variable_declarator\") {\n const declName = cursor.childForFieldName(\"name\");\n if (declName) return nodeText(declName, source);\n return null;\n }\n if (cursor.type === \"function_declaration\" || cursor.type === \"class_declaration\") return null;\n cursor = cursor.parent;\n }\n return null;\n}\n\nfunction sha1(s: string): string {\n return createHash(\"sha1\").update(s).digest(\"hex\");\n}\n","import Parser from \"web-tree-sitter\";\n\ntype SyntaxNode = Parser.SyntaxNode;\n\n/**\n * Lazy depth-first walk that yields every descendant. Excludes the root\n * itself. Used by extractors to find symbols anywhere in a file without\n * stitching together SyntaxNode cursor APIs.\n */\nexport function* walk(node: SyntaxNode): Generator<SyntaxNode> {\n const stack: SyntaxNode[] = [];\n for (let i = node.namedChildCount - 1; i >= 0; i--) {\n const child = node.namedChild(i);\n if (child) stack.push(child);\n }\n while (stack.length > 0) {\n const current = stack.pop();\n if (!current) continue;\n yield current;\n for (let i = current.namedChildCount - 1; i >= 0; i--) {\n const child = current.namedChild(i);\n if (child) stack.push(child);\n }\n }\n}\n\nexport function findChildByType(node: SyntaxNode, type: string): SyntaxNode | null {\n for (let i = 0; i < node.namedChildCount; i++) {\n const child = node.namedChild(i);\n if (child && child.type === type) return child;\n }\n return null;\n}\n\nexport function findChildrenByType(node: SyntaxNode, type: string): SyntaxNode[] {\n const out: SyntaxNode[] = [];\n for (let i = 0; i < node.namedChildCount; i++) {\n const child = node.namedChild(i);\n if (child && child.type === type) out.push(child);\n }\n return out;\n}\n\nexport function nodeText(node: SyntaxNode, source: string): string {\n return source.slice(node.startIndex, node.endIndex);\n}\n\n/**\n * Tree-sitter line numbers are 0-indexed; we surface 1-indexed numbers\n * everywhere downstream so they match what editors and stack traces use.\n */\nexport function startLine(node: SyntaxNode): number {\n return node.startPosition.row + 1;\n}\n\nexport function endLine(node: SyntaxNode): number {\n return node.endPosition.row + 1;\n}\n\n/**\n * Returns the leading line-comment block immediately above `node`, joined\n * into a single string. Empty string when no comment is found.\n */\nexport function leadingCommentFor(node: SyntaxNode, source: string): string {\n let cursor: SyntaxNode | null = node.previousNamedSibling;\n const lines: string[] = [];\n while (cursor && /comment/.test(cursor.type)) {\n lines.unshift(stripCommentMarkers(nodeText(cursor, source)));\n cursor = cursor.previousNamedSibling;\n }\n return lines.join(\"\\n\").trim();\n}\n\nfunction stripCommentMarkers(text: string): string {\n return text\n .replace(/^\\/\\*+/, \"\")\n .replace(/\\*+\\/$/, \"\")\n .replace(/^\\/\\//gm, \"\")\n .replace(/^\\s*\\*/gm, \"\")\n .trim();\n}\n\nexport function isPascalCase(name: string): boolean {\n return /^[A-Z][A-Za-z0-9]*$/.test(name);\n}\n","import { createHash } from \"node:crypto\";\nimport { basename } from \"node:path\";\nimport Parser from \"web-tree-sitter\";\n\ntype SyntaxNode = Parser.SyntaxNode;\nimport {\n type GraphEdge,\n type GraphNode,\n makeFileId,\n makeNodeId,\n} from \"@codegraph/shared\";\nimport { parseSource } from \"../parser.js\";\nimport { endLine, findChildByType, nodeText, startLine, walk } from \"../walker.js\";\nimport type { ExtractFileInput, ExtractFileResult } from \"./extract.js\";\n\n/**\n * Python extractor. Emits the same `GraphNode` / `GraphEdge` shapes as the JS/TS\n * extractor so the rest of the pipeline (resolver, embedder, MCP tools) is\n * language-agnostic. Scope of v1:\n *\n * - `function_definition` / `class_definition` (including those wrapped in\n * `decorated_definition`) become `Function` / `Class` nodes.\n * - Module-level assignments to a plain identifier become `Variable` nodes.\n * - `import_statement` + `import_from_statement` produce `IMPORTS` edges with\n * the spec rewritten into a repo-relative path the shared resolver understands\n * (e.g. `from .utils import x` -> `./utils`, `from app.services import y`\n * -> `app/services`).\n * - `call` expressions inside a function/class become `CALLS` edges keyed by the\n * callee's last name segment.\n *\n * Out of scope for v1: `Interface` (Python has no analog), `Component` /\n * `RENDERS`, FastAPI/Flask route detection (handled in a separate pass when we\n * add it), import-alias-aware call resolution.\n */\nexport async function extractPythonFile(input: ExtractFileInput): Promise<ExtractFileResult> {\n const parsed = await parseSource(input.source, input.language);\n\n const fileId = makeFileId({ repoId: input.repoId, path: input.relativePath });\n const file: GraphNode = {\n id: fileId,\n kind: \"File\",\n repoId: input.repoId,\n name: basename(input.relativePath),\n path: input.relativePath,\n lineStart: 1,\n lineEnd: Math.max(1, parsed.rootNode.endPosition.row + 1),\n language: input.language,\n sizeBytes: Buffer.byteLength(input.source, \"utf8\"),\n contentHash: sha1(input.source),\n };\n\n const nodes: GraphNode[] = [];\n const edges: GraphEdge[] = [];\n\n // Local symbol name -> id, used for intra-file call resolution. Cross-file\n // calls are emitted unresolved and matched by the orchestrator's resolver.\n const localSymbols = new Map<string, string>();\n\n // Pass 1: function / class / module-level variable declarations.\n for (const node of walk(parsed.rootNode)) {\n const symbol = extractPythonSymbol(node, input, parsed.source);\n if (!symbol) continue;\n nodes.push(symbol.node);\n localSymbols.set(symbol.node.name, symbol.node.id);\n edges.push({ kind: \"DEFINES\", fromId: fileId, toId: symbol.node.id });\n if (symbol.node.isExported) {\n edges.push({ kind: \"EXPORTS\", fromId: fileId, toId: symbol.node.id });\n }\n for (const parent of symbol.parentClasses ?? []) {\n edges.push({\n kind: \"INHERITS\",\n fromId: symbol.node.id,\n toId: \"\",\n unresolvedTargetName: parent,\n });\n }\n }\n\n // Pass 2: imports. Rewrite Python module syntax to a repo-relative spec the\n // shared resolver can match against `knownFilePaths`.\n for (const node of walk(parsed.rootNode)) {\n if (node.type === \"import_statement\") {\n for (const moduleNode of moduleNamesInImport(node)) {\n const spec = dottedNameToPath(moduleNode, parsed.source);\n if (!spec) continue;\n edges.push({\n kind: \"IMPORTS\",\n fromId: fileId,\n toId: \"\",\n line: startLine(node),\n fromPath: input.relativePath,\n toPath: spec,\n unresolvedTargetName: spec,\n });\n }\n } else if (node.type === \"import_from_statement\") {\n const moduleNode = node.childForFieldName(\"module_name\");\n if (!moduleNode) continue;\n const spec = moduleSpecFromFromImport(moduleNode, parsed.source);\n if (!spec) continue;\n edges.push({\n kind: \"IMPORTS\",\n fromId: fileId,\n toId: \"\",\n line: startLine(node),\n fromPath: input.relativePath,\n toPath: spec,\n unresolvedTargetName: spec,\n });\n }\n }\n\n // Pass 3: CALLS. Enclosing symbol is the nearest function/class we already\n // recorded in `localSymbols`; calls outside any defined symbol (top-level\n // module code) are dropped.\n for (const node of walk(parsed.rootNode)) {\n if (node.type !== \"call\") continue;\n const callee = node.childForFieldName(\"function\");\n if (!callee) continue;\n const calleeName = extractCalleeName(callee, parsed.source);\n if (!calleeName) continue;\n const enclosing = findEnclosingPythonSymbolId(node, localSymbols, parsed.source);\n if (!enclosing) continue;\n edges.push({\n kind: \"CALLS\",\n fromId: enclosing,\n toId: \"\",\n line: startLine(node),\n unresolvedTargetName: calleeName,\n });\n }\n\n return { file, nodes, edges };\n}\n\ninterface PythonSymbol {\n node: GraphNode;\n parentClasses?: string[];\n}\n\nfunction extractPythonSymbol(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n): PythonSymbol | null {\n switch (node.type) {\n case \"function_definition\":\n return pythonFunction(node, input, source);\n case \"class_definition\":\n return pythonClass(node, input, source);\n case \"assignment\":\n return pythonModuleVariable(node, input, source);\n default:\n return null;\n }\n}\n\nfunction pythonFunction(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n): PythonSymbol | null {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return null;\n const name = nodeText(nameNode, source);\n // Top-of-the-def line. If the def is wrapped in a `decorated_definition`, the\n // decorators sit on earlier lines but the symbol's \"real\" location is the\n // `def`/`class` keyword line, which matches what editors and stack traces use.\n const line = startLine(node);\n const id = makeNodeId({\n repoId: input.repoId,\n kind: \"Function\",\n path: input.relativePath,\n name,\n line,\n });\n return {\n node: {\n id,\n kind: \"Function\",\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: decoratedLineStart(node),\n lineEnd: endLine(node),\n signature: pythonDefSignature(node, source, \"def\"),\n leadingComment: pythonDocstring(node, source),\n isExported: isPythonExported(name),\n isAsync: isAsyncFunctionDef(node, source),\n },\n };\n}\n\nfunction pythonClass(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n): PythonSymbol | null {\n const nameNode = node.childForFieldName(\"name\");\n if (!nameNode) return null;\n const name = nodeText(nameNode, source);\n const line = startLine(node);\n const id = makeNodeId({\n repoId: input.repoId,\n kind: \"Class\",\n path: input.relativePath,\n name,\n line,\n });\n const parents = extractPythonBaseClasses(node, source);\n return {\n node: {\n id,\n kind: \"Class\",\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: decoratedLineStart(node),\n lineEnd: endLine(node),\n signature: pythonDefSignature(node, source, \"class\"),\n leadingComment: pythonDocstring(node, source),\n isExported: isPythonExported(name),\n },\n ...(parents.length > 0 ? { parentClasses: parents } : {}),\n };\n}\n\n/**\n * Emit a `Variable` node only for module-level assignments of the form\n * `NAME = <expr>`. Tuple unpacking, class attributes, and locals inside a\n * function body are intentionally skipped to keep the graph signal-to-noise\n * high.\n */\nfunction pythonModuleVariable(\n node: SyntaxNode,\n input: ExtractFileInput,\n source: string,\n): PythonSymbol | null {\n // Module-level scoping: assignment's parent is `expression_statement`, whose\n // parent is `module`.\n const stmtParent = node.parent;\n if (!stmtParent || stmtParent.type !== \"expression_statement\") return null;\n const moduleParent = stmtParent.parent;\n if (!moduleParent || moduleParent.type !== \"module\") return null;\n\n const left = node.childForFieldName(\"left\");\n if (!left || left.type !== \"identifier\") return null;\n const name = nodeText(left, source);\n const line = startLine(node);\n const id = makeNodeId({\n repoId: input.repoId,\n kind: \"Variable\",\n path: input.relativePath,\n name,\n line,\n });\n return {\n node: {\n id,\n kind: \"Variable\",\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(node),\n signature: nodeText(node, source).split(\"\\n\")[0]?.slice(0, 200) ?? \"\",\n isExported: isPythonExported(name),\n },\n };\n}\n\n/** Python \"export\" convention: a name is public iff it doesn't start with `_`. */\nfunction isPythonExported(name: string): boolean {\n return !name.startsWith(\"_\");\n}\n\n/** `async def foo(): ...` -> true. tree-sitter-python keeps `async` as a leading unnamed token. */\nfunction isAsyncFunctionDef(node: SyntaxNode, source: string): boolean {\n return nodeText(node, source).trimStart().startsWith(\"async\");\n}\n\n/**\n * When a def is wrapped in `decorated_definition`, the user-visible block starts\n * at the first decorator line. Using that as `lineStart` makes blast-radius\n * tools point at the right span.\n */\nfunction decoratedLineStart(node: SyntaxNode): number {\n const parent = node.parent;\n if (parent && parent.type === \"decorated_definition\") {\n return startLine(parent);\n }\n return startLine(node);\n}\n\n/** First line of the def header, trimmed and capped. */\nfunction pythonDefSignature(node: SyntaxNode, source: string, keyword: \"def\" | \"class\"): string {\n const text = nodeText(node, source);\n const firstLine = text.split(\"\\n\")[0]?.trim() ?? \"\";\n // Strip trailing colon for a cleaner signature.\n const cleaned = firstLine.replace(/:\\s*$/, \"\");\n if (cleaned.length > 0) return cleaned.slice(0, 200);\n return `${keyword} ?`;\n}\n\n/**\n * Returns the docstring of a function/class as a leading comment if one is the\n * first statement of the body. Python uses string literals at the top of a block\n * instead of comments above the def, so this is the closest analog to the JS\n * extractor's leading-comment capture.\n */\nfunction pythonDocstring(node: SyntaxNode, source: string): string {\n const body = node.childForFieldName(\"body\");\n if (!body) return \"\";\n const firstStmt = body.namedChild(0);\n if (!firstStmt || firstStmt.type !== \"expression_statement\") return \"\";\n const expr = firstStmt.namedChild(0);\n if (!expr || expr.type !== \"string\") return \"\";\n const raw = nodeText(expr, source);\n return stripPythonStringQuotes(raw).trim();\n}\n\nfunction stripPythonStringQuotes(raw: string): string {\n // Handles triple and single-quoted forms, optional prefixes (r, b, f, u, rb...).\n const withoutPrefix = raw.replace(/^[rRbBuUfF]+/, \"\");\n if (withoutPrefix.startsWith('\"\"\"') && withoutPrefix.endsWith('\"\"\"')) {\n return withoutPrefix.slice(3, -3);\n }\n if (withoutPrefix.startsWith(\"'''\") && withoutPrefix.endsWith(\"'''\")) {\n return withoutPrefix.slice(3, -3);\n }\n if (\n (withoutPrefix.startsWith('\"') && withoutPrefix.endsWith('\"')) ||\n (withoutPrefix.startsWith(\"'\") && withoutPrefix.endsWith(\"'\"))\n ) {\n return withoutPrefix.slice(1, -1);\n }\n return withoutPrefix;\n}\n\n/**\n * Collect base-class names from `class Foo(Bar, mod.Baz, metaclass=Meta): ...`.\n * Keyword args (`metaclass=...`) are skipped; attribute references collapse to\n * their last segment so the resolver can match `Baz` against the symbol table.\n */\nfunction extractPythonBaseClasses(node: SyntaxNode, source: string): string[] {\n const supers = node.childForFieldName(\"superclasses\");\n if (!supers) return [];\n const out: string[] = [];\n for (let i = 0; i < supers.namedChildCount; i++) {\n const arg = supers.namedChild(i);\n if (!arg) continue;\n if (arg.type === \"keyword_argument\") continue;\n const name = extractCalleeName(arg, source);\n if (name) out.push(name);\n }\n return out;\n}\n\n/**\n * `import_statement` may contain one or more `dotted_name` / `aliased_import`\n * children. We extract the underlying module name from each so a single\n * `import a, b.c` produces two IMPORTS edges.\n */\nfunction moduleNamesInImport(importNode: SyntaxNode): SyntaxNode[] {\n const out: SyntaxNode[] = [];\n for (let i = 0; i < importNode.namedChildCount; i++) {\n const child = importNode.namedChild(i);\n if (!child) continue;\n if (child.type === \"dotted_name\") {\n out.push(child);\n } else if (child.type === \"aliased_import\") {\n const inner = child.childForFieldName(\"name\") ?? findChildByType(child, \"dotted_name\");\n if (inner) out.push(inner);\n }\n }\n return out;\n}\n\n/** Convert `a.b.c` (a `dotted_name`) to a repo-rooted spec `a/b/c`. */\nfunction dottedNameToPath(node: SyntaxNode, source: string): string | null {\n if (node.type !== \"dotted_name\") return null;\n const segments: string[] = [];\n for (let i = 0; i < node.namedChildCount; i++) {\n const ident = node.namedChild(i);\n if (!ident) continue;\n segments.push(nodeText(ident, source));\n }\n if (segments.length === 0) return null;\n return segments.join(\"/\");\n}\n\n/**\n * `from .utils import x` module_name = `relative_import` with one dot\n * `from ..pkg.sub import x` module_name = `relative_import` with two dots + dotted_name\n * `from app.services import x` module_name = `dotted_name`\n *\n * Output specs match what the shared resolver expects:\n * - relative -> `./X`, `../X`, `../../X`\n * - absolute -> `app/services` (resolved against repo root as a final fallback)\n */\nfunction moduleSpecFromFromImport(moduleNode: SyntaxNode, source: string): string | null {\n if (moduleNode.type === \"dotted_name\") {\n return dottedNameToPath(moduleNode, source);\n }\n if (moduleNode.type !== \"relative_import\") return null;\n // The prefix is an unnamed token (`.`, `..`, `...`). Count dots by scanning text.\n let dotCount = 0;\n let dottedSpec: string | null = null;\n for (let i = 0; i < moduleNode.childCount; i++) {\n const child = moduleNode.child(i);\n if (!child) continue;\n if (child.type === \"import_prefix\") {\n dotCount = nodeText(child, source).length;\n } else if (child.type === \"dotted_name\") {\n dottedSpec = dottedNameToPath(child, source);\n }\n }\n if (dotCount === 0) return dottedSpec;\n // One dot = current package. Two dots = parent package. We translate to\n // `./X` (zero `../` hops) and `../X` (one `../` hop), etc.\n const upHops = \"../\".repeat(Math.max(0, dotCount - 1));\n const base = upHops.length > 0 ? upHops.slice(0, -1) : \".\";\n if (dottedSpec) return `${base}/${dottedSpec}`;\n return base;\n}\n\n/**\n * Reduce a callee expression to a single name:\n * - `foo(...)` -> `foo`\n * - `obj.method(...)` -> `method` (last attribute segment)\n * - `mod.sub.fn(...)` -> `fn`\n * Anything else (subscripts, calls of calls, lambdas) yields null and the call\n * is dropped, matching the JS extractor's \"best-effort name\" stance.\n */\nfunction extractCalleeName(node: SyntaxNode, source: string): string | null {\n if (node.type === \"identifier\") {\n return nodeText(node, source);\n }\n if (node.type === \"attribute\") {\n const attr = node.childForFieldName(\"attribute\");\n if (attr && attr.type === \"identifier\") return nodeText(attr, source);\n return null;\n }\n return null;\n}\n\n/**\n * Walk up the parent chain until we hit a function/class definition whose name\n * we recorded during Pass 1. Returns the symbol's id, or null if the call\n * sits at module scope.\n */\nfunction findEnclosingPythonSymbolId(\n node: SyntaxNode,\n localSymbols: Map<string, string>,\n source: string,\n): string | null {\n let cursor: SyntaxNode | null = node.parent;\n while (cursor) {\n if (cursor.type === \"function_definition\" || cursor.type === \"class_definition\") {\n const nameNode = cursor.childForFieldName(\"name\");\n if (nameNode) {\n const id = localSymbols.get(nodeText(nameNode, source));\n if (id) return id;\n }\n }\n cursor = cursor.parent;\n }\n return null;\n}\n\nfunction sha1(text: string): string {\n return createHash(\"sha1\").update(text).digest(\"hex\");\n}\n","import Parser from \"web-tree-sitter\";\n\ntype SyntaxNode = Parser.SyntaxNode;\nimport { type GraphNode, type Language, makeNodeId } from \"@codegraph/shared\";\nimport { endLine, findChildByType, nodeText, startLine, walk } from \"../walker.js\";\n\nconst EXPRESS_METHODS = new Set([\n \"get\",\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n \"options\",\n \"head\",\n \"all\",\n \"use\",\n]);\n\nconst HTTP_VERBS = new Set([\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"OPTIONS\",\n \"HEAD\",\n]);\n\nexport interface DetectRoutesInput {\n repoId: string;\n relativePath: string;\n absolutePath: string;\n fileId: string;\n rootNode: SyntaxNode;\n source: string;\n language: Language;\n}\n\n/**\n * Returns Route nodes for:\n * 1. Express `app.get('/x', handler)` / `router.post(...)` patterns.\n * 2. Next.js App Router `app/**\\/route.ts` exports (`GET`, `POST`, ...).\n * 3. Next.js Pages Router `pages/api/**` default exports.\n */\nexport function detectRoutes(input: DetectRoutesInput): GraphNode[] {\n return [\n ...detectExpressRoutes(input),\n ...detectNextAppRouterRoutes(input),\n ...detectNextPagesApiRoutes(input),\n ];\n}\n\nfunction detectExpressRoutes(input: DetectRoutesInput): GraphNode[] {\n const out: GraphNode[] = [];\n for (const node of walk(input.rootNode)) {\n if (node.type !== \"call_expression\") continue;\n const callee = node.childForFieldName(\"function\");\n if (!callee || callee.type !== \"member_expression\") continue;\n const obj = callee.childForFieldName(\"object\");\n const prop = callee.childForFieldName(\"property\");\n if (!obj || !prop) continue;\n const method = nodeText(prop, input.source).toLowerCase();\n if (!EXPRESS_METHODS.has(method)) continue;\n const args = node.childForFieldName(\"arguments\");\n if (!args) continue;\n const firstArg = args.namedChild(0);\n if (!firstArg || firstArg.type !== \"string\") continue;\n const routePath = stripQuotes(nodeText(firstArg, input.source));\n if (!routePath.startsWith(\"/\")) continue;\n const line = startLine(node);\n const name = `${method.toUpperCase()} ${routePath}`;\n out.push({\n id: makeNodeId({\n repoId: input.repoId,\n kind: \"Route\",\n path: input.relativePath,\n name,\n line,\n }),\n kind: \"Route\",\n repoId: input.repoId,\n name,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(node),\n method: method.toUpperCase(),\n routePath,\n framework: \"express\",\n });\n }\n return out;\n}\n\nfunction detectNextAppRouterRoutes(input: DetectRoutesInput): GraphNode[] {\n if (!/(^|\\/)app\\/.+\\/route\\.(ts|tsx|js|jsx|mjs|cjs)$/.test(input.relativePath)) return [];\n const routePath = appRoutePathFor(input.relativePath);\n const out: GraphNode[] = [];\n for (const node of walk(input.rootNode)) {\n if (node.type !== \"export_statement\") continue;\n // `export async function GET(...)` or `export const GET = ...`\n const decl = findChildByType(node, \"function_declaration\") ?? findChildByType(node, \"lexical_declaration\");\n if (!decl) continue;\n const name = extractTopLevelName(decl, input.source);\n if (!name || !HTTP_VERBS.has(name)) continue;\n const line = startLine(node);\n out.push({\n id: makeNodeId({\n repoId: input.repoId,\n kind: \"Route\",\n path: input.relativePath,\n name: `${name} ${routePath}`,\n line,\n }),\n kind: \"Route\",\n repoId: input.repoId,\n name: `${name} ${routePath}`,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(node),\n method: name,\n routePath,\n framework: \"next-app\",\n });\n }\n return out;\n}\n\nfunction detectNextPagesApiRoutes(input: DetectRoutesInput): GraphNode[] {\n if (!/(^|\\/)pages\\/api\\//.test(input.relativePath)) return [];\n const routePath = pagesApiPathFor(input.relativePath);\n // Pages API uses a default-exported handler that responds to all verbs.\n for (const node of walk(input.rootNode)) {\n if (node.type !== \"export_statement\") continue;\n const text = nodeText(node, input.source);\n if (!/default/.test(text)) continue;\n const line = startLine(node);\n return [\n {\n id: makeNodeId({\n repoId: input.repoId,\n kind: \"Route\",\n path: input.relativePath,\n name: `ANY ${routePath}`,\n line,\n }),\n kind: \"Route\",\n repoId: input.repoId,\n name: `ANY ${routePath}`,\n path: input.relativePath,\n lineStart: line,\n lineEnd: endLine(node),\n method: \"ANY\",\n routePath,\n framework: \"next-pages\",\n },\n ];\n }\n return [];\n}\n\nfunction stripQuotes(s: string): string {\n return s.replace(/^[\"'`]/, \"\").replace(/[\"'`]$/, \"\");\n}\n\nfunction extractTopLevelName(decl: SyntaxNode, source: string): string | null {\n if (decl.type === \"function_declaration\") {\n const name = decl.childForFieldName(\"name\");\n return name ? nodeText(name, source) : null;\n }\n if (decl.type === \"lexical_declaration\") {\n const declarator = findChildByType(decl, \"variable_declarator\");\n if (!declarator) return null;\n const name = declarator.childForFieldName(\"name\");\n return name ? nodeText(name, source) : null;\n }\n return null;\n}\n\nfunction appRoutePathFor(relativePath: string): string {\n // app/(group)/users/[id]/route.ts -> /users/:id\n const idx = relativePath.indexOf(\"app/\");\n const tail = idx >= 0 ? relativePath.slice(idx + \"app/\".length) : relativePath;\n const segments = tail\n .replace(/\\/route\\.[^/]+$/, \"\")\n .split(\"/\")\n .filter((seg) => seg.length > 0 && !/^\\(.*\\)$/.test(seg)) // strip route groups\n .map((seg) => seg.replace(/^\\[\\.\\.\\.(.+)\\]$/, \":$1*\").replace(/^\\[(.+)\\]$/, \":$1\"));\n return `/${segments.join(\"/\")}` || \"/\";\n}\n\nfunction pagesApiPathFor(relativePath: string): string {\n const idx = relativePath.indexOf(\"pages/api/\");\n const tail = idx >= 0 ? relativePath.slice(idx + \"pages/api/\".length) : relativePath;\n const base = tail.replace(/\\.[^/.]+$/, \"\");\n const segments = base\n .split(\"/\")\n .filter((seg) => seg.length > 0)\n .map((seg) =>\n seg\n .replace(/^\\[\\.\\.\\.(.+)\\]$/, \":$1*\")\n .replace(/^\\[(.+)\\]$/, \":$1\")\n .replace(/^index$/, \"\"),\n )\n .filter((seg) => seg.length > 0);\n return `/api/${segments.join(\"/\")}`.replace(/\\/+$/, \"\") || \"/api\";\n}\n","import path from \"node:path\";\nimport { type GraphEdge, type GraphNode, makeFileId } from \"@codegraph/shared\";\n\nexport interface ResolveInput {\n repoId: string;\n /** All nodes from all parsed files in the current index pass. */\n nodes: GraphNode[];\n /** All edges with `unresolvedTargetName` set on IMPORTS/CALLS/RENDERS/INHERITS. */\n edges: GraphEdge[];\n /** Repo paths of files that successfully parsed, used for IMPORTS resolution. */\n knownFilePaths: Set<string>;\n /**\n * Optional TypeScript-style path aliases extracted from `tsconfig.json` /\n * `jsconfig.json`. When supplied, imports that don't start with `.` or `/` are\n * matched against the alias table before being dropped as \"third-party\".\n */\n tsconfigPaths?: TsconfigPaths;\n}\n\n/**\n * Subset of TS `compilerOptions` we use for resolution. `baseUrl` is repo-relative\n * (POSIX), `paths` maps an alias spec like `\"@/*\"` to one or more replacements like\n * `[\"src/*\"]`. The replacement targets are also repo-relative.\n */\nexport interface TsconfigPaths {\n baseUrl: string;\n paths: Record<string, string[]>;\n}\n\nexport interface ResolveResult {\n resolved: GraphEdge[];\n dropped: number;\n}\n\nconst EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".py\"];\n\n/**\n * Files that count as a \"directory import\" target. JS uses `index.<ext>`;\n * Python uses `__init__.py`. We try all of these for every candidate stem\n * regardless of language: collisions are impossible because the file sets\n * never overlap, and keeping one list avoids threading the source file's\n * language through every resolver call.\n */\nconst DIRECTORY_INDEX_FILES = [\n \"index.ts\",\n \"index.tsx\",\n \"index.js\",\n \"index.jsx\",\n \"index.mjs\",\n \"index.cjs\",\n \"__init__.py\",\n];\n\n/**\n * Second pass that converts the *names* captured during single-file\n * extraction into concrete `toId` values. Edges whose target can't be\n * resolved are dropped silently (and counted in `dropped`) - they\n * commonly point at npm packages or unindexed code.\n */\nexport function resolveEdges(input: ResolveInput): ResolveResult {\n // Symbol lookup by name. When the same name appears in multiple files,\n // the first one wins; Phase 4's LSP integration will replace this with\n // type-aware resolution.\n const byName = new Map<string, string>();\n // Function/class/component/etc -> first node id with that name.\n for (const n of input.nodes) {\n if (n.kind === \"File\") continue;\n if (!byName.has(n.name)) byName.set(n.name, n.id);\n }\n\n const out: GraphEdge[] = [];\n let dropped = 0;\n\n for (const edge of input.edges) {\n if (edge.toId) {\n out.push(edge);\n continue;\n }\n if (!edge.unresolvedTargetName) {\n dropped++;\n continue;\n }\n if (edge.kind === \"IMPORTS\") {\n const resolved = resolveImportPath({\n repoId: input.repoId,\n fromPath: edge.fromPath ?? \"\",\n spec: edge.unresolvedTargetName,\n known: input.knownFilePaths,\n ...(input.tsconfigPaths ? { tsconfigPaths: input.tsconfigPaths } : {}),\n });\n if (!resolved) {\n dropped++;\n continue;\n }\n const targetId = makeFileId({ repoId: input.repoId, path: resolved });\n const { unresolvedTargetName: _unused, ...rest } = edge;\n out.push({ ...rest, toId: targetId, toPath: resolved });\n continue;\n }\n const targetId = byName.get(edge.unresolvedTargetName);\n if (!targetId) {\n dropped++;\n continue;\n }\n const { unresolvedTargetName: _unused, ...rest } = edge;\n out.push({ ...rest, toId: targetId });\n }\n\n return { resolved: out, dropped };\n}\n\ninterface ResolveImportInput {\n repoId: string;\n fromPath: string;\n spec: string;\n known: Set<string>;\n tsconfigPaths?: TsconfigPaths;\n}\n\nfunction resolveImportPath(input: ResolveImportInput): string | null {\n const { fromPath, spec, known, tsconfigPaths } = input;\n // Relative or rooted spec: classic node-style resolution.\n if (spec.startsWith(\".\") || spec.startsWith(\"/\")) {\n const baseDir = path.posix.dirname(toPosix(fromPath));\n const joined = path.posix.normalize(path.posix.join(baseDir, toPosix(spec)));\n return firstMatchingCandidate(joined, known);\n }\n // Non-relative spec: maybe a TS path alias (`@/foo`, `~/foo`, `components/Foo`)?\n // Walk the alias table, longest pattern first, and try every replacement.\n if (tsconfigPaths) {\n const candidates = expandAliasCandidates(spec, tsconfigPaths);\n for (const c of candidates) {\n const resolved = firstMatchingCandidate(c, known);\n if (resolved) return resolved;\n }\n }\n // Final fallback: treat the spec as a repo-root-relative path. This catches\n // Python absolute imports (`from app.services import auth` was rewritten to\n // `app/services` by the Python extractor) and any in-repo JS imports that\n // bypassed tsconfig aliases. Third-party packages still fall through to\n // null because their stems don't match any indexed file.\n const fromRoot = firstMatchingCandidate(toPosix(spec), known);\n if (fromRoot) return fromRoot;\n return null;\n}\n\n/**\n * For a literal repo-relative path (no extension assumed), try the literal, every\n * known source extension, and a `/index.<ext>` directory entry. Modern ESM commonly\n * writes `./foo.js` even when the source is `./foo.ts`, so we strip an existing\n * extension before trying each candidate.\n */\nfunction firstMatchingCandidate(joined: string, known: Set<string>): string | null {\n const candidates: string[] = [joined];\n const ext = path.posix.extname(joined);\n const stem = ext ? joined.slice(0, -ext.length) : joined;\n for (const e of EXTENSIONS) candidates.push(`${stem}${e}`);\n for (const indexFile of DIRECTORY_INDEX_FILES) candidates.push(`${stem}/${indexFile}`);\n for (const c of candidates) {\n if (known.has(c)) return c;\n }\n return null;\n}\n\n/**\n * Expand a non-relative import against the tsconfig `paths` table. Patterns ending in\n * `/*` are treated as prefix matches and the trailing slice is grafted onto each\n * replacement; bare patterns are exact-match aliases. Replacements are joined with\n * `baseUrl` (also repo-relative) so we end up with repo-relative POSIX paths to feed\n * into `firstMatchingCandidate`.\n *\n * Longest pattern wins, matching the TS compiler's precedence rule.\n */\nfunction expandAliasCandidates(spec: string, cfg: TsconfigPaths): string[] {\n const sortedPatterns = Object.keys(cfg.paths).sort((a, b) => b.length - a.length);\n const out: string[] = [];\n for (const pattern of sortedPatterns) {\n const replacements = cfg.paths[pattern] ?? [];\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -1); // keep trailing \"/\"\n if (!spec.startsWith(prefix)) continue;\n const tail = spec.slice(prefix.length);\n for (const r of replacements) {\n const rTail = r.endsWith(\"/*\") ? r.slice(0, -1) : r.endsWith(\"*\") ? r.slice(0, -1) : r;\n const joined = path.posix.normalize(\n path.posix.join(toPosix(cfg.baseUrl), `${rTail}${tail}`),\n );\n out.push(joined);\n }\n } else if (spec === pattern) {\n for (const r of replacements) {\n const joined = path.posix.normalize(path.posix.join(toPosix(cfg.baseUrl), r));\n out.push(joined);\n }\n }\n }\n return out;\n}\n\nfunction toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport { cpus } from \"node:os\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport ignore from \"ignore\";\nimport type { GraphDb, UpsertEdgeInput, UpsertNodeInput } from \"@codegraph/graph-db\";\nimport type { LlmRouter } from \"@codegraph/llm-router\";\nimport type { GraphEdge, GraphNode } from \"@codegraph/shared\";\nimport { embedNodes, type EmbeddedNode } from \"./embedder.js\";\nimport { extractFile, resolveEdges } from \"./extractors/index.js\";\nimport { loadTsconfigPaths } from \"./tsconfig.js\";\nimport { detectLanguage } from \"./parser.js\";\nimport { walkRepo } from \"./repo-walker.js\";\n\nexport interface IndexRepoOptions {\n repoId: string;\n repoPath: string;\n graphDb: GraphDb;\n router?: LlmRouter;\n /** Parallelism for in-process parsing. Defaults to `os.cpus().length`. */\n parallelism?: number;\n /** Set to false in tests to skip the (slow) embedding network call. */\n skipEmbeddings?: boolean;\n onProgress?: (e: ProgressEvent) => void;\n}\n\nexport type ProgressEvent =\n | { type: \"walk\"; files: number }\n | { type: \"parse\"; parsed: number; total: number }\n | { type: \"embed\"; embedded: number; total: number }\n | { type: \"upsert\"; nodes: number; edges: number };\n\nexport interface IndexResult {\n durationMs: number;\n parsedFiles: number;\n failedFiles: number;\n nodes: number;\n edges: number;\n embeddings: number;\n droppedEdges: number;\n}\n\n/**\n * Top-level indexer. Sequence:\n * 1. Walk the repo (gitignore-aware), classify by language.\n * 2. Parse + extract per file with bounded concurrency.\n * 3. Resolve cross-file edge targets (CALLS / RENDERS / IMPORTS / INHERITS).\n * 4. Embed every non-File node so the vectors are ready before we touch the graph.\n * 5. Wipe the repo's slice and write nodes (with embeddings folded into the property\n * map of the CREATE) + edges.\n *\n * Why embeddings are folded into the initial CREATE rather than back-filled via\n * `SET n.embedding = ...`: Kuzu 0.11.x rejects writes to a vector-indexed column\n * (kuzudb/kuzu#5965), so codegraph v0.1.x deliberately skips the HNSW index and uses\n * brute-force `array_cosine_similarity` for semantic search. Putting the vector in the\n * CREATE clause makes the path identical whether or not embeddings exist.\n *\n * Phase 1 is a full-repo index. Incremental re-index lands in Phase 3 with the webhook\n * flow.\n */\nexport async function indexRepo(opts: IndexRepoOptions): Promise<IndexResult> {\n const start = Date.now();\n const parallelism = Math.max(1, opts.parallelism ?? cpus().length);\n\n const files = await walkRepo(opts.repoPath);\n opts.onProgress?.({ type: \"walk\", files: files.length });\n\n const parsable = files\n .map((rel) => ({ rel, language: detectLanguage(rel) }))\n .filter((f): f is { rel: string; language: NonNullable<ReturnType<typeof detectLanguage>> } =>\n f.language !== null,\n );\n\n const knownFilePaths = new Set(parsable.map((f) => f.rel));\n\n const allNodes: GraphNode[] = [];\n const allEdges: GraphEdge[] = [];\n let parsedCount = 0;\n let failed = 0;\n\n await runWithConcurrency(parsable, parallelism, async (entry) => {\n const abs = join(opts.repoPath, entry.rel);\n try {\n const source = await readFile(abs, \"utf8\");\n const result = await extractFile({\n repoId: opts.repoId,\n relativePath: entry.rel,\n absolutePath: abs,\n language: entry.language,\n source,\n });\n allNodes.push(result.file, ...result.nodes);\n allEdges.push(...result.edges);\n } catch (_err) {\n // Parse failures are non-fatal; we surface the count in IndexResult so\n // CI can flag if it spikes.\n failed++;\n } finally {\n parsedCount++;\n opts.onProgress?.({ type: \"parse\", parsed: parsedCount, total: parsable.length });\n }\n });\n\n const tsconfigPaths = await loadTsconfigPaths(opts.repoPath);\n const { resolved, dropped } = resolveEdges({\n repoId: opts.repoId,\n nodes: allNodes,\n edges: allEdges,\n knownFilePaths,\n ...(tsconfigPaths ? { tsconfigPaths } : {}),\n });\n\n let embeddedById: Map<string, EmbeddedNode> = new Map();\n if (!opts.skipEmbeddings && opts.router) {\n const embedded = await embedNodes(allNodes, {\n router: opts.router,\n onBatch: ({ embedded, total }) =>\n opts.onProgress?.({ type: \"embed\", embedded, total }),\n });\n embeddedById = new Map(embedded.map((e) => [e.id, e]));\n }\n\n const nodePayload: UpsertNodeInput[] = allNodes.map((n) => {\n const e = embeddedById.get(n.id);\n const base = n as unknown as UpsertNodeInput;\n if (!e) return base;\n return { ...base, embedding: e.embedding, embeddingNamespace: e.embeddingNamespace };\n });\n\n // Wipe the repo's existing slice so the upcoming CREATE doesn't collide on primary keys.\n await opts.graphDb.deleteByRepo(opts.repoId);\n await opts.graphDb.upsertNodes(nodePayload);\n await opts.graphDb.upsertEdges(resolved as unknown as UpsertEdgeInput[]);\n opts.onProgress?.({ type: \"upsert\", nodes: allNodes.length, edges: resolved.length });\n\n const embeddingCount = embeddedById.size;\n\n return {\n durationMs: Date.now() - start,\n parsedFiles: parsedCount - failed,\n failedFiles: failed,\n nodes: allNodes.length,\n edges: resolved.length,\n embeddings: embeddingCount,\n droppedEdges: dropped,\n };\n}\n\n/**\n * Lightweight concurrency runner. We deliberately avoid `workerpool` here\n * because tree-sitter wasm initialization in worker_threads requires per-\n * worker grammar reloads, which is a regression for the small repos this\n * tool targets in Phase 1. Switching to true OS threads is a Phase 4\n * optimization once profiling shows we're CPU-bound on multi-million-LOC\n * repos.\n */\nasync function runWithConcurrency<T>(\n items: readonly T[],\n concurrency: number,\n fn: (item: T) => Promise<void>,\n): Promise<void> {\n let cursor = 0;\n const runners = Array.from({ length: Math.min(concurrency, items.length) }, async () => {\n while (cursor < items.length) {\n const i = cursor++;\n const item = items[i];\n if (item === undefined) continue;\n await fn(item);\n }\n });\n await Promise.all(runners);\n}\n\n/** Stable content hash used to skip re-parsing unchanged files later. */\nexport function hashFileContent(source: string): string {\n return createHash(\"sha1\").update(source).digest(\"hex\");\n}\n\n/** Helper for callers who only want a stat-based size. */\nexport async function fileSize(absolutePath: string): Promise<number> {\n const s = await stat(absolutePath);\n return s.size;\n}\n\n/** Used by smoke tests / docs to verify that ignore globs apply. */\nexport function buildIgnoreFilter(patterns: readonly string[]) {\n return ignore().add(patterns as string[]);\n}\n","import type { LlmRouter } from \"@codegraph/llm-router\";\nimport type { GraphNode } from \"@codegraph/shared\";\n\nexport interface EmbedderOptions {\n router: LlmRouter;\n /** Max items per `embed()` call. Defaults to 100 per the build plan. */\n batchSize?: number;\n /** Hook for progress reporting from the CLI. */\n onBatch?: (info: { batchIndex: number; total: number; embedded: number }) => void;\n}\n\nexport interface EmbeddedNode {\n id: string;\n embedding: number[];\n embeddingNamespace: string;\n}\n\n/**\n * Embedding input format from the build plan:\n * `${kind} ${name}\\n${signature}\\n${leadingComment}`\n *\n * File nodes are excluded - we embed *symbols*, not raw files.\n */\nexport function buildEmbeddingInput(node: GraphNode): string {\n const sig = node.signature ?? \"\";\n const comment = node.leadingComment ?? \"\";\n return `${node.kind} ${node.name}\\n${sig}\\n${comment}`.trim();\n}\n\nexport async function embedNodes(\n nodes: GraphNode[],\n opts: EmbedderOptions,\n): Promise<EmbeddedNode[]> {\n const batchSize = opts.batchSize ?? 100;\n const candidates = nodes.filter((n) => n.kind !== \"File\");\n const totalSymbols = candidates.length;\n const result: EmbeddedNode[] = [];\n const namespace = `${opts.router.config.embeddingNamespace.provider}:${opts.router.config.embeddingNamespace.model}:${opts.router.config.embeddingNamespace.dimension}`;\n for (let i = 0; i < candidates.length; i += batchSize) {\n const slice = candidates.slice(i, i + batchSize);\n const inputs = slice.map(buildEmbeddingInput);\n const vectors = await opts.router.embed(inputs);\n for (let j = 0; j < slice.length; j++) {\n const node = slice[j];\n const vec = vectors[j];\n if (!node || !vec) continue;\n result.push({ id: node.id, embedding: vec, embeddingNamespace: namespace });\n }\n opts.onBatch?.({\n batchIndex: i / batchSize,\n total: totalSymbols,\n embedded: result.length,\n });\n }\n return result;\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { TsconfigPaths } from \"./extractors/resolve.js\";\n\n/**\n * Best-effort loader for a repo's TypeScript path-alias table. We deliberately do *not*\n * pull in the `typescript` package or `tsconfig-paths`: we only need the `compilerOptions\n * .baseUrl` + `compilerOptions.paths` fields, and we can parse those out of the JSON\n * ourselves. Real tsconfigs allow comments and trailing commas (JSONC), so we strip\n * those before `JSON.parse`.\n *\n * Resolution order: `tsconfig.json`, then `jsconfig.json` as a fallback for JS-only\n * repos. We do NOT follow the `extends` chain - if a project splits its config across\n * multiple files we'll miss aliases declared in a parent. This is acceptable for v0.1.x\n * and can be made recursive later.\n *\n * Returns `null` when no usable config is found, the file can't be parsed, or it has no\n * `paths` entries.\n */\nexport async function loadTsconfigPaths(repoRoot: string): Promise<TsconfigPaths | null> {\n for (const name of [\"tsconfig.json\", \"jsconfig.json\"]) {\n const raw = await readIfExists(path.join(repoRoot, name));\n if (!raw) continue;\n let parsed: { compilerOptions?: { baseUrl?: string; paths?: Record<string, string[]> } };\n try {\n parsed = JSON.parse(stripJsonComments(raw)) as typeof parsed;\n } catch {\n continue;\n }\n const co = parsed.compilerOptions ?? {};\n const paths = co.paths ?? {};\n if (Object.keys(paths).length === 0) continue;\n const baseUrl = (co.baseUrl ?? \".\").trim();\n return {\n baseUrl: toPosix(baseUrl),\n paths,\n };\n }\n return null;\n}\n\nasync function readIfExists(filePath: string): Promise<string | null> {\n try {\n return await readFile(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Strip line + block comments and trailing commas. Naïve but enough for tsconfig: we\n * preserve string contents (including any `//` or `/*` inside them) by walking the\n * source character-by-character with a tiny state machine.\n */\nfunction stripJsonComments(input: string): string {\n let out = \"\";\n let i = 0;\n let inString = false;\n let stringChar = \"\";\n while (i < input.length) {\n const c = input[i];\n const next = input[i + 1];\n if (inString) {\n out += c;\n if (c === \"\\\\\" && next !== undefined) {\n out += next;\n i += 2;\n continue;\n }\n if (c === stringChar) inString = false;\n i++;\n continue;\n }\n if (c === '\"' || c === \"'\") {\n inString = true;\n stringChar = c;\n out += c;\n i++;\n continue;\n }\n if (c === \"/\" && next === \"/\") {\n while (i < input.length && input[i] !== \"\\n\") i++;\n continue;\n }\n if (c === \"/\" && next === \"*\") {\n i += 2;\n while (i < input.length && !(input[i] === \"*\" && input[i + 1] === \"/\")) i++;\n i += 2;\n continue;\n }\n out += c;\n i++;\n }\n return removeTrailingCommas(out);\n}\n\nfunction removeTrailingCommas(s: string): string {\n return s.replace(/,\\s*([}\\]])/g, \"$1\");\n}\n\nfunction toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n","import { readFile, readdir, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\n\n/**\n * Directories we never traverse regardless of .gitignore contents. Mix of:\n * - VCS / IDE metadata (`.git`, `.idea`, `.vscode`)\n * - JS/TS build + tool caches (`node_modules`, `dist`, `build`, `out`, `.next`,\n * `.turbo`, `.cache`, `coverage`, `.parcel-cache`, `.svelte-kit`, `.nuxt`)\n * - Python virtualenvs and caches (`venv`, `.venv`, `env`, `.env.local`, `__pycache__`,\n * `site-packages`, `.pytest_cache`, `.mypy_cache`, `.ruff_cache`, `.tox`, `.eggs`)\n * - Rust / Go / Java / Swift build dirs (`target`, `vendor`, `Pods`, `DerivedData`)\n * - Test-runner artifacts and OS metadata (`.nyc_output`, `__snapshots__` we keep\n * because they're useful; `.DS_Store` files filter naturally on read).\n *\n * Without these, walking a real-world repo (especially one with a Python `venv/` or\n * a checked-in `vendor/`) will pull in tens of thousands of irrelevant files and tank\n * indexing time + graph signal-to-noise.\n */\nconst ALWAYS_SKIP_DIRS = new Set([\n \".git\",\n \".hg\",\n \".svn\",\n \"node_modules\",\n \".next\",\n \".nuxt\",\n \".svelte-kit\",\n \"dist\",\n \"build\",\n \"out\",\n \".turbo\",\n \".cache\",\n \".parcel-cache\",\n \"coverage\",\n \".nyc_output\",\n \".idea\",\n \".vscode\",\n \".vs\",\n \"venv\",\n \".venv\",\n \"env\",\n \"__pycache__\",\n \"site-packages\",\n \".pytest_cache\",\n \".mypy_cache\",\n \".ruff_cache\",\n \".tox\",\n \".eggs\",\n \"target\",\n \"vendor\",\n \"Pods\",\n \"DerivedData\",\n \".gradle\",\n \".terraform\",\n]);\n\n/**\n * DFS over `root`. Honors the *root* `.gitignore` and the always-skip\n * directory set above. Nested `.gitignore` files (e.g. one inside\n * `packages/foo/`) are intentionally ignored for Phase 1 simplicity -\n * monorepos hit this limitation rarely because the root file usually\n * captures shared exclusions. Returns repo-relative POSIX paths.\n */\nexport async function walkRepo(root: string): Promise<string[]> {\n const base = path.resolve(root);\n const matcher = ignore();\n await loadGitignoreInto(matcher, base);\n const out: string[] = [];\n await walkDir(base, \"\", matcher, out);\n return out.sort();\n}\n\nasync function walkDir(\n absDir: string,\n relDir: string,\n ig: Ignore,\n out: string[],\n): Promise<void> {\n let entries: import(\"node:fs\").Dirent<string>[];\n try {\n entries = await readdir(absDir, { withFileTypes: true, encoding: \"utf8\" });\n } catch {\n return;\n }\n for (const entry of entries) {\n const name = entry.name;\n const rel = relDir ? `${relDir}/${name}` : name;\n const abs = path.join(absDir, name);\n if (entry.isDirectory()) {\n if (ALWAYS_SKIP_DIRS.has(name)) continue;\n // `ignore` expects a trailing slash to test directories.\n if (ig.ignores(`${rel}/`)) continue;\n await walkDir(abs, rel, ig, out);\n } else if (entry.isFile()) {\n if (ig.ignores(rel)) continue;\n const s = await safeStat(abs);\n if (s && s.size > 2_000_000) continue;\n out.push(rel);\n }\n }\n}\n\nasync function loadGitignoreInto(ig: Ignore, absDir: string): Promise<void> {\n const file = path.join(absDir, \".gitignore\");\n try {\n const text = await readFile(file, \"utf8\");\n ig.add(text);\n } catch {\n // Missing or unreadable .gitignore - fine.\n }\n}\n\nasync function safeStat(p: string): Promise<Awaited<ReturnType<typeof stat>> | null> {\n try {\n return await stat(p);\n } catch {\n return null;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport path from \"node:path\";\n\n/**\n * Deterministic, human-readable repo identifier based on the absolute path.\n * Falls back to a short hash for collisions or weird path characters.\n *\n * /Users/x/Code/codegraph -> codegraph-aab12cd3\n */\nexport function repoIdFromPath(absPath: string): string {\n const base = path.basename(path.resolve(absPath));\n const sha = createHash(\"sha1\").update(path.resolve(absPath)).digest(\"hex\").slice(0, 8);\n const safe = base.replace(/[^A-Za-z0-9_-]/g, \"_\");\n return `${safe}-${sha}`;\n}\n","import { spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { confirm, input, password, select } from \"@inquirer/prompts\";\nimport { createLlmRouter, namespaceLabel } from \"@codegraph/llm-router\";\nimport { resolveServerConfig } from \"@codegraph/mcp-server\";\nimport { LLM_PRESETS } from \"@codegraph/shared\";\nimport boxen from \"boxen\";\nimport kleur from \"kleur\";\nimport { configPath, loadConfig, saveConfig } from \"../config-store.js\";\nimport { detectOllama, LOCAL_MODELS } from \"../ollama.js\";\nimport { makeSpinner, printBanner } from \"../ui.js\";\n\nconst TOTAL_STEPS = 6;\n\n/**\n * Interactive onboarding wizard. Walks a brand-new user from \"I just installed codegraph\"\n * to \"my AI assistant is calling MCP tools against my repo\" without forcing them to\n * read README files. Designed to be the first command we point new users at.\n *\n * Flow: welcome → env check → LLM setup → live credential test → optional index →\n * MCP server boot instructions → AI client config with real bearer token → celebrate.\n */\nexport async function runInitCommand(): Promise<void> {\n printWelcome();\n const start = await confirm({ message: \"Ready to get started?\", default: true });\n if (!start) {\n console.log(kleur.dim(\"Aborted. Run `codegraph init` again any time.\"));\n return;\n }\n\n runEnvCheck();\n await runLlmSetup();\n await runLiveTest();\n await runIndexStep();\n const bearerToken = await runServeStep();\n await runClientStep(bearerToken);\n await runCelebration();\n}\n\nfunction printWelcome(): void {\n printBanner();\n const description = [\n kleur.bold(\"CodeGraph\") +\n \" parses your JS/TS repo with tree-sitter, stores nodes (Function, Class,\",\n \"Route…) and edges (CALLS, IMPORTS, RENDERS…) in an embedded Kuzu graph with\",\n \"vector embeddings, then runs a local MCP server your AI assistant can call.\",\n \"\",\n kleur.dim(\"This wizard will:\"),\n ` ${kleur.cyan(\"1.\")} Configure an LLM provider (cloud or local)`,\n ` ${kleur.cyan(\"2.\")} Verify your credentials with a live round-trip`,\n ` ${kleur.cyan(\"3.\")} Index this repo into the graph`,\n ` ${kleur.cyan(\"4.\")} Show you how to boot the MCP server`,\n ` ${kleur.cyan(\"5.\")} Print a copy-paste config for your AI client`,\n ].join(\"\\n\");\n process.stdout.write(\n `${boxen(description, {\n padding: 1,\n margin: { top: 0, bottom: 1, left: 0, right: 0 },\n borderStyle: \"round\",\n borderColor: \"cyan\",\n title: kleur.bold(\"Welcome\"),\n titleAlignment: \"left\",\n })}\\n`,\n );\n}\n\nfunction stepHeader(n: number, label: string): void {\n console.log();\n console.log(\n kleur.cyan(`──── Step ${n}/${TOTAL_STEPS}: ${kleur.bold(label)} ${\"─\".repeat(Math.max(4, 40 - label.length))}`),\n );\n}\n\nfunction runEnvCheck(): void {\n stepHeader(1, \"Environment check\");\n const version = process.versions.node;\n const major = Number(version.split(\".\")[0] ?? 0);\n if (major < 20) {\n console.log(`${kleur.red(\"✗\")} node version v${version} ${kleur.red(\"(codegraph requires >= 20)\")}`);\n throw new Error(`Node ${version} is too old; install Node 20+ and re-run \\`codegraph init\\`.`);\n }\n console.log(`${kleur.green(\"✓\")} node version ${kleur.dim(`v${version}`)}`);\n}\n\n/**\n * Two-level LLM selection: local-zero-cost vs cloud. The local path drives a full\n * Ollama detection and guided setup flow; cloud mirrors the original behaviour.\n */\nasync function runLlmSetup(): Promise<void> {\n stepHeader(2, \"LLM setup\");\n\n const mode = await select({\n message: \"How would you like to power CodeGraph?\",\n choices: [\n {\n name: \"Local, zero cost\",\n value: \"local\",\n description:\n \"Runs entirely on your laptop. No API keys. Uses Ollama (guided install).\",\n },\n {\n name: \"Cloud provider\",\n value: \"cloud\",\n description: \"OpenAI, Anthropic, or Google. Better quality, requires an API key.\",\n },\n ],\n });\n\n if (mode === \"local\") {\n await setupLocalOllama();\n } else {\n await setupCloudProvider();\n }\n}\n\n/**\n * Detects Ollama state and guides the user through whichever recovery path is needed:\n * install, start, or model pull. Falls back to a custom-URL or cloud escape hatch if\n * the user can't or doesn't want to run Ollama.\n */\nasync function setupLocalOllama(): Promise<void> {\n const spinner = makeSpinner(\"Detecting Ollama\").start();\n let detection = await detectOllama();\n spinner.stop();\n\n // ── Not installed ──────────────────────────────────────────────────────────\n if (detection.status === \"not-installed\") {\n console.log();\n console.log(kleur.yellow(\" Ollama is not installed.\"));\n console.log(` ${kleur.cyan(\"→\")} Install from: ${kleur.underline(\"https://ollama.com\")}`);\n console.log(` ${kleur.dim(\" Then run: ollama serve\")}`);\n openUrl(\"https://ollama.com\");\n\n const next = await select({\n message: \"What would you like to do?\",\n choices: [\n { name: \"I just installed it — detect again\", value: \"retry\" },\n { name: \"Use a custom local server (llama.cpp, LM Studio, vLLM…)\", value: \"custom\" },\n { name: \"Switch to a cloud provider instead\", value: \"cloud\" },\n { name: \"Skip for now (configure LLM later)\", value: \"skip\" },\n ],\n });\n if (next === \"retry\") { await setupLocalOllama(); return; }\n if (next === \"custom\") { await setupCustomUrl(); return; }\n if (next === \"cloud\") { await setupCloudProvider(); return; }\n console.log(kleur.yellow(\"! Skipped. Run `codegraph config llm set` to configure later.\"));\n return;\n }\n\n // ── Installed but daemon not running ──────────────────────────────────────\n if (detection.status === \"installed-not-running\") {\n console.log();\n console.log(kleur.yellow(\" Ollama is installed but not running.\"));\n console.log(` Start it in another terminal: ${kleur.cyan(\"ollama serve\")}`);\n\n while (true) {\n const next = await select({\n message: \"What would you like to do?\",\n choices: [\n { name: \"Retry (I started ollama serve)\", value: \"retry\" },\n { name: \"Use a custom local server (llama.cpp, LM Studio, vLLM…)\", value: \"custom\" },\n { name: \"Switch to a cloud provider instead\", value: \"cloud\" },\n { name: \"Skip for now (configure LLM later)\", value: \"skip\" },\n ],\n });\n if (next === \"custom\") { await setupCustomUrl(); return; }\n if (next === \"cloud\") { await setupCloudProvider(); return; }\n if (next === \"skip\") {\n console.log(kleur.yellow(\"! Skipped. Run `codegraph config llm set` to configure later.\"));\n return;\n }\n const retrySpinner = makeSpinner(\"Checking Ollama\").start();\n detection = await detectOllama();\n retrySpinner.stop();\n if (detection.status === \"ready\" || detection.status === \"running-no-models\") break;\n console.log(kleur.red(\" ✗ Ollama still not reachable on :11434.\"));\n }\n }\n\n // ── Running but required models missing — pull them ───────────────────────\n if (detection.status === \"running-no-models\") {\n console.log(kleur.dim(` Ollama is running. Pulling required models…`));\n try {\n await pullOllamaModels();\n } catch (err) {\n console.log(\n kleur.yellow(`! Pull failed: ${err instanceof Error ? err.message : String(err)}`),\n );\n console.log(kleur.dim(\" You can pull manually: ollama pull qwen2.5-coder:1.5b && ollama pull nomic-embed-text\"));\n }\n }\n\n if (detection.status === \"ready\") {\n console.log(`${kleur.green(\"✓\")} Ollama ready, required models present`);\n }\n\n // ── Save preset ───────────────────────────────────────────────────────────\n const config = await loadConfig();\n const lookup = LLM_PRESETS[\"local-ollama\"]!;\n config.llm = { ...config.llm, ...lookup };\n config.llm.baseUrl = undefined;\n await saveConfig(config);\n console.log(`${kleur.green(\"✓\")} preset saved ${kleur.dim('\"local-ollama\" → ' + configPath())}`);\n console.log(`${kleur.dim(\" namespace \")}${namespaceLabel(config.llm)}`);\n}\n\n/** Pull the two required Ollama models, streaming progress directly to the terminal. */\nasync function pullOllamaModels(): Promise<void> {\n for (const model of [LOCAL_MODELS.generation, LOCAL_MODELS.embeddings]) {\n console.log(kleur.dim(` pulling ${model}…`));\n await new Promise<void>((resolve, reject) => {\n const child = spawn(\"ollama\", [\"pull\", model], { stdio: \"inherit\" });\n child.on(\"error\", (err) =>\n reject(new Error(`Failed to spawn ollama: ${err.message}`)),\n );\n child.on(\"exit\", (code) => {\n if (code === 0) resolve();\n else reject(new Error(`ollama pull ${model} exited with code ${code}`));\n });\n });\n }\n console.log(`${kleur.green(\"✓\")} models ready`);\n}\n\n/**\n * Escape hatch: prompt for a base URL and model names for any OpenAI-compatible local\n * server (llama.cpp server, LM Studio, vLLM, LocalAI). Saves the\n * local-openai-compatible preset with the user-supplied values.\n */\nasync function setupCustomUrl(): Promise<void> {\n console.log();\n console.log(kleur.dim(\" Compatible servers: llama.cpp server, LM Studio, vLLM, LocalAI\"));\n console.log(kleur.dim(\" Make sure your server exposes /v1/chat/completions and /v1/embeddings\"));\n console.log();\n\n const baseUrl = await input({\n message: \"Server base URL:\",\n default: \"http://localhost:8080/v1\",\n validate: (v) =>\n v.trim().startsWith(\"http\") ? true : \"Must be an http(s) URL\",\n });\n\n const genModel = await input({\n message: \"Generation model name (as loaded in your server):\",\n default: \"qwen2.5-coder\",\n });\n\n const embedModel = await input({\n message: \"Embedding model name:\",\n default: \"nomic-embed-text\",\n });\n\n const lookup = LLM_PRESETS[\"local-openai-compatible\"]!;\n const config = await loadConfig();\n config.llm = {\n ...config.llm,\n ...lookup,\n generation: { provider: \"openai\", model: genModel.trim() },\n embeddings: { provider: \"openai\", model: embedModel.trim(), dimension: 768 },\n baseUrl: baseUrl.trim(),\n };\n await saveConfig(config);\n\n console.log();\n console.log(\n `${kleur.green(\"✓\")} preset saved ${kleur.dim('\"local-openai-compatible\" → ' + configPath())}`,\n );\n console.log(`${kleur.dim(\" base URL \")}${kleur.dim(baseUrl.trim())}`);\n console.log(\n kleur.dim(\n \" Tip: edit ~/.codegraph/config.json to adjust embeddings.dimension if your model differs from 768.\",\n ),\n );\n}\n\n/** Cloud provider sub-picker. Applies the chosen preset and prompts for the API key. */\nasync function setupCloudProvider(): Promise<void> {\n const preset = await select({\n message: \"Which cloud provider?\",\n choices: [\n {\n name: \"OpenAI\",\n value: \"byo-openai\",\n description: \"gpt-4o-mini + text-embedding-3-small\",\n },\n {\n name: \"Anthropic\",\n value: \"byo-anthropic\",\n description: \"claude-3-5-haiku (gen) + OpenAI text-embedding-3-small (embed)\",\n },\n {\n name: \"Google\",\n value: \"byo-google\",\n description: \"gemini-1.5-flash + text-embedding-004\",\n },\n ],\n });\n\n const lookup = LLM_PRESETS[preset];\n if (!lookup) throw new Error(`Unknown preset \"${preset}\".`);\n\n const config = await loadConfig();\n config.llm = { ...config.llm, ...lookup };\n config.llm.baseUrl = undefined;\n await saveConfig(config);\n\n console.log();\n console.log(`${kleur.green(\"✓\")} preset saved ${kleur.dim(`\"${preset}\" → ${configPath()}`)}`);\n console.log(`${kleur.dim(\" namespace \")}${namespaceLabel(config.llm)}`);\n\n if (preset === \"byo-anthropic\") {\n console.log();\n console.log(kleur.yellow(\"Note: Anthropic has no embedding API, so codegraph uses OpenAI embeddings.\"));\n console.log(kleur.yellow(\"You'll need both ANTHROPIC_API_KEY and OPENAI_API_KEY set.\"));\n await promptApiKey(\"ANTHROPIC_API_KEY\");\n await promptApiKey(\"OPENAI_API_KEY\");\n return;\n }\n\n const envVar = apiKeyEnvVarFor(preset);\n if (envVar) await promptApiKey(envVar);\n}\n\n/** Open a URL in the default browser without blocking. */\nfunction openUrl(url: string): void {\n const cmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n const child = spawn(cmd, [url], { detached: true, stdio: \"ignore\" });\n child.unref();\n}\n\nfunction apiKeyEnvVarFor(preset: string): string | null {\n if (preset === \"byo-openai\" || preset === \"managed-stub\") return \"OPENAI_API_KEY\";\n if (preset === \"byo-anthropic\") return \"ANTHROPIC_API_KEY\";\n if (preset === \"byo-google\") return \"GOOGLE_GENERATIVE_AI_API_KEY\";\n return null;\n}\n\n/**\n * Hidden-input prompt for a single API key env var. We never persist the key to disk;\n * shell env vars stay the right place for secrets. If the user opts to provide a value,\n * we set it in `process.env` for the current process (so the live test + index work\n * immediately) and also print the `export` line so they can persist it themselves.\n */\nasync function promptApiKey(envVar: string): Promise<void> {\n console.log();\n if (process.env[envVar]) {\n console.log(`${kleur.green(\"✓\")} ${envVar} ${kleur.dim(\"already set in this shell\")}`);\n return;\n }\n const provide = await confirm({\n message: `${envVar} is not set. Provide it now? (input will be hidden)`,\n default: true,\n });\n if (!provide) {\n console.log(\n kleur.yellow(`! Skipped. Export ${envVar} before \\`codegraph index\\` or \\`codegraph serve\\`.`),\n );\n return;\n }\n const value = await password({ message: `${envVar}`, mask: \"*\" });\n if (!value) {\n console.log(kleur.yellow(`! Empty value — skipping ${envVar}.`));\n return;\n }\n process.env[envVar] = value;\n console.log();\n console.log(kleur.dim(\"Add this to your ~/.zshrc or ~/.bashrc so it persists:\"));\n console.log(` ${kleur.cyan(`export ${envVar}=${maskTail(value)}`)}`);\n}\n\n/** Show only the last 4 chars of a secret, masking the rest, for the displayed export line. */\nfunction maskTail(value: string): string {\n if (value.length <= 8) return \"*\".repeat(value.length);\n return `${\"*\".repeat(value.length - 4)}${value.slice(-4)}`;\n}\n\n/**\n * Live round-trip against the configured LLM. Same logic as `config llm test` but with\n * a retry loop so the user can fix credentials in another terminal and retry without\n * restarting the wizard.\n */\nasync function runLiveTest(): Promise<void> {\n stepHeader(3, \"Verify credentials\");\n while (true) {\n const config = await loadConfig();\n console.log(\n kleur.dim(\n ` testing ${config.llm.generation.provider}:${config.llm.generation.model} + ${config.llm.embeddings.provider}:${config.llm.embeddings.model}`,\n ),\n );\n const spinner = makeSpinner(\"Calling provider\").start();\n try {\n const router = await createLlmRouter({ config: config.llm });\n const result = await router.selfTest();\n spinner.succeed(\"LLM provider reachable\");\n console.log(\n kleur.dim(\n ` embed=${result.embedLatencyMs}ms gen=${result.generateLatencyMs}ms dims=${result.embedDims}`,\n ),\n );\n return;\n } catch (err) {\n spinner.fail(\"LLM provider unreachable\");\n console.log(kleur.red(` ${err instanceof Error ? err.message : String(err)}`));\n\n const choice = await select({\n message: \"What now?\",\n choices: [\n { name: \"Retry (I'll fix it in another terminal)\", value: \"retry\" },\n { name: \"Skip — set up LLM later\", value: \"skip\" },\n ],\n });\n if (choice === \"skip\") {\n console.log(\n kleur.yellow(\n \"! Continuing without a verified LLM. Embeddings and semantic search will fail until you fix this.\",\n ),\n );\n return;\n }\n }\n }\n}\n\n/**\n * Optional: index the current working directory.\n *\n * We deliberately spawn `codegraph index <cwd>` as a child process rather than calling\n * `runIndexCommand()` in-process. Kuzu's Node.js bindings (0.11.x) attach N-API\n * finalizers to the Database/Connection handles and rely on a process-exit hook for\n * final cleanup. When we kept indexing in-process, those finalizers ran on libuv\n * worker threads while the next inquirer prompt grabbed stdin in raw mode, racing\n * with readline and SIGSEGV'ing the wizard. Running indexing in a child isolates\n * Kuzu's lifecycle entirely — the child dies, Kuzu cleans up safely with no stdin\n * to fight over, and the parent wizard's terminal stays untouched.\n */\nasync function runIndexStep(): Promise<void> {\n stepHeader(4, \"Index this repo\");\n const cwd = process.cwd();\n const display = abbreviateHome(cwd);\n const yes = await confirm({\n message: `Index the current directory (${display}) now?`,\n default: true,\n });\n if (!yes) {\n console.log(kleur.dim(\"Skipped. Run this when ready:\"));\n console.log(` ${kleur.cyan(`codegraph index ${display}`)}`);\n return;\n }\n console.log();\n\n const binPath = resolveBinPath();\n try {\n await spawnIndex(binPath, cwd);\n } catch (err) {\n console.log();\n console.log(\n kleur.yellow(\n `! Index failed: ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n console.log(\n kleur.dim(\" You can retry later with `codegraph index <path>`. Continuing wizard.\"),\n );\n }\n}\n\n/**\n * Locate the codegraph CLI binary. When the wizard is running, `process.argv[1]` is the\n * resolved path to `dist/bin.js` (Node resolves the npm bin shim symlink before exec).\n * Fall back to a relative lookup from this module's location when argv[1] isn't a real\n * file (e.g. during weird launchers). Both paths land on the same `dist/bin.js`.\n */\nfunction resolveBinPath(): string {\n if (process.argv[1] && path.isAbsolute(process.argv[1])) return process.argv[1];\n return fileURLToPath(new URL(\"./bin.js\", import.meta.url));\n}\n\nfunction spawnIndex(binPath: string, repoPath: string): Promise<void> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(process.execPath, [binPath, \"index\", repoPath], {\n stdio: \"inherit\",\n env: process.env,\n });\n child.on(\"error\", reject);\n child.on(\"exit\", (code, signal) => {\n if (signal) {\n reject(new Error(`codegraph index terminated by signal ${signal}`));\n return;\n }\n if (code !== 0) {\n reject(new Error(`codegraph index exited with code ${code}`));\n return;\n }\n resolvePromise();\n });\n });\n}\n\n/**\n * MCP server step. Doesn't actually start the server (the user needs it running in a\n * separate terminal so `codegraph init` can keep prompting). Generates/reads the bearer\n * token so we can show the real value in the next step's config snippet.\n */\nasync function runServeStep(): Promise<string> {\n stepHeader(5, \"Boot the MCP server\");\n\n const { config: serverConfig, created } = await resolveServerConfig({});\n if (created) {\n console.log(kleur.dim(\" generated a new bearer token for this machine\"));\n }\n\n const url = `http://${serverConfig.host}:${serverConfig.port}/mcp`;\n const body = [\n \"Open a \" + kleur.bold(\"new terminal\") + \" and run:\",\n \"\",\n ` ${kleur.cyan(\"codegraph serve\")}`,\n \"\",\n kleur.dim(\"Expected output:\"),\n kleur.dim(` codegraph mcp listening on ${url}`),\n \"\",\n kleur.dim(\"Keep that terminal running while you use CodeGraph.\"),\n ].join(\"\\n\");\n process.stdout.write(\n `${boxen(body, {\n padding: { top: 0, bottom: 0, left: 2, right: 2 },\n margin: { top: 1, bottom: 1, left: 0, right: 0 },\n borderStyle: \"round\",\n borderColor: \"cyan\",\n title: kleur.bold(\"Start the server\"),\n titleAlignment: \"left\",\n })}\\n`,\n );\n\n await confirm({\n message: \"Done — the server is running in another terminal?\",\n default: true,\n });\n return serverConfig.bearerToken;\n}\n\n/**\n * Client selector + filled-in config snippet. The bearer token is the real resolved\n * value, so the user can copy-paste verbatim without hunting in `config.json`.\n */\nasync function runClientStep(bearerToken: string): Promise<void> {\n stepHeader(6, \"Connect your AI client\");\n\n const url = \"http://127.0.0.1:3748/mcp\";\n\n const client = await select({\n message: \"Which AI client are you connecting?\",\n choices: [\n { name: \"Cursor\", value: \"cursor\" },\n { name: \"Claude Code\", value: \"claude\" },\n { name: \"Windsurf\", value: \"windsurf\" },\n { name: \"Skip for now\", value: \"skip\" },\n ],\n });\n\n if (client === \"skip\") {\n console.log(\n kleur.dim(\"Skipped. See docs/clients.md for per-client configuration when ready.\"),\n );\n return;\n }\n\n if (client === \"cursor\") {\n const snippet = JSON.stringify(\n {\n mcpServers: {\n codegraph: {\n url,\n headers: { Authorization: `Bearer ${bearerToken}` },\n },\n },\n },\n null,\n 2,\n );\n const body = [\n \"Create or edit \" + kleur.cyan(\".cursor/mcp.json\") + \" in your project root:\",\n \"\",\n kleur.green(snippet),\n \"\",\n kleur.dim(\"Then open Cursor → Settings → MCP.\"),\n kleur.dim(\"`codegraph` should appear as connected with 10 tools.\"),\n ].join(\"\\n\");\n process.stdout.write(\n `${boxen(body, {\n padding: 1,\n margin: { top: 1, bottom: 1, left: 0, right: 0 },\n borderStyle: \"round\",\n borderColor: \"magenta\",\n title: kleur.bold(\"Cursor config\"),\n titleAlignment: \"left\",\n })}\\n`,\n );\n } else if (client === \"claude\") {\n const oneliner = [\n \"claude mcp add --transport sse codegraph \\\\\",\n ` ${url} \\\\`,\n ` --header \"Authorization: Bearer ${bearerToken}\"`,\n ].join(\"\\n\");\n const body = [\n \"Run this in your terminal:\",\n \"\",\n kleur.green(oneliner),\n \"\",\n kleur.dim(\"Then type \") +\n kleur.cyan(\"/mcp\") +\n kleur.dim(\" in Claude Code to confirm 10 tools are listed.\"),\n ].join(\"\\n\");\n process.stdout.write(\n `${boxen(body, {\n padding: 1,\n margin: { top: 1, bottom: 1, left: 0, right: 0 },\n borderStyle: \"round\",\n borderColor: \"magenta\",\n title: kleur.bold(\"Claude Code config\"),\n titleAlignment: \"left\",\n })}\\n`,\n );\n } else {\n const snippet = JSON.stringify(\n {\n mcpServers: {\n codegraph: {\n serverUrl: url,\n headers: { Authorization: `Bearer ${bearerToken}` },\n },\n },\n },\n null,\n 2,\n );\n const body = [\n \"Edit \" + kleur.cyan(\"~/.codeium/windsurf/mcp_config.json\") + \":\",\n \"\",\n kleur.green(snippet),\n \"\",\n kleur.dim(\"Then restart Windsurf or run \") +\n kleur.cyan(\"/refresh-tools\") +\n kleur.dim(\" in Cascade.\"),\n ].join(\"\\n\");\n process.stdout.write(\n `${boxen(body, {\n padding: 1,\n margin: { top: 1, bottom: 1, left: 0, right: 0 },\n borderStyle: \"round\",\n borderColor: \"magenta\",\n title: kleur.bold(\"Windsurf config\"),\n titleAlignment: \"left\",\n })}\\n`,\n );\n }\n\n await confirm({\n message: \"Done — your client is configured?\",\n default: true,\n });\n}\n\n/**\n * Final step: invite the user to try a real prompt, then print a celebration box. The\n * \"Skip\" branch still prints the summary so users can finish the wizard without an AI\n * client at hand.\n */\nasync function runCelebration(): Promise<void> {\n console.log();\n console.log(kleur.cyan(`──── ${kleur.bold(\"Almost there!\")} ────`));\n console.log(\n kleur.dim(\n 'Ask your AI assistant something like: \"What files are in this repo?\"',\n ),\n );\n console.log(\n kleur.dim(\"It should call a `codegraph_*` MCP tool to answer.\"),\n );\n console.log();\n\n const choice = await select({\n message: \"How did it go?\",\n choices: [\n { name: \"It worked!\", value: \"worked\" },\n { name: \"Skip\", value: \"skip\" },\n ],\n });\n\n const header =\n choice === \"worked\"\n ? kleur.green().bold(\"✓ CodeGraph is fully connected!\")\n : kleur.cyan().bold(\"✓ CodeGraph setup complete\");\n\n const body = [\n header,\n \"\",\n \"Your AI assistant can now call these tools:\",\n ` ${kleur.cyan(\"•\")} find_callers — what calls a function`,\n ` ${kleur.cyan(\"•\")} get_component_tree — render dependency tree`,\n ` ${kleur.cyan(\"•\")} blast_radius — impact of a change`,\n ` ${kleur.cyan(\"•\")} search_semantic — symbol search by description`,\n ` ${kleur.cyan(\"•\")} nl_query — natural-language Cypher`,\n ` ${kleur.dim(\"…plus 5 more (search_symbol, find_file, get_file_context,\")}`,\n ` ${kleur.dim(\" get_dependencies, affected_by)\")}`,\n \"\",\n kleur.dim(\"Visualise the graph:\"),\n ` ${kleur.cyan(\"codegraph view\")} ${kleur.dim(\"— opens the interactive graph explorer in your browser\")}`,\n ` ${kleur.dim(\"or visit\")} ${kleur.cyan(\"http://127.0.0.1:3748/viewer\")} ${kleur.dim(\"while the server is running\")}`,\n \"\",\n kleur.dim(\"Helpful next steps:\"),\n ` ${kleur.cyan(\"codegraph doctor\")} ${kleur.dim(\"— verify environment + LLM + Kuzu\")}`,\n ` ${kleur.cyan(\"codegraph status\")} ${kleur.dim(\"<path>\")} ${kleur.dim(\"— node/edge counts + embedding coverage\")}`,\n \"\",\n kleur.dim(\"Docs: https://github.com/leanlabsinnov/codegraph\"),\n ].join(\"\\n\");\n\n process.stdout.write(\n `${boxen(body, {\n padding: 1,\n margin: { top: 1, bottom: 1, left: 0, right: 0 },\n borderStyle: \"round\",\n borderColor: choice === \"worked\" ? \"green\" : \"cyan\",\n })}\\n`,\n );\n}\n\n/** Replace the user's home directory with `~` for display, leaving everything else alone. */\nfunction abbreviateHome(p: string): string {\n const home = process.env.HOME ?? process.env.USERPROFILE;\n if (!home) return p;\n const rel = path.relative(home, p);\n if (rel.startsWith(\"..\")) return p;\n return rel ? `~${path.sep}${rel}` : \"~\";\n}\n","import { DEFAULT_CONFIG } from \"@codegraph/shared\";\nimport { InMemoryCache } from \"./cache.js\";\nimport {\n defaultConfigPath,\n readCodegraphConfig,\n resolveDbPath,\n resolveServerConfig,\n} from \"./config.js\";\nimport { createConsoleLogger } from \"./logger.js\";\nimport { type StartedSseServer, startSseServer } from \"./server.js\";\nimport type { GraphClient, LlmRouter, ServerConfig, ToolDeps } from \"./types.js\";\n\nexport interface StartMcpServerOptions {\n /** Port override; defaults to the value in config or {@link MCP_PORT}. */\n port?: number;\n host?: string;\n configPath?: string;\n /** Optional override for the embedded Kuzu graph directory. */\n dbPath?: string;\n /** Custom deps for tests; if provided, skips loading Phase-1 packages. */\n deps?: Partial<ToolDeps>;\n /**\n * Absolute path to the viewer static assets directory.\n * Forwarded to {@link startSseServer}; enables /viewer and /api/* routes.\n */\n viewerDir?: string;\n}\n\n/**\n * High-level CLI-facing helper. Reads `~/.codegraph/config.json`, wires up the embedded\n * Kuzu graph client and the LLM router from the Phase-1 packages, and boots the SSE\n * server. The tool-result cache is an in-process LRU; we no longer require Redis.\n *\n * Returns the running {@link StartedSseServer} so the caller can await graceful shutdown.\n */\nexport async function startMcpServer(\n portOrOptions?: number | StartMcpServerOptions,\n): Promise<StartedSseServer> {\n const options: StartMcpServerOptions =\n typeof portOrOptions === \"number\" ? { port: portOrOptions } : (portOrOptions ?? {});\n const logger = createConsoleLogger();\n\n const overrides: Partial<ServerConfig> = {};\n if (options.port !== undefined) overrides.port = options.port;\n if (options.host !== undefined) overrides.host = options.host;\n\n const { config, configPath, created } = await resolveServerConfig({\n ...(options.configPath !== undefined ? { configPath: options.configPath } : {}),\n overrides,\n });\n if (created) logger.info(\"generated new bearer token\", { configPath });\n\n const fileConfig = await readCodegraphConfig(options.configPath ?? defaultConfigPath());\n const dbPath = options.dbPath ?? resolveDbPath(fileConfig);\n\n const cache = options.deps?.cache ?? new InMemoryCache();\n const graph = options.deps?.graph ?? (await loadGraphClient(dbPath));\n const llm = options.deps?.llm ?? (await loadLlmRouter(options.configPath ?? defaultConfigPath()));\n\n const deps: ToolDeps = {\n graph,\n llm,\n cache,\n cacheTtlSeconds: config.cacheTtlSeconds,\n logger,\n };\n return startSseServer({ deps, config, viewerDir: options.viewerDir });\n}\n\n/** Dynamic import wrapper around `@codegraph/graph-db`. */\nasync function loadGraphClient(dbPath: string | undefined): Promise<GraphClient> {\n let mod: Record<string, unknown>;\n try {\n mod = (await import(\"@codegraph/graph-db\")) as Record<string, unknown>;\n } catch (err) {\n throw new Error(\n `Failed to import @codegraph/graph-db. Run \\`pnpm -r build\\` first. Underlying error: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n const GraphDb = mod.GraphDb as\n | (new (opts: { dbPath?: string }) => GraphDbLike)\n | undefined;\n if (typeof GraphDb !== \"function\") {\n throw new Error(\"@codegraph/graph-db has no `GraphDb` export.\");\n }\n const db = new GraphDb(dbPath !== undefined ? { dbPath } : {});\n await db.connect();\n await db.migrate();\n return {\n async query<T extends Record<string, unknown>>(\n cypher: string,\n params?: Record<string, unknown>,\n ): Promise<T[]> {\n const r = await db.query<T>(cypher, params ?? {});\n return r.data;\n },\n async close() {\n await db.close();\n },\n };\n}\n\ninterface GraphDbLike {\n connect(): Promise<void>;\n close(): Promise<void>;\n migrate(): Promise<void>;\n query<T extends Record<string, unknown> = Record<string, unknown>>(\n cypher: string,\n params?: Record<string, unknown>,\n ): Promise<{ data: T[] }>;\n}\n\n/** Dynamic import wrapper around `@codegraph/llm-router`. */\nasync function loadLlmRouter(configPath: string): Promise<LlmRouter> {\n let mod: Record<string, unknown>;\n try {\n mod = (await import(\"@codegraph/llm-router\")) as Record<string, unknown>;\n } catch (err) {\n throw new Error(\n `Failed to import @codegraph/llm-router. Run \\`pnpm -r build\\` first. Underlying error: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n const createLlmRouter = mod.createLlmRouter as\n | ((opts: {\n config?: unknown;\n configPath?: string;\n }) => Promise<RouterLike> | RouterLike)\n | undefined;\n if (typeof createLlmRouter !== \"function\") {\n throw new Error(\"@codegraph/llm-router has no `createLlmRouter` export.\");\n }\n // Read the persisted llm config out of the codegraph config file. If it's missing\n // (user ran `codegraph serve` before ever calling `codegraph config llm set`), fall\n // back to the shared DEFAULT_CONFIG so we at least surface a useful \"missing API key\"\n // error rather than a `Cannot read properties of undefined`.\n const fileConfig = await readCodegraphConfig(configPath);\n const llmConfig =\n (fileConfig.llm as { generation?: unknown; embeddings?: unknown } | undefined) ??\n undefined;\n const effectiveConfig =\n llmConfig && llmConfig.generation && llmConfig.embeddings ? llmConfig : DEFAULT_CONFIG.llm;\n const router = await createLlmRouter({\n config: effectiveConfig as unknown,\n configPath,\n });\n return adaptLlmRouter(router);\n}\n\ninterface RouterLike {\n embed(texts: string[]): Promise<number[][]>;\n generate(opts: {\n system?: string;\n messages: { role: \"system\" | \"user\" | \"assistant\"; content: string }[];\n maxTokens?: number;\n temperature?: number;\n }): Promise<string>;\n config?: {\n embeddingNamespace?: { provider: string; model: string; dimension: number };\n embeddings?: { provider: string; model: string; dimension: number };\n };\n}\n\nfunction adaptLlmRouter(router: RouterLike): LlmRouter {\n const ns =\n router.config?.embeddingNamespace ??\n (router.config?.embeddings\n ? {\n provider: router.config.embeddings.provider,\n model: router.config.embeddings.model,\n dimension: router.config.embeddings.dimension,\n }\n : { provider: \"unknown\", model: \"unknown\", dimension: 0 });\n return {\n embed: (texts) => router.embed(texts),\n generate: (opts) => router.generate(opts),\n embeddingNamespace: ns,\n };\n}\n","import { createHash } from \"node:crypto\";\nimport type { ToolCache } from \"./types.js\";\n\n/** Build a stable cache key from a tool name and arguments. */\nexport function buildCacheKey(toolName: string, args: unknown, namespace = \"v1\"): string {\n const serialized = stableStringify(args);\n const hash = createHash(\"sha1\").update(serialized).digest(\"hex\");\n return `codegraph:${namespace}:tool:${toolName}:${hash}`;\n}\n\n/** Deterministic JSON.stringify that sorts object keys. */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(value, (_key, v) => {\n if (v && typeof v === \"object\" && !Array.isArray(v)) {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(v as Record<string, unknown>).sort()) {\n sorted[key] = (v as Record<string, unknown>)[key];\n }\n return sorted;\n }\n return v;\n });\n}\n\n/**\n * In-memory TTL cache. Used everywhere now that we no longer run a separate Redis service.\n *\n * Per-process is fine for the single-user local tool: every MCP server boot starts with a\n * cold cache, which trades a few extra Cypher queries for one fewer process to manage.\n */\nexport class InMemoryCache implements ToolCache {\n private store = new Map<string, { value: string; expiresAt: number }>();\n\n async get(key: string): Promise<string | null> {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt <= Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value;\n }\n\n async set(key: string, value: string, ttlSeconds: number): Promise<void> {\n this.store.set(key, { value, expiresAt: Date.now() + ttlSeconds * 1000 });\n }\n\n async close(): Promise<void> {\n this.store.clear();\n }\n}\n\n/**\n * Returns a cached value or computes it via `compute`, storing the result with the given TTL.\n * Errors from the cache layer are swallowed - compute is still called, just uncached.\n */\nexport async function memoizeJson<T>(\n cache: ToolCache,\n key: string,\n ttlSeconds: number,\n compute: () => Promise<T>,\n): Promise<T> {\n const cached = await cache.get(key);\n if (cached !== null) {\n try {\n return JSON.parse(cached) as T;\n } catch {\n // corrupt cache entry; fall through and recompute\n }\n }\n const value = await compute();\n await cache.set(key, JSON.stringify(value), ttlSeconds);\n return value;\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, resolve } from \"node:path\";\nimport { generateBearerToken } from \"./server.js\";\nimport type { ServerConfig } from \"./types.js\";\n\n/**\n * Persisted config file shape. Stays intentionally permissive so we can interoperate with\n * the Phase-1 `~/.codegraph/config.json` that `@codegraph/llm-router` writes.\n *\n * - `mcpToken` is the legacy/Phase-1 location for the bearer token.\n * - `server.bearerToken` is the Phase-2 location. Both are accepted on read; new writes\n * populate both fields to avoid one writer clobbering another reader.\n * - `data.dbPath` is the optional override for the embedded Kuzu graph directory.\n */\nexport interface CodegraphConfigFile {\n llm?: Record<string, unknown>;\n data?: { dbPath?: string };\n server?: {\n host?: string;\n port?: number;\n bearerToken?: string;\n cacheTtlSeconds?: number;\n };\n /** Phase-1 alias for `server.bearerToken`. Treated as authoritative if both are set. */\n mcpToken?: string;\n [extra: string]: unknown;\n}\n\n/** Default MCP listen port. Used by both server boot and clients via {@link MCP_PORT}. */\nexport const MCP_PORT = 3748;\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_TTL = 30;\n\nexport function defaultConfigPath(): string {\n return resolve(homedir(), \".codegraph\", \"config.json\");\n}\n\nexport async function readCodegraphConfig(\n path: string = defaultConfigPath(),\n): Promise<CodegraphConfigFile> {\n try {\n const raw = await readFile(path, \"utf8\");\n return JSON.parse(raw) as CodegraphConfigFile;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return {};\n throw err;\n }\n}\n\nexport async function writeCodegraphConfig(\n config: CodegraphConfigFile,\n path: string = defaultConfigPath(),\n): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(config, null, 2)}\\n`, \"utf8\");\n}\n\n/**\n * Resolve runtime server config from (in order): CLI overrides, config file,\n * environment variables, then hard-coded defaults. Generates and persists a bearer token\n * the first time so users don't have to think about it.\n */\nexport async function resolveServerConfig(opts: {\n configPath?: string;\n overrides?: Partial<ServerConfig>;\n}): Promise<{ config: ServerConfig; configPath: string; created: boolean }> {\n const path = opts.configPath ?? defaultConfigPath();\n const fileConfig = await readCodegraphConfig(path);\n const env = process.env;\n\n let bearerToken =\n opts.overrides?.bearerToken ??\n fileConfig.mcpToken ??\n fileConfig.server?.bearerToken ??\n env.CODEGRAPH_BEARER_TOKEN ??\n \"\";\n let created = false;\n if (!bearerToken) {\n bearerToken = generateBearerToken();\n created = true;\n await writeCodegraphConfig(\n {\n ...fileConfig,\n mcpToken: bearerToken,\n server: { ...(fileConfig.server ?? {}), bearerToken },\n },\n path,\n );\n }\n\n const config: ServerConfig = {\n host: opts.overrides?.host ?? fileConfig.server?.host ?? env.CODEGRAPH_HOST ?? DEFAULT_HOST,\n port:\n opts.overrides?.port ??\n fileConfig.server?.port ??\n (env.CODEGRAPH_PORT ? Number(env.CODEGRAPH_PORT) : MCP_PORT),\n bearerToken,\n cacheTtlSeconds:\n opts.overrides?.cacheTtlSeconds ??\n fileConfig.server?.cacheTtlSeconds ??\n (env.CODEGRAPH_CACHE_TTL ? Number(env.CODEGRAPH_CACHE_TTL) : DEFAULT_TTL),\n };\n return { config, configPath: path, created };\n}\n\n/**\n * Resolve the on-disk Kuzu database path from (in order): the config file, the\n * `CODEGRAPH_DB_PATH` env var, then `undefined` (which lets `@codegraph/graph-db` fall\n * back to its own `~/.codegraph/graph` default).\n */\nexport function resolveDbPath(fileConfig: CodegraphConfigFile): string | undefined {\n return fileConfig.data?.dbPath ?? process.env.CODEGRAPH_DB_PATH ?? undefined;\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { Server as HttpServer } from \"node:http\";\nimport { join } from \"node:path\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport express, { type Request, type Response, type NextFunction, Router } from \"express\";\nimport { registerAllTools } from \"./tools/index.js\";\nimport { registerViewerApiRoutes } from \"./viewer-routes.js\";\nimport type { Logger, ServerConfig, ToolDeps } from \"./types.js\";\n\nexport interface CreateMcpServerOptions {\n deps: ToolDeps;\n /** Optional name/version override; defaults to \"codegraph\" / package version. */\n serverInfo?: { name: string; version: string } | undefined;\n}\n\n/** Build an MCP server, register every Phase-2 tool, and return it (unconnected). */\nexport function createMcpServer(opts: CreateMcpServerOptions): McpServer {\n const info = opts.serverInfo ?? { name: \"codegraph\", version: \"0.0.0\" };\n const server = new McpServer(info, {\n capabilities: { tools: {}, logging: {} },\n });\n registerAllTools(server, opts.deps);\n return server;\n}\n\nexport interface StartSseServerOptions {\n deps: ToolDeps;\n config: ServerConfig;\n serverInfo?: { name: string; version: string } | undefined;\n /**\n * Absolute path to the directory containing the static viewer HTML/JS/CSS.\n * When supplied the server exposes:\n * GET /viewer → index.html\n * GET /viewer/* → other static assets\n * GET /api/repos → unauthenticated JSON API\n * GET /api/graph → unauthenticated JSON API\n * Routes are served WITHOUT bearer-auth (loopback-only server, browser client).\n */\n viewerDir?: string | undefined;\n}\n\nexport interface StartedSseServer {\n /** Underlying Node HTTP server. */\n httpServer: HttpServer;\n /** Resolved listen address (handy when port=0 in tests). */\n address: { host: string; port: number };\n /** Graceful shutdown: close transports, then HTTP server, then deps. */\n close(): Promise<void>;\n}\n\n/**\n * Boot an HTTP server that exposes the MCP protocol over SSE on `${host}:${port}`.\n *\n * Endpoints (per the v1.x SDK example):\n * GET /mcp - establish SSE stream\n * POST /messages - client -> server JSON-RPC messages\n * GET /healthz - unauthenticated liveness probe\n *\n * Every authenticated request must include `Authorization: Bearer <token>`.\n */\nexport async function startSseServer(opts: StartSseServerOptions): Promise<StartedSseServer> {\n const { deps, config } = opts;\n const logger: Logger | undefined = deps.logger;\n const app = express();\n app.use(express.json({ limit: \"2mb\" }));\n\n app.get(\"/healthz\", (_req, res) => {\n res.status(200).json({ ok: true });\n });\n\n // Viewer + public API — registered BEFORE bearer auth (browser-accessible on loopback).\n if (opts.viewerDir) {\n const viewerDir = opts.viewerDir;\n // Serve index.html directly on both /viewer and /viewer/. We avoid\n // res.redirect(\"/viewer/\") here because Express's default non-strict\n // routing makes \"/viewer\" match \"/viewer/\" too, which would loop.\n const sendIndex = (_req: Request, res: Response, next: NextFunction): void => {\n res.sendFile(join(viewerDir, \"index.html\"), (err) => {\n if (err) next(err);\n });\n };\n app.get(\"/viewer\", sendIndex);\n app.get(\"/viewer/\", sendIndex);\n // Any additional static assets (future css/js/images) under /viewer/<file>.\n // `fallthrough: false` so a missing file returns 404 instead of cascading\n // into the bearer-auth middleware below.\n app.use(\n \"/viewer\",\n express.static(viewerDir, { index: false, fallthrough: false }),\n );\n // Mount the graph API routes (unauthenticated; loopback-only).\n const apiRouter = Router();\n registerViewerApiRoutes(apiRouter, deps.graph);\n app.use(apiRouter);\n }\n\n app.use(bearerAuthMiddleware(config.bearerToken, logger));\n\n const transports = new Map<string, SSEServerTransport>();\n\n app.get(\"/mcp\", async (_req: Request, res: Response) => {\n let transport: SSEServerTransport;\n try {\n transport = new SSEServerTransport(\"/messages\", res);\n } catch (err) {\n logger?.error(\"failed to create SSE transport\", {\n error: err instanceof Error ? err.message : String(err),\n });\n if (!res.headersSent) res.status(500).send(\"Failed to establish SSE stream\");\n return;\n }\n const sessionId = transport.sessionId;\n transports.set(sessionId, transport);\n transport.onclose = () => {\n transports.delete(sessionId);\n logger?.info(\"sse session closed\", { sessionId });\n };\n\n const server = createMcpServer({ deps, serverInfo: opts.serverInfo });\n try {\n await server.connect(transport);\n logger?.info(\"sse session opened\", { sessionId });\n } catch (err) {\n logger?.error(\"server.connect failed\", {\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n transports.delete(sessionId);\n if (!res.headersSent) res.status(500).send(\"MCP connect failed\");\n }\n });\n\n app.post(\"/messages\", async (req: Request, res: Response) => {\n const sessionId = req.query.sessionId as string | undefined;\n if (!sessionId) {\n res.status(400).json({ error: \"Missing sessionId query parameter\" });\n return;\n }\n const transport = transports.get(sessionId);\n if (!transport) {\n res.status(404).json({ error: \"No active session for sessionId\" });\n return;\n }\n try {\n await transport.handlePostMessage(req, res, req.body);\n } catch (err) {\n logger?.error(\"handlePostMessage failed\", {\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n if (!res.headersSent) res.status(500).json({ error: \"Failed to handle message\" });\n }\n });\n\n const httpServer = await new Promise<HttpServer>((resolve, reject) => {\n const srv = app.listen(config.port, config.host, () => resolve(srv)).on(\"error\", reject);\n });\n\n const address = httpServer.address();\n if (address === null || typeof address === \"string\") {\n throw new Error(\"HTTP server bound to unexpected address\");\n }\n logger?.info(\"codegraph mcp server listening\", {\n host: address.address,\n port: address.port,\n tools: 10,\n });\n\n const started: StartedSseServer = {\n httpServer,\n address: { host: address.address, port: address.port },\n async close() {\n for (const [id, t] of transports) {\n try {\n await t.close();\n } catch {\n // best-effort\n }\n transports.delete(id);\n }\n await new Promise<void>((resolve, reject) => {\n httpServer.close((err) => (err ? reject(err) : resolve()));\n });\n await deps.cache.close?.();\n await deps.graph.close?.();\n },\n };\n return started;\n}\n\nfunction bearerAuthMiddleware(expectedToken: string, logger?: Logger) {\n return (req: Request, res: Response, next: NextFunction): void => {\n const header = req.header(\"authorization\") ?? req.header(\"Authorization\");\n if (!header || !header.toLowerCase().startsWith(\"bearer \")) {\n logger?.warn(\"auth missing\", { path: req.path });\n res.status(401).json({ error: \"Missing bearer token\" });\n return;\n }\n const presented = header.slice(\"bearer \".length).trim();\n if (!safeEqual(presented, expectedToken)) {\n logger?.warn(\"auth rejected\", { path: req.path });\n res.status(403).json({ error: \"Invalid bearer token\" });\n return;\n }\n next();\n };\n}\n\n/** Constant-time string compare to avoid timing leaks on the bearer token check. */\nfunction safeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) {\n diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return diff === 0;\n}\n\n/** Generate a fresh bearer token (32 hex chars). */\nexport function generateBearerToken(): string {\n return randomUUID().replace(/-/g, \"\");\n}\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult } from \"./util.js\";\n\nconst inputSchema = {\n symbol: z.string().min(1).describe(\"Symbol name. Use `path` for the file when ambiguous.\"),\n path: z.string().optional().describe(\"Optional file path to disambiguate the symbol.\"),\n depth: z.number().int().positive().max(6).default(3),\n limit: z.number().int().positive().max(500).default(200),\n};\n\nexport const affectedByTool: ToolDefinition<typeof inputSchema> = {\n name: \"affected_by\",\n config: {\n title: \"Affected By\",\n description:\n \"Reverse-BFS over CALLS and IMPORTS edges to surface every symbol or file whose behaviour could be affected by changing the given symbol. Depth-limited to keep query bounded.\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ symbol, path, depth, limit }, deps) =>\n cachedJsonResult(\"affected_by\", { symbol, path, depth, limit }, deps, async () => {\n const where = path\n ? \"WHERE target.name = $symbol AND target.path = $path\"\n : \"WHERE target.name = $symbol\";\n const rows = await deps.graph.query(\n `MATCH (target:Symbol) ${where}\n WITH target\n MATCH path = (affected:Symbol)-[:CALLS|IMPORTS*1..${depth}]->(target)\n WITH DISTINCT affected, min(length(path)) AS distance\n RETURN affected.id AS id, affected.name AS name, affected.kind AS kind,\n affected.path AS path, distance\n ORDER BY distance ASC, affected.path ASC LIMIT $limit`,\n { symbol, path: path ?? null, limit },\n );\n return { symbol, path: path ?? null, depth, count: rows.length, affected: rows };\n }),\n};\n","import type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { buildCacheKey, memoizeJson } from \"../cache.js\";\nimport type { ToolDeps } from \"../types.js\";\n\n/** Default tool-result TTL, per the Phase-2 plan. */\nexport const DEFAULT_TOOL_TTL_SECONDS = 30;\n\n/** Wrap a JSON-serializable payload into the MCP `CallToolResult` shape. */\nexport function jsonResult(payload: unknown, extra?: { isError?: boolean }): CallToolResult {\n const text = JSON.stringify(payload, null, 2);\n const base = {\n content: [{ type: \"text\" as const, text }],\n structuredContent: isStructuredContent(payload) ? payload : { result: payload },\n };\n return extra?.isError ? { ...base, isError: true } : base;\n}\n\nfunction isStructuredContent(value: unknown): value is { [key: string]: unknown } {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/** Memoized JSON result helper. */\nexport async function cachedJsonResult<TArgs, TResult>(\n toolName: string,\n args: TArgs,\n deps: ToolDeps,\n compute: () => Promise<TResult>,\n): Promise<CallToolResult> {\n const key = buildCacheKey(toolName, args);\n const ttl = deps.cacheTtlSeconds ?? DEFAULT_TOOL_TTL_SECONDS;\n const value = await memoizeJson(deps.cache, key, ttl, compute);\n return jsonResult(value);\n}\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult } from \"./util.js\";\n\nconst inputSchema = {\n symbol: z.string().min(1).describe(\"Symbol name to compute the blast radius for.\"),\n path: z.string().optional().describe(\"Optional file path to disambiguate the symbol.\"),\n depth: z.number().int().positive().max(6).default(4),\n sampleSize: z.number().int().positive().max(50).default(10),\n};\n\nexport const blastRadiusTool: ToolDefinition<typeof inputSchema> = {\n name: \"blast_radius\",\n config: {\n title: \"Blast Radius\",\n description:\n \"Reverse-BFS over CALLS, IMPORTS, and RENDERS edges to count the total number of upstream dependents, plus a small sample to give the agent context.\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ symbol, path, depth, sampleSize }, deps) =>\n cachedJsonResult(\"blast_radius\", { symbol, path, depth, sampleSize }, deps, async () => {\n const where = path\n ? \"WHERE target.name = $symbol AND target.path = $path\"\n : \"WHERE target.name = $symbol\";\n const [stats] = await deps.graph.query<{ total: number }>(\n `MATCH (target:Symbol) ${where}\n WITH target\n MATCH (dependent:Symbol)-[:CALLS|IMPORTS|RENDERS*1..${depth}]->(target)\n RETURN count(DISTINCT dependent) AS total`,\n { symbol, path: path ?? null },\n );\n const sample = await deps.graph.query(\n `MATCH (target:Symbol) ${where}\n WITH target\n MATCH p = (dependent:Symbol)-[:CALLS|IMPORTS|RENDERS*1..${depth}]->(target)\n WITH DISTINCT dependent, min(length(p)) AS distance\n RETURN dependent.id AS id, dependent.name AS name, dependent.kind AS kind,\n dependent.path AS path, distance\n ORDER BY distance ASC, dependent.path ASC LIMIT $sampleSize`,\n { symbol, path: path ?? null, sampleSize },\n );\n return {\n symbol,\n path: path ?? null,\n depth,\n totalDependents: stats?.total ?? 0,\n sample,\n };\n }),\n};\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult } from \"./util.js\";\n\nconst inputSchema = {\n name: z.string().min(1).describe(\"Exact symbol name to find callers of.\"),\n limit: z.number().int().positive().max(500).default(100),\n};\n\nexport const findCallersTool: ToolDefinition<typeof inputSchema> = {\n name: \"find_callers\",\n config: {\n title: \"Find Callers\",\n description:\n \"Return symbols that have a CALLS edge to the named target. Uses Phase-1 heuristic edges (identifier-position match).\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ name, limit }, deps) =>\n cachedJsonResult(\"find_callers\", { name, limit }, deps, async () => {\n const rows = await deps.graph.query(\n `MATCH (caller:Symbol)-[:CALLS]->(callee:Symbol)\n WHERE callee.name = $name\n RETURN caller.id AS id, caller.name AS name, caller.kind AS kind,\n caller.path AS path, caller.lineStart AS line\n ORDER BY caller.path, caller.lineStart LIMIT $limit`,\n { name, limit },\n );\n return { name, count: rows.length, callers: rows };\n }),\n};\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult } from \"./util.js\";\n\nconst inputSchema = {\n fragment: z.string().min(1).describe(\"Substring to match against file paths.\"),\n limit: z.number().int().positive().max(200).default(50),\n};\n\nexport const findFileTool: ToolDefinition<typeof inputSchema> = {\n name: \"find_file\",\n config: {\n title: \"Find File\",\n description: \"Locate files in the indexed repo by a substring of their path.\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ fragment, limit }, deps) =>\n cachedJsonResult(\"find_file\", { fragment, limit }, deps, async () => {\n const rows = await deps.graph.query(\n `MATCH (f:Symbol)\n WHERE f.kind = 'File' AND lower(f.path) CONTAINS lower($q)\n RETURN f.id AS id, f.path AS path, f.name AS name\n ORDER BY f.path LIMIT $limit`,\n { q: fragment, limit },\n );\n return { fragment, count: rows.length, matches: rows };\n }),\n};\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult } from \"./util.js\";\n\nconst inputSchema = {\n name: z.string().min(1).describe(\"Component name (PascalCase).\"),\n depth: z.number().int().positive().max(8).default(4),\n};\n\nexport const getComponentTreeTool: ToolDefinition<typeof inputSchema> = {\n name: \"get_component_tree\",\n config: {\n title: \"Get Component Tree\",\n description:\n \"Recursively walk RENDERS edges from the named component, returning the rendered descendants up to the requested depth.\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ name, depth }, deps) =>\n cachedJsonResult(\"get_component_tree\", { name, depth }, deps, async () => {\n // We accept Component OR Function as the root kind: the Phase-1 extractor only\n // tags arrow-function components as `Component`; declared functions returning JSX\n // still land as `Function`, and we don't want the tool to silently fail in that\n // case. The agent gets a `rootKind` field to disambiguate.\n const rootRows = await deps.graph.query<{\n rootId: string;\n rootName: string;\n rootPath: string;\n rootKind: string;\n }>(\n `MATCH (root:Symbol)\n WHERE root.name = $name AND (root.kind = 'Component' OR root.kind = 'Function' OR root.kind = 'Class')\n RETURN root.id AS rootId, root.name AS rootName, root.path AS rootPath, root.kind AS rootKind\n ORDER BY CASE root.kind WHEN 'Component' THEN 0 WHEN 'Function' THEN 1 ELSE 2 END\n LIMIT 1`,\n { name },\n );\n const root = rootRows[0];\n if (!root) {\n return {\n name,\n depth,\n found: false,\n root: null,\n children: [],\n };\n }\n const children = await deps.graph.query<{\n id: string;\n name: string;\n path: string;\n kind: string;\n distance: number;\n }>(\n `MATCH (root:Symbol {id: $rootId})\n OPTIONAL MATCH p = (root)-[:RENDERS*1..${depth}]->(child:Symbol)\n WITH child, min(length(p)) AS distance\n WHERE child IS NOT NULL\n RETURN child.id AS id, child.name AS name, child.kind AS kind,\n child.path AS path, distance\n ORDER BY distance ASC, child.name ASC`,\n { rootId: root.rootId },\n );\n return {\n name,\n depth,\n found: true,\n root: {\n id: root.rootId,\n name: root.rootName,\n path: root.rootPath,\n kind: root.rootKind,\n },\n children,\n };\n }),\n};\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult } from \"./util.js\";\n\nconst inputSchema = {\n path: z.string().min(1).describe(\"Repo-relative file path.\"),\n depth: z.number().int().positive().max(8).default(4),\n limit: z.number().int().positive().max(500).default(200),\n};\n\nexport const getDependenciesTool: ToolDefinition<typeof inputSchema> = {\n name: \"get_dependencies\",\n config: {\n title: \"Get Dependencies\",\n description:\n \"Forward-BFS over IMPORTS edges, returning every file transitively imported by the given path, with depth.\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ path, depth, limit }, deps) =>\n cachedJsonResult(\"get_dependencies\", { path, depth, limit }, deps, async () => {\n const rows = await deps.graph.query(\n `MATCH (root:Symbol)\n WHERE root.kind = 'File' AND root.path = $path\n OPTIONAL MATCH p = (root)-[:IMPORTS*1..${depth}]->(dep:Symbol)\n WHERE dep.kind = 'File'\n WITH DISTINCT dep, min(length(p)) AS distance\n WHERE dep IS NOT NULL\n RETURN dep.id AS id, dep.path AS path, distance\n ORDER BY distance ASC, dep.path ASC LIMIT $limit`,\n { path, limit },\n );\n return { path, depth, count: rows.length, dependencies: rows };\n }),\n};\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult } from \"./util.js\";\n\nconst inputSchema = {\n path: z.string().min(1).describe(\"Repo-relative file path.\"),\n symbolLimit: z.number().int().positive().max(500).default(100),\n};\n\nexport const getFileContextTool: ToolDefinition<typeof inputSchema> = {\n name: \"get_file_context\",\n config: {\n title: \"Get File Context\",\n description:\n \"Return the file's defined symbols, imported files, exported symbols, and the files that import it.\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ path, symbolLimit }, deps) =>\n cachedJsonResult(\"get_file_context\", { path, symbolLimit }, deps, async () => {\n const fileRows = await deps.graph.query(\n `MATCH (f:Symbol)\n WHERE f.kind = 'File' AND f.path = $path\n RETURN f.id AS id, f.path AS path, f.name AS name LIMIT 1`,\n { path },\n );\n if (fileRows.length === 0) {\n return { path, found: false };\n }\n const [defined, imports, exports, importers] = await Promise.all([\n deps.graph.query(\n `MATCH (f:Symbol)-[:DEFINES]->(s:Symbol)\n WHERE f.kind = 'File' AND f.path = $path\n RETURN s.id AS id, s.name AS name, s.kind AS kind, s.lineStart AS line, s.signature AS signature\n ORDER BY s.lineStart LIMIT $limit`,\n { path, limit: symbolLimit },\n ),\n deps.graph.query(\n // Kuzu drops the node variable `t` from scope after `RETURN DISTINCT`, so the\n // ORDER BY references the projection alias instead - using `t.path` here\n // raises a \"Variable t is not in scope\" binder exception.\n `MATCH (f:Symbol)-[:IMPORTS]->(t:Symbol)\n WHERE f.kind = 'File' AND t.kind = 'File' AND f.path = $path\n RETURN DISTINCT t.path AS path ORDER BY path`,\n { path },\n ),\n deps.graph.query(\n `MATCH (f:Symbol)-[:EXPORTS]->(s:Symbol)\n WHERE f.kind = 'File' AND f.path = $path\n RETURN s.id AS id, s.name AS name, s.kind AS kind, s.lineStart AS line\n ORDER BY s.name`,\n { path },\n ),\n deps.graph.query(\n `MATCH (other:Symbol)-[:IMPORTS]->(f:Symbol)\n WHERE other.kind = 'File' AND f.kind = 'File' AND f.path = $path\n RETURN DISTINCT other.path AS path ORDER BY path`,\n { path },\n ),\n ]);\n return {\n path,\n found: true,\n file: fileRows[0],\n definedSymbols: defined,\n importsFiles: imports,\n exportedSymbols: exports,\n importedBy: importers,\n };\n }),\n};\n","import { z } from \"zod\";\nimport { validateReadOnlyCypher } from \"../cypher-guard.js\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult, jsonResult } from \"./util.js\";\n\nconst inputSchema = {\n question: z.string().min(1).describe(\"Natural-language question about the codebase.\"),\n limit: z\n .number()\n .int()\n .positive()\n .max(200)\n .default(50)\n .describe(\"Row cap injected into the generated query as $limit.\"),\n};\n\nconst SYSTEM_PROMPT = `You translate natural-language questions about a code graph into a single Cypher query.\n\nSchema (Kuzu):\n- Single node table: \\`Symbol\\`. Distinguish kinds via the \\`kind\\` STRING column.\n Valid kinds: File, Function, Class, Interface, Component, Route, Variable.\n- Edge tables (each FROM Symbol TO Symbol): IMPORTS, CALLS, RENDERS, INHERITS, DEFINES, EXPORTS.\n- Useful Symbol columns: id, kind, repoId, name, path, lineStart, lineEnd, signature, leadingComment.\n\nExamples:\n // All files imported by app.ts:\n MATCH (a:Symbol)-[:IMPORTS]->(b:Symbol)\n WHERE a.kind = 'File' AND a.path = 'app.ts' AND b.kind = 'File'\n RETURN b.path LIMIT $limit\n\n // What calls useAuth?\n MATCH (caller:Symbol)-[:CALLS]->(callee:Symbol)\n WHERE callee.name = 'useAuth'\n RETURN caller.name, caller.path, caller.kind LIMIT $limit\n\nConstraints you MUST follow:\n- Produce exactly ONE statement.\n- It must be read-only: only MATCH / OPTIONAL MATCH / WITH / UNWIND / RETURN clauses.\n- Do not use CREATE, MERGE, DELETE, SET, REMOVE, DROP, FOREACH, CALL { ... }, or procedure CALLs.\n- Always include a LIMIT (use the $limit parameter that will be passed in).\n- Use \\`s.kind = 'File'\\` style filters - do NOT use multi-label syntax like \\`(s:File)\\`.\n- Return useful columns named clearly (id, name, kind, path, line, score, etc.).\n- Output ONLY the Cypher query. No prose, no markdown fences.`;\n\nexport const nlQueryTool: ToolDefinition<typeof inputSchema> = {\n name: \"nl_query\",\n config: {\n title: \"Natural-Language Cypher Query\",\n description:\n \"Translate a natural-language question into Cypher via the configured LLM, validate it against a read-only allowlist, then execute it on the graph.\",\n inputSchema,\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n handler: async ({ question, limit }, deps) => {\n const rawCypher = await deps.llm.generate({\n system: SYSTEM_PROMPT,\n messages: [{ role: \"user\", content: question }],\n temperature: 0,\n maxTokens: 400,\n });\n const cypher = stripCodeFence(rawCypher).trim();\n const guard = validateReadOnlyCypher(cypher);\n if (!guard.ok) {\n return jsonResult(\n {\n question,\n accepted: false,\n rejectedCypher: cypher,\n reason: guard.reason,\n },\n { isError: false },\n );\n }\n return cachedJsonResult(\n \"nl_query\",\n { question, limit, cypher: guard.normalized },\n deps,\n async () => {\n try {\n const rows = await deps.graph.query(guard.normalized ?? cypher, { limit });\n return {\n question,\n accepted: true,\n cypher: guard.normalized ?? cypher,\n rowCount: rows.length,\n rows,\n };\n } catch (err) {\n return {\n question,\n accepted: true,\n cypher: guard.normalized ?? cypher,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n },\n};\n\nfunction stripCodeFence(text: string): string {\n const fenced = text.match(/```(?:cypher)?\\n([\\s\\S]*?)```/i);\n if (fenced?.[1]) return fenced[1];\n return text;\n}\n","/**\n * Allowlist-style validator for Cypher generated by `nl_query`.\n *\n * The rules are intentionally strict and conservative:\n * - Exactly one statement (no semicolons except optionally one trailing).\n * - The first non-whitespace clause must be a read clause (MATCH, OPTIONAL MATCH, WITH,\n * UNWIND, RETURN).\n * - Mutating keywords (CREATE, MERGE, DELETE, DETACH DELETE, SET, REMOVE, DROP, FOREACH)\n * are rejected.\n * - `CALL { ... }` subqueries are rejected because they can hide writes.\n * - Procedure calls (`CALL db.foo()`) are rejected because they can mutate or be slow.\n *\n * String literals and comments are stripped before checking so that keywords inside quoted\n * strings (e.g. a node `name` literal containing the word `DELETE`) don't trip the guard.\n */\n\nexport interface CypherGuardResult {\n ok: boolean;\n /** When `ok === false`, a one-line reason suitable for surfacing back to the LLM. */\n reason?: string;\n /** The normalized statement that was validated (comments and strings stripped). */\n normalized?: string;\n}\n\nconst ALLOWED_LEADING_CLAUSES = [\"MATCH\", \"OPTIONAL MATCH\", \"WITH\", \"UNWIND\", \"RETURN\"] as const;\n\nconst FORBIDDEN_KEYWORDS = [\n \"CREATE\",\n \"MERGE\",\n \"DELETE\",\n \"DETACH DELETE\",\n \"SET\",\n \"REMOVE\",\n \"DROP\",\n \"FOREACH\",\n \"LOAD CSV\",\n] as const;\n\n/** Strip `//` and `/* ... *\\/` style comments. */\nfunction stripComments(src: string): string {\n return src.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/\\/\\/[^\\n]*/g, \" \");\n}\n\n/** Replace string literal contents with empty quotes so keywords inside strings are ignored. */\nfunction stripStringLiterals(src: string): string {\n return src\n .replace(/'(?:\\\\.|[^'\\\\])*'/g, \"''\")\n .replace(/\"(?:\\\\.|[^\"\\\\])*\"/g, '\"\"')\n .replace(/`(?:\\\\.|[^`\\\\])*`/g, \"``\");\n}\n\nfunction startsWithAllowedClause(upper: string): boolean {\n for (const clause of ALLOWED_LEADING_CLAUSES) {\n if (upper.startsWith(`${clause} `) || upper === clause) {\n return true;\n }\n }\n return false;\n}\n\nfunction findForbiddenKeyword(upper: string): string | null {\n for (const kw of FORBIDDEN_KEYWORDS) {\n const pattern = new RegExp(`\\\\b${kw.replace(/\\s+/g, \"\\\\s+\")}\\\\b`);\n if (pattern.test(upper)) {\n return kw;\n }\n }\n return null;\n}\n\nexport function validateReadOnlyCypher(input: string): CypherGuardResult {\n if (typeof input !== \"string\" || input.trim().length === 0) {\n return { ok: false, reason: \"Empty Cypher statement.\" };\n }\n\n const withoutComments = stripComments(input);\n const sanitized = stripStringLiterals(withoutComments).trim();\n\n const withoutTrailingSemicolon = sanitized.replace(/;\\s*$/, \"\");\n if (withoutTrailingSemicolon.includes(\";\")) {\n return {\n ok: false,\n reason: \"Multiple statements are not allowed (found `;`).\",\n normalized: sanitized,\n };\n }\n\n const normalized = withoutTrailingSemicolon.trim();\n const upper = normalized.toUpperCase().replace(/\\s+/g, \" \").trim();\n\n if (!startsWithAllowedClause(upper)) {\n return {\n ok: false,\n reason: `Statement must start with one of: ${ALLOWED_LEADING_CLAUSES.join(\", \")}.`,\n normalized,\n };\n }\n\n const forbidden = findForbiddenKeyword(upper);\n if (forbidden) {\n return {\n ok: false,\n reason: `Mutating keyword '${forbidden}' is not allowed in nl_query results.`,\n normalized,\n };\n }\n\n if (/\\bCALL\\s*\\{/.test(upper)) {\n return {\n ok: false,\n reason: \"CALL { ... } subqueries are not allowed (they may hide writes).\",\n normalized,\n };\n }\n\n if (/\\bCALL\\s+[A-Z0-9_.]+\\s*\\(/.test(upper)) {\n return {\n ok: false,\n reason: \"Procedure calls (CALL ns.proc(...)) are not allowed.\",\n normalized,\n };\n }\n\n return { ok: true, normalized };\n}\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult, jsonResult } from \"./util.js\";\n\nconst inputSchema = {\n description: z\n .string()\n .min(1)\n .describe(\"Natural-language description of the symbol you are looking for.\"),\n k: z.number().int().positive().max(50).default(10).describe(\"Number of nearest neighbours.\"),\n};\n\nexport const searchSemanticTool: ToolDefinition<typeof inputSchema> = {\n name: \"search_semantic\",\n config: {\n title: \"Semantic Symbol Search\",\n description:\n \"Embed the supplied description via the configured LLM router, then run a vector KNN over indexed symbol embeddings.\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ description, k }, deps) => {\n const [embedding] = await deps.llm.embed([description]);\n if (!embedding) {\n return jsonResult(\n { error: \"LLM router returned no embedding for the query.\" },\n { isError: true },\n );\n }\n const namespace = `${deps.llm.embeddingNamespace.provider}:${deps.llm.embeddingNamespace.model}:${deps.llm.embeddingNamespace.dimension}`;\n const dim = deps.llm.embeddingNamespace.dimension;\n return cachedJsonResult(\"search_semantic\", { description, k, namespace }, deps, async () => {\n // Brute-force cosine similarity over `Symbol.embedding`. v0.1.x deliberately skips\n // Kuzu's HNSW index because kuzudb/kuzu#5965 / #6040 make vector-indexed columns\n // unwritable. `array_cosine_similarity` is a core Kuzu function (no extension), and\n // for Phase 1 corpus sizes (tens of thousands of symbols) it returns in <10ms. The\n // namespace filter prevents cross-provider drift from poisoning results.\n //\n // The query vector arrives as a plain JS array; Kuzu won't auto-infer FLOAT[N], so\n // we CAST it inline to match the column's fixed-dimension type.\n const rows = await deps.graph.query(\n `MATCH (s:Symbol)\n WHERE s.embeddingNamespace = $ns\n RETURN s.id AS id, s.name AS name, s.kind AS kind, s.path AS path,\n s.lineStart AS line, s.signature AS signature,\n array_cosine_similarity(s.embedding, CAST($vec AS FLOAT[${dim}])) AS score\n ORDER BY score DESC\n LIMIT $k`,\n { vec: embedding, k, ns: namespace },\n );\n return { description, k, namespace, count: rows.length, matches: rows };\n });\n },\n};\n","import { z } from \"zod\";\nimport type { ToolDefinition } from \"./types.js\";\nimport { cachedJsonResult } from \"./util.js\";\n\nconst inputSchema = {\n query: z.string().min(1).describe(\"Substring to match against symbol names (case-insensitive).\"),\n kind: z\n .enum([\"File\", \"Function\", \"Class\", \"Interface\", \"Component\", \"Route\", \"Variable\"])\n .optional()\n .describe(\"Optional filter by node kind.\"),\n limit: z.number().int().positive().max(200).default(25),\n};\n\nexport const searchSymbolTool: ToolDefinition<typeof inputSchema> = {\n name: \"search_symbol\",\n config: {\n title: \"Search Symbol\",\n description:\n \"Find functions, classes, components, routes, or variables by case-insensitive substring match on the symbol name.\",\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n handler: async ({ query, kind, limit }, deps) =>\n cachedJsonResult(\"search_symbol\", { query, kind, limit }, deps, async () => {\n // Kuzu stores all symbols under a single `:Symbol` table with a `kind` discriminator\n // column, so the kind filter is a `WHERE s.kind = $kind` rather than a label.\n const cypher = kind\n ? `MATCH (s:Symbol)\n WHERE s.kind = $kind AND lower(s.name) CONTAINS lower($q)\n RETURN s.id AS id, s.name AS name, s.kind AS kind, s.path AS path,\n s.lineStart AS line, s.signature AS signature\n ORDER BY s.name LIMIT $limit`\n : `MATCH (s:Symbol)\n WHERE s.name IS NOT NULL AND lower(s.name) CONTAINS lower($q)\n RETURN s.id AS id, s.name AS name, s.kind AS kind, s.path AS path,\n s.lineStart AS line, s.signature AS signature\n ORDER BY s.name LIMIT $limit`;\n const rows = await deps.graph.query(cypher, { q: query, limit, kind: kind ?? null });\n return { query, kind: kind ?? null, count: rows.length, matches: rows };\n }),\n};\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolDeps } from \"../types.js\";\nimport { affectedByTool } from \"./affected-by.js\";\nimport { blastRadiusTool } from \"./blast-radius.js\";\nimport { findCallersTool } from \"./find-callers.js\";\nimport { findFileTool } from \"./find-file.js\";\nimport { getComponentTreeTool } from \"./get-component-tree.js\";\nimport { getDependenciesTool } from \"./get-dependencies.js\";\nimport { getFileContextTool } from \"./get-file-context.js\";\nimport { nlQueryTool } from \"./nl-query.js\";\nimport { searchSemanticTool } from \"./search-semantic.js\";\nimport { searchSymbolTool } from \"./search-symbol.js\";\nimport type { ToolDefinition, ToolInputShape } from \"./types.js\";\nimport { jsonResult } from \"./util.js\";\n\nexport const ALL_TOOLS: ReadonlyArray<ToolDefinition<ToolInputShape>> = [\n searchSymbolTool,\n findFileTool,\n searchSemanticTool,\n getFileContextTool,\n findCallersTool,\n getComponentTreeTool,\n affectedByTool,\n getDependenciesTool,\n blastRadiusTool,\n nlQueryTool,\n] as unknown as ReadonlyArray<ToolDefinition<ToolInputShape>>;\n\n/** Register every Phase-2 tool with the provided MCP server, wired to the given deps. */\nexport function registerAllTools(server: McpServer, deps: ToolDeps): void {\n for (const tool of ALL_TOOLS) {\n server.registerTool(tool.name, tool.config, async (args) => {\n try {\n return await tool.handler(args as never, deps);\n } catch (err) {\n deps.logger?.error(\"tool handler threw\", {\n tool: tool.name,\n error: err instanceof Error ? err.message : String(err),\n });\n return jsonResult(\n {\n tool: tool.name,\n error: err instanceof Error ? err.message : String(err),\n },\n { isError: true },\n );\n }\n });\n }\n}\n\nexport {\n affectedByTool,\n blastRadiusTool,\n findCallersTool,\n findFileTool,\n getComponentTreeTool,\n getDependenciesTool,\n getFileContextTool,\n nlQueryTool,\n searchSemanticTool,\n searchSymbolTool,\n};\nexport type { ToolDefinition, ToolInputShape } from \"./types.js\";\n","import type { Request, Response, Router } from \"express\";\nimport { EDGE_KINDS } from \"@codegraph/shared\";\nimport type { GraphClient } from \"./types.js\";\n\ntype GraphRow = Record<string, unknown>;\n\n/**\n * Register unauthenticated viewer API routes on the given Express router:\n *\n * GET /api/repos → { repos: string[] }\n * GET /api/graph?repoId= → { repoId, nodes: [...], edges: [...] }\n *\n * These routes are intentionally public (no bearer auth) because they are\n * served only on the loopback interface and consumed by the browser viewer\n * on the same machine. The MCP/messages routes remain auth-gated.\n */\nexport function registerViewerApiRoutes(router: Router, graph: GraphClient): void {\n router.get(\"/api/repos\", async (_req: Request, res: Response) => {\n try {\n const rows = await graph.query<GraphRow>(\n \"MATCH (n:Symbol) RETURN DISTINCT n.repoId AS repoId ORDER BY repoId\",\n );\n const repos = rows\n .map((r) => r.repoId)\n .filter((id): id is string => typeof id === \"string\" && id.length > 0);\n res.json({ repos });\n } catch (err) {\n res.status(500).json({ error: String(err) });\n }\n });\n\n router.get(\"/api/graph\", async (req: Request, res: Response) => {\n const repoId = req.query.repoId as string | undefined;\n if (!repoId) {\n res.status(400).json({ error: \"Missing repoId query parameter\" });\n return;\n }\n const limit = Math.min(Number(req.query.limit) || 600, 2000);\n\n try {\n const nodeRows = await graph.query<GraphRow>(\n `MATCH (n:Symbol)\n WHERE n.repoId = $repoId\n RETURN n.id AS id, n.kind AS kind, n.name AS name,\n n.path AS path, n.lineStart AS lineStart\n ORDER BY n.path ASC, n.lineStart ASC\n LIMIT $limit`,\n { repoId, limit },\n );\n\n // Restrict edges to the nodes we just fetched so the client never sees\n // edges to nodes it doesn't have. Build the set of returned node ids.\n const nodeIds = new Set(\n nodeRows\n .map((n) => n.id)\n .filter((v): v is string => typeof v === \"string\"),\n );\n\n // Fetch edges per kind (Kuzu stores each rel-table separately).\n // NB: `from`/`to` are reserved Cypher keywords; alias with non-reserved names.\n const edgeRows: Array<{ from: string; to: string; kind: string }> = [];\n const edgeLimit = limit * 3;\n for (const kind of EDGE_KINDS) {\n const rows = await graph.query<GraphRow>(\n `MATCH (a:Symbol)-[:${kind}]->(b:Symbol)\n WHERE a.repoId = $repoId AND b.repoId = $repoId\n RETURN a.id AS fromId, b.id AS toId\n LIMIT $edgeLimit`,\n { repoId, edgeLimit },\n );\n for (const r of rows) {\n const from = r.fromId;\n const to = r.toId;\n if (typeof from !== \"string\" || typeof to !== \"string\") continue;\n if (!nodeIds.has(from) || !nodeIds.has(to)) continue;\n edgeRows.push({ from, to, kind });\n }\n }\n\n res.json({ repoId, nodes: nodeRows, edges: edgeRows });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n // Surface as a structured error so the viewer can show something useful.\n res.status(500).json({ error: message });\n }\n });\n}\n","import type { Logger } from \"./types.js\";\n\n/** Minimal stderr JSON logger. Stdout is reserved for MCP-over-stdio future use. */\nexport function createConsoleLogger(level: \"info\" | \"warn\" | \"error\" = \"info\"): Logger {\n const levels = { info: 10, warn: 20, error: 30 };\n const min = levels[level];\n const emit = (lvl: \"info\" | \"warn\" | \"error\", msg: string, meta?: Record<string, unknown>) => {\n if (levels[lvl] < min) return;\n const line = JSON.stringify({ ts: new Date().toISOString(), level: lvl, msg, ...meta });\n process.stderr.write(`${line}\\n`);\n };\n return {\n info: (msg, meta) => emit(\"info\", msg, meta),\n warn: (msg, meta) => emit(\"warn\", msg, meta),\n error: (msg, meta) => emit(\"error\", msg, meta),\n };\n}\n","import { realpathSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { startMcpServer } from \"@codegraph/mcp-server\";\nimport kleur from \"kleur\";\nimport { loadConfig } from \"../config-store.js\";\nimport { makeSpinner, renderServeBanner } from \"../ui.js\";\n\n/**\n * Resolve the viewer static assets directory relative to the running CLI build.\n *\n * Tries, in order:\n * 1. `import.meta.url` — the path of the bundled chunk this code lives in\n * (e.g. `<pkg>/dist/chunk-XXX.js`). Walking up two levels then into\n * `viewer/` lands at the published `<pkg>/viewer/index.html`.\n * 2. `realpathSync(process.argv[1])` — resolves the `/usr/local/bin/codegraph`\n * symlink that `npm i -g` creates to the actual install path.\n *\n * Falls back to a non-existent path; `express.static` will then simply 404 and\n * the user can still hit `/mcp` normally.\n */\nfunction resolveViewerDir(): string {\n try {\n const here = fileURLToPath(import.meta.url);\n return join(dirname(here), \"..\", \"viewer\");\n } catch {\n // ignore — fall through to argv-based resolution\n }\n try {\n const bin = realpathSync(process.argv[1] ?? \"\");\n return join(dirname(bin), \"..\", \"viewer\");\n } catch {\n return join(dirname(process.argv[1] ?? \"\"), \"..\", \"viewer\");\n }\n}\n\nexport interface ServeCommandOptions {\n port?: number;\n host?: string;\n dbPath?: string;\n}\n\n/**\n * Provider -> env var lookup. Mirrors `doctor.ts`'s `providerEnvVar`; kept inline here\n * to avoid a CLI<->CLI internal import dependency.\n */\nfunction providerEnvVar(provider: string): string | null {\n if (provider === \"openai\") return \"OPENAI_API_KEY\";\n if (provider === \"anthropic\") return \"ANTHROPIC_API_KEY\";\n if (provider === \"google\") return \"GOOGLE_GENERATIVE_AI_API_KEY\";\n return null;\n}\n\n/**\n * Boots the local MCP server in-process. The bootstrap reads `~/.codegraph/config.json`\n * (generating a bearer token on first run), connects to the embedded Kuzu graph, and\n * starts the SSE listener.\n *\n * SIGINT / SIGTERM trigger a graceful shutdown. The shutdown closes active SSE\n * transports, releases the HTTP server, and disposes the graph + cache.\n */\nexport async function runServeCommand(opts: ServeCommandOptions = {}): Promise<void> {\n // Warn loudly if the LLM provider expects an env var that isn't present in *this*\n // process. The CLI inherits the shell's environment, but `serve` is often launched\n // detached (e.g. by an editor's MCP integration) and the bug is invisible until the\n // first `search_semantic` request fails with \"OPENAI_API_KEY missing\". We catch it\n // here so the user sees the problem at startup, not at first use.\n try {\n const config = await loadConfig();\n const missing: string[] = [];\n for (const provider of [\n config.llm.generation.provider,\n config.llm.embeddings.provider,\n ]) {\n const envVar = providerEnvVar(provider);\n if (envVar && !process.env[envVar] && !missing.includes(envVar)) {\n missing.push(envVar);\n }\n }\n if (missing.length > 0) {\n process.stderr.write(\n `${kleur.yellow(\n `! ${missing.join(\", \")} not set in serve's environment. ` +\n `Semantic search and nl_query will fail until the variable is exported before \\`codegraph serve\\`.`,\n )}\\n`,\n );\n }\n } catch {\n // No config yet (first run) - the server's own bootstrap will create one. Skip.\n }\n\n const spinner = makeSpinner(\"Booting MCP server\").start();\n let started: Awaited<ReturnType<typeof startMcpServer>>;\n try {\n started = await startMcpServer({\n ...(opts.port !== undefined ? { port: opts.port } : {}),\n ...(opts.host !== undefined ? { host: opts.host } : {}),\n ...(opts.dbPath !== undefined ? { dbPath: opts.dbPath } : {}),\n viewerDir: resolveViewerDir(),\n });\n spinner.stop();\n } catch (err) {\n spinner.fail(\"Server failed to start\");\n throw err;\n }\n\n const base = `http://${started.address.host}:${started.address.port}`;\n const url = `${base}/mcp`;\n const viewerUrl = `${base}/viewer`;\n const tokenHint =\n \"bearer token at ~/.codegraph/config.json (codegraph config show to view)\";\n process.stdout.write(`${renderServeBanner(url, tokenHint, viewerUrl)}\\n`);\n\n const shutdown = async (signal: NodeJS.Signals): Promise<never> => {\n process.stderr.write(`\\nshutting down (${signal})...\\n`);\n try {\n await started.close();\n } catch (err) {\n process.stderr.write(\n `shutdown failed: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n process.exit(0);\n };\n process.once(\"SIGINT\", shutdown);\n process.once(\"SIGTERM\", shutdown);\n\n // Hold the event loop open so the SSE listener keeps accepting connections. The signal\n // handlers above terminate the process when triggered.\n await new Promise<void>(() => {});\n}\n","import { exec } from \"node:child_process\";\nimport { MCP_PORT } from \"@codegraph/mcp-server\";\nimport kleur from \"kleur\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\n\n/**\n * Open `url` in the OS default browser.\n * Uses `open` (macOS/BSD), `xdg-open` (Linux), or `start` (Windows).\n */\nfunction openBrowser(url: string): void {\n const cmd =\n process.platform === \"darwin\"\n ? `open \"${url}\"`\n : process.platform === \"win32\"\n ? `start \"\" \"${url}\"`\n : `xdg-open \"${url}\"`;\n exec(cmd, (err) => {\n if (err) {\n process.stderr.write(\n `${kleur.yellow(\"!\")} Could not open browser automatically. Open manually:\\n ${kleur.cyan(url)}\\n`,\n );\n }\n });\n}\n\n/**\n * Probe whether the MCP server is already listening by hitting /healthz.\n * Returns true when the server responds 200, false on any error/non-200.\n */\nasync function isServerUp(host: string, port: number): Promise<boolean> {\n try {\n const res = await fetch(`http://${host}:${port}/healthz`, {\n signal: AbortSignal.timeout(1500),\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n\nexport interface ViewCommandOptions {\n port?: number;\n host?: string;\n}\n\n/**\n * Open the CodeGraph graph viewer in the default browser.\n *\n * Checks whether `codegraph serve` is running first. If the server is not up,\n * prints a helpful message and exits. If it is up, opens\n * `http://<host>:<port>/viewer` in the default browser.\n */\nexport async function runViewCommand(opts: ViewCommandOptions = {}): Promise<void> {\n const host = opts.host ?? DEFAULT_HOST;\n const port = opts.port ?? MCP_PORT;\n const viewerUrl = `http://${host}:${port}/viewer`;\n\n process.stdout.write(kleur.dim(`Checking server at http://${host}:${port}/healthz …\\n`));\n\n const up = await isServerUp(host, port);\n\n if (!up) {\n process.stdout.write(\n [\n \"\",\n `${kleur.red(\"✗\")} CodeGraph server is not running.`,\n \"\",\n ` Start it with: ${kleur.cyan(\"codegraph serve\")}`,\n ` Then re-run: ${kleur.cyan(\"codegraph view\")}`,\n \"\",\n ].join(\"\\n\"),\n );\n process.exit(1);\n }\n\n process.stdout.write(`${kleur.green(\"✓\")} Server is up. Opening ${kleur.cyan(viewerUrl)} …\\n`);\n openBrowser(viewerUrl);\n}\n"],"mappings":"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","names":["kleur","kleur","mkdir","kleur","kleur","path","mkdir","path","readFile","dirname","require","createHash","basename","input","input","input","basename","sha1","extractCalleeName","id","ident","createHash","path","input","targetId","_unused","rest","path","readFile","stat","join","createHash","ignore","readFile","path","toPosix","input","readFile","path","join","readFile","embedded","kleur","createHash","path","path","kleur","spinner","path","input","password","select","createHash","mkdir","readFile","writeFile","dirname","join","z","createHash","path","inputSchema","z","input","join","resolve","readFile","mkdir","dirname","writeFile","configPath","GraphDb","createLlmRouter","boxen","kleur","kleur","boxen","select","resolve","input","apiKeyEnvVarFor","password","path","dirname","join","fileURLToPath","kleur","fileURLToPath","join","dirname","providerEnvVar","kleur","kleur","DEFAULT_HOST"]}