@glasstrace/sdk 1.10.1 → 1.11.0
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/README.md +43 -5
- package/dist/{chunk-WQF7ZQOM.js → chunk-DQFGNX3H.js} +13 -8
- package/dist/{chunk-WQF7ZQOM.js.map → chunk-DQFGNX3H.js.map} +1 -1
- package/dist/{chunk-UMGZJYC4.js → chunk-FQ4SEG6Y.js} +8 -3
- package/dist/chunk-FQ4SEG6Y.js.map +1 -0
- package/dist/chunk-KOYZJN6G.js +651 -0
- package/dist/chunk-KOYZJN6G.js.map +1 -0
- package/dist/{chunk-ZBQQXVHD.js → chunk-YIEXKQYP.js} +2 -67
- package/dist/chunk-YIEXKQYP.js.map +1 -0
- package/dist/cli/init.cjs +460 -127
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +29 -16
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/mcp-add.cjs +346 -98
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +32 -14
- package/dist/cli/mcp-add.js.map +1 -1
- package/dist/cli/status.cjs +6 -1
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.js +7 -2
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/uninit.cjs +6 -1
- package/dist/cli/uninit.cjs.map +1 -1
- package/dist/cli/uninit.js +2 -2
- package/dist/cli/upgrade-instructions.cjs +390 -113
- package/dist/cli/upgrade-instructions.cjs.map +1 -1
- package/dist/cli/upgrade-instructions.js +70 -18
- package/dist/cli/upgrade-instructions.js.map +1 -1
- package/dist/index.cjs +11 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/node-entry.cjs +11 -6
- package/dist/node-entry.cjs.map +1 -1
- package/dist/node-entry.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-TJ46YOGJ.js +0 -355
- package/dist/chunk-TJ46YOGJ.js.map +0 -1
- package/dist/chunk-UMGZJYC4.js.map +0 -1
- package/dist/chunk-ZBQQXVHD.js.map +0 -1
package/dist/cli/mcp-add.cjs
CHANGED
|
@@ -14277,33 +14277,61 @@ var AGENT_RULES = [
|
|
|
14277
14277
|
},
|
|
14278
14278
|
{
|
|
14279
14279
|
name: "codex",
|
|
14280
|
+
// Codex 2026 default discovery is `AGENTS.override.md` → `AGENTS.md` →
|
|
14281
|
+
// opt-in `project_doc_fallback_filenames`; `codex.md` is NOT in the
|
|
14282
|
+
// default fallback list. Detection requires Codex-specific markers
|
|
14283
|
+
// (`codex.md` legacy, `.codex/` config dir) — `AGENTS.md` is NOT
|
|
14284
|
+
// included as a marker because the SDK now writes `AGENTS.md`
|
|
14285
|
+
// broadly via the multi-target dispatcher's companion writes; if
|
|
14286
|
+
// `AGENTS.md` were a Codex marker, every project with the SDK's
|
|
14287
|
+
// own companion AGENTS.md would re-classify as Codex on subsequent
|
|
14288
|
+
// detect runs and trigger unintended `.codex/config.toml` writes
|
|
14289
|
+
// (Codex P1 + Copilot P1 review of Wave 18 PR #274). The canonical
|
|
14290
|
+
// write destination remains AGENTS.md regardless of which marker
|
|
14291
|
+
// classified the project.
|
|
14280
14292
|
markers: ["codex.md", ".codex"],
|
|
14281
14293
|
mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".codex", "config.toml"),
|
|
14282
|
-
infoFilePath: (dir) => (0, import_node_path.join)(dir, "
|
|
14294
|
+
infoFilePath: (dir) => (0, import_node_path.join)(dir, "AGENTS.md"),
|
|
14283
14295
|
cliBinary: "codex",
|
|
14284
14296
|
registrationCommand: "npx glasstrace mcp add --agent codex"
|
|
14285
14297
|
},
|
|
14286
14298
|
{
|
|
14287
14299
|
name: "gemini",
|
|
14288
|
-
markers: [".gemini"],
|
|
14300
|
+
markers: [".gemini", "GEMINI.md"],
|
|
14289
14301
|
mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".gemini", "settings.json"),
|
|
14290
|
-
infoFilePath: () =>
|
|
14302
|
+
infoFilePath: (dir) => (0, import_node_path.join)(dir, "GEMINI.md"),
|
|
14291
14303
|
cliBinary: "gemini",
|
|
14292
14304
|
registrationCommand: "npx glasstrace mcp add --agent gemini"
|
|
14293
14305
|
},
|
|
14294
14306
|
{
|
|
14295
14307
|
name: "cursor",
|
|
14308
|
+
// `.cursor/rules/*.mdc` is the current canonical format per Cursor's
|
|
14309
|
+
// 2026 docs. `.cursorrules` (single file) is supported-but-deprecated
|
|
14310
|
+
// and stays as a transitional fallback that the multi-target write
|
|
14311
|
+
// helper writes unconditionally alongside the .mdc canonical.
|
|
14296
14312
|
markers: [".cursor", ".cursorrules"],
|
|
14297
14313
|
mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".cursor", "mcp.json"),
|
|
14298
|
-
infoFilePath: (dir) => (0, import_node_path.join)(dir, ".
|
|
14314
|
+
infoFilePath: (dir) => (0, import_node_path.join)(dir, ".cursor", "rules", "glasstrace.mdc"),
|
|
14299
14315
|
cliBinary: null,
|
|
14300
14316
|
registrationCommand: "npx glasstrace mcp add --agent cursor"
|
|
14301
14317
|
},
|
|
14302
14318
|
{
|
|
14303
14319
|
name: "windsurf",
|
|
14304
|
-
|
|
14320
|
+
// Windsurf's current canonical workspace-rules format is
|
|
14321
|
+
// `.windsurf/rules/*.md`. AGENTS.md is a parallel cross-tool
|
|
14322
|
+
// mechanism Windsurf also reads BUT is NOT included as a Windsurf
|
|
14323
|
+
// detection marker — the SDK writes `AGENTS.md` broadly via the
|
|
14324
|
+
// multi-target dispatcher's companion writes, so treating
|
|
14325
|
+
// `AGENTS.md` as a Windsurf marker would re-classify every
|
|
14326
|
+
// SDK-managed project as Windsurf and cause `glasstrace uninit`
|
|
14327
|
+
// to mutate the global `~/.codeium/windsurf/mcp_config.json` for
|
|
14328
|
+
// non-Windsurf projects (Codex P1 + Copilot P1 review of Wave 18
|
|
14329
|
+
// PR #274). The single-file `.windsurfrules` is the deprecated
|
|
14330
|
+
// legacy form — recognized as a marker so legacy projects classify
|
|
14331
|
+
// correctly, but the SDK no longer writes to it.
|
|
14332
|
+
markers: [".windsurf", ".windsurfrules"],
|
|
14305
14333
|
mcpConfigPath: () => (0, import_node_path.join)((0, import_node_os.homedir)(), ".codeium", "windsurf", "mcp_config.json"),
|
|
14306
|
-
infoFilePath: (dir) => (0, import_node_path.join)(dir, ".
|
|
14334
|
+
infoFilePath: (dir) => (0, import_node_path.join)(dir, ".windsurf", "rules", "glasstrace.md"),
|
|
14307
14335
|
cliBinary: null,
|
|
14308
14336
|
registrationCommand: "npx glasstrace mcp add --agent windsurf"
|
|
14309
14337
|
}
|
|
@@ -14390,10 +14418,7 @@ async function detectAgents(projectRoot) {
|
|
|
14390
14418
|
continue;
|
|
14391
14419
|
}
|
|
14392
14420
|
seenAgents.add(rule.name);
|
|
14393
|
-
|
|
14394
|
-
if (infoFilePath !== null && !await pathExists(infoFilePath)) {
|
|
14395
|
-
infoFilePath = null;
|
|
14396
|
-
}
|
|
14421
|
+
const infoFilePath = rule.infoFilePath(foundDir);
|
|
14397
14422
|
const cliAvailable = rule.cliBinary ? await isCliAvailable(rule.cliBinary) : false;
|
|
14398
14423
|
detected.push({
|
|
14399
14424
|
name: rule.name,
|
|
@@ -14406,7 +14431,7 @@ async function detectAgents(projectRoot) {
|
|
|
14406
14431
|
detected.push({
|
|
14407
14432
|
name: "generic",
|
|
14408
14433
|
mcpConfigPath: (0, import_node_path.join)(resolvedRoot, ".glasstrace", "mcp.json"),
|
|
14409
|
-
infoFilePath:
|
|
14434
|
+
infoFilePath: (0, import_node_path.join)(resolvedRoot, "AGENTS.md"),
|
|
14410
14435
|
cliAvailable: false,
|
|
14411
14436
|
registrationCommand: null
|
|
14412
14437
|
});
|
|
@@ -14436,7 +14461,13 @@ function buildAgentInstructionBody() {
|
|
|
14436
14461
|
"1. Start with `find_trace_candidates`. Pass whatever route or procedure name is natural \u2014 the server normalizes vocabulary and, on miss, returns close matches and a sample of routes actually present in the window.",
|
|
14437
14462
|
"2. Take the highest-confidence candidate's `suggestedFollowups` and pass them straight to `get_trace` or `get_root_cause`.",
|
|
14438
14463
|
"3. For side-effect bugs, read `sideEffectSummary` in the `get_trace` / `get_root_cause` response. The allowlisted fields (`templateKey`, `providerOperation`, `role`, `locale`, `timezone`, `status`, `phase`) are the ones that disambiguate payload bugs.",
|
|
14439
|
-
"4. If a tool returns empty, READ the response's
|
|
14464
|
+
"4. If a tool returns empty, READ the response's empty-result envelope before pivoting to source \u2014 each field disambiguates a different reason for the empty result:",
|
|
14465
|
+
" - `closeMatches` / `recentRoutesSample` \u2014 your filter vocabulary doesn't match server-side names; the server returns the closest known names + a sample of routes actually present.",
|
|
14466
|
+
' - `windowActivity` \u2014 load-bearing four-way distinguisher. `totalTracesInWindow === 0` AND `totalTracesInTenantEver > 0` means "your time window missed the activity"; `totalTracesInTenantEver === 0` means "this tenant has never produced traces" (SDK not registered, or never hit); `captureConfigBlocksRequest === true` means "the SDK\'s capture config dropped this route"; otherwise the empty result is a vocabulary miss \u2014 see `closeMatches`.',
|
|
14467
|
+
" - `humanReadable` \u2014 prose guidance written for the agent.",
|
|
14468
|
+
" - `recoveryActions` \u2014 concrete next-call shapes.",
|
|
14469
|
+
" - `diagnosticValue` / `recommendedNextStep` \u2014 whether to keep searching or stop.",
|
|
14470
|
+
" Empty results carry `notAbsenceProof: true` \u2014 they are never proof the bug did not occur.",
|
|
14440
14471
|
"",
|
|
14441
14472
|
"### Tools",
|
|
14442
14473
|
"- `find_trace_candidates` \u2014 discovery, vocabulary-tolerant filter",
|
|
@@ -14580,34 +14611,75 @@ function generateInfoSection(agent, endpoint, sdkVersion) {
|
|
|
14580
14611
|
}
|
|
14581
14612
|
const content = buildAgentInstructionBody();
|
|
14582
14613
|
switch (agent.name) {
|
|
14583
|
-
case "claude":
|
|
14584
|
-
|
|
14585
|
-
|
|
14586
|
-
|
|
14587
|
-
|
|
14588
|
-
}
|
|
14589
|
-
case "codex": {
|
|
14614
|
+
case "claude":
|
|
14615
|
+
case "codex":
|
|
14616
|
+
case "gemini":
|
|
14617
|
+
case "windsurf":
|
|
14618
|
+
case "generic": {
|
|
14590
14619
|
const m = htmlMarkers(sdkVersion);
|
|
14591
14620
|
return `${m.start}
|
|
14592
14621
|
${content}${m.end}
|
|
14593
14622
|
`;
|
|
14594
14623
|
}
|
|
14595
14624
|
case "cursor": {
|
|
14596
|
-
const m =
|
|
14625
|
+
const m = htmlMarkers(sdkVersion);
|
|
14597
14626
|
return `${m.start}
|
|
14598
14627
|
${content}${m.end}
|
|
14599
14628
|
`;
|
|
14600
14629
|
}
|
|
14601
|
-
case "gemini":
|
|
14602
|
-
case "windsurf":
|
|
14603
|
-
case "generic":
|
|
14604
|
-
return "";
|
|
14605
14630
|
default: {
|
|
14606
14631
|
const _exhaustive = agent.name;
|
|
14607
14632
|
throw new Error(`Unknown agent: ${_exhaustive}`);
|
|
14608
14633
|
}
|
|
14609
14634
|
}
|
|
14610
14635
|
}
|
|
14636
|
+
function generateInfoSectionForCursorrulesLegacy(endpoint, sdkVersion) {
|
|
14637
|
+
if (!endpoint || endpoint.trim() === "") {
|
|
14638
|
+
throw new Error("endpoint must not be empty");
|
|
14639
|
+
}
|
|
14640
|
+
if (!sdkVersion || sdkVersion.trim() === "") {
|
|
14641
|
+
throw new Error("sdkVersion must not be empty");
|
|
14642
|
+
}
|
|
14643
|
+
if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {
|
|
14644
|
+
throw new Error(
|
|
14645
|
+
"sdkVersion must match [A-Za-z0-9.+\\-]+ (semver-shaped, no whitespace, no angle brackets)"
|
|
14646
|
+
);
|
|
14647
|
+
}
|
|
14648
|
+
const content = buildAgentInstructionBody();
|
|
14649
|
+
const m = hashMarkers(sdkVersion);
|
|
14650
|
+
return `${m.start}
|
|
14651
|
+
${content}${m.end}
|
|
14652
|
+
`;
|
|
14653
|
+
}
|
|
14654
|
+
function generateInfoSectionForCursorMdc(endpoint, sdkVersion) {
|
|
14655
|
+
if (!endpoint || endpoint.trim() === "") {
|
|
14656
|
+
throw new Error("endpoint must not be empty");
|
|
14657
|
+
}
|
|
14658
|
+
if (!sdkVersion || sdkVersion.trim() === "") {
|
|
14659
|
+
throw new Error("sdkVersion must not be empty");
|
|
14660
|
+
}
|
|
14661
|
+
if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {
|
|
14662
|
+
throw new Error(
|
|
14663
|
+
"sdkVersion must match [A-Za-z0-9.+\\-]+ (semver-shaped, no whitespace, no angle brackets)"
|
|
14664
|
+
);
|
|
14665
|
+
}
|
|
14666
|
+
const content = buildAgentInstructionBody();
|
|
14667
|
+
const m = htmlMarkers(sdkVersion);
|
|
14668
|
+
return [
|
|
14669
|
+
"---",
|
|
14670
|
+
"description: Glasstrace MCP runtime debugging tools \u2014 runtime evidence the agent reads when source alone cannot resolve a bug",
|
|
14671
|
+
"alwaysApply: true",
|
|
14672
|
+
"---",
|
|
14673
|
+
"",
|
|
14674
|
+
`${m.start}
|
|
14675
|
+
${content}${m.end}
|
|
14676
|
+
`
|
|
14677
|
+
].join("\n");
|
|
14678
|
+
}
|
|
14679
|
+
|
|
14680
|
+
// src/agent-detection/inject-all-targets.ts
|
|
14681
|
+
var import_promises3 = require("node:fs/promises");
|
|
14682
|
+
var import_node_path3 = require("node:path");
|
|
14611
14683
|
|
|
14612
14684
|
// src/agent-detection/inject.ts
|
|
14613
14685
|
var import_promises2 = require("node:fs/promises");
|
|
@@ -14682,71 +14754,6 @@ function findMarkerBoundaries(lines) {
|
|
|
14682
14754
|
}
|
|
14683
14755
|
return null;
|
|
14684
14756
|
}
|
|
14685
|
-
async function injectInfoSection(agent, content, projectRoot) {
|
|
14686
|
-
if (agent.infoFilePath === null) {
|
|
14687
|
-
return;
|
|
14688
|
-
}
|
|
14689
|
-
if (content === "") {
|
|
14690
|
-
return;
|
|
14691
|
-
}
|
|
14692
|
-
const filePath = agent.infoFilePath;
|
|
14693
|
-
let existingContent = null;
|
|
14694
|
-
try {
|
|
14695
|
-
existingContent = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
14696
|
-
} catch (err) {
|
|
14697
|
-
const code = err.code;
|
|
14698
|
-
if (code !== "ENOENT") {
|
|
14699
|
-
if (isPermissionError(err)) {
|
|
14700
|
-
process.stderr.write(
|
|
14701
|
-
`Warning: cannot read info file ${filePath}: permission denied
|
|
14702
|
-
`
|
|
14703
|
-
);
|
|
14704
|
-
return;
|
|
14705
|
-
}
|
|
14706
|
-
throw err;
|
|
14707
|
-
}
|
|
14708
|
-
}
|
|
14709
|
-
if (existingContent === null) {
|
|
14710
|
-
try {
|
|
14711
|
-
await (0, import_promises2.mkdir)((0, import_node_path2.dirname)(filePath), { recursive: true });
|
|
14712
|
-
await (0, import_promises2.writeFile)(filePath, content, "utf-8");
|
|
14713
|
-
} catch (err) {
|
|
14714
|
-
if (isPermissionError(err)) {
|
|
14715
|
-
process.stderr.write(
|
|
14716
|
-
`Warning: cannot write info file ${filePath}: permission denied
|
|
14717
|
-
`
|
|
14718
|
-
);
|
|
14719
|
-
return;
|
|
14720
|
-
}
|
|
14721
|
-
throw err;
|
|
14722
|
-
}
|
|
14723
|
-
return;
|
|
14724
|
-
}
|
|
14725
|
-
const lines = existingContent.split("\n");
|
|
14726
|
-
const boundaries = findMarkerBoundaries(lines);
|
|
14727
|
-
let newContent;
|
|
14728
|
-
if (boundaries !== null) {
|
|
14729
|
-
const before = lines.slice(0, boundaries.startIdx);
|
|
14730
|
-
const after = lines.slice(boundaries.endIdx + 1);
|
|
14731
|
-
const contentWithoutTrailingNewline = content.endsWith("\n") ? content.slice(0, -1) : content;
|
|
14732
|
-
newContent = [...before, contentWithoutTrailingNewline, ...after].join("\n");
|
|
14733
|
-
} else {
|
|
14734
|
-
const separator = existingContent.endsWith("\n") ? "\n" : "\n\n";
|
|
14735
|
-
newContent = existingContent + separator + content;
|
|
14736
|
-
}
|
|
14737
|
-
try {
|
|
14738
|
-
await (0, import_promises2.writeFile)(filePath, newContent, "utf-8");
|
|
14739
|
-
} catch (err) {
|
|
14740
|
-
if (isPermissionError(err)) {
|
|
14741
|
-
process.stderr.write(
|
|
14742
|
-
`Warning: cannot write info file ${filePath}: permission denied
|
|
14743
|
-
`
|
|
14744
|
-
);
|
|
14745
|
-
return;
|
|
14746
|
-
}
|
|
14747
|
-
throw err;
|
|
14748
|
-
}
|
|
14749
|
-
}
|
|
14750
14757
|
async function updateGitignore(paths, projectRoot) {
|
|
14751
14758
|
const gitignorePath = (0, import_node_path2.join)(projectRoot, ".gitignore");
|
|
14752
14759
|
const relativePaths = paths.filter((p) => !(0, import_node_path2.isAbsolute)(p));
|
|
@@ -14794,6 +14801,228 @@ async function updateGitignore(paths, projectRoot) {
|
|
|
14794
14801
|
}
|
|
14795
14802
|
}
|
|
14796
14803
|
|
|
14804
|
+
// src/agent-detection/inject-all-targets.ts
|
|
14805
|
+
async function injectAllTargets(agents, endpoint, sdkVersion, projectRoot) {
|
|
14806
|
+
const writtenAgentsMd = /* @__PURE__ */ new Set();
|
|
14807
|
+
for (const agent of agents) {
|
|
14808
|
+
const targets = computeTargets(agent, projectRoot);
|
|
14809
|
+
for (const target of targets) {
|
|
14810
|
+
if (target.isAgentsMdCompanion) {
|
|
14811
|
+
if (writtenAgentsMd.has(target.path)) {
|
|
14812
|
+
continue;
|
|
14813
|
+
}
|
|
14814
|
+
writtenAgentsMd.add(target.path);
|
|
14815
|
+
}
|
|
14816
|
+
let createContent;
|
|
14817
|
+
let managedSectionOnly;
|
|
14818
|
+
if (target.kind === "cursor-mdc") {
|
|
14819
|
+
createContent = generateInfoSectionForCursorMdc(endpoint, sdkVersion);
|
|
14820
|
+
managedSectionOnly = generateInfoSection(agent, endpoint, sdkVersion);
|
|
14821
|
+
} else if (target.kind === "cursorrules-legacy") {
|
|
14822
|
+
createContent = generateInfoSectionForCursorrulesLegacy(
|
|
14823
|
+
endpoint,
|
|
14824
|
+
sdkVersion
|
|
14825
|
+
);
|
|
14826
|
+
managedSectionOnly = createContent;
|
|
14827
|
+
} else {
|
|
14828
|
+
createContent = generateInfoSection(agent, endpoint, sdkVersion);
|
|
14829
|
+
managedSectionOnly = createContent;
|
|
14830
|
+
}
|
|
14831
|
+
if (managedSectionOnly === "") continue;
|
|
14832
|
+
await writeManagedSectionToTarget(
|
|
14833
|
+
target.path,
|
|
14834
|
+
createContent,
|
|
14835
|
+
managedSectionOnly
|
|
14836
|
+
);
|
|
14837
|
+
}
|
|
14838
|
+
}
|
|
14839
|
+
}
|
|
14840
|
+
function foundDirFromAgent(agent) {
|
|
14841
|
+
if (agent.infoFilePath === null) return null;
|
|
14842
|
+
switch (agent.name) {
|
|
14843
|
+
case "claude":
|
|
14844
|
+
case "codex":
|
|
14845
|
+
case "gemini":
|
|
14846
|
+
case "generic":
|
|
14847
|
+
return (0, import_node_path3.dirname)(agent.infoFilePath);
|
|
14848
|
+
case "cursor":
|
|
14849
|
+
return (0, import_node_path3.dirname)((0, import_node_path3.dirname)((0, import_node_path3.dirname)(agent.infoFilePath)));
|
|
14850
|
+
case "windsurf":
|
|
14851
|
+
return (0, import_node_path3.dirname)((0, import_node_path3.dirname)((0, import_node_path3.dirname)(agent.infoFilePath)));
|
|
14852
|
+
}
|
|
14853
|
+
}
|
|
14854
|
+
function computeTargets(agent, projectRoot) {
|
|
14855
|
+
const targets = [];
|
|
14856
|
+
const foundDir = foundDirFromAgent(agent) ?? projectRoot;
|
|
14857
|
+
switch (agent.name) {
|
|
14858
|
+
case "claude": {
|
|
14859
|
+
if (agent.infoFilePath) {
|
|
14860
|
+
targets.push({
|
|
14861
|
+
path: agent.infoFilePath,
|
|
14862
|
+
kind: "primary",
|
|
14863
|
+
isAgentsMdCompanion: false
|
|
14864
|
+
});
|
|
14865
|
+
}
|
|
14866
|
+
targets.push({
|
|
14867
|
+
path: (0, import_node_path3.join)(foundDir, "AGENTS.md"),
|
|
14868
|
+
kind: "agents-md-companion",
|
|
14869
|
+
isAgentsMdCompanion: true
|
|
14870
|
+
});
|
|
14871
|
+
return targets;
|
|
14872
|
+
}
|
|
14873
|
+
case "codex": {
|
|
14874
|
+
if (agent.infoFilePath) {
|
|
14875
|
+
targets.push({
|
|
14876
|
+
path: agent.infoFilePath,
|
|
14877
|
+
kind: "primary",
|
|
14878
|
+
isAgentsMdCompanion: true
|
|
14879
|
+
});
|
|
14880
|
+
}
|
|
14881
|
+
return targets;
|
|
14882
|
+
}
|
|
14883
|
+
case "gemini": {
|
|
14884
|
+
if (agent.infoFilePath) {
|
|
14885
|
+
targets.push({
|
|
14886
|
+
path: agent.infoFilePath,
|
|
14887
|
+
kind: "primary",
|
|
14888
|
+
isAgentsMdCompanion: false
|
|
14889
|
+
});
|
|
14890
|
+
}
|
|
14891
|
+
targets.push({
|
|
14892
|
+
path: (0, import_node_path3.join)(foundDir, "AGENTS.md"),
|
|
14893
|
+
kind: "agents-md-companion",
|
|
14894
|
+
isAgentsMdCompanion: true
|
|
14895
|
+
});
|
|
14896
|
+
return targets;
|
|
14897
|
+
}
|
|
14898
|
+
case "cursor": {
|
|
14899
|
+
if (agent.infoFilePath) {
|
|
14900
|
+
targets.push({
|
|
14901
|
+
path: agent.infoFilePath,
|
|
14902
|
+
kind: "cursor-mdc",
|
|
14903
|
+
isAgentsMdCompanion: false
|
|
14904
|
+
});
|
|
14905
|
+
targets.push({
|
|
14906
|
+
path: (0, import_node_path3.join)(foundDir, ".cursorrules"),
|
|
14907
|
+
kind: "cursorrules-legacy",
|
|
14908
|
+
isAgentsMdCompanion: false
|
|
14909
|
+
});
|
|
14910
|
+
}
|
|
14911
|
+
targets.push({
|
|
14912
|
+
path: (0, import_node_path3.join)(foundDir, "AGENTS.md"),
|
|
14913
|
+
kind: "agents-md-companion",
|
|
14914
|
+
isAgentsMdCompanion: true
|
|
14915
|
+
});
|
|
14916
|
+
return targets;
|
|
14917
|
+
}
|
|
14918
|
+
case "windsurf": {
|
|
14919
|
+
if (agent.infoFilePath) {
|
|
14920
|
+
targets.push({
|
|
14921
|
+
path: agent.infoFilePath,
|
|
14922
|
+
kind: "primary",
|
|
14923
|
+
isAgentsMdCompanion: false
|
|
14924
|
+
});
|
|
14925
|
+
}
|
|
14926
|
+
targets.push({
|
|
14927
|
+
path: (0, import_node_path3.join)(foundDir, "AGENTS.md"),
|
|
14928
|
+
kind: "agents-md-companion",
|
|
14929
|
+
isAgentsMdCompanion: true
|
|
14930
|
+
});
|
|
14931
|
+
return targets;
|
|
14932
|
+
}
|
|
14933
|
+
case "generic": {
|
|
14934
|
+
if (agent.infoFilePath) {
|
|
14935
|
+
targets.push({
|
|
14936
|
+
path: agent.infoFilePath,
|
|
14937
|
+
kind: "primary",
|
|
14938
|
+
isAgentsMdCompanion: true
|
|
14939
|
+
});
|
|
14940
|
+
}
|
|
14941
|
+
return targets;
|
|
14942
|
+
}
|
|
14943
|
+
default: {
|
|
14944
|
+
const _exhaustive = agent.name;
|
|
14945
|
+
throw new Error(`Unknown agent: ${_exhaustive}`);
|
|
14946
|
+
}
|
|
14947
|
+
}
|
|
14948
|
+
}
|
|
14949
|
+
async function writeManagedSectionToTarget(filePath, createContent, managedSectionOnly) {
|
|
14950
|
+
let existingContent = null;
|
|
14951
|
+
try {
|
|
14952
|
+
existingContent = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
14953
|
+
} catch (err) {
|
|
14954
|
+
const code = err.code;
|
|
14955
|
+
if (code !== "ENOENT") {
|
|
14956
|
+
emitTargetWarning(filePath, "read", err);
|
|
14957
|
+
return;
|
|
14958
|
+
}
|
|
14959
|
+
}
|
|
14960
|
+
if (existingContent === null) {
|
|
14961
|
+
try {
|
|
14962
|
+
await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(filePath), { recursive: true });
|
|
14963
|
+
await (0, import_promises3.writeFile)(filePath, createContent, "utf-8");
|
|
14964
|
+
} catch (err) {
|
|
14965
|
+
emitTargetWarning(filePath, "write", err);
|
|
14966
|
+
return;
|
|
14967
|
+
}
|
|
14968
|
+
return;
|
|
14969
|
+
}
|
|
14970
|
+
const lines = existingContent.split("\n");
|
|
14971
|
+
const boundaries = findMarkerBoundaries(lines);
|
|
14972
|
+
let newContent;
|
|
14973
|
+
if (boundaries !== null) {
|
|
14974
|
+
const before = lines.slice(0, boundaries.startIdx);
|
|
14975
|
+
const after = lines.slice(boundaries.endIdx + 1);
|
|
14976
|
+
const contentWithoutTrailingNewline = managedSectionOnly.endsWith("\n") ? managedSectionOnly.slice(0, -1) : managedSectionOnly;
|
|
14977
|
+
newContent = [...before, contentWithoutTrailingNewline, ...after].join(
|
|
14978
|
+
"\n"
|
|
14979
|
+
);
|
|
14980
|
+
} else {
|
|
14981
|
+
const separator = existingContent.endsWith("\n") ? "\n" : "\n\n";
|
|
14982
|
+
newContent = existingContent + separator + managedSectionOnly;
|
|
14983
|
+
}
|
|
14984
|
+
try {
|
|
14985
|
+
await (0, import_promises3.writeFile)(filePath, newContent, "utf-8");
|
|
14986
|
+
} catch (err) {
|
|
14987
|
+
emitTargetWarning(filePath, "write", err);
|
|
14988
|
+
}
|
|
14989
|
+
}
|
|
14990
|
+
function emitTargetWarning(filePath, op, err) {
|
|
14991
|
+
const code = err.code;
|
|
14992
|
+
let qualifier;
|
|
14993
|
+
switch (code) {
|
|
14994
|
+
case "EACCES":
|
|
14995
|
+
case "EPERM":
|
|
14996
|
+
qualifier = "permission denied";
|
|
14997
|
+
break;
|
|
14998
|
+
case "EROFS":
|
|
14999
|
+
qualifier = "filesystem read-only";
|
|
15000
|
+
break;
|
|
15001
|
+
case "ENOSPC":
|
|
15002
|
+
qualifier = "disk full";
|
|
15003
|
+
break;
|
|
15004
|
+
case "ENAMETOOLONG":
|
|
15005
|
+
qualifier = "path too long";
|
|
15006
|
+
break;
|
|
15007
|
+
case "ENOTDIR":
|
|
15008
|
+
qualifier = "not a directory";
|
|
15009
|
+
break;
|
|
15010
|
+
case "EISDIR":
|
|
15011
|
+
qualifier = "is a directory";
|
|
15012
|
+
break;
|
|
15013
|
+
default:
|
|
15014
|
+
qualifier = "I/O error";
|
|
15015
|
+
break;
|
|
15016
|
+
}
|
|
15017
|
+
try {
|
|
15018
|
+
process.stderr.write(
|
|
15019
|
+
`Warning: cannot ${op} info file ${filePath}: ${qualifier}
|
|
15020
|
+
`
|
|
15021
|
+
);
|
|
15022
|
+
} catch {
|
|
15023
|
+
}
|
|
15024
|
+
}
|
|
15025
|
+
|
|
14797
15026
|
// src/cli/constants.ts
|
|
14798
15027
|
function formatAgentName(name) {
|
|
14799
15028
|
const displayNames = {
|
|
@@ -14949,14 +15178,9 @@ async function mcpAdd(options) {
|
|
|
14949
15178
|
const bearer = resolved.effective.key;
|
|
14950
15179
|
for (const agent of targetAgents) {
|
|
14951
15180
|
const name = formatAgentName(agent.name);
|
|
14952
|
-
const sdkVersion = true ? "1.10.1" : "0.0.0-dev";
|
|
14953
15181
|
if (agent.name !== "generic") {
|
|
14954
15182
|
const cliSuccess = await registerViaCli(agent, bearer);
|
|
14955
15183
|
if (cliSuccess) {
|
|
14956
|
-
const infoContent = generateInfoSection(agent, MCP_ENDPOINT, sdkVersion);
|
|
14957
|
-
if (infoContent !== "") {
|
|
14958
|
-
await injectInfoSection(agent, infoContent, projectRoot);
|
|
14959
|
-
}
|
|
14960
15184
|
results.push({
|
|
14961
15185
|
agent: agent.name,
|
|
14962
15186
|
success: true,
|
|
@@ -14971,10 +15195,6 @@ async function mcpAdd(options) {
|
|
|
14971
15195
|
const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
|
|
14972
15196
|
await writeMcpConfig(agent, configContent, projectRoot);
|
|
14973
15197
|
if (fs.existsSync(agent.mcpConfigPath)) {
|
|
14974
|
-
const infoContent = generateInfoSection(agent, MCP_ENDPOINT, sdkVersion);
|
|
14975
|
-
if (infoContent !== "") {
|
|
14976
|
-
await injectInfoSection(agent, infoContent, projectRoot);
|
|
14977
|
-
}
|
|
14978
15198
|
results.push({
|
|
14979
15199
|
agent: agent.name,
|
|
14980
15200
|
success: true,
|
|
@@ -15007,6 +15227,34 @@ async function mcpAdd(options) {
|
|
|
15007
15227
|
message: `${name}: No registration method available`
|
|
15008
15228
|
});
|
|
15009
15229
|
}
|
|
15230
|
+
const successfulAgentNames = new Set(
|
|
15231
|
+
results.filter((r) => r.success).map((r) => r.agent)
|
|
15232
|
+
);
|
|
15233
|
+
const agentsWithMcpReady = targetAgents.filter(
|
|
15234
|
+
(a) => successfulAgentNames.has(a.name)
|
|
15235
|
+
);
|
|
15236
|
+
const detectedNonGenericMcpAdd = targetAgents.filter(
|
|
15237
|
+
(a) => a.name !== "generic"
|
|
15238
|
+
);
|
|
15239
|
+
const nonGenericReadyMcpAdd = agentsWithMcpReady.filter(
|
|
15240
|
+
(a) => a.name !== "generic"
|
|
15241
|
+
);
|
|
15242
|
+
const dispatchSetMcpAdd = detectedNonGenericMcpAdd.length === 0 ? agentsWithMcpReady : nonGenericReadyMcpAdd;
|
|
15243
|
+
if (dispatchSetMcpAdd.length > 0) {
|
|
15244
|
+
const sdkVersion = true ? "1.11.0" : "0.0.0-dev";
|
|
15245
|
+
try {
|
|
15246
|
+
await injectAllTargets(
|
|
15247
|
+
dispatchSetMcpAdd,
|
|
15248
|
+
MCP_ENDPOINT,
|
|
15249
|
+
sdkVersion,
|
|
15250
|
+
projectRoot
|
|
15251
|
+
);
|
|
15252
|
+
} catch (injectErr) {
|
|
15253
|
+
messages.push(
|
|
15254
|
+
`Warning: Failed to write some agent-instruction files: ${injectErr instanceof Error ? injectErr.message : String(injectErr)}`
|
|
15255
|
+
);
|
|
15256
|
+
}
|
|
15257
|
+
}
|
|
15010
15258
|
await updateGitignore(
|
|
15011
15259
|
[".mcp.json", ".cursor/mcp.json", ".gemini/settings.json", ".codex/config.toml"],
|
|
15012
15260
|
projectRoot
|