gitnexus 1.6.6-rc.6 → 1.6.6-rc.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.
|
@@ -59,6 +59,22 @@ interface RepoHandle {
|
|
|
59
59
|
remoteUrl?: string;
|
|
60
60
|
stats?: RegistryEntry['stats'];
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve the git diff cwd for detect_changes, auto-detecting linked worktrees.
|
|
64
|
+
*
|
|
65
|
+
* When `launchCwd` is a linked worktree of the same canonical repository as
|
|
66
|
+
* `repoPath` (i.e. `getGitRoot(launchCwd)` differs from `repoPath` but both
|
|
67
|
+
* share the same `getCanonicalRepoRoot`), returns the worktree's git root so
|
|
68
|
+
* that `git diff` sees the correct working directory and index.
|
|
69
|
+
*
|
|
70
|
+
* Returns `repoPath` unchanged in all other cases (non-worktree, git
|
|
71
|
+
* unavailable, unrelated repo).
|
|
72
|
+
*
|
|
73
|
+
* Extracted as a module-level export so tests can pass any `launchCwd` instead
|
|
74
|
+
* of relying on `process.cwd()`, which is fixed to the server launch directory
|
|
75
|
+
* and cannot be changed mid-process.
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveWorktreeCwd(repoPath: string, launchCwd: string): string;
|
|
62
78
|
export declare class LocalBackend {
|
|
63
79
|
private repos;
|
|
64
80
|
private contextCache;
|
|
@@ -14,7 +14,8 @@ export { isWriteQuery };
|
|
|
14
14
|
// at MCP server startup — crashes on unsupported Node ABI versions (#89)
|
|
15
15
|
// git utilities available if needed
|
|
16
16
|
// import { isGitRepo, getCurrentCommit, getGitRoot } from '../../storage/git.js';
|
|
17
|
-
import { parseDiffHunks } from '../../storage/git.js';
|
|
17
|
+
import { parseDiffHunks, getCanonicalRepoRoot, getGitRoot, } from '../../storage/git.js';
|
|
18
|
+
import { realpathSync } from 'fs';
|
|
18
19
|
import { listRegisteredRepos, cleanupOldKuzuFiles, } from '../../storage/repo-manager.js';
|
|
19
20
|
import { GroupService } from '../../core/group/service.js';
|
|
20
21
|
import { resolveAtGroupMemberRepoPath } from '../../core/group/resolve-at-member.js';
|
|
@@ -160,6 +161,55 @@ function logQueryTiming(query, phases) {
|
|
|
160
161
|
const truncated = query.length > 80 ? `${query.slice(0, 80)}…` : query;
|
|
161
162
|
logger.debug({ query: truncated, totalMs, phases }, 'GitNexus query timing');
|
|
162
163
|
}
|
|
164
|
+
/** Resolve symlinks for path comparison; falls back to path.resolve on error.
|
|
165
|
+
* Uses `realpathSync.native` (not the pure-JS `realpathSync`) so that Windows
|
|
166
|
+
* 8.3 short names (e.g. RUNNER~1 → runneradmin) are expanded to long form,
|
|
167
|
+
* matching the output of `git rev-parse --show-toplevel`. */
|
|
168
|
+
function tryRealpath(p) {
|
|
169
|
+
try {
|
|
170
|
+
return realpathSync.native(p);
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return path.resolve(p);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Resolve the git diff cwd for detect_changes, auto-detecting linked worktrees.
|
|
178
|
+
*
|
|
179
|
+
* When `launchCwd` is a linked worktree of the same canonical repository as
|
|
180
|
+
* `repoPath` (i.e. `getGitRoot(launchCwd)` differs from `repoPath` but both
|
|
181
|
+
* share the same `getCanonicalRepoRoot`), returns the worktree's git root so
|
|
182
|
+
* that `git diff` sees the correct working directory and index.
|
|
183
|
+
*
|
|
184
|
+
* Returns `repoPath` unchanged in all other cases (non-worktree, git
|
|
185
|
+
* unavailable, unrelated repo).
|
|
186
|
+
*
|
|
187
|
+
* Extracted as a module-level export so tests can pass any `launchCwd` instead
|
|
188
|
+
* of relying on `process.cwd()`, which is fixed to the server launch directory
|
|
189
|
+
* and cannot be changed mid-process.
|
|
190
|
+
*/
|
|
191
|
+
export function resolveWorktreeCwd(repoPath, launchCwd) {
|
|
192
|
+
try {
|
|
193
|
+
const launchGitRoot = getGitRoot(launchCwd);
|
|
194
|
+
if (launchGitRoot) {
|
|
195
|
+
// Normalise via realpathSync before comparing so macOS /var → /private/var
|
|
196
|
+
// symlinks (and Windows 8.3 short names) don't create false mismatches.
|
|
197
|
+
const realLaunch = tryRealpath(launchGitRoot);
|
|
198
|
+
const realRepo = tryRealpath(repoPath);
|
|
199
|
+
if (realLaunch !== realRepo) {
|
|
200
|
+
const launchCanonical = getCanonicalRepoRoot(launchCwd);
|
|
201
|
+
const repoCanonical = getCanonicalRepoRoot(repoPath);
|
|
202
|
+
if (launchCanonical && repoCanonical && launchCanonical === repoCanonical) {
|
|
203
|
+
return launchGitRoot;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// Best-effort; fall through to repoPath.
|
|
210
|
+
}
|
|
211
|
+
return repoPath;
|
|
212
|
+
}
|
|
163
213
|
export class LocalBackend {
|
|
164
214
|
repos = new Map();
|
|
165
215
|
contextCache = new Map();
|
|
@@ -1770,11 +1820,50 @@ export class LocalBackend {
|
|
|
1770
1820
|
}
|
|
1771
1821
|
let diffOutput;
|
|
1772
1822
|
try {
|
|
1823
|
+
// Resolve the cwd for git diff.
|
|
1824
|
+
//
|
|
1825
|
+
// In a linked worktree (e.g. /repo/wt-feature/), the user's staged and
|
|
1826
|
+
// unstaged changes live in that worktree's separate working directory and
|
|
1827
|
+
// index. Running `git diff` from the canonical repo root sees a different
|
|
1828
|
+
// working tree and returns empty output.
|
|
1829
|
+
//
|
|
1830
|
+
// Resolution order (see resolveWorktreeCwd for details):
|
|
1831
|
+
// 1. params.worktree — explicit override, validated against the
|
|
1832
|
+
// registered repo's canonical root.
|
|
1833
|
+
// 2. Auto-detect — if the server's launch cwd (process.cwd()) is a
|
|
1834
|
+
// linked worktree of the same canonical repo, use its git root.
|
|
1835
|
+
// 3. repo.repoPath — fallback (original behaviour, handled inside
|
|
1836
|
+
// resolveWorktreeCwd when no worktree is detected).
|
|
1837
|
+
//
|
|
1838
|
+
// Start with the auto-detected value; override with the validated
|
|
1839
|
+
// explicit param when provided. This avoids a dead initial assignment.
|
|
1840
|
+
let diffCwd = resolveWorktreeCwd(repo.repoPath, process.cwd());
|
|
1841
|
+
if (params.worktree) {
|
|
1842
|
+
if (!path.isAbsolute(params.worktree)) {
|
|
1843
|
+
return {
|
|
1844
|
+
error: `worktree must be an absolute path, got: "${params.worktree}"`,
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1847
|
+
const providedResolved = path.resolve(params.worktree);
|
|
1848
|
+
const repoCanonical = getCanonicalRepoRoot(repo.repoPath);
|
|
1849
|
+
if (!repoCanonical) {
|
|
1850
|
+
return {
|
|
1851
|
+
error: `Could not determine canonical root for repo "${repo.repoPath}". Is git available?`,
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
const worktreeCanonical = getCanonicalRepoRoot(providedResolved);
|
|
1855
|
+
if (!worktreeCanonical || tryRealpath(worktreeCanonical) !== tryRealpath(repoCanonical)) {
|
|
1856
|
+
return {
|
|
1857
|
+
error: `worktree "${params.worktree}" is not a worktree of repo "${repo.repoPath}". Ensure the path is inside the same git repository.`,
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
diffCwd = providedResolved;
|
|
1861
|
+
}
|
|
1773
1862
|
// maxBuffer raised from Node's 1MB default to 256MB to avoid ENOBUFS on
|
|
1774
1863
|
// repos with large unstaged/untracked diffs (e.g. unignored build folders).
|
|
1775
1864
|
// See issue: spawnSync git ENOBUFS in detect_changes(scope="unstaged").
|
|
1776
1865
|
diffOutput = execFileSync('git', diffArgs, {
|
|
1777
|
-
cwd:
|
|
1866
|
+
cwd: diffCwd,
|
|
1778
1867
|
encoding: 'utf-8',
|
|
1779
1868
|
maxBuffer: 256 * 1024 * 1024,
|
|
1780
1869
|
});
|
package/dist/mcp/tools.js
CHANGED
|
@@ -218,6 +218,8 @@ Maps git diff hunks to indexed symbols, then traces which processes are impacted
|
|
|
218
218
|
WHEN TO USE: Before committing — to understand what your changes affect. Pre-commit review, PR preparation.
|
|
219
219
|
AFTER THIS: Review affected processes. Use context() on high-risk symbols. READ gitnexus://repo/{name}/process/{name} for full traces.
|
|
220
220
|
|
|
221
|
+
GIT WORKTREE SUPPORT: GitNexus automatically detects when the MCP server was launched from inside a linked git worktree and runs git diff against that worktree — no extra parameters needed in the common case. Pass "worktree" explicitly only when the server was started from a different directory than the worktree you are editing (e.g., the server runs from the canonical root but your changes are in a linked worktree at a different path).
|
|
222
|
+
|
|
221
223
|
Returns: changed symbols, affected processes, and a risk summary.`,
|
|
222
224
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
223
225
|
inputSchema: {
|
|
@@ -233,6 +235,10 @@ Returns: changed symbols, affected processes, and a risk summary.`,
|
|
|
233
235
|
type: 'string',
|
|
234
236
|
description: 'Branch/commit for "compare" scope (e.g., "main")',
|
|
235
237
|
},
|
|
238
|
+
worktree: {
|
|
239
|
+
type: 'string',
|
|
240
|
+
description: 'Absolute path to a linked git worktree. Pass this when your changes are in a worktree (the .git entry at that path is a file, not a directory). GitNexus will run git diff from that worktree so staged/unstaged changes are correctly detected.',
|
|
241
|
+
},
|
|
236
242
|
repo: {
|
|
237
243
|
type: 'string',
|
|
238
244
|
description: 'Repository name or path. Omit if only one repo is indexed.',
|
package/package.json
CHANGED