vexp-cli 2.0.19 → 2.0.21
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/agent-config.js +335 -170
- package/mcp/mcp-server.cjs +49 -45
- package/package.json +7 -6
package/dist/agent-config.js
CHANGED
|
@@ -16,7 +16,7 @@ import { VEXP_GUARD_HOOK } from "./hook-template.js";
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
const VEXP_MARKER_RE = /<!-- vexp(?:\s+v[\d.]+)? -->/;
|
|
18
18
|
const VEXP_MARKER_END = "<!-- /vexp -->";
|
|
19
|
-
// Matches LEGACY vexp entry keys ONLY
|
|
19
|
+
// Matches LEGACY vexp entry keys ONLY - "vexp-mcp", "vexp-core", "vexp-stdio",
|
|
20
20
|
// "vexp_old", etc. Explicitly excludes the canonical "vexp" key so that idempotency
|
|
21
21
|
// checks (command+args+env identical?) work: we only remove siblings, not the entry
|
|
22
22
|
// we're about to upsert.
|
|
@@ -73,10 +73,10 @@ function logRemoval(removed) {
|
|
|
73
73
|
if (removed.length === 0)
|
|
74
74
|
return;
|
|
75
75
|
for (const entry of removed) {
|
|
76
|
-
process.stdout.write(`
|
|
76
|
+
process.stdout.write(` - Removed legacy entry: ${entry}\n`);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
// All vexp MCP tools (all read-only
|
|
79
|
+
// All vexp MCP tools (all read-only - safe to pre-approve).
|
|
80
80
|
const VEXP_TOOLS = [
|
|
81
81
|
"run_pipeline",
|
|
82
82
|
"get_context_capsule",
|
|
@@ -92,7 +92,7 @@ const VEXP_TOOLS = [
|
|
|
92
92
|
"get_token_savings",
|
|
93
93
|
];
|
|
94
94
|
// ---------------------------------------------------------------------------
|
|
95
|
-
// Agent detectors
|
|
95
|
+
// Agent detectors - mirrors VS Code extension's AGENT_DETECTORS
|
|
96
96
|
// ---------------------------------------------------------------------------
|
|
97
97
|
const AGENT_DETECTORS = [
|
|
98
98
|
{
|
|
@@ -396,8 +396,104 @@ export function configureSelectedAgents(workspaceRoot, binaryPath, version, sele
|
|
|
396
396
|
return { agents: results, mcpConfigs };
|
|
397
397
|
}
|
|
398
398
|
// ---------------------------------------------------------------------------
|
|
399
|
-
// File helpers
|
|
399
|
+
// File helpers - ported from agent-auto-config.ts
|
|
400
400
|
// ---------------------------------------------------------------------------
|
|
401
|
+
/**
|
|
402
|
+
* Parse JSON that may use JSONC syntax - `//` and slash-star comments and
|
|
403
|
+
* trailing commas. VS Code mcp.json and Zed settings.json are JSONC, so a raw
|
|
404
|
+
* JSON.parse throws on perfectly valid user files. Strips comments and trailing
|
|
405
|
+
* commas (preserving string contents) before parsing.
|
|
406
|
+
*/
|
|
407
|
+
export function parseJsonc(text) {
|
|
408
|
+
let out = "";
|
|
409
|
+
let inString = false;
|
|
410
|
+
let inLineComment = false;
|
|
411
|
+
let inBlockComment = false;
|
|
412
|
+
for (let i = 0; i < text.length; i++) {
|
|
413
|
+
const c = text[i];
|
|
414
|
+
const next = text[i + 1];
|
|
415
|
+
if (inLineComment) {
|
|
416
|
+
if (c === "\n") {
|
|
417
|
+
inLineComment = false;
|
|
418
|
+
out += c;
|
|
419
|
+
}
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
if (inBlockComment) {
|
|
423
|
+
if (c === "*" && next === "/") {
|
|
424
|
+
inBlockComment = false;
|
|
425
|
+
i++;
|
|
426
|
+
}
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
if (inString) {
|
|
430
|
+
out += c;
|
|
431
|
+
if (c === "\\") {
|
|
432
|
+
out += next ?? "";
|
|
433
|
+
i++;
|
|
434
|
+
}
|
|
435
|
+
else if (c === '"')
|
|
436
|
+
inString = false;
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
if (c === '"') {
|
|
440
|
+
inString = true;
|
|
441
|
+
out += c;
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
if (c === "/" && next === "/") {
|
|
445
|
+
inLineComment = true;
|
|
446
|
+
i++;
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
if (c === "/" && next === "*") {
|
|
450
|
+
inBlockComment = true;
|
|
451
|
+
i++;
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
out += c;
|
|
455
|
+
}
|
|
456
|
+
out = out.replace(/,(\s*[}\]])/g, "$1");
|
|
457
|
+
return JSON.parse(out);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Read a JSON/JSONC config file without ever risking user data. When the file
|
|
461
|
+
* exists but cannot be parsed (even as JSONC), returns ok:false so callers skip
|
|
462
|
+
* the write instead of silently clobbering the user's config.
|
|
463
|
+
*/
|
|
464
|
+
export function readJsonConfigSafe(filePath) {
|
|
465
|
+
if (!fs.existsSync(filePath))
|
|
466
|
+
return { data: {}, ok: true, existed: false };
|
|
467
|
+
let raw;
|
|
468
|
+
try {
|
|
469
|
+
raw = fs.readFileSync(filePath, "utf-8");
|
|
470
|
+
}
|
|
471
|
+
catch {
|
|
472
|
+
return { data: {}, ok: false, existed: true };
|
|
473
|
+
}
|
|
474
|
+
if (raw.trim() === "")
|
|
475
|
+
return { data: {}, ok: true, existed: true };
|
|
476
|
+
try {
|
|
477
|
+
const parsed = parseJsonc(raw);
|
|
478
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
479
|
+
return { data: parsed, ok: true, existed: true };
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
catch { /* fall through to ok:false */ }
|
|
483
|
+
return { data: {}, ok: false, existed: true };
|
|
484
|
+
}
|
|
485
|
+
/** Copy an existing config to <file>.vexp-bak before overwriting it. */
|
|
486
|
+
function backupConfig(filePath) {
|
|
487
|
+
try {
|
|
488
|
+
if (fs.existsSync(filePath))
|
|
489
|
+
fs.copyFileSync(filePath, `${filePath}.vexp-bak`);
|
|
490
|
+
}
|
|
491
|
+
catch { /* non-fatal */ }
|
|
492
|
+
}
|
|
493
|
+
/** Warn that we refused to touch an unparseable config file. */
|
|
494
|
+
function warnUnparseable(filePath) {
|
|
495
|
+
process.stderr.write(` [!] ${filePath} could not be parsed - leaving it untouched. Fix the file or add vexp manually, then re-run setup.\n`);
|
|
496
|
+
}
|
|
401
497
|
function appendOrCreate(filePath, content, version) {
|
|
402
498
|
if (!fs.existsSync(filePath)) {
|
|
403
499
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
@@ -422,7 +518,7 @@ function appendOrCreate(filePath, content, version) {
|
|
|
422
518
|
if (endIdx !== -1) {
|
|
423
519
|
const existingSection = existing.substring(startIdx, endIdx + VEXP_MARKER_END.length);
|
|
424
520
|
if (existingSection === content)
|
|
425
|
-
return "skipped"; // truly identical
|
|
521
|
+
return "skipped"; // truly identical -> no write
|
|
426
522
|
const before = existing.substring(0, startIdx);
|
|
427
523
|
const after = existing.substring(endIdx + VEXP_MARKER_END.length);
|
|
428
524
|
fs.writeFileSync(filePath, before + content + after, "utf-8");
|
|
@@ -433,16 +529,13 @@ function appendOrCreate(filePath, content, version) {
|
|
|
433
529
|
}
|
|
434
530
|
return "updated";
|
|
435
531
|
}
|
|
436
|
-
function mergeJsonConfig(filePath, mergePayload, version) {
|
|
437
|
-
|
|
438
|
-
if (
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
catch {
|
|
443
|
-
// Malformed JSON: overwrite
|
|
444
|
-
}
|
|
532
|
+
export function mergeJsonConfig(filePath, mergePayload, version) {
|
|
533
|
+
const read = readJsonConfigSafe(filePath);
|
|
534
|
+
if (!read.ok) {
|
|
535
|
+
warnUnparseable(filePath);
|
|
536
|
+
return "skipped";
|
|
445
537
|
}
|
|
538
|
+
const existing = read.data;
|
|
446
539
|
// Build the merged result first, then compare to avoid unnecessary writes.
|
|
447
540
|
const merged = { ...existing };
|
|
448
541
|
for (const [key, value] of Object.entries(mergePayload)) {
|
|
@@ -461,32 +554,31 @@ function mergeJsonConfig(filePath, mergePayload, version) {
|
|
|
461
554
|
}
|
|
462
555
|
delete merged.__vexp;
|
|
463
556
|
merged.__vexp_version = version;
|
|
464
|
-
// Compare serialized output
|
|
557
|
+
// Compare serialized output - skip if truly identical
|
|
465
558
|
const mergedStr = JSON.stringify(merged, null, 2);
|
|
466
559
|
const existingStr = JSON.stringify(existing, null, 2);
|
|
467
560
|
if (mergedStr === existingStr)
|
|
468
561
|
return "skipped";
|
|
469
562
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
563
|
+
if (read.existed)
|
|
564
|
+
backupConfig(filePath);
|
|
470
565
|
fs.writeFileSync(filePath, mergedStr, "utf-8");
|
|
471
566
|
return "merged";
|
|
472
567
|
}
|
|
473
568
|
// ---------------------------------------------------------------------------
|
|
474
|
-
// MCP config writers
|
|
569
|
+
// MCP config writers - adapted for Rust binary path
|
|
475
570
|
// ---------------------------------------------------------------------------
|
|
476
571
|
/**
|
|
477
572
|
* Write MCP config JSON for agents that use mcpServers format (Cursor, Windsurf).
|
|
478
573
|
* Returns true if a new entry was written.
|
|
479
574
|
*/
|
|
480
|
-
function writeMcpConfig(mcpConfigPath, binaryPath, alwaysAllow, mcpServerPath, workspaceRoot) {
|
|
481
|
-
|
|
482
|
-
if (
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
catch {
|
|
487
|
-
// Malformed JSON: overwrite
|
|
488
|
-
}
|
|
575
|
+
export function writeMcpConfig(mcpConfigPath, binaryPath, alwaysAllow, mcpServerPath, workspaceRoot) {
|
|
576
|
+
const read = readJsonConfigSafe(mcpConfigPath);
|
|
577
|
+
if (!read.ok) {
|
|
578
|
+
warnUnparseable(mcpConfigPath);
|
|
579
|
+
return false;
|
|
489
580
|
}
|
|
581
|
+
const existing = read.data;
|
|
490
582
|
const useNode = mcpServerPath && fs.existsSync(mcpServerPath);
|
|
491
583
|
const targetCmd = useNode ? "node" : binaryPath;
|
|
492
584
|
const targetArgs = useNode ? [mcpServerPath] : ["mcp"];
|
|
@@ -517,6 +609,8 @@ function writeMcpConfig(mcpConfigPath, binaryPath, alwaysAllow, mcpServerPath, w
|
|
|
517
609
|
};
|
|
518
610
|
existing.mcpServers = servers;
|
|
519
611
|
fs.mkdirSync(path.dirname(mcpConfigPath), { recursive: true });
|
|
612
|
+
if (read.existed)
|
|
613
|
+
backupConfig(mcpConfigPath);
|
|
520
614
|
fs.writeFileSync(mcpConfigPath, JSON.stringify(existing, null, 2), "utf-8");
|
|
521
615
|
return true;
|
|
522
616
|
}
|
|
@@ -561,49 +655,124 @@ function readMcpPort(workspaceRoot) {
|
|
|
561
655
|
}
|
|
562
656
|
return DEFAULT_PORT;
|
|
563
657
|
}
|
|
658
|
+
// Marker placed inside a vexp-generated [mcp_servers.vexp] section so we can
|
|
659
|
+
// tell OUR config apart from a config the user hand-wrote. Must stay in sync
|
|
660
|
+
// with packages/vexp-vscode/src/providers/agent-auto-config.ts.
|
|
661
|
+
const CODEX_MANAGED_MARKER = "# vexp-managed";
|
|
662
|
+
/** Quote a value as a TOML literal string (single quotes, no escaping) so
|
|
663
|
+
* Windows paths work verbatim. Falls back to a basic escaped string if the
|
|
664
|
+
* value contains a single quote. */
|
|
665
|
+
function tomlString(value) {
|
|
666
|
+
if (!value.includes("'"))
|
|
667
|
+
return `'${value}'`;
|
|
668
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
669
|
+
}
|
|
670
|
+
/** Extract the existing canonical [mcp_servers.vexp] block (incl. subsections). */
|
|
671
|
+
function extractCodexVexpSection(content) {
|
|
672
|
+
const m = content.match(CANONICAL_VEXP_TOML_SECTION_RE);
|
|
673
|
+
return m ? m.join("\n") : "";
|
|
674
|
+
}
|
|
675
|
+
/** True when the existing [mcp_servers.vexp] section was written by the user
|
|
676
|
+
* (not by vexp) and must NOT be overwritten. */
|
|
677
|
+
function isUserManagedCodexSection(section) {
|
|
678
|
+
if (!section)
|
|
679
|
+
return false;
|
|
680
|
+
if (section.includes(CODEX_MANAGED_MARKER))
|
|
681
|
+
return false; // ours
|
|
682
|
+
if (/^\s*command\s*=/m.test(section))
|
|
683
|
+
return true; // hand-written direct config
|
|
684
|
+
const localUrl = /^\s*url\s*=\s*"https?:\/\/127\.0\.0\.1[:/]/m.test(section);
|
|
685
|
+
const anyUrl = /^\s*url\s*=/m.test(section);
|
|
686
|
+
if (anyUrl && !localUrl)
|
|
687
|
+
return true; // points elsewhere
|
|
688
|
+
return false;
|
|
689
|
+
}
|
|
690
|
+
/** Build the canonical [mcp_servers.vexp] section for the chosen transport.
|
|
691
|
+
* Returns null for `direct` when no usable core binary is available. */
|
|
692
|
+
function buildCodexSection(opts) {
|
|
693
|
+
if (opts.transport === "direct") {
|
|
694
|
+
if (!opts.coreBinaryPath)
|
|
695
|
+
return null;
|
|
696
|
+
const lines = [
|
|
697
|
+
"",
|
|
698
|
+
"[mcp_servers.vexp]",
|
|
699
|
+
`${CODEX_MANAGED_MARKER}: direct transport (set VEXP_CODEX_TRANSPORT=http for the HTTP supervisor)`,
|
|
700
|
+
`command = ${tomlString(opts.coreBinaryPath)}`,
|
|
701
|
+
`args = ["mcp"]`,
|
|
702
|
+
];
|
|
703
|
+
if (opts.workspaceRoot)
|
|
704
|
+
lines.push(`cwd = ${tomlString(opts.workspaceRoot)}`);
|
|
705
|
+
lines.push("tool_timeout_sec = 120", "", "[mcp_servers.vexp.env]");
|
|
706
|
+
if (opts.workspaceRoot)
|
|
707
|
+
lines.push(`VEXP_WORKSPACE = ${tomlString(opts.workspaceRoot)}`);
|
|
708
|
+
if (opts.home)
|
|
709
|
+
lines.push(`VEXP_HOME = ${tomlString(opts.home)}`);
|
|
710
|
+
lines.push("");
|
|
711
|
+
return lines.join("\n");
|
|
712
|
+
}
|
|
713
|
+
const wsHash = opts.workspaceRoot ? workspaceHash(opts.workspaceRoot) : "";
|
|
714
|
+
const urlPath = wsHash ? `/ws/${wsHash}/mcp` : "/mcp";
|
|
715
|
+
const desiredUrl = `http://127.0.0.1:${opts.mcpPort}${urlPath}`;
|
|
716
|
+
return `\n[mcp_servers.vexp]\n${CODEX_MANAGED_MARKER}: http transport (set VEXP_CODEX_TRANSPORT=direct for stdio)\nurl = "${desiredUrl}"\ntool_timeout_sec = 120\n\n[mcp_servers.vexp.http_headers]\nAuthorization = "Bearer ${opts.token}"\n`;
|
|
717
|
+
}
|
|
564
718
|
/**
|
|
565
719
|
* Configure MCP in ~/.codex/config.toml (global).
|
|
566
720
|
* Codex only reads the global config, not project-level .codex/config.toml.
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
721
|
+
*
|
|
722
|
+
* Default transport is `direct` (stdio: `vexp-core mcp`), which works with AND
|
|
723
|
+
* without VS Code/daemon: `vexp-core mcp` auto-proxies to a running daemon when
|
|
724
|
+
* reachable and otherwise runs an embedded in-process index. Override with the
|
|
725
|
+
* VEXP_CODEX_TRANSPORT env var ("direct" | "http").
|
|
726
|
+
*
|
|
727
|
+
* Never clobbers a config the user wrote by hand.
|
|
570
728
|
*/
|
|
571
|
-
function configureCodexGlobal(binaryPath,
|
|
729
|
+
export function configureCodexGlobal(binaryPath, _mcpServerPath, workspaceRoot) {
|
|
572
730
|
const home = os.homedir();
|
|
573
731
|
if (!home)
|
|
574
732
|
return false;
|
|
575
733
|
const configPath = path.join(home, ".codex", "config.toml");
|
|
576
734
|
const mcpPort = readMcpPort(workspaceRoot);
|
|
577
735
|
const token = resolveCodexToken();
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
const desiredUrl = `http://127.0.0.1:${mcpPort}${urlPath}`;
|
|
584
|
-
const newSection = `\n[mcp_servers.vexp]\nurl = "${desiredUrl}"\ntool_timeout_sec = 120\n\n[mcp_servers.vexp.http_headers]\nAuthorization = "Bearer ${token}"\n`;
|
|
736
|
+
const requested = (process.env.VEXP_CODEX_TRANSPORT ?? "direct").toLowerCase();
|
|
737
|
+
let transport = requested === "http" ? "http" : "direct";
|
|
738
|
+
if (transport === "direct" && !(binaryPath && fs.existsSync(binaryPath))) {
|
|
739
|
+
transport = "http";
|
|
740
|
+
}
|
|
585
741
|
let content = "";
|
|
586
|
-
if (fs.existsSync(configPath))
|
|
742
|
+
if (fs.existsSync(configPath))
|
|
587
743
|
content = fs.readFileSync(configPath, "utf-8");
|
|
588
|
-
|
|
744
|
+
const original = content;
|
|
589
745
|
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
590
746
|
// Step 1: strip LEGACY vexp-* sections (not the canonical one).
|
|
591
747
|
const beforeLegacy = content.length;
|
|
592
748
|
content = content.replace(LEGACY_VEXP_TOML_SECTION_RE, "");
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
process.stdout.write(` · Removed legacy codex entries from ${configPath}\n`);
|
|
749
|
+
if (content.length !== beforeLegacy) {
|
|
750
|
+
process.stdout.write(` - Removed legacy codex entries from ${configPath}\n`);
|
|
596
751
|
}
|
|
597
|
-
// Step 2:
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
content
|
|
601
|
-
|
|
752
|
+
// Step 2: no-clobber — leave a hand-written [mcp_servers.vexp] alone.
|
|
753
|
+
const existingSection = extractCodexVexpSection(content);
|
|
754
|
+
if (isUserManagedCodexSection(existingSection)) {
|
|
755
|
+
if (content !== original) {
|
|
756
|
+
backupConfig(configPath);
|
|
757
|
+
fs.writeFileSync(configPath, content, "utf-8");
|
|
758
|
+
return true;
|
|
759
|
+
}
|
|
602
760
|
return false;
|
|
603
761
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
762
|
+
const newSection = buildCodexSection({ transport, coreBinaryPath: binaryPath, workspaceRoot, mcpPort, token, home });
|
|
763
|
+
if (!newSection) {
|
|
764
|
+
if (content !== original) {
|
|
765
|
+
backupConfig(configPath);
|
|
766
|
+
fs.writeFileSync(configPath, content, "utf-8");
|
|
767
|
+
return true;
|
|
768
|
+
}
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
// Step 3: rewrite the canonical section.
|
|
772
|
+
content = content.replace(CANONICAL_VEXP_TOML_SECTION_RE, "") + newSection;
|
|
773
|
+
if (content === original)
|
|
774
|
+
return false;
|
|
775
|
+
backupConfig(configPath);
|
|
607
776
|
fs.writeFileSync(configPath, content, "utf-8");
|
|
608
777
|
return true;
|
|
609
778
|
}
|
|
@@ -611,16 +780,13 @@ function configureCodexGlobal(binaryPath, mcpServerPath, workspaceRoot) {
|
|
|
611
780
|
* Write .vscode/mcp.json for GitHub Copilot.
|
|
612
781
|
* VS Code uses "servers" (not "mcpServers") + "type": "stdio".
|
|
613
782
|
*/
|
|
614
|
-
function writeVsCodeMcpConfig(p, binaryPath, mcpServerPath, workspaceRoot) {
|
|
615
|
-
|
|
616
|
-
if (
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
}
|
|
620
|
-
catch {
|
|
621
|
-
// Malformed JSON: overwrite
|
|
622
|
-
}
|
|
783
|
+
export function writeVsCodeMcpConfig(p, binaryPath, mcpServerPath, workspaceRoot) {
|
|
784
|
+
const read = readJsonConfigSafe(p);
|
|
785
|
+
if (!read.ok) {
|
|
786
|
+
warnUnparseable(p);
|
|
787
|
+
return false;
|
|
623
788
|
}
|
|
789
|
+
const existing = read.data;
|
|
624
790
|
const useNode = mcpServerPath && fs.existsSync(mcpServerPath);
|
|
625
791
|
const targetCmd = useNode ? "node" : binaryPath;
|
|
626
792
|
const targetArgs = useNode ? [mcpServerPath] : ["mcp"];
|
|
@@ -645,22 +811,21 @@ function writeVsCodeMcpConfig(p, binaryPath, mcpServerPath, workspaceRoot) {
|
|
|
645
811
|
};
|
|
646
812
|
existing.servers = servers;
|
|
647
813
|
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
814
|
+
if (read.existed)
|
|
815
|
+
backupConfig(p);
|
|
648
816
|
fs.writeFileSync(p, JSON.stringify(existing, null, 2), "utf-8");
|
|
649
817
|
return true;
|
|
650
818
|
}
|
|
651
819
|
/**
|
|
652
820
|
* Write context_servers in .zed/settings.json for Zed.
|
|
653
821
|
*/
|
|
654
|
-
function writeZedMcpConfig(p, binaryPath, mcpServerPath, workspaceRoot) {
|
|
655
|
-
|
|
656
|
-
if (
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
660
|
-
catch {
|
|
661
|
-
// Malformed JSON: overwrite
|
|
662
|
-
}
|
|
822
|
+
export function writeZedMcpConfig(p, binaryPath, mcpServerPath, workspaceRoot) {
|
|
823
|
+
const read = readJsonConfigSafe(p);
|
|
824
|
+
if (!read.ok) {
|
|
825
|
+
warnUnparseable(p);
|
|
826
|
+
return false;
|
|
663
827
|
}
|
|
828
|
+
const settings = read.data;
|
|
664
829
|
const useNode = mcpServerPath && fs.existsSync(mcpServerPath);
|
|
665
830
|
const targetCmd = useNode ? "node" : binaryPath;
|
|
666
831
|
const targetArgs = useNode ? [mcpServerPath] : ["mcp"];
|
|
@@ -694,6 +859,8 @@ function writeZedMcpConfig(p, binaryPath, mcpServerPath, workspaceRoot) {
|
|
|
694
859
|
}
|
|
695
860
|
settings.agent = { ...agent, tool_permissions: { ...tp, tools } };
|
|
696
861
|
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
862
|
+
if (read.existed)
|
|
863
|
+
backupConfig(p);
|
|
697
864
|
fs.writeFileSync(p, JSON.stringify(settings, null, 2), "utf-8");
|
|
698
865
|
return true;
|
|
699
866
|
}
|
|
@@ -701,20 +868,17 @@ function writeZedMcpConfig(p, binaryPath, mcpServerPath, workspaceRoot) {
|
|
|
701
868
|
* Configure vexp MCP in ~/.claude.json (user-scope) using the Rust binary.
|
|
702
869
|
* Returns true if config was written/updated.
|
|
703
870
|
*/
|
|
704
|
-
function configureClaudeCodeGlobal(binaryPath, mcpServerPath, workspaceRoot) {
|
|
871
|
+
export function configureClaudeCodeGlobal(binaryPath, mcpServerPath, workspaceRoot) {
|
|
705
872
|
const home = os.homedir();
|
|
706
873
|
if (!home)
|
|
707
874
|
return false;
|
|
708
875
|
const configPath = path.join(home, ".claude.json");
|
|
709
|
-
|
|
710
|
-
if (
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
}
|
|
714
|
-
catch {
|
|
715
|
-
// Malformed JSON: overwrite
|
|
716
|
-
}
|
|
876
|
+
const read = readJsonConfigSafe(configPath);
|
|
877
|
+
if (!read.ok) {
|
|
878
|
+
warnUnparseable(configPath);
|
|
879
|
+
return false;
|
|
717
880
|
}
|
|
881
|
+
const config = read.data;
|
|
718
882
|
const beforeServers = config.mcpServers;
|
|
719
883
|
const existing = beforeServers?.["vexp"];
|
|
720
884
|
const useNode = mcpServerPath && fs.existsSync(mcpServerPath);
|
|
@@ -736,18 +900,20 @@ function configureClaudeCodeGlobal(binaryPath, mcpServerPath, workspaceRoot) {
|
|
|
736
900
|
...(desiredEnv ? { env: desiredEnv } : {}),
|
|
737
901
|
};
|
|
738
902
|
config.mcpServers = servers;
|
|
903
|
+
if (read.existed)
|
|
904
|
+
backupConfig(configPath);
|
|
739
905
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
740
906
|
return true;
|
|
741
907
|
}
|
|
742
908
|
// ---------------------------------------------------------------------------
|
|
743
|
-
// Claude Code PreToolUse hook
|
|
909
|
+
// Claude Code PreToolUse hook - blocks Grep/Glob when daemon is available
|
|
744
910
|
// ---------------------------------------------------------------------------
|
|
745
911
|
/**
|
|
746
912
|
* Install the vexp-guard hook for Claude Code.
|
|
747
913
|
* Creates .claude/hooks/vexp-guard.sh and merges hook config into .claude/settings.json.
|
|
748
914
|
* Returns the action taken, or null if nothing was written.
|
|
749
915
|
*/
|
|
750
|
-
function installClaudeCodeHook(workspaceRoot) {
|
|
916
|
+
export function installClaudeCodeHook(workspaceRoot) {
|
|
751
917
|
const hookDir = path.join(workspaceRoot, ".claude", "hooks");
|
|
752
918
|
const hookPath = path.join(hookDir, "vexp-guard.sh");
|
|
753
919
|
const settingsPath = path.join(workspaceRoot, ".claude", "settings.json");
|
|
@@ -757,19 +923,16 @@ function installClaudeCodeHook(workspaceRoot) {
|
|
|
757
923
|
if (existed) {
|
|
758
924
|
const current = fs.readFileSync(hookPath, "utf-8");
|
|
759
925
|
if (current === VEXP_GUARD_HOOK)
|
|
760
|
-
return null; // identical
|
|
926
|
+
return null; // identical - skip
|
|
761
927
|
}
|
|
762
928
|
fs.writeFileSync(hookPath, VEXP_GUARD_HOOK, { mode: 0o755 });
|
|
763
929
|
// 2. Merge hook config into .claude/settings.json
|
|
764
|
-
|
|
765
|
-
if (
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
}
|
|
769
|
-
catch {
|
|
770
|
-
// Malformed JSON: overwrite
|
|
771
|
-
}
|
|
930
|
+
const read = readJsonConfigSafe(settingsPath);
|
|
931
|
+
if (!read.ok) {
|
|
932
|
+
warnUnparseable(settingsPath);
|
|
933
|
+
return existed ? "updated" : "created";
|
|
772
934
|
}
|
|
935
|
+
const settings = read.data;
|
|
773
936
|
const hooks = (settings.hooks ?? {});
|
|
774
937
|
const existingPreToolUse = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
|
|
775
938
|
// Aggressively remove ALL vexp-related hook entries (old format, stale matchers, malformed)
|
|
@@ -806,6 +969,8 @@ function installClaudeCodeHook(workspaceRoot) {
|
|
|
806
969
|
],
|
|
807
970
|
});
|
|
808
971
|
settings.hooks = { ...hooks, PreToolUse: filtered };
|
|
972
|
+
if (read.existed)
|
|
973
|
+
backupConfig(settingsPath);
|
|
809
974
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
810
975
|
return existed ? "updated" : "created";
|
|
811
976
|
}
|
|
@@ -834,13 +999,13 @@ function generateAgentConfig(template, vars) {
|
|
|
834
999
|
}
|
|
835
1000
|
}
|
|
836
1001
|
// ---------------------------------------------------------------------------
|
|
837
|
-
// Templates
|
|
1002
|
+
// Templates - copied verbatim from agent-auto-config.ts
|
|
838
1003
|
// ---------------------------------------------------------------------------
|
|
839
1004
|
function claudeCodeTemplate(vars) {
|
|
840
|
-
return `## vexp
|
|
1005
|
+
return `## vexp - Context-Aware AI Coding <!-- vexp v${vars.version} -->
|
|
841
1006
|
|
|
842
|
-
### MANDATORY: use vexp pipeline
|
|
843
|
-
For every task
|
|
1007
|
+
### MANDATORY: use vexp pipeline - do NOT grep or glob the codebase
|
|
1008
|
+
For every task - bug fixes, features, refactors, debugging:
|
|
844
1009
|
**call \`run_pipeline\` FIRST**. It executes context search + impact analysis +
|
|
845
1010
|
memory recall in a single call, returning compressed results.
|
|
846
1011
|
|
|
@@ -851,47 +1016,47 @@ inspect files (detail: minimal/standard/detailed, 70-90% token savings).
|
|
|
851
1016
|
Only use Read when you need exact raw content to edit a specific line.
|
|
852
1017
|
|
|
853
1018
|
### Primary Tool
|
|
854
|
-
- \`run_pipeline\`
|
|
1019
|
+
- \`run_pipeline\` - **USE THIS FOR EVERYTHING**. Single call that runs
|
|
855
1020
|
capsule + impact + memory server-side. Returns compressed results.
|
|
856
1021
|
Auto-detects intent (debug/modify/refactor/explore) from your task.
|
|
857
1022
|
Includes full file content for pivots.
|
|
858
1023
|
Examples:
|
|
859
|
-
- \`run_pipeline({ "task": "fix JWT validation bug" })\`
|
|
860
|
-
- \`run_pipeline({ "task": "refactor db layer", "preset": "refactor" })\`
|
|
861
|
-
- \`run_pipeline({ "task": "add auth", "observation": "using JWT" })\`
|
|
1024
|
+
- \`run_pipeline({ "task": "fix JWT validation bug" })\` - auto-detect
|
|
1025
|
+
- \`run_pipeline({ "task": "refactor db layer", "preset": "refactor" })\` - explicit
|
|
1026
|
+
- \`run_pipeline({ "task": "add auth", "observation": "using JWT" })\` - save insight in same call
|
|
862
1027
|
|
|
863
1028
|
### Other MCP tools (use only when run_pipeline is insufficient)
|
|
864
|
-
- \`get_skeleton\`
|
|
865
|
-
- \`index_status\`
|
|
866
|
-
- \`expand_vexp_ref\`
|
|
1029
|
+
- \`get_skeleton\` - **preferred over Read** for inspecting files (minimal/standard/detailed detail levels, 70-90% token savings)
|
|
1030
|
+
- \`index_status\` - indexing status and health check
|
|
1031
|
+
- \`expand_vexp_ref\` - expand V-REF hash placeholders in v2 compact output
|
|
867
1032
|
|
|
868
1033
|
### Workflow
|
|
869
|
-
1. \`run_pipeline("your task")\`
|
|
870
|
-
2. Need more detail on a file? Use \`get_skeleton({ files: [...], detail: "detailed" })\`
|
|
1034
|
+
1. \`run_pipeline("your task")\` - ALWAYS FIRST. Returns pivots + impact + memories in 1 call
|
|
1035
|
+
2. Need more detail on a file? Use \`get_skeleton({ files: [...], detail: "detailed" })\` - avoid Read unless editing
|
|
871
1036
|
3. Make targeted changes based on the context returned
|
|
872
1037
|
4. \`run_pipeline\` again ONLY if you need more context during implementation
|
|
873
|
-
5. Do NOT chain multiple vexp calls
|
|
1038
|
+
5. Do NOT chain multiple vexp calls - one \`run_pipeline\` replaces capsule + impact + memory + observation
|
|
874
1039
|
|
|
875
1040
|
### Subagent / Explore / Plan mode
|
|
876
|
-
- Subagents CAN and MUST call \`run_pipeline\`
|
|
1041
|
+
- Subagents CAN and MUST call \`run_pipeline\` - always include the task description
|
|
877
1042
|
- The PreToolUse hook blocks Grep/Glob when vexp daemon is running
|
|
878
|
-
- Do NOT spawn Agent(Explore) to freely search
|
|
1043
|
+
- Do NOT spawn Agent(Explore) to freely search - call \`run_pipeline\` first,
|
|
879
1044
|
then pass the returned context into the agent prompt if needed
|
|
880
|
-
- Always: \`run_pipeline\`
|
|
1045
|
+
- Always: \`run_pipeline\` -> get context -> spawn agent with context
|
|
881
1046
|
|
|
882
|
-
### Smart Features (automatic
|
|
883
|
-
- **Intent Detection**: auto-detects from your task keywords. "fix bug"
|
|
1047
|
+
### Smart Features (automatic - no action needed)
|
|
1048
|
+
- **Intent Detection**: auto-detects from your task keywords. "fix bug" -> Debug, "refactor" -> blast-radius, "add" -> Modify
|
|
884
1049
|
- **Hybrid Search**: keyword + semantic + graph centrality ranking
|
|
885
1050
|
- **Session Memory**: auto-captures observations; memories auto-surfaced in results
|
|
886
1051
|
- **LSP Bridge**: VS Code captures type-resolved call edges
|
|
887
1052
|
- **Change Coupling**: co-changed files included as related context
|
|
888
1053
|
|
|
889
1054
|
### Advanced Parameters
|
|
890
|
-
- \`preset: "debug"\`
|
|
891
|
-
- \`preset: "refactor"\`
|
|
892
|
-
- \`max_tokens: 12000\`
|
|
893
|
-
- \`include_tests: true\`
|
|
894
|
-
- \`include_file_content: false\`
|
|
1055
|
+
- \`preset: "debug"\` - forces debug mode (capsule+tests+impact+memory)
|
|
1056
|
+
- \`preset: "refactor"\` - deep impact analysis (depth 5)
|
|
1057
|
+
- \`max_tokens: 12000\` - increase total budget for complex tasks
|
|
1058
|
+
- \`include_tests: true\` - include test files in results
|
|
1059
|
+
- \`include_file_content: false\` - omit full file content (lighter response)
|
|
895
1060
|
|
|
896
1061
|
### Fallback
|
|
897
1062
|
If \`run_pipeline\` returns \`status: "degraded"\` or 0 pivots with an INDEX EMPTY warning,
|
|
@@ -905,28 +1070,28 @@ Use \`index_status\` to discover available repo aliases.
|
|
|
905
1070
|
function cursorTemplate(vars) {
|
|
906
1071
|
return `## vexp rules for Cursor <!-- vexp v${vars.version} -->
|
|
907
1072
|
|
|
908
|
-
**MANDATORY: use \`run_pipeline\`
|
|
1073
|
+
**MANDATORY: use \`run_pipeline\` - do NOT grep, glob, or read files manually.**
|
|
909
1074
|
vexp returns pre-indexed, graph-ranked context in a single call.
|
|
910
1075
|
|
|
911
1076
|
### Workflow
|
|
912
|
-
1. \`run_pipeline\` with your task description
|
|
1077
|
+
1. \`run_pipeline\` with your task description - ALWAYS FIRST (replaces all other tools)
|
|
913
1078
|
2. Make targeted changes based on the context returned
|
|
914
1079
|
3. \`run_pipeline\` again only if you need more context
|
|
915
1080
|
|
|
916
1081
|
### Available MCP tools
|
|
917
|
-
- \`run_pipeline\`
|
|
1082
|
+
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
918
1083
|
Auto-detects intent. Includes file content. Example: \`run_pipeline({ "task": "fix auth bug" })\`
|
|
919
|
-
- \`get_skeleton\`
|
|
920
|
-
- \`index_status\`
|
|
921
|
-
- \`expand_vexp_ref\`
|
|
1084
|
+
- \`get_skeleton\` - compact file structure
|
|
1085
|
+
- \`index_status\` - indexing status
|
|
1086
|
+
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
922
1087
|
|
|
923
1088
|
### Agentic search
|
|
924
|
-
- Do NOT use built-in file search, grep, or codebase indexing
|
|
1089
|
+
- Do NOT use built-in file search, grep, or codebase indexing - always call \`run_pipeline\` first
|
|
925
1090
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
926
1091
|
rather than letting them search the codebase independently
|
|
927
1092
|
|
|
928
1093
|
### Tips
|
|
929
|
-
- Natural language queries work well
|
|
1094
|
+
- Natural language queries work well - vexp uses hybrid search (keyword + semantic + graph)
|
|
930
1095
|
- Add \`include_tests: true\` when debugging
|
|
931
1096
|
- Use \`preset: "refactor"\` for deep impact analysis
|
|
932
1097
|
|
|
@@ -938,29 +1103,29 @@ Use file search and read tools directly until the index is ready.
|
|
|
938
1103
|
\`run_pipeline\` auto-queries all indexed repos. Use \`repos: ["alias"]\` to scope. Run \`index_status\` to see aliases.
|
|
939
1104
|
|
|
940
1105
|
> **Tip:** To avoid confirmation prompts on every tool call, enable Yolo mode:
|
|
941
|
-
> Cursor Settings
|
|
1106
|
+
> Cursor Settings -> Features -> Agent -> Enable Yolo Mode.
|
|
942
1107
|
<!-- /vexp -->`;
|
|
943
1108
|
}
|
|
944
1109
|
function windsurfTemplate(vars) {
|
|
945
1110
|
return `## vexp for Windsurf <!-- vexp v${vars.version} -->
|
|
946
1111
|
|
|
947
|
-
**MANDATORY: use \`run_pipeline\`
|
|
1112
|
+
**MANDATORY: use \`run_pipeline\` - do NOT grep, glob, or read files manually.**
|
|
948
1113
|
vexp returns pre-indexed, graph-ranked context in a single call.
|
|
949
1114
|
|
|
950
1115
|
### Workflow
|
|
951
|
-
1. \`run_pipeline\` with your task description
|
|
1116
|
+
1. \`run_pipeline\` with your task description - ALWAYS FIRST (replaces all other tools)
|
|
952
1117
|
2. Make targeted changes based on the context returned
|
|
953
1118
|
3. \`run_pipeline\` again only if you need more context
|
|
954
1119
|
|
|
955
1120
|
### Available MCP tools
|
|
956
|
-
- \`run_pipeline\`
|
|
1121
|
+
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
957
1122
|
Auto-detects intent. Includes file content. Example: \`run_pipeline({ "task": "fix auth bug" })\`
|
|
958
|
-
- \`get_skeleton\`
|
|
959
|
-
- \`index_status\`
|
|
960
|
-
- \`expand_vexp_ref\`
|
|
1123
|
+
- \`get_skeleton\` - compact file structure
|
|
1124
|
+
- \`index_status\` - indexing status
|
|
1125
|
+
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
961
1126
|
|
|
962
1127
|
### Agentic search
|
|
963
|
-
- Do NOT use built-in file search, grep, or codebase indexing
|
|
1128
|
+
- Do NOT use built-in file search, grep, or codebase indexing - always call \`run_pipeline\` first
|
|
964
1129
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
965
1130
|
rather than letting them search the codebase independently
|
|
966
1131
|
|
|
@@ -993,23 +1158,23 @@ function continueTemplate(vars) {
|
|
|
993
1158
|
function augmentTemplate(vars) {
|
|
994
1159
|
return `## vexp for Augment <!-- vexp v${vars.version} -->
|
|
995
1160
|
|
|
996
|
-
**MANDATORY: use \`run_pipeline\`
|
|
1161
|
+
**MANDATORY: use \`run_pipeline\` - do NOT grep, glob, or read files manually.**
|
|
997
1162
|
vexp returns pre-indexed, graph-ranked context in a single call.
|
|
998
1163
|
|
|
999
1164
|
When working on this codebase:
|
|
1000
|
-
1. \`run_pipeline\` with task description
|
|
1165
|
+
1. \`run_pipeline\` with task description - ALWAYS FIRST
|
|
1001
1166
|
2. Make targeted changes based on the context returned
|
|
1002
1167
|
3. \`run_pipeline\` again only if you need more context
|
|
1003
1168
|
|
|
1004
1169
|
### Available MCP tools
|
|
1005
|
-
- \`run_pipeline\`
|
|
1170
|
+
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
1006
1171
|
Example: \`run_pipeline({ "task": "fix auth bug" })\`
|
|
1007
|
-
- \`get_skeleton\`
|
|
1008
|
-
- \`index_status\`
|
|
1009
|
-
- \`expand_vexp_ref\`
|
|
1172
|
+
- \`get_skeleton\` - token-efficient file structure
|
|
1173
|
+
- \`index_status\` - indexing status
|
|
1174
|
+
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
1010
1175
|
|
|
1011
1176
|
### Agentic search
|
|
1012
|
-
- Do NOT use built-in file search, grep, or codebase indexing
|
|
1177
|
+
- Do NOT use built-in file search, grep, or codebase indexing - always call \`run_pipeline\` first
|
|
1013
1178
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1014
1179
|
rather than letting them search the codebase independently
|
|
1015
1180
|
|
|
@@ -1023,23 +1188,23 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
1023
1188
|
function copilotTemplate(vars) {
|
|
1024
1189
|
return `## vexp context tools <!-- vexp v${vars.version} -->
|
|
1025
1190
|
|
|
1026
|
-
**MANDATORY: use \`run_pipeline\`
|
|
1191
|
+
**MANDATORY: use \`run_pipeline\` - do NOT grep, glob, or read files manually.**
|
|
1027
1192
|
vexp returns pre-indexed, graph-ranked context in a single call.
|
|
1028
1193
|
|
|
1029
1194
|
### Workflow
|
|
1030
|
-
1. \`run_pipeline\` with your task description
|
|
1195
|
+
1. \`run_pipeline\` with your task description - ALWAYS FIRST (replaces all other tools)
|
|
1031
1196
|
2. Make targeted changes based on the context returned
|
|
1032
1197
|
3. \`run_pipeline\` again only if you need more context
|
|
1033
1198
|
|
|
1034
1199
|
### Available MCP tools
|
|
1035
|
-
- \`run_pipeline\`
|
|
1200
|
+
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
1036
1201
|
Auto-detects intent. Includes file content. Example: \`run_pipeline({ "task": "fix auth bug" })\`
|
|
1037
|
-
- \`get_skeleton\`
|
|
1038
|
-
- \`index_status\`
|
|
1039
|
-
- \`expand_vexp_ref\`
|
|
1202
|
+
- \`get_skeleton\` - compact file structure
|
|
1203
|
+
- \`index_status\` - indexing status
|
|
1204
|
+
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
1040
1205
|
|
|
1041
1206
|
### Agentic search
|
|
1042
|
-
- Do NOT use built-in file search, grep, or codebase indexing
|
|
1207
|
+
- Do NOT use built-in file search, grep, or codebase indexing - always call \`run_pipeline\` first
|
|
1043
1208
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1044
1209
|
rather than letting them search the codebase independently
|
|
1045
1210
|
|
|
@@ -1053,23 +1218,23 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
1053
1218
|
function zedTemplate(vars) {
|
|
1054
1219
|
return `## vexp for Zed <!-- vexp v${vars.version} -->
|
|
1055
1220
|
|
|
1056
|
-
**MANDATORY: use \`run_pipeline\`
|
|
1221
|
+
**MANDATORY: use \`run_pipeline\` - do NOT grep, glob, or read files manually.**
|
|
1057
1222
|
vexp returns pre-indexed, graph-ranked context in a single call.
|
|
1058
1223
|
|
|
1059
1224
|
### Workflow
|
|
1060
|
-
1. \`run_pipeline\` with your task description
|
|
1225
|
+
1. \`run_pipeline\` with your task description - ALWAYS FIRST (replaces all other tools)
|
|
1061
1226
|
2. Make targeted changes based on the context returned
|
|
1062
1227
|
3. \`run_pipeline\` again only if you need more context
|
|
1063
1228
|
|
|
1064
1229
|
### Available MCP tools
|
|
1065
|
-
- \`run_pipeline\`
|
|
1230
|
+
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
1066
1231
|
Example: \`run_pipeline({ "task": "fix auth bug" })\`
|
|
1067
|
-
- \`get_skeleton\`
|
|
1068
|
-
- \`index_status\`
|
|
1069
|
-
- \`expand_vexp_ref\`
|
|
1232
|
+
- \`get_skeleton\` - compact file structure
|
|
1233
|
+
- \`index_status\` - indexing status
|
|
1234
|
+
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
1070
1235
|
|
|
1071
1236
|
### Agentic search
|
|
1072
|
-
- Do NOT use built-in file search, grep, or codebase indexing
|
|
1237
|
+
- Do NOT use built-in file search, grep, or codebase indexing - always call \`run_pipeline\` first
|
|
1073
1238
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1074
1239
|
rather than letting them search the codebase independently
|
|
1075
1240
|
|
|
@@ -1083,23 +1248,23 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
1083
1248
|
function agentsMdTemplate(vars) {
|
|
1084
1249
|
return `## vexp <!-- vexp v${vars.version} -->
|
|
1085
1250
|
|
|
1086
|
-
**MANDATORY: use \`run_pipeline\`
|
|
1251
|
+
**MANDATORY: use \`run_pipeline\` - do NOT grep or glob the codebase.**
|
|
1087
1252
|
vexp returns pre-indexed, graph-ranked context in a single call.
|
|
1088
1253
|
|
|
1089
1254
|
### Workflow
|
|
1090
|
-
1. \`run_pipeline\` with your task description
|
|
1255
|
+
1. \`run_pipeline\` with your task description - ALWAYS FIRST (replaces all other tools)
|
|
1091
1256
|
2. Make targeted changes based on the context returned
|
|
1092
1257
|
3. \`run_pipeline\` again only if you need more context
|
|
1093
1258
|
|
|
1094
1259
|
### Available MCP tools
|
|
1095
|
-
- \`run_pipeline\`
|
|
1260
|
+
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
1096
1261
|
Auto-detects intent. Includes file content. Example: \`run_pipeline({ "task": "fix auth bug" })\`
|
|
1097
|
-
- \`get_skeleton\`
|
|
1098
|
-
- \`index_status\`
|
|
1099
|
-
- \`expand_vexp_ref\`
|
|
1262
|
+
- \`get_skeleton\` - compact file structure
|
|
1263
|
+
- \`index_status\` - indexing status
|
|
1264
|
+
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
1100
1265
|
|
|
1101
1266
|
### Agentic search
|
|
1102
|
-
- Do NOT use built-in file search, grep, or codebase indexing
|
|
1267
|
+
- Do NOT use built-in file search, grep, or codebase indexing - always call \`run_pipeline\` first
|
|
1103
1268
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1104
1269
|
rather than letting them search the codebase independently
|
|
1105
1270
|
|
|
@@ -1113,23 +1278,23 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
1113
1278
|
function kiroTemplate(vars) {
|
|
1114
1279
|
return `# vexp steering <!-- vexp v${vars.version} -->
|
|
1115
1280
|
|
|
1116
|
-
**MANDATORY: use \`run_pipeline\`
|
|
1281
|
+
**MANDATORY: use \`run_pipeline\` - do NOT grep, glob, or read files manually.**
|
|
1117
1282
|
vexp returns pre-indexed, graph-ranked context in a single call.
|
|
1118
1283
|
|
|
1119
1284
|
## Workflow
|
|
1120
|
-
1. \`run_pipeline\` with your task description
|
|
1285
|
+
1. \`run_pipeline\` with your task description - ALWAYS FIRST (replaces all other tools)
|
|
1121
1286
|
2. Make targeted changes based on the context returned
|
|
1122
1287
|
3. \`run_pipeline\` again only if you need more context
|
|
1123
1288
|
|
|
1124
1289
|
## Available vexp tools
|
|
1125
|
-
- \`run_pipeline\`
|
|
1290
|
+
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
1126
1291
|
Example: \`run_pipeline({ "task": "fix auth bug" })\`
|
|
1127
|
-
- \`get_skeleton\`
|
|
1128
|
-
- \`index_status\`
|
|
1129
|
-
- \`expand_vexp_ref\`
|
|
1292
|
+
- \`get_skeleton\` - compact file structure
|
|
1293
|
+
- \`index_status\` - indexing status
|
|
1294
|
+
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
1130
1295
|
|
|
1131
1296
|
## Agentic search
|
|
1132
|
-
- Do NOT use built-in file search, grep, or codebase indexing
|
|
1297
|
+
- Do NOT use built-in file search, grep, or codebase indexing - always call \`run_pipeline\` first
|
|
1133
1298
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1134
1299
|
rather than letting them search the codebase independently
|
|
1135
1300
|
|
|
@@ -1143,23 +1308,23 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
1143
1308
|
function genericTemplate(vars) {
|
|
1144
1309
|
return `## vexp <!-- vexp v${vars.version} -->
|
|
1145
1310
|
|
|
1146
|
-
**MANDATORY: use \`run_pipeline\`
|
|
1311
|
+
**MANDATORY: use \`run_pipeline\` - do NOT grep or glob the codebase.**
|
|
1147
1312
|
vexp returns pre-indexed, graph-ranked context in a single call.
|
|
1148
1313
|
|
|
1149
1314
|
### Workflow
|
|
1150
|
-
1. \`run_pipeline\` with your task description
|
|
1315
|
+
1. \`run_pipeline\` with your task description - ALWAYS FIRST (replaces all other tools)
|
|
1151
1316
|
2. Make targeted changes based on the context returned
|
|
1152
1317
|
3. \`run_pipeline\` again only if you need more context
|
|
1153
1318
|
|
|
1154
1319
|
### Available MCP tools
|
|
1155
|
-
- \`run_pipeline\`
|
|
1320
|
+
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
1156
1321
|
Example: \`run_pipeline({ "task": "fix auth bug" })\`
|
|
1157
|
-
- \`get_skeleton\`
|
|
1158
|
-
- \`index_status\`
|
|
1159
|
-
- \`expand_vexp_ref\`
|
|
1322
|
+
- \`get_skeleton\` - compact file structure
|
|
1323
|
+
- \`index_status\` - indexing status
|
|
1324
|
+
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
1160
1325
|
|
|
1161
1326
|
### Agentic search
|
|
1162
|
-
- Do NOT use built-in file search, grep, or codebase indexing
|
|
1327
|
+
- Do NOT use built-in file search, grep, or codebase indexing - always call \`run_pipeline\` first
|
|
1163
1328
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1164
1329
|
rather than letting them search the codebase independently
|
|
1165
1330
|
|