@glasstrace/sdk 0.15.1 → 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 (78) 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-ZNOD6FC7.js → chunk-CTJI2YKA.js} +8 -15
  13. package/dist/{chunk-ZNOD6FC7.js.map → chunk-CTJI2YKA.js.map} +1 -1
  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-A2AZL6MZ.js → chunk-O63DJKIJ.js} +169 -18
  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-ROFOJQWN.js → chunk-XNDHQN4S.js} +7 -11
  28. package/dist/{chunk-ROFOJQWN.js.map → chunk-XNDHQN4S.js.map} +1 -1
  29. package/dist/cli/init.cjs +673 -161
  30. package/dist/cli/init.cjs.map +1 -1
  31. package/dist/cli/init.d.cts +54 -1
  32. package/dist/cli/init.d.ts +54 -1
  33. package/dist/cli/init.js +146 -37
  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 +10 -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 +56 -59
  43. package/dist/cli/uninit.cjs.map +1 -1
  44. package/dist/cli/uninit.js +4 -4
  45. package/dist/cli/validate.cjs +2 -2
  46. package/dist/cli/validate.js +3 -6
  47. package/dist/cli/validate.js.map +1 -1
  48. package/dist/{esm-MDK7CZID.js → esm-KBPHCVB4.js} +3 -3
  49. package/dist/{getMachineId-bsd-4NIRBWME.js → getMachineId-bsd-345PYXFX.js} +4 -7
  50. package/dist/{getMachineId-bsd-4NIRBWME.js.map → getMachineId-bsd-345PYXFX.js.map} +1 -1
  51. package/dist/{getMachineId-darwin-2XNOCCJQ.js → getMachineId-darwin-5L2D25AD.js} +4 -7
  52. package/dist/{getMachineId-darwin-2XNOCCJQ.js.map → getMachineId-darwin-5L2D25AD.js.map} +1 -1
  53. package/dist/{getMachineId-linux-V6YSQEY7.js → getMachineId-linux-KJR4P5HN.js} +3 -6
  54. package/dist/{getMachineId-linux-V6YSQEY7.js.map → getMachineId-linux-KJR4P5HN.js.map} +1 -1
  55. package/dist/{getMachineId-unsupported-4FKBJNVO.js → getMachineId-unsupported-NDNXDYDY.js} +3 -6
  56. package/dist/{getMachineId-unsupported-4FKBJNVO.js.map → getMachineId-unsupported-NDNXDYDY.js.map} +1 -1
  57. package/dist/{getMachineId-win-WLRZBKVG.js → getMachineId-win-T7PJNJXG.js} +4 -7
  58. package/dist/{getMachineId-win-WLRZBKVG.js.map → getMachineId-win-T7PJNJXG.js.map} +1 -1
  59. package/dist/index.cjs +449 -461
  60. package/dist/index.cjs.map +1 -1
  61. package/dist/index.d.cts +38 -3
  62. package/dist/index.d.ts +38 -3
  63. package/dist/index.js +195 -701
  64. package/dist/index.js.map +1 -1
  65. package/dist/{monorepo-YILKGQXQ.js → monorepo-N5Z63XP7.js} +4 -4
  66. package/dist/{source-map-uploader-3GWUQDTS.js → source-map-uploader-MUZPI2S5.js} +5 -4
  67. package/dist/source-map-uploader-MUZPI2S5.js.map +1 -0
  68. package/package.json +1 -1
  69. package/dist/chunk-2LDBR3F3.js.map +0 -1
  70. package/dist/chunk-A2AZL6MZ.js.map +0 -1
  71. package/dist/chunk-BGZ7J74D.js.map +0 -1
  72. package/dist/chunk-UPS5BGER.js +0 -182
  73. package/dist/chunk-UPS5BGER.js.map +0 -1
  74. package/dist/chunk-WK7MPK2T.js.map +0 -1
  75. package/dist/chunk-YMEXDDTA.js.map +0 -1
  76. /package/dist/{esm-MDK7CZID.js.map → chunk-NSBPE2FW.js.map} +0 -0
  77. /package/dist/{monorepo-YILKGQXQ.js.map → esm-KBPHCVB4.js.map} +0 -0
  78. /package/dist/{source-map-uploader-3GWUQDTS.js.map → monorepo-N5Z63XP7.js.map} +0 -0
@@ -61,6 +61,15 @@ type CompletedStep = "instrumentation" | "next-config" | "env-local" | "gitignor
61
61
  */
62
62
  interface RollbackState {
63
63
  steps: CompletedStep[];
64
+ /**
65
+ * Absolute path of the instrumentation file that the scaffolder
66
+ * wrote to. May be either `{root}/instrumentation.ts` or
67
+ * `{root}/src/instrumentation.ts` depending on the project layout
68
+ * (DISC-493 Issue 1). When absent, rollback falls back to the
69
+ * root path for backward compatibility with callers that do not
70
+ * populate this field.
71
+ */
72
+ instrumentationPath?: string;
64
73
  /** Original instrumentation.ts content saved before injection.
65
74
  * When present, rollback restores this instead of using removeRegisterGlasstrace. */
66
75
  originalInstrumentationContent?: string;
@@ -78,5 +87,49 @@ declare function rollbackSteps(steps: CompletedStep[], projectRoot: string, stat
78
87
  * bottom calls this function and translates the result to process.exit().
79
88
  */
80
89
  declare function runInit(options: InitOptions): Promise<InitResult>;
90
+ /**
91
+ * Outcome of {@link verifyAnonKeyRegistration}:
92
+ *
93
+ * - `"verified"` — the server registered the anon key (HTTP 2xx with a
94
+ * schema-valid response body).
95
+ * - `"skipped"` — no anon key was on disk, so no verification request
96
+ * was sent. Typically means MCP auto-configuration failed earlier
97
+ * (warnings were already emitted) — distinct from a verification
98
+ * success.
99
+ * - `"failed"` — the verification request was sent and failed.
100
+ * `error` is a user-facing message distinguishing the failure class
101
+ * (`fetch failed: ...`, `server rejected the key ...`, or
102
+ * `server returned malformed response ...`) with no anon key bytes.
103
+ */
104
+ type VerifyAnonKeyOutcome = {
105
+ outcome: "verified";
106
+ } | {
107
+ outcome: "skipped";
108
+ } | {
109
+ outcome: "failed";
110
+ error: string;
111
+ };
112
+ /**
113
+ * Verifies that the anonymous key written by init is registered
114
+ * server-side. Called at the end of the scaffold flow so that when it
115
+ * fails, the user sees an actionable error rather than a misleading
116
+ * "initialized successfully" followed by silent MCP authentication
117
+ * failures (DISC-494).
118
+ *
119
+ * Returns a discriminated outcome so the CLI can distinguish a genuine
120
+ * verification pass from the "no anon key on disk" skip case. On
121
+ * failure the error message distinguishes three classes:
122
+ * - "fetch failed" — transport error (DNS, TCP, TLS, timeout)
123
+ * - "server rejected the key" — HTTP 4xx/5xx
124
+ * - "server returned malformed response" — HTTP 2xx with unparseable
125
+ * body
126
+ *
127
+ * The anon key is NEVER included in the returned message. Callers
128
+ * (the CLI entry point) render it verbatim to stderr via the errors
129
+ * array and exit non-zero.
130
+ *
131
+ * @internal Exported for testability.
132
+ */
133
+ declare function verifyAnonKeyRegistration(projectRoot: string): Promise<VerifyAnonKeyOutcome>;
81
134
 
82
- export { type InitOptions, type InitResult, decideMcpConfigAction, meetsNodeVersion, rollbackSteps, runInit };
135
+ export { type InitOptions, type InitResult, type VerifyAnonKeyOutcome, decideMcpConfigAction, meetsNodeVersion, rollbackSteps, runInit, verifyAnonKeyRegistration };
@@ -61,6 +61,15 @@ type CompletedStep = "instrumentation" | "next-config" | "env-local" | "gitignor
61
61
  */
62
62
  interface RollbackState {
63
63
  steps: CompletedStep[];
64
+ /**
65
+ * Absolute path of the instrumentation file that the scaffolder
66
+ * wrote to. May be either `{root}/instrumentation.ts` or
67
+ * `{root}/src/instrumentation.ts` depending on the project layout
68
+ * (DISC-493 Issue 1). When absent, rollback falls back to the
69
+ * root path for backward compatibility with callers that do not
70
+ * populate this field.
71
+ */
72
+ instrumentationPath?: string;
64
73
  /** Original instrumentation.ts content saved before injection.
65
74
  * When present, rollback restores this instead of using removeRegisterGlasstrace. */
66
75
  originalInstrumentationContent?: string;
@@ -78,5 +87,49 @@ declare function rollbackSteps(steps: CompletedStep[], projectRoot: string, stat
78
87
  * bottom calls this function and translates the result to process.exit().
79
88
  */
80
89
  declare function runInit(options: InitOptions): Promise<InitResult>;
90
+ /**
91
+ * Outcome of {@link verifyAnonKeyRegistration}:
92
+ *
93
+ * - `"verified"` — the server registered the anon key (HTTP 2xx with a
94
+ * schema-valid response body).
95
+ * - `"skipped"` — no anon key was on disk, so no verification request
96
+ * was sent. Typically means MCP auto-configuration failed earlier
97
+ * (warnings were already emitted) — distinct from a verification
98
+ * success.
99
+ * - `"failed"` — the verification request was sent and failed.
100
+ * `error` is a user-facing message distinguishing the failure class
101
+ * (`fetch failed: ...`, `server rejected the key ...`, or
102
+ * `server returned malformed response ...`) with no anon key bytes.
103
+ */
104
+ type VerifyAnonKeyOutcome = {
105
+ outcome: "verified";
106
+ } | {
107
+ outcome: "skipped";
108
+ } | {
109
+ outcome: "failed";
110
+ error: string;
111
+ };
112
+ /**
113
+ * Verifies that the anonymous key written by init is registered
114
+ * server-side. Called at the end of the scaffold flow so that when it
115
+ * fails, the user sees an actionable error rather than a misleading
116
+ * "initialized successfully" followed by silent MCP authentication
117
+ * failures (DISC-494).
118
+ *
119
+ * Returns a discriminated outcome so the CLI can distinguish a genuine
120
+ * verification pass from the "no anon key on disk" skip case. On
121
+ * failure the error message distinguishes three classes:
122
+ * - "fetch failed" — transport error (DNS, TCP, TLS, timeout)
123
+ * - "server rejected the key" — HTTP 4xx/5xx
124
+ * - "server returned malformed response" — HTTP 2xx with unparseable
125
+ * body
126
+ *
127
+ * The anon key is NEVER included in the returned message. Callers
128
+ * (the CLI entry point) render it verbatim to stderr via the errors
129
+ * array and exit non-zero.
130
+ *
131
+ * @internal Exported for testability.
132
+ */
133
+ declare function verifyAnonKeyRegistration(projectRoot: string): Promise<VerifyAnonKeyOutcome>;
81
134
 
82
- export { type InitOptions, type InitResult, decideMcpConfigAction, meetsNodeVersion, rollbackSteps, runInit };
135
+ export { type InitOptions, type InitResult, type VerifyAnonKeyOutcome, decideMcpConfigAction, meetsNodeVersion, rollbackSteps, runInit, verifyAnonKeyRegistration };
package/dist/cli/init.js CHANGED
@@ -1,17 +1,21 @@
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-ROFOJQWN.js";
18
+ } from "../chunk-XNDHQN4S.js";
15
19
  import {
16
20
  detectAgents,
17
21
  generateInfoSection,
@@ -19,37 +23,35 @@ import {
19
23
  injectInfoSection,
20
24
  updateGitignore,
21
25
  writeMcpConfig
22
- } from "../chunk-ZNOD6FC7.js";
26
+ } from "../chunk-CTJI2YKA.js";
23
27
  import {
24
28
  getOrCreateAnonKey,
25
29
  readAnonKey
26
- } from "../chunk-ECEN724Y.js";
27
- import "../chunk-YMEXDDTA.js";
30
+ } from "../chunk-TM5NKZTO.js";
31
+ import "../chunk-7JBKXSBU.js";
28
32
  import {
29
33
  addCoverageMapEnv,
30
34
  isDevApiKey,
31
35
  mcpConfigMatches,
32
36
  readEnvLocalApiKey,
37
+ resolveInstrumentationTarget,
33
38
  scaffoldEnvLocal,
34
39
  scaffoldGitignore,
35
40
  scaffoldInstrumentation,
36
41
  scaffoldMcpMarker,
37
42
  scaffoldNextConfig
38
- } from "../chunk-A2AZL6MZ.js";
43
+ } from "../chunk-O63DJKIJ.js";
39
44
  import {
40
45
  MCP_ENDPOINT,
41
46
  NEXT_CONFIG_NAMES,
42
47
  formatAgentName
43
- } from "../chunk-BL3YDC6V.js";
44
- import {
45
- init_esm_shims
46
- } from "../chunk-BGZ7J74D.js";
48
+ } from "../chunk-DXRZKKSO.js";
49
+ import "../chunk-NSBPE2FW.js";
47
50
 
48
51
  // src/cli/init.ts
49
- init_esm_shims();
50
- import * as fs from "fs";
51
- import * as path from "path";
52
- 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";
53
55
  function meetsNodeVersion(minMajor) {
54
56
  const [major] = process.versions.node.split(".").map(Number);
55
57
  return major >= minMajor;
@@ -108,7 +110,7 @@ async function rollbackSteps(steps, projectRoot, state) {
108
110
  try {
109
111
  switch (step) {
110
112
  case "instrumentation": {
111
- const instrPath = path.join(projectRoot, "instrumentation.ts");
113
+ const instrPath = state?.instrumentationPath ?? path.join(projectRoot, "instrumentation.ts");
112
114
  if (fs.existsSync(instrPath)) {
113
115
  const content = fs.readFileSync(instrPath, "utf-8");
114
116
  if (isInitCreatedInstrumentation(content)) {
@@ -211,32 +213,76 @@ async function runInit(options) {
211
213
  }
212
214
  const rollbackState = { steps: [] };
213
215
  try {
214
- const instrPath = path.join(projectRoot, "instrumentation.ts");
215
- if (fs.existsSync(instrPath)) {
216
- 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
+ }
225
+ }
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;
217
234
  }
218
- const instrResult = await scaffoldInstrumentation(projectRoot);
235
+ const relativePath = instrResult.filePath !== void 0 ? path.relative(projectRoot, instrResult.filePath) : "instrumentation.ts";
219
236
  switch (instrResult.action) {
220
237
  case "created":
221
- summary.push("Created instrumentation.ts");
238
+ summary.push(`Created ${relativePath}`);
222
239
  rollbackState.steps.push("instrumentation");
223
240
  break;
224
241
  case "injected":
225
- 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
+ );
226
249
  rollbackState.steps.push("instrumentation");
227
250
  break;
228
251
  case "already-registered":
229
- summary.push("Skipped instrumentation.ts (registerGlasstrace already present)");
252
+ summary.push(`Skipped ${relativePath} (registerGlasstrace already present)`);
253
+ break;
254
+ case "skipped":
255
+ warnings.push(
256
+ `Preserved ${relativePath} (merge declined; re-run with --force to apply the merge without prompting)`
257
+ );
230
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
+ }
231
269
  case "unrecognized":
232
270
  warnings.push(
233
- '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
+ `
234
280
  );
235
281
  break;
236
282
  }
237
283
  } catch (err) {
238
284
  await rollbackSteps(rollbackState.steps, projectRoot, rollbackState);
239
- 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)}`);
240
286
  return { exitCode: 1, summary, warnings, errors };
241
287
  }
242
288
  try {
@@ -429,8 +475,64 @@ async function runInit(options) {
429
475
  warnings.push(`Import graph scan failed: ${err instanceof Error ? err.message : String(err)}. You can run it later.`);
430
476
  }
431
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
+ }
432
491
  return { exitCode: 0, summary, warnings, errors };
433
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
+ }
434
536
  function parseArgs(argv) {
435
537
  const args = argv.slice(2);
436
538
  let yes = false;
@@ -538,19 +640,25 @@ Usage: glasstrace mcp add [--force] [--dry-run]
538
640
  }
539
641
  }
540
642
  if (result.summary.length > 0) {
541
- process.stderr.write("\nGlasstrace initialized successfully!\n\n");
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
+ }
542
648
  for (const line of result.summary) {
543
649
  process.stderr.write(` - ${line}
544
650
  `);
545
651
  }
546
- process.stderr.write("\nNext steps:\n");
547
- process.stderr.write(" 1. Start your Next.js dev server\n");
548
- process.stderr.write(
549
- " 2. Glasstrace works immediately in anonymous mode\n"
550
- );
551
- process.stderr.write(
552
- " 3. To link to your account, set GLASSTRACE_API_KEY in .env.local\n\n"
553
- );
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
+ }
554
662
  }
555
663
  process.exit(result.exitCode);
556
664
  }).catch((err) => {
@@ -597,7 +705,7 @@ Usage: glasstrace mcp add [--force] [--dry-run]
597
705
  } else if (subcommand === "status") {
598
706
  const remainingArgs = process.argv.slice(3);
599
707
  const json = remainingArgs.includes("--json");
600
- 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 }]) => {
601
709
  let projectRoot = process.cwd();
602
710
  try {
603
711
  projectRoot = resolve(projectRoot).projectRoot;
@@ -652,6 +760,7 @@ export {
652
760
  decideMcpConfigAction,
653
761
  meetsNodeVersion,
654
762
  rollbackSteps,
655
- runInit
763
+ runInit,
764
+ verifyAnonKeyRegistration
656
765
  };
657
766
  //# sourceMappingURL=init.js.map