* Get CodeGraph instance for a project * * If projectPath is provided, opens that project's CodeGraph (cached). * Otherwise returns the default CodeGraph instance. * * Walks up parent directories to find the nearest .codegraph/ folder, * similar to how git finds .git/ directories.
(projectPath?: string)
| 998 | * similar to how git finds .git/ directories. |
| 999 | */ |
| 1000 | private getCodeGraph(projectPath?: string): CodeGraph { |
| 1001 | if (!projectPath) { |
| 1002 | if (!this.cg) { |
| 1003 | const searched = this.defaultProjectHint ?? process.cwd(); |
| 1004 | throw new NotIndexedError( |
| 1005 | 'No CodeGraph project is loaded for this session.\n' + |
| 1006 | `Searched for a .codegraph/ directory starting from: ${searched}\n` + |
| 1007 | 'Either the server root has no index of its own (e.g. a monorepo where only ' + |
| 1008 | "sub-projects are indexed), or the MCP client launched the server outside your " + |
| 1009 | 'project without reporting the workspace root. Either way, target the project ' + |
| 1010 | 'explicitly:\n' + |
| 1011 | ' • Pass projectPath to the tool call, e.g. projectPath: "/absolute/path/to/your/project" ' + |
| 1012 | '(any project that has a .codegraph/ — including a sub-project of a monorepo)\n' + |
| 1013 | ' • Or add --path to the server\'s MCP config args: ["serve", "--mcp", "--path", "/absolute/path/to/your/project"]\n' + |
| 1014 | 'If a project simply has no index, use your built-in tools (Read/Grep/Glob) for THAT ' + |
| 1015 | "project (the user can run 'codegraph init' there to enable it) — you can still query " + |
| 1016 | 'other indexed projects by projectPath in the same session.' |
| 1017 | ); |
| 1018 | } |
| 1019 | return this.freshen(this.cg); |
| 1020 | } |
| 1021 | |
| 1022 | // Reject sensitive system directories before opening. Only validate a |
| 1023 | // path that actually exists — a nested or not-yet-created sub-path of a |
| 1024 | // real project must still be allowed to resolve UP to its .codegraph/ |
| 1025 | // root below (issue #238), so we don't run the existence-checking |
| 1026 | // validator on paths that are meant to walk up. |
| 1027 | if (existsSync(projectPath)) { |
| 1028 | const pathError = validateProjectPath(projectPath); |
| 1029 | if (pathError) { |
| 1030 | throw new PathRefusalError(pathError); |
| 1031 | } |
| 1032 | } |
| 1033 | |
| 1034 | // Always RE-RESOLVE the nearest .codegraph/ from the input path. The walk |
| 1035 | // is cheap (a few existsSync up the tree) and is the only thing that |
| 1036 | // notices a path whose index root CHANGED since it was first seen — most |
| 1037 | // importantly a git worktree that gained its own .codegraph/ after the |
| 1038 | // (long-lived) server first resolved it up to the parent checkout. We used |
| 1039 | // to short-circuit on a `projectCache[projectPath]` entry before resolving, |
| 1040 | // which pinned that first resolution for the server's whole lifetime, so a |
| 1041 | // worktree kept being served the parent checkout's index until restart |
| 1042 | // (#926). The DB connection itself is still cached (by resolved root, |
| 1043 | // below), so re-resolving costs only the stat walk, never a reopen. |
| 1044 | const resolvedRoot = findNearestCodeGraphRoot(projectPath); |
| 1045 | |
| 1046 | if (!resolvedRoot) { |
| 1047 | throw new NotIndexedError( |
| 1048 | `The project at ${projectPath} isn't indexed with codegraph (no .codegraph/ directory found ` + |
| 1049 | 'walking up from it), so codegraph cannot query it. Use your built-in tools (Read/Grep/Glob) ' + |
| 1050 | "for that codebase instead, and don't call codegraph for it again this session. " + |
| 1051 | "Indexing is the user's decision — they can run 'codegraph init' in that project to enable it." |
| 1052 | ); |
| 1053 | } |
| 1054 | |
| 1055 | // If the path resolves to the default project, reuse the already-open |
| 1056 | // default instance rather than opening a SECOND connection to the same DB. |
| 1057 | // A duplicate connection serializes reads against the watcher's auto-sync |
no test coverage detected