@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 +859 -35
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +288 -10
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/uninit.cjs +583 -0
- package/dist/cli/uninit.cjs.map +1 -0
- package/dist/cli/uninit.d.cts +141 -0
- package/dist/cli/uninit.d.ts +141 -0
- package/dist/cli/uninit.js +541 -0
- package/dist/cli/uninit.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
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,
|
|
543
|
-
if (!
|
|
542
|
+
function getElementAtPath(obj, path7) {
|
|
543
|
+
if (!path7)
|
|
544
544
|
return obj;
|
|
545
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 = [...
|
|
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
|
|
1147
|
-
for (const seg of
|
|
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
|
|
13912
|
-
if (
|
|
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 (
|
|
13917
|
-
const key =
|
|
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(
|
|
14894
|
+
async function pathExists(path7, mode = import_node_fs.constants.R_OK) {
|
|
14895
14895
|
try {
|
|
14896
|
-
await (0, import_promises2.access)(
|
|
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 &&
|
|
15451
|
-
const content =
|
|
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
|
-
|
|
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 =
|
|
15500
|
-
if (
|
|
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 (
|
|
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,
|
|
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
|
-
|
|
15632
|
-
|
|
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
|
|
15652
|
-
var
|
|
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 {
|
|
16637
|
+
const { yes, coverageMap } = options;
|
|
15858
16638
|
const summary = [];
|
|
15859
16639
|
const warnings = [];
|
|
15860
16640
|
const errors = [];
|
|
15861
|
-
|
|
15862
|
-
|
|
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:
|
|
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 &&
|
|
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:
|
|
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 &&
|
|
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 &&
|
|
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 ?
|
|
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
|
);
|