@glasstrace/sdk 0.10.0 → 0.12.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 (48) hide show
  1. package/dist/adapters/drizzle.js +1 -1
  2. package/dist/{chunk-ZRNG36LU.js → chunk-6GRNJ722.js} +38 -17
  3. package/dist/chunk-6GRNJ722.js.map +1 -0
  4. package/dist/chunk-IPGOKORJ.js +580 -0
  5. package/dist/chunk-IPGOKORJ.js.map +1 -0
  6. package/dist/{chunk-5MAHIPFH.js → chunk-LW7DPKBA.js} +2 -2
  7. package/dist/{chunk-KOYJ2UQE.js → chunk-MSMOH6IH.js} +108 -38
  8. package/dist/chunk-MSMOH6IH.js.map +1 -0
  9. package/dist/chunk-NSBPE2FW.js +17 -0
  10. package/dist/{chunk-O3Y45VGV.js → chunk-OKIP4SRG.js} +5 -3
  11. package/dist/{chunk-O3Y45VGV.js.map → chunk-OKIP4SRG.js.map} +1 -1
  12. package/dist/cli/init.cjs +457 -330
  13. package/dist/cli/init.cjs.map +1 -1
  14. package/dist/cli/init.d.cts +25 -1
  15. package/dist/cli/init.d.ts +25 -1
  16. package/dist/cli/init.js +114 -4
  17. package/dist/cli/init.js.map +1 -1
  18. package/dist/cli/mcp-add.cjs +63 -47
  19. package/dist/cli/mcp-add.cjs.map +1 -1
  20. package/dist/cli/mcp-add.js +3 -3
  21. package/dist/cli/uninit.js +15 -564
  22. package/dist/cli/uninit.js.map +1 -1
  23. package/dist/{esm-POMEQPKL.js → esm-KBPHCVB4.js} +2 -2
  24. package/dist/{getMachineId-bsd-TC3JSTY5.js → getMachineId-bsd-345PYXFX.js} +2 -2
  25. package/dist/{getMachineId-darwin-2SUKQCE6.js → getMachineId-darwin-5L2D25AD.js} +2 -2
  26. package/dist/{getMachineId-linux-PNAFHLXH.js → getMachineId-linux-KJR4P5HN.js} +2 -2
  27. package/dist/{getMachineId-unsupported-L2MNYW3W.js → getMachineId-unsupported-NDNXDYDY.js} +2 -2
  28. package/dist/{getMachineId-win-D6D42WOQ.js → getMachineId-win-T7PJNJXG.js} +2 -2
  29. package/dist/index.cjs +327 -159
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +75 -11
  32. package/dist/index.d.ts +75 -11
  33. package/dist/index.js +159 -82
  34. package/dist/index.js.map +1 -1
  35. package/dist/{source-map-uploader-OA5NCDOK.js → source-map-uploader-ZFCYOURS.js} +6 -4
  36. package/package.json +1 -1
  37. package/dist/chunk-KOYJ2UQE.js.map +0 -1
  38. package/dist/chunk-PZ5AY32C.js +0 -10
  39. package/dist/chunk-ZRNG36LU.js.map +0 -1
  40. /package/dist/{chunk-5MAHIPFH.js.map → chunk-LW7DPKBA.js.map} +0 -0
  41. /package/dist/{chunk-PZ5AY32C.js.map → chunk-NSBPE2FW.js.map} +0 -0
  42. /package/dist/{esm-POMEQPKL.js.map → esm-KBPHCVB4.js.map} +0 -0
  43. /package/dist/{getMachineId-bsd-TC3JSTY5.js.map → getMachineId-bsd-345PYXFX.js.map} +0 -0
  44. /package/dist/{getMachineId-darwin-2SUKQCE6.js.map → getMachineId-darwin-5L2D25AD.js.map} +0 -0
  45. /package/dist/{getMachineId-linux-PNAFHLXH.js.map → getMachineId-linux-KJR4P5HN.js.map} +0 -0
  46. /package/dist/{getMachineId-unsupported-L2MNYW3W.js.map → getMachineId-unsupported-NDNXDYDY.js.map} +0 -0
  47. /package/dist/{getMachineId-win-D6D42WOQ.js.map → getMachineId-win-T7PJNJXG.js.map} +0 -0
  48. /package/dist/{source-map-uploader-OA5NCDOK.js.map → source-map-uploader-ZFCYOURS.js.map} +0 -0
package/dist/cli/init.cjs CHANGED
@@ -14792,7 +14792,9 @@ var init_dist = __esm({
14792
14792
  });
14793
14793
  DiscoveryResponseSchema = external_exports.object({
14794
14794
  key: AnonApiKeySchema,
14795
- sessionId: SessionIdSchema
14795
+ sessionId: SessionIdSchema,
14796
+ claimed: external_exports.boolean().optional(),
14797
+ accountHint: external_exports.string().optional()
14796
14798
  });
14797
14799
  SourceMapUploadResponseSchema = external_exports.object({
14798
14800
  success: external_exports.literal(true),
@@ -14843,16 +14845,33 @@ var init_dist = __esm({
14843
14845
  });
14844
14846
 
14845
14847
  // src/anon-key.ts
14848
+ async function loadFsPath() {
14849
+ if (fsPathCache !== void 0) return fsPathCache;
14850
+ try {
14851
+ const [fs7, path7] = await Promise.all([
14852
+ import("fs/promises"),
14853
+ import("path")
14854
+ ]);
14855
+ fsPathCache = { fs: fs7, path: path7 };
14856
+ return fsPathCache;
14857
+ } catch {
14858
+ fsPathCache = null;
14859
+ return null;
14860
+ }
14861
+ }
14846
14862
  async function readAnonKey(projectRoot) {
14847
14863
  const root = projectRoot ?? process.cwd();
14848
- const keyPath = (0, import_node_path.join)(root, GLASSTRACE_DIR, ANON_KEY_FILE);
14849
- try {
14850
- const content = await (0, import_promises.readFile)(keyPath, "utf-8");
14851
- const result = AnonApiKeySchema.safeParse(content);
14852
- if (result.success) {
14853
- return result.data;
14864
+ const modules = await loadFsPath();
14865
+ if (modules) {
14866
+ const keyPath = modules.path.join(root, GLASSTRACE_DIR, ANON_KEY_FILE);
14867
+ try {
14868
+ const content = await modules.fs.readFile(keyPath, "utf-8");
14869
+ const result = AnonApiKeySchema.safeParse(content);
14870
+ if (result.success) {
14871
+ return result.data;
14872
+ }
14873
+ } catch {
14854
14874
  }
14855
- } catch {
14856
14875
  }
14857
14876
  const cached2 = ephemeralKeyCache.get(root);
14858
14877
  if (cached2 !== void 0) {
@@ -14862,8 +14881,6 @@ async function readAnonKey(projectRoot) {
14862
14881
  }
14863
14882
  async function getOrCreateAnonKey(projectRoot) {
14864
14883
  const root = projectRoot ?? process.cwd();
14865
- const dirPath = (0, import_node_path.join)(root, GLASSTRACE_DIR);
14866
- const keyPath = (0, import_node_path.join)(dirPath, ANON_KEY_FILE);
14867
14884
  const existingKey = await readAnonKey(root);
14868
14885
  if (existingKey !== null) {
14869
14886
  return existingKey;
@@ -14873,9 +14890,16 @@ async function getOrCreateAnonKey(projectRoot) {
14873
14890
  return cached2;
14874
14891
  }
14875
14892
  const newKey = createAnonApiKey();
14893
+ const modules = await loadFsPath();
14894
+ if (!modules) {
14895
+ ephemeralKeyCache.set(root, newKey);
14896
+ return newKey;
14897
+ }
14898
+ const dirPath = modules.path.join(root, GLASSTRACE_DIR);
14899
+ const keyPath = modules.path.join(dirPath, ANON_KEY_FILE);
14876
14900
  try {
14877
- await (0, import_promises.mkdir)(dirPath, { recursive: true, mode: 448 });
14878
- await (0, import_promises.writeFile)(keyPath, newKey, { flag: "wx", mode: 384 });
14901
+ await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
14902
+ await modules.fs.writeFile(keyPath, newKey, { flag: "wx", mode: 384 });
14879
14903
  return newKey;
14880
14904
  } catch (err) {
14881
14905
  const code = err.code;
@@ -14890,8 +14914,8 @@ async function getOrCreateAnonKey(projectRoot) {
14890
14914
  }
14891
14915
  }
14892
14916
  try {
14893
- await (0, import_promises.writeFile)(keyPath, newKey, { mode: 384 });
14894
- await (0, import_promises.chmod)(keyPath, 384);
14917
+ await modules.fs.writeFile(keyPath, newKey, { mode: 384 });
14918
+ await modules.fs.chmod(keyPath, 384);
14895
14919
  return newKey;
14896
14920
  } catch {
14897
14921
  }
@@ -14903,12 +14927,10 @@ async function getOrCreateAnonKey(projectRoot) {
14903
14927
  return newKey;
14904
14928
  }
14905
14929
  }
14906
- var import_promises, import_node_path, GLASSTRACE_DIR, ANON_KEY_FILE, ephemeralKeyCache;
14930
+ var GLASSTRACE_DIR, ANON_KEY_FILE, fsPathCache, ephemeralKeyCache;
14907
14931
  var init_anon_key = __esm({
14908
14932
  "src/anon-key.ts"() {
14909
14933
  "use strict";
14910
- import_promises = require("fs/promises");
14911
- import_node_path = require("path");
14912
14934
  init_dist();
14913
14935
  GLASSTRACE_DIR = ".glasstrace";
14914
14936
  ANON_KEY_FILE = "anon_key";
@@ -14919,25 +14941,25 @@ var init_anon_key = __esm({
14919
14941
  // src/agent-detection/detect.ts
14920
14942
  async function pathExists(path7, mode = import_node_fs.constants.R_OK) {
14921
14943
  try {
14922
- await (0, import_promises2.access)(path7, mode);
14944
+ await (0, import_promises.access)(path7, mode);
14923
14945
  return true;
14924
14946
  } catch {
14925
14947
  return false;
14926
14948
  }
14927
14949
  }
14928
14950
  async function findGitRoot(startDir) {
14929
- let current = (0, import_node_path2.resolve)(startDir);
14951
+ let current = (0, import_node_path.resolve)(startDir);
14930
14952
  while (true) {
14931
- if (await pathExists((0, import_node_path2.join)(current, ".git"), import_node_fs.constants.F_OK)) {
14953
+ if (await pathExists((0, import_node_path.join)(current, ".git"), import_node_fs.constants.F_OK)) {
14932
14954
  return current;
14933
14955
  }
14934
- const parent = (0, import_node_path2.dirname)(current);
14956
+ const parent = (0, import_node_path.dirname)(current);
14935
14957
  if (parent === current) {
14936
14958
  break;
14937
14959
  }
14938
14960
  current = parent;
14939
14961
  }
14940
- return (0, import_node_path2.resolve)(startDir);
14962
+ return (0, import_node_path.resolve)(startDir);
14941
14963
  }
14942
14964
  function isCliAvailable(binary) {
14943
14965
  return new Promise((resolve2) => {
@@ -14948,10 +14970,10 @@ function isCliAvailable(binary) {
14948
14970
  });
14949
14971
  }
14950
14972
  async function detectAgents(projectRoot) {
14951
- const resolvedRoot = (0, import_node_path2.resolve)(projectRoot);
14973
+ const resolvedRoot = (0, import_node_path.resolve)(projectRoot);
14952
14974
  let rootStat;
14953
14975
  try {
14954
- rootStat = await (0, import_promises2.stat)(resolvedRoot);
14976
+ rootStat = await (0, import_promises.stat)(resolvedRoot);
14955
14977
  } catch (err) {
14956
14978
  const code = err.code;
14957
14979
  throw new Error(
@@ -14969,7 +14991,7 @@ async function detectAgents(projectRoot) {
14969
14991
  if (current === gitRoot) {
14970
14992
  break;
14971
14993
  }
14972
- const parent = (0, import_node_path2.dirname)(current);
14994
+ const parent = (0, import_node_path.dirname)(current);
14973
14995
  if (parent === current) {
14974
14996
  break;
14975
14997
  }
@@ -14982,7 +15004,7 @@ async function detectAgents(projectRoot) {
14982
15004
  for (const dir of searchDirs) {
14983
15005
  let markerFound = false;
14984
15006
  for (const marker of rule.markers) {
14985
- if (await pathExists((0, import_node_path2.join)(dir, marker))) {
15007
+ if (await pathExists((0, import_node_path.join)(dir, marker))) {
14986
15008
  markerFound = true;
14987
15009
  break;
14988
15010
  }
@@ -15014,43 +15036,43 @@ async function detectAgents(projectRoot) {
15014
15036
  }
15015
15037
  detected.push({
15016
15038
  name: "generic",
15017
- mcpConfigPath: (0, import_node_path2.join)(resolvedRoot, ".glasstrace", "mcp.json"),
15039
+ mcpConfigPath: (0, import_node_path.join)(resolvedRoot, ".glasstrace", "mcp.json"),
15018
15040
  infoFilePath: null,
15019
15041
  cliAvailable: false,
15020
15042
  registrationCommand: null
15021
15043
  });
15022
15044
  return detected;
15023
15045
  }
15024
- var import_node_child_process, import_promises2, import_node_path2, import_node_os, import_node_fs, AGENT_RULES;
15046
+ var import_node_child_process, import_promises, import_node_path, import_node_os, import_node_fs, AGENT_RULES;
15025
15047
  var init_detect = __esm({
15026
15048
  "src/agent-detection/detect.ts"() {
15027
15049
  "use strict";
15028
15050
  import_node_child_process = require("child_process");
15029
- import_promises2 = require("fs/promises");
15030
- import_node_path2 = require("path");
15051
+ import_promises = require("fs/promises");
15052
+ import_node_path = require("path");
15031
15053
  import_node_os = require("os");
15032
15054
  import_node_fs = require("fs");
15033
15055
  AGENT_RULES = [
15034
15056
  {
15035
15057
  name: "claude",
15036
15058
  markers: [".claude", "CLAUDE.md"],
15037
- mcpConfigPath: (dir) => (0, import_node_path2.join)(dir, ".mcp.json"),
15038
- infoFilePath: (dir) => (0, import_node_path2.join)(dir, "CLAUDE.md"),
15059
+ mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".mcp.json"),
15060
+ infoFilePath: (dir) => (0, import_node_path.join)(dir, "CLAUDE.md"),
15039
15061
  cliBinary: "claude",
15040
15062
  registrationCommand: "npx glasstrace mcp add --agent claude"
15041
15063
  },
15042
15064
  {
15043
15065
  name: "codex",
15044
15066
  markers: ["codex.md", ".codex"],
15045
- mcpConfigPath: (dir) => (0, import_node_path2.join)(dir, ".codex", "config.toml"),
15046
- infoFilePath: (dir) => (0, import_node_path2.join)(dir, "codex.md"),
15067
+ mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".codex", "config.toml"),
15068
+ infoFilePath: (dir) => (0, import_node_path.join)(dir, "codex.md"),
15047
15069
  cliBinary: "codex",
15048
15070
  registrationCommand: "npx glasstrace mcp add --agent codex"
15049
15071
  },
15050
15072
  {
15051
15073
  name: "gemini",
15052
15074
  markers: [".gemini"],
15053
- mcpConfigPath: (dir) => (0, import_node_path2.join)(dir, ".gemini", "settings.json"),
15075
+ mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".gemini", "settings.json"),
15054
15076
  infoFilePath: () => null,
15055
15077
  cliBinary: "gemini",
15056
15078
  registrationCommand: "npx glasstrace mcp add --agent gemini"
@@ -15058,16 +15080,16 @@ var init_detect = __esm({
15058
15080
  {
15059
15081
  name: "cursor",
15060
15082
  markers: [".cursor", ".cursorrules"],
15061
- mcpConfigPath: (dir) => (0, import_node_path2.join)(dir, ".cursor", "mcp.json"),
15062
- infoFilePath: (dir) => (0, import_node_path2.join)(dir, ".cursorrules"),
15083
+ mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".cursor", "mcp.json"),
15084
+ infoFilePath: (dir) => (0, import_node_path.join)(dir, ".cursorrules"),
15063
15085
  cliBinary: null,
15064
15086
  registrationCommand: "npx glasstrace mcp add --agent cursor"
15065
15087
  },
15066
15088
  {
15067
15089
  name: "windsurf",
15068
15090
  markers: [".windsurfrules", ".windsurf"],
15069
- mcpConfigPath: () => (0, import_node_path2.join)((0, import_node_os.homedir)(), ".codeium", "windsurf", "mcp_config.json"),
15070
- infoFilePath: (dir) => (0, import_node_path2.join)(dir, ".windsurfrules"),
15091
+ mcpConfigPath: () => (0, import_node_path.join)((0, import_node_os.homedir)(), ".codeium", "windsurf", "mcp_config.json"),
15092
+ infoFilePath: (dir) => (0, import_node_path.join)(dir, ".windsurfrules"),
15071
15093
  cliBinary: null,
15072
15094
  registrationCommand: "npx glasstrace mcp add --agent windsurf"
15073
15095
  }
@@ -15252,9 +15274,9 @@ async function writeMcpConfig(agent, content, projectRoot) {
15252
15274
  return;
15253
15275
  }
15254
15276
  const configPath = agent.mcpConfigPath;
15255
- const parentDir = (0, import_node_path3.dirname)(configPath);
15277
+ const parentDir = (0, import_node_path2.dirname)(configPath);
15256
15278
  try {
15257
- await (0, import_promises3.mkdir)(parentDir, { recursive: true });
15279
+ await (0, import_promises2.mkdir)(parentDir, { recursive: true });
15258
15280
  } catch (err) {
15259
15281
  if (isPermissionError(err)) {
15260
15282
  process.stderr.write(
@@ -15266,7 +15288,7 @@ async function writeMcpConfig(agent, content, projectRoot) {
15266
15288
  throw err;
15267
15289
  }
15268
15290
  try {
15269
- await (0, import_promises3.writeFile)(configPath, content, { mode: 384 });
15291
+ await (0, import_promises2.writeFile)(configPath, content, { mode: 384 });
15270
15292
  } catch (err) {
15271
15293
  if (isPermissionError(err)) {
15272
15294
  process.stderr.write(
@@ -15278,7 +15300,7 @@ async function writeMcpConfig(agent, content, projectRoot) {
15278
15300
  throw err;
15279
15301
  }
15280
15302
  try {
15281
- await (0, import_promises3.chmod)(configPath, 384);
15303
+ await (0, import_promises2.chmod)(configPath, 384);
15282
15304
  } catch {
15283
15305
  }
15284
15306
  }
@@ -15311,7 +15333,7 @@ async function injectInfoSection(agent, content, projectRoot) {
15311
15333
  const filePath = agent.infoFilePath;
15312
15334
  let existingContent = null;
15313
15335
  try {
15314
- existingContent = await (0, import_promises3.readFile)(filePath, "utf-8");
15336
+ existingContent = await (0, import_promises2.readFile)(filePath, "utf-8");
15315
15337
  } catch (err) {
15316
15338
  const code = err.code;
15317
15339
  if (code !== "ENOENT") {
@@ -15327,8 +15349,8 @@ async function injectInfoSection(agent, content, projectRoot) {
15327
15349
  }
15328
15350
  if (existingContent === null) {
15329
15351
  try {
15330
- await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(filePath), { recursive: true });
15331
- await (0, import_promises3.writeFile)(filePath, content, "utf-8");
15352
+ await (0, import_promises2.mkdir)((0, import_node_path2.dirname)(filePath), { recursive: true });
15353
+ await (0, import_promises2.writeFile)(filePath, content, "utf-8");
15332
15354
  } catch (err) {
15333
15355
  if (isPermissionError(err)) {
15334
15356
  process.stderr.write(
@@ -15354,7 +15376,7 @@ async function injectInfoSection(agent, content, projectRoot) {
15354
15376
  newContent = existingContent + separator + content;
15355
15377
  }
15356
15378
  try {
15357
- await (0, import_promises3.writeFile)(filePath, newContent, "utf-8");
15379
+ await (0, import_promises2.writeFile)(filePath, newContent, "utf-8");
15358
15380
  } catch (err) {
15359
15381
  if (isPermissionError(err)) {
15360
15382
  process.stderr.write(
@@ -15367,14 +15389,14 @@ async function injectInfoSection(agent, content, projectRoot) {
15367
15389
  }
15368
15390
  }
15369
15391
  async function updateGitignore(paths, projectRoot) {
15370
- const gitignorePath = (0, import_node_path3.join)(projectRoot, ".gitignore");
15371
- const relativePaths = paths.filter((p) => !(0, import_node_path3.isAbsolute)(p));
15392
+ const gitignorePath = (0, import_node_path2.join)(projectRoot, ".gitignore");
15393
+ const relativePaths = paths.filter((p) => !(0, import_node_path2.isAbsolute)(p));
15372
15394
  if (relativePaths.length === 0) {
15373
15395
  return;
15374
15396
  }
15375
15397
  let existingContent = "";
15376
15398
  try {
15377
- existingContent = await (0, import_promises3.readFile)(gitignorePath, "utf-8");
15399
+ existingContent = await (0, import_promises2.readFile)(gitignorePath, "utf-8");
15378
15400
  } catch (err) {
15379
15401
  const code = err.code;
15380
15402
  if (code !== "ENOENT") {
@@ -15400,7 +15422,7 @@ async function updateGitignore(paths, projectRoot) {
15400
15422
  }
15401
15423
  updatedContent += toAdd.join("\n") + "\n";
15402
15424
  try {
15403
- await (0, import_promises3.writeFile)(gitignorePath, updatedContent, "utf-8");
15425
+ await (0, import_promises2.writeFile)(gitignorePath, updatedContent, "utf-8");
15404
15426
  } catch (err) {
15405
15427
  if (isPermissionError(err)) {
15406
15428
  process.stderr.write(
@@ -15412,12 +15434,12 @@ async function updateGitignore(paths, projectRoot) {
15412
15434
  throw err;
15413
15435
  }
15414
15436
  }
15415
- var import_promises3, import_node_path3, HTML_START, HTML_END, HASH_START, HASH_END;
15437
+ var import_promises2, import_node_path2, HTML_START, HTML_END, HASH_START, HASH_END;
15416
15438
  var init_inject = __esm({
15417
15439
  "src/agent-detection/inject.ts"() {
15418
15440
  "use strict";
15419
- import_promises3 = require("fs/promises");
15420
- import_node_path3 = require("path");
15441
+ import_promises2 = require("fs/promises");
15442
+ import_node_path2 = require("path");
15421
15443
  HTML_START = "<!-- glasstrace:mcp:start -->";
15422
15444
  HTML_END = "<!-- glasstrace:mcp:end -->";
15423
15445
  HASH_START = "# glasstrace:mcp:start";
@@ -15425,236 +15447,6 @@ var init_inject = __esm({
15425
15447
  }
15426
15448
  });
15427
15449
 
15428
- // src/cli/mcp-add.ts
15429
- var mcp_add_exports = {};
15430
- __export(mcp_add_exports, {
15431
- mcpAdd: () => mcpAdd
15432
- });
15433
- async function registerViaCli(agent, anonKey) {
15434
- if (!agent.cliAvailable) {
15435
- return false;
15436
- }
15437
- try {
15438
- switch (agent.name) {
15439
- case "claude": {
15440
- const payload = JSON.stringify({
15441
- type: "http",
15442
- url: MCP_ENDPOINT,
15443
- headers: { Authorization: `Bearer ${anonKey}` }
15444
- });
15445
- await execFileAsync("claude", [
15446
- "mcp",
15447
- "add-json",
15448
- "glasstrace",
15449
- payload,
15450
- "--scope",
15451
- "project"
15452
- ]);
15453
- return true;
15454
- }
15455
- case "codex": {
15456
- await execFileAsync("codex", [
15457
- "mcp",
15458
- "add",
15459
- "glasstrace",
15460
- "--url",
15461
- MCP_ENDPOINT
15462
- ]);
15463
- const configPath = agent.mcpConfigPath;
15464
- if (configPath !== null && fs4.existsSync(configPath)) {
15465
- const content = fs4.readFileSync(configPath, "utf-8");
15466
- if (!content.includes("bearer_token_env_var")) {
15467
- const appendContent = content.endsWith("\n") ? "" : "\n";
15468
- fs4.writeFileSync(
15469
- configPath,
15470
- content + appendContent + 'bearer_token_env_var = "GLASSTRACE_API_KEY"\n',
15471
- "utf-8"
15472
- );
15473
- }
15474
- }
15475
- process.stderr.write(
15476
- " Note: Set GLASSTRACE_API_KEY environment variable for Codex authentication.\n"
15477
- );
15478
- return true;
15479
- }
15480
- case "gemini": {
15481
- await execFileAsync("gemini", [
15482
- "mcp",
15483
- "add",
15484
- "--transport",
15485
- "http",
15486
- "--header",
15487
- `Authorization: Bearer ${anonKey}`,
15488
- "glasstrace",
15489
- MCP_ENDPOINT
15490
- ]);
15491
- return true;
15492
- }
15493
- default:
15494
- return false;
15495
- }
15496
- } catch {
15497
- return false;
15498
- }
15499
- }
15500
- async function mcpAdd(options) {
15501
- const force = options?.force ?? false;
15502
- const dryRun = options?.dryRun ?? false;
15503
- const projectRoot = process.cwd();
15504
- const messages = [];
15505
- const anonKey = await readAnonKey(projectRoot);
15506
- if (anonKey === null) {
15507
- return {
15508
- exitCode: 1,
15509
- results: [],
15510
- messages: ["Error: Run `glasstrace init` first to generate an API key."]
15511
- };
15512
- }
15513
- const markerPath = path4.join(projectRoot, ".glasstrace", "mcp-connected");
15514
- if (fs4.existsSync(markerPath) && !force) {
15515
- return {
15516
- exitCode: 0,
15517
- results: [],
15518
- messages: ["MCP already configured. Use --force to reconfigure."]
15519
- };
15520
- }
15521
- const agents = await detectAgents(projectRoot);
15522
- const detectedNonGeneric = agents.filter((a) => a.name !== "generic");
15523
- const targetAgents = detectedNonGeneric.length > 0 ? detectedNonGeneric : agents.filter((a) => a.name === "generic");
15524
- if (dryRun) {
15525
- messages.push("Dry run: would perform the following actions:", "");
15526
- for (const agent of targetAgents) {
15527
- const name = formatAgentName(agent.name);
15528
- if (agent.cliAvailable) {
15529
- messages.push(
15530
- ` ${name}: Register via CLI (${agent.name} mcp add)`
15531
- );
15532
- } else if (agent.mcpConfigPath !== null) {
15533
- messages.push(
15534
- ` ${name}: Write config to ${agent.mcpConfigPath}`
15535
- );
15536
- }
15537
- if (agent.infoFilePath !== null) {
15538
- messages.push(
15539
- ` ${name}: Inject info section into ${agent.infoFilePath}`
15540
- );
15541
- }
15542
- }
15543
- messages.push(
15544
- "",
15545
- " Update .gitignore with MCP config paths",
15546
- " Create .glasstrace/mcp-connected marker"
15547
- );
15548
- return { exitCode: 0, results: [], messages };
15549
- }
15550
- const results = [];
15551
- for (const agent of targetAgents) {
15552
- const name = formatAgentName(agent.name);
15553
- if (agent.name !== "generic") {
15554
- const cliSuccess = await registerViaCli(agent, anonKey);
15555
- if (cliSuccess) {
15556
- const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
15557
- if (infoContent !== "") {
15558
- await injectInfoSection(agent, infoContent, projectRoot);
15559
- }
15560
- results.push({
15561
- agent: agent.name,
15562
- success: true,
15563
- method: "cli",
15564
- message: `${name}: Registered via CLI`
15565
- });
15566
- continue;
15567
- }
15568
- }
15569
- if (agent.mcpConfigPath !== null) {
15570
- try {
15571
- const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);
15572
- await writeMcpConfig(agent, configContent, projectRoot);
15573
- if (fs4.existsSync(agent.mcpConfigPath)) {
15574
- const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
15575
- if (infoContent !== "") {
15576
- await injectInfoSection(agent, infoContent, projectRoot);
15577
- }
15578
- results.push({
15579
- agent: agent.name,
15580
- success: true,
15581
- method: "file",
15582
- message: `${name}: Configured via ${agent.mcpConfigPath}`
15583
- });
15584
- continue;
15585
- }
15586
- results.push({
15587
- agent: agent.name,
15588
- success: false,
15589
- method: "file",
15590
- message: `${name}: Failed to write config to ${agent.mcpConfigPath} (permission denied)`
15591
- });
15592
- continue;
15593
- } catch (err) {
15594
- results.push({
15595
- agent: agent.name,
15596
- success: false,
15597
- method: "file",
15598
- message: `${name}: Failed - ${err instanceof Error ? err.message : String(err)}`
15599
- });
15600
- continue;
15601
- }
15602
- }
15603
- results.push({
15604
- agent: agent.name,
15605
- success: false,
15606
- method: "skipped",
15607
- message: `${name}: No registration method available`
15608
- });
15609
- }
15610
- await updateGitignore(
15611
- [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json", ".codex/config.toml"],
15612
- projectRoot
15613
- );
15614
- const anySuccess = results.some((r) => r.success);
15615
- if (anySuccess) {
15616
- await scaffoldMcpMarker(projectRoot, anonKey);
15617
- }
15618
- messages.push("", "MCP registration summary:");
15619
- for (const result of results) {
15620
- const icon = result.success ? "+" : "-";
15621
- messages.push(` [${icon}] ${result.message}`);
15622
- }
15623
- if (results.length === 0) {
15624
- messages.push(
15625
- " No agents detected. Place agent marker files (e.g., CLAUDE.md, .cursor/) in your project."
15626
- );
15627
- }
15628
- if (!anySuccess && results.length > 0) {
15629
- messages.push(
15630
- "",
15631
- "All agent registrations failed. Check errors above."
15632
- );
15633
- return { exitCode: 1, results, messages };
15634
- }
15635
- if (anySuccess) {
15636
- messages.push("", "MCP registration complete.");
15637
- }
15638
- return { exitCode: 0, results, messages };
15639
- }
15640
- var import_node_child_process2, fs4, path4, import_node_util, execFileAsync;
15641
- var init_mcp_add = __esm({
15642
- "src/cli/mcp-add.ts"() {
15643
- "use strict";
15644
- import_node_child_process2 = require("child_process");
15645
- fs4 = __toESM(require("fs"), 1);
15646
- path4 = __toESM(require("path"), 1);
15647
- import_node_util = require("util");
15648
- init_anon_key();
15649
- init_detect();
15650
- init_configs();
15651
- init_inject();
15652
- init_scaffolder();
15653
- init_constants();
15654
- execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
15655
- }
15656
- });
15657
-
15658
15450
  // src/cli/uninit.ts
15659
15451
  var uninit_exports = {};
15660
15452
  __export(uninit_exports, {
@@ -15979,11 +15771,11 @@ async function runUninit(options) {
15979
15771
  try {
15980
15772
  let configHandled = false;
15981
15773
  for (const name of NEXT_CONFIG_NAMES) {
15982
- const configPath = path5.join(projectRoot, name);
15983
- if (!fs5.existsSync(configPath)) {
15774
+ const configPath = path4.join(projectRoot, name);
15775
+ if (!fs4.existsSync(configPath)) {
15984
15776
  continue;
15985
15777
  }
15986
- const content = fs5.readFileSync(configPath, "utf-8");
15778
+ const content = fs4.readFileSync(configPath, "utf-8");
15987
15779
  if (!content.includes("withGlasstraceConfig")) {
15988
15780
  continue;
15989
15781
  }
@@ -15993,7 +15785,7 @@ async function runUninit(options) {
15993
15785
  const cleaned = removeGlasstraceConfigImport(unwrapResult.content);
15994
15786
  const final = cleanLeadingBlankLines(cleaned);
15995
15787
  if (!dryRun) {
15996
- fs5.writeFileSync(configPath, final, "utf-8");
15788
+ fs4.writeFileSync(configPath, final, "utf-8");
15997
15789
  }
15998
15790
  summary.push(`${prefix}Unwrapped withGlasstraceConfig from ${name}`);
15999
15791
  configHandled = true;
@@ -16014,20 +15806,20 @@ async function runUninit(options) {
16014
15806
  );
16015
15807
  }
16016
15808
  try {
16017
- const instrPath = path5.join(projectRoot, "instrumentation.ts");
16018
- if (fs5.existsSync(instrPath)) {
16019
- const content = fs5.readFileSync(instrPath, "utf-8");
15809
+ const instrPath = path4.join(projectRoot, "instrumentation.ts");
15810
+ if (fs4.existsSync(instrPath)) {
15811
+ const content = fs4.readFileSync(instrPath, "utf-8");
16020
15812
  if (content.includes("registerGlasstrace") || content.includes("@glasstrace/sdk")) {
16021
15813
  if (isInitCreatedInstrumentation(content)) {
16022
15814
  if (!dryRun) {
16023
- fs5.unlinkSync(instrPath);
15815
+ fs4.unlinkSync(instrPath);
16024
15816
  }
16025
15817
  summary.push(`${prefix}Deleted instrumentation.ts (init-created)`);
16026
15818
  } else {
16027
15819
  const cleaned = removeRegisterGlasstrace(content);
16028
15820
  if (cleaned !== content) {
16029
15821
  if (!dryRun) {
16030
- fs5.writeFileSync(instrPath, cleaned, "utf-8");
15822
+ fs4.writeFileSync(instrPath, cleaned, "utf-8");
16031
15823
  }
16032
15824
  summary.push(
16033
15825
  `${prefix}Removed registerGlasstrace() from instrumentation.ts`
@@ -16042,10 +15834,10 @@ async function runUninit(options) {
16042
15834
  );
16043
15835
  }
16044
15836
  try {
16045
- const glasstraceDir = path5.join(projectRoot, ".glasstrace");
16046
- if (fs5.existsSync(glasstraceDir)) {
15837
+ const glasstraceDir = path4.join(projectRoot, ".glasstrace");
15838
+ if (fs4.existsSync(glasstraceDir)) {
16047
15839
  if (!dryRun) {
16048
- fs5.rmSync(glasstraceDir, { recursive: true, force: true });
15840
+ fs4.rmSync(glasstraceDir, { recursive: true, force: true });
16049
15841
  }
16050
15842
  summary.push(`${prefix}Removed .glasstrace/ directory`);
16051
15843
  }
@@ -16055,9 +15847,9 @@ async function runUninit(options) {
16055
15847
  );
16056
15848
  }
16057
15849
  try {
16058
- const envPath = path5.join(projectRoot, ".env.local");
16059
- if (fs5.existsSync(envPath)) {
16060
- const content = fs5.readFileSync(envPath, "utf-8");
15850
+ const envPath = path4.join(projectRoot, ".env.local");
15851
+ if (fs4.existsSync(envPath)) {
15852
+ const content = fs4.readFileSync(envPath, "utf-8");
16061
15853
  const lines = content.split("\n");
16062
15854
  const filtered = lines.filter((line) => {
16063
15855
  const trimmed = line.trim();
@@ -16067,12 +15859,12 @@ async function runUninit(options) {
16067
15859
  const result = filtered.join("\n");
16068
15860
  if (result.trim().length === 0) {
16069
15861
  if (!dryRun) {
16070
- fs5.unlinkSync(envPath);
15862
+ fs4.unlinkSync(envPath);
16071
15863
  }
16072
15864
  summary.push(`${prefix}Deleted .env.local (no remaining entries)`);
16073
15865
  } else {
16074
15866
  if (!dryRun) {
16075
- fs5.writeFileSync(envPath, result, "utf-8");
15867
+ fs4.writeFileSync(envPath, result, "utf-8");
16076
15868
  }
16077
15869
  summary.push(`${prefix}Removed GLASSTRACE entries from .env.local`);
16078
15870
  }
@@ -16084,9 +15876,9 @@ async function runUninit(options) {
16084
15876
  );
16085
15877
  }
16086
15878
  try {
16087
- const gitignorePath = path5.join(projectRoot, ".gitignore");
16088
- if (fs5.existsSync(gitignorePath)) {
16089
- const content = fs5.readFileSync(gitignorePath, "utf-8");
15879
+ const gitignorePath = path4.join(projectRoot, ".gitignore");
15880
+ if (fs4.existsSync(gitignorePath)) {
15881
+ const content = fs4.readFileSync(gitignorePath, "utf-8");
16090
15882
  const lines = content.split("\n");
16091
15883
  const mcpGitignoreEntries = /* @__PURE__ */ new Set([
16092
15884
  ".glasstrace/",
@@ -16102,12 +15894,12 @@ async function runUninit(options) {
16102
15894
  const result = filtered.join("\n");
16103
15895
  if (result.trim().length === 0) {
16104
15896
  if (!dryRun) {
16105
- fs5.unlinkSync(gitignorePath);
15897
+ fs4.unlinkSync(gitignorePath);
16106
15898
  }
16107
15899
  summary.push(`${prefix}Deleted .gitignore (no remaining entries)`);
16108
15900
  } else {
16109
15901
  if (!dryRun) {
16110
- fs5.writeFileSync(gitignorePath, result, "utf-8");
15902
+ fs4.writeFileSync(gitignorePath, result, "utf-8");
16111
15903
  }
16112
15904
  summary.push(`${prefix}Removed Glasstrace entries from .gitignore`);
16113
15905
  }
@@ -16120,63 +15912,63 @@ async function runUninit(options) {
16120
15912
  }
16121
15913
  try {
16122
15914
  for (const configFile of MCP_CONFIG_FILES) {
16123
- const configPath = path5.join(projectRoot, configFile);
16124
- if (!fs5.existsSync(configPath)) {
15915
+ const configPath = path4.join(projectRoot, configFile);
15916
+ if (!fs4.existsSync(configPath)) {
16125
15917
  continue;
16126
15918
  }
16127
- const content = fs5.readFileSync(configPath, "utf-8");
15919
+ const content = fs4.readFileSync(configPath, "utf-8");
16128
15920
  const result = processJsonMcpConfig(content);
16129
15921
  if (result.action === "deleted") {
16130
15922
  if (!dryRun) {
16131
- fs5.unlinkSync(configPath);
15923
+ fs4.unlinkSync(configPath);
16132
15924
  }
16133
15925
  summary.push(`${prefix}Deleted ${configFile}`);
16134
15926
  } else if (result.action === "removed-key" && result.content !== void 0) {
16135
15927
  if (!dryRun) {
16136
- fs5.writeFileSync(configPath, result.content, "utf-8");
15928
+ fs4.writeFileSync(configPath, result.content, "utf-8");
16137
15929
  }
16138
15930
  summary.push(`${prefix}Removed glasstrace from ${configFile}`);
16139
15931
  }
16140
15932
  }
16141
- const codexConfigPath = path5.join(projectRoot, ".codex", "config.toml");
16142
- if (fs5.existsSync(codexConfigPath)) {
16143
- const content = fs5.readFileSync(codexConfigPath, "utf-8");
15933
+ const codexConfigPath = path4.join(projectRoot, ".codex", "config.toml");
15934
+ if (fs4.existsSync(codexConfigPath)) {
15935
+ const content = fs4.readFileSync(codexConfigPath, "utf-8");
16144
15936
  const tomlResult = processTomlMcpConfig(content);
16145
15937
  if (tomlResult.action === "deleted") {
16146
15938
  if (!dryRun) {
16147
- fs5.unlinkSync(codexConfigPath);
15939
+ fs4.unlinkSync(codexConfigPath);
16148
15940
  }
16149
15941
  summary.push(`${prefix}Deleted .codex/config.toml`);
16150
15942
  } else if (tomlResult.action === "removed-section" && tomlResult.content !== void 0) {
16151
15943
  if (!dryRun) {
16152
- fs5.writeFileSync(codexConfigPath, tomlResult.content, "utf-8");
15944
+ fs4.writeFileSync(codexConfigPath, tomlResult.content, "utf-8");
16153
15945
  }
16154
15946
  summary.push(`${prefix}Removed glasstrace from .codex/config.toml`);
16155
15947
  }
16156
15948
  }
16157
- const hasWindsurfMarkers = fs5.existsSync(path5.join(projectRoot, ".windsurfrules")) || fs5.existsSync(path5.join(projectRoot, ".windsurf"));
15949
+ const hasWindsurfMarkers = fs4.existsSync(path4.join(projectRoot, ".windsurfrules")) || fs4.existsSync(path4.join(projectRoot, ".windsurf"));
16158
15950
  if (hasWindsurfMarkers) {
16159
- const windsurfConfigPath = path5.join(
15951
+ const windsurfConfigPath = path4.join(
16160
15952
  os.homedir(),
16161
15953
  ".codeium",
16162
15954
  "windsurf",
16163
15955
  "mcp_config.json"
16164
15956
  );
16165
- if (fs5.existsSync(windsurfConfigPath)) {
16166
- const content = fs5.readFileSync(windsurfConfigPath, "utf-8");
15957
+ if (fs4.existsSync(windsurfConfigPath)) {
15958
+ const content = fs4.readFileSync(windsurfConfigPath, "utf-8");
16167
15959
  const windsurfResult = processJsonMcpConfig(content);
16168
15960
  const home = os.homedir();
16169
15961
  const displayPath = windsurfConfigPath.startsWith(home) ? "~" + windsurfConfigPath.slice(home.length) : windsurfConfigPath;
16170
15962
  if (windsurfResult.action === "deleted") {
16171
15963
  if (!dryRun) {
16172
- fs5.unlinkSync(windsurfConfigPath);
15964
+ fs4.unlinkSync(windsurfConfigPath);
16173
15965
  }
16174
15966
  summary.push(
16175
15967
  `${prefix}Deleted global Windsurf config (${displayPath})`
16176
15968
  );
16177
15969
  } else if (windsurfResult.action === "removed-key" && windsurfResult.content !== void 0) {
16178
15970
  if (!dryRun) {
16179
- fs5.writeFileSync(windsurfConfigPath, windsurfResult.content, "utf-8");
15971
+ fs4.writeFileSync(windsurfConfigPath, windsurfResult.content, "utf-8");
16180
15972
  }
16181
15973
  summary.push(
16182
15974
  `${prefix}Removed glasstrace from global Windsurf config (${displayPath})`
@@ -16191,21 +15983,21 @@ async function runUninit(options) {
16191
15983
  }
16192
15984
  try {
16193
15985
  for (const infoFile of AGENT_INFO_FILES) {
16194
- const filePath = path5.join(projectRoot, infoFile);
16195
- if (!fs5.existsSync(filePath)) {
15986
+ const filePath = path4.join(projectRoot, infoFile);
15987
+ if (!fs4.existsSync(filePath)) {
16196
15988
  continue;
16197
15989
  }
16198
- const content = fs5.readFileSync(filePath, "utf-8");
15990
+ const content = fs4.readFileSync(filePath, "utf-8");
16199
15991
  const result = removeMarkerSection(content);
16200
15992
  if (result.removed) {
16201
15993
  if (result.content.trim().length === 0) {
16202
15994
  if (!dryRun) {
16203
- fs5.unlinkSync(filePath);
15995
+ fs4.unlinkSync(filePath);
16204
15996
  }
16205
15997
  summary.push(`${prefix}Deleted ${infoFile} (only contained Glasstrace section)`);
16206
15998
  } else {
16207
15999
  if (!dryRun) {
16208
- fs5.writeFileSync(filePath, result.content, "utf-8");
16000
+ fs4.writeFileSync(filePath, result.content, "utf-8");
16209
16001
  }
16210
16002
  summary.push(`${prefix}Removed Glasstrace section from ${infoFile}`);
16211
16003
  }
@@ -16221,13 +16013,13 @@ async function runUninit(options) {
16221
16013
  }
16222
16014
  return { exitCode: errors.length > 0 ? 1 : 0, summary, warnings, errors };
16223
16015
  }
16224
- var fs5, os, path5, MCP_CONFIG_FILES, AGENT_INFO_FILES;
16016
+ var fs4, os, path4, MCP_CONFIG_FILES, AGENT_INFO_FILES;
16225
16017
  var init_uninit = __esm({
16226
16018
  "src/cli/uninit.ts"() {
16227
16019
  "use strict";
16228
- fs5 = __toESM(require("fs"), 1);
16020
+ fs4 = __toESM(require("fs"), 1);
16229
16021
  os = __toESM(require("os"), 1);
16230
- path5 = __toESM(require("path"), 1);
16022
+ path4 = __toESM(require("path"), 1);
16231
16023
  init_constants();
16232
16024
  MCP_CONFIG_FILES = [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json"];
16233
16025
  AGENT_INFO_FILES = [
@@ -16238,10 +16030,241 @@ var init_uninit = __esm({
16238
16030
  }
16239
16031
  });
16240
16032
 
16033
+ // src/cli/mcp-add.ts
16034
+ var mcp_add_exports = {};
16035
+ __export(mcp_add_exports, {
16036
+ mcpAdd: () => mcpAdd
16037
+ });
16038
+ async function registerViaCli(agent, anonKey) {
16039
+ if (!agent.cliAvailable) {
16040
+ return false;
16041
+ }
16042
+ try {
16043
+ switch (agent.name) {
16044
+ case "claude": {
16045
+ const payload = JSON.stringify({
16046
+ type: "http",
16047
+ url: MCP_ENDPOINT,
16048
+ headers: { Authorization: `Bearer ${anonKey}` }
16049
+ });
16050
+ await execFileAsync("claude", [
16051
+ "mcp",
16052
+ "add-json",
16053
+ "glasstrace",
16054
+ payload,
16055
+ "--scope",
16056
+ "project"
16057
+ ]);
16058
+ return true;
16059
+ }
16060
+ case "codex": {
16061
+ await execFileAsync("codex", [
16062
+ "mcp",
16063
+ "add",
16064
+ "glasstrace",
16065
+ "--url",
16066
+ MCP_ENDPOINT
16067
+ ]);
16068
+ const configPath = agent.mcpConfigPath;
16069
+ if (configPath !== null && fs5.existsSync(configPath)) {
16070
+ const content = fs5.readFileSync(configPath, "utf-8");
16071
+ if (!content.includes("bearer_token_env_var")) {
16072
+ const appendContent = content.endsWith("\n") ? "" : "\n";
16073
+ fs5.writeFileSync(
16074
+ configPath,
16075
+ content + appendContent + 'bearer_token_env_var = "GLASSTRACE_API_KEY"\n',
16076
+ "utf-8"
16077
+ );
16078
+ }
16079
+ }
16080
+ process.stderr.write(
16081
+ " Note: Set GLASSTRACE_API_KEY environment variable for Codex authentication.\n"
16082
+ );
16083
+ return true;
16084
+ }
16085
+ case "gemini": {
16086
+ await execFileAsync("gemini", [
16087
+ "mcp",
16088
+ "add",
16089
+ "--transport",
16090
+ "http",
16091
+ "--header",
16092
+ `Authorization: Bearer ${anonKey}`,
16093
+ "glasstrace",
16094
+ MCP_ENDPOINT
16095
+ ]);
16096
+ return true;
16097
+ }
16098
+ default:
16099
+ return false;
16100
+ }
16101
+ } catch {
16102
+ return false;
16103
+ }
16104
+ }
16105
+ async function mcpAdd(options) {
16106
+ const force = options?.force ?? false;
16107
+ const dryRun = options?.dryRun ?? false;
16108
+ const projectRoot = process.cwd();
16109
+ const messages = [];
16110
+ const anonKey = await readAnonKey(projectRoot);
16111
+ if (anonKey === null) {
16112
+ return {
16113
+ exitCode: 1,
16114
+ results: [],
16115
+ messages: ["Error: Run `glasstrace init` first to generate an API key."]
16116
+ };
16117
+ }
16118
+ const markerPath = path5.join(projectRoot, ".glasstrace", "mcp-connected");
16119
+ if (fs5.existsSync(markerPath) && !force) {
16120
+ return {
16121
+ exitCode: 0,
16122
+ results: [],
16123
+ messages: ["MCP already configured. Use --force to reconfigure."]
16124
+ };
16125
+ }
16126
+ const agents = await detectAgents(projectRoot);
16127
+ const detectedNonGeneric = agents.filter((a) => a.name !== "generic");
16128
+ const targetAgents = detectedNonGeneric.length > 0 ? detectedNonGeneric : agents.filter((a) => a.name === "generic");
16129
+ if (dryRun) {
16130
+ messages.push("Dry run: would perform the following actions:", "");
16131
+ for (const agent of targetAgents) {
16132
+ const name = formatAgentName(agent.name);
16133
+ if (agent.cliAvailable) {
16134
+ messages.push(
16135
+ ` ${name}: Register via CLI (${agent.name} mcp add)`
16136
+ );
16137
+ } else if (agent.mcpConfigPath !== null) {
16138
+ messages.push(
16139
+ ` ${name}: Write config to ${agent.mcpConfigPath}`
16140
+ );
16141
+ }
16142
+ if (agent.infoFilePath !== null) {
16143
+ messages.push(
16144
+ ` ${name}: Inject info section into ${agent.infoFilePath}`
16145
+ );
16146
+ }
16147
+ }
16148
+ messages.push(
16149
+ "",
16150
+ " Update .gitignore with MCP config paths",
16151
+ " Create .glasstrace/mcp-connected marker"
16152
+ );
16153
+ return { exitCode: 0, results: [], messages };
16154
+ }
16155
+ const results = [];
16156
+ for (const agent of targetAgents) {
16157
+ const name = formatAgentName(agent.name);
16158
+ if (agent.name !== "generic") {
16159
+ const cliSuccess = await registerViaCli(agent, anonKey);
16160
+ if (cliSuccess) {
16161
+ const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
16162
+ if (infoContent !== "") {
16163
+ await injectInfoSection(agent, infoContent, projectRoot);
16164
+ }
16165
+ results.push({
16166
+ agent: agent.name,
16167
+ success: true,
16168
+ method: "cli",
16169
+ message: `${name}: Registered via CLI`
16170
+ });
16171
+ continue;
16172
+ }
16173
+ }
16174
+ if (agent.mcpConfigPath !== null) {
16175
+ try {
16176
+ const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);
16177
+ await writeMcpConfig(agent, configContent, projectRoot);
16178
+ if (fs5.existsSync(agent.mcpConfigPath)) {
16179
+ const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
16180
+ if (infoContent !== "") {
16181
+ await injectInfoSection(agent, infoContent, projectRoot);
16182
+ }
16183
+ results.push({
16184
+ agent: agent.name,
16185
+ success: true,
16186
+ method: "file",
16187
+ message: `${name}: Configured via ${agent.mcpConfigPath}`
16188
+ });
16189
+ continue;
16190
+ }
16191
+ results.push({
16192
+ agent: agent.name,
16193
+ success: false,
16194
+ method: "file",
16195
+ message: `${name}: Failed to write config to ${agent.mcpConfigPath} (permission denied)`
16196
+ });
16197
+ continue;
16198
+ } catch (err) {
16199
+ results.push({
16200
+ agent: agent.name,
16201
+ success: false,
16202
+ method: "file",
16203
+ message: `${name}: Failed - ${err instanceof Error ? err.message : String(err)}`
16204
+ });
16205
+ continue;
16206
+ }
16207
+ }
16208
+ results.push({
16209
+ agent: agent.name,
16210
+ success: false,
16211
+ method: "skipped",
16212
+ message: `${name}: No registration method available`
16213
+ });
16214
+ }
16215
+ await updateGitignore(
16216
+ [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json", ".codex/config.toml"],
16217
+ projectRoot
16218
+ );
16219
+ const anySuccess = results.some((r) => r.success);
16220
+ if (anySuccess) {
16221
+ await scaffoldMcpMarker(projectRoot, anonKey);
16222
+ }
16223
+ messages.push("", "MCP registration summary:");
16224
+ for (const result of results) {
16225
+ const icon = result.success ? "+" : "-";
16226
+ messages.push(` [${icon}] ${result.message}`);
16227
+ }
16228
+ if (results.length === 0) {
16229
+ messages.push(
16230
+ " No agents detected. Place agent marker files (e.g., CLAUDE.md, .cursor/) in your project."
16231
+ );
16232
+ }
16233
+ if (!anySuccess && results.length > 0) {
16234
+ messages.push(
16235
+ "",
16236
+ "All agent registrations failed. Check errors above."
16237
+ );
16238
+ return { exitCode: 1, results, messages };
16239
+ }
16240
+ if (anySuccess) {
16241
+ messages.push("", "MCP registration complete.");
16242
+ }
16243
+ return { exitCode: 0, results, messages };
16244
+ }
16245
+ var import_node_child_process2, fs5, path5, import_node_util, execFileAsync;
16246
+ var init_mcp_add = __esm({
16247
+ "src/cli/mcp-add.ts"() {
16248
+ "use strict";
16249
+ import_node_child_process2 = require("child_process");
16250
+ fs5 = __toESM(require("fs"), 1);
16251
+ path5 = __toESM(require("path"), 1);
16252
+ import_node_util = require("util");
16253
+ init_anon_key();
16254
+ init_detect();
16255
+ init_configs();
16256
+ init_inject();
16257
+ init_scaffolder();
16258
+ init_constants();
16259
+ execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
16260
+ }
16261
+ });
16262
+
16241
16263
  // src/cli/init.ts
16242
16264
  var init_exports = {};
16243
16265
  __export(init_exports, {
16244
16266
  meetsNodeVersion: () => meetsNodeVersion,
16267
+ rollbackSteps: () => rollbackSteps,
16245
16268
  runInit: () => runInit
16246
16269
  });
16247
16270
  module.exports = __toCommonJS(init_exports);
@@ -16659,6 +16682,7 @@ function walkDirectories(baseDir) {
16659
16682
  }
16660
16683
 
16661
16684
  // src/cli/init.ts
16685
+ init_uninit();
16662
16686
  function meetsNodeVersion(minMajor) {
16663
16687
  const [major] = process.versions.node.split(".").map(Number);
16664
16688
  return major >= minMajor;
@@ -16684,6 +16708,94 @@ async function promptYesNo(question, defaultValue) {
16684
16708
  });
16685
16709
  });
16686
16710
  }
16711
+ function cleanLeadingBlankLines2(content) {
16712
+ return content.replace(/^\n{2,}/, "\n");
16713
+ }
16714
+ async function rollbackSteps(steps, projectRoot, state) {
16715
+ for (const step of [...steps].reverse()) {
16716
+ try {
16717
+ switch (step) {
16718
+ case "instrumentation": {
16719
+ const instrPath = path6.join(projectRoot, "instrumentation.ts");
16720
+ if (fs6.existsSync(instrPath)) {
16721
+ const content = fs6.readFileSync(instrPath, "utf-8");
16722
+ if (isInitCreatedInstrumentation(content)) {
16723
+ fs6.unlinkSync(instrPath);
16724
+ } else if (state?.originalInstrumentationContent !== void 0) {
16725
+ fs6.writeFileSync(instrPath, state.originalInstrumentationContent, "utf-8");
16726
+ } else {
16727
+ const cleaned = removeRegisterGlasstrace(content);
16728
+ if (cleaned !== content) {
16729
+ fs6.writeFileSync(instrPath, cleaned, "utf-8");
16730
+ }
16731
+ }
16732
+ }
16733
+ break;
16734
+ }
16735
+ case "next-config": {
16736
+ for (const name of NEXT_CONFIG_NAMES) {
16737
+ const configPath = path6.join(projectRoot, name);
16738
+ if (!fs6.existsSync(configPath)) {
16739
+ continue;
16740
+ }
16741
+ const content = fs6.readFileSync(configPath, "utf-8");
16742
+ if (!content.includes("withGlasstraceConfig")) {
16743
+ continue;
16744
+ }
16745
+ const isESM = name.endsWith(".ts") || name.endsWith(".mjs");
16746
+ const unwrapResult = isESM ? unwrapExport(content) : unwrapCJSExport(content);
16747
+ if (unwrapResult.unwrapped) {
16748
+ const cleaned = removeGlasstraceConfigImport(unwrapResult.content);
16749
+ fs6.writeFileSync(configPath, cleanLeadingBlankLines2(cleaned), "utf-8");
16750
+ }
16751
+ break;
16752
+ }
16753
+ break;
16754
+ }
16755
+ case "env-local": {
16756
+ const envPath = path6.join(projectRoot, ".env.local");
16757
+ if (fs6.existsSync(envPath)) {
16758
+ const content = fs6.readFileSync(envPath, "utf-8");
16759
+ const lines = content.split("\n");
16760
+ const filtered = lines.filter((line) => {
16761
+ const trimmed = line.trim();
16762
+ return !/^\s*#?\s*GLASSTRACE_API_KEY\s*=/.test(trimmed);
16763
+ });
16764
+ if (filtered.length !== lines.length) {
16765
+ const result = filtered.join("\n");
16766
+ if (result.trim().length === 0) {
16767
+ fs6.unlinkSync(envPath);
16768
+ } else {
16769
+ fs6.writeFileSync(envPath, result, "utf-8");
16770
+ }
16771
+ }
16772
+ }
16773
+ break;
16774
+ }
16775
+ case "gitignore": {
16776
+ const gitignorePath = path6.join(projectRoot, ".gitignore");
16777
+ if (fs6.existsSync(gitignorePath)) {
16778
+ const content = fs6.readFileSync(gitignorePath, "utf-8");
16779
+ const lines = content.split("\n");
16780
+ const filtered = lines.filter(
16781
+ (line) => line.trim() !== ".glasstrace/"
16782
+ );
16783
+ if (filtered.length !== lines.length) {
16784
+ const result = filtered.join("\n");
16785
+ if (result.trim().length === 0) {
16786
+ fs6.unlinkSync(gitignorePath);
16787
+ } else {
16788
+ fs6.writeFileSync(gitignorePath, result, "utf-8");
16789
+ }
16790
+ }
16791
+ }
16792
+ break;
16793
+ }
16794
+ }
16795
+ } catch {
16796
+ }
16797
+ }
16798
+ }
16687
16799
  async function runInit(options) {
16688
16800
  const { yes, coverageMap } = options;
16689
16801
  const summary = [];
@@ -16705,14 +16817,21 @@ async function runInit(options) {
16705
16817
  errors.push("No package.json found. Run this command from a Node.js project root.");
16706
16818
  return { exitCode: 1, summary, warnings, errors };
16707
16819
  }
16820
+ const rollbackState = { steps: [] };
16708
16821
  try {
16822
+ const instrPath = path6.join(projectRoot, "instrumentation.ts");
16823
+ if (fs6.existsSync(instrPath)) {
16824
+ rollbackState.originalInstrumentationContent = fs6.readFileSync(instrPath, "utf-8");
16825
+ }
16709
16826
  const instrResult = await scaffoldInstrumentation(projectRoot);
16710
16827
  switch (instrResult.action) {
16711
16828
  case "created":
16712
16829
  summary.push("Created instrumentation.ts");
16830
+ rollbackState.steps.push("instrumentation");
16713
16831
  break;
16714
16832
  case "injected":
16715
16833
  summary.push("Added registerGlasstrace() to existing instrumentation.ts");
16834
+ rollbackState.steps.push("instrumentation");
16716
16835
  break;
16717
16836
  case "already-registered":
16718
16837
  summary.push("Skipped instrumentation.ts (registerGlasstrace already present)");
@@ -16724,6 +16843,7 @@ async function runInit(options) {
16724
16843
  break;
16725
16844
  }
16726
16845
  } catch (err) {
16846
+ await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
16727
16847
  errors.push(`Failed to write instrumentation.ts: ${err instanceof Error ? err.message : String(err)}`);
16728
16848
  return { exitCode: 1, summary, warnings, errors };
16729
16849
  }
@@ -16731,6 +16851,7 @@ async function runInit(options) {
16731
16851
  const configResult = await scaffoldNextConfig(projectRoot);
16732
16852
  if (configResult?.modified) {
16733
16853
  summary.push("Wrapped next.config with withGlasstraceConfig()");
16854
+ rollbackState.steps.push("next-config");
16734
16855
  } else if (configResult === null) {
16735
16856
  warnings.push("No next.config.* found. You may need to create one for Next.js projects.");
16736
16857
  } else if (configResult.reason === "already-wrapped") {
@@ -16741,6 +16862,7 @@ async function runInit(options) {
16741
16862
  warnings.push("next.config has no recognizable export pattern \u2014 add withGlasstraceConfig() manually");
16742
16863
  }
16743
16864
  } catch (err) {
16865
+ await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
16744
16866
  errors.push(`Failed to modify next.config: ${err instanceof Error ? err.message : String(err)}`);
16745
16867
  return { exitCode: 1, summary, warnings, errors };
16746
16868
  }
@@ -16748,10 +16870,12 @@ async function runInit(options) {
16748
16870
  const envCreated = await scaffoldEnvLocal(projectRoot);
16749
16871
  if (envCreated) {
16750
16872
  summary.push("Updated .env.local with Glasstrace configuration");
16873
+ rollbackState.steps.push("env-local");
16751
16874
  } else {
16752
16875
  summary.push("Skipped .env.local (GLASSTRACE_API_KEY already configured)");
16753
16876
  }
16754
16877
  } catch (err) {
16878
+ await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
16755
16879
  errors.push(`Failed to update .env.local: ${err instanceof Error ? err.message : String(err)}`);
16756
16880
  return { exitCode: 1, summary, warnings, errors };
16757
16881
  }
@@ -16759,10 +16883,12 @@ async function runInit(options) {
16759
16883
  const gitignoreUpdated = await scaffoldGitignore(projectRoot);
16760
16884
  if (gitignoreUpdated) {
16761
16885
  summary.push("Updated .gitignore with .glasstrace/");
16886
+ rollbackState.steps.push("gitignore");
16762
16887
  } else {
16763
16888
  summary.push("Skipped .gitignore (.glasstrace/ already listed)");
16764
16889
  }
16765
16890
  } catch (err) {
16891
+ await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
16766
16892
  errors.push(`Failed to update .gitignore: ${err instanceof Error ? err.message : String(err)}`);
16767
16893
  return { exitCode: 1, summary, warnings, errors };
16768
16894
  }
@@ -17022,6 +17148,7 @@ Usage:
17022
17148
  // Annotate the CommonJS export names for ESM import in node:
17023
17149
  0 && (module.exports = {
17024
17150
  meetsNodeVersion,
17151
+ rollbackSteps,
17025
17152
  runInit
17026
17153
  });
17027
17154
  //# sourceMappingURL=init.cjs.map