@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.
Files changed (39) hide show
  1. package/README.md +43 -5
  2. package/dist/{chunk-WQF7ZQOM.js → chunk-DQFGNX3H.js} +13 -8
  3. package/dist/{chunk-WQF7ZQOM.js.map → chunk-DQFGNX3H.js.map} +1 -1
  4. package/dist/{chunk-UMGZJYC4.js → chunk-FQ4SEG6Y.js} +8 -3
  5. package/dist/chunk-FQ4SEG6Y.js.map +1 -0
  6. package/dist/chunk-KOYZJN6G.js +651 -0
  7. package/dist/chunk-KOYZJN6G.js.map +1 -0
  8. package/dist/{chunk-ZBQQXVHD.js → chunk-YIEXKQYP.js} +2 -67
  9. package/dist/chunk-YIEXKQYP.js.map +1 -0
  10. package/dist/cli/init.cjs +460 -127
  11. package/dist/cli/init.cjs.map +1 -1
  12. package/dist/cli/init.js +29 -16
  13. package/dist/cli/init.js.map +1 -1
  14. package/dist/cli/mcp-add.cjs +346 -98
  15. package/dist/cli/mcp-add.cjs.map +1 -1
  16. package/dist/cli/mcp-add.js +32 -14
  17. package/dist/cli/mcp-add.js.map +1 -1
  18. package/dist/cli/status.cjs +6 -1
  19. package/dist/cli/status.cjs.map +1 -1
  20. package/dist/cli/status.js +7 -2
  21. package/dist/cli/status.js.map +1 -1
  22. package/dist/cli/uninit.cjs +6 -1
  23. package/dist/cli/uninit.cjs.map +1 -1
  24. package/dist/cli/uninit.js +2 -2
  25. package/dist/cli/upgrade-instructions.cjs +390 -113
  26. package/dist/cli/upgrade-instructions.cjs.map +1 -1
  27. package/dist/cli/upgrade-instructions.js +70 -18
  28. package/dist/cli/upgrade-instructions.js.map +1 -1
  29. package/dist/index.cjs +11 -6
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.js +2 -2
  32. package/dist/node-entry.cjs +11 -6
  33. package/dist/node-entry.cjs.map +1 -1
  34. package/dist/node-entry.js +2 -2
  35. package/package.json +1 -1
  36. package/dist/chunk-TJ46YOGJ.js +0 -355
  37. package/dist/chunk-TJ46YOGJ.js.map +0 -1
  38. package/dist/chunk-UMGZJYC4.js.map +0 -1
  39. package/dist/chunk-ZBQQXVHD.js.map +0 -1
package/dist/cli/init.cjs CHANGED
@@ -15226,10 +15226,7 @@ async function detectAgents(projectRoot) {
15226
15226
  continue;
15227
15227
  }
15228
15228
  seenAgents.add(rule.name);
15229
- let infoFilePath = rule.infoFilePath(foundDir);
15230
- if (infoFilePath !== null && !await pathExists(infoFilePath)) {
15231
- infoFilePath = null;
15232
- }
15229
+ const infoFilePath = rule.infoFilePath(foundDir);
15233
15230
  const cliAvailable = rule.cliBinary ? await isCliAvailable(rule.cliBinary) : false;
15234
15231
  detected.push({
15235
15232
  name: rule.name,
@@ -15242,7 +15239,7 @@ async function detectAgents(projectRoot) {
15242
15239
  detected.push({
15243
15240
  name: "generic",
15244
15241
  mcpConfigPath: (0, import_node_path.join)(resolvedRoot, ".glasstrace", "mcp.json"),
15245
- infoFilePath: null,
15242
+ infoFilePath: (0, import_node_path.join)(resolvedRoot, "AGENTS.md"),
15246
15243
  cliAvailable: false,
15247
15244
  registrationCommand: null
15248
15245
  });
@@ -15268,33 +15265,61 @@ var init_detect = __esm({
15268
15265
  },
15269
15266
  {
15270
15267
  name: "codex",
15268
+ // Codex 2026 default discovery is `AGENTS.override.md` → `AGENTS.md` →
15269
+ // opt-in `project_doc_fallback_filenames`; `codex.md` is NOT in the
15270
+ // default fallback list. Detection requires Codex-specific markers
15271
+ // (`codex.md` legacy, `.codex/` config dir) — `AGENTS.md` is NOT
15272
+ // included as a marker because the SDK now writes `AGENTS.md`
15273
+ // broadly via the multi-target dispatcher's companion writes; if
15274
+ // `AGENTS.md` were a Codex marker, every project with the SDK's
15275
+ // own companion AGENTS.md would re-classify as Codex on subsequent
15276
+ // detect runs and trigger unintended `.codex/config.toml` writes
15277
+ // (Codex P1 + Copilot P1 review of Wave 18 PR #274). The canonical
15278
+ // write destination remains AGENTS.md regardless of which marker
15279
+ // classified the project.
15271
15280
  markers: ["codex.md", ".codex"],
15272
15281
  mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".codex", "config.toml"),
15273
- infoFilePath: (dir) => (0, import_node_path.join)(dir, "codex.md"),
15282
+ infoFilePath: (dir) => (0, import_node_path.join)(dir, "AGENTS.md"),
15274
15283
  cliBinary: "codex",
15275
15284
  registrationCommand: "npx glasstrace mcp add --agent codex"
15276
15285
  },
15277
15286
  {
15278
15287
  name: "gemini",
15279
- markers: [".gemini"],
15288
+ markers: [".gemini", "GEMINI.md"],
15280
15289
  mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".gemini", "settings.json"),
15281
- infoFilePath: () => null,
15290
+ infoFilePath: (dir) => (0, import_node_path.join)(dir, "GEMINI.md"),
15282
15291
  cliBinary: "gemini",
15283
15292
  registrationCommand: "npx glasstrace mcp add --agent gemini"
15284
15293
  },
15285
15294
  {
15286
15295
  name: "cursor",
15296
+ // `.cursor/rules/*.mdc` is the current canonical format per Cursor's
15297
+ // 2026 docs. `.cursorrules` (single file) is supported-but-deprecated
15298
+ // and stays as a transitional fallback that the multi-target write
15299
+ // helper writes unconditionally alongside the .mdc canonical.
15287
15300
  markers: [".cursor", ".cursorrules"],
15288
15301
  mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".cursor", "mcp.json"),
15289
- infoFilePath: (dir) => (0, import_node_path.join)(dir, ".cursorrules"),
15302
+ infoFilePath: (dir) => (0, import_node_path.join)(dir, ".cursor", "rules", "glasstrace.mdc"),
15290
15303
  cliBinary: null,
15291
15304
  registrationCommand: "npx glasstrace mcp add --agent cursor"
15292
15305
  },
15293
15306
  {
15294
15307
  name: "windsurf",
15295
- markers: [".windsurfrules", ".windsurf"],
15308
+ // Windsurf's current canonical workspace-rules format is
15309
+ // `.windsurf/rules/*.md`. AGENTS.md is a parallel cross-tool
15310
+ // mechanism Windsurf also reads BUT is NOT included as a Windsurf
15311
+ // detection marker — the SDK writes `AGENTS.md` broadly via the
15312
+ // multi-target dispatcher's companion writes, so treating
15313
+ // `AGENTS.md` as a Windsurf marker would re-classify every
15314
+ // SDK-managed project as Windsurf and cause `glasstrace uninit`
15315
+ // to mutate the global `~/.codeium/windsurf/mcp_config.json` for
15316
+ // non-Windsurf projects (Codex P1 + Copilot P1 review of Wave 18
15317
+ // PR #274). The single-file `.windsurfrules` is the deprecated
15318
+ // legacy form — recognized as a marker so legacy projects classify
15319
+ // correctly, but the SDK no longer writes to it.
15320
+ markers: [".windsurf", ".windsurfrules"],
15296
15321
  mcpConfigPath: () => (0, import_node_path.join)((0, import_node_os.homedir)(), ".codeium", "windsurf", "mcp_config.json"),
15297
- infoFilePath: (dir) => (0, import_node_path.join)(dir, ".windsurfrules"),
15322
+ infoFilePath: (dir) => (0, import_node_path.join)(dir, ".windsurf", "rules", "glasstrace.md"),
15298
15323
  cliBinary: null,
15299
15324
  registrationCommand: "npx glasstrace mcp add --agent windsurf"
15300
15325
  }
@@ -15325,7 +15350,13 @@ function buildAgentInstructionBody() {
15325
15350
  "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.",
15326
15351
  "2. Take the highest-confidence candidate's `suggestedFollowups` and pass them straight to `get_trace` or `get_root_cause`.",
15327
15352
  "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.",
15328
- "4. If a tool returns empty, READ the response's `closeMatches`, `recentRoutesSample`, and `recoveryActions` before pivoting to source. Empty results carry `notAbsenceProof: true` \u2014 they are never proof the bug did not occur.",
15353
+ "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:",
15354
+ " - `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.",
15355
+ ' - `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`.',
15356
+ " - `humanReadable` \u2014 prose guidance written for the agent.",
15357
+ " - `recoveryActions` \u2014 concrete next-call shapes.",
15358
+ " - `diagnosticValue` / `recommendedNextStep` \u2014 whether to keep searching or stop.",
15359
+ " Empty results carry `notAbsenceProof: true` \u2014 they are never proof the bug did not occur.",
15329
15360
  "",
15330
15361
  "### Tools",
15331
15362
  "- `find_trace_candidates` \u2014 discovery, vocabulary-tolerant filter",
@@ -15473,34 +15504,71 @@ function generateInfoSection(agent, endpoint, sdkVersion) {
15473
15504
  }
15474
15505
  const content = buildAgentInstructionBody();
15475
15506
  switch (agent.name) {
15476
- case "claude": {
15477
- const m = htmlMarkers(sdkVersion);
15478
- return `${m.start}
15479
- ${content}${m.end}
15480
- `;
15481
- }
15482
- case "codex": {
15507
+ case "claude":
15508
+ case "codex":
15509
+ case "gemini":
15510
+ case "windsurf":
15511
+ case "generic": {
15483
15512
  const m = htmlMarkers(sdkVersion);
15484
15513
  return `${m.start}
15485
15514
  ${content}${m.end}
15486
15515
  `;
15487
15516
  }
15488
15517
  case "cursor": {
15489
- const m = hashMarkers(sdkVersion);
15518
+ const m = htmlMarkers(sdkVersion);
15490
15519
  return `${m.start}
15491
15520
  ${content}${m.end}
15492
15521
  `;
15493
15522
  }
15494
- case "gemini":
15495
- case "windsurf":
15496
- case "generic":
15497
- return "";
15498
15523
  default: {
15499
15524
  const _exhaustive = agent.name;
15500
15525
  throw new Error(`Unknown agent: ${_exhaustive}`);
15501
15526
  }
15502
15527
  }
15503
15528
  }
15529
+ function generateInfoSectionForCursorrulesLegacy(endpoint, sdkVersion) {
15530
+ if (!endpoint || endpoint.trim() === "") {
15531
+ throw new Error("endpoint must not be empty");
15532
+ }
15533
+ if (!sdkVersion || sdkVersion.trim() === "") {
15534
+ throw new Error("sdkVersion must not be empty");
15535
+ }
15536
+ if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {
15537
+ throw new Error(
15538
+ "sdkVersion must match [A-Za-z0-9.+\\-]+ (semver-shaped, no whitespace, no angle brackets)"
15539
+ );
15540
+ }
15541
+ const content = buildAgentInstructionBody();
15542
+ const m = hashMarkers(sdkVersion);
15543
+ return `${m.start}
15544
+ ${content}${m.end}
15545
+ `;
15546
+ }
15547
+ function generateInfoSectionForCursorMdc(endpoint, sdkVersion) {
15548
+ if (!endpoint || endpoint.trim() === "") {
15549
+ throw new Error("endpoint must not be empty");
15550
+ }
15551
+ if (!sdkVersion || sdkVersion.trim() === "") {
15552
+ throw new Error("sdkVersion must not be empty");
15553
+ }
15554
+ if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {
15555
+ throw new Error(
15556
+ "sdkVersion must match [A-Za-z0-9.+\\-]+ (semver-shaped, no whitespace, no angle brackets)"
15557
+ );
15558
+ }
15559
+ const content = buildAgentInstructionBody();
15560
+ const m = htmlMarkers(sdkVersion);
15561
+ return [
15562
+ "---",
15563
+ "description: Glasstrace MCP runtime debugging tools \u2014 runtime evidence the agent reads when source alone cannot resolve a bug",
15564
+ "alwaysApply: true",
15565
+ "---",
15566
+ "",
15567
+ `${m.start}
15568
+ ${content}${m.end}
15569
+ `
15570
+ ].join("\n");
15571
+ }
15504
15572
  var SDK_VERSION_STAMP_PATTERN;
15505
15573
  var init_configs = __esm({
15506
15574
  "src/agent-detection/configs.ts"() {
@@ -15580,71 +15648,6 @@ function findMarkerBoundaries(lines) {
15580
15648
  }
15581
15649
  return null;
15582
15650
  }
15583
- async function injectInfoSection(agent, content, projectRoot) {
15584
- if (agent.infoFilePath === null) {
15585
- return;
15586
- }
15587
- if (content === "") {
15588
- return;
15589
- }
15590
- const filePath = agent.infoFilePath;
15591
- let existingContent = null;
15592
- try {
15593
- existingContent = await (0, import_promises2.readFile)(filePath, "utf-8");
15594
- } catch (err) {
15595
- const code = err.code;
15596
- if (code !== "ENOENT") {
15597
- if (isPermissionError(err)) {
15598
- process.stderr.write(
15599
- `Warning: cannot read info file ${filePath}: permission denied
15600
- `
15601
- );
15602
- return;
15603
- }
15604
- throw err;
15605
- }
15606
- }
15607
- if (existingContent === null) {
15608
- try {
15609
- await (0, import_promises2.mkdir)((0, import_node_path2.dirname)(filePath), { recursive: true });
15610
- await (0, import_promises2.writeFile)(filePath, content, "utf-8");
15611
- } catch (err) {
15612
- if (isPermissionError(err)) {
15613
- process.stderr.write(
15614
- `Warning: cannot write info file ${filePath}: permission denied
15615
- `
15616
- );
15617
- return;
15618
- }
15619
- throw err;
15620
- }
15621
- return;
15622
- }
15623
- const lines = existingContent.split("\n");
15624
- const boundaries = findMarkerBoundaries(lines);
15625
- let newContent;
15626
- if (boundaries !== null) {
15627
- const before = lines.slice(0, boundaries.startIdx);
15628
- const after = lines.slice(boundaries.endIdx + 1);
15629
- const contentWithoutTrailingNewline = content.endsWith("\n") ? content.slice(0, -1) : content;
15630
- newContent = [...before, contentWithoutTrailingNewline, ...after].join("\n");
15631
- } else {
15632
- const separator = existingContent.endsWith("\n") ? "\n" : "\n\n";
15633
- newContent = existingContent + separator + content;
15634
- }
15635
- try {
15636
- await (0, import_promises2.writeFile)(filePath, newContent, "utf-8");
15637
- } catch (err) {
15638
- if (isPermissionError(err)) {
15639
- process.stderr.write(
15640
- `Warning: cannot write info file ${filePath}: permission denied
15641
- `
15642
- );
15643
- return;
15644
- }
15645
- throw err;
15646
- }
15647
- }
15648
15651
  async function hasManagedSection(filePath) {
15649
15652
  let content;
15650
15653
  try {
@@ -15715,6 +15718,238 @@ var init_inject = __esm({
15715
15718
  }
15716
15719
  });
15717
15720
 
15721
+ // src/agent-detection/inject-all-targets.ts
15722
+ async function injectAllTargets(agents, endpoint, sdkVersion, projectRoot) {
15723
+ const writtenAgentsMd = /* @__PURE__ */ new Set();
15724
+ for (const agent of agents) {
15725
+ const targets = computeTargets(agent, projectRoot);
15726
+ for (const target of targets) {
15727
+ if (target.isAgentsMdCompanion) {
15728
+ if (writtenAgentsMd.has(target.path)) {
15729
+ continue;
15730
+ }
15731
+ writtenAgentsMd.add(target.path);
15732
+ }
15733
+ let createContent;
15734
+ let managedSectionOnly;
15735
+ if (target.kind === "cursor-mdc") {
15736
+ createContent = generateInfoSectionForCursorMdc(endpoint, sdkVersion);
15737
+ managedSectionOnly = generateInfoSection(agent, endpoint, sdkVersion);
15738
+ } else if (target.kind === "cursorrules-legacy") {
15739
+ createContent = generateInfoSectionForCursorrulesLegacy(
15740
+ endpoint,
15741
+ sdkVersion
15742
+ );
15743
+ managedSectionOnly = createContent;
15744
+ } else {
15745
+ createContent = generateInfoSection(agent, endpoint, sdkVersion);
15746
+ managedSectionOnly = createContent;
15747
+ }
15748
+ if (managedSectionOnly === "") continue;
15749
+ await writeManagedSectionToTarget(
15750
+ target.path,
15751
+ createContent,
15752
+ managedSectionOnly
15753
+ );
15754
+ }
15755
+ }
15756
+ }
15757
+ function foundDirFromAgent(agent) {
15758
+ if (agent.infoFilePath === null) return null;
15759
+ switch (agent.name) {
15760
+ case "claude":
15761
+ case "codex":
15762
+ case "gemini":
15763
+ case "generic":
15764
+ return (0, import_node_path3.dirname)(agent.infoFilePath);
15765
+ case "cursor":
15766
+ return (0, import_node_path3.dirname)((0, import_node_path3.dirname)((0, import_node_path3.dirname)(agent.infoFilePath)));
15767
+ case "windsurf":
15768
+ return (0, import_node_path3.dirname)((0, import_node_path3.dirname)((0, import_node_path3.dirname)(agent.infoFilePath)));
15769
+ }
15770
+ }
15771
+ function computeTargets(agent, projectRoot) {
15772
+ const targets = [];
15773
+ const foundDir = foundDirFromAgent(agent) ?? projectRoot;
15774
+ switch (agent.name) {
15775
+ case "claude": {
15776
+ if (agent.infoFilePath) {
15777
+ targets.push({
15778
+ path: agent.infoFilePath,
15779
+ kind: "primary",
15780
+ isAgentsMdCompanion: false
15781
+ });
15782
+ }
15783
+ targets.push({
15784
+ path: (0, import_node_path3.join)(foundDir, "AGENTS.md"),
15785
+ kind: "agents-md-companion",
15786
+ isAgentsMdCompanion: true
15787
+ });
15788
+ return targets;
15789
+ }
15790
+ case "codex": {
15791
+ if (agent.infoFilePath) {
15792
+ targets.push({
15793
+ path: agent.infoFilePath,
15794
+ kind: "primary",
15795
+ isAgentsMdCompanion: true
15796
+ });
15797
+ }
15798
+ return targets;
15799
+ }
15800
+ case "gemini": {
15801
+ if (agent.infoFilePath) {
15802
+ targets.push({
15803
+ path: agent.infoFilePath,
15804
+ kind: "primary",
15805
+ isAgentsMdCompanion: false
15806
+ });
15807
+ }
15808
+ targets.push({
15809
+ path: (0, import_node_path3.join)(foundDir, "AGENTS.md"),
15810
+ kind: "agents-md-companion",
15811
+ isAgentsMdCompanion: true
15812
+ });
15813
+ return targets;
15814
+ }
15815
+ case "cursor": {
15816
+ if (agent.infoFilePath) {
15817
+ targets.push({
15818
+ path: agent.infoFilePath,
15819
+ kind: "cursor-mdc",
15820
+ isAgentsMdCompanion: false
15821
+ });
15822
+ targets.push({
15823
+ path: (0, import_node_path3.join)(foundDir, ".cursorrules"),
15824
+ kind: "cursorrules-legacy",
15825
+ isAgentsMdCompanion: false
15826
+ });
15827
+ }
15828
+ targets.push({
15829
+ path: (0, import_node_path3.join)(foundDir, "AGENTS.md"),
15830
+ kind: "agents-md-companion",
15831
+ isAgentsMdCompanion: true
15832
+ });
15833
+ return targets;
15834
+ }
15835
+ case "windsurf": {
15836
+ if (agent.infoFilePath) {
15837
+ targets.push({
15838
+ path: agent.infoFilePath,
15839
+ kind: "primary",
15840
+ isAgentsMdCompanion: false
15841
+ });
15842
+ }
15843
+ targets.push({
15844
+ path: (0, import_node_path3.join)(foundDir, "AGENTS.md"),
15845
+ kind: "agents-md-companion",
15846
+ isAgentsMdCompanion: true
15847
+ });
15848
+ return targets;
15849
+ }
15850
+ case "generic": {
15851
+ if (agent.infoFilePath) {
15852
+ targets.push({
15853
+ path: agent.infoFilePath,
15854
+ kind: "primary",
15855
+ isAgentsMdCompanion: true
15856
+ });
15857
+ }
15858
+ return targets;
15859
+ }
15860
+ default: {
15861
+ const _exhaustive = agent.name;
15862
+ throw new Error(`Unknown agent: ${_exhaustive}`);
15863
+ }
15864
+ }
15865
+ }
15866
+ async function writeManagedSectionToTarget(filePath, createContent, managedSectionOnly) {
15867
+ let existingContent = null;
15868
+ try {
15869
+ existingContent = await (0, import_promises3.readFile)(filePath, "utf-8");
15870
+ } catch (err) {
15871
+ const code = err.code;
15872
+ if (code !== "ENOENT") {
15873
+ emitTargetWarning(filePath, "read", err);
15874
+ return;
15875
+ }
15876
+ }
15877
+ if (existingContent === null) {
15878
+ try {
15879
+ await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(filePath), { recursive: true });
15880
+ await (0, import_promises3.writeFile)(filePath, createContent, "utf-8");
15881
+ } catch (err) {
15882
+ emitTargetWarning(filePath, "write", err);
15883
+ return;
15884
+ }
15885
+ return;
15886
+ }
15887
+ const lines = existingContent.split("\n");
15888
+ const boundaries = findMarkerBoundaries(lines);
15889
+ let newContent;
15890
+ if (boundaries !== null) {
15891
+ const before = lines.slice(0, boundaries.startIdx);
15892
+ const after = lines.slice(boundaries.endIdx + 1);
15893
+ const contentWithoutTrailingNewline = managedSectionOnly.endsWith("\n") ? managedSectionOnly.slice(0, -1) : managedSectionOnly;
15894
+ newContent = [...before, contentWithoutTrailingNewline, ...after].join(
15895
+ "\n"
15896
+ );
15897
+ } else {
15898
+ const separator = existingContent.endsWith("\n") ? "\n" : "\n\n";
15899
+ newContent = existingContent + separator + managedSectionOnly;
15900
+ }
15901
+ try {
15902
+ await (0, import_promises3.writeFile)(filePath, newContent, "utf-8");
15903
+ } catch (err) {
15904
+ emitTargetWarning(filePath, "write", err);
15905
+ }
15906
+ }
15907
+ function emitTargetWarning(filePath, op, err) {
15908
+ const code = err.code;
15909
+ let qualifier;
15910
+ switch (code) {
15911
+ case "EACCES":
15912
+ case "EPERM":
15913
+ qualifier = "permission denied";
15914
+ break;
15915
+ case "EROFS":
15916
+ qualifier = "filesystem read-only";
15917
+ break;
15918
+ case "ENOSPC":
15919
+ qualifier = "disk full";
15920
+ break;
15921
+ case "ENAMETOOLONG":
15922
+ qualifier = "path too long";
15923
+ break;
15924
+ case "ENOTDIR":
15925
+ qualifier = "not a directory";
15926
+ break;
15927
+ case "EISDIR":
15928
+ qualifier = "is a directory";
15929
+ break;
15930
+ default:
15931
+ qualifier = "I/O error";
15932
+ break;
15933
+ }
15934
+ try {
15935
+ process.stderr.write(
15936
+ `Warning: cannot ${op} info file ${filePath}: ${qualifier}
15937
+ `
15938
+ );
15939
+ } catch {
15940
+ }
15941
+ }
15942
+ var import_promises3, import_node_path3;
15943
+ var init_inject_all_targets = __esm({
15944
+ "src/agent-detection/inject-all-targets.ts"() {
15945
+ "use strict";
15946
+ import_promises3 = require("node:fs/promises");
15947
+ import_node_path3 = require("node:path");
15948
+ init_configs();
15949
+ init_inject();
15950
+ }
15951
+ });
15952
+
15718
15953
  // src/cli/monorepo.ts
15719
15954
  var monorepo_exports = {};
15720
15955
  __export(monorepo_exports, {
@@ -16867,9 +17102,14 @@ var init_uninit = __esm({
16867
17102
  init_inject();
16868
17103
  MCP_CONFIG_FILES = [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json"];
16869
17104
  AGENT_INFO_FILES = [
17105
+ "AGENTS.md",
16870
17106
  "CLAUDE.md",
17107
+ "GEMINI.md",
17108
+ ".cursor/rules/glasstrace.mdc",
17109
+ ".windsurf/rules/glasstrace.md",
17110
+ ".cursorrules",
16871
17111
  "codex.md",
16872
- ".cursorrules"
17112
+ ".windsurfrules"
16873
17113
  ];
16874
17114
  }
16875
17115
  });
@@ -17020,14 +17260,9 @@ async function mcpAdd(options) {
17020
17260
  const bearer = resolved.effective.key;
17021
17261
  for (const agent of targetAgents) {
17022
17262
  const name = formatAgentName(agent.name);
17023
- const sdkVersion = true ? "1.10.1" : "0.0.0-dev";
17024
17263
  if (agent.name !== "generic") {
17025
17264
  const cliSuccess = await registerViaCli(agent, bearer);
17026
17265
  if (cliSuccess) {
17027
- const infoContent = generateInfoSection(agent, MCP_ENDPOINT, sdkVersion);
17028
- if (infoContent !== "") {
17029
- await injectInfoSection(agent, infoContent, projectRoot);
17030
- }
17031
17266
  results.push({
17032
17267
  agent: agent.name,
17033
17268
  success: true,
@@ -17042,10 +17277,6 @@ async function mcpAdd(options) {
17042
17277
  const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
17043
17278
  await writeMcpConfig(agent, configContent, projectRoot);
17044
17279
  if (fs6.existsSync(agent.mcpConfigPath)) {
17045
- const infoContent = generateInfoSection(agent, MCP_ENDPOINT, sdkVersion);
17046
- if (infoContent !== "") {
17047
- await injectInfoSection(agent, infoContent, projectRoot);
17048
- }
17049
17280
  results.push({
17050
17281
  agent: agent.name,
17051
17282
  success: true,
@@ -17078,6 +17309,34 @@ async function mcpAdd(options) {
17078
17309
  message: `${name}: No registration method available`
17079
17310
  });
17080
17311
  }
17312
+ const successfulAgentNames = new Set(
17313
+ results.filter((r) => r.success).map((r) => r.agent)
17314
+ );
17315
+ const agentsWithMcpReady = targetAgents.filter(
17316
+ (a) => successfulAgentNames.has(a.name)
17317
+ );
17318
+ const detectedNonGenericMcpAdd = targetAgents.filter(
17319
+ (a) => a.name !== "generic"
17320
+ );
17321
+ const nonGenericReadyMcpAdd = agentsWithMcpReady.filter(
17322
+ (a) => a.name !== "generic"
17323
+ );
17324
+ const dispatchSetMcpAdd = detectedNonGenericMcpAdd.length === 0 ? agentsWithMcpReady : nonGenericReadyMcpAdd;
17325
+ if (dispatchSetMcpAdd.length > 0) {
17326
+ const sdkVersion = true ? "1.11.0" : "0.0.0-dev";
17327
+ try {
17328
+ await injectAllTargets(
17329
+ dispatchSetMcpAdd,
17330
+ MCP_ENDPOINT,
17331
+ sdkVersion,
17332
+ projectRoot
17333
+ );
17334
+ } catch (injectErr) {
17335
+ messages.push(
17336
+ `Warning: Failed to write some agent-instruction files: ${injectErr instanceof Error ? injectErr.message : String(injectErr)}`
17337
+ );
17338
+ }
17339
+ }
17081
17340
  await updateGitignore(
17082
17341
  [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json", ".codex/config.toml"],
17083
17342
  projectRoot
@@ -17133,6 +17392,7 @@ var init_mcp_add = __esm({
17133
17392
  init_mcp_runtime();
17134
17393
  init_detect();
17135
17394
  init_configs();
17395
+ init_inject_all_targets();
17136
17396
  init_inject();
17137
17397
  init_constants();
17138
17398
  execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
@@ -17267,9 +17527,41 @@ var upgrade_instructions_exports = {};
17267
17527
  __export(upgrade_instructions_exports, {
17268
17528
  runUpgradeInstructions: () => runUpgradeInstructions
17269
17529
  });
17530
+ function legacyDestinationsForAgent(agent) {
17531
+ if (agent.infoFilePath === null) {
17532
+ return [];
17533
+ }
17534
+ switch (agent.name) {
17535
+ case "codex":
17536
+ return [(0, import_node_path4.join)((0, import_node_path4.dirname)(agent.infoFilePath), "codex.md")];
17537
+ case "cursor":
17538
+ return [
17539
+ (0, import_node_path4.join)((0, import_node_path4.dirname)((0, import_node_path4.dirname)((0, import_node_path4.dirname)(agent.infoFilePath))), ".cursorrules")
17540
+ ];
17541
+ case "windsurf":
17542
+ return [
17543
+ (0, import_node_path4.join)(
17544
+ (0, import_node_path4.dirname)((0, import_node_path4.dirname)((0, import_node_path4.dirname)(agent.infoFilePath))),
17545
+ ".windsurfrules"
17546
+ )
17547
+ ];
17548
+ case "claude":
17549
+ case "gemini":
17550
+ case "generic":
17551
+ return [];
17552
+ }
17553
+ }
17554
+ async function anyHasManagedSection(paths) {
17555
+ for (const p of paths) {
17556
+ if (await hasManagedSection(p)) {
17557
+ return true;
17558
+ }
17559
+ }
17560
+ return false;
17561
+ }
17270
17562
  function formatPathForOutput(filePath, projectRoot) {
17271
- const rel = (0, import_node_path3.relative)(projectRoot, filePath);
17272
- if (rel === "" || rel.startsWith("..") || (0, import_node_path3.isAbsolute)(rel)) {
17563
+ const rel = (0, import_node_path4.relative)(projectRoot, filePath);
17564
+ if (rel === "" || rel.startsWith("..") || (0, import_node_path4.isAbsolute)(rel)) {
17273
17565
  return filePath;
17274
17566
  }
17275
17567
  return rel;
@@ -17288,7 +17580,8 @@ async function runUpgradeInstructions(options) {
17288
17580
  );
17289
17581
  return { exitCode: 1, refreshed, skipped, warnings, errors };
17290
17582
  }
17291
- const sdkVersion = true ? "1.10.1" : "0.0.0-dev";
17583
+ const sdkVersion = true ? "1.11.0" : "0.0.0-dev";
17584
+ const optedInAgents = [];
17292
17585
  for (const agent of agents) {
17293
17586
  if (agent.infoFilePath === null) {
17294
17587
  continue;
@@ -17297,44 +17590,64 @@ async function runUpgradeInstructions(options) {
17297
17590
  agent.infoFilePath,
17298
17591
  options.projectRoot
17299
17592
  );
17300
- let containsSection;
17593
+ const legacyDestinations = legacyDestinationsForAgent(agent);
17594
+ let optedIn;
17301
17595
  try {
17302
- containsSection = await hasManagedSection(agent.infoFilePath);
17596
+ optedIn = await anyHasManagedSection([
17597
+ agent.infoFilePath,
17598
+ ...legacyDestinations
17599
+ ]);
17303
17600
  } catch (err) {
17304
17601
  warnings.push(
17305
17602
  `Could not inspect ${displayPath}: ${err instanceof Error ? err.message : String(err)}`
17306
17603
  );
17307
17604
  continue;
17308
17605
  }
17309
- if (!containsSection) {
17606
+ if (!optedIn) {
17310
17607
  skipped.push(displayPath);
17311
17608
  continue;
17312
17609
  }
17313
- const content = generateInfoSection(agent, MCP_ENDPOINT, sdkVersion);
17314
- if (content === "") {
17315
- continue;
17316
- }
17610
+ optedInAgents.push(agent);
17611
+ }
17612
+ if (optedInAgents.length > 0) {
17317
17613
  try {
17318
- await injectInfoSection(agent, content, options.projectRoot);
17319
- refreshed.push(displayPath);
17614
+ await injectAllTargets(
17615
+ optedInAgents,
17616
+ MCP_ENDPOINT,
17617
+ sdkVersion,
17618
+ options.projectRoot
17619
+ );
17620
+ for (const a of optedInAgents) {
17621
+ if (a.infoFilePath !== null) {
17622
+ refreshed.push(formatPathForOutput(a.infoFilePath, options.projectRoot));
17623
+ }
17624
+ }
17320
17625
  } catch (err) {
17321
17626
  errors.push(
17322
- `Failed to refresh ${displayPath}: ${err instanceof Error ? err.message : String(err)}`
17627
+ `Failed to refresh agent-instruction files: ${err instanceof Error ? err.message : String(err)}`
17323
17628
  );
17324
17629
  }
17325
17630
  }
17631
+ const refreshedSet = new Set(refreshed);
17632
+ const dedupedSkipped = skipped.filter((p) => !refreshedSet.has(p));
17326
17633
  const exitCode = errors.length === 0 ? 0 : 1;
17327
- return { exitCode, refreshed, skipped, warnings, errors };
17634
+ return {
17635
+ exitCode,
17636
+ refreshed,
17637
+ skipped: dedupedSkipped,
17638
+ warnings,
17639
+ errors
17640
+ };
17328
17641
  }
17329
- var import_node_path3;
17642
+ var import_node_path4;
17330
17643
  var init_upgrade_instructions = __esm({
17331
17644
  "src/cli/upgrade-instructions.ts"() {
17332
17645
  "use strict";
17333
- import_node_path3 = require("node:path");
17646
+ import_node_path4 = require("node:path");
17334
17647
  init_mcp_runtime();
17335
17648
  init_detect();
17336
- init_configs();
17337
17649
  init_inject();
17650
+ init_inject_all_targets();
17338
17651
  }
17339
17652
  });
17340
17653
 
@@ -17522,9 +17835,14 @@ var init_status = __esm({
17522
17835
  MCP_JSON_FILES = [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json", ".glasstrace/mcp.json"];
17523
17836
  MCP_TOML_FILES = [".codex/config.toml"];
17524
17837
  AGENT_INFO_FILES2 = [
17838
+ "AGENTS.md",
17525
17839
  "CLAUDE.md",
17840
+ "GEMINI.md",
17841
+ ".cursor/rules/glasstrace.mdc",
17842
+ ".windsurf/rules/glasstrace.md",
17843
+ ".cursorrules",
17526
17844
  "codex.md",
17527
- ".cursorrules"
17845
+ ".windsurfrules"
17528
17846
  ];
17529
17847
  INSTRUMENTATION_FILES = [
17530
17848
  "instrumentation.ts",
@@ -18106,6 +18424,7 @@ async function buildImportGraph(projectRoot) {
18106
18424
  init_anon_key();
18107
18425
  init_detect();
18108
18426
  init_configs();
18427
+ init_inject_all_targets();
18109
18428
  init_inject();
18110
18429
  init_constants();
18111
18430
  init_monorepo();
@@ -18904,6 +19223,7 @@ Then add this as the first statement in your register() function:
18904
19223
  agents = [];
18905
19224
  }
18906
19225
  const configuredNames = [];
19226
+ const agentsWithMcpReady = [];
18907
19227
  for (const agent of agents) {
18908
19228
  try {
18909
19229
  const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
@@ -18918,6 +19238,7 @@ Then add this as the first statement in your register() function:
18918
19238
  );
18919
19239
  if (agent.mcpConfigPath !== null && fs9.existsSync(agent.mcpConfigPath)) {
18920
19240
  anyConfigWritten = true;
19241
+ agentsWithMcpReady.push(agent);
18921
19242
  }
18922
19243
  continue;
18923
19244
  }
@@ -18928,15 +19249,7 @@ Then add this as the first statement in your register() function:
18928
19249
  }
18929
19250
  anyConfigWritten = true;
18930
19251
  anyConfigRewrittenWithBearer = true;
18931
- const sdkVersionForInject = true ? "1.10.1" : "0.0.0-dev";
18932
- const infoContent = generateInfoSection(
18933
- agent,
18934
- MCP_ENDPOINT,
18935
- sdkVersionForInject
18936
- );
18937
- if (infoContent !== "") {
18938
- await injectInfoSection(agent, infoContent, projectRoot);
18939
- }
19252
+ agentsWithMcpReady.push(agent);
18940
19253
  if (agent.name !== "generic") {
18941
19254
  configuredNames.push(formatAgentName(agent.name));
18942
19255
  }
@@ -18946,6 +19259,26 @@ Then add this as the first statement in your register() function:
18946
19259
  );
18947
19260
  }
18948
19261
  }
19262
+ const detectedNonGeneric = agents.filter((a) => a.name !== "generic");
19263
+ const nonGenericReady = agentsWithMcpReady.filter(
19264
+ (a) => a.name !== "generic"
19265
+ );
19266
+ const dispatchSet = detectedNonGeneric.length === 0 ? agentsWithMcpReady : nonGenericReady;
19267
+ if (dispatchSet.length > 0) {
19268
+ const sdkVersionForInject = true ? "1.11.0" : "0.0.0-dev";
19269
+ try {
19270
+ await injectAllTargets(
19271
+ dispatchSet,
19272
+ MCP_ENDPOINT,
19273
+ sdkVersionForInject,
19274
+ projectRoot
19275
+ );
19276
+ } catch (injectErr) {
19277
+ warnings.push(
19278
+ `Failed to write agent-instruction files: ${injectErr instanceof Error ? injectErr.message : String(injectErr)}`
19279
+ );
19280
+ }
19281
+ }
18949
19282
  if (configuredNames.length > 0) {
18950
19283
  summary.push(`Configured MCP for: ${configuredNames.join(", ")}`);
18951
19284
  } else if (anyConfigWritten) {
@@ -19034,7 +19367,7 @@ async function verifyAnonKeyRegistration(projectRoot) {
19034
19367
  }
19035
19368
  const baseConfig = resolveConfig({ apiKey: devKey });
19036
19369
  const config2 = { ...baseConfig, apiKey: devKey };
19037
- const sdkVersion = true ? "1.10.1" : "0.0.0-dev";
19370
+ const sdkVersion = true ? "1.11.0" : "0.0.0-dev";
19038
19371
  const result = await verifyInitReachable(config2, anonKey, sdkVersion);
19039
19372
  if (result.ok) {
19040
19373
  return { outcome: "verified" };