@glasstrace/sdk 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/{chunk-KE7MCPO5.js → chunk-4EZ6JTDG.js} +2 -2
  2. package/dist/{chunk-67RIOAXV.js → chunk-6RNBUUBR.js} +2 -2
  3. package/dist/{chunk-DXRZKKSO.js → chunk-7SZQN6IU.js} +1 -3
  4. package/dist/chunk-7SZQN6IU.js.map +1 -0
  5. package/dist/{chunk-55FBXXER.js → chunk-DIM4JRXM.js} +2 -2
  6. package/dist/{chunk-UGJ3X4CT.js → chunk-DST4UBXU.js} +2 -2
  7. package/dist/{chunk-DO2YPMQ5.js → chunk-MXDZHFJQ.js} +23 -5
  8. package/dist/chunk-MXDZHFJQ.js.map +1 -0
  9. package/dist/chunk-P22UQ2OJ.js +384 -0
  10. package/dist/chunk-P22UQ2OJ.js.map +1 -0
  11. package/dist/{chunk-HAU66QBQ.js → chunk-P4OYPFQ5.js} +9 -9
  12. package/dist/chunk-P4OYPFQ5.js.map +1 -0
  13. package/dist/{chunk-TQ54WLCZ.js → chunk-X5MAXP5T.js} +2 -1
  14. package/dist/{chunk-ZBTC5QIQ.js → chunk-Y26HJUPD.js} +9 -9
  15. package/dist/{chunk-LU3PPAOQ.js → chunk-ZRDQ6ZKI.js} +474 -93
  16. package/dist/chunk-ZRDQ6ZKI.js.map +1 -0
  17. package/dist/cli/init.cjs +1118 -946
  18. package/dist/cli/init.cjs.map +1 -1
  19. package/dist/cli/init.js +42 -29
  20. package/dist/cli/init.js.map +1 -1
  21. package/dist/cli/mcp-add.cjs +243 -83
  22. package/dist/cli/mcp-add.cjs.map +1 -1
  23. package/dist/cli/mcp-add.d.cts +35 -4
  24. package/dist/cli/mcp-add.d.ts +35 -4
  25. package/dist/cli/mcp-add.js +48 -24
  26. package/dist/cli/mcp-add.js.map +1 -1
  27. package/dist/cli/status.cjs.map +1 -1
  28. package/dist/cli/status.js +3 -1
  29. package/dist/cli/status.js.map +1 -1
  30. package/dist/cli/uninit.cjs +4 -4
  31. package/dist/cli/uninit.cjs.map +1 -1
  32. package/dist/cli/uninit.js +4 -4
  33. package/dist/edge-entry.js +2 -2
  34. package/dist/index.cjs +293 -11
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.js +5 -5
  37. package/dist/{monorepo-N5Z63XP7.js → monorepo-GSL6JD3G.js} +5 -3
  38. package/dist/node-entry.cjs +293 -11
  39. package/dist/node-entry.cjs.map +1 -1
  40. package/dist/node-entry.js +7 -7
  41. package/dist/node-subpath.js +3 -3
  42. package/dist/{source-map-uploader-BJIXRLJ6.js → source-map-uploader-DPUUCLNW.js} +3 -3
  43. package/package.json +1 -1
  44. package/dist/chunk-DO2YPMQ5.js.map +0 -1
  45. package/dist/chunk-DXRZKKSO.js.map +0 -1
  46. package/dist/chunk-HAU66QBQ.js.map +0 -1
  47. package/dist/chunk-IP4NMDJK.js +0 -98
  48. package/dist/chunk-IP4NMDJK.js.map +0 -1
  49. package/dist/chunk-LU3PPAOQ.js.map +0 -1
  50. package/dist/chunk-O63DJKIJ.js +0 -460
  51. package/dist/chunk-O63DJKIJ.js.map +0 -1
  52. /package/dist/{chunk-KE7MCPO5.js.map → chunk-4EZ6JTDG.js.map} +0 -0
  53. /package/dist/{chunk-67RIOAXV.js.map → chunk-6RNBUUBR.js.map} +0 -0
  54. /package/dist/{chunk-55FBXXER.js.map → chunk-DIM4JRXM.js.map} +0 -0
  55. /package/dist/{chunk-UGJ3X4CT.js.map → chunk-DST4UBXU.js.map} +0 -0
  56. /package/dist/{chunk-TQ54WLCZ.js.map → chunk-X5MAXP5T.js.map} +0 -0
  57. /package/dist/{chunk-ZBTC5QIQ.js.map → chunk-Y26HJUPD.js.map} +0 -0
  58. /package/dist/{monorepo-N5Z63XP7.js.map → monorepo-GSL6JD3G.js.map} +0 -0
  59. /package/dist/{source-map-uploader-BJIXRLJ6.js.map → source-map-uploader-DPUUCLNW.js.map} +0 -0
package/dist/cli/init.cjs CHANGED
@@ -31,889 +31,418 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  ));
32
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
 
34
- // src/cli/constants.ts
35
- function formatAgentName(name) {
36
- const displayNames = {
37
- claude: "Claude Code",
38
- codex: "Codex",
39
- gemini: "Gemini",
40
- cursor: "Cursor",
41
- windsurf: "Windsurf",
42
- generic: "Generic"
43
- };
44
- return displayNames[name];
45
- }
46
- var MCP_ENDPOINT, NEXT_CONFIG_NAMES;
47
- var init_constants = __esm({
48
- "src/cli/constants.ts"() {
49
- "use strict";
50
- MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
51
- NEXT_CONFIG_NAMES = ["next.config.ts", "next.config.js", "next.config.mjs"];
52
- }
53
- });
54
-
55
- // src/cli/scaffolder.ts
56
- function identityFingerprint(token) {
57
- return `sha256:${(0, import_node_crypto.createHash)("sha256").update(token).digest("hex")}`;
58
- }
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 hasGlasstraceImport2 = 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 (hasGlasstraceImport2) {
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
- }
34
+ // ../../node_modules/zod/v4/core/core.js
35
+ // @__NO_SIDE_EFFECTS__
36
+ function $constructor(name, initializer3, params) {
37
+ function init(inst, def) {
38
+ if (!inst._zod) {
39
+ Object.defineProperty(inst, "_zod", {
40
+ value: {
41
+ def,
42
+ constr: _,
43
+ traits: /* @__PURE__ */ new Set()
44
+ },
45
+ enumerable: false
46
+ });
111
47
  }
112
- } else {
113
- modified = importLine + content.slice(0, insertPoint) + callInjection + content.slice(insertPoint);
114
- }
115
- return { injected: true, content: modified };
116
- }
117
- function resolveInstrumentationTarget(projectRoot) {
118
- const rootExisting = [];
119
- const srcExisting = [];
120
- for (const name of INSTRUMENTATION_FILENAMES) {
121
- const rootPath = path.join(projectRoot, name);
122
- if (isRegularFile(rootPath)) {
123
- rootExisting.push(rootPath);
48
+ if (inst._zod.traits.has(name)) {
49
+ return;
124
50
  }
125
- const srcPath = path.join(projectRoot, "src", name);
126
- if (isRegularFile(srcPath)) {
127
- srcExisting.push(srcPath);
51
+ inst._zod.traits.add(name);
52
+ initializer3(inst, def);
53
+ const proto = _.prototype;
54
+ const keys = Object.keys(proto);
55
+ for (let i = 0; i < keys.length; i++) {
56
+ const k = keys[i];
57
+ if (!(k in inst)) {
58
+ inst[k] = proto[k].bind(inst);
59
+ }
128
60
  }
129
61
  }
130
- const existing = [...rootExisting, ...srcExisting];
131
- if (rootExisting.length > 0 && srcExisting.length > 0) {
132
- return {
133
- target: null,
134
- layout: null,
135
- existing,
136
- rootExisting,
137
- srcExisting,
138
- conflict: true
139
- };
140
- }
141
- if (srcExisting.length > 0) {
142
- return {
143
- target: srcExisting[0],
144
- layout: "src",
145
- existing,
146
- rootExisting,
147
- srcExisting,
148
- conflict: false
149
- };
150
- }
151
- if (rootExisting.length > 0) {
152
- return {
153
- target: rootExisting[0],
154
- layout: "root",
155
- existing,
156
- rootExisting,
157
- srcExisting,
158
- conflict: false
159
- };
160
- }
161
- const srcDir = path.join(projectRoot, "src");
162
- const layout = isDirectory(srcDir) ? "src" : "root";
163
- const target = layout === "src" ? path.join(projectRoot, "src", "instrumentation.ts") : path.join(projectRoot, "instrumentation.ts");
164
- return {
165
- target,
166
- layout,
167
- existing,
168
- rootExisting,
169
- srcExisting,
170
- conflict: false
171
- };
172
- }
173
- function isDirectory(p) {
174
- try {
175
- return fs.statSync(p).isDirectory();
176
- } catch {
177
- return false;
62
+ const Parent = params?.Parent ?? Object;
63
+ class Definition extends Parent {
178
64
  }
179
- }
180
- function isRegularFile(p) {
181
- try {
182
- const stat2 = fs.lstatSync(p);
183
- if (stat2.isSymbolicLink()) {
184
- return fs.statSync(p).isFile();
65
+ Object.defineProperty(Definition, "name", { value: name });
66
+ function _(def) {
67
+ var _a2;
68
+ const inst = params?.Parent ? new Definition() : this;
69
+ init(inst, def);
70
+ (_a2 = inst._zod).deferred ?? (_a2.deferred = []);
71
+ for (const fn of inst._zod.deferred) {
72
+ fn();
185
73
  }
186
- return stat2.isFile();
187
- } catch {
188
- return false;
74
+ return inst;
189
75
  }
190
- }
191
- function appendRegisterFunction(content) {
192
- const importLine = 'import { registerGlasstrace } from "@glasstrace/sdk";\n';
193
- 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";
194
- let withImport = content;
195
- const hasGlasstraceImport2 = content.includes("@glasstrace/sdk");
196
- if (!hasGlasstraceImport2) {
197
- withImport = importLine + content;
198
- } else {
199
- const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']@glasstrace\/sdk["']/;
200
- const importMatch = importRegex.exec(content);
201
- if (importMatch) {
202
- const specifiers = importMatch[1];
203
- const alreadyImported = specifiers.split(",").some((s) => s.trim() === "registerGlasstrace");
204
- if (!alreadyImported) {
205
- const existingImports = specifiers.trimEnd();
206
- const separator = existingImports.endsWith(",") ? " " : ", ";
207
- const updatedImport = `import { ${existingImports.trim()}${separator}registerGlasstrace } from "@glasstrace/sdk"`;
208
- withImport = content.replace(importMatch[0], updatedImport);
209
- }
210
- } else {
211
- withImport = importLine + content;
76
+ Object.defineProperty(_, "init", { value: init });
77
+ Object.defineProperty(_, Symbol.hasInstance, {
78
+ value: (inst) => {
79
+ if (params?.Parent && inst instanceof params.Parent)
80
+ return true;
81
+ return inst?._zod?.traits?.has(name);
212
82
  }
213
- }
214
- const trailingNewline = withImport.endsWith("\n") ? "" : "\n";
215
- return withImport + trailingNewline + functionBlock;
216
- }
217
- async function defaultInstrumentationPrompt(question, defaultValue) {
218
- if (!process.stdin.isTTY) return defaultValue;
219
- const readline2 = await import("node:readline");
220
- const rl = readline2.createInterface({
221
- input: process.stdin,
222
- output: process.stdout
223
- });
224
- return new Promise((resolve2) => {
225
- const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
226
- rl.question(question + suffix, (answer) => {
227
- rl.close();
228
- const trimmed = answer.trim().toLowerCase();
229
- if (trimmed === "") {
230
- resolve2(defaultValue);
231
- return;
232
- }
233
- resolve2(trimmed === "y" || trimmed === "yes");
234
- });
235
83
  });
84
+ Object.defineProperty(_, "name", { value: name });
85
+ return _;
236
86
  }
237
- async function scaffoldInstrumentation(projectRoot, options = {}) {
238
- const target = resolveInstrumentationTarget(projectRoot);
239
- if (target.conflict) {
240
- return {
241
- action: "conflict",
242
- // Point the user at the `src/` variant — modern Next.js apps with a
243
- // `src/` directory load from there, so that's the merge target. The
244
- // competing path is reported separately for the error message.
245
- filePath: target.srcExisting[0],
246
- conflictingPath: target.rootExisting[0]
247
- };
248
- }
249
- const filePath = target.target;
250
- const layout = target.layout;
251
- if (filePath === null || layout === null) {
252
- return { action: "unrecognized" };
253
- }
254
- const force = options.force === true;
255
- const prompt = options.prompt ?? defaultInstrumentationPrompt;
256
- if (!fs.existsSync(filePath)) {
257
- const content = `import { registerGlasstrace } from "@glasstrace/sdk";
258
-
259
- export async function register() {
260
- // Glasstrace must be registered before Prisma instrumentation
261
- // to ensure all ORM spans are captured correctly.
262
- // If you use @prisma/instrumentation, import it after this call.
263
- registerGlasstrace();
87
+ function config(newConfig) {
88
+ if (newConfig)
89
+ Object.assign(globalConfig, newConfig);
90
+ return globalConfig;
264
91
  }
265
- `;
266
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
267
- fs.writeFileSync(filePath, content, "utf-8");
268
- return { action: "created", filePath, layout };
269
- }
270
- const existing = fs.readFileSync(filePath, "utf-8");
271
- if (hasRegisterGlasstraceCall(existing)) {
272
- return { action: "already-registered", filePath, layout };
273
- }
274
- if (!force) {
275
- const approved = await prompt(
276
- `Merge registerGlasstrace() into ${path.relative(projectRoot, filePath)}?`,
277
- false
278
- );
279
- if (!approved) {
280
- return { action: "skipped", filePath, layout };
281
- }
282
- }
283
- const injectResult = injectRegisterGlasstrace(existing);
284
- if (injectResult.injected) {
285
- fs.writeFileSync(filePath, injectResult.content, "utf-8");
286
- return { action: "injected", filePath, layout };
92
+ var NEVER, $brand, $ZodAsyncError, $ZodEncodeError, globalConfig;
93
+ var init_core = __esm({
94
+ "../../node_modules/zod/v4/core/core.js"() {
95
+ "use strict";
96
+ NEVER = Object.freeze({
97
+ status: "aborted"
98
+ });
99
+ $brand = /* @__PURE__ */ Symbol("zod_brand");
100
+ $ZodAsyncError = class extends Error {
101
+ constructor() {
102
+ super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
103
+ }
104
+ };
105
+ $ZodEncodeError = class extends Error {
106
+ constructor(name) {
107
+ super(`Encountered unidirectional transform during encode: ${name}`);
108
+ this.name = "ZodEncodeError";
109
+ }
110
+ };
111
+ globalConfig = {};
287
112
  }
288
- const appended = appendRegisterFunction(existing);
289
- fs.writeFileSync(filePath, appended, "utf-8");
290
- return { action: "appended", filePath, layout };
113
+ });
114
+
115
+ // ../../node_modules/zod/v4/core/util.js
116
+ var util_exports = {};
117
+ __export(util_exports, {
118
+ BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES,
119
+ Class: () => Class,
120
+ NUMBER_FORMAT_RANGES: () => NUMBER_FORMAT_RANGES,
121
+ aborted: () => aborted,
122
+ allowsEval: () => allowsEval,
123
+ assert: () => assert,
124
+ assertEqual: () => assertEqual,
125
+ assertIs: () => assertIs,
126
+ assertNever: () => assertNever,
127
+ assertNotEqual: () => assertNotEqual,
128
+ assignProp: () => assignProp,
129
+ base64ToUint8Array: () => base64ToUint8Array,
130
+ base64urlToUint8Array: () => base64urlToUint8Array,
131
+ cached: () => cached,
132
+ captureStackTrace: () => captureStackTrace,
133
+ cleanEnum: () => cleanEnum,
134
+ cleanRegex: () => cleanRegex,
135
+ clone: () => clone,
136
+ cloneDef: () => cloneDef,
137
+ createTransparentProxy: () => createTransparentProxy,
138
+ defineLazy: () => defineLazy,
139
+ esc: () => esc,
140
+ escapeRegex: () => escapeRegex,
141
+ extend: () => extend,
142
+ finalizeIssue: () => finalizeIssue,
143
+ floatSafeRemainder: () => floatSafeRemainder,
144
+ getElementAtPath: () => getElementAtPath,
145
+ getEnumValues: () => getEnumValues,
146
+ getLengthableOrigin: () => getLengthableOrigin,
147
+ getParsedType: () => getParsedType,
148
+ getSizableOrigin: () => getSizableOrigin,
149
+ hexToUint8Array: () => hexToUint8Array,
150
+ isObject: () => isObject,
151
+ isPlainObject: () => isPlainObject,
152
+ issue: () => issue,
153
+ joinValues: () => joinValues,
154
+ jsonStringifyReplacer: () => jsonStringifyReplacer,
155
+ merge: () => merge,
156
+ mergeDefs: () => mergeDefs,
157
+ normalizeParams: () => normalizeParams,
158
+ nullish: () => nullish,
159
+ numKeys: () => numKeys,
160
+ objectClone: () => objectClone,
161
+ omit: () => omit,
162
+ optionalKeys: () => optionalKeys,
163
+ parsedType: () => parsedType,
164
+ partial: () => partial,
165
+ pick: () => pick,
166
+ prefixIssues: () => prefixIssues,
167
+ primitiveTypes: () => primitiveTypes,
168
+ promiseAllObject: () => promiseAllObject,
169
+ propertyKeyTypes: () => propertyKeyTypes,
170
+ randomString: () => randomString,
171
+ required: () => required,
172
+ safeExtend: () => safeExtend,
173
+ shallowClone: () => shallowClone,
174
+ slugify: () => slugify,
175
+ stringifyPrimitive: () => stringifyPrimitive,
176
+ uint8ArrayToBase64: () => uint8ArrayToBase64,
177
+ uint8ArrayToBase64url: () => uint8ArrayToBase64url,
178
+ uint8ArrayToHex: () => uint8ArrayToHex,
179
+ unwrapMessage: () => unwrapMessage
180
+ });
181
+ function assertEqual(val) {
182
+ return val;
291
183
  }
292
- async function scaffoldNextConfig(projectRoot) {
293
- let configPath;
294
- let configName;
295
- for (const name of NEXT_CONFIG_NAMES) {
296
- const candidate = path.join(projectRoot, name);
297
- if (fs.existsSync(candidate)) {
298
- configPath = candidate;
299
- configName = name;
300
- break;
301
- }
302
- }
303
- if (configPath === void 0 || configName === void 0) {
304
- return null;
305
- }
306
- const existing = fs.readFileSync(configPath, "utf-8");
307
- if (existing.trim().length === 0) {
308
- return { modified: false, reason: "empty-file" };
309
- }
310
- if (existing.includes("withGlasstraceConfig")) {
311
- return { modified: false, reason: "already-wrapped" };
312
- }
313
- const isESM = configName.endsWith(".ts") || configName.endsWith(".mjs");
314
- if (isESM) {
315
- const importLine = 'import { withGlasstraceConfig } from "@glasstrace/sdk";\n';
316
- const wrapResult2 = wrapExport(existing);
317
- if (!wrapResult2.wrapped) {
318
- return { modified: false, reason: "no-export" };
319
- }
320
- const modified2 = importLine + "\n" + wrapResult2.content;
321
- fs.writeFileSync(configPath, modified2, "utf-8");
322
- return { modified: true };
323
- }
324
- const requireLine = 'const { withGlasstraceConfig } = require("@glasstrace/sdk");\n';
325
- const wrapResult = wrapCJSExport(existing);
326
- if (!wrapResult.wrapped) {
327
- return { modified: false, reason: "no-export" };
328
- }
329
- const modified = requireLine + "\n" + wrapResult.content;
330
- fs.writeFileSync(configPath, modified, "utf-8");
331
- return { modified: true };
184
+ function assertNotEqual(val) {
185
+ return val;
332
186
  }
333
- function wrapExport(content) {
334
- const marker = "export default";
335
- const idx = content.lastIndexOf(marker);
336
- if (idx === -1) {
337
- return { content, wrapped: false };
338
- }
339
- const preamble = content.slice(0, idx);
340
- const exprRaw = content.slice(idx + marker.length);
341
- const expr = exprRaw.trim().replace(/;?\s*$/, "");
342
- if (expr.length === 0) {
343
- return { content, wrapped: false };
344
- }
345
- return {
346
- content: preamble + `export default withGlasstraceConfig(${expr});
347
- `,
348
- wrapped: true
349
- };
187
+ function assertIs(_arg) {
350
188
  }
351
- function wrapCJSExport(content) {
352
- const cjsMarker = "module.exports";
353
- const cjsIdx = content.lastIndexOf(cjsMarker);
354
- if (cjsIdx === -1) {
355
- return { content, wrapped: false };
356
- }
357
- const preamble = content.slice(0, cjsIdx);
358
- const afterMarker = content.slice(cjsIdx + cjsMarker.length);
359
- const eqMatch = /^\s*=\s*/.exec(afterMarker);
360
- if (!eqMatch) {
361
- return { content, wrapped: false };
362
- }
363
- const exprRaw = afterMarker.slice(eqMatch[0].length);
364
- const expr = exprRaw.trim().replace(/;?\s*$/, "");
365
- if (expr.length === 0) {
366
- return { content, wrapped: false };
367
- }
189
+ function assertNever(_x) {
190
+ throw new Error("Unexpected value in exhaustive check");
191
+ }
192
+ function assert(_) {
193
+ }
194
+ function getEnumValues(entries) {
195
+ const numericValues = Object.values(entries).filter((v) => typeof v === "number");
196
+ const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
197
+ return values;
198
+ }
199
+ function joinValues(array2, separator = "|") {
200
+ return array2.map((val) => stringifyPrimitive(val)).join(separator);
201
+ }
202
+ function jsonStringifyReplacer(_, value) {
203
+ if (typeof value === "bigint")
204
+ return value.toString();
205
+ return value;
206
+ }
207
+ function cached(getter) {
208
+ const set2 = false;
368
209
  return {
369
- content: preamble + `module.exports = withGlasstraceConfig(${expr});
370
- `,
371
- wrapped: true
210
+ get value() {
211
+ if (!set2) {
212
+ const value = getter();
213
+ Object.defineProperty(this, "value", { value });
214
+ return value;
215
+ }
216
+ throw new Error("cached value already set");
217
+ }
372
218
  };
373
219
  }
374
- function readEnvLocalApiKey(content) {
375
- let last = null;
376
- const regex = /^\s*GLASSTRACE_API_KEY\s*=\s*(.*)$/gm;
377
- let match;
378
- while ((match = regex.exec(content)) !== null) {
379
- const raw = match[1].trim();
380
- if (raw === "") continue;
381
- const unquoted = raw.replace(/^(['"])(.*)\1$/, "$2");
382
- if (unquoted === "" || unquoted === "your_key_here") continue;
383
- last = unquoted;
384
- }
385
- return last;
220
+ function nullish(input) {
221
+ return input === null || input === void 0;
386
222
  }
387
- function isDevApiKey(value) {
388
- if (value === null || value === void 0) return false;
389
- return value.trim().startsWith("gt_dev_");
223
+ function cleanRegex(source) {
224
+ const start = source.startsWith("^") ? 1 : 0;
225
+ const end = source.endsWith("$") ? source.length - 1 : source.length;
226
+ return source.slice(start, end);
390
227
  }
391
- async function scaffoldEnvLocal(projectRoot) {
392
- const filePath = path.join(projectRoot, ".env.local");
393
- if (fs.existsSync(filePath)) {
394
- const existing = fs.readFileSync(filePath, "utf-8");
395
- if (/^\s*#?\s*GLASSTRACE_API_KEY\s*=/m.test(existing)) {
396
- return false;
228
+ function floatSafeRemainder(val, step) {
229
+ const valDecCount = (val.toString().split(".")[1] || "").length;
230
+ const stepString = step.toString();
231
+ let stepDecCount = (stepString.split(".")[1] || "").length;
232
+ if (stepDecCount === 0 && /\d?e-\d?/.test(stepString)) {
233
+ const match = stepString.match(/\d?e-(\d?)/);
234
+ if (match?.[1]) {
235
+ stepDecCount = Number.parseInt(match[1]);
397
236
  }
398
- const separator = existing.endsWith("\n") ? "" : "\n";
399
- fs.writeFileSync(filePath, existing + separator + "# GLASSTRACE_API_KEY=your_key_here\n", "utf-8");
400
- return true;
401
237
  }
402
- fs.writeFileSync(filePath, "# GLASSTRACE_API_KEY=your_key_here\n", "utf-8");
403
- return true;
238
+ const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
239
+ const valInt = Number.parseInt(val.toFixed(decCount).replace(".", ""));
240
+ const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
241
+ return valInt % stepInt / 10 ** decCount;
404
242
  }
405
- async function addCoverageMapEnv(projectRoot) {
406
- const filePath = path.join(projectRoot, ".env.local");
407
- if (!fs.existsSync(filePath)) {
408
- fs.writeFileSync(filePath, "GLASSTRACE_COVERAGE_MAP=true\n", "utf-8");
409
- return true;
410
- }
411
- const existing = fs.readFileSync(filePath, "utf-8");
412
- const keyRegex = /^(\s*GLASSTRACE_COVERAGE_MAP\s*=\s*)(.*)$/m;
413
- const keyMatch = keyRegex.exec(existing);
414
- if (keyMatch) {
415
- const currentValue = keyMatch[2].trim();
416
- if (currentValue === "true") {
417
- return false;
418
- }
419
- const updated = existing.replace(keyRegex, `${keyMatch[1]}true`);
420
- fs.writeFileSync(filePath, updated, "utf-8");
421
- return true;
422
- }
423
- const separator = existing.endsWith("\n") ? "" : "\n";
424
- fs.writeFileSync(filePath, existing + separator + "GLASSTRACE_COVERAGE_MAP=true\n", "utf-8");
425
- return true;
243
+ function defineLazy(object2, key, getter) {
244
+ let value = void 0;
245
+ Object.defineProperty(object2, key, {
246
+ get() {
247
+ if (value === EVALUATING) {
248
+ return void 0;
249
+ }
250
+ if (value === void 0) {
251
+ value = EVALUATING;
252
+ value = getter();
253
+ }
254
+ return value;
255
+ },
256
+ set(v) {
257
+ Object.defineProperty(object2, key, {
258
+ value: v
259
+ // configurable: true,
260
+ });
261
+ },
262
+ configurable: true
263
+ });
426
264
  }
427
- async function scaffoldGitignore(projectRoot) {
428
- const filePath = path.join(projectRoot, ".gitignore");
429
- if (fs.existsSync(filePath)) {
430
- const existing = fs.readFileSync(filePath, "utf-8");
431
- const lines = existing.split("\n").map((l) => l.trim());
432
- if (lines.includes(".glasstrace/")) {
433
- return false;
434
- }
435
- const separator = existing.endsWith("\n") ? "" : "\n";
436
- fs.writeFileSync(filePath, existing + separator + ".glasstrace/\n", "utf-8");
437
- return true;
438
- }
439
- fs.writeFileSync(filePath, ".glasstrace/\n", "utf-8");
440
- return true;
265
+ function objectClone(obj) {
266
+ return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
441
267
  }
442
- function mcpConfigMatches(existingContent, expectedContent) {
443
- const trimmedExpected = expectedContent.trim();
444
- try {
445
- const existingParsed = JSON.parse(existingContent);
446
- const expectedParsed = JSON.parse(trimmedExpected);
447
- return JSON.stringify(canonicalize(existingParsed)) === JSON.stringify(canonicalize(expectedParsed));
448
- } catch {
449
- }
450
- return existingContent.trim() === trimmedExpected;
268
+ function assignProp(target, prop, value) {
269
+ Object.defineProperty(target, prop, {
270
+ value,
271
+ writable: true,
272
+ enumerable: true,
273
+ configurable: true
274
+ });
451
275
  }
452
- function canonicalize(value) {
453
- if (Array.isArray(value)) {
454
- return value.map(canonicalize);
455
- }
456
- if (value !== null && typeof value === "object") {
457
- const obj = value;
458
- const sorted = {};
459
- for (const key of Object.keys(obj).sort()) {
460
- sorted[key] = canonicalize(obj[key]);
461
- }
462
- return sorted;
276
+ function mergeDefs(...defs) {
277
+ const mergedDescriptors = {};
278
+ for (const def of defs) {
279
+ const descriptors = Object.getOwnPropertyDescriptors(def);
280
+ Object.assign(mergedDescriptors, descriptors);
463
281
  }
464
- return value;
282
+ return Object.defineProperties({}, mergedDescriptors);
465
283
  }
466
- async function scaffoldMcpMarker(projectRoot, anonKey) {
467
- const dirPath = path.join(projectRoot, ".glasstrace");
468
- const markerPath = path.join(dirPath, "mcp-connected");
469
- const keyHash = identityFingerprint(anonKey);
470
- if (fs.existsSync(markerPath)) {
471
- try {
472
- const existing = JSON.parse(fs.readFileSync(markerPath, "utf-8"));
473
- if (existing.keyHash === keyHash) {
474
- return false;
475
- }
476
- } catch {
477
- }
478
- }
479
- fs.mkdirSync(dirPath, { recursive: true, mode: 448 });
480
- const marker = JSON.stringify(
481
- { keyHash, configuredAt: (/* @__PURE__ */ new Date()).toISOString() },
482
- null,
483
- 2
484
- );
485
- fs.writeFileSync(markerPath, marker, { mode: 384 });
486
- fs.chmodSync(markerPath, 384);
487
- return true;
284
+ function cloneDef(schema) {
285
+ return mergeDefs(schema._zod.def);
488
286
  }
489
- var import_node_crypto, fs, path, INSTRUMENTATION_FILENAMES;
490
- var init_scaffolder = __esm({
491
- "src/cli/scaffolder.ts"() {
492
- "use strict";
493
- import_node_crypto = require("node:crypto");
494
- fs = __toESM(require("node:fs"), 1);
495
- path = __toESM(require("node:path"), 1);
496
- init_constants();
497
- INSTRUMENTATION_FILENAMES = [
498
- "instrumentation.ts",
499
- "instrumentation.js",
500
- "instrumentation.mjs"
501
- ];
502
- }
503
- });
504
-
505
- // ../../node_modules/zod/v4/core/core.js
506
- // @__NO_SIDE_EFFECTS__
507
- function $constructor(name, initializer3, params) {
508
- function init(inst, def) {
509
- if (!inst._zod) {
510
- Object.defineProperty(inst, "_zod", {
511
- value: {
512
- def,
513
- constr: _,
514
- traits: /* @__PURE__ */ new Set()
515
- },
516
- enumerable: false
517
- });
518
- }
519
- if (inst._zod.traits.has(name)) {
520
- return;
521
- }
522
- inst._zod.traits.add(name);
523
- initializer3(inst, def);
524
- const proto = _.prototype;
525
- const keys = Object.keys(proto);
287
+ function getElementAtPath(obj, path10) {
288
+ if (!path10)
289
+ return obj;
290
+ return path10.reduce((acc, key) => acc?.[key], obj);
291
+ }
292
+ function promiseAllObject(promisesObj) {
293
+ const keys = Object.keys(promisesObj);
294
+ const promises = keys.map((key) => promisesObj[key]);
295
+ return Promise.all(promises).then((results) => {
296
+ const resolvedObj = {};
526
297
  for (let i = 0; i < keys.length; i++) {
527
- const k = keys[i];
528
- if (!(k in inst)) {
529
- inst[k] = proto[k].bind(inst);
530
- }
298
+ resolvedObj[keys[i]] = results[i];
531
299
  }
300
+ return resolvedObj;
301
+ });
302
+ }
303
+ function randomString(length = 10) {
304
+ const chars = "abcdefghijklmnopqrstuvwxyz";
305
+ let str = "";
306
+ for (let i = 0; i < length; i++) {
307
+ str += chars[Math.floor(Math.random() * chars.length)];
532
308
  }
533
- const Parent = params?.Parent ?? Object;
534
- class Definition extends Parent {
309
+ return str;
310
+ }
311
+ function esc(str) {
312
+ return JSON.stringify(str);
313
+ }
314
+ function slugify(input) {
315
+ return input.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
316
+ }
317
+ function isObject(data) {
318
+ return typeof data === "object" && data !== null && !Array.isArray(data);
319
+ }
320
+ function isPlainObject(o) {
321
+ if (isObject(o) === false)
322
+ return false;
323
+ const ctor = o.constructor;
324
+ if (ctor === void 0)
325
+ return true;
326
+ if (typeof ctor !== "function")
327
+ return true;
328
+ const prot = ctor.prototype;
329
+ if (isObject(prot) === false)
330
+ return false;
331
+ if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
332
+ return false;
535
333
  }
536
- Object.defineProperty(Definition, "name", { value: name });
537
- function _(def) {
538
- var _a2;
539
- const inst = params?.Parent ? new Definition() : this;
540
- init(inst, def);
541
- (_a2 = inst._zod).deferred ?? (_a2.deferred = []);
542
- for (const fn of inst._zod.deferred) {
543
- fn();
334
+ return true;
335
+ }
336
+ function shallowClone(o) {
337
+ if (isPlainObject(o))
338
+ return { ...o };
339
+ if (Array.isArray(o))
340
+ return [...o];
341
+ return o;
342
+ }
343
+ function numKeys(data) {
344
+ let keyCount = 0;
345
+ for (const key in data) {
346
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
347
+ keyCount++;
544
348
  }
545
- return inst;
546
349
  }
547
- Object.defineProperty(_, "init", { value: init });
548
- Object.defineProperty(_, Symbol.hasInstance, {
549
- value: (inst) => {
550
- if (params?.Parent && inst instanceof params.Parent)
551
- return true;
552
- return inst?._zod?.traits?.has(name);
553
- }
554
- });
555
- Object.defineProperty(_, "name", { value: name });
556
- return _;
350
+ return keyCount;
557
351
  }
558
- function config(newConfig) {
559
- if (newConfig)
560
- Object.assign(globalConfig, newConfig);
561
- return globalConfig;
352
+ function escapeRegex(str) {
353
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
562
354
  }
563
- var NEVER, $brand, $ZodAsyncError, $ZodEncodeError, globalConfig;
564
- var init_core = __esm({
565
- "../../node_modules/zod/v4/core/core.js"() {
566
- "use strict";
567
- NEVER = Object.freeze({
568
- status: "aborted"
569
- });
570
- $brand = /* @__PURE__ */ Symbol("zod_brand");
571
- $ZodAsyncError = class extends Error {
572
- constructor() {
573
- super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
574
- }
575
- };
576
- $ZodEncodeError = class extends Error {
577
- constructor(name) {
578
- super(`Encountered unidirectional transform during encode: ${name}`);
579
- this.name = "ZodEncodeError";
580
- }
581
- };
582
- globalConfig = {};
583
- }
584
- });
585
-
586
- // ../../node_modules/zod/v4/core/util.js
587
- var util_exports = {};
588
- __export(util_exports, {
589
- BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES,
590
- Class: () => Class,
591
- NUMBER_FORMAT_RANGES: () => NUMBER_FORMAT_RANGES,
592
- aborted: () => aborted,
593
- allowsEval: () => allowsEval,
594
- assert: () => assert,
595
- assertEqual: () => assertEqual,
596
- assertIs: () => assertIs,
597
- assertNever: () => assertNever,
598
- assertNotEqual: () => assertNotEqual,
599
- assignProp: () => assignProp,
600
- base64ToUint8Array: () => base64ToUint8Array,
601
- base64urlToUint8Array: () => base64urlToUint8Array,
602
- cached: () => cached,
603
- captureStackTrace: () => captureStackTrace,
604
- cleanEnum: () => cleanEnum,
605
- cleanRegex: () => cleanRegex,
606
- clone: () => clone,
607
- cloneDef: () => cloneDef,
608
- createTransparentProxy: () => createTransparentProxy,
609
- defineLazy: () => defineLazy,
610
- esc: () => esc,
611
- escapeRegex: () => escapeRegex,
612
- extend: () => extend,
613
- finalizeIssue: () => finalizeIssue,
614
- floatSafeRemainder: () => floatSafeRemainder,
615
- getElementAtPath: () => getElementAtPath,
616
- getEnumValues: () => getEnumValues,
617
- getLengthableOrigin: () => getLengthableOrigin,
618
- getParsedType: () => getParsedType,
619
- getSizableOrigin: () => getSizableOrigin,
620
- hexToUint8Array: () => hexToUint8Array,
621
- isObject: () => isObject,
622
- isPlainObject: () => isPlainObject,
623
- issue: () => issue,
624
- joinValues: () => joinValues,
625
- jsonStringifyReplacer: () => jsonStringifyReplacer,
626
- merge: () => merge,
627
- mergeDefs: () => mergeDefs,
628
- normalizeParams: () => normalizeParams,
629
- nullish: () => nullish,
630
- numKeys: () => numKeys,
631
- objectClone: () => objectClone,
632
- omit: () => omit,
633
- optionalKeys: () => optionalKeys,
634
- parsedType: () => parsedType,
635
- partial: () => partial,
636
- pick: () => pick,
637
- prefixIssues: () => prefixIssues,
638
- primitiveTypes: () => primitiveTypes,
639
- promiseAllObject: () => promiseAllObject,
640
- propertyKeyTypes: () => propertyKeyTypes,
641
- randomString: () => randomString,
642
- required: () => required,
643
- safeExtend: () => safeExtend,
644
- shallowClone: () => shallowClone,
645
- slugify: () => slugify,
646
- stringifyPrimitive: () => stringifyPrimitive,
647
- uint8ArrayToBase64: () => uint8ArrayToBase64,
648
- uint8ArrayToBase64url: () => uint8ArrayToBase64url,
649
- uint8ArrayToHex: () => uint8ArrayToHex,
650
- unwrapMessage: () => unwrapMessage
651
- });
652
- function assertEqual(val) {
653
- return val;
654
- }
655
- function assertNotEqual(val) {
656
- return val;
657
- }
658
- function assertIs(_arg) {
659
- }
660
- function assertNever(_x) {
661
- throw new Error("Unexpected value in exhaustive check");
662
- }
663
- function assert(_) {
664
- }
665
- function getEnumValues(entries) {
666
- const numericValues = Object.values(entries).filter((v) => typeof v === "number");
667
- const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
668
- return values;
669
- }
670
- function joinValues(array2, separator = "|") {
671
- return array2.map((val) => stringifyPrimitive(val)).join(separator);
672
- }
673
- function jsonStringifyReplacer(_, value) {
674
- if (typeof value === "bigint")
675
- return value.toString();
676
- return value;
677
- }
678
- function cached(getter) {
679
- const set2 = false;
680
- return {
681
- get value() {
682
- if (!set2) {
683
- const value = getter();
684
- Object.defineProperty(this, "value", { value });
685
- return value;
686
- }
687
- throw new Error("cached value already set");
688
- }
689
- };
690
- }
691
- function nullish(input) {
692
- return input === null || input === void 0;
693
- }
694
- function cleanRegex(source) {
695
- const start = source.startsWith("^") ? 1 : 0;
696
- const end = source.endsWith("$") ? source.length - 1 : source.length;
697
- return source.slice(start, end);
355
+ function clone(inst, def, params) {
356
+ const cl = new inst._zod.constr(def ?? inst._zod.def);
357
+ if (!def || params?.parent)
358
+ cl._zod.parent = inst;
359
+ return cl;
698
360
  }
699
- function floatSafeRemainder(val, step) {
700
- const valDecCount = (val.toString().split(".")[1] || "").length;
701
- const stepString = step.toString();
702
- let stepDecCount = (stepString.split(".")[1] || "").length;
703
- if (stepDecCount === 0 && /\d?e-\d?/.test(stepString)) {
704
- const match = stepString.match(/\d?e-(\d?)/);
705
- if (match?.[1]) {
706
- stepDecCount = Number.parseInt(match[1]);
707
- }
361
+ function normalizeParams(_params) {
362
+ const params = _params;
363
+ if (!params)
364
+ return {};
365
+ if (typeof params === "string")
366
+ return { error: () => params };
367
+ if (params?.message !== void 0) {
368
+ if (params?.error !== void 0)
369
+ throw new Error("Cannot specify both `message` and `error` params");
370
+ params.error = params.message;
708
371
  }
709
- const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
710
- const valInt = Number.parseInt(val.toFixed(decCount).replace(".", ""));
711
- const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
712
- return valInt % stepInt / 10 ** decCount;
372
+ delete params.message;
373
+ if (typeof params.error === "string")
374
+ return { ...params, error: () => params.error };
375
+ return params;
713
376
  }
714
- function defineLazy(object2, key, getter) {
715
- let value = void 0;
716
- Object.defineProperty(object2, key, {
717
- get() {
718
- if (value === EVALUATING) {
719
- return void 0;
720
- }
721
- if (value === void 0) {
722
- value = EVALUATING;
723
- value = getter();
724
- }
725
- return value;
377
+ function createTransparentProxy(getter) {
378
+ let target;
379
+ return new Proxy({}, {
380
+ get(_, prop, receiver) {
381
+ target ?? (target = getter());
382
+ return Reflect.get(target, prop, receiver);
726
383
  },
727
- set(v) {
728
- Object.defineProperty(object2, key, {
729
- value: v
730
- // configurable: true,
731
- });
384
+ set(_, prop, value, receiver) {
385
+ target ?? (target = getter());
386
+ return Reflect.set(target, prop, value, receiver);
732
387
  },
733
- configurable: true
388
+ has(_, prop) {
389
+ target ?? (target = getter());
390
+ return Reflect.has(target, prop);
391
+ },
392
+ deleteProperty(_, prop) {
393
+ target ?? (target = getter());
394
+ return Reflect.deleteProperty(target, prop);
395
+ },
396
+ ownKeys(_) {
397
+ target ?? (target = getter());
398
+ return Reflect.ownKeys(target);
399
+ },
400
+ getOwnPropertyDescriptor(_, prop) {
401
+ target ?? (target = getter());
402
+ return Reflect.getOwnPropertyDescriptor(target, prop);
403
+ },
404
+ defineProperty(_, prop, descriptor) {
405
+ target ?? (target = getter());
406
+ return Reflect.defineProperty(target, prop, descriptor);
407
+ }
734
408
  });
735
409
  }
736
- function objectClone(obj) {
737
- return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
410
+ function stringifyPrimitive(value) {
411
+ if (typeof value === "bigint")
412
+ return value.toString() + "n";
413
+ if (typeof value === "string")
414
+ return `"${value}"`;
415
+ return `${value}`;
738
416
  }
739
- function assignProp(target, prop, value) {
740
- Object.defineProperty(target, prop, {
741
- value,
742
- writable: true,
743
- enumerable: true,
744
- configurable: true
417
+ function optionalKeys(shape) {
418
+ return Object.keys(shape).filter((k) => {
419
+ return shape[k]._zod.optin === "optional" && shape[k]._zod.optout === "optional";
745
420
  });
746
421
  }
747
- function mergeDefs(...defs) {
748
- const mergedDescriptors = {};
749
- for (const def of defs) {
750
- const descriptors = Object.getOwnPropertyDescriptors(def);
751
- Object.assign(mergedDescriptors, descriptors);
422
+ function pick(schema, mask) {
423
+ const currDef = schema._zod.def;
424
+ const checks = currDef.checks;
425
+ const hasChecks = checks && checks.length > 0;
426
+ if (hasChecks) {
427
+ throw new Error(".pick() cannot be used on object schemas containing refinements");
752
428
  }
753
- return Object.defineProperties({}, mergedDescriptors);
754
- }
755
- function cloneDef(schema) {
756
- return mergeDefs(schema._zod.def);
757
- }
758
- function getElementAtPath(obj, path10) {
759
- if (!path10)
760
- return obj;
761
- return path10.reduce((acc, key) => acc?.[key], obj);
762
- }
763
- function promiseAllObject(promisesObj) {
764
- const keys = Object.keys(promisesObj);
765
- const promises = keys.map((key) => promisesObj[key]);
766
- return Promise.all(promises).then((results) => {
767
- const resolvedObj = {};
768
- for (let i = 0; i < keys.length; i++) {
769
- resolvedObj[keys[i]] = results[i];
770
- }
771
- return resolvedObj;
772
- });
773
- }
774
- function randomString(length = 10) {
775
- const chars = "abcdefghijklmnopqrstuvwxyz";
776
- let str = "";
777
- for (let i = 0; i < length; i++) {
778
- str += chars[Math.floor(Math.random() * chars.length)];
779
- }
780
- return str;
781
- }
782
- function esc(str) {
783
- return JSON.stringify(str);
784
- }
785
- function slugify(input) {
786
- return input.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
787
- }
788
- function isObject(data) {
789
- return typeof data === "object" && data !== null && !Array.isArray(data);
790
- }
791
- function isPlainObject(o) {
792
- if (isObject(o) === false)
793
- return false;
794
- const ctor = o.constructor;
795
- if (ctor === void 0)
796
- return true;
797
- if (typeof ctor !== "function")
798
- return true;
799
- const prot = ctor.prototype;
800
- if (isObject(prot) === false)
801
- return false;
802
- if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
803
- return false;
804
- }
805
- return true;
806
- }
807
- function shallowClone(o) {
808
- if (isPlainObject(o))
809
- return { ...o };
810
- if (Array.isArray(o))
811
- return [...o];
812
- return o;
813
- }
814
- function numKeys(data) {
815
- let keyCount = 0;
816
- for (const key in data) {
817
- if (Object.prototype.hasOwnProperty.call(data, key)) {
818
- keyCount++;
819
- }
820
- }
821
- return keyCount;
822
- }
823
- function escapeRegex(str) {
824
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
825
- }
826
- function clone(inst, def, params) {
827
- const cl = new inst._zod.constr(def ?? inst._zod.def);
828
- if (!def || params?.parent)
829
- cl._zod.parent = inst;
830
- return cl;
831
- }
832
- function normalizeParams(_params) {
833
- const params = _params;
834
- if (!params)
835
- return {};
836
- if (typeof params === "string")
837
- return { error: () => params };
838
- if (params?.message !== void 0) {
839
- if (params?.error !== void 0)
840
- throw new Error("Cannot specify both `message` and `error` params");
841
- params.error = params.message;
842
- }
843
- delete params.message;
844
- if (typeof params.error === "string")
845
- return { ...params, error: () => params.error };
846
- return params;
847
- }
848
- function createTransparentProxy(getter) {
849
- let target;
850
- return new Proxy({}, {
851
- get(_, prop, receiver) {
852
- target ?? (target = getter());
853
- return Reflect.get(target, prop, receiver);
854
- },
855
- set(_, prop, value, receiver) {
856
- target ?? (target = getter());
857
- return Reflect.set(target, prop, value, receiver);
858
- },
859
- has(_, prop) {
860
- target ?? (target = getter());
861
- return Reflect.has(target, prop);
862
- },
863
- deleteProperty(_, prop) {
864
- target ?? (target = getter());
865
- return Reflect.deleteProperty(target, prop);
866
- },
867
- ownKeys(_) {
868
- target ?? (target = getter());
869
- return Reflect.ownKeys(target);
870
- },
871
- getOwnPropertyDescriptor(_, prop) {
872
- target ?? (target = getter());
873
- return Reflect.getOwnPropertyDescriptor(target, prop);
874
- },
875
- defineProperty(_, prop, descriptor) {
876
- target ?? (target = getter());
877
- return Reflect.defineProperty(target, prop, descriptor);
878
- }
879
- });
880
- }
881
- function stringifyPrimitive(value) {
882
- if (typeof value === "bigint")
883
- return value.toString() + "n";
884
- if (typeof value === "string")
885
- return `"${value}"`;
886
- return `${value}`;
887
- }
888
- function optionalKeys(shape) {
889
- return Object.keys(shape).filter((k) => {
890
- return shape[k]._zod.optin === "optional" && shape[k]._zod.optout === "optional";
891
- });
892
- }
893
- function pick(schema, mask) {
894
- const currDef = schema._zod.def;
895
- const checks = currDef.checks;
896
- const hasChecks = checks && checks.length > 0;
897
- if (hasChecks) {
898
- throw new Error(".pick() cannot be used on object schemas containing refinements");
899
- }
900
- const def = mergeDefs(schema._zod.def, {
901
- get shape() {
902
- const newShape = {};
903
- for (const key in mask) {
904
- if (!(key in currDef.shape)) {
905
- throw new Error(`Unrecognized key: "${key}"`);
906
- }
907
- if (!mask[key])
908
- continue;
909
- newShape[key] = currDef.shape[key];
910
- }
911
- assignProp(this, "shape", newShape);
912
- return newShape;
913
- },
914
- checks: []
915
- });
916
- return clone(schema, def);
429
+ const def = mergeDefs(schema._zod.def, {
430
+ get shape() {
431
+ const newShape = {};
432
+ for (const key in mask) {
433
+ if (!(key in currDef.shape)) {
434
+ throw new Error(`Unrecognized key: "${key}"`);
435
+ }
436
+ if (!mask[key])
437
+ continue;
438
+ newShape[key] = currDef.shape[key];
439
+ }
440
+ assignProp(this, "shape", newShape);
441
+ return newShape;
442
+ },
443
+ checks: []
444
+ });
445
+ return clone(schema, def);
917
446
  }
918
447
  function omit(schema, mask) {
919
448
  const currDef = schema._zod.def;
@@ -15104,99 +14633,706 @@ var init_dist = __esm({
15104
14633
  3329325298
15105
14634
  ]);
15106
14635
  }
15107
- });
15108
-
15109
- // src/anon-key.ts
15110
- async function loadFsPath() {
15111
- if (fsPathCache !== void 0) return fsPathCache;
15112
- try {
15113
- const [fs10, path10] = await Promise.all([
15114
- import("node:fs/promises"),
15115
- import("node:path")
15116
- ]);
15117
- fsPathCache = { fs: fs10, path: path10 };
15118
- return fsPathCache;
15119
- } catch {
15120
- fsPathCache = null;
15121
- return null;
14636
+ });
14637
+
14638
+ // src/anon-key.ts
14639
+ async function loadFsPath() {
14640
+ if (fsPathCache !== void 0) return fsPathCache;
14641
+ try {
14642
+ const [fs10, path10] = await Promise.all([
14643
+ import("node:fs/promises"),
14644
+ import("node:path")
14645
+ ]);
14646
+ fsPathCache = { fs: fs10, path: path10 };
14647
+ return fsPathCache;
14648
+ } catch {
14649
+ fsPathCache = null;
14650
+ return null;
14651
+ }
14652
+ }
14653
+ async function readAnonKey(projectRoot) {
14654
+ const root = projectRoot ?? process.cwd();
14655
+ const modules = await loadFsPath();
14656
+ if (modules) {
14657
+ const keyPath = modules.path.join(root, GLASSTRACE_DIR, ANON_KEY_FILE);
14658
+ try {
14659
+ const content = await modules.fs.readFile(keyPath, "utf-8");
14660
+ const result = AnonApiKeySchema.safeParse(content);
14661
+ if (result.success) {
14662
+ return result.data;
14663
+ }
14664
+ } catch {
14665
+ }
14666
+ }
14667
+ const cached2 = ephemeralKeyCache.get(root);
14668
+ if (cached2 !== void 0) {
14669
+ return cached2;
14670
+ }
14671
+ return null;
14672
+ }
14673
+ async function readClaimedKey(projectRoot) {
14674
+ const root = projectRoot ?? process.cwd();
14675
+ const modules = await loadFsPath();
14676
+ if (!modules) return null;
14677
+ const keyPath = modules.path.join(root, GLASSTRACE_DIR, CLAIMED_KEY_FILE);
14678
+ try {
14679
+ const content = await modules.fs.readFile(keyPath, "utf-8");
14680
+ const trimmed = content.trim();
14681
+ const parsed = DevApiKeySchema.safeParse(trimmed);
14682
+ if (parsed.success) {
14683
+ return parsed.data;
14684
+ }
14685
+ } catch {
14686
+ }
14687
+ return null;
14688
+ }
14689
+ async function getOrCreateAnonKey(projectRoot) {
14690
+ const root = projectRoot ?? process.cwd();
14691
+ const existingKey = await readAnonKey(root);
14692
+ if (existingKey !== null) {
14693
+ return existingKey;
14694
+ }
14695
+ const cached2 = ephemeralKeyCache.get(root);
14696
+ if (cached2 !== void 0) {
14697
+ return cached2;
14698
+ }
14699
+ const newKey = createAnonApiKey();
14700
+ const modules = await loadFsPath();
14701
+ if (!modules) {
14702
+ ephemeralKeyCache.set(root, newKey);
14703
+ return newKey;
14704
+ }
14705
+ const dirPath = modules.path.join(root, GLASSTRACE_DIR);
14706
+ const keyPath = modules.path.join(dirPath, ANON_KEY_FILE);
14707
+ try {
14708
+ await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
14709
+ await modules.fs.writeFile(keyPath, newKey, { flag: "wx", mode: 384 });
14710
+ return newKey;
14711
+ } catch (err) {
14712
+ const code = err.code;
14713
+ if (code === "EEXIST") {
14714
+ for (let attempt = 0; attempt < 3; attempt++) {
14715
+ const winnerKey = await readAnonKey(root);
14716
+ if (winnerKey !== null) {
14717
+ return winnerKey;
14718
+ }
14719
+ if (attempt < 2) {
14720
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
14721
+ }
14722
+ }
14723
+ try {
14724
+ await modules.fs.writeFile(keyPath, newKey, { mode: 384 });
14725
+ await modules.fs.chmod(keyPath, 384);
14726
+ return newKey;
14727
+ } catch {
14728
+ }
14729
+ }
14730
+ ephemeralKeyCache.set(root, newKey);
14731
+ console.warn(
14732
+ `[glasstrace] Failed to persist anonymous key to ${keyPath}: ${err instanceof Error ? err.message : String(err)}. Using ephemeral key.`
14733
+ );
14734
+ return newKey;
14735
+ }
14736
+ }
14737
+ var GLASSTRACE_DIR, ANON_KEY_FILE, CLAIMED_KEY_FILE, fsPathCache, ephemeralKeyCache;
14738
+ var init_anon_key = __esm({
14739
+ "src/anon-key.ts"() {
14740
+ "use strict";
14741
+ init_dist();
14742
+ GLASSTRACE_DIR = ".glasstrace";
14743
+ ANON_KEY_FILE = "anon_key";
14744
+ CLAIMED_KEY_FILE = "claimed-key";
14745
+ ephemeralKeyCache = /* @__PURE__ */ new Map();
14746
+ }
14747
+ });
14748
+
14749
+ // src/mcp-runtime.ts
14750
+ async function loadFsPath2() {
14751
+ if (fsPathCache2 !== void 0) return fsPathCache2;
14752
+ try {
14753
+ const [fs10, path10] = await Promise.all([
14754
+ import("node:fs/promises"),
14755
+ import("node:path")
14756
+ ]);
14757
+ fsPathCache2 = { fs: fs10, path: path10 };
14758
+ return fsPathCache2;
14759
+ } catch {
14760
+ fsPathCache2 = null;
14761
+ return null;
14762
+ }
14763
+ }
14764
+ function identityFingerprint(token) {
14765
+ return `sha256:${(0, import_node_crypto.createHash)("sha256").update(token).digest("hex")}`;
14766
+ }
14767
+ function mcpConfigMatches(existingContent, expectedContent) {
14768
+ const trimmedExpected = expectedContent.trim();
14769
+ try {
14770
+ const existingParsed = JSON.parse(existingContent);
14771
+ const expectedParsed = JSON.parse(trimmedExpected);
14772
+ return JSON.stringify(canonicalize(existingParsed)) === JSON.stringify(canonicalize(expectedParsed));
14773
+ } catch {
14774
+ }
14775
+ return existingContent.trim() === trimmedExpected;
14776
+ }
14777
+ function canonicalize(value) {
14778
+ if (Array.isArray(value)) {
14779
+ return value.map(canonicalize);
14780
+ }
14781
+ if (value !== null && typeof value === "object") {
14782
+ const obj = value;
14783
+ const sorted = {};
14784
+ for (const key of Object.keys(obj).sort()) {
14785
+ sorted[key] = canonicalize(obj[key]);
14786
+ }
14787
+ return sorted;
14788
+ }
14789
+ return value;
14790
+ }
14791
+ function readEnvLocalApiKey(content) {
14792
+ let last = null;
14793
+ const regex = /^\s*GLASSTRACE_API_KEY\s*=\s*(.*)$/gm;
14794
+ let match;
14795
+ while ((match = regex.exec(content)) !== null) {
14796
+ const raw = match[1].trim();
14797
+ if (raw === "") continue;
14798
+ const unquoted = raw.replace(/^(['"])(.*)\1$/, "$2");
14799
+ if (unquoted === "" || unquoted === "your_key_here") continue;
14800
+ last = unquoted;
14801
+ }
14802
+ return last;
14803
+ }
14804
+ function isDevApiKey(value) {
14805
+ if (value === null || value === void 0) return false;
14806
+ return value.trim().startsWith("gt_dev_");
14807
+ }
14808
+ function isAnonApiKey(value) {
14809
+ if (value === null || value === void 0) return false;
14810
+ return AnonApiKeySchema.safeParse(value).success;
14811
+ }
14812
+ async function resolveEffectiveMcpCredential(projectRoot) {
14813
+ const root = projectRoot ?? process.cwd();
14814
+ const warnings = [];
14815
+ const envLocalKey = await readEnvLocalDevKey(root, warnings);
14816
+ const claimedKey = envLocalKey === null ? await readClaimedKey(root) : null;
14817
+ const anonKey = await readAnonKey(root);
14818
+ let effective = null;
14819
+ if (envLocalKey !== null) {
14820
+ effective = { source: "env-local", key: envLocalKey };
14821
+ } else if (claimedKey !== null) {
14822
+ effective = { source: "claimed-key", key: claimedKey };
14823
+ warnings.push("claimed-key-only");
14824
+ } else if (anonKey !== null) {
14825
+ effective = { source: "anon", key: anonKey };
14826
+ }
14827
+ return { effective, anonKey, warnings };
14828
+ }
14829
+ async function readEnvLocalDevKey(root, warnings) {
14830
+ const modules = await loadFsPath2();
14831
+ if (!modules) return null;
14832
+ const envPath = modules.path.join(root, ".env.local");
14833
+ let content;
14834
+ try {
14835
+ content = await modules.fs.readFile(envPath, "utf-8");
14836
+ } catch {
14837
+ return null;
14838
+ }
14839
+ const raw = readEnvLocalApiKey(content);
14840
+ if (raw === null) return null;
14841
+ const parsed = DevApiKeySchema.safeParse(raw);
14842
+ if (!parsed.success) {
14843
+ warnings.push("malformed-env-local");
14844
+ return null;
14845
+ }
14846
+ return parsed.data;
14847
+ }
14848
+ async function readMcpMarker(projectRoot) {
14849
+ const root = projectRoot ?? process.cwd();
14850
+ const modules = await loadFsPath2();
14851
+ if (!modules) return { status: "absent" };
14852
+ const markerPath = modules.path.join(root, GLASSTRACE_DIR2, MCP_MARKER_FILE);
14853
+ let content;
14854
+ try {
14855
+ content = await modules.fs.readFile(markerPath, "utf-8");
14856
+ } catch {
14857
+ return { status: "absent" };
14858
+ }
14859
+ let parsed;
14860
+ try {
14861
+ parsed = JSON.parse(content);
14862
+ } catch {
14863
+ return { status: "corrupted" };
14864
+ }
14865
+ if (parsed === null || typeof parsed !== "object") {
14866
+ return { status: "corrupted" };
14867
+ }
14868
+ const obj = parsed;
14869
+ const version2 = obj["version"];
14870
+ if (version2 === void 0) {
14871
+ const keyHash = obj["keyHash"];
14872
+ if (typeof keyHash !== "string" || keyHash === "") {
14873
+ return { status: "corrupted" };
14874
+ }
14875
+ return {
14876
+ status: "valid",
14877
+ credentialSource: "anon",
14878
+ credentialHash: keyHash
14879
+ };
14880
+ }
14881
+ if (version2 === 2) {
14882
+ const source = obj["credentialSource"];
14883
+ const hash2 = obj["credentialHash"];
14884
+ if (source !== "env-local" && source !== "claimed-key" && source !== "anon" || typeof hash2 !== "string" || hash2 === "") {
14885
+ return { status: "corrupted" };
14886
+ }
14887
+ return {
14888
+ status: "valid",
14889
+ credentialSource: source,
14890
+ credentialHash: hash2
14891
+ };
14892
+ }
14893
+ if (typeof version2 === "number" && version2 > 2) {
14894
+ return { status: "unknown-version" };
14895
+ }
14896
+ return { status: "corrupted" };
14897
+ }
14898
+ async function writeMcpMarker(projectRoot, target) {
14899
+ const modules = await loadFsPath2();
14900
+ if (!modules) return false;
14901
+ const dirPath = modules.path.join(projectRoot, GLASSTRACE_DIR2);
14902
+ const markerPath = modules.path.join(dirPath, MCP_MARKER_FILE);
14903
+ const state = await readMcpMarker(projectRoot);
14904
+ if (state.status === "valid" && state.credentialSource === target.credentialSource && state.credentialHash === target.credentialHash) {
14905
+ return false;
14906
+ }
14907
+ await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
14908
+ const body = JSON.stringify(
14909
+ {
14910
+ version: 2,
14911
+ credentialSource: target.credentialSource,
14912
+ credentialHash: target.credentialHash,
14913
+ configuredAt: (/* @__PURE__ */ new Date()).toISOString()
14914
+ },
14915
+ null,
14916
+ 2
14917
+ );
14918
+ await modules.fs.writeFile(markerPath, body, { mode: 384 });
14919
+ await modules.fs.chmod(markerPath, 384);
14920
+ return true;
14921
+ }
14922
+ var import_node_crypto, MCP_ENDPOINT, fsPathCache2, MCP_MARKER_FILE, GLASSTRACE_DIR2;
14923
+ var init_mcp_runtime = __esm({
14924
+ "src/mcp-runtime.ts"() {
14925
+ "use strict";
14926
+ import_node_crypto = require("node:crypto");
14927
+ init_dist();
14928
+ init_anon_key();
14929
+ MCP_ENDPOINT = "https://api.glasstrace.dev/mcp";
14930
+ MCP_MARKER_FILE = "mcp-connected";
14931
+ GLASSTRACE_DIR2 = ".glasstrace";
14932
+ }
14933
+ });
14934
+
14935
+ // src/cli/constants.ts
14936
+ function formatAgentName(name) {
14937
+ const displayNames = {
14938
+ claude: "Claude Code",
14939
+ codex: "Codex",
14940
+ gemini: "Gemini",
14941
+ cursor: "Cursor",
14942
+ windsurf: "Windsurf",
14943
+ generic: "Generic"
14944
+ };
14945
+ return displayNames[name];
14946
+ }
14947
+ var NEXT_CONFIG_NAMES;
14948
+ var init_constants = __esm({
14949
+ "src/cli/constants.ts"() {
14950
+ "use strict";
14951
+ init_mcp_runtime();
14952
+ NEXT_CONFIG_NAMES = ["next.config.ts", "next.config.js", "next.config.mjs"];
14953
+ }
14954
+ });
14955
+
14956
+ // src/cli/scaffolder.ts
14957
+ function hasRegisterGlasstraceCall(content) {
14958
+ return content.split("\n").some((line) => {
14959
+ const uncommented = line.replace(/\/\/.*$/, "");
14960
+ return /\bregisterGlasstrace\s*\(/.test(uncommented);
14961
+ });
14962
+ }
14963
+ function injectRegisterGlasstrace(content) {
14964
+ if (hasRegisterGlasstraceCall(content)) {
14965
+ return { injected: false, content };
14966
+ }
14967
+ const registerFnRegex = /export\s+(?:async\s+)?function\s+register\s*\([^)]*\)\s*\{/;
14968
+ const match = registerFnRegex.exec(content);
14969
+ if (!match) {
14970
+ return { injected: false, content };
14971
+ }
14972
+ const afterBrace = content.slice(match.index + match[0].length);
14973
+ const indentMatch = /\n([ \t]+)/.exec(afterBrace);
14974
+ const indent = indentMatch ? indentMatch[1] : " ";
14975
+ const importLine = 'import { registerGlasstrace } from "@glasstrace/sdk";\n';
14976
+ const hasGlasstraceImport2 = content.includes("@glasstrace/sdk");
14977
+ const insertPoint = match.index + match[0].length;
14978
+ const callInjection = `
14979
+ ${indent}// Glasstrace must be registered before other instrumentation
14980
+ ${indent}registerGlasstrace();
14981
+ `;
14982
+ let modified;
14983
+ if (hasGlasstraceImport2) {
14984
+ const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']@glasstrace\/sdk["']/;
14985
+ const importMatch = importRegex.exec(content);
14986
+ if (importMatch) {
14987
+ const specifiers = importMatch[1];
14988
+ const alreadyImported = specifiers.split(",").some((s) => s.trim() === "registerGlasstrace");
14989
+ if (alreadyImported) {
14990
+ modified = content.slice(0, insertPoint) + callInjection + content.slice(insertPoint);
14991
+ } else {
14992
+ const existingImports = specifiers.trimEnd();
14993
+ const separator = existingImports.endsWith(",") ? " " : ", ";
14994
+ const updatedImport = `import { ${existingImports.trim()}${separator}registerGlasstrace } from "@glasstrace/sdk"`;
14995
+ modified = content.replace(importMatch[0], updatedImport);
14996
+ const newMatch = registerFnRegex.exec(modified);
14997
+ if (newMatch) {
14998
+ const newInsertPoint = newMatch.index + newMatch[0].length;
14999
+ modified = modified.slice(0, newInsertPoint) + callInjection + modified.slice(newInsertPoint);
15000
+ }
15001
+ }
15002
+ } else {
15003
+ modified = importLine + content;
15004
+ const newMatch = registerFnRegex.exec(modified);
15005
+ if (newMatch) {
15006
+ const newInsertPoint = newMatch.index + newMatch[0].length;
15007
+ modified = modified.slice(0, newInsertPoint) + callInjection + modified.slice(newInsertPoint);
15008
+ }
15009
+ }
15010
+ } else {
15011
+ modified = importLine + content.slice(0, insertPoint) + callInjection + content.slice(insertPoint);
15012
+ }
15013
+ return { injected: true, content: modified };
15014
+ }
15015
+ function resolveInstrumentationTarget(projectRoot) {
15016
+ const rootExisting = [];
15017
+ const srcExisting = [];
15018
+ for (const name of INSTRUMENTATION_FILENAMES) {
15019
+ const rootPath = path.join(projectRoot, name);
15020
+ if (isRegularFile(rootPath)) {
15021
+ rootExisting.push(rootPath);
15022
+ }
15023
+ const srcPath = path.join(projectRoot, "src", name);
15024
+ if (isRegularFile(srcPath)) {
15025
+ srcExisting.push(srcPath);
15026
+ }
15027
+ }
15028
+ const existing = [...rootExisting, ...srcExisting];
15029
+ if (rootExisting.length > 0 && srcExisting.length > 0) {
15030
+ return {
15031
+ target: null,
15032
+ layout: null,
15033
+ existing,
15034
+ rootExisting,
15035
+ srcExisting,
15036
+ conflict: true
15037
+ };
15038
+ }
15039
+ if (srcExisting.length > 0) {
15040
+ return {
15041
+ target: srcExisting[0],
15042
+ layout: "src",
15043
+ existing,
15044
+ rootExisting,
15045
+ srcExisting,
15046
+ conflict: false
15047
+ };
15048
+ }
15049
+ if (rootExisting.length > 0) {
15050
+ return {
15051
+ target: rootExisting[0],
15052
+ layout: "root",
15053
+ existing,
15054
+ rootExisting,
15055
+ srcExisting,
15056
+ conflict: false
15057
+ };
15058
+ }
15059
+ const srcDir = path.join(projectRoot, "src");
15060
+ const layout = isDirectory(srcDir) ? "src" : "root";
15061
+ const target = layout === "src" ? path.join(projectRoot, "src", "instrumentation.ts") : path.join(projectRoot, "instrumentation.ts");
15062
+ return {
15063
+ target,
15064
+ layout,
15065
+ existing,
15066
+ rootExisting,
15067
+ srcExisting,
15068
+ conflict: false
15069
+ };
15070
+ }
15071
+ function isDirectory(p) {
15072
+ try {
15073
+ return fs.statSync(p).isDirectory();
15074
+ } catch {
15075
+ return false;
15076
+ }
15077
+ }
15078
+ function isRegularFile(p) {
15079
+ try {
15080
+ const stat2 = fs.lstatSync(p);
15081
+ if (stat2.isSymbolicLink()) {
15082
+ return fs.statSync(p).isFile();
15083
+ }
15084
+ return stat2.isFile();
15085
+ } catch {
15086
+ return false;
15087
+ }
15088
+ }
15089
+ function appendRegisterFunction(content) {
15090
+ const importLine = 'import { registerGlasstrace } from "@glasstrace/sdk";\n';
15091
+ 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";
15092
+ let withImport = content;
15093
+ const hasGlasstraceImport2 = content.includes("@glasstrace/sdk");
15094
+ if (!hasGlasstraceImport2) {
15095
+ withImport = importLine + content;
15096
+ } else {
15097
+ const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']@glasstrace\/sdk["']/;
15098
+ const importMatch = importRegex.exec(content);
15099
+ if (importMatch) {
15100
+ const specifiers = importMatch[1];
15101
+ const alreadyImported = specifiers.split(",").some((s) => s.trim() === "registerGlasstrace");
15102
+ if (!alreadyImported) {
15103
+ const existingImports = specifiers.trimEnd();
15104
+ const separator = existingImports.endsWith(",") ? " " : ", ";
15105
+ const updatedImport = `import { ${existingImports.trim()}${separator}registerGlasstrace } from "@glasstrace/sdk"`;
15106
+ withImport = content.replace(importMatch[0], updatedImport);
15107
+ }
15108
+ } else {
15109
+ withImport = importLine + content;
15110
+ }
15111
+ }
15112
+ const trailingNewline = withImport.endsWith("\n") ? "" : "\n";
15113
+ return withImport + trailingNewline + functionBlock;
15114
+ }
15115
+ async function defaultInstrumentationPrompt(question, defaultValue) {
15116
+ if (!process.stdin.isTTY) return defaultValue;
15117
+ const readline2 = await import("node:readline");
15118
+ const rl = readline2.createInterface({
15119
+ input: process.stdin,
15120
+ output: process.stdout
15121
+ });
15122
+ return new Promise((resolve2) => {
15123
+ const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
15124
+ rl.question(question + suffix, (answer) => {
15125
+ rl.close();
15126
+ const trimmed = answer.trim().toLowerCase();
15127
+ if (trimmed === "") {
15128
+ resolve2(defaultValue);
15129
+ return;
15130
+ }
15131
+ resolve2(trimmed === "y" || trimmed === "yes");
15132
+ });
15133
+ });
15134
+ }
15135
+ async function scaffoldInstrumentation(projectRoot, options = {}) {
15136
+ const target = resolveInstrumentationTarget(projectRoot);
15137
+ if (target.conflict) {
15138
+ return {
15139
+ action: "conflict",
15140
+ // Point the user at the `src/` variant — modern Next.js apps with a
15141
+ // `src/` directory load from there, so that's the merge target. The
15142
+ // competing path is reported separately for the error message.
15143
+ filePath: target.srcExisting[0],
15144
+ conflictingPath: target.rootExisting[0]
15145
+ };
15146
+ }
15147
+ const filePath = target.target;
15148
+ const layout = target.layout;
15149
+ if (filePath === null || layout === null) {
15150
+ return { action: "unrecognized" };
15151
+ }
15152
+ const force = options.force === true;
15153
+ const prompt = options.prompt ?? defaultInstrumentationPrompt;
15154
+ if (!fs.existsSync(filePath)) {
15155
+ const content = `import { registerGlasstrace } from "@glasstrace/sdk";
15156
+
15157
+ export async function register() {
15158
+ // Glasstrace must be registered before Prisma instrumentation
15159
+ // to ensure all ORM spans are captured correctly.
15160
+ // If you use @prisma/instrumentation, import it after this call.
15161
+ registerGlasstrace();
15162
+ }
15163
+ `;
15164
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
15165
+ fs.writeFileSync(filePath, content, "utf-8");
15166
+ return { action: "created", filePath, layout };
15167
+ }
15168
+ const existing = fs.readFileSync(filePath, "utf-8");
15169
+ if (hasRegisterGlasstraceCall(existing)) {
15170
+ return { action: "already-registered", filePath, layout };
15171
+ }
15172
+ if (!force) {
15173
+ const approved = await prompt(
15174
+ `Merge registerGlasstrace() into ${path.relative(projectRoot, filePath)}?`,
15175
+ false
15176
+ );
15177
+ if (!approved) {
15178
+ return { action: "skipped", filePath, layout };
15179
+ }
15180
+ }
15181
+ const injectResult = injectRegisterGlasstrace(existing);
15182
+ if (injectResult.injected) {
15183
+ fs.writeFileSync(filePath, injectResult.content, "utf-8");
15184
+ return { action: "injected", filePath, layout };
15122
15185
  }
15186
+ const appended = appendRegisterFunction(existing);
15187
+ fs.writeFileSync(filePath, appended, "utf-8");
15188
+ return { action: "appended", filePath, layout };
15123
15189
  }
15124
- async function readAnonKey(projectRoot) {
15125
- const root = projectRoot ?? process.cwd();
15126
- const modules = await loadFsPath();
15127
- if (modules) {
15128
- const keyPath = modules.path.join(root, GLASSTRACE_DIR, ANON_KEY_FILE);
15129
- try {
15130
- const content = await modules.fs.readFile(keyPath, "utf-8");
15131
- const result = AnonApiKeySchema.safeParse(content);
15132
- if (result.success) {
15133
- return result.data;
15134
- }
15135
- } catch {
15190
+ async function scaffoldNextConfig(projectRoot) {
15191
+ let configPath;
15192
+ let configName;
15193
+ for (const name of NEXT_CONFIG_NAMES) {
15194
+ const candidate = path.join(projectRoot, name);
15195
+ if (fs.existsSync(candidate)) {
15196
+ configPath = candidate;
15197
+ configName = name;
15198
+ break;
15136
15199
  }
15137
15200
  }
15138
- const cached2 = ephemeralKeyCache.get(root);
15139
- if (cached2 !== void 0) {
15140
- return cached2;
15201
+ if (configPath === void 0 || configName === void 0) {
15202
+ return null;
15141
15203
  }
15142
- return null;
15204
+ const existing = fs.readFileSync(configPath, "utf-8");
15205
+ if (existing.trim().length === 0) {
15206
+ return { modified: false, reason: "empty-file" };
15207
+ }
15208
+ if (existing.includes("withGlasstraceConfig")) {
15209
+ return { modified: false, reason: "already-wrapped" };
15210
+ }
15211
+ const isESM = configName.endsWith(".ts") || configName.endsWith(".mjs");
15212
+ if (isESM) {
15213
+ const importLine = 'import { withGlasstraceConfig } from "@glasstrace/sdk";\n';
15214
+ const wrapResult2 = wrapExport(existing);
15215
+ if (!wrapResult2.wrapped) {
15216
+ return { modified: false, reason: "no-export" };
15217
+ }
15218
+ const modified2 = importLine + "\n" + wrapResult2.content;
15219
+ fs.writeFileSync(configPath, modified2, "utf-8");
15220
+ return { modified: true };
15221
+ }
15222
+ const requireLine = 'const { withGlasstraceConfig } = require("@glasstrace/sdk");\n';
15223
+ const wrapResult = wrapCJSExport(existing);
15224
+ if (!wrapResult.wrapped) {
15225
+ return { modified: false, reason: "no-export" };
15226
+ }
15227
+ const modified = requireLine + "\n" + wrapResult.content;
15228
+ fs.writeFileSync(configPath, modified, "utf-8");
15229
+ return { modified: true };
15143
15230
  }
15144
- async function getOrCreateAnonKey(projectRoot) {
15145
- const root = projectRoot ?? process.cwd();
15146
- const existingKey = await readAnonKey(root);
15147
- if (existingKey !== null) {
15148
- return existingKey;
15231
+ function wrapExport(content) {
15232
+ const marker = "export default";
15233
+ const idx = content.lastIndexOf(marker);
15234
+ if (idx === -1) {
15235
+ return { content, wrapped: false };
15149
15236
  }
15150
- const cached2 = ephemeralKeyCache.get(root);
15151
- if (cached2 !== void 0) {
15152
- return cached2;
15237
+ const preamble = content.slice(0, idx);
15238
+ const exprRaw = content.slice(idx + marker.length);
15239
+ const expr = exprRaw.trim().replace(/;?\s*$/, "");
15240
+ if (expr.length === 0) {
15241
+ return { content, wrapped: false };
15153
15242
  }
15154
- const newKey = createAnonApiKey();
15155
- const modules = await loadFsPath();
15156
- if (!modules) {
15157
- ephemeralKeyCache.set(root, newKey);
15158
- return newKey;
15243
+ return {
15244
+ content: preamble + `export default withGlasstraceConfig(${expr});
15245
+ `,
15246
+ wrapped: true
15247
+ };
15248
+ }
15249
+ function wrapCJSExport(content) {
15250
+ const cjsMarker = "module.exports";
15251
+ const cjsIdx = content.lastIndexOf(cjsMarker);
15252
+ if (cjsIdx === -1) {
15253
+ return { content, wrapped: false };
15159
15254
  }
15160
- const dirPath = modules.path.join(root, GLASSTRACE_DIR);
15161
- const keyPath = modules.path.join(dirPath, ANON_KEY_FILE);
15162
- try {
15163
- await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
15164
- await modules.fs.writeFile(keyPath, newKey, { flag: "wx", mode: 384 });
15165
- return newKey;
15166
- } catch (err) {
15167
- const code = err.code;
15168
- if (code === "EEXIST") {
15169
- for (let attempt = 0; attempt < 3; attempt++) {
15170
- const winnerKey = await readAnonKey(root);
15171
- if (winnerKey !== null) {
15172
- return winnerKey;
15173
- }
15174
- if (attempt < 2) {
15175
- await new Promise((resolve2) => setTimeout(resolve2, 50));
15176
- }
15177
- }
15178
- try {
15179
- await modules.fs.writeFile(keyPath, newKey, { mode: 384 });
15180
- await modules.fs.chmod(keyPath, 384);
15181
- return newKey;
15182
- } catch {
15183
- }
15255
+ const preamble = content.slice(0, cjsIdx);
15256
+ const afterMarker = content.slice(cjsIdx + cjsMarker.length);
15257
+ const eqMatch = /^\s*=\s*/.exec(afterMarker);
15258
+ if (!eqMatch) {
15259
+ return { content, wrapped: false };
15260
+ }
15261
+ const exprRaw = afterMarker.slice(eqMatch[0].length);
15262
+ const expr = exprRaw.trim().replace(/;?\s*$/, "");
15263
+ if (expr.length === 0) {
15264
+ return { content, wrapped: false };
15265
+ }
15266
+ return {
15267
+ content: preamble + `module.exports = withGlasstraceConfig(${expr});
15268
+ `,
15269
+ wrapped: true
15270
+ };
15271
+ }
15272
+ async function scaffoldEnvLocal(projectRoot) {
15273
+ const filePath = path.join(projectRoot, ".env.local");
15274
+ if (fs.existsSync(filePath)) {
15275
+ const existing = fs.readFileSync(filePath, "utf-8");
15276
+ if (/^\s*#?\s*GLASSTRACE_API_KEY\s*=/m.test(existing)) {
15277
+ return false;
15184
15278
  }
15185
- ephemeralKeyCache.set(root, newKey);
15186
- console.warn(
15187
- `[glasstrace] Failed to persist anonymous key to ${keyPath}: ${err instanceof Error ? err.message : String(err)}. Using ephemeral key.`
15188
- );
15189
- return newKey;
15279
+ const separator = existing.endsWith("\n") ? "" : "\n";
15280
+ fs.writeFileSync(filePath, existing + separator + "# GLASSTRACE_API_KEY=your_key_here\n", "utf-8");
15281
+ return true;
15190
15282
  }
15283
+ fs.writeFileSync(filePath, "# GLASSTRACE_API_KEY=your_key_here\n", "utf-8");
15284
+ return true;
15191
15285
  }
15192
- var GLASSTRACE_DIR, ANON_KEY_FILE, fsPathCache, ephemeralKeyCache;
15193
- var init_anon_key = __esm({
15194
- "src/anon-key.ts"() {
15286
+ async function addCoverageMapEnv(projectRoot) {
15287
+ const filePath = path.join(projectRoot, ".env.local");
15288
+ if (!fs.existsSync(filePath)) {
15289
+ fs.writeFileSync(filePath, "GLASSTRACE_COVERAGE_MAP=true\n", "utf-8");
15290
+ return true;
15291
+ }
15292
+ const existing = fs.readFileSync(filePath, "utf-8");
15293
+ const keyRegex = /^(\s*GLASSTRACE_COVERAGE_MAP\s*=\s*)(.*)$/m;
15294
+ const keyMatch = keyRegex.exec(existing);
15295
+ if (keyMatch) {
15296
+ const currentValue = keyMatch[2].trim();
15297
+ if (currentValue === "true") {
15298
+ return false;
15299
+ }
15300
+ const updated = existing.replace(keyRegex, `${keyMatch[1]}true`);
15301
+ fs.writeFileSync(filePath, updated, "utf-8");
15302
+ return true;
15303
+ }
15304
+ const separator = existing.endsWith("\n") ? "" : "\n";
15305
+ fs.writeFileSync(filePath, existing + separator + "GLASSTRACE_COVERAGE_MAP=true\n", "utf-8");
15306
+ return true;
15307
+ }
15308
+ async function scaffoldGitignore(projectRoot) {
15309
+ const filePath = path.join(projectRoot, ".gitignore");
15310
+ if (fs.existsSync(filePath)) {
15311
+ const existing = fs.readFileSync(filePath, "utf-8");
15312
+ const lines = existing.split("\n").map((l) => l.trim());
15313
+ if (lines.includes(".glasstrace/")) {
15314
+ return false;
15315
+ }
15316
+ const separator = existing.endsWith("\n") ? "" : "\n";
15317
+ fs.writeFileSync(filePath, existing + separator + ".glasstrace/\n", "utf-8");
15318
+ return true;
15319
+ }
15320
+ fs.writeFileSync(filePath, ".glasstrace/\n", "utf-8");
15321
+ return true;
15322
+ }
15323
+ var fs, path, INSTRUMENTATION_FILENAMES;
15324
+ var init_scaffolder = __esm({
15325
+ "src/cli/scaffolder.ts"() {
15195
15326
  "use strict";
15196
- init_dist();
15197
- GLASSTRACE_DIR = ".glasstrace";
15198
- ANON_KEY_FILE = "anon_key";
15199
- ephemeralKeyCache = /* @__PURE__ */ new Map();
15327
+ fs = __toESM(require("node:fs"), 1);
15328
+ path = __toESM(require("node:path"), 1);
15329
+ init_constants();
15330
+ init_mcp_runtime();
15331
+ INSTRUMENTATION_FILENAMES = [
15332
+ "instrumentation.ts",
15333
+ "instrumentation.js",
15334
+ "instrumentation.mjs"
15335
+ ];
15200
15336
  }
15201
15337
  });
15202
15338
 
@@ -15360,12 +15496,12 @@ var init_detect = __esm({
15360
15496
  });
15361
15497
 
15362
15498
  // src/agent-detection/configs.ts
15363
- function generateMcpConfig(agent, endpoint, anonKey) {
15499
+ function generateMcpConfig(agent, endpoint, bearer) {
15364
15500
  if (!endpoint || endpoint.trim() === "") {
15365
15501
  throw new Error("endpoint must not be empty");
15366
15502
  }
15367
- if (!anonKey || anonKey.trim() === "") {
15368
- throw new Error("anonKey must not be empty");
15503
+ if (!bearer || bearer.trim() === "") {
15504
+ throw new Error("bearer must not be empty");
15369
15505
  }
15370
15506
  switch (agent.name) {
15371
15507
  case "claude":
@@ -15376,7 +15512,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
15376
15512
  type: "http",
15377
15513
  url: endpoint,
15378
15514
  headers: {
15379
- Authorization: `Bearer ${anonKey}`
15515
+ Authorization: `Bearer ${bearer}`
15380
15516
  }
15381
15517
  }
15382
15518
  }
@@ -15400,7 +15536,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
15400
15536
  glasstrace: {
15401
15537
  httpUrl: endpoint,
15402
15538
  headers: {
15403
- Authorization: `Bearer ${anonKey}`
15539
+ Authorization: `Bearer ${bearer}`
15404
15540
  }
15405
15541
  }
15406
15542
  }
@@ -15415,7 +15551,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
15415
15551
  glasstrace: {
15416
15552
  url: endpoint,
15417
15553
  headers: {
15418
- Authorization: `Bearer ${anonKey}`
15554
+ Authorization: `Bearer ${bearer}`
15419
15555
  }
15420
15556
  }
15421
15557
  }
@@ -15430,7 +15566,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
15430
15566
  glasstrace: {
15431
15567
  serverUrl: endpoint,
15432
15568
  headers: {
15433
- Authorization: `Bearer ${anonKey}`
15569
+ Authorization: `Bearer ${bearer}`
15434
15570
  }
15435
15571
  }
15436
15572
  }
@@ -15445,7 +15581,7 @@ function generateMcpConfig(agent, endpoint, anonKey) {
15445
15581
  glasstrace: {
15446
15582
  url: endpoint,
15447
15583
  headers: {
15448
- Authorization: `Bearer ${anonKey}`
15584
+ Authorization: `Bearer ${bearer}`
15449
15585
  }
15450
15586
  }
15451
15587
  }
@@ -16873,19 +17009,23 @@ var init_uninit = __esm({
16873
17009
  // src/cli/mcp-add.ts
16874
17010
  var mcp_add_exports = {};
16875
17011
  __export(mcp_add_exports, {
16876
- mcpAdd: () => mcpAdd
17012
+ mcpAdd: () => mcpAdd,
17013
+ registerViaCli: () => registerViaCli
16877
17014
  });
16878
- async function registerViaCli(agent, anonKey) {
17015
+ async function registerViaCli(agent, bearer) {
16879
17016
  if (!agent.cliAvailable) {
16880
17017
  return false;
16881
17018
  }
17019
+ if (agent.name !== "codex" && !isAnonApiKey(bearer)) {
17020
+ return false;
17021
+ }
16882
17022
  try {
16883
17023
  switch (agent.name) {
16884
17024
  case "claude": {
16885
17025
  const payload = JSON.stringify({
16886
17026
  type: "http",
16887
17027
  url: MCP_ENDPOINT,
16888
- headers: { Authorization: `Bearer ${anonKey}` }
17028
+ headers: { Authorization: `Bearer ${bearer}` }
16889
17029
  });
16890
17030
  await execFileAsync("claude", [
16891
17031
  "mcp",
@@ -16929,7 +17069,7 @@ async function registerViaCli(agent, anonKey) {
16929
17069
  "--transport",
16930
17070
  "http",
16931
17071
  "--header",
16932
- `Authorization: Bearer ${anonKey}`,
17072
+ `Authorization: Bearer ${bearer}`,
16933
17073
  "glasstrace",
16934
17074
  MCP_ENDPOINT
16935
17075
  ]);
@@ -16942,26 +17082,41 @@ async function registerViaCli(agent, anonKey) {
16942
17082
  return false;
16943
17083
  }
16944
17084
  }
17085
+ async function markerMatchesEffective(projectRoot, effective) {
17086
+ const state = await readMcpMarker(projectRoot);
17087
+ if (state.status !== "valid") return false;
17088
+ return state.credentialHash === identityFingerprint(effective.key);
17089
+ }
16945
17090
  async function mcpAdd(options) {
16946
17091
  const force = options?.force ?? false;
16947
17092
  const dryRun = options?.dryRun ?? false;
16948
17093
  const projectRoot = process.cwd();
16949
17094
  const messages = [];
16950
- const anonKey = await readAnonKey(projectRoot);
16951
- if (anonKey === null) {
17095
+ const resolved = await resolveEffectiveMcpCredential(projectRoot);
17096
+ if (resolved.effective === null) {
16952
17097
  return {
16953
17098
  exitCode: 1,
16954
17099
  results: [],
16955
17100
  messages: ["Error: Run `glasstrace init` first to generate an API key."]
16956
17101
  };
16957
17102
  }
17103
+ if (resolved.warnings.includes("claimed-key-only")) {
17104
+ messages.push(
17105
+ "Note: dev key was loaded from .glasstrace/claimed-key. Copy it into .env.local so your app and Codex pick it up automatically."
17106
+ );
17107
+ }
16958
17108
  const markerPath = path6.join(projectRoot, ".glasstrace", "mcp-connected");
16959
17109
  if (fs6.existsSync(markerPath) && !force) {
16960
- return {
16961
- exitCode: 0,
16962
- results: [],
16963
- messages: ["MCP already configured. Use --force to reconfigure."]
16964
- };
17110
+ if (await markerMatchesEffective(projectRoot, resolved.effective)) {
17111
+ return {
17112
+ exitCode: 0,
17113
+ results: [],
17114
+ messages: ["MCP already configured. Use --force to reconfigure."]
17115
+ };
17116
+ }
17117
+ messages.push(
17118
+ "Detected a credential change since MCP was last configured. Refreshing MCP config so queries use the current account credential."
17119
+ );
16965
17120
  }
16966
17121
  const agents = await detectAgents(projectRoot);
16967
17122
  const detectedNonGeneric = agents.filter((a) => a.name !== "generic");
@@ -16970,7 +17125,7 @@ async function mcpAdd(options) {
16970
17125
  messages.push("Dry run: would perform the following actions:", "");
16971
17126
  for (const agent of targetAgents) {
16972
17127
  const name = formatAgentName(agent.name);
16973
- if (agent.cliAvailable) {
17128
+ if (agent.cliAvailable && resolved.effective.source === "anon") {
16974
17129
  messages.push(
16975
17130
  ` ${name}: Register via CLI (${agent.name} mcp add)`
16976
17131
  );
@@ -16993,10 +17148,11 @@ async function mcpAdd(options) {
16993
17148
  return { exitCode: 0, results: [], messages };
16994
17149
  }
16995
17150
  const results = [];
17151
+ const bearer = resolved.effective.key;
16996
17152
  for (const agent of targetAgents) {
16997
17153
  const name = formatAgentName(agent.name);
16998
17154
  if (agent.name !== "generic") {
16999
- const cliSuccess = await registerViaCli(agent, anonKey);
17155
+ const cliSuccess = await registerViaCli(agent, bearer);
17000
17156
  if (cliSuccess) {
17001
17157
  const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
17002
17158
  if (infoContent !== "") {
@@ -17013,7 +17169,7 @@ async function mcpAdd(options) {
17013
17169
  }
17014
17170
  if (agent.mcpConfigPath !== null) {
17015
17171
  try {
17016
- const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);
17172
+ const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
17017
17173
  await writeMcpConfig(agent, configContent, projectRoot);
17018
17174
  if (fs6.existsSync(agent.mcpConfigPath)) {
17019
17175
  const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
@@ -17058,7 +17214,10 @@ async function mcpAdd(options) {
17058
17214
  );
17059
17215
  const anySuccess = results.some((r) => r.success);
17060
17216
  if (anySuccess) {
17061
- await scaffoldMcpMarker(projectRoot, anonKey);
17217
+ await writeMcpMarker(projectRoot, {
17218
+ credentialSource: resolved.effective.source,
17219
+ credentialHash: identityFingerprint(resolved.effective.key)
17220
+ });
17062
17221
  }
17063
17222
  messages.push("", "MCP registration summary:");
17064
17223
  for (const result of results) {
@@ -17090,11 +17249,10 @@ var init_mcp_add = __esm({
17090
17249
  fs6 = __toESM(require("node:fs"), 1);
17091
17250
  path6 = __toESM(require("node:path"), 1);
17092
17251
  import_node_util = require("node:util");
17093
- init_anon_key();
17252
+ init_mcp_runtime();
17094
17253
  init_detect();
17095
17254
  init_configs();
17096
17255
  init_inject();
17097
- init_scaffolder();
17098
17256
  init_constants();
17099
17257
  execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
17100
17258
  }
@@ -17414,6 +17572,7 @@ var fs9 = __toESM(require("node:fs"), 1);
17414
17572
  var path9 = __toESM(require("node:path"), 1);
17415
17573
  var readline = __toESM(require("node:readline"), 1);
17416
17574
  init_scaffolder();
17575
+ init_mcp_runtime();
17417
17576
 
17418
17577
  // src/import-graph.ts
17419
17578
  var fs2 = __toESM(require("node:fs/promises"), 1);
@@ -18332,6 +18491,9 @@ Then add this as the first statement in your register() function:
18332
18491
  );
18333
18492
  }
18334
18493
  let anyConfigWritten = false;
18494
+ let anyConfigRewrittenWithBearer = false;
18495
+ const resolved = await resolveEffectiveMcpCredential(projectRoot);
18496
+ const bearer = resolved.effective?.key ?? anonKey;
18335
18497
  if (isCI) {
18336
18498
  const genericAgent = {
18337
18499
  name: "generic",
@@ -18340,7 +18502,7 @@ Then add this as the first statement in your register() function:
18340
18502
  cliAvailable: false,
18341
18503
  registrationCommand: null
18342
18504
  };
18343
- const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, anonKey);
18505
+ const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, bearer);
18344
18506
  const decision = await decideMcpConfigAction({
18345
18507
  configPath: genericAgent.mcpConfigPath,
18346
18508
  expectedContent: genericConfig,
@@ -18348,6 +18510,9 @@ Then add this as the first statement in your register() function:
18348
18510
  });
18349
18511
  if (decision !== "skip") {
18350
18512
  await writeMcpConfig(genericAgent, genericConfig, projectRoot);
18513
+ if (genericAgent.mcpConfigPath !== null && fs9.existsSync(genericAgent.mcpConfigPath)) {
18514
+ anyConfigRewrittenWithBearer = true;
18515
+ }
18351
18516
  }
18352
18517
  if (genericAgent.mcpConfigPath !== null && fs9.existsSync(genericAgent.mcpConfigPath)) {
18353
18518
  anyConfigWritten = true;
@@ -18368,17 +18533,18 @@ Then add this as the first statement in your register() function:
18368
18533
  cliAvailable: false,
18369
18534
  registrationCommand: null
18370
18535
  };
18371
- const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, anonKey);
18536
+ const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, bearer);
18372
18537
  await writeMcpConfig(genericAgent, genericConfig, projectRoot);
18373
18538
  if (genericAgent.mcpConfigPath !== null && fs9.existsSync(genericAgent.mcpConfigPath)) {
18374
18539
  anyConfigWritten = true;
18540
+ anyConfigRewrittenWithBearer = true;
18375
18541
  }
18376
18542
  agents = [];
18377
18543
  }
18378
18544
  const configuredNames = [];
18379
18545
  for (const agent of agents) {
18380
18546
  try {
18381
- const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);
18547
+ const configContent = generateMcpConfig(agent, MCP_ENDPOINT, bearer);
18382
18548
  const decision = await decideMcpConfigAction({
18383
18549
  configPath: agent.mcpConfigPath,
18384
18550
  expectedContent: configContent,
@@ -18399,6 +18565,7 @@ Then add this as the first statement in your register() function:
18399
18565
  continue;
18400
18566
  }
18401
18567
  anyConfigWritten = true;
18568
+ anyConfigRewrittenWithBearer = true;
18402
18569
  const infoContent = generateInfoSection(agent, MCP_ENDPOINT);
18403
18570
  if (infoContent !== "") {
18404
18571
  await injectInfoSection(agent, infoContent, projectRoot);
@@ -18422,8 +18589,13 @@ Then add this as the first statement in your register() function:
18422
18589
  [".mcp.json", ".cursor/mcp.json", ".gemini/settings.json", ".codex/config.toml"],
18423
18590
  projectRoot
18424
18591
  );
18425
- if (anyConfigWritten) {
18426
- const markerCreated = await scaffoldMcpMarker(projectRoot, anonKey);
18592
+ if (anyConfigRewrittenWithBearer) {
18593
+ const markerSource = resolved.effective?.source ?? "anon";
18594
+ const markerHash = identityFingerprint(bearer);
18595
+ const markerCreated = await writeMcpMarker(projectRoot, {
18596
+ credentialSource: markerSource,
18597
+ credentialHash: markerHash
18598
+ });
18427
18599
  if (markerCreated) {
18428
18600
  summary.push("Created .glasstrace/mcp-connected marker");
18429
18601
  }
@@ -18492,7 +18664,7 @@ async function verifyAnonKeyRegistration(projectRoot) {
18492
18664
  }
18493
18665
  const baseConfig = resolveConfig({ apiKey: devKey });
18494
18666
  const config2 = { ...baseConfig, apiKey: devKey };
18495
- const sdkVersion = true ? "1.1.0" : "0.0.0-dev";
18667
+ const sdkVersion = true ? "1.1.1" : "0.0.0-dev";
18496
18668
  const result = await verifyInitReachable(config2, anonKey, sdkVersion);
18497
18669
  if (result.ok) {
18498
18670
  return { outcome: "verified" };