@glasstrace/sdk 0.14.2 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +84 -1
  2. package/dist/adapters/drizzle.js +2 -5
  3. package/dist/adapters/drizzle.js.map +1 -1
  4. package/dist/{chunk-PD2SKFQQ.js → chunk-55FBXXER.js} +4 -8
  5. package/dist/{chunk-PD2SKFQQ.js.map → chunk-55FBXXER.js.map} +1 -1
  6. package/dist/chunk-5C2TJFLB.js +851 -0
  7. package/dist/chunk-5C2TJFLB.js.map +1 -0
  8. package/dist/{chunk-YMEXDDTA.js → chunk-7JBKXSBU.js} +3 -99
  9. package/dist/chunk-7JBKXSBU.js.map +1 -0
  10. package/dist/{chunk-2LDBR3F3.js → chunk-BANTDXUT.js} +15 -74
  11. package/dist/chunk-BANTDXUT.js.map +1 -0
  12. package/dist/{chunk-WV3NIPWJ.js → chunk-CTJI2YKA.js} +23 -288
  13. package/dist/chunk-CTJI2YKA.js.map +1 -0
  14. package/dist/{chunk-WK7MPK2T.js → chunk-DQ25VOKK.js} +1 -89
  15. package/dist/chunk-DQ25VOKK.js.map +1 -0
  16. package/dist/{chunk-BL3YDC6V.js → chunk-DXRZKKSO.js} +1 -6
  17. package/dist/{chunk-BL3YDC6V.js.map → chunk-DXRZKKSO.js.map} +1 -1
  18. package/dist/{chunk-BGZ7J74D.js → chunk-NSBPE2FW.js} +2 -16
  19. package/dist/chunk-O63DJKIJ.js +460 -0
  20. package/dist/chunk-O63DJKIJ.js.map +1 -0
  21. package/dist/{chunk-ECEN724Y.js → chunk-TM5NKZTO.js} +4 -8
  22. package/dist/{chunk-ECEN724Y.js.map → chunk-TM5NKZTO.js.map} +1 -1
  23. package/dist/chunk-VUZCLMIX.js +57 -0
  24. package/dist/chunk-VUZCLMIX.js.map +1 -0
  25. package/dist/{chunk-OSXIUKD5.js → chunk-WZXVS2EO.js} +1 -6
  26. package/dist/{chunk-OSXIUKD5.js.map → chunk-WZXVS2EO.js.map} +1 -1
  27. package/dist/{chunk-ARAOZCZT.js → chunk-XNDHQN4S.js} +122 -24
  28. package/dist/chunk-XNDHQN4S.js.map +1 -0
  29. package/dist/cli/init.cjs +1110 -255
  30. package/dist/cli/init.cjs.map +1 -1
  31. package/dist/cli/init.d.cts +86 -1
  32. package/dist/cli/init.d.ts +86 -1
  33. package/dist/cli/init.js +277 -66
  34. package/dist/cli/init.js.map +1 -1
  35. package/dist/cli/mcp-add.cjs +16 -16
  36. package/dist/cli/mcp-add.cjs.map +1 -1
  37. package/dist/cli/mcp-add.js +12 -13
  38. package/dist/cli/mcp-add.js.map +1 -1
  39. package/dist/cli/status.cjs +2 -2
  40. package/dist/cli/status.js +4 -7
  41. package/dist/cli/status.js.map +1 -1
  42. package/dist/cli/uninit.cjs +138 -20
  43. package/dist/cli/uninit.cjs.map +1 -1
  44. package/dist/cli/uninit.d.cts +38 -8
  45. package/dist/cli/uninit.d.ts +38 -8
  46. package/dist/cli/uninit.js +8 -5
  47. package/dist/cli/validate.cjs +135 -0
  48. package/dist/cli/validate.cjs.map +1 -0
  49. package/dist/cli/validate.d.cts +60 -0
  50. package/dist/cli/validate.d.ts +60 -0
  51. package/dist/cli/validate.js +100 -0
  52. package/dist/cli/validate.js.map +1 -0
  53. package/dist/{esm-MDK7CZID.js → esm-KBPHCVB4.js} +3 -3
  54. package/dist/{getMachineId-bsd-4NIRBWME.js → getMachineId-bsd-345PYXFX.js} +4 -7
  55. package/dist/{getMachineId-bsd-4NIRBWME.js.map → getMachineId-bsd-345PYXFX.js.map} +1 -1
  56. package/dist/{getMachineId-darwin-2XNOCCJQ.js → getMachineId-darwin-5L2D25AD.js} +4 -7
  57. package/dist/{getMachineId-darwin-2XNOCCJQ.js.map → getMachineId-darwin-5L2D25AD.js.map} +1 -1
  58. package/dist/{getMachineId-linux-V6YSQEY7.js → getMachineId-linux-KJR4P5HN.js} +3 -6
  59. package/dist/{getMachineId-linux-V6YSQEY7.js.map → getMachineId-linux-KJR4P5HN.js.map} +1 -1
  60. package/dist/{getMachineId-unsupported-4FKBJNVO.js → getMachineId-unsupported-NDNXDYDY.js} +3 -6
  61. package/dist/{getMachineId-unsupported-4FKBJNVO.js.map → getMachineId-unsupported-NDNXDYDY.js.map} +1 -1
  62. package/dist/{getMachineId-win-WLRZBKVG.js → getMachineId-win-T7PJNJXG.js} +4 -7
  63. package/dist/{getMachineId-win-WLRZBKVG.js.map → getMachineId-win-T7PJNJXG.js.map} +1 -1
  64. package/dist/index.cjs +519 -494
  65. package/dist/index.cjs.map +1 -1
  66. package/dist/index.d.cts +47 -6
  67. package/dist/index.d.ts +47 -6
  68. package/dist/index.js +250 -719
  69. package/dist/index.js.map +1 -1
  70. package/dist/{monorepo-YILKGQXQ.js → monorepo-N5Z63XP7.js} +4 -4
  71. package/dist/{source-map-uploader-3GWUQDTS.js → source-map-uploader-MUZPI2S5.js} +5 -4
  72. package/dist/source-map-uploader-MUZPI2S5.js.map +1 -0
  73. package/package.json +6 -4
  74. package/dist/chunk-2LDBR3F3.js.map +0 -1
  75. package/dist/chunk-ARAOZCZT.js.map +0 -1
  76. package/dist/chunk-BGZ7J74D.js.map +0 -1
  77. package/dist/chunk-UPS5BGER.js +0 -182
  78. package/dist/chunk-UPS5BGER.js.map +0 -1
  79. package/dist/chunk-WK7MPK2T.js.map +0 -1
  80. package/dist/chunk-WV3NIPWJ.js.map +0 -1
  81. package/dist/chunk-YMEXDDTA.js.map +0 -1
  82. /package/dist/{esm-MDK7CZID.js.map → chunk-NSBPE2FW.js.map} +0 -0
  83. /package/dist/{monorepo-YILKGQXQ.js.map → esm-KBPHCVB4.js.map} +0 -0
  84. /package/dist/{source-map-uploader-3GWUQDTS.js.map → monorepo-N5Z63XP7.js.map} +0 -0
package/dist/cli/init.js CHANGED
@@ -1,53 +1,86 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolveProjectRoot
4
- } from "../chunk-PD2SKFQQ.js";
4
+ } from "../chunk-55FBXXER.js";
5
5
  import {
6
- buildImportGraph
7
- } from "../chunk-UPS5BGER.js";
6
+ buildImportGraph,
7
+ verifyInitReachable
8
+ } from "../chunk-5C2TJFLB.js";
9
+ import {
10
+ resolveConfig
11
+ } from "../chunk-VUZCLMIX.js";
8
12
  import {
9
13
  isInitCreatedInstrumentation,
10
14
  removeGlasstraceConfigImport,
11
15
  removeRegisterGlasstrace,
12
16
  unwrapCJSExport,
13
17
  unwrapExport
14
- } from "../chunk-ARAOZCZT.js";
18
+ } from "../chunk-XNDHQN4S.js";
15
19
  import {
16
- addCoverageMapEnv,
17
20
  detectAgents,
18
21
  generateInfoSection,
19
22
  generateMcpConfig,
20
23
  injectInfoSection,
24
+ updateGitignore,
25
+ writeMcpConfig
26
+ } from "../chunk-CTJI2YKA.js";
27
+ import {
28
+ getOrCreateAnonKey,
29
+ readAnonKey
30
+ } from "../chunk-TM5NKZTO.js";
31
+ import "../chunk-7JBKXSBU.js";
32
+ import {
33
+ addCoverageMapEnv,
34
+ isDevApiKey,
35
+ mcpConfigMatches,
36
+ readEnvLocalApiKey,
37
+ resolveInstrumentationTarget,
21
38
  scaffoldEnvLocal,
22
39
  scaffoldGitignore,
23
40
  scaffoldInstrumentation,
24
41
  scaffoldMcpMarker,
25
- scaffoldNextConfig,
26
- updateGitignore,
27
- writeMcpConfig
28
- } from "../chunk-WV3NIPWJ.js";
29
- import {
30
- getOrCreateAnonKey
31
- } from "../chunk-ECEN724Y.js";
32
- import "../chunk-YMEXDDTA.js";
42
+ scaffoldNextConfig
43
+ } from "../chunk-O63DJKIJ.js";
33
44
  import {
34
45
  MCP_ENDPOINT,
35
46
  NEXT_CONFIG_NAMES,
36
47
  formatAgentName
37
- } from "../chunk-BL3YDC6V.js";
38
- import {
39
- init_esm_shims
40
- } from "../chunk-BGZ7J74D.js";
48
+ } from "../chunk-DXRZKKSO.js";
49
+ import "../chunk-NSBPE2FW.js";
41
50
 
42
51
  // src/cli/init.ts
43
- init_esm_shims();
44
- import * as fs from "fs";
45
- import * as path from "path";
46
- import * as readline from "readline";
52
+ import * as fs from "node:fs";
53
+ import * as path from "node:path";
54
+ import * as readline from "node:readline";
47
55
  function meetsNodeVersion(minMajor) {
48
56
  const [major] = process.versions.node.split(".").map(Number);
49
57
  return major >= minMajor;
50
58
  }
59
+ async function decideMcpConfigAction(options) {
60
+ const { configPath, expectedContent, force } = options;
61
+ if (configPath === null) return "write";
62
+ const exists = options.existsSync ?? fs.existsSync;
63
+ const read = options.readFile ?? ((p) => fs.readFileSync(p, "utf-8"));
64
+ const prompt = options.prompt ?? promptYesNo;
65
+ if (!exists(configPath)) return "write";
66
+ let existingContent;
67
+ try {
68
+ existingContent = read(configPath);
69
+ } catch {
70
+ return "write";
71
+ }
72
+ if (mcpConfigMatches(existingContent, expectedContent)) {
73
+ return "write";
74
+ }
75
+ if (force) {
76
+ return "force-overwrite";
77
+ }
78
+ const answer = await prompt(
79
+ `Existing MCP config at ${configPath} differs from Glasstrace's template. Overwrite?`,
80
+ false
81
+ );
82
+ return answer ? "force-overwrite" : "skip";
83
+ }
51
84
  async function promptYesNo(question, defaultValue) {
52
85
  if (!process.stdin.isTTY) {
53
86
  return defaultValue;
@@ -77,7 +110,7 @@ async function rollbackSteps(steps, projectRoot, state) {
77
110
  try {
78
111
  switch (step) {
79
112
  case "instrumentation": {
80
- const instrPath = path.join(projectRoot, "instrumentation.ts");
113
+ const instrPath = state?.instrumentationPath ?? path.join(projectRoot, "instrumentation.ts");
81
114
  if (fs.existsSync(instrPath)) {
82
115
  const content = fs.readFileSync(instrPath, "utf-8");
83
116
  if (isInitCreatedInstrumentation(content)) {
@@ -180,32 +213,76 @@ async function runInit(options) {
180
213
  }
181
214
  const rollbackState = { steps: [] };
182
215
  try {
183
- const instrPath = path.join(projectRoot, "instrumentation.ts");
184
- if (fs.existsSync(instrPath)) {
185
- rollbackState.originalInstrumentationContent = fs.readFileSync(instrPath, "utf-8");
216
+ const preResolved = resolveInstrumentationTarget(projectRoot);
217
+ if (!preResolved.conflict && preResolved.target !== null) {
218
+ rollbackState.instrumentationPath = preResolved.target;
219
+ if (fs.existsSync(preResolved.target)) {
220
+ rollbackState.originalInstrumentationContent = fs.readFileSync(
221
+ preResolved.target,
222
+ "utf-8"
223
+ );
224
+ }
186
225
  }
187
- const instrResult = await scaffoldInstrumentation(projectRoot);
226
+ const instrResult = await scaffoldInstrumentation(projectRoot, {
227
+ // `--yes` implies non-interactive automation and must not hang on a
228
+ // merge confirmation prompt. `--force` skips the prompt explicitly
229
+ // (DISC-1247 Scenario 2c parity).
230
+ force: options.force === true || options.yes
231
+ });
232
+ if (instrResult.filePath !== void 0) {
233
+ rollbackState.instrumentationPath = instrResult.filePath;
234
+ }
235
+ const relativePath = instrResult.filePath !== void 0 ? path.relative(projectRoot, instrResult.filePath) : "instrumentation.ts";
188
236
  switch (instrResult.action) {
189
237
  case "created":
190
- summary.push("Created instrumentation.ts");
238
+ summary.push(`Created ${relativePath}`);
191
239
  rollbackState.steps.push("instrumentation");
192
240
  break;
193
241
  case "injected":
194
- summary.push("Added registerGlasstrace() to existing instrumentation.ts");
242
+ summary.push(`Added registerGlasstrace() to existing ${relativePath}`);
243
+ rollbackState.steps.push("instrumentation");
244
+ break;
245
+ case "appended":
246
+ summary.push(
247
+ `Appended register() with registerGlasstrace() to ${relativePath}`
248
+ );
195
249
  rollbackState.steps.push("instrumentation");
196
250
  break;
197
251
  case "already-registered":
198
- summary.push("Skipped instrumentation.ts (registerGlasstrace already present)");
252
+ summary.push(`Skipped ${relativePath} (registerGlasstrace already present)`);
199
253
  break;
254
+ case "skipped":
255
+ warnings.push(
256
+ `Preserved ${relativePath} (merge declined; re-run with --force to apply the merge without prompting)`
257
+ );
258
+ break;
259
+ case "conflict": {
260
+ const primary = instrResult.filePath !== void 0 ? path.relative(projectRoot, instrResult.filePath) : "src/instrumentation.ts";
261
+ const competing = instrResult.conflictingPath !== void 0 ? path.relative(projectRoot, instrResult.conflictingPath) : "instrumentation.ts";
262
+ await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
263
+ errors.push(
264
+ `Both ${primary} and ${competing} exist. Next.js's loader behavior is undefined when both are present.
265
+ Merge your instrumentation into ${primary} and remove ${competing}, then re-run init.`
266
+ );
267
+ return { exitCode: 1, summary, warnings, errors };
268
+ }
200
269
  case "unrecognized":
201
270
  warnings.push(
202
- 'instrumentation.ts exists but has no recognizable register() function.\nAdd this import at the top of your file:\n\n import { registerGlasstrace } from "@glasstrace/sdk";\n\nThen add this as the first statement in your register() function:\n\n registerGlasstrace();\n'
271
+ `${relativePath} exists but has no recognizable register() function.
272
+ Add this import at the top of your file:
273
+
274
+ import { registerGlasstrace } from "@glasstrace/sdk";
275
+
276
+ Then add this as the first statement in your register() function:
277
+
278
+ registerGlasstrace();
279
+ `
203
280
  );
204
281
  break;
205
282
  }
206
283
  } catch (err) {
207
284
  await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
208
- errors.push(`Failed to write instrumentation.ts: ${err instanceof Error ? err.message : String(err)}`);
285
+ errors.push(`Failed to write instrumentation file: ${err instanceof Error ? err.message : String(err)}`);
209
286
  return { exitCode: 1, summary, warnings, errors };
210
287
  }
211
288
  try {
@@ -228,10 +305,20 @@ async function runInit(options) {
228
305
  return { exitCode: 1, summary, warnings, errors };
229
306
  }
230
307
  try {
308
+ const envPathForCheck = path.join(projectRoot, ".env.local");
309
+ let existingDevKey = false;
310
+ if (fs.existsSync(envPathForCheck)) {
311
+ const existingContent = fs.readFileSync(envPathForCheck, "utf-8");
312
+ existingDevKey = isDevApiKey(readEnvLocalApiKey(existingContent));
313
+ }
231
314
  const envCreated = await scaffoldEnvLocal(projectRoot);
232
315
  if (envCreated) {
233
316
  summary.push("Updated .env.local with Glasstrace configuration");
234
317
  rollbackState.steps.push("env-local");
318
+ } else if (existingDevKey) {
319
+ summary.push(
320
+ "Preserved existing .env.local (GLASSTRACE_API_KEY contains a claimed dev key)"
321
+ );
235
322
  } else {
236
323
  summary.push("Skipped .env.local (GLASSTRACE_API_KEY already configured)");
237
324
  }
@@ -256,7 +343,11 @@ async function runInit(options) {
256
343
  const ciEnv = process.env["CI"];
257
344
  const isCI = typeof ciEnv === "string" && ciEnv.trim() !== "" && ciEnv.toLowerCase() !== "false" && ciEnv.trim() !== "0" || process.env["GITHUB_ACTIONS"] === "true";
258
345
  try {
346
+ const preExistingAnonKey = await readAnonKey(projectRoot);
259
347
  const anonKey = await getOrCreateAnonKey(projectRoot);
348
+ if (preExistingAnonKey !== null) {
349
+ summary.push("Preserved existing .glasstrace/anon_key");
350
+ }
260
351
  let anyConfigWritten = false;
261
352
  if (isCI) {
262
353
  const genericAgent = {
@@ -267,7 +358,14 @@ async function runInit(options) {
267
358
  registrationCommand: null
268
359
  };
269
360
  const genericConfig = generateMcpConfig(genericAgent, MCP_ENDPOINT, anonKey);
270
- await writeMcpConfig(genericAgent, genericConfig, projectRoot);
361
+ const decision = await decideMcpConfigAction({
362
+ configPath: genericAgent.mcpConfigPath,
363
+ expectedContent: genericConfig,
364
+ force: true
365
+ });
366
+ if (decision !== "skip") {
367
+ await writeMcpConfig(genericAgent, genericConfig, projectRoot);
368
+ }
271
369
  if (genericAgent.mcpConfigPath !== null && fs.existsSync(genericAgent.mcpConfigPath)) {
272
370
  anyConfigWritten = true;
273
371
  summary.push("Created .glasstrace/mcp.json (CI mode)");
@@ -298,6 +396,20 @@ async function runInit(options) {
298
396
  for (const agent of agents) {
299
397
  try {
300
398
  const configContent = generateMcpConfig(agent, MCP_ENDPOINT, anonKey);
399
+ const decision = await decideMcpConfigAction({
400
+ configPath: agent.mcpConfigPath,
401
+ expectedContent: configContent,
402
+ force: options.force === true || options.yes
403
+ });
404
+ if (decision === "skip") {
405
+ summary.push(
406
+ `Preserved existing ${agent.mcpConfigPath ?? agent.name} (user declined overwrite)`
407
+ );
408
+ if (agent.mcpConfigPath !== null && fs.existsSync(agent.mcpConfigPath)) {
409
+ anyConfigWritten = true;
410
+ }
411
+ continue;
412
+ }
301
413
  await writeMcpConfig(agent, configContent, projectRoot);
302
414
  const configExists = agent.mcpConfigPath !== null && fs.existsSync(agent.mcpConfigPath);
303
415
  if (!configExists) {
@@ -363,17 +475,76 @@ async function runInit(options) {
363
475
  warnings.push(`Import graph scan failed: ${err instanceof Error ? err.message : String(err)}. You can run it later.`);
364
476
  }
365
477
  }
478
+ const skipVerify = process.env["GLASSTRACE_SKIP_INIT_VERIFY"] === "1" || process.env["GLASSTRACE_SKIP_INIT_VERIFY"] === "true" || process.env["VITEST"] === "true";
479
+ if (!skipVerify && !isCI) {
480
+ const verifyResult = await verifyAnonKeyRegistration(projectRoot);
481
+ if (verifyResult.outcome === "failed") {
482
+ errors.push(verifyResult.error);
483
+ return { exitCode: 2, summary, warnings, errors };
484
+ }
485
+ if (verifyResult.outcome === "verified") {
486
+ summary.push("Verified anon key registration with Glasstrace API");
487
+ } else {
488
+ summary.push("Skipped anon key verification (no anon key on disk)");
489
+ }
490
+ }
366
491
  return { exitCode: 0, summary, warnings, errors };
367
492
  }
493
+ async function verifyAnonKeyRegistration(projectRoot) {
494
+ const anonKey = await readAnonKey(projectRoot);
495
+ if (anonKey === null) {
496
+ return { outcome: "skipped" };
497
+ }
498
+ let devKey;
499
+ try {
500
+ const envPath = path.join(projectRoot, ".env.local");
501
+ if (fs.existsSync(envPath)) {
502
+ const envContent = fs.readFileSync(envPath, "utf-8");
503
+ const effective = readEnvLocalApiKey(envContent);
504
+ if (effective !== null && isDevApiKey(effective)) {
505
+ devKey = effective;
506
+ }
507
+ }
508
+ } catch {
509
+ }
510
+ const baseConfig = resolveConfig({ apiKey: devKey });
511
+ const config = { ...baseConfig, apiKey: devKey };
512
+ const sdkVersion = true ? "0.16.0" : "0.0.0-dev";
513
+ const result = await verifyInitReachable(config, anonKey, sdkVersion);
514
+ if (result.ok) {
515
+ return { outcome: "verified" };
516
+ }
517
+ const hint = "Run 'npx glasstrace status' or 'npx glasstrace doctor' to diagnose.";
518
+ switch (result.reason) {
519
+ case "transport":
520
+ return {
521
+ outcome: "failed",
522
+ error: `Glasstrace init verification failed: fetch failed: ${result.detail}. ${hint}`
523
+ };
524
+ case "rejected":
525
+ return {
526
+ outcome: "failed",
527
+ error: `Glasstrace init verification failed: server rejected the key (HTTP ${result.status}). ${hint}`
528
+ };
529
+ case "malformed":
530
+ return {
531
+ outcome: "failed",
532
+ error: `Glasstrace init verification failed: server returned malformed response. ${hint}`
533
+ };
534
+ }
535
+ }
368
536
  function parseArgs(argv) {
369
537
  const args = argv.slice(2);
370
538
  let yes = false;
371
539
  let coverageMap = false;
540
+ let force = false;
372
541
  for (const arg of args) {
373
542
  if (arg === "--yes" || arg === "-y") {
374
543
  yes = true;
375
544
  } else if (arg === "--coverage-map") {
376
545
  coverageMap = true;
546
+ } else if (arg === "--force") {
547
+ force = true;
377
548
  }
378
549
  }
379
550
  if (!process.stdin.isTTY) {
@@ -382,7 +553,8 @@ function parseArgs(argv) {
382
553
  return {
383
554
  projectRoot: process.cwd(),
384
555
  yes,
385
- coverageMap
556
+ coverageMap,
557
+ force
386
558
  };
387
559
  }
388
560
  var scriptPath = typeof process !== "undefined" && process.argv[1] !== void 0 ? process.argv[1].replace(/\\/g, "/") : void 0;
@@ -424,47 +596,84 @@ Usage: glasstrace mcp add [--force] [--dry-run]
424
596
  process.exit(1);
425
597
  }
426
598
  } else if (subcommand === void 0 || subcommand === "init" || subcommand.startsWith("-")) {
427
- const options = parseArgs(process.argv);
428
- runInit(options).then((result) => {
429
- if (result.errors.length > 0) {
430
- for (const err of result.errors) {
431
- process.stderr.write(`Error: ${err}
432
- `);
433
- }
599
+ const forwardedArgs = process.argv.slice(subcommand === "init" ? 3 : 2);
600
+ if (forwardedArgs.includes("--validate")) {
601
+ let validateProjectRoot = process.cwd();
602
+ try {
603
+ validateProjectRoot = resolveProjectRoot(validateProjectRoot).projectRoot;
604
+ } catch {
434
605
  }
435
- if (result.warnings.length > 0) {
436
- for (const warn of result.warnings) {
437
- process.stderr.write(`Warning: ${warn}
606
+ import("./validate.js").then(({ runValidate }) => runValidate({ projectRoot: validateProjectRoot })).then((result) => {
607
+ for (const line of result.summary) {
608
+ process.stderr.write(`${line}
438
609
  `);
439
610
  }
440
- }
441
- if (result.summary.length > 0) {
442
- process.stderr.write("\nGlasstrace initialized successfully!\n\n");
443
- for (const line of result.summary) {
444
- process.stderr.write(` - ${line}
611
+ for (const issue of result.issues) {
612
+ process.stderr.write(` - ${issue.message}
445
613
  `);
614
+ if (issue.fix) {
615
+ process.stderr.write(` Fix: ${issue.fix}
616
+ `);
617
+ }
446
618
  }
447
- process.stderr.write("\nNext steps:\n");
448
- process.stderr.write(" 1. Start your Next.js dev server\n");
619
+ process.exit(result.exitCode);
620
+ }).catch((err) => {
449
621
  process.stderr.write(
450
- " 2. Glasstrace works immediately in anonymous mode\n"
622
+ `Fatal error: ${err instanceof Error ? err.message : String(err)}
623
+ `
451
624
  );
625
+ process.exit(1);
626
+ });
627
+ } else {
628
+ const options = parseArgs(process.argv);
629
+ runInit(options).then((result) => {
630
+ if (result.errors.length > 0) {
631
+ for (const err of result.errors) {
632
+ process.stderr.write(`Error: ${err}
633
+ `);
634
+ }
635
+ }
636
+ if (result.warnings.length > 0) {
637
+ for (const warn of result.warnings) {
638
+ process.stderr.write(`Warning: ${warn}
639
+ `);
640
+ }
641
+ }
642
+ if (result.summary.length > 0) {
643
+ if (result.exitCode === 0) {
644
+ process.stderr.write("\nGlasstrace initialized successfully!\n\n");
645
+ } else {
646
+ process.stderr.write("\nGlasstrace init completed with errors.\n\n");
647
+ }
648
+ for (const line of result.summary) {
649
+ process.stderr.write(` - ${line}
650
+ `);
651
+ }
652
+ if (result.exitCode === 0) {
653
+ process.stderr.write("\nNext steps:\n");
654
+ process.stderr.write(" 1. Start your Next.js dev server\n");
655
+ process.stderr.write(
656
+ " 2. Glasstrace works immediately in anonymous mode\n"
657
+ );
658
+ process.stderr.write(
659
+ " 3. To link to your account, set GLASSTRACE_API_KEY in .env.local\n\n"
660
+ );
661
+ }
662
+ }
663
+ process.exit(result.exitCode);
664
+ }).catch((err) => {
452
665
  process.stderr.write(
453
- " 3. To link to your account, set GLASSTRACE_API_KEY in .env.local\n\n"
454
- );
455
- }
456
- process.exit(result.exitCode);
457
- }).catch((err) => {
458
- process.stderr.write(
459
- `Fatal error: ${err instanceof Error ? err.message : String(err)}
666
+ `Fatal error: ${err instanceof Error ? err.message : String(err)}
460
667
  `
461
- );
462
- process.exit(1);
463
- });
668
+ );
669
+ process.exit(1);
670
+ });
671
+ }
464
672
  } else if (subcommand === "uninit") {
465
673
  const remainingArgs = process.argv.slice(3);
466
674
  const dryRun = remainingArgs.includes("--dry-run");
467
- import("./uninit.js").then(({ runUninit }) => runUninit({ projectRoot: process.cwd(), dryRun })).then((result) => {
675
+ const force = remainingArgs.includes("--force");
676
+ import("./uninit.js").then(({ runUninit }) => runUninit({ projectRoot: process.cwd(), dryRun, force })).then((result) => {
468
677
  if (result.errors.length > 0) {
469
678
  for (const err of result.errors) {
470
679
  process.stderr.write(`Error: ${err}
@@ -496,7 +705,7 @@ Usage: glasstrace mcp add [--force] [--dry-run]
496
705
  } else if (subcommand === "status") {
497
706
  const remainingArgs = process.argv.slice(3);
498
707
  const json = remainingArgs.includes("--json");
499
- Promise.all([import("./status.js"), import("../monorepo-YILKGQXQ.js")]).then(([{ runStatus }, { resolveProjectRoot: resolve }]) => {
708
+ Promise.all([import("./status.js"), import("../monorepo-N5Z63XP7.js")]).then(([{ runStatus }, { resolveProjectRoot: resolve }]) => {
500
709
  let projectRoot = process.cwd();
501
710
  try {
502
711
  projectRoot = resolve(projectRoot).projectRoot;
@@ -538,8 +747,8 @@ Usage: glasstrace mcp add [--force] [--dry-run]
538
747
  `Unknown command: ${subcommand}
539
748
 
540
749
  Usage:
541
- glasstrace init [--yes] [--coverage-map]
542
- glasstrace uninit [--dry-run]
750
+ glasstrace init [--yes] [--coverage-map] [--force] [--validate]
751
+ glasstrace uninit [--dry-run] [--force]
543
752
  glasstrace status [--json]
544
753
  glasstrace mcp add [--force] [--dry-run]
545
754
  `
@@ -548,8 +757,10 @@ Usage:
548
757
  }
549
758
  }
550
759
  export {
760
+ decideMcpConfigAction,
551
761
  meetsNodeVersion,
552
762
  rollbackSteps,
553
- runInit
763
+ runInit,
764
+ verifyAnonKeyRegistration
554
765
  };
555
766
  //# sourceMappingURL=init.js.map