@glasstrace/sdk 1.3.9 → 1.5.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 (81) hide show
  1. package/README.md +124 -0
  2. package/dist/capture-error-BmQz7xF6.d.cts +455 -0
  3. package/dist/capture-error-CTgSYxek.d.ts +455 -0
  4. package/dist/{chunk-XS5W3SPL.js → chunk-4WI7B5FQ.js} +91 -5
  5. package/dist/chunk-4WI7B5FQ.js.map +1 -0
  6. package/dist/{chunk-JZ475QRH.js → chunk-D3QXU2VM.js} +22 -191
  7. package/dist/chunk-D3QXU2VM.js.map +1 -0
  8. package/dist/{chunk-GYTCZSAV.js → chunk-MFYOQOD7.js} +2 -2
  9. package/dist/{chunk-4WUHMLMM.js → chunk-MMKFFF2L.js} +2 -2
  10. package/dist/{chunk-JH7EGRC5.js → chunk-N3XIVM2U.js} +158 -12
  11. package/dist/chunk-N3XIVM2U.js.map +1 -0
  12. package/dist/{chunk-FKBCEOJ5.js → chunk-Q42BY5BA.js} +2 -2
  13. package/dist/{chunk-DBKG6SRI.js → chunk-QU26IKIJ.js} +2 -2
  14. package/dist/{chunk-ADUD4PEK.js → chunk-TANUWTFO.js} +3 -3
  15. package/dist/{chunk-LJMZXJ45.js → chunk-YLY7AGLC.js} +9 -6
  16. package/dist/chunk-YLY7AGLC.js.map +1 -0
  17. package/dist/chunk-ZBQQXVHD.js +208 -0
  18. package/dist/chunk-ZBQQXVHD.js.map +1 -0
  19. package/dist/cli/init.cjs +218 -35
  20. package/dist/cli/init.cjs.map +1 -1
  21. package/dist/cli/init.js +69 -12
  22. package/dist/cli/init.js.map +1 -1
  23. package/dist/cli/mcp-add.cjs +57 -26
  24. package/dist/cli/mcp-add.cjs.map +1 -1
  25. package/dist/cli/mcp-add.js +12 -9
  26. package/dist/cli/mcp-add.js.map +1 -1
  27. package/dist/cli/status.cjs +33 -3
  28. package/dist/cli/status.cjs.map +1 -1
  29. package/dist/cli/status.js +12 -3
  30. package/dist/cli/status.js.map +1 -1
  31. package/dist/cli/uninit.cjs +27 -3
  32. package/dist/cli/uninit.cjs.map +1 -1
  33. package/dist/cli/uninit.d.cts +10 -2
  34. package/dist/cli/uninit.d.ts +10 -2
  35. package/dist/cli/uninit.js +4 -3
  36. package/dist/cli/upgrade-instructions.cjs +440 -0
  37. package/dist/cli/upgrade-instructions.cjs.map +1 -0
  38. package/dist/cli/upgrade-instructions.d.cts +48 -0
  39. package/dist/cli/upgrade-instructions.d.ts +48 -0
  40. package/dist/cli/upgrade-instructions.js +80 -0
  41. package/dist/cli/upgrade-instructions.js.map +1 -0
  42. package/dist/cli/validate.cjs +12 -1
  43. package/dist/cli/validate.cjs.map +1 -1
  44. package/dist/cli/validate.js +2 -2
  45. package/dist/{edge-entry-BSKA1l_0.d.ts → edge-entry-AWO70gje.d.ts} +1 -1
  46. package/dist/{edge-entry-DyMWa6JK.d.cts → edge-entry-DaeG7D7S.d.cts} +1 -1
  47. package/dist/edge-entry.cjs +43 -2
  48. package/dist/edge-entry.cjs.map +1 -1
  49. package/dist/edge-entry.d.cts +2 -2
  50. package/dist/edge-entry.d.ts +2 -2
  51. package/dist/edge-entry.js +2 -2
  52. package/dist/index.cjs +594 -64
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/{index.d-Bo_Rxund.d.cts → index.d-Dq33YwFT.d.cts} +91 -1
  55. package/dist/{index.d-Bo_Rxund.d.ts → index.d-Dq33YwFT.d.ts} +91 -1
  56. package/dist/index.d.cts +91 -431
  57. package/dist/index.d.ts +91 -431
  58. package/dist/index.js +291 -6
  59. package/dist/index.js.map +1 -1
  60. package/dist/node-entry.cjs +282 -71
  61. package/dist/node-entry.cjs.map +1 -1
  62. package/dist/node-entry.d.cts +3 -3
  63. package/dist/node-entry.d.ts +3 -3
  64. package/dist/node-entry.js +8 -7
  65. package/dist/node-subpath.cjs +12 -1
  66. package/dist/node-subpath.cjs.map +1 -1
  67. package/dist/node-subpath.d.cts +1 -1
  68. package/dist/node-subpath.d.ts +1 -1
  69. package/dist/node-subpath.js +3 -3
  70. package/dist/{source-map-uploader-FSTHCYDR.js → source-map-uploader-PB3M4PPP.js} +3 -3
  71. package/package.json +1 -1
  72. package/dist/chunk-JH7EGRC5.js.map +0 -1
  73. package/dist/chunk-JZ475QRH.js.map +0 -1
  74. package/dist/chunk-LJMZXJ45.js.map +0 -1
  75. package/dist/chunk-XS5W3SPL.js.map +0 -1
  76. /package/dist/{chunk-GYTCZSAV.js.map → chunk-MFYOQOD7.js.map} +0 -0
  77. /package/dist/{chunk-4WUHMLMM.js.map → chunk-MMKFFF2L.js.map} +0 -0
  78. /package/dist/{chunk-FKBCEOJ5.js.map → chunk-Q42BY5BA.js.map} +0 -0
  79. /package/dist/{chunk-DBKG6SRI.js.map → chunk-QU26IKIJ.js.map} +0 -0
  80. /package/dist/{chunk-ADUD4PEK.js.map → chunk-TANUWTFO.js.map} +0 -0
  81. /package/dist/{source-map-uploader-FSTHCYDR.js.map → source-map-uploader-PB3M4PPP.js.map} +0 -0
package/README.md CHANGED
@@ -98,6 +98,62 @@ total cap). HTTP 4xx/5xx and malformed responses are surfaced
98
98
  immediately. Set `GLASSTRACE_SKIP_INIT_VERIFY=1` to skip verification
99
99
  for offline installs.
100
100
 
101
+ ## Refreshing agent instruction guidance
102
+
103
+ `glasstrace init` and `glasstrace mcp add` write a managed Glasstrace
104
+ MCP section into your project's agent instruction file (CLAUDE.md /
105
+ codex.md / .cursorrules). The section opens with a cost-aware
106
+ cross-tool decision paragraph telling your AI agent **when** Glasstrace
107
+ MCP is worth calling and **which** tool is the cheapest first call for
108
+ each symptom class.
109
+
110
+ The managed section's start marker carries an SDK version stamp, e.g.
111
+ `<!-- glasstrace:mcp:start v=1.5.0 -->`. When you upgrade
112
+ `@glasstrace/sdk`, run:
113
+
114
+ ```bash
115
+ npx glasstrace upgrade-instructions
116
+ ```
117
+
118
+ The command refreshes every detected agent instruction file in one
119
+ run. Files outside the markers are untouched; files without a
120
+ Glasstrace managed section are left alone. The command is idempotent
121
+ — re-running produces byte-for-byte identical output.
122
+
123
+ `npx glasstrace mcp add` performs the same managed-section refresh
124
+ when run with `--force` (or against a project whose marker file has
125
+ shifted credentials), so either command is a valid upgrade path.
126
+
127
+ ### Stale-section warning at SDK init
128
+
129
+ When the running SDK detects that an agent instruction file's stamp
130
+ is strictly older than the running version, it writes a single
131
+ stderr line at `registerGlasstrace()` time pointing at the upgrade
132
+ command. Constraints:
133
+
134
+ - Stderr only, never stdout. Tracing behaviour is unaffected.
135
+ - At most one warning per process boot, even when multiple
136
+ `registerGlasstrace()` calls happen (test runners, hot reload).
137
+ - Node-only — no-op on Edge / browser runtimes. Never throws.
138
+ - Does not mutate any file at runtime; the user opts in by running
139
+ the upgrade command.
140
+ - Suppressed by setting one of:
141
+
142
+ ```bash
143
+ GLASSTRACE_DISABLE_UPGRADE_NOTICE=1
144
+ GLASSTRACE_DISABLE_UPGRADE_NOTICE=true
145
+ GLASSTRACE_DISABLE_UPGRADE_NOTICE=yes
146
+ ```
147
+
148
+ (case-insensitive). Any other value, including unset, leaves the
149
+ warning enabled.
150
+
151
+ Legacy unstamped managed sections (written by `@glasstrace/sdk`
152
+ versions before 1.5.0) trigger no warning — those projects receive
153
+ the refreshed text on their next `mcp add` or
154
+ `upgrade-instructions` run, and the upgrade replaces the legacy
155
+ block in place rather than appending a duplicate.
156
+
101
157
  ## Server Action detection (Next.js)
102
158
 
103
159
  Next.js does not emit a dedicated OTel span for Server Actions. The SDK
@@ -293,6 +349,74 @@ body data. If your account enables the flag but a span never carries
293
349
  the internal attribute (no adapter set it), the public attribute is
294
350
  still absent. The default is "off, twice".
295
351
 
352
+ ## Capturing side-effect evidence
353
+
354
+ When debugging a bug whose root cause is which side-effect operation
355
+ ran with which non-sensitive semantic value — "the cancellation email
356
+ used the wrong locale", "the wrong invite role was sent" — the agent
357
+ needs to know template key, role, locale, timezone, status, and phase,
358
+ but never the recipient, the rendered subject or body, the calendar
359
+ link, or any token that flowed through the operation. The SDK can
360
+ record allowlisted side-effect evidence on the active trace via
361
+ `recordSideEffect()`, gated by the `sideEffectEvidence` capture-config
362
+ flag.
363
+
364
+ What the SDK captures: a compact, normalized operation label, the
365
+ operation kind (`email`, `calendar_link`, `webhook`, `external_api`,
366
+ `queue`, `after_callback`), an optional lifecycle status
367
+ (`scheduled`, `started`, `succeeded`, `failed`, `unknown`), an
368
+ optional execution phase (`request`, `post_response`, `background`,
369
+ `unknown`), and a small set of allowlisted semantic fields:
370
+ `templateKey`, `providerOperation`, `role`, `locale`, `timezone`,
371
+ `status`, `phase`. Each value is bounded to compact tokens — IANA
372
+ timezones, BCP-47 locales, identifier-shaped enum tokens. The
373
+ per-trace operation budget is five.
374
+
375
+ What the SDK does not capture: recipient email addresses, sender or
376
+ recipient names, rendered email subjects or bodies, calendar links,
377
+ invite links, any URL with a query string or fragment, any
378
+ `Authorization`/`Cookie`/bearer-shaped value, any
379
+ password/token/api_key key-value pair, any UUID, any Glasstrace API
380
+ key, any free-form prose, and any structured payload. Values matching
381
+ those shapes are silently dropped and replaced with an integer count
382
+ under the matching omission attribute. The dropped value never
383
+ appears on the span, in any log line, or in any export.
384
+
385
+ Behavior-neutrality: `recordSideEffect()` is an observer. It does
386
+ not send, retry, duplicate, schedule, or delay any side effect. It
387
+ never throws. If no recording span is active, the call is a silent
388
+ no-op.
389
+
390
+ Account opt-in: the capture is gated on the `sideEffectEvidence` flag
391
+ in your account's capture configuration, which the SDK fetches at
392
+ init time. The flag defaults to `false`, so no side-effect attribute
393
+ is ever attached unless your account has explicitly enabled it.
394
+
395
+ ```ts
396
+ import { recordSideEffect } from "@glasstrace/sdk";
397
+
398
+ await mailer.send({ to: recipient, template: "EventCanceledEmail" });
399
+ recordSideEffect({
400
+ kind: "email",
401
+ operation: "email.send",
402
+ status: "succeeded",
403
+ phase: "request",
404
+ fields: {
405
+ templateKey: "EventCanceledEmail",
406
+ role: "invitee",
407
+ locale: "en-US",
408
+ timezone: "Europe/Paris",
409
+ },
410
+ });
411
+ ```
412
+
413
+ The SDK guard protects only callers of `recordSideEffect()`; user
414
+ code that bypasses the SDK and writes directly to the OTel span will
415
+ still hit the wire as-is and is filtered by the glasstrace-product
416
+ ingestion service before persistence. This is intentional
417
+ defense-in-depth: the SDK is the first gate; the product receiver
418
+ is the second.
419
+
296
420
  ## Source maps
297
421
 
298
422
  Glasstrace uploads server-side source maps at build time and resolves
@@ -0,0 +1,455 @@
1
+ import { G as GlasstraceEnvVars, f as GlasstraceOptions, A as AnonApiKey, g as SdkInitResponse, C as CaptureConfig, h as SdkHealthReport, I as ImportGraphPayload, i as SdkDiagnosticCode } from './index.d-Dq33YwFT.cjs';
2
+ import { ReadableSpan } from './export/ReadableSpan';
3
+ import { SpanExporter } from './export/SpanExporter';
4
+ import { ExportResult } from './ExportResult';
5
+ import { a as SessionManager } from './edge-entry-DaeG7D7S.cjs';
6
+ import { SpanProcessor } from './SpanProcessor';
7
+
8
+ /**
9
+ * Resolved configuration after merging explicit options with environment variables.
10
+ */
11
+ interface ResolvedConfig {
12
+ apiKey: string | undefined;
13
+ endpoint: string;
14
+ forceEnable: boolean;
15
+ verbose: boolean;
16
+ environment: string | undefined;
17
+ coverageMapEnabled: boolean;
18
+ nodeEnv: string | undefined;
19
+ vercelEnv: string | undefined;
20
+ }
21
+ /**
22
+ * Reads all recognized Glasstrace environment variables from process.env.
23
+ * Returns undefined for any variable not set. Never throws.
24
+ */
25
+ declare function readEnvVars(): GlasstraceEnvVars;
26
+ /**
27
+ * Merges explicit GlasstraceOptions with environment variables.
28
+ * Explicit options take precedence over environment variables.
29
+ */
30
+ declare function resolveConfig(options?: GlasstraceOptions): ResolvedConfig;
31
+ /**
32
+ * Returns true when the SDK should be inactive (production detected without force-enable).
33
+ * Logic order:
34
+ * 1. forceEnable === true → return false (override)
35
+ * 2. NODE_ENV === 'production' → return true
36
+ * 3. VERCEL_ENV === 'production' → return true
37
+ * 4. Otherwise → return false
38
+ */
39
+ declare function isProductionDisabled(config: ResolvedConfig): boolean;
40
+ /**
41
+ * Returns true when no API key is configured (anonymous mode).
42
+ * Treats undefined, empty string, whitespace-only, and gt_anon_* keys as anonymous.
43
+ */
44
+ declare function isAnonymousMode(config: ResolvedConfig): boolean;
45
+
46
+ /**
47
+ * The set of recognized fetch target categories.
48
+ */
49
+ type FetchTarget = "supabase" | "stripe" | "internal" | "unknown";
50
+ /**
51
+ * Classifies an outbound fetch target URL into a known category.
52
+ * Classification is case-insensitive and based on the URL hostname.
53
+ * Uses dot-boundary matching to avoid false positives (e.g. evilstripe.com).
54
+ *
55
+ * Returns one of: 'supabase', 'stripe', 'internal', or 'unknown'.
56
+ */
57
+ declare function classifyFetchTarget(url: string): FetchTarget;
58
+
59
+ /**
60
+ * Reads an existing anonymous key from the filesystem.
61
+ * Returns the key if valid, or null if:
62
+ * - The file does not exist
63
+ * - The file content is invalid
64
+ * - An I/O error occurs
65
+ * - `node:fs` is unavailable (non-Node environment)
66
+ */
67
+ declare function readAnonKey(projectRoot?: string): Promise<AnonApiKey | null>;
68
+ /**
69
+ * Gets an existing anonymous key from the filesystem, or creates a new one.
70
+ *
71
+ * - If file exists and contains a valid key, returns it
72
+ * - If file does not exist or content is invalid, generates a new key via createAnonApiKey()
73
+ * - Writes the new key to `.glasstrace/anon_key`, creating the directory if needed
74
+ * - On file write failure: logs a warning, caches an ephemeral in-memory key so
75
+ * repeated calls in the same process return the same key
76
+ * - In non-Node environments: returns an ephemeral in-memory key
77
+ */
78
+ declare function getOrCreateAnonKey(projectRoot?: string): Promise<AnonApiKey>;
79
+
80
+ /**
81
+ * Reads and validates a cached config file from `.glasstrace/config`.
82
+ * Returns the parsed `SdkInitResponse` or `null` on any failure,
83
+ * including when `node:fs` is unavailable (non-Node environments).
84
+ */
85
+ declare function loadCachedConfig(projectRoot?: string): SdkInitResponse | null;
86
+ /**
87
+ * Persists the init response to `.glasstrace/config` using the SDK 2.0
88
+ * atomic-write protocol (`tmp + fsync(tmp) + rename + fsync(parent)`).
89
+ * Silently skipped when `node:fs` is unavailable (non-Node environments).
90
+ * On I/O failure, logs a warning.
91
+ *
92
+ * Atomicity: the payload is written to `.glasstrace/config.tmp`, fsynced
93
+ * to durable storage, then renamed into place; the parent directory is
94
+ * fsynced last so the rename survives an immediate crash. `rename` is
95
+ * atomic on POSIX filesystems, so readers either see the previous valid
96
+ * config or the new valid config — never a truncated or partially-written
97
+ * file (DISC-1247 Scenario 5). If any step fails, the temp file is
98
+ * cleaned up on a best-effort basis.
99
+ */
100
+ declare function saveCachedConfig(response: SdkInitResponse, projectRoot?: string): Promise<void>;
101
+ /**
102
+ * Sends a POST request to `/v1/sdk/init`.
103
+ * Validates the response against `SdkInitResponseSchema`.
104
+ *
105
+ * Uses `node:https` via {@link httpsPostJson} rather than the global
106
+ * `fetch` because Next.js 16 patches `fetch` for caching/revalidation
107
+ * and can cause the init request to silently hang (DISC-493 Issue 3).
108
+ * Retries transport-level failures (DNS, TCP, TLS) twice with 500ms +
109
+ * 1500ms backoff, capped at a 20-second total deadline. Server responses
110
+ * (HTTP 4xx/5xx) are never retried and are surfaced immediately.
111
+ */
112
+ declare function sendInitRequest(config: ResolvedConfig, anonKey: AnonApiKey | null, sdkVersion: string, importGraph?: ImportGraphPayload, healthReport?: SdkHealthReport, diagnostics?: Array<{
113
+ code: SdkDiagnosticCode;
114
+ message: string;
115
+ timestamp: number;
116
+ }>, signal?: AbortSignal): Promise<SdkInitResponse>;
117
+ /**
118
+ * Result returned by {@link performInit} when the backend reports an
119
+ * account claim transition. `null` means no claim was present.
120
+ */
121
+ interface InitClaimResult {
122
+ claimResult: NonNullable<SdkInitResponse["claimResult"]>;
123
+ }
124
+ /**
125
+ * Orchestrates the full init flow: send request, update config, cache result.
126
+ * This function MUST NOT throw.
127
+ *
128
+ * Returns the claim result when the backend reports an account claim
129
+ * transition, or `null` when no claim result is available (including
130
+ * when init is skipped due to rate-limit backoff, missing API key,
131
+ * or request failure). Callers that do not need claim information
132
+ * can safely ignore the return value.
133
+ */
134
+ declare function performInit(config: ResolvedConfig, anonKey: AnonApiKey | null, sdkVersion: string, healthReport?: SdkHealthReport | null): Promise<InitClaimResult | null>;
135
+ /**
136
+ * Returns the current capture config from the three-tier fallback chain:
137
+ * 1. In-memory config from latest init response
138
+ * 2. File cache (read at most once per process lifetime)
139
+ * 3. DEFAULT_CAPTURE_CONFIG
140
+ *
141
+ * The disk read is cached via `configCacheChecked` to avoid repeated
142
+ * synchronous I/O on the hot path (called by GlasstraceExporter on
143
+ * every span export batch).
144
+ */
145
+ declare function getActiveConfig(): CaptureConfig;
146
+ /**
147
+ * Returns the `linkedAccountId` from the current in-memory init response,
148
+ * or `undefined` if no init response is available or no account is linked.
149
+ *
150
+ * Used by the discovery endpoint to determine whether `claimed: true`
151
+ * should be included in the response.
152
+ */
153
+ declare function getLinkedAccountId(): string | undefined;
154
+
155
+ /**
156
+ * Options for constructing a {@link GlasstraceExporter}.
157
+ */
158
+ interface GlasstraceExporterOptions {
159
+ getApiKey: () => string;
160
+ sessionManager: SessionManager;
161
+ getConfig: () => CaptureConfig;
162
+ environment: string | undefined;
163
+ endpointUrl: string;
164
+ createDelegate: ((url: string, headers: Record<string, string>) => SpanExporter) | null;
165
+ /** When true, logs diagnostic details about enrichment decisions via sdkLog. */
166
+ verbose?: boolean;
167
+ }
168
+ /**
169
+ * A SpanExporter that enriches spans with glasstrace.* attributes at export
170
+ * time, then delegates to a real OTLP exporter.
171
+ *
172
+ * This design resolves three issues:
173
+ * - Spans emitted before the API key resolves are buffered (not dropped)
174
+ * and flushed once the key is available.
175
+ * - Enrichment happens in the exporter (not onEnding), so it works
176
+ * on Vercel where CompositeSpanProcessor does not forward onEnding().
177
+ * - Session ID is computed at export time using the resolved API key,
178
+ * not the "pending" placeholder.
179
+ */
180
+ declare class GlasstraceExporter implements SpanExporter {
181
+ private readonly getApiKey;
182
+ private readonly sessionManager;
183
+ private readonly getConfig;
184
+ private readonly environment;
185
+ private readonly endpointUrl;
186
+ private readonly createDelegateFn;
187
+ private readonly verbose;
188
+ private delegate;
189
+ private delegateKey;
190
+ private pendingBatches;
191
+ private pendingSpanCount;
192
+ private overflowLogged;
193
+ constructor(options: GlasstraceExporterOptions);
194
+ export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
195
+ /**
196
+ * Called when the API key transitions from "pending" to a resolved value.
197
+ * Creates the delegate exporter and flushes all buffered spans.
198
+ */
199
+ notifyKeyResolved(): void;
200
+ shutdown(): Promise<void>;
201
+ /**
202
+ * Flushes any pending buffered spans (if the API key has resolved) and
203
+ * delegates to the underlying exporter's forceFlush to drain its queue.
204
+ */
205
+ forceFlush(): Promise<void>;
206
+ /**
207
+ * Enriches a ReadableSpan with all glasstrace.* attributes.
208
+ * Returns a new ReadableSpan wrapper; the original span is not mutated.
209
+ *
210
+ * Only {@link SessionManager.getSessionId} is individually guarded because
211
+ * it calls into crypto and schema validation — a session ID failure should
212
+ * not prevent the rest of enrichment. The other helper calls
213
+ * ({@link deriveErrorCategory}, {@link deriveOrmProvider},
214
+ * {@link classifyFetchTarget}) are pure functions on typed string inputs
215
+ * and rely on the outer catch for any unexpected failure.
216
+ *
217
+ * On total failure, returns the original span unchanged.
218
+ */
219
+ private enrichSpan;
220
+ /**
221
+ * Lazily creates the delegate OTLP exporter once the API key is resolved.
222
+ * Recreates the delegate if the key has changed (e.g., after key rotation)
223
+ * so the Authorization header stays current.
224
+ */
225
+ private ensureDelegate;
226
+ /**
227
+ * Buffers raw (unenriched) spans while the API key is pending.
228
+ * Evicts oldest batches if the buffer exceeds MAX_PENDING_SPANS.
229
+ * Re-checks the key after buffering to close the race window where
230
+ * the key resolves between the caller's check and this buffer call.
231
+ */
232
+ private bufferSpans;
233
+ /**
234
+ * Flushes all buffered spans through the delegate exporter.
235
+ * Enriches spans at flush time (not buffer time) so that session IDs
236
+ * are computed with the resolved API key instead of the "pending" sentinel.
237
+ */
238
+ private flushPending;
239
+ }
240
+
241
+ /**
242
+ * The primary SDK entry point called by developers in their `instrumentation.ts`.
243
+ * Orchestrates OTel setup, span processor, init client, anon key, and discovery endpoint.
244
+ *
245
+ * This function is synchronous and MUST NOT throw. The developer's server is never blocked.
246
+ * Background work (key resolution, init call) happens via fire-and-forget promises.
247
+ *
248
+ * @param options - Optional SDK configuration. Environment variables are used as fallbacks.
249
+ *
250
+ * @example
251
+ * ```ts
252
+ * // instrumentation.ts
253
+ * import { registerGlasstrace } from "@glasstrace/sdk";
254
+ * registerGlasstrace(); // uses env vars
255
+ * ```
256
+ */
257
+ declare function registerGlasstrace(options?: GlasstraceOptions): void;
258
+ /**
259
+ * Returns the registered discovery handler, or null if not registered.
260
+ */
261
+ declare function getDiscoveryHandler(): ((request: Request) => Promise<Response | null>) | null;
262
+
263
+ /**
264
+ * Structural view of Next.js's `NextConfig`. The SDK does not import Next's
265
+ * type directly because Next is not a peer dependency — this wrapper must
266
+ * type-check regardless of which Next.js version the consumer has installed.
267
+ *
268
+ * The constraint is `object` rather than `Record<string, unknown>` because
269
+ * Next's actual `NextConfig` is an interface *without* a string index
270
+ * signature. Requiring `[key: string]: unknown` would fail the assignability
271
+ * check that caused DISC-1256, reported by Next 16 consumers as:
272
+ * > Argument of type 'NextConfig' is not assignable to parameter of type
273
+ * > 'NextConfig'. Index signature for type 'string' is missing in type
274
+ * > 'NextConfig'.
275
+ *
276
+ * `object` accepts every non-primitive value, which is what the wrapper
277
+ * actually handles at runtime (it shallow-copies the input and reads a few
278
+ * known properties defensively). Combined with the generic signature on
279
+ * `withGlasstraceConfig`, callers preserve their exact config subtype.
280
+ */
281
+ type NextConfig = object;
282
+ /**
283
+ * Wraps the developer's Next.js config to enable source map generation
284
+ * and upload .map files to the ingestion API at build time.
285
+ *
286
+ * The build NEVER fails because of Glasstrace — all errors are caught
287
+ * and logged as warnings.
288
+ *
289
+ * ## What the wrapper configures for you
290
+ *
291
+ * - `experimental.serverSourceMaps: true` — enables server-side source maps
292
+ * so Glasstrace can resolve stack traces back to your source.
293
+ * - `serverExternalPackages: ["@glasstrace/sdk"]` — tells Next to load the
294
+ * SDK via Node's `require()` at runtime instead of bundling it through
295
+ * webpack or Turbopack on the RSC / Route Handler paths. This is the same
296
+ * pattern Prisma, `@vercel/otel`, Sentry, `sharp`, and `bcrypt` ship with.
297
+ * - A webpack `externals` entry that marks every Node.js built-in import
298
+ * (both `node:*` and bare forms like `zlib` or `stream`) as a runtime
299
+ * `commonjs` require. `serverExternalPackages` does not apply to the
300
+ * instrumentation path under `next dev --webpack`
301
+ * (vercel/next.js#58003, #28774), so any bundled SDK chunk that imports
302
+ * `node:child_process` or the bare `zlib` specifier used by
303
+ * `@opentelemetry/otlp-exporter-base` would otherwise crash with
304
+ * `UnhandledSchemeError` or `Can't resolve 'zlib'`. This entry is the
305
+ * actual DISC-1257 fix for the dev-webpack path. Turbopack is
306
+ * unaffected — it ignores `config.webpack` and resolves Node built-ins
307
+ * natively.
308
+ * - An empty `turbopack: {}` when none is set, so Next 16 does not reject
309
+ * the config for setting `webpack` without a companion `turbopack` key
310
+ * (DISC-1256).
311
+ * - A `webpack` hook that collects and uploads `.map` files on client-side
312
+ * production builds.
313
+ *
314
+ * ## Turbopack
315
+ *
316
+ * Next.js 16 made Turbopack the default bundler for `next build`, and Next
317
+ * rejects configs that set `webpack` without also setting `turbopack`. This
318
+ * wrapper therefore seeds an empty `turbopack: {}` when the user has not set
319
+ * one themselves, preserving existing behaviour for explicit Turbopack configs.
320
+ *
321
+ * **Source-map upload is currently webpack-only.** Under Turbopack the build
322
+ * succeeds, but the afterEmit hook that collects and uploads `.map` files does
323
+ * not fire. Run `next build --webpack` to get source-map uploads, or wait for
324
+ * a follow-up release that ports the plugin to Turbopack.
325
+ *
326
+ * @param nextConfig - The developer's existing Next.js configuration object.
327
+ * @returns A new config object with source map generation and upload enabled.
328
+ * The return type mirrors the input type so that caller-side config
329
+ * properties are preserved. The `object` constraint (rather than
330
+ * `Record<string, unknown>`) is what makes the wrapper accept Next's
331
+ * real `NextConfig` interface (DISC-1256).
332
+ */
333
+ declare function withGlasstraceConfig<T extends NextConfig>(nextConfig: T): T;
334
+
335
+ /**
336
+ * Returns true when the SDK is in ACTIVE or ACTIVE_DEGRADED state.
337
+ */
338
+ declare function isReady(): boolean;
339
+ /**
340
+ * Resolves when the SDK reaches ACTIVE or ACTIVE_DEGRADED.
341
+ * Rejects on PRODUCTION_DISABLED, REGISTRATION_FAILED, or timeout.
342
+ *
343
+ * Checks current state synchronously first — resolves/rejects immediately
344
+ * if the SDK has already reached a terminal or ready state.
345
+ */
346
+ declare function waitForReady(timeoutMs?: number): Promise<void>;
347
+ /**
348
+ * Simplified public state query for external consumers.
349
+ * Hides implementation details like coexistence scenarios.
350
+ *
351
+ * The returned `tracing` field is the canonical user-observable signal
352
+ * for OTel coexistence outcomes:
353
+ *
354
+ * - `"active"` — the SDK owns the OTel provider and is exporting spans.
355
+ * - `"coexistence"` — another OTel provider was detected and the SDK
356
+ * either auto-attached its span processor or found one already
357
+ * present. Spans are exported through the existing pipeline.
358
+ * - `"degraded"` — the SDK is exporting but the core lifecycle entered
359
+ * `ACTIVE_DEGRADED` (e.g., a non-fatal export failure).
360
+ * - `"not-configured"` — the SDK could not configure tracing. Covers
361
+ * `OtelState.UNCONFIGURED`, `OtelState.CONFIGURING`, and
362
+ * `OtelState.COEXISTENCE_FAILED` (the DISC-1556 Next 16 production
363
+ * "auto-attach returned null" path). When the value is
364
+ * `"not-configured"` after `registerGlasstrace()` has resolved,
365
+ * spans are NOT reaching the Glasstrace exporter and the manual
366
+ * `createGlasstraceSpanProcessor()` workaround should be applied.
367
+ * See `runtime-state.json`'s `lastError` field for the structured
368
+ * failure record.
369
+ */
370
+ declare function getStatus(): {
371
+ ready: boolean;
372
+ mode: "anonymous" | "authenticated" | "claiming" | "disabled";
373
+ tracing: "active" | "degraded" | "not-configured" | "coexistence";
374
+ };
375
+
376
+ /**
377
+ * OTel Coexistence Public API
378
+ *
379
+ * Provides createGlasstraceSpanProcessor() for developers who want to
380
+ * manually integrate Glasstrace with their existing OTel provider
381
+ * (e.g., Sentry's openTelemetrySpanProcessors config option).
382
+ *
383
+ * Also provides the auto-attach path (tryAutoAttachGlasstraceProcessor)
384
+ * that configureOtel() uses when it detects a pre-registered provider
385
+ * at runtime (Next.js 16 production, Sentry, Datadog, New Relic). Both
386
+ * entry points reuse the same span-processor factory so the manual and
387
+ * automatic paths stay in lockstep.
388
+ *
389
+ * Design: sdk-otel-coexistence.md Sections 3, 4, 5, 6
390
+ */
391
+
392
+ /**
393
+ * Creates a Glasstrace span processor for manual integration with an
394
+ * existing OTel provider.
395
+ *
396
+ * Use this when another tool (e.g., Sentry) owns the OTel provider and
397
+ * you want to add Glasstrace to their processor list:
398
+ *
399
+ * @example
400
+ * ```ts
401
+ * import * as Sentry from "@sentry/nextjs";
402
+ * import { createGlasstraceSpanProcessor } from "@glasstrace/sdk";
403
+ *
404
+ * Sentry.init({
405
+ * dsn: "...",
406
+ * openTelemetrySpanProcessors: [createGlasstraceSpanProcessor()],
407
+ * });
408
+ * ```
409
+ *
410
+ * **Important:** `registerGlasstrace()` is still required even when using
411
+ * this function. The processor handles span transport (enrichment and
412
+ * export). `registerGlasstrace()` handles everything else: init calls,
413
+ * config sync, session management, anonymous key generation, discovery
414
+ * endpoint, and health reporting.
415
+ *
416
+ * @param options - Optional SDK configuration. If omitted, uses the same
417
+ * config as registerGlasstrace() (environment variables).
418
+ * @returns A BatchSpanProcessor wrapping a GlasstraceExporter with the
419
+ * branded Symbol.for('glasstrace.exporter') for coexistence detection.
420
+ */
421
+ declare function createGlasstraceSpanProcessor(options?: GlasstraceOptions): SpanProcessor;
422
+
423
+ /**
424
+ * Manual error capture API.
425
+ *
426
+ * Provides a simple function for developers to manually record errors
427
+ * as span events, independent of the `consoleErrors` config flag.
428
+ */
429
+ /**
430
+ * Records an error as a span event on the currently active OTel span.
431
+ *
432
+ * Works regardless of the `consoleErrors` configuration — this is an
433
+ * explicit, opt-in API for manual error reporting. If no span is active
434
+ * or OTel is not available, the call is silently ignored.
435
+ *
436
+ * On the first captured error, may display a one-time diagnostic nudge
437
+ * to stderr if the MCP connection marker is absent (dev environments only).
438
+ *
439
+ * @param error - The error to capture. Accepts `Error` objects, strings, or any value.
440
+ *
441
+ * @example
442
+ * ```ts
443
+ * import { captureError } from "@glasstrace/sdk";
444
+ *
445
+ * try {
446
+ * await riskyOperation();
447
+ * } catch (err) {
448
+ * captureError(err);
449
+ * // handle error normally...
450
+ * }
451
+ * ```
452
+ */
453
+ declare function captureError(error: unknown): void;
454
+
455
+ export { type FetchTarget as F, GlasstraceExporter as G, type InitClaimResult as I, type ResolvedConfig as R, type GlasstraceExporterOptions as a, classifyFetchTarget as b, captureError as c, createGlasstraceSpanProcessor as d, getDiscoveryHandler as e, getLinkedAccountId as f, getActiveConfig as g, getOrCreateAnonKey as h, getStatus as i, isAnonymousMode as j, isProductionDisabled as k, isReady as l, loadCachedConfig as m, readEnvVars as n, registerGlasstrace as o, performInit as p, resolveConfig as q, readAnonKey as r, saveCachedConfig as s, sendInitRequest as t, withGlasstraceConfig as u, waitForReady as w };