@glasstrace/sdk 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/init.cjs CHANGED
@@ -539,10 +539,10 @@ function mergeDefs(...defs) {
539
539
  function cloneDef(schema) {
540
540
  return mergeDefs(schema._zod.def);
541
541
  }
542
- function getElementAtPath(obj, path5) {
543
- if (!path5)
542
+ function getElementAtPath(obj, path7) {
543
+ if (!path7)
544
544
  return obj;
545
- return path5.reduce((acc, key) => acc?.[key], obj);
545
+ return path7.reduce((acc, key) => acc?.[key], obj);
546
546
  }
547
547
  function promiseAllObject(promisesObj) {
548
548
  const keys = Object.keys(promisesObj);
@@ -854,11 +854,11 @@ function aborted(x, startIndex = 0) {
854
854
  }
855
855
  return false;
856
856
  }
857
- function prefixIssues(path5, issues) {
857
+ function prefixIssues(path7, issues) {
858
858
  return issues.map((iss) => {
859
859
  var _a2;
860
860
  (_a2 = iss).path ?? (_a2.path = []);
861
- iss.path.unshift(path5);
861
+ iss.path.unshift(path7);
862
862
  return iss;
863
863
  });
864
864
  }
@@ -1101,7 +1101,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
1101
1101
  }
1102
1102
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
1103
1103
  const result = { errors: [] };
1104
- const processError = (error49, path5 = []) => {
1104
+ const processError = (error49, path7 = []) => {
1105
1105
  var _a2, _b;
1106
1106
  for (const issue2 of error49.issues) {
1107
1107
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -1111,7 +1111,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
1111
1111
  } else if (issue2.code === "invalid_element") {
1112
1112
  processError({ issues: issue2.issues }, issue2.path);
1113
1113
  } else {
1114
- const fullpath = [...path5, ...issue2.path];
1114
+ const fullpath = [...path7, ...issue2.path];
1115
1115
  if (fullpath.length === 0) {
1116
1116
  result.errors.push(mapper(issue2));
1117
1117
  continue;
@@ -1143,8 +1143,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
1143
1143
  }
1144
1144
  function toDotPath(_path) {
1145
1145
  const segs = [];
1146
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1147
- for (const seg of path5) {
1146
+ const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1147
+ for (const seg of path7) {
1148
1148
  if (typeof seg === "number")
1149
1149
  segs.push(`[${seg}]`);
1150
1150
  else if (typeof seg === "symbol")
@@ -13908,13 +13908,13 @@ function resolveRef(ref, ctx) {
13908
13908
  if (!ref.startsWith("#")) {
13909
13909
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
13910
13910
  }
13911
- const path5 = ref.slice(1).split("/").filter(Boolean);
13912
- if (path5.length === 0) {
13911
+ const path7 = ref.slice(1).split("/").filter(Boolean);
13912
+ if (path7.length === 0) {
13913
13913
  return ctx.rootSchema;
13914
13914
  }
13915
13915
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
13916
- if (path5[0] === defsKey) {
13917
- const key = path5[1];
13916
+ if (path7[0] === defsKey) {
13917
+ const key = path7[1];
13918
13918
  if (!key || !ctx.defs[key]) {
13919
13919
  throw new Error(`Reference not found: ${ref}`);
13920
13920
  }
@@ -14891,9 +14891,9 @@ var init_anon_key = __esm({
14891
14891
  });
14892
14892
 
14893
14893
  // src/agent-detection/detect.ts
14894
- async function pathExists(path5, mode = import_node_fs.constants.R_OK) {
14894
+ async function pathExists(path7, mode = import_node_fs.constants.R_OK) {
14895
14895
  try {
14896
- await (0, import_promises2.access)(path5, mode);
14896
+ await (0, import_promises2.access)(path7, mode);
14897
14897
  return true;
14898
14898
  } catch {
14899
14899
  return false;
@@ -15447,11 +15447,11 @@ async function registerViaCli(agent, anonKey) {
15447
15447
  MCP_ENDPOINT
15448
15448
  ]);
15449
15449
  const configPath = agent.mcpConfigPath;
15450
- if (configPath !== null && fs3.existsSync(configPath)) {
15451
- const content = fs3.readFileSync(configPath, "utf-8");
15450
+ if (configPath !== null && fs4.existsSync(configPath)) {
15451
+ const content = fs4.readFileSync(configPath, "utf-8");
15452
15452
  if (!content.includes("bearer_token_env_var")) {
15453
15453
  const appendContent = content.endsWith("\n") ? "" : "\n";
15454
- fs3.writeFileSync(
15454
+ fs4.writeFileSync(
15455
15455
  configPath,
15456
15456
  content + appendContent + 'bearer_token_env_var = "GLASSTRACE_API_KEY"\n',
15457
15457
  "utf-8"
@@ -15496,8 +15496,8 @@ async function mcpAdd(options) {
15496
15496
  messages: ["Error: Run `glasstrace init` first to generate an API key."]
15497
15497
  };
15498
15498
  }
15499
- const markerPath = path3.join(projectRoot, ".glasstrace", "mcp-connected");
15500
- if (fs3.existsSync(markerPath) && !force) {
15499
+ const markerPath = path4.join(projectRoot, ".glasstrace", "mcp-connected");
15500
+ if (fs4.existsSync(markerPath) && !force) {
15501
15501
  return {
15502
15502
  exitCode: 0,
15503
15503
  results: [],
@@ -15556,7 +15556,7 @@ async function mcpAdd(options) {
15556
15556
  try {
15557
15557
  const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);
15558
15558
  await writeMcpConfig(agent, configContent, projectRoot);
15559
- if (fs3.existsSync(agent.mcpConfigPath)) {
15559
+ if (fs4.existsSync(agent.mcpConfigPath)) {
15560
15560
  const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
15561
15561
  if (infoContent !== "") {
15562
15562
  await injectInfoSection(agent, infoContent, projectRoot);
@@ -15623,13 +15623,13 @@ async function mcpAdd(options) {
15623
15623
  }
15624
15624
  return { exitCode: 0, results, messages };
15625
15625
  }
15626
- var import_node_child_process2, fs3, path3, import_node_util, execFileAsync;
15626
+ var import_node_child_process2, fs4, path4, import_node_util, execFileAsync;
15627
15627
  var init_mcp_add = __esm({
15628
15628
  "src/cli/mcp-add.ts"() {
15629
15629
  "use strict";
15630
15630
  import_node_child_process2 = require("child_process");
15631
- fs3 = __toESM(require("fs"), 1);
15632
- path3 = __toESM(require("path"), 1);
15631
+ fs4 = __toESM(require("fs"), 1);
15632
+ path4 = __toESM(require("path"), 1);
15633
15633
  import_node_util = require("util");
15634
15634
  init_anon_key();
15635
15635
  init_detect();
@@ -15641,6 +15641,552 @@ var init_mcp_add = __esm({
15641
15641
  }
15642
15642
  });
15643
15643
 
15644
+ // src/cli/uninit.ts
15645
+ var uninit_exports = {};
15646
+ __export(uninit_exports, {
15647
+ findMatchingParen: () => findMatchingParen,
15648
+ isInitCreatedInstrumentation: () => isInitCreatedInstrumentation,
15649
+ processJsonMcpConfig: () => processJsonMcpConfig,
15650
+ processTomlMcpConfig: () => processTomlMcpConfig,
15651
+ removeGlasstraceConfigImport: () => removeGlasstraceConfigImport,
15652
+ removeMarkerSection: () => removeMarkerSection,
15653
+ removeRegisterGlasstrace: () => removeRegisterGlasstrace,
15654
+ runUninit: () => runUninit,
15655
+ unwrapCJSExport: () => unwrapCJSExport,
15656
+ unwrapExport: () => unwrapExport
15657
+ });
15658
+ function findMatchingParen(text, openPos) {
15659
+ let depth = 0;
15660
+ for (let i = openPos; i < text.length; i++) {
15661
+ if (text[i] === "(") {
15662
+ depth++;
15663
+ } else if (text[i] === ")") {
15664
+ depth--;
15665
+ if (depth === 0) {
15666
+ return i;
15667
+ }
15668
+ }
15669
+ }
15670
+ return -1;
15671
+ }
15672
+ function unwrapExport(content) {
15673
+ const pattern = /export\s+default\s+withGlasstraceConfig\s*\(/;
15674
+ const match = pattern.exec(content);
15675
+ if (!match) {
15676
+ return { content, unwrapped: false };
15677
+ }
15678
+ const openParenIdx = match.index + match[0].length - 1;
15679
+ const closeParenIdx = findMatchingParen(content, openParenIdx);
15680
+ if (closeParenIdx === -1) {
15681
+ return { content, unwrapped: false };
15682
+ }
15683
+ const innerExpr = content.slice(openParenIdx + 1, closeParenIdx).trim();
15684
+ if (innerExpr.length === 0) {
15685
+ return { content, unwrapped: false };
15686
+ }
15687
+ const before = content.slice(0, match.index);
15688
+ const afterClose = content.slice(closeParenIdx + 1);
15689
+ const trailing = afterClose.replace(/^;?\s*/, "");
15690
+ const result = before + `export default ${innerExpr};
15691
+ ` + trailing;
15692
+ return { content: result, unwrapped: true };
15693
+ }
15694
+ function unwrapCJSExport(content) {
15695
+ const pattern = /module\.exports\s*=\s*withGlasstraceConfig\s*\(/;
15696
+ const match = pattern.exec(content);
15697
+ if (!match) {
15698
+ return { content, unwrapped: false };
15699
+ }
15700
+ const openParenIdx = match.index + match[0].length - 1;
15701
+ const closeParenIdx = findMatchingParen(content, openParenIdx);
15702
+ if (closeParenIdx === -1) {
15703
+ return { content, unwrapped: false };
15704
+ }
15705
+ const innerExpr = content.slice(openParenIdx + 1, closeParenIdx).trim();
15706
+ if (innerExpr.length === 0) {
15707
+ return { content, unwrapped: false };
15708
+ }
15709
+ const before = content.slice(0, match.index);
15710
+ const afterClose = content.slice(closeParenIdx + 1);
15711
+ const trailing = afterClose.replace(/^;?\s*/, "");
15712
+ const result = before + `module.exports = ${innerExpr};
15713
+ ` + trailing;
15714
+ return { content: result, unwrapped: true };
15715
+ }
15716
+ function removeGlasstraceConfigImport(content) {
15717
+ const esmSoleImport = /import\s*\{\s*withGlasstraceConfig\s*\}\s*from\s*["']@glasstrace\/sdk["']\s*;?\s*\n?/;
15718
+ if (esmSoleImport.test(content)) {
15719
+ return content.replace(esmSoleImport, "");
15720
+ }
15721
+ const esmMultiImport = /import\s*\{([^}]*)\}\s*from\s*["']@glasstrace\/sdk["']/;
15722
+ const multiMatch = esmMultiImport.exec(content);
15723
+ if (multiMatch) {
15724
+ const specifiers = multiMatch[1].split(",").map((s) => s.trim()).filter((s) => s !== "" && s !== "withGlasstraceConfig");
15725
+ if (specifiers.length === 0) {
15726
+ return content.replace(
15727
+ /import\s*\{[^}]*\}\s*from\s*["']@glasstrace\/sdk["']\s*;?\s*\n?/,
15728
+ ""
15729
+ );
15730
+ }
15731
+ const newImport = `import { ${specifiers.join(", ")} } from "@glasstrace/sdk"`;
15732
+ return content.replace(multiMatch[0], newImport);
15733
+ }
15734
+ const cjsSoleRequire = /const\s*\{\s*withGlasstraceConfig\s*\}\s*=\s*require\s*\(\s*["']@glasstrace\/sdk["']\s*\)\s*;?\s*\n?/;
15735
+ if (cjsSoleRequire.test(content)) {
15736
+ return content.replace(cjsSoleRequire, "");
15737
+ }
15738
+ const cjsMultiRequire = /const\s*\{([^}]*)\}\s*=\s*require\s*\(\s*["']@glasstrace\/sdk["']\s*\)/;
15739
+ const cjsMultiMatch = cjsMultiRequire.exec(content);
15740
+ if (cjsMultiMatch) {
15741
+ const specifiers = cjsMultiMatch[1].split(",").map((s) => s.trim()).filter((s) => s !== "" && s !== "withGlasstraceConfig");
15742
+ if (specifiers.length === 0) {
15743
+ return content.replace(
15744
+ /const\s*\{[^}]*\}\s*=\s*require\s*\(\s*["']@glasstrace\/sdk["']\s*\)\s*;?\s*\n?/,
15745
+ ""
15746
+ );
15747
+ }
15748
+ const newRequire = `const { ${specifiers.join(", ")} } = require("@glasstrace/sdk")`;
15749
+ return content.replace(cjsMultiMatch[0], newRequire);
15750
+ }
15751
+ return content;
15752
+ }
15753
+ function cleanLeadingBlankLines(content) {
15754
+ return content.replace(/^\n{2,}/, "\n");
15755
+ }
15756
+ function isInitCreatedInstrumentation(content) {
15757
+ const lines = content.split("\n");
15758
+ const importLines = lines.filter(
15759
+ (l) => /^\s*import\s/.test(l) && !l.trim().startsWith("//")
15760
+ );
15761
+ const nonGlasstraceImports = importLines.filter(
15762
+ (l) => !l.includes("@glasstrace/sdk")
15763
+ );
15764
+ if (nonGlasstraceImports.length > 0) {
15765
+ return false;
15766
+ }
15767
+ const registerFnRegex = /export\s+(?:async\s+)?function\s+register\s*\([^)]*\)\s*\{/;
15768
+ const match = registerFnRegex.exec(content);
15769
+ if (!match) {
15770
+ return false;
15771
+ }
15772
+ const afterBrace = content.slice(match.index + match[0].length);
15773
+ const closingBraceIdx = findMatchingBrace(content, match.index + match[0].length - 1);
15774
+ if (closingBraceIdx === -1) {
15775
+ return false;
15776
+ }
15777
+ const body = afterBrace.slice(0, closingBraceIdx - (match.index + match[0].length));
15778
+ const bodyLines = body.split("\n");
15779
+ const statements = bodyLines.filter((l) => {
15780
+ const trimmed = l.trim();
15781
+ return trimmed !== "" && !trimmed.startsWith("//");
15782
+ });
15783
+ if (statements.length !== 1) {
15784
+ return false;
15785
+ }
15786
+ if (!/^\s*registerGlasstrace\s*\(\s*\)\s*;?\s*$/.test(statements[0])) {
15787
+ return false;
15788
+ }
15789
+ const beforeFn = content.slice(0, match.index);
15790
+ const afterFn = content.slice(closingBraceIdx + 1);
15791
+ const topLevelBefore = beforeFn.split("\n").filter((l) => {
15792
+ const trimmed = l.trim();
15793
+ return trimmed !== "" && !trimmed.startsWith("//") && !trimmed.startsWith("import ") && !trimmed.startsWith("import{");
15794
+ });
15795
+ const topLevelAfter = afterFn.split("\n").filter((l) => {
15796
+ const trimmed = l.trim();
15797
+ return trimmed !== "" && !trimmed.startsWith("//");
15798
+ });
15799
+ return topLevelBefore.length === 0 && topLevelAfter.length === 0;
15800
+ }
15801
+ function findMatchingBrace(text, openPos) {
15802
+ let depth = 0;
15803
+ for (let i = openPos; i < text.length; i++) {
15804
+ if (text[i] === "{") {
15805
+ depth++;
15806
+ } else if (text[i] === "}") {
15807
+ depth--;
15808
+ if (depth === 0) {
15809
+ return i;
15810
+ }
15811
+ }
15812
+ }
15813
+ return -1;
15814
+ }
15815
+ function removeRegisterGlasstrace(content) {
15816
+ let result = content;
15817
+ result = result.replace(
15818
+ /[ \t]*\/\/\s*Glasstrace must be registered[^\n]*\n(?:[ \t]*\/\/[^\n]*\n)*[ \t]*registerGlasstrace\s*\(\s*\)\s*;?\s*\n?/g,
15819
+ ""
15820
+ );
15821
+ result = result.replace(
15822
+ /[ \t]*registerGlasstrace\s*\(\s*\)\s*;?\s*\n?/g,
15823
+ ""
15824
+ );
15825
+ const soleImportPattern = /import\s*\{\s*registerGlasstrace\s*\}\s*from\s*["']@glasstrace\/sdk["']\s*;?\s*\n?/;
15826
+ if (soleImportPattern.test(result)) {
15827
+ result = result.replace(soleImportPattern, "");
15828
+ } else {
15829
+ const multiImportPattern = /import\s*\{([^}]*)\}\s*from\s*["']@glasstrace\/sdk["']/;
15830
+ const multiMatch = multiImportPattern.exec(result);
15831
+ if (multiMatch) {
15832
+ const specifiers = multiMatch[1].split(",").map((s) => s.trim()).filter((s) => s !== "" && s !== "registerGlasstrace");
15833
+ if (specifiers.length === 0) {
15834
+ result = result.replace(
15835
+ /import\s*\{[^}]*\}\s*from\s*["']@glasstrace\/sdk["']\s*;?\s*\n?/,
15836
+ ""
15837
+ );
15838
+ } else {
15839
+ const newImport = `import { ${specifiers.join(", ")} } from "@glasstrace/sdk"`;
15840
+ result = result.replace(multiMatch[0], newImport);
15841
+ }
15842
+ }
15843
+ }
15844
+ return cleanLeadingBlankLines(result);
15845
+ }
15846
+ function removeMarkerSection(content) {
15847
+ const lines = content.split("\n");
15848
+ let startIdx = -1;
15849
+ let endIdx = -1;
15850
+ for (let i = 0; i < lines.length; i++) {
15851
+ const trimmed = lines[i].trim();
15852
+ if (trimmed === "<!-- glasstrace:mcp:start -->" || trimmed === "# glasstrace:mcp:start") {
15853
+ startIdx = i;
15854
+ } else if ((trimmed === "<!-- glasstrace:mcp:end -->" || trimmed === "# glasstrace:mcp:end") && startIdx !== -1) {
15855
+ endIdx = i;
15856
+ break;
15857
+ }
15858
+ }
15859
+ if (startIdx === -1 || endIdx === -1) {
15860
+ return { content, removed: false };
15861
+ }
15862
+ const before = lines.slice(0, startIdx);
15863
+ const after = lines.slice(endIdx + 1);
15864
+ while (before.length > 0 && before[before.length - 1].trim() === "") {
15865
+ before.pop();
15866
+ }
15867
+ const result = [...before, ...after].join("\n");
15868
+ const trimmedResult = result.trimEnd();
15869
+ return {
15870
+ content: trimmedResult.length > 0 ? trimmedResult + "\n" : "",
15871
+ removed: true
15872
+ };
15873
+ }
15874
+ function processJsonMcpConfig(content) {
15875
+ let parsed;
15876
+ try {
15877
+ parsed = JSON.parse(content);
15878
+ } catch {
15879
+ return { action: "skipped" };
15880
+ }
15881
+ const mcpServers = parsed["mcpServers"];
15882
+ if (!mcpServers || typeof mcpServers !== "object" || !("glasstrace" in mcpServers)) {
15883
+ return { action: "skipped" };
15884
+ }
15885
+ const remainingServers = Object.keys(mcpServers).filter((k) => k !== "glasstrace");
15886
+ const otherTopLevelKeys = Object.keys(parsed).filter((k) => k !== "mcpServers");
15887
+ if (remainingServers.length === 0 && otherTopLevelKeys.length === 0) {
15888
+ return { action: "deleted" };
15889
+ }
15890
+ const { glasstrace: _, ...rest } = mcpServers;
15891
+ void _;
15892
+ if (remainingServers.length > 0) {
15893
+ parsed["mcpServers"] = rest;
15894
+ } else {
15895
+ delete parsed["mcpServers"];
15896
+ }
15897
+ return { action: "removed-key", content: JSON.stringify(parsed, null, 2) + "\n" };
15898
+ }
15899
+ function processTomlMcpConfig(content) {
15900
+ if (!content.includes("[mcp_servers.glasstrace]")) {
15901
+ return { action: "skipped" };
15902
+ }
15903
+ const lines = content.split("\n");
15904
+ const startIdx = lines.findIndex(
15905
+ (l) => l.trim() === "[mcp_servers.glasstrace]"
15906
+ );
15907
+ if (startIdx === -1) {
15908
+ return { action: "skipped" };
15909
+ }
15910
+ let endIdx = lines.length;
15911
+ for (let i = startIdx + 1; i < lines.length; i++) {
15912
+ if (/^\s*\[/.test(lines[i])) {
15913
+ endIdx = i;
15914
+ break;
15915
+ }
15916
+ }
15917
+ const before = lines.slice(0, startIdx);
15918
+ const after = lines.slice(endIdx);
15919
+ while (before.length > 0 && before[before.length - 1].trim() === "") {
15920
+ before.pop();
15921
+ }
15922
+ const result = [...before, ...after].join("\n").trimEnd();
15923
+ if (result.trim().length === 0) {
15924
+ return { action: "deleted" };
15925
+ }
15926
+ return { action: "removed-section", content: result + "\n" };
15927
+ }
15928
+ async function runUninit(options) {
15929
+ const { projectRoot, dryRun } = options;
15930
+ const summary = [];
15931
+ const warnings = [];
15932
+ const errors = [];
15933
+ const prefix = dryRun ? "[dry run] " : "";
15934
+ try {
15935
+ let configHandled = false;
15936
+ for (const name of NEXT_CONFIG_NAMES3) {
15937
+ const configPath = path5.join(projectRoot, name);
15938
+ if (!fs5.existsSync(configPath)) {
15939
+ continue;
15940
+ }
15941
+ const content = fs5.readFileSync(configPath, "utf-8");
15942
+ if (!content.includes("withGlasstraceConfig")) {
15943
+ continue;
15944
+ }
15945
+ const isESM = name.endsWith(".ts") || name.endsWith(".mjs");
15946
+ const unwrapResult = isESM ? unwrapExport(content) : unwrapCJSExport(content);
15947
+ if (unwrapResult.unwrapped) {
15948
+ const cleaned = removeGlasstraceConfigImport(unwrapResult.content);
15949
+ const final = cleanLeadingBlankLines(cleaned);
15950
+ if (!dryRun) {
15951
+ fs5.writeFileSync(configPath, final, "utf-8");
15952
+ }
15953
+ summary.push(`${prefix}Unwrapped withGlasstraceConfig from ${name}`);
15954
+ configHandled = true;
15955
+ break;
15956
+ } else {
15957
+ warnings.push(
15958
+ `${name} contains withGlasstraceConfig but could not be automatically unwrapped. Please remove withGlasstraceConfig() manually.`
15959
+ );
15960
+ configHandled = true;
15961
+ break;
15962
+ }
15963
+ }
15964
+ if (!configHandled) {
15965
+ }
15966
+ } catch (err) {
15967
+ errors.push(
15968
+ `Failed to process next.config: ${err instanceof Error ? err.message : String(err)}`
15969
+ );
15970
+ }
15971
+ try {
15972
+ const instrPath = path5.join(projectRoot, "instrumentation.ts");
15973
+ if (fs5.existsSync(instrPath)) {
15974
+ const content = fs5.readFileSync(instrPath, "utf-8");
15975
+ if (content.includes("registerGlasstrace") || content.includes("@glasstrace/sdk")) {
15976
+ if (isInitCreatedInstrumentation(content)) {
15977
+ if (!dryRun) {
15978
+ fs5.unlinkSync(instrPath);
15979
+ }
15980
+ summary.push(`${prefix}Deleted instrumentation.ts (init-created)`);
15981
+ } else {
15982
+ const cleaned = removeRegisterGlasstrace(content);
15983
+ if (cleaned !== content) {
15984
+ if (!dryRun) {
15985
+ fs5.writeFileSync(instrPath, cleaned, "utf-8");
15986
+ }
15987
+ summary.push(
15988
+ `${prefix}Removed registerGlasstrace() from instrumentation.ts`
15989
+ );
15990
+ }
15991
+ }
15992
+ }
15993
+ }
15994
+ } catch (err) {
15995
+ errors.push(
15996
+ `Failed to process instrumentation.ts: ${err instanceof Error ? err.message : String(err)}`
15997
+ );
15998
+ }
15999
+ try {
16000
+ const glasstraceDir = path5.join(projectRoot, ".glasstrace");
16001
+ if (fs5.existsSync(glasstraceDir)) {
16002
+ if (!dryRun) {
16003
+ fs5.rmSync(glasstraceDir, { recursive: true, force: true });
16004
+ }
16005
+ summary.push(`${prefix}Removed .glasstrace/ directory`);
16006
+ }
16007
+ } catch (err) {
16008
+ errors.push(
16009
+ `Failed to remove .glasstrace/: ${err instanceof Error ? err.message : String(err)}`
16010
+ );
16011
+ }
16012
+ try {
16013
+ const envPath = path5.join(projectRoot, ".env.local");
16014
+ if (fs5.existsSync(envPath)) {
16015
+ const content = fs5.readFileSync(envPath, "utf-8");
16016
+ const lines = content.split("\n");
16017
+ const filtered = lines.filter((line) => {
16018
+ const trimmed = line.trim();
16019
+ return !(/^\s*#?\s*GLASSTRACE_API_KEY\s*=/.test(trimmed) || /^\s*#?\s*GLASSTRACE_COVERAGE_MAP\s*=/.test(trimmed));
16020
+ });
16021
+ if (filtered.length !== lines.length) {
16022
+ const result = filtered.join("\n");
16023
+ if (result.trim().length === 0) {
16024
+ if (!dryRun) {
16025
+ fs5.unlinkSync(envPath);
16026
+ }
16027
+ summary.push(`${prefix}Deleted .env.local (no remaining entries)`);
16028
+ } else {
16029
+ if (!dryRun) {
16030
+ fs5.writeFileSync(envPath, result, "utf-8");
16031
+ }
16032
+ summary.push(`${prefix}Removed GLASSTRACE entries from .env.local`);
16033
+ }
16034
+ }
16035
+ }
16036
+ } catch (err) {
16037
+ errors.push(
16038
+ `Failed to process .env.local: ${err instanceof Error ? err.message : String(err)}`
16039
+ );
16040
+ }
16041
+ try {
16042
+ const gitignorePath = path5.join(projectRoot, ".gitignore");
16043
+ if (fs5.existsSync(gitignorePath)) {
16044
+ const content = fs5.readFileSync(gitignorePath, "utf-8");
16045
+ const lines = content.split("\n");
16046
+ const mcpGitignoreEntries = /* @__PURE__ */ new Set([
16047
+ ".glasstrace/",
16048
+ ".mcp.json",
16049
+ ".cursor/mcp.json",
16050
+ ".gemini/settings.json",
16051
+ ".codex/config.toml"
16052
+ ]);
16053
+ const filtered = lines.filter(
16054
+ (line) => !mcpGitignoreEntries.has(line.trim())
16055
+ );
16056
+ if (filtered.length !== lines.length) {
16057
+ const result = filtered.join("\n");
16058
+ if (result.trim().length === 0) {
16059
+ if (!dryRun) {
16060
+ fs5.unlinkSync(gitignorePath);
16061
+ }
16062
+ summary.push(`${prefix}Deleted .gitignore (no remaining entries)`);
16063
+ } else {
16064
+ if (!dryRun) {
16065
+ fs5.writeFileSync(gitignorePath, result, "utf-8");
16066
+ }
16067
+ summary.push(`${prefix}Removed Glasstrace entries from .gitignore`);
16068
+ }
16069
+ }
16070
+ }
16071
+ } catch (err) {
16072
+ errors.push(
16073
+ `Failed to process .gitignore: ${err instanceof Error ? err.message : String(err)}`
16074
+ );
16075
+ }
16076
+ try {
16077
+ for (const configFile of MCP_CONFIG_FILES) {
16078
+ const configPath = path5.join(projectRoot, configFile);
16079
+ if (!fs5.existsSync(configPath)) {
16080
+ continue;
16081
+ }
16082
+ const content = fs5.readFileSync(configPath, "utf-8");
16083
+ const result = processJsonMcpConfig(content);
16084
+ if (result.action === "deleted") {
16085
+ if (!dryRun) {
16086
+ fs5.unlinkSync(configPath);
16087
+ }
16088
+ summary.push(`${prefix}Deleted ${configFile}`);
16089
+ } else if (result.action === "removed-key" && result.content !== void 0) {
16090
+ if (!dryRun) {
16091
+ fs5.writeFileSync(configPath, result.content, "utf-8");
16092
+ }
16093
+ summary.push(`${prefix}Removed glasstrace from ${configFile}`);
16094
+ }
16095
+ }
16096
+ const codexConfigPath = path5.join(projectRoot, ".codex", "config.toml");
16097
+ if (fs5.existsSync(codexConfigPath)) {
16098
+ const content = fs5.readFileSync(codexConfigPath, "utf-8");
16099
+ const tomlResult = processTomlMcpConfig(content);
16100
+ if (tomlResult.action === "deleted") {
16101
+ if (!dryRun) {
16102
+ fs5.unlinkSync(codexConfigPath);
16103
+ }
16104
+ summary.push(`${prefix}Deleted .codex/config.toml`);
16105
+ } else if (tomlResult.action === "removed-section" && tomlResult.content !== void 0) {
16106
+ if (!dryRun) {
16107
+ fs5.writeFileSync(codexConfigPath, tomlResult.content, "utf-8");
16108
+ }
16109
+ summary.push(`${prefix}Removed glasstrace from .codex/config.toml`);
16110
+ }
16111
+ }
16112
+ const hasWindsurfMarkers = fs5.existsSync(path5.join(projectRoot, ".windsurfrules")) || fs5.existsSync(path5.join(projectRoot, ".windsurf"));
16113
+ if (hasWindsurfMarkers) {
16114
+ const windsurfConfigPath = path5.join(
16115
+ os.homedir(),
16116
+ ".codeium",
16117
+ "windsurf",
16118
+ "mcp_config.json"
16119
+ );
16120
+ if (fs5.existsSync(windsurfConfigPath)) {
16121
+ const content = fs5.readFileSync(windsurfConfigPath, "utf-8");
16122
+ const windsurfResult = processJsonMcpConfig(content);
16123
+ if (windsurfResult.action === "deleted") {
16124
+ if (!dryRun) {
16125
+ fs5.unlinkSync(windsurfConfigPath);
16126
+ }
16127
+ summary.push(`${prefix}Deleted Windsurf MCP config`);
16128
+ } else if (windsurfResult.action === "removed-key" && windsurfResult.content !== void 0) {
16129
+ if (!dryRun) {
16130
+ fs5.writeFileSync(windsurfConfigPath, windsurfResult.content, "utf-8");
16131
+ }
16132
+ summary.push(`${prefix}Removed glasstrace from Windsurf MCP config`);
16133
+ }
16134
+ }
16135
+ }
16136
+ } catch (err) {
16137
+ errors.push(
16138
+ `Failed to process MCP config: ${err instanceof Error ? err.message : String(err)}`
16139
+ );
16140
+ }
16141
+ try {
16142
+ for (const infoFile of AGENT_INFO_FILES) {
16143
+ const filePath = path5.join(projectRoot, infoFile);
16144
+ if (!fs5.existsSync(filePath)) {
16145
+ continue;
16146
+ }
16147
+ const content = fs5.readFileSync(filePath, "utf-8");
16148
+ const result = removeMarkerSection(content);
16149
+ if (result.removed) {
16150
+ if (result.content.trim().length === 0) {
16151
+ if (!dryRun) {
16152
+ fs5.unlinkSync(filePath);
16153
+ }
16154
+ summary.push(`${prefix}Deleted ${infoFile} (only contained Glasstrace section)`);
16155
+ } else {
16156
+ if (!dryRun) {
16157
+ fs5.writeFileSync(filePath, result.content, "utf-8");
16158
+ }
16159
+ summary.push(`${prefix}Removed Glasstrace section from ${infoFile}`);
16160
+ }
16161
+ }
16162
+ }
16163
+ } catch (err) {
16164
+ errors.push(
16165
+ `Failed to process agent info files: ${err instanceof Error ? err.message : String(err)}`
16166
+ );
16167
+ }
16168
+ if (summary.length === 0 && errors.length === 0) {
16169
+ summary.push("No Glasstrace artifacts found \u2014 nothing to do.");
16170
+ }
16171
+ return { exitCode: errors.length > 0 ? 1 : 0, summary, warnings, errors };
16172
+ }
16173
+ var fs5, os, path5, NEXT_CONFIG_NAMES3, MCP_CONFIG_FILES, AGENT_INFO_FILES;
16174
+ var init_uninit = __esm({
16175
+ "src/cli/uninit.ts"() {
16176
+ "use strict";
16177
+ fs5 = __toESM(require("fs"), 1);
16178
+ os = __toESM(require("os"), 1);
16179
+ path5 = __toESM(require("path"), 1);
16180
+ NEXT_CONFIG_NAMES3 = ["next.config.ts", "next.config.js", "next.config.mjs"];
16181
+ MCP_CONFIG_FILES = [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json"];
16182
+ AGENT_INFO_FILES = [
16183
+ "CLAUDE.md",
16184
+ "codex.md",
16185
+ ".cursorrules"
16186
+ ];
16187
+ }
16188
+ });
16189
+
15644
16190
  // src/cli/init.ts
15645
16191
  var init_exports = {};
15646
16192
  __export(init_exports, {
@@ -15648,8 +16194,8 @@ __export(init_exports, {
15648
16194
  runInit: () => runInit
15649
16195
  });
15650
16196
  module.exports = __toCommonJS(init_exports);
15651
- var fs4 = __toESM(require("fs"), 1);
15652
- var path4 = __toESM(require("path"), 1);
16197
+ var fs6 = __toESM(require("fs"), 1);
16198
+ var path6 = __toESM(require("path"), 1);
15653
16199
  var readline = __toESM(require("readline"), 1);
15654
16200
  init_scaffolder();
15655
16201
 
@@ -15828,6 +16374,240 @@ init_detect();
15828
16374
  init_configs();
15829
16375
  init_inject();
15830
16376
  init_constants();
16377
+
16378
+ // src/cli/monorepo.ts
16379
+ var fs3 = __toESM(require("fs"), 1);
16380
+ var path3 = __toESM(require("path"), 1);
16381
+ var NEXT_CONFIG_NAMES2 = ["next.config.ts", "next.config.js", "next.config.mjs"];
16382
+ function resolveProjectRoot(cwd) {
16383
+ if (hasNextConfig(cwd)) {
16384
+ return { projectRoot: cwd, isMonorepo: false };
16385
+ }
16386
+ if (hasNextDependency(cwd)) {
16387
+ return { projectRoot: cwd, isMonorepo: false };
16388
+ }
16389
+ if (isMonorepoRoot(cwd)) {
16390
+ const apps = findNextJsApps(cwd);
16391
+ if (apps.length === 0) {
16392
+ throw new Error(
16393
+ "This is a monorepo but no Next.js apps were found in workspace packages."
16394
+ );
16395
+ }
16396
+ if (apps.length === 1) {
16397
+ const appDir = apps[0];
16398
+ const relativePath = path3.relative(cwd, appDir);
16399
+ return {
16400
+ projectRoot: appDir,
16401
+ isMonorepo: true,
16402
+ appRelativePath: relativePath
16403
+ };
16404
+ }
16405
+ const appList = apps.map((app) => ` - ${path3.relative(cwd, app)}`).join("\n");
16406
+ throw new Error(
16407
+ `Found multiple Next.js apps:
16408
+ ${appList}
16409
+ Run init from the specific app directory you want to instrument.`
16410
+ );
16411
+ }
16412
+ throw new Error(
16413
+ "No Next.js project found in the current directory.\nRun this command from your Next.js app directory, or from a monorepo root."
16414
+ );
16415
+ }
16416
+ function hasNextConfig(dir) {
16417
+ return NEXT_CONFIG_NAMES2.some(
16418
+ (name) => fs3.existsSync(path3.join(dir, name))
16419
+ );
16420
+ }
16421
+ function hasNextDependency(dir) {
16422
+ const packageJsonPath = path3.join(dir, "package.json");
16423
+ if (!fs3.existsSync(packageJsonPath)) return false;
16424
+ try {
16425
+ const content = fs3.readFileSync(packageJsonPath, "utf-8");
16426
+ const pkg = JSON.parse(content);
16427
+ const deps = pkg["dependencies"];
16428
+ const devDeps = pkg["devDependencies"];
16429
+ if (typeof deps === "object" && deps !== null && "next" in deps) return true;
16430
+ if (typeof devDeps === "object" && devDeps !== null && "next" in devDeps) return true;
16431
+ } catch {
16432
+ }
16433
+ return false;
16434
+ }
16435
+ function isMonorepoRoot(dir) {
16436
+ if (fs3.existsSync(path3.join(dir, "pnpm-workspace.yaml"))) return true;
16437
+ if (fs3.existsSync(path3.join(dir, "turbo.json"))) return true;
16438
+ if (fs3.existsSync(path3.join(dir, "lerna.json"))) return true;
16439
+ const packageJsonPath = path3.join(dir, "package.json");
16440
+ if (fs3.existsSync(packageJsonPath)) {
16441
+ try {
16442
+ const content = fs3.readFileSync(packageJsonPath, "utf-8");
16443
+ const pkg = JSON.parse(content);
16444
+ if (pkg["workspaces"] !== void 0) return true;
16445
+ } catch {
16446
+ }
16447
+ }
16448
+ return false;
16449
+ }
16450
+ function findNextJsApps(monorepoRoot) {
16451
+ const { includeGlobs, negationPatterns } = collectWorkspaceGlobs(monorepoRoot);
16452
+ if (includeGlobs.length === 0) {
16453
+ throw new Error(
16454
+ 'Monorepo detected but no workspace configuration found.\nAdd a "workspaces" field to package.json or create pnpm-workspace.yaml.'
16455
+ );
16456
+ }
16457
+ const workspaceDirs = expandGlobs(monorepoRoot, includeGlobs);
16458
+ const excludedDirs = expandGlobs(monorepoRoot, negationPatterns);
16459
+ const excludedSet = new Set(excludedDirs);
16460
+ const seen = /* @__PURE__ */ new Set();
16461
+ const nextApps = [];
16462
+ for (const dir of workspaceDirs) {
16463
+ if (seen.has(dir)) continue;
16464
+ seen.add(dir);
16465
+ if (excludedSet.has(dir)) continue;
16466
+ if (hasNextConfig(dir) || hasNextDependency(dir)) {
16467
+ nextApps.push(dir);
16468
+ }
16469
+ }
16470
+ return nextApps.sort();
16471
+ }
16472
+ function collectWorkspaceGlobs(root) {
16473
+ const globs = [];
16474
+ const negations = [];
16475
+ const pnpmPath = path3.join(root, "pnpm-workspace.yaml");
16476
+ if (fs3.existsSync(pnpmPath)) {
16477
+ const content = fs3.readFileSync(pnpmPath, "utf-8");
16478
+ const parsed = parsePnpmWorkspaceYaml(content);
16479
+ globs.push(...parsed.includeGlobs);
16480
+ negations.push(...parsed.negationPatterns);
16481
+ }
16482
+ const packageJsonPath = path3.join(root, "package.json");
16483
+ if (fs3.existsSync(packageJsonPath)) {
16484
+ try {
16485
+ const content = fs3.readFileSync(packageJsonPath, "utf-8");
16486
+ const pkg = JSON.parse(content);
16487
+ globs.push(...parsePackageJsonWorkspaces(pkg));
16488
+ } catch {
16489
+ }
16490
+ }
16491
+ const lernaPath = path3.join(root, "lerna.json");
16492
+ if (fs3.existsSync(lernaPath)) {
16493
+ try {
16494
+ const content = fs3.readFileSync(lernaPath, "utf-8");
16495
+ const lerna = JSON.parse(content);
16496
+ const packages = lerna["packages"];
16497
+ if (Array.isArray(packages)) {
16498
+ for (const pkg of packages) {
16499
+ if (typeof pkg === "string") {
16500
+ globs.push(pkg);
16501
+ }
16502
+ }
16503
+ }
16504
+ } catch {
16505
+ }
16506
+ }
16507
+ return {
16508
+ includeGlobs: [...new Set(globs)],
16509
+ negationPatterns: [...new Set(negations)]
16510
+ };
16511
+ }
16512
+ function parsePnpmWorkspaceYaml(content) {
16513
+ const lines = content.split("\n");
16514
+ const includeGlobs = [];
16515
+ const negationPatterns = [];
16516
+ let inPackages = false;
16517
+ for (const rawLine of lines) {
16518
+ const trimmed = rawLine.trim();
16519
+ if (/^packages\s*:/.test(trimmed)) {
16520
+ inPackages = true;
16521
+ continue;
16522
+ }
16523
+ if (inPackages && trimmed.length > 0 && !trimmed.startsWith("-") && !rawLine.startsWith(" ") && !rawLine.startsWith(" ")) {
16524
+ inPackages = false;
16525
+ continue;
16526
+ }
16527
+ if (!inPackages) continue;
16528
+ const itemMatch = /^\s*-\s+(.+)$/.exec(rawLine);
16529
+ if (!itemMatch) continue;
16530
+ const value = itemMatch[1].trim().replace(/^["']|["']$/g, "");
16531
+ if (value.length === 0) continue;
16532
+ if (value.startsWith("!")) {
16533
+ negationPatterns.push(value.slice(1));
16534
+ continue;
16535
+ }
16536
+ includeGlobs.push(value);
16537
+ }
16538
+ return { includeGlobs, negationPatterns };
16539
+ }
16540
+ function parsePackageJsonWorkspaces(pkg) {
16541
+ const workspaces = pkg["workspaces"];
16542
+ if (workspaces === void 0 || workspaces === null) return [];
16543
+ if (Array.isArray(workspaces)) {
16544
+ return workspaces.filter((w) => typeof w === "string");
16545
+ }
16546
+ if (typeof workspaces === "object") {
16547
+ const obj = workspaces;
16548
+ const packages = obj["packages"];
16549
+ if (Array.isArray(packages)) {
16550
+ return packages.filter((p) => typeof p === "string");
16551
+ }
16552
+ }
16553
+ return [];
16554
+ }
16555
+ function expandGlobs(root, globs) {
16556
+ const dirs = [];
16557
+ for (const glob of globs) {
16558
+ const cleanGlob = glob.replace(/\/+$/, "");
16559
+ if (cleanGlob.includes("**")) {
16560
+ const prefix = cleanGlob.split("**")[0].replace(/\/+$/, "");
16561
+ const baseDir = path3.join(root, prefix);
16562
+ if (fs3.existsSync(baseDir)) {
16563
+ dirs.push(...walkDirectories(baseDir));
16564
+ }
16565
+ } else if (cleanGlob.includes("*")) {
16566
+ const parts = cleanGlob.split("*");
16567
+ const baseDir = path3.join(root, parts[0].replace(/\/+$/, ""));
16568
+ const suffix = parts.slice(1).join("*");
16569
+ if (!fs3.existsSync(baseDir)) continue;
16570
+ let entries;
16571
+ try {
16572
+ entries = fs3.readdirSync(baseDir, { withFileTypes: true });
16573
+ } catch {
16574
+ continue;
16575
+ }
16576
+ for (const entry of entries) {
16577
+ if (!entry.isDirectory()) continue;
16578
+ if (suffix && !entry.name.endsWith(suffix)) continue;
16579
+ dirs.push(path3.join(baseDir, entry.name));
16580
+ }
16581
+ } else {
16582
+ const targetDir = path3.join(root, cleanGlob);
16583
+ if (fs3.existsSync(targetDir) && fs3.statSync(targetDir).isDirectory()) {
16584
+ dirs.push(targetDir);
16585
+ }
16586
+ }
16587
+ }
16588
+ return dirs;
16589
+ }
16590
+ function walkDirectories(baseDir) {
16591
+ const result = [];
16592
+ let entries;
16593
+ try {
16594
+ entries = fs3.readdirSync(baseDir, { withFileTypes: true });
16595
+ } catch {
16596
+ return result;
16597
+ }
16598
+ for (const entry of entries) {
16599
+ if (!entry.isDirectory()) continue;
16600
+ if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
16601
+ const fullPath = path3.join(baseDir, entry.name);
16602
+ if (fs3.existsSync(path3.join(fullPath, "package.json"))) {
16603
+ result.push(fullPath);
16604
+ }
16605
+ result.push(...walkDirectories(fullPath));
16606
+ }
16607
+ return result;
16608
+ }
16609
+
16610
+ // src/cli/init.ts
15831
16611
  function meetsNodeVersion(minMajor) {
15832
16612
  const [major] = process.versions.node.split(".").map(Number);
15833
16613
  return major >= minMajor;
@@ -15854,12 +16634,23 @@ async function promptYesNo(question, defaultValue) {
15854
16634
  });
15855
16635
  }
15856
16636
  async function runInit(options) {
15857
- const { projectRoot, yes, coverageMap } = options;
16637
+ const { yes, coverageMap } = options;
15858
16638
  const summary = [];
15859
16639
  const warnings = [];
15860
16640
  const errors = [];
15861
- const packageJsonPath = path4.join(projectRoot, "package.json");
15862
- if (!fs4.existsSync(packageJsonPath)) {
16641
+ let projectRoot;
16642
+ try {
16643
+ const classification = resolveProjectRoot(options.projectRoot);
16644
+ projectRoot = classification.projectRoot;
16645
+ if (classification.isMonorepo && classification.appRelativePath) {
16646
+ summary.push(`Found Next.js app at ${classification.appRelativePath} \u2014 installing there`);
16647
+ }
16648
+ } catch (err) {
16649
+ errors.push(err instanceof Error ? err.message : String(err));
16650
+ return { exitCode: 1, summary, warnings, errors };
16651
+ }
16652
+ const packageJsonPath = path6.join(projectRoot, "package.json");
16653
+ if (!fs6.existsSync(packageJsonPath)) {
15863
16654
  errors.push("No package.json found. Run this command from a Node.js project root.");
15864
16655
  return { exitCode: 1, summary, warnings, errors };
15865
16656
  }
@@ -15932,14 +16723,14 @@ async function runInit(options) {
15932
16723
  if (isCI) {
15933
16724
  const genericAgent = {
15934
16725
  name: "generic",
15935
- mcpConfigPath: path4.join(projectRoot, ".glasstrace", "mcp.json"),
16726
+ mcpConfigPath: path6.join(projectRoot, ".glasstrace", "mcp.json"),
15936
16727
  infoFilePath: null,
15937
16728
  cliAvailable: false,
15938
16729
  registrationCommand: null
15939
16730
  };
15940
16731
  const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, anonKey);
15941
16732
  await writeMcpConfig(genericAgent, genericConfig, projectRoot);
15942
- if (genericAgent.mcpConfigPath !== null && fs4.existsSync(genericAgent.mcpConfigPath)) {
16733
+ if (genericAgent.mcpConfigPath !== null && fs6.existsSync(genericAgent.mcpConfigPath)) {
15943
16734
  anyConfigWritten = true;
15944
16735
  summary.push("Created .glasstrace/mcp.json (CI mode)");
15945
16736
  }
@@ -15953,14 +16744,14 @@ async function runInit(options) {
15953
16744
  );
15954
16745
  const genericAgent = {
15955
16746
  name: "generic",
15956
- mcpConfigPath: path4.join(projectRoot, ".glasstrace", "mcp.json"),
16747
+ mcpConfigPath: path6.join(projectRoot, ".glasstrace", "mcp.json"),
15957
16748
  infoFilePath: null,
15958
16749
  cliAvailable: false,
15959
16750
  registrationCommand: null
15960
16751
  };
15961
16752
  const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, anonKey);
15962
16753
  await writeMcpConfig(genericAgent, genericConfig, projectRoot);
15963
- if (genericAgent.mcpConfigPath !== null && fs4.existsSync(genericAgent.mcpConfigPath)) {
16754
+ if (genericAgent.mcpConfigPath !== null && fs6.existsSync(genericAgent.mcpConfigPath)) {
15964
16755
  anyConfigWritten = true;
15965
16756
  }
15966
16757
  agents = [];
@@ -15970,7 +16761,7 @@ async function runInit(options) {
15970
16761
  try {
15971
16762
  const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);
15972
16763
  await writeMcpConfig(agent, configContent, projectRoot);
15973
- const configExists = agent.mcpConfigPath !== null && fs4.existsSync(agent.mcpConfigPath);
16764
+ const configExists = agent.mcpConfigPath !== null && fs6.existsSync(agent.mcpConfigPath);
15974
16765
  if (!configExists) {
15975
16766
  continue;
15976
16767
  }
@@ -16057,7 +16848,7 @@ function parseArgs(argv) {
16057
16848
  };
16058
16849
  }
16059
16850
  var scriptPath = typeof process !== "undefined" && process.argv[1] !== void 0 ? process.argv[1].replace(/\\/g, "/") : void 0;
16060
- var scriptBasename = scriptPath !== void 0 ? path4.basename(scriptPath) : void 0;
16851
+ var scriptBasename = scriptPath !== void 0 ? path6.basename(scriptPath) : void 0;
16061
16852
  var isDirectExecution = scriptPath !== void 0 && (scriptPath.endsWith("/cli/init.js") || scriptPath.endsWith("/cli/init.ts") || scriptBasename === "glasstrace");
16062
16853
  if (isDirectExecution) {
16063
16854
  if (!meetsNodeVersion(20)) {
@@ -16128,6 +16919,38 @@ Usage: glasstrace mcp add [--force] [--dry-run]
16128
16919
  }).catch((err) => {
16129
16920
  process.stderr.write(
16130
16921
  `Fatal error: ${err instanceof Error ? err.message : String(err)}
16922
+ `
16923
+ );
16924
+ process.exit(1);
16925
+ });
16926
+ } else if (subcommand === "uninit") {
16927
+ const remainingArgs = process.argv.slice(3);
16928
+ const dryRun = remainingArgs.includes("--dry-run");
16929
+ Promise.resolve().then(() => (init_uninit(), uninit_exports)).then(({ runUninit: runUninit2 }) => runUninit2({ projectRoot: process.cwd(), dryRun })).then((result) => {
16930
+ if (result.errors.length > 0) {
16931
+ for (const err of result.errors) {
16932
+ process.stderr.write(`Error: ${err}
16933
+ `);
16934
+ }
16935
+ }
16936
+ if (result.warnings.length > 0) {
16937
+ for (const warn of result.warnings) {
16938
+ process.stderr.write(`Warning: ${warn}
16939
+ `);
16940
+ }
16941
+ }
16942
+ if (result.summary.length > 0) {
16943
+ process.stderr.write("\n");
16944
+ for (const line of result.summary) {
16945
+ process.stderr.write(` ${line}
16946
+ `);
16947
+ }
16948
+ process.stderr.write("\n");
16949
+ }
16950
+ process.exit(result.exitCode);
16951
+ }).catch((err) => {
16952
+ process.stderr.write(
16953
+ `Fatal error: ${err instanceof Error ? err.message : String(err)}
16131
16954
  `
16132
16955
  );
16133
16956
  process.exit(1);
@@ -16138,6 +16961,7 @@ Usage: glasstrace mcp add [--force] [--dry-run]
16138
16961
 
16139
16962
  Usage:
16140
16963
  glasstrace init [--yes] [--coverage-map]
16964
+ glasstrace uninit [--dry-run]
16141
16965
  glasstrace mcp add [--force] [--dry-run]
16142
16966
  `
16143
16967
  );