vexp-mcp 2.0.30 → 2.0.32
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.
- package/dist/daemon-client.js +44 -19
- package/package.json +1 -1
package/dist/daemon-client.js
CHANGED
|
@@ -420,8 +420,20 @@ function discoverWorkspaceRoot() {
|
|
|
420
420
|
}
|
|
421
421
|
return cwd;
|
|
422
422
|
}
|
|
423
|
+
/** Emit a stderr warning at most once per distinct message. The resolvers below
|
|
424
|
+
* run on every connect; without this guard a misconfig would spam the MCP log.
|
|
425
|
+
* stderr is safe — stdout carries the JSON-RPC protocol, stderr is for logs. */
|
|
426
|
+
const _warnedOnce = new Set();
|
|
427
|
+
function warnOnce(msg) {
|
|
428
|
+
if (_warnedOnce.has(msg))
|
|
429
|
+
return;
|
|
430
|
+
_warnedOnce.add(msg);
|
|
431
|
+
console.error(msg);
|
|
432
|
+
}
|
|
423
433
|
/**
|
|
424
|
-
*
|
|
434
|
+
* Decide the workspace root AND which signal chose it. Single source of truth
|
|
435
|
+
* for {@link resolveWorkspaceRoot} and {@link resolveTargeting} so they cannot
|
|
436
|
+
* drift.
|
|
425
437
|
*
|
|
426
438
|
* Precedence:
|
|
427
439
|
* 1. `explicit` — an HTTP per-workspace client's pinned root
|
|
@@ -432,12 +444,36 @@ function discoverWorkspaceRoot() {
|
|
|
432
444
|
* user-scope ~/.claude.json MCP entry is shared (and intentionally no longer
|
|
433
445
|
* pins VEXP_WORKSPACE — see agent-config.ts:configureClaudeCodeGlobal).
|
|
434
446
|
* 4. cwd walk-up ({@link discoverWorkspaceRoot})
|
|
447
|
+
*
|
|
448
|
+
* EXCEPTION: a *global/stale* `VEXP_WORKSPACE` must not silently override the
|
|
449
|
+
* per-session `CLAUDE_PROJECT_DIR`. When both are set and DISAGREE, the
|
|
450
|
+
* per-session signal wins (and we warn once) — otherwise every parallel agent
|
|
451
|
+
* session is pinned to one repo's daemon and cross-repo get_skeleton /
|
|
452
|
+
* run_pipeline return []/wrong-repo results. A deliberate single-project pin
|
|
453
|
+
* (VEXP_WORKSPACE set, no CLAUDE_PROJECT_DIR — e.g. Codex, the CLI, VS Code)
|
|
454
|
+
* is unaffected.
|
|
435
455
|
*/
|
|
456
|
+
function resolveWorkspaceWithSource(explicit) {
|
|
457
|
+
if (explicit)
|
|
458
|
+
return { root: explicit, source: "VEXP_WORKSPACE" };
|
|
459
|
+
const vw = process.env["VEXP_WORKSPACE"];
|
|
460
|
+
const cpd = process.env["CLAUDE_PROJECT_DIR"];
|
|
461
|
+
if (vw && cpd && path.resolve(vw).toLowerCase() !== path.resolve(cpd).toLowerCase()) {
|
|
462
|
+
warnOnce(`[vexp-mcp] VEXP_WORKSPACE=${vw} disagrees with this session's ` +
|
|
463
|
+
`CLAUDE_PROJECT_DIR=${cpd}; using CLAUDE_PROJECT_DIR for per-session ` +
|
|
464
|
+
`targeting. Unset the global VEXP_WORKSPACE env var to silence this.`);
|
|
465
|
+
return { root: cpd, source: "CLAUDE_PROJECT_DIR" };
|
|
466
|
+
}
|
|
467
|
+
if (vw)
|
|
468
|
+
return { root: vw, source: "VEXP_WORKSPACE" };
|
|
469
|
+
if (cpd)
|
|
470
|
+
return { root: cpd, source: "CLAUDE_PROJECT_DIR" };
|
|
471
|
+
return { root: discoverWorkspaceRoot(), source: "cwd-discovery" };
|
|
472
|
+
}
|
|
473
|
+
/** @see resolveWorkspaceWithSource for the precedence (and the VEXP_WORKSPACE /
|
|
474
|
+
* CLAUDE_PROJECT_DIR divergence rule). */
|
|
436
475
|
export function resolveWorkspaceRoot(explicit) {
|
|
437
|
-
return (explicit
|
|
438
|
-
process.env["VEXP_WORKSPACE"] ??
|
|
439
|
-
process.env["CLAUDE_PROJECT_DIR"] ??
|
|
440
|
-
discoverWorkspaceRoot());
|
|
476
|
+
return resolveWorkspaceWithSource(explicit).root;
|
|
441
477
|
}
|
|
442
478
|
/**
|
|
443
479
|
* Read `~/.vexp/daemons.json` and pick the best entry for the given workspace.
|
|
@@ -529,20 +565,9 @@ function pickFromDaemonRegistry(workspaceHint) {
|
|
|
529
565
|
export function resolveTargeting() {
|
|
530
566
|
// Which signal gives us the workspace root? (Reported even when VEXP_SOCKET
|
|
531
567
|
// overrides the socket, so the diagnostics still show the intended project.)
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
workspaceRoot = process.env["VEXP_WORKSPACE"];
|
|
536
|
-
source = "VEXP_WORKSPACE";
|
|
537
|
-
}
|
|
538
|
-
else if (process.env["CLAUDE_PROJECT_DIR"]) {
|
|
539
|
-
workspaceRoot = process.env["CLAUDE_PROJECT_DIR"];
|
|
540
|
-
source = "CLAUDE_PROJECT_DIR";
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
workspaceRoot = discoverWorkspaceRoot();
|
|
544
|
-
source = "cwd-discovery";
|
|
545
|
-
}
|
|
568
|
+
// Shared with resolveWorkspaceRoot — including the VEXP_WORKSPACE /
|
|
569
|
+
// CLAUDE_PROJECT_DIR divergence rule.
|
|
570
|
+
const { root: workspaceRoot, source } = resolveWorkspaceWithSource();
|
|
546
571
|
const explicit = process.env["VEXP_SOCKET"];
|
|
547
572
|
if (explicit) {
|
|
548
573
|
return { socket: explicit, source, socketOrigin: "explicit", workspaceRoot };
|