@glasstrace/sdk 1.1.0 → 1.1.2
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/README.md +78 -1
- package/dist/{chunk-55FBXXER.js → chunk-2M57EO6U.js} +2 -2
- package/dist/chunk-3LILTM3T.js +384 -0
- package/dist/chunk-3LILTM3T.js.map +1 -0
- package/dist/{chunk-KE7MCPO5.js → chunk-4EZ6JTDG.js} +2 -2
- package/dist/{chunk-67RIOAXV.js → chunk-6RNBUUBR.js} +2 -2
- package/dist/{chunk-DO2YPMQ5.js → chunk-C567H5EQ.js} +23 -5
- package/dist/chunk-C567H5EQ.js.map +1 -0
- package/dist/{chunk-UGJ3X4CT.js → chunk-DST4UBXU.js} +2 -2
- package/dist/{chunk-DXRZKKSO.js → chunk-NB7GJE4S.js} +2 -4
- package/dist/chunk-NB7GJE4S.js.map +1 -0
- package/dist/{chunk-HAU66QBQ.js → chunk-P4OYPFQ5.js} +9 -9
- package/dist/chunk-P4OYPFQ5.js.map +1 -0
- package/dist/{chunk-LU3PPAOQ.js → chunk-UJ2JC7PZ.js} +4 -4
- package/dist/chunk-UJ2JC7PZ.js.map +1 -0
- package/dist/{chunk-TQ54WLCZ.js → chunk-X5MAXP5T.js} +2 -1
- package/dist/{chunk-ZBTC5QIQ.js → chunk-Z35HKVSO.js} +137 -10
- package/dist/chunk-Z35HKVSO.js.map +1 -0
- package/dist/cli/init.cjs +1313 -1118
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +456 -72
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/mcp-add.cjs +257 -85
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.d.cts +35 -4
- package/dist/cli/mcp-add.d.ts +35 -4
- package/dist/cli/mcp-add.js +61 -25
- package/dist/cli/mcp-add.js.map +1 -1
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.js +1 -1
- package/dist/cli/uninit.cjs +1 -1
- package/dist/cli/uninit.cjs.map +1 -1
- package/dist/cli/uninit.js +4 -4
- package/dist/cli/validate.cjs +14162 -2
- package/dist/cli/validate.cjs.map +1 -1
- package/dist/cli/validate.d.cts +7 -3
- package/dist/cli/validate.d.ts +7 -3
- package/dist/cli/validate.js +25 -2
- package/dist/cli/validate.js.map +1 -1
- package/dist/edge-entry.js +2 -2
- package/dist/index.cjs +423 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -5
- package/dist/{monorepo-N5Z63XP7.js → monorepo-PFVNPQ6X.js} +3 -3
- package/dist/node-entry.cjs +423 -12
- package/dist/node-entry.cjs.map +1 -1
- package/dist/node-entry.js +7 -7
- package/dist/node-subpath.js +3 -3
- package/dist/{source-map-uploader-BJIXRLJ6.js → source-map-uploader-DPUUCLNW.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-DO2YPMQ5.js.map +0 -1
- package/dist/chunk-DXRZKKSO.js.map +0 -1
- package/dist/chunk-HAU66QBQ.js.map +0 -1
- package/dist/chunk-IP4NMDJK.js +0 -98
- package/dist/chunk-IP4NMDJK.js.map +0 -1
- package/dist/chunk-LU3PPAOQ.js.map +0 -1
- package/dist/chunk-O63DJKIJ.js +0 -460
- package/dist/chunk-O63DJKIJ.js.map +0 -1
- package/dist/chunk-ZBTC5QIQ.js.map +0 -1
- /package/dist/{chunk-55FBXXER.js.map → chunk-2M57EO6U.js.map} +0 -0
- /package/dist/{chunk-KE7MCPO5.js.map → chunk-4EZ6JTDG.js.map} +0 -0
- /package/dist/{chunk-67RIOAXV.js.map → chunk-6RNBUUBR.js.map} +0 -0
- /package/dist/{chunk-UGJ3X4CT.js.map → chunk-DST4UBXU.js.map} +0 -0
- /package/dist/{chunk-TQ54WLCZ.js.map → chunk-X5MAXP5T.js.map} +0 -0
- /package/dist/{monorepo-N5Z63XP7.js.map → monorepo-PFVNPQ6X.js.map} +0 -0
- /package/dist/{source-map-uploader-BJIXRLJ6.js.map → source-map-uploader-DPUUCLNW.js.map} +0 -0
package/dist/cli/init.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolveProjectRoot
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-2M57EO6U.js";
|
|
5
5
|
import {
|
|
6
6
|
verifyInitReachable
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-C567H5EQ.js";
|
|
8
8
|
import {
|
|
9
9
|
buildImportGraph
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-DST4UBXU.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveConfig
|
|
13
13
|
} from "../chunk-VUZCLMIX.js";
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
unwrapCJSExport,
|
|
22
22
|
unwrapExport,
|
|
23
23
|
writeDiscoveryFile
|
|
24
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-UJ2JC7PZ.js";
|
|
25
25
|
import {
|
|
26
26
|
detectAgents,
|
|
27
27
|
generateInfoSection,
|
|
@@ -29,35 +29,406 @@ import {
|
|
|
29
29
|
injectInfoSection,
|
|
30
30
|
updateGitignore,
|
|
31
31
|
writeMcpConfig
|
|
32
|
-
} from "../chunk-
|
|
32
|
+
} from "../chunk-P4OYPFQ5.js";
|
|
33
33
|
import {
|
|
34
|
+
MCP_ENDPOINT,
|
|
34
35
|
getOrCreateAnonKey,
|
|
35
|
-
|
|
36
|
-
} from "../chunk-IP4NMDJK.js";
|
|
37
|
-
import {
|
|
38
|
-
addCoverageMapEnv,
|
|
36
|
+
identityFingerprint,
|
|
39
37
|
isDevApiKey,
|
|
40
38
|
mcpConfigMatches,
|
|
39
|
+
readAnonKey,
|
|
41
40
|
readEnvLocalApiKey,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
scaffoldMcpMarker,
|
|
47
|
-
scaffoldNextConfig
|
|
48
|
-
} from "../chunk-O63DJKIJ.js";
|
|
49
|
-
import "../chunk-TQ54WLCZ.js";
|
|
41
|
+
resolveEffectiveMcpCredential,
|
|
42
|
+
writeMcpMarker
|
|
43
|
+
} from "../chunk-3LILTM3T.js";
|
|
44
|
+
import "../chunk-X5MAXP5T.js";
|
|
50
45
|
import {
|
|
51
|
-
MCP_ENDPOINT,
|
|
52
46
|
NEXT_CONFIG_NAMES,
|
|
53
47
|
formatAgentName
|
|
54
|
-
} from "../chunk-
|
|
48
|
+
} from "../chunk-NB7GJE4S.js";
|
|
55
49
|
import "../chunk-NSBPE2FW.js";
|
|
56
50
|
|
|
57
51
|
// src/cli/init.ts
|
|
52
|
+
import * as fs2 from "node:fs";
|
|
53
|
+
import * as path2 from "node:path";
|
|
54
|
+
import * as readline from "node:readline";
|
|
55
|
+
|
|
56
|
+
// src/cli/scaffolder.ts
|
|
58
57
|
import * as fs from "node:fs";
|
|
59
58
|
import * as path from "node:path";
|
|
60
|
-
|
|
59
|
+
function hasRegisterGlasstraceCall(content) {
|
|
60
|
+
return content.split("\n").some((line) => {
|
|
61
|
+
const uncommented = line.replace(/\/\/.*$/, "");
|
|
62
|
+
return /\bregisterGlasstrace\s*\(/.test(uncommented);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function injectRegisterGlasstrace(content) {
|
|
66
|
+
if (hasRegisterGlasstraceCall(content)) {
|
|
67
|
+
return { injected: false, content };
|
|
68
|
+
}
|
|
69
|
+
const registerFnRegex = /export\s+(?:async\s+)?function\s+register\s*\([^)]*\)\s*\{/;
|
|
70
|
+
const match = registerFnRegex.exec(content);
|
|
71
|
+
if (!match) {
|
|
72
|
+
return { injected: false, content };
|
|
73
|
+
}
|
|
74
|
+
const afterBrace = content.slice(match.index + match[0].length);
|
|
75
|
+
const indentMatch = /\n([ \t]+)/.exec(afterBrace);
|
|
76
|
+
const indent = indentMatch ? indentMatch[1] : " ";
|
|
77
|
+
const importLine = 'import { registerGlasstrace } from "@glasstrace/sdk";\n';
|
|
78
|
+
const hasGlasstraceImport = content.includes("@glasstrace/sdk");
|
|
79
|
+
const insertPoint = match.index + match[0].length;
|
|
80
|
+
const callInjection = `
|
|
81
|
+
${indent}// Glasstrace must be registered before other instrumentation
|
|
82
|
+
${indent}registerGlasstrace();
|
|
83
|
+
`;
|
|
84
|
+
let modified;
|
|
85
|
+
if (hasGlasstraceImport) {
|
|
86
|
+
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']@glasstrace\/sdk["']/;
|
|
87
|
+
const importMatch = importRegex.exec(content);
|
|
88
|
+
if (importMatch) {
|
|
89
|
+
const specifiers = importMatch[1];
|
|
90
|
+
const alreadyImported = specifiers.split(",").some((s) => s.trim() === "registerGlasstrace");
|
|
91
|
+
if (alreadyImported) {
|
|
92
|
+
modified = content.slice(0, insertPoint) + callInjection + content.slice(insertPoint);
|
|
93
|
+
} else {
|
|
94
|
+
const existingImports = specifiers.trimEnd();
|
|
95
|
+
const separator = existingImports.endsWith(",") ? " " : ", ";
|
|
96
|
+
const updatedImport = `import { ${existingImports.trim()}${separator}registerGlasstrace } from "@glasstrace/sdk"`;
|
|
97
|
+
modified = content.replace(importMatch[0], updatedImport);
|
|
98
|
+
const newMatch = registerFnRegex.exec(modified);
|
|
99
|
+
if (newMatch) {
|
|
100
|
+
const newInsertPoint = newMatch.index + newMatch[0].length;
|
|
101
|
+
modified = modified.slice(0, newInsertPoint) + callInjection + modified.slice(newInsertPoint);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
modified = importLine + content;
|
|
106
|
+
const newMatch = registerFnRegex.exec(modified);
|
|
107
|
+
if (newMatch) {
|
|
108
|
+
const newInsertPoint = newMatch.index + newMatch[0].length;
|
|
109
|
+
modified = modified.slice(0, newInsertPoint) + callInjection + modified.slice(newInsertPoint);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
modified = importLine + content.slice(0, insertPoint) + callInjection + content.slice(insertPoint);
|
|
114
|
+
}
|
|
115
|
+
return { injected: true, content: modified };
|
|
116
|
+
}
|
|
117
|
+
var INSTRUMENTATION_FILENAMES = [
|
|
118
|
+
"instrumentation.ts",
|
|
119
|
+
"instrumentation.js",
|
|
120
|
+
"instrumentation.mjs"
|
|
121
|
+
];
|
|
122
|
+
function resolveInstrumentationTarget(projectRoot) {
|
|
123
|
+
const rootExisting = [];
|
|
124
|
+
const srcExisting = [];
|
|
125
|
+
for (const name of INSTRUMENTATION_FILENAMES) {
|
|
126
|
+
const rootPath = path.join(projectRoot, name);
|
|
127
|
+
if (isRegularFile(rootPath)) {
|
|
128
|
+
rootExisting.push(rootPath);
|
|
129
|
+
}
|
|
130
|
+
const srcPath = path.join(projectRoot, "src", name);
|
|
131
|
+
if (isRegularFile(srcPath)) {
|
|
132
|
+
srcExisting.push(srcPath);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const existing = [...rootExisting, ...srcExisting];
|
|
136
|
+
if (rootExisting.length > 0 && srcExisting.length > 0) {
|
|
137
|
+
return {
|
|
138
|
+
target: null,
|
|
139
|
+
layout: null,
|
|
140
|
+
existing,
|
|
141
|
+
rootExisting,
|
|
142
|
+
srcExisting,
|
|
143
|
+
conflict: true
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
if (srcExisting.length > 0) {
|
|
147
|
+
return {
|
|
148
|
+
target: srcExisting[0],
|
|
149
|
+
layout: "src",
|
|
150
|
+
existing,
|
|
151
|
+
rootExisting,
|
|
152
|
+
srcExisting,
|
|
153
|
+
conflict: false
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (rootExisting.length > 0) {
|
|
157
|
+
return {
|
|
158
|
+
target: rootExisting[0],
|
|
159
|
+
layout: "root",
|
|
160
|
+
existing,
|
|
161
|
+
rootExisting,
|
|
162
|
+
srcExisting,
|
|
163
|
+
conflict: false
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const srcDir = path.join(projectRoot, "src");
|
|
167
|
+
const layout = isDirectory(srcDir) ? "src" : "root";
|
|
168
|
+
const target = layout === "src" ? path.join(projectRoot, "src", "instrumentation.ts") : path.join(projectRoot, "instrumentation.ts");
|
|
169
|
+
return {
|
|
170
|
+
target,
|
|
171
|
+
layout,
|
|
172
|
+
existing,
|
|
173
|
+
rootExisting,
|
|
174
|
+
srcExisting,
|
|
175
|
+
conflict: false
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function isDirectory(p) {
|
|
179
|
+
try {
|
|
180
|
+
return fs.statSync(p).isDirectory();
|
|
181
|
+
} catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function isRegularFile(p) {
|
|
186
|
+
try {
|
|
187
|
+
const stat = fs.lstatSync(p);
|
|
188
|
+
if (stat.isSymbolicLink()) {
|
|
189
|
+
return fs.statSync(p).isFile();
|
|
190
|
+
}
|
|
191
|
+
return stat.isFile();
|
|
192
|
+
} catch {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function appendRegisterFunction(content) {
|
|
197
|
+
const importLine = 'import { registerGlasstrace } from "@glasstrace/sdk";\n';
|
|
198
|
+
const functionBlock = "\nexport async function register() {\n // Glasstrace must be registered before Prisma instrumentation\n // to ensure all ORM spans are captured correctly.\n // If you use @prisma/instrumentation, import it after this call.\n registerGlasstrace();\n}\n";
|
|
199
|
+
let withImport = content;
|
|
200
|
+
const hasGlasstraceImport = content.includes("@glasstrace/sdk");
|
|
201
|
+
if (!hasGlasstraceImport) {
|
|
202
|
+
withImport = importLine + content;
|
|
203
|
+
} else {
|
|
204
|
+
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']@glasstrace\/sdk["']/;
|
|
205
|
+
const importMatch = importRegex.exec(content);
|
|
206
|
+
if (importMatch) {
|
|
207
|
+
const specifiers = importMatch[1];
|
|
208
|
+
const alreadyImported = specifiers.split(",").some((s) => s.trim() === "registerGlasstrace");
|
|
209
|
+
if (!alreadyImported) {
|
|
210
|
+
const existingImports = specifiers.trimEnd();
|
|
211
|
+
const separator = existingImports.endsWith(",") ? " " : ", ";
|
|
212
|
+
const updatedImport = `import { ${existingImports.trim()}${separator}registerGlasstrace } from "@glasstrace/sdk"`;
|
|
213
|
+
withImport = content.replace(importMatch[0], updatedImport);
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
withImport = importLine + content;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const trailingNewline = withImport.endsWith("\n") ? "" : "\n";
|
|
220
|
+
return withImport + trailingNewline + functionBlock;
|
|
221
|
+
}
|
|
222
|
+
async function defaultInstrumentationPrompt(question, defaultValue) {
|
|
223
|
+
if (!process.stdin.isTTY) return defaultValue;
|
|
224
|
+
const readline2 = await import("node:readline");
|
|
225
|
+
const rl = readline2.createInterface({
|
|
226
|
+
input: process.stdin,
|
|
227
|
+
output: process.stdout
|
|
228
|
+
});
|
|
229
|
+
return new Promise((resolve) => {
|
|
230
|
+
const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
|
|
231
|
+
rl.question(question + suffix, (answer) => {
|
|
232
|
+
rl.close();
|
|
233
|
+
const trimmed = answer.trim().toLowerCase();
|
|
234
|
+
if (trimmed === "") {
|
|
235
|
+
resolve(defaultValue);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
resolve(trimmed === "y" || trimmed === "yes");
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
async function scaffoldInstrumentation(projectRoot, options = {}) {
|
|
243
|
+
const target = resolveInstrumentationTarget(projectRoot);
|
|
244
|
+
if (target.conflict) {
|
|
245
|
+
return {
|
|
246
|
+
action: "conflict",
|
|
247
|
+
// Point the user at the `src/` variant — modern Next.js apps with a
|
|
248
|
+
// `src/` directory load from there, so that's the merge target. The
|
|
249
|
+
// competing path is reported separately for the error message.
|
|
250
|
+
filePath: target.srcExisting[0],
|
|
251
|
+
conflictingPath: target.rootExisting[0]
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
const filePath = target.target;
|
|
255
|
+
const layout = target.layout;
|
|
256
|
+
if (filePath === null || layout === null) {
|
|
257
|
+
return { action: "unrecognized" };
|
|
258
|
+
}
|
|
259
|
+
const force = options.force === true;
|
|
260
|
+
const prompt = options.prompt ?? defaultInstrumentationPrompt;
|
|
261
|
+
if (!fs.existsSync(filePath)) {
|
|
262
|
+
const content = `import { registerGlasstrace } from "@glasstrace/sdk";
|
|
263
|
+
|
|
264
|
+
export async function register() {
|
|
265
|
+
// Glasstrace must be registered before Prisma instrumentation
|
|
266
|
+
// to ensure all ORM spans are captured correctly.
|
|
267
|
+
// If you use @prisma/instrumentation, import it after this call.
|
|
268
|
+
registerGlasstrace();
|
|
269
|
+
}
|
|
270
|
+
`;
|
|
271
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
272
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
273
|
+
return { action: "created", filePath, layout };
|
|
274
|
+
}
|
|
275
|
+
const existing = fs.readFileSync(filePath, "utf-8");
|
|
276
|
+
if (hasRegisterGlasstraceCall(existing)) {
|
|
277
|
+
return { action: "already-registered", filePath, layout };
|
|
278
|
+
}
|
|
279
|
+
if (!force) {
|
|
280
|
+
const approved = await prompt(
|
|
281
|
+
`Merge registerGlasstrace() into ${path.relative(projectRoot, filePath)}?`,
|
|
282
|
+
false
|
|
283
|
+
);
|
|
284
|
+
if (!approved) {
|
|
285
|
+
return { action: "skipped", filePath, layout };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const injectResult = injectRegisterGlasstrace(existing);
|
|
289
|
+
if (injectResult.injected) {
|
|
290
|
+
fs.writeFileSync(filePath, injectResult.content, "utf-8");
|
|
291
|
+
return { action: "injected", filePath, layout };
|
|
292
|
+
}
|
|
293
|
+
const appended = appendRegisterFunction(existing);
|
|
294
|
+
fs.writeFileSync(filePath, appended, "utf-8");
|
|
295
|
+
return { action: "appended", filePath, layout };
|
|
296
|
+
}
|
|
297
|
+
async function scaffoldNextConfig(projectRoot) {
|
|
298
|
+
let configPath;
|
|
299
|
+
let configName;
|
|
300
|
+
for (const name of NEXT_CONFIG_NAMES) {
|
|
301
|
+
const candidate = path.join(projectRoot, name);
|
|
302
|
+
if (fs.existsSync(candidate)) {
|
|
303
|
+
configPath = candidate;
|
|
304
|
+
configName = name;
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (configPath === void 0 || configName === void 0) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
const existing = fs.readFileSync(configPath, "utf-8");
|
|
312
|
+
if (existing.trim().length === 0) {
|
|
313
|
+
return { modified: false, reason: "empty-file" };
|
|
314
|
+
}
|
|
315
|
+
if (existing.includes("withGlasstraceConfig")) {
|
|
316
|
+
return { modified: false, reason: "already-wrapped" };
|
|
317
|
+
}
|
|
318
|
+
const isESM = configName.endsWith(".ts") || configName.endsWith(".mjs");
|
|
319
|
+
if (isESM) {
|
|
320
|
+
const importLine = 'import { withGlasstraceConfig } from "@glasstrace/sdk";\n';
|
|
321
|
+
const wrapResult2 = wrapExport(existing);
|
|
322
|
+
if (!wrapResult2.wrapped) {
|
|
323
|
+
return { modified: false, reason: "no-export" };
|
|
324
|
+
}
|
|
325
|
+
const modified2 = importLine + "\n" + wrapResult2.content;
|
|
326
|
+
fs.writeFileSync(configPath, modified2, "utf-8");
|
|
327
|
+
return { modified: true };
|
|
328
|
+
}
|
|
329
|
+
const requireLine = 'const { withGlasstraceConfig } = require("@glasstrace/sdk");\n';
|
|
330
|
+
const wrapResult = wrapCJSExport(existing);
|
|
331
|
+
if (!wrapResult.wrapped) {
|
|
332
|
+
return { modified: false, reason: "no-export" };
|
|
333
|
+
}
|
|
334
|
+
const modified = requireLine + "\n" + wrapResult.content;
|
|
335
|
+
fs.writeFileSync(configPath, modified, "utf-8");
|
|
336
|
+
return { modified: true };
|
|
337
|
+
}
|
|
338
|
+
function wrapExport(content) {
|
|
339
|
+
const marker = "export default";
|
|
340
|
+
const idx = content.lastIndexOf(marker);
|
|
341
|
+
if (idx === -1) {
|
|
342
|
+
return { content, wrapped: false };
|
|
343
|
+
}
|
|
344
|
+
const preamble = content.slice(0, idx);
|
|
345
|
+
const exprRaw = content.slice(idx + marker.length);
|
|
346
|
+
const expr = exprRaw.trim().replace(/;?\s*$/, "");
|
|
347
|
+
if (expr.length === 0) {
|
|
348
|
+
return { content, wrapped: false };
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
content: preamble + `export default withGlasstraceConfig(${expr});
|
|
352
|
+
`,
|
|
353
|
+
wrapped: true
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function wrapCJSExport(content) {
|
|
357
|
+
const cjsMarker = "module.exports";
|
|
358
|
+
const cjsIdx = content.lastIndexOf(cjsMarker);
|
|
359
|
+
if (cjsIdx === -1) {
|
|
360
|
+
return { content, wrapped: false };
|
|
361
|
+
}
|
|
362
|
+
const preamble = content.slice(0, cjsIdx);
|
|
363
|
+
const afterMarker = content.slice(cjsIdx + cjsMarker.length);
|
|
364
|
+
const eqMatch = /^\s*=\s*/.exec(afterMarker);
|
|
365
|
+
if (!eqMatch) {
|
|
366
|
+
return { content, wrapped: false };
|
|
367
|
+
}
|
|
368
|
+
const exprRaw = afterMarker.slice(eqMatch[0].length);
|
|
369
|
+
const expr = exprRaw.trim().replace(/;?\s*$/, "");
|
|
370
|
+
if (expr.length === 0) {
|
|
371
|
+
return { content, wrapped: false };
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
content: preamble + `module.exports = withGlasstraceConfig(${expr});
|
|
375
|
+
`,
|
|
376
|
+
wrapped: true
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
async function scaffoldEnvLocal(projectRoot) {
|
|
380
|
+
const filePath = path.join(projectRoot, ".env.local");
|
|
381
|
+
if (fs.existsSync(filePath)) {
|
|
382
|
+
const existing = fs.readFileSync(filePath, "utf-8");
|
|
383
|
+
if (/^\s*#?\s*GLASSTRACE_API_KEY\s*=/m.test(existing)) {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
387
|
+
fs.writeFileSync(filePath, existing + separator + "# GLASSTRACE_API_KEY=your_key_here\n", "utf-8");
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
fs.writeFileSync(filePath, "# GLASSTRACE_API_KEY=your_key_here\n", "utf-8");
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
async function addCoverageMapEnv(projectRoot) {
|
|
394
|
+
const filePath = path.join(projectRoot, ".env.local");
|
|
395
|
+
if (!fs.existsSync(filePath)) {
|
|
396
|
+
fs.writeFileSync(filePath, "GLASSTRACE_COVERAGE_MAP=true\n", "utf-8");
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
const existing = fs.readFileSync(filePath, "utf-8");
|
|
400
|
+
const keyRegex = /^(\s*GLASSTRACE_COVERAGE_MAP\s*=\s*)(.*)$/m;
|
|
401
|
+
const keyMatch = keyRegex.exec(existing);
|
|
402
|
+
if (keyMatch) {
|
|
403
|
+
const currentValue = keyMatch[2].trim();
|
|
404
|
+
if (currentValue === "true") {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
const updated = existing.replace(keyRegex, `${keyMatch[1]}true`);
|
|
408
|
+
fs.writeFileSync(filePath, updated, "utf-8");
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
412
|
+
fs.writeFileSync(filePath, existing + separator + "GLASSTRACE_COVERAGE_MAP=true\n", "utf-8");
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
async function scaffoldGitignore(projectRoot) {
|
|
416
|
+
const filePath = path.join(projectRoot, ".gitignore");
|
|
417
|
+
if (fs.existsSync(filePath)) {
|
|
418
|
+
const existing = fs.readFileSync(filePath, "utf-8");
|
|
419
|
+
const lines = existing.split("\n").map((l) => l.trim());
|
|
420
|
+
if (lines.includes(".glasstrace/")) {
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
424
|
+
fs.writeFileSync(filePath, existing + separator + ".glasstrace/\n", "utf-8");
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
fs.writeFileSync(filePath, ".glasstrace/\n", "utf-8");
|
|
428
|
+
return true;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// src/cli/init.ts
|
|
61
432
|
function meetsNodeVersion(minMajor) {
|
|
62
433
|
const [major] = process.versions.node.split(".").map(Number);
|
|
63
434
|
return major >= minMajor;
|
|
@@ -65,8 +436,8 @@ function meetsNodeVersion(minMajor) {
|
|
|
65
436
|
async function decideMcpConfigAction(options) {
|
|
66
437
|
const { configPath, expectedContent, force } = options;
|
|
67
438
|
if (configPath === null) return "write";
|
|
68
|
-
const exists = options.existsSync ??
|
|
69
|
-
const read = options.readFile ?? ((p) =>
|
|
439
|
+
const exists = options.existsSync ?? fs2.existsSync;
|
|
440
|
+
const read = options.readFile ?? ((p) => fs2.readFileSync(p, "utf-8"));
|
|
70
441
|
const prompt = options.prompt ?? promptYesNo;
|
|
71
442
|
if (!exists(configPath)) return "write";
|
|
72
443
|
let existingContent;
|
|
@@ -163,17 +534,17 @@ async function rollbackSteps(steps, projectRoot, state) {
|
|
|
163
534
|
try {
|
|
164
535
|
switch (step) {
|
|
165
536
|
case "instrumentation": {
|
|
166
|
-
const instrPath = state?.instrumentationPath ??
|
|
167
|
-
if (
|
|
168
|
-
const content =
|
|
537
|
+
const instrPath = state?.instrumentationPath ?? path2.join(projectRoot, "instrumentation.ts");
|
|
538
|
+
if (fs2.existsSync(instrPath)) {
|
|
539
|
+
const content = fs2.readFileSync(instrPath, "utf-8");
|
|
169
540
|
if (isInitCreatedInstrumentation(content)) {
|
|
170
|
-
|
|
541
|
+
fs2.unlinkSync(instrPath);
|
|
171
542
|
} else if (state?.originalInstrumentationContent !== void 0) {
|
|
172
|
-
|
|
543
|
+
fs2.writeFileSync(instrPath, state.originalInstrumentationContent, "utf-8");
|
|
173
544
|
} else {
|
|
174
545
|
const cleaned = removeRegisterGlasstrace(content);
|
|
175
546
|
if (cleaned !== content) {
|
|
176
|
-
|
|
547
|
+
fs2.writeFileSync(instrPath, cleaned, "utf-8");
|
|
177
548
|
}
|
|
178
549
|
}
|
|
179
550
|
}
|
|
@@ -181,11 +552,11 @@ async function rollbackSteps(steps, projectRoot, state) {
|
|
|
181
552
|
}
|
|
182
553
|
case "next-config": {
|
|
183
554
|
for (const name of NEXT_CONFIG_NAMES) {
|
|
184
|
-
const configPath =
|
|
185
|
-
if (!
|
|
555
|
+
const configPath = path2.join(projectRoot, name);
|
|
556
|
+
if (!fs2.existsSync(configPath)) {
|
|
186
557
|
continue;
|
|
187
558
|
}
|
|
188
|
-
const content =
|
|
559
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
189
560
|
if (!content.includes("withGlasstraceConfig")) {
|
|
190
561
|
continue;
|
|
191
562
|
}
|
|
@@ -193,16 +564,16 @@ async function rollbackSteps(steps, projectRoot, state) {
|
|
|
193
564
|
const unwrapResult = isESM ? unwrapExport(content) : unwrapCJSExport(content);
|
|
194
565
|
if (unwrapResult.unwrapped) {
|
|
195
566
|
const cleaned = removeGlasstraceConfigImport(unwrapResult.content);
|
|
196
|
-
|
|
567
|
+
fs2.writeFileSync(configPath, cleanLeadingBlankLines(cleaned), "utf-8");
|
|
197
568
|
}
|
|
198
569
|
break;
|
|
199
570
|
}
|
|
200
571
|
break;
|
|
201
572
|
}
|
|
202
573
|
case "env-local": {
|
|
203
|
-
const envPath =
|
|
204
|
-
if (
|
|
205
|
-
const content =
|
|
574
|
+
const envPath = path2.join(projectRoot, ".env.local");
|
|
575
|
+
if (fs2.existsSync(envPath)) {
|
|
576
|
+
const content = fs2.readFileSync(envPath, "utf-8");
|
|
206
577
|
const lines = content.split("\n");
|
|
207
578
|
const filtered = lines.filter((line) => {
|
|
208
579
|
const trimmed = line.trim();
|
|
@@ -211,18 +582,18 @@ async function rollbackSteps(steps, projectRoot, state) {
|
|
|
211
582
|
if (filtered.length !== lines.length) {
|
|
212
583
|
const result = filtered.join("\n");
|
|
213
584
|
if (result.trim().length === 0) {
|
|
214
|
-
|
|
585
|
+
fs2.unlinkSync(envPath);
|
|
215
586
|
} else {
|
|
216
|
-
|
|
587
|
+
fs2.writeFileSync(envPath, result, "utf-8");
|
|
217
588
|
}
|
|
218
589
|
}
|
|
219
590
|
}
|
|
220
591
|
break;
|
|
221
592
|
}
|
|
222
593
|
case "gitignore": {
|
|
223
|
-
const gitignorePath =
|
|
224
|
-
if (
|
|
225
|
-
const content =
|
|
594
|
+
const gitignorePath = path2.join(projectRoot, ".gitignore");
|
|
595
|
+
if (fs2.existsSync(gitignorePath)) {
|
|
596
|
+
const content = fs2.readFileSync(gitignorePath, "utf-8");
|
|
226
597
|
const lines = content.split("\n");
|
|
227
598
|
const filtered = lines.filter(
|
|
228
599
|
(line) => line.trim() !== ".glasstrace/"
|
|
@@ -230,9 +601,9 @@ async function rollbackSteps(steps, projectRoot, state) {
|
|
|
230
601
|
if (filtered.length !== lines.length) {
|
|
231
602
|
const result = filtered.join("\n");
|
|
232
603
|
if (result.trim().length === 0) {
|
|
233
|
-
|
|
604
|
+
fs2.unlinkSync(gitignorePath);
|
|
234
605
|
} else {
|
|
235
|
-
|
|
606
|
+
fs2.writeFileSync(gitignorePath, result, "utf-8");
|
|
236
607
|
}
|
|
237
608
|
}
|
|
238
609
|
}
|
|
@@ -263,8 +634,8 @@ async function runInit(options) {
|
|
|
263
634
|
errors.push(err instanceof Error ? err.message : String(err));
|
|
264
635
|
return { exitCode: 1, summary, warnings, errors };
|
|
265
636
|
}
|
|
266
|
-
const packageJsonPath =
|
|
267
|
-
if (!
|
|
637
|
+
const packageJsonPath = path2.join(projectRoot, "package.json");
|
|
638
|
+
if (!fs2.existsSync(packageJsonPath)) {
|
|
268
639
|
errors.push("No package.json found. Run this command from a Node.js project root.");
|
|
269
640
|
return { exitCode: 1, summary, warnings, errors };
|
|
270
641
|
}
|
|
@@ -273,8 +644,8 @@ async function runInit(options) {
|
|
|
273
644
|
const preResolved = resolveInstrumentationTarget(projectRoot);
|
|
274
645
|
if (!preResolved.conflict && preResolved.target !== null) {
|
|
275
646
|
rollbackState.instrumentationPath = preResolved.target;
|
|
276
|
-
if (
|
|
277
|
-
rollbackState.originalInstrumentationContent =
|
|
647
|
+
if (fs2.existsSync(preResolved.target)) {
|
|
648
|
+
rollbackState.originalInstrumentationContent = fs2.readFileSync(
|
|
278
649
|
preResolved.target,
|
|
279
650
|
"utf-8"
|
|
280
651
|
);
|
|
@@ -289,7 +660,7 @@ async function runInit(options) {
|
|
|
289
660
|
if (instrResult.filePath !== void 0) {
|
|
290
661
|
rollbackState.instrumentationPath = instrResult.filePath;
|
|
291
662
|
}
|
|
292
|
-
const relativePath = instrResult.filePath !== void 0 ?
|
|
663
|
+
const relativePath = instrResult.filePath !== void 0 ? path2.relative(projectRoot, instrResult.filePath) : "instrumentation.ts";
|
|
293
664
|
switch (instrResult.action) {
|
|
294
665
|
case "created":
|
|
295
666
|
summary.push(`Created ${relativePath}`);
|
|
@@ -314,8 +685,8 @@ async function runInit(options) {
|
|
|
314
685
|
);
|
|
315
686
|
break;
|
|
316
687
|
case "conflict": {
|
|
317
|
-
const primary = instrResult.filePath !== void 0 ?
|
|
318
|
-
const competing = instrResult.conflictingPath !== void 0 ?
|
|
688
|
+
const primary = instrResult.filePath !== void 0 ? path2.relative(projectRoot, instrResult.filePath) : "src/instrumentation.ts";
|
|
689
|
+
const competing = instrResult.conflictingPath !== void 0 ? path2.relative(projectRoot, instrResult.conflictingPath) : "instrumentation.ts";
|
|
319
690
|
await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
|
|
320
691
|
errors.push(
|
|
321
692
|
`Both ${primary} and ${competing} exist. Next.js's loader behavior is undefined when both are present.
|
|
@@ -362,10 +733,10 @@ Then add this as the first statement in your register() function:
|
|
|
362
733
|
return { exitCode: 1, summary, warnings, errors };
|
|
363
734
|
}
|
|
364
735
|
try {
|
|
365
|
-
const envPathForCheck =
|
|
736
|
+
const envPathForCheck = path2.join(projectRoot, ".env.local");
|
|
366
737
|
let existingDevKey = false;
|
|
367
|
-
if (
|
|
368
|
-
const existingContent =
|
|
738
|
+
if (fs2.existsSync(envPathForCheck)) {
|
|
739
|
+
const existingContent = fs2.readFileSync(envPathForCheck, "utf-8");
|
|
369
740
|
existingDevKey = isDevApiKey(readEnvLocalApiKey(existingContent));
|
|
370
741
|
}
|
|
371
742
|
const envCreated = await scaffoldEnvLocal(projectRoot);
|
|
@@ -430,10 +801,10 @@ Then add this as the first statement in your register() function:
|
|
|
430
801
|
);
|
|
431
802
|
break;
|
|
432
803
|
}
|
|
433
|
-
const gitignorePath =
|
|
434
|
-
if (
|
|
804
|
+
const gitignorePath = path2.join(projectRoot, ".gitignore");
|
|
805
|
+
if (fs2.existsSync(gitignorePath)) {
|
|
435
806
|
try {
|
|
436
|
-
const gitignoreContent =
|
|
807
|
+
const gitignoreContent = fs2.readFileSync(gitignorePath, "utf-8");
|
|
437
808
|
if (gitignoreExcludesDiscoveryFile(gitignoreContent, discoveryResult.layout)) {
|
|
438
809
|
warnings.push(
|
|
439
810
|
`Your .gitignore excludes ${relPath} (directly or via a parent rule). The discovery file must be committed for the Glasstrace browser extension to find it in deployed builds. Remove the matching line from .gitignore or add an explicit negation (e.g. \`!` + relPath + "`)."
|
|
@@ -450,15 +821,18 @@ Then add this as the first statement in your register() function:
|
|
|
450
821
|
);
|
|
451
822
|
}
|
|
452
823
|
let anyConfigWritten = false;
|
|
824
|
+
let anyConfigRewrittenWithBearer = false;
|
|
825
|
+
const resolved = await resolveEffectiveMcpCredential(projectRoot);
|
|
826
|
+
const bearer = resolved.effective?.key ?? anonKey;
|
|
453
827
|
if (isCI) {
|
|
454
828
|
const genericAgent = {
|
|
455
829
|
name: "generic",
|
|
456
|
-
mcpConfigPath:
|
|
830
|
+
mcpConfigPath: path2.join(projectRoot, ".glasstrace", "mcp.json"),
|
|
457
831
|
infoFilePath: null,
|
|
458
832
|
cliAvailable: false,
|
|
459
833
|
registrationCommand: null
|
|
460
834
|
};
|
|
461
|
-
const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT,
|
|
835
|
+
const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, bearer);
|
|
462
836
|
const decision = await decideMcpConfigAction({
|
|
463
837
|
configPath: genericAgent.mcpConfigPath,
|
|
464
838
|
expectedContent: genericConfig,
|
|
@@ -466,8 +840,11 @@ Then add this as the first statement in your register() function:
|
|
|
466
840
|
});
|
|
467
841
|
if (decision !== "skip") {
|
|
468
842
|
await writeMcpConfig(genericAgent, genericConfig, projectRoot);
|
|
843
|
+
if (genericAgent.mcpConfigPath !== null && fs2.existsSync(genericAgent.mcpConfigPath)) {
|
|
844
|
+
anyConfigRewrittenWithBearer = true;
|
|
845
|
+
}
|
|
469
846
|
}
|
|
470
|
-
if (genericAgent.mcpConfigPath !== null &&
|
|
847
|
+
if (genericAgent.mcpConfigPath !== null && fs2.existsSync(genericAgent.mcpConfigPath)) {
|
|
471
848
|
anyConfigWritten = true;
|
|
472
849
|
summary.push("Created .glasstrace/mcp.json (CI mode)");
|
|
473
850
|
}
|
|
@@ -481,22 +858,23 @@ Then add this as the first statement in your register() function:
|
|
|
481
858
|
);
|
|
482
859
|
const genericAgent = {
|
|
483
860
|
name: "generic",
|
|
484
|
-
mcpConfigPath:
|
|
861
|
+
mcpConfigPath: path2.join(projectRoot, ".glasstrace", "mcp.json"),
|
|
485
862
|
infoFilePath: null,
|
|
486
863
|
cliAvailable: false,
|
|
487
864
|
registrationCommand: null
|
|
488
865
|
};
|
|
489
|
-
const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT,
|
|
866
|
+
const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, bearer);
|
|
490
867
|
await writeMcpConfig(genericAgent, genericConfig, projectRoot);
|
|
491
|
-
if (genericAgent.mcpConfigPath !== null &&
|
|
868
|
+
if (genericAgent.mcpConfigPath !== null && fs2.existsSync(genericAgent.mcpConfigPath)) {
|
|
492
869
|
anyConfigWritten = true;
|
|
870
|
+
anyConfigRewrittenWithBearer = true;
|
|
493
871
|
}
|
|
494
872
|
agents = [];
|
|
495
873
|
}
|
|
496
874
|
const configuredNames = [];
|
|
497
875
|
for (const agent of agents) {
|
|
498
876
|
try {
|
|
499
|
-
const configContent = generateMcpConfig(agent, MCP_ENDPOINT,
|
|
877
|
+
const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
|
|
500
878
|
const decision = await decideMcpConfigAction({
|
|
501
879
|
configPath: agent.mcpConfigPath,
|
|
502
880
|
expectedContent: configContent,
|
|
@@ -506,17 +884,18 @@ Then add this as the first statement in your register() function:
|
|
|
506
884
|
summary.push(
|
|
507
885
|
`Preserved existing ${agent.mcpConfigPath ?? agent.name} (user declined overwrite)`
|
|
508
886
|
);
|
|
509
|
-
if (agent.mcpConfigPath !== null &&
|
|
887
|
+
if (agent.mcpConfigPath !== null && fs2.existsSync(agent.mcpConfigPath)) {
|
|
510
888
|
anyConfigWritten = true;
|
|
511
889
|
}
|
|
512
890
|
continue;
|
|
513
891
|
}
|
|
514
892
|
await writeMcpConfig(agent, configContent, projectRoot);
|
|
515
|
-
const configExists = agent.mcpConfigPath !== null &&
|
|
893
|
+
const configExists = agent.mcpConfigPath !== null && fs2.existsSync(agent.mcpConfigPath);
|
|
516
894
|
if (!configExists) {
|
|
517
895
|
continue;
|
|
518
896
|
}
|
|
519
897
|
anyConfigWritten = true;
|
|
898
|
+
anyConfigRewrittenWithBearer = true;
|
|
520
899
|
const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
|
|
521
900
|
if (infoContent !== "") {
|
|
522
901
|
await injectInfoSection(agent, infoContent, projectRoot);
|
|
@@ -540,8 +919,13 @@ Then add this as the first statement in your register() function:
|
|
|
540
919
|
[".mcp.json", ".cursor/mcp.json", ".gemini/settings.json", ".codex/config.toml"],
|
|
541
920
|
projectRoot
|
|
542
921
|
);
|
|
543
|
-
if (
|
|
544
|
-
const
|
|
922
|
+
if (anyConfigRewrittenWithBearer) {
|
|
923
|
+
const markerSource = resolved.effective?.source ?? "anon";
|
|
924
|
+
const markerHash = identityFingerprint(bearer);
|
|
925
|
+
const markerCreated = await writeMcpMarker(projectRoot, {
|
|
926
|
+
credentialSource: markerSource,
|
|
927
|
+
credentialHash: markerHash
|
|
928
|
+
});
|
|
545
929
|
if (markerCreated) {
|
|
546
930
|
summary.push("Created .glasstrace/mcp-connected marker");
|
|
547
931
|
}
|
|
@@ -598,9 +982,9 @@ async function verifyAnonKeyRegistration(projectRoot) {
|
|
|
598
982
|
}
|
|
599
983
|
let devKey;
|
|
600
984
|
try {
|
|
601
|
-
const envPath =
|
|
602
|
-
if (
|
|
603
|
-
const envContent =
|
|
985
|
+
const envPath = path2.join(projectRoot, ".env.local");
|
|
986
|
+
if (fs2.existsSync(envPath)) {
|
|
987
|
+
const envContent = fs2.readFileSync(envPath, "utf-8");
|
|
604
988
|
const effective = readEnvLocalApiKey(envContent);
|
|
605
989
|
if (effective !== null && isDevApiKey(effective)) {
|
|
606
990
|
devKey = effective;
|
|
@@ -610,7 +994,7 @@ async function verifyAnonKeyRegistration(projectRoot) {
|
|
|
610
994
|
}
|
|
611
995
|
const baseConfig = resolveConfig({ apiKey: devKey });
|
|
612
996
|
const config = { ...baseConfig, apiKey: devKey };
|
|
613
|
-
const sdkVersion = true ? "1.1.
|
|
997
|
+
const sdkVersion = true ? "1.1.2" : "0.0.0-dev";
|
|
614
998
|
const result = await verifyInitReachable(config, anonKey, sdkVersion);
|
|
615
999
|
if (result.ok) {
|
|
616
1000
|
return { outcome: "verified" };
|
|
@@ -659,7 +1043,7 @@ function parseArgs(argv) {
|
|
|
659
1043
|
};
|
|
660
1044
|
}
|
|
661
1045
|
var scriptPath = typeof process !== "undefined" && process.argv[1] !== void 0 ? process.argv[1].replace(/\\/g, "/") : void 0;
|
|
662
|
-
var scriptBasename = scriptPath !== void 0 ?
|
|
1046
|
+
var scriptBasename = scriptPath !== void 0 ? path2.basename(scriptPath) : void 0;
|
|
663
1047
|
var isDirectExecution = scriptPath !== void 0 && (scriptPath.endsWith("/cli/init.js") || scriptPath.endsWith("/cli/init.ts") || scriptBasename === "glasstrace");
|
|
664
1048
|
if (isDirectExecution) {
|
|
665
1049
|
if (!meetsNodeVersion(20)) {
|
|
@@ -806,7 +1190,7 @@ Usage: glasstrace mcp add [--force] [--dry-run]
|
|
|
806
1190
|
} else if (subcommand === "status") {
|
|
807
1191
|
const remainingArgs = process.argv.slice(3);
|
|
808
1192
|
const json = remainingArgs.includes("--json");
|
|
809
|
-
Promise.all([import("./status.js"), import("../monorepo-
|
|
1193
|
+
Promise.all([import("./status.js"), import("../monorepo-PFVNPQ6X.js")]).then(([{ runStatus }, { resolveProjectRoot: resolve }]) => {
|
|
810
1194
|
let projectRoot = process.cwd();
|
|
811
1195
|
try {
|
|
812
1196
|
projectRoot = resolve(projectRoot).projectRoot;
|