@glasstrace/sdk 0.11.0 → 0.12.1

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