@glasstrace/sdk 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +78 -1
  2. package/dist/{chunk-DIM4JRXM.js → chunk-2M57EO6U.js} +2 -2
  3. package/dist/{chunk-P22UQ2OJ.js → chunk-3LILTM3T.js} +1 -1
  4. package/dist/chunk-3LILTM3T.js.map +1 -0
  5. package/dist/{chunk-MXDZHFJQ.js → chunk-C567H5EQ.js} +2 -2
  6. package/dist/{chunk-7SZQN6IU.js → chunk-NB7GJE4S.js} +2 -2
  7. package/dist/chunk-NB7GJE4S.js.map +1 -0
  8. package/dist/{chunk-ZRDQ6ZKI.js → chunk-UJ2JC7PZ.js} +92 -473
  9. package/dist/chunk-UJ2JC7PZ.js.map +1 -0
  10. package/dist/{chunk-Y26HJUPD.js → chunk-Z35HKVSO.js} +135 -8
  11. package/dist/chunk-Z35HKVSO.js.map +1 -0
  12. package/dist/cli/init.cjs +463 -440
  13. package/dist/cli/init.cjs.map +1 -1
  14. package/dist/cli/init.js +434 -63
  15. package/dist/cli/init.js.map +1 -1
  16. package/dist/cli/mcp-add.cjs +14 -2
  17. package/dist/cli/mcp-add.cjs.map +1 -1
  18. package/dist/cli/mcp-add.js +17 -5
  19. package/dist/cli/mcp-add.js.map +1 -1
  20. package/dist/cli/status.cjs.map +1 -1
  21. package/dist/cli/status.js +1 -3
  22. package/dist/cli/status.js.map +1 -1
  23. package/dist/cli/uninit.cjs +3 -3
  24. package/dist/cli/uninit.cjs.map +1 -1
  25. package/dist/cli/uninit.js +3 -3
  26. package/dist/cli/validate.cjs +14162 -2
  27. package/dist/cli/validate.cjs.map +1 -1
  28. package/dist/cli/validate.d.cts +7 -3
  29. package/dist/cli/validate.d.ts +7 -3
  30. package/dist/cli/validate.js +25 -2
  31. package/dist/cli/validate.js.map +1 -1
  32. package/dist/index.cjs +134 -5
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.js +3 -3
  35. package/dist/{monorepo-GSL6JD3G.js → monorepo-PFVNPQ6X.js} +3 -5
  36. package/dist/node-entry.cjs +134 -5
  37. package/dist/node-entry.cjs.map +1 -1
  38. package/dist/node-entry.js +3 -3
  39. package/package.json +1 -1
  40. package/dist/chunk-7SZQN6IU.js.map +0 -1
  41. package/dist/chunk-P22UQ2OJ.js.map +0 -1
  42. package/dist/chunk-Y26HJUPD.js.map +0 -1
  43. package/dist/chunk-ZRDQ6ZKI.js.map +0 -1
  44. /package/dist/{chunk-DIM4JRXM.js.map → chunk-2M57EO6U.js.map} +0 -0
  45. /package/dist/{chunk-MXDZHFJQ.js.map → chunk-C567H5EQ.js.map} +0 -0
  46. /package/dist/{monorepo-GSL6JD3G.js.map → monorepo-PFVNPQ6X.js.map} +0 -0
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  registerGlasstrace,
13
13
  waitForReady,
14
14
  withGlasstraceConfig
15
- } from "./chunk-Y26HJUPD.js";
15
+ } from "./chunk-Z35HKVSO.js";
16
16
  import {
17
17
  GlasstraceSpanProcessor,
18
18
  SdkError,
@@ -27,7 +27,7 @@ import {
27
27
  performInit,
28
28
  saveCachedConfig,
29
29
  sendInitRequest
30
- } from "./chunk-MXDZHFJQ.js";
30
+ } from "./chunk-C567H5EQ.js";
31
31
  import {
32
32
  isAnonymousMode,
33
33
  isProductionDisabled,
@@ -37,7 +37,7 @@ import {
37
37
  import {
38
38
  getOrCreateAnonKey,
39
39
  readAnonKey
40
- } from "./chunk-P22UQ2OJ.js";
40
+ } from "./chunk-3LILTM3T.js";
41
41
  import {
42
42
  deriveSessionId
43
43
  } from "./chunk-X5MAXP5T.js";
@@ -3,10 +3,8 @@ import {
3
3
  isMonorepoRoot,
4
4
  parsePnpmWorkspaceYaml,
5
5
  resolveProjectRoot
6
- } from "./chunk-DIM4JRXM.js";
7
- import "./chunk-7SZQN6IU.js";
8
- import "./chunk-P22UQ2OJ.js";
9
- import "./chunk-X5MAXP5T.js";
6
+ } from "./chunk-2M57EO6U.js";
7
+ import "./chunk-NB7GJE4S.js";
10
8
  import "./chunk-NSBPE2FW.js";
11
9
  export {
12
10
  findNextJsApps,
@@ -14,4 +12,4 @@ export {
14
12
  parsePnpmWorkspaceYaml,
15
13
  resolveProjectRoot
16
14
  };
17
- //# sourceMappingURL=monorepo-GSL6JD3G.js.map
15
+ //# sourceMappingURL=monorepo-PFVNPQ6X.js.map
@@ -18109,6 +18109,128 @@ init_esm();
18109
18109
  init_dist();
18110
18110
  init_console_capture();
18111
18111
  init_error_nudge();
18112
+
18113
+ // src/error-response-body.ts
18114
+ var ERROR_RESPONSE_BODY_MAX_BYTES = 4096;
18115
+ var ERROR_RESPONSE_BODY_TRUNCATION_MARKER = "...[truncated]";
18116
+ var REDACTED = "[REDACTED]";
18117
+ var ERROR_STATUS_MIN = 400;
18118
+ var ERROR_STATUS_MAX = 599;
18119
+ function isHttpErrorStatus(status) {
18120
+ let numeric;
18121
+ if (typeof status === "number") {
18122
+ numeric = status;
18123
+ } else if (typeof status === "string" && status.length > 0) {
18124
+ numeric = Number(status);
18125
+ } else {
18126
+ return false;
18127
+ }
18128
+ if (!Number.isFinite(numeric)) return false;
18129
+ return numeric >= ERROR_STATUS_MIN && numeric <= ERROR_STATUS_MAX;
18130
+ }
18131
+ var REDACTION_PATTERNS = [
18132
+ // Order matters: redact specific token shapes BEFORE the generic
18133
+ // key=value catcher so a literal `Bearer eyJ…` collapses into a single
18134
+ // [REDACTED] and the JWT regex does not separately match the suffix.
18135
+ {
18136
+ name: "bearer",
18137
+ // Case-insensitive on the scheme: HTTP frameworks and proxies
18138
+ // round-trip the auth scheme with inconsistent casing
18139
+ // (`Bearer`, `bearer`, `BEARER`), and a real token leaks just as
18140
+ // badly under any of them.
18141
+ pattern: /\bBearer\s+[A-Za-z0-9._\-+/=]+/gi
18142
+ },
18143
+ {
18144
+ name: "jwt",
18145
+ // Three base64url segments separated by dots. Real JWTs encode at
18146
+ // minimum a small JSON header in the first segment, which alone is
18147
+ // typically ≥10 chars after base64url; a 16-char floor avoids false
18148
+ // positives on dotted text like a stack-trace frame
18149
+ // (`react.dom.server`) while still catching every real JWT we have
18150
+ // seen in the wild. Anchored with word boundaries on both sides so
18151
+ // a 3-dot semantic version like "next@15.4.1.2" does not match.
18152
+ pattern: /\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g
18153
+ },
18154
+ {
18155
+ name: "glasstrace-api-key",
18156
+ // gt_dev_* and gt_anon_* keys are >=24 chars of [A-Za-z0-9].
18157
+ pattern: /\bgt_(?:dev|anon)_[A-Za-z0-9]{16,}\b/g
18158
+ },
18159
+ {
18160
+ name: "aws-access-key",
18161
+ // 20-char prefix-fixed identifier.
18162
+ pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g
18163
+ },
18164
+ {
18165
+ name: "key-value-secret-quoted",
18166
+ // Quoted-string variant: (key) [:=] "<value>". The value runs to
18167
+ // the next unescaped closing quote so a multi-word secret like
18168
+ // `password="my secret phrase"` is fully consumed instead of
18169
+ // splitting at the first space and leaving the tail visible.
18170
+ // The leading `(?<![A-Za-z0-9_])` prevents matching inside
18171
+ // identifiers like `passwordless`. The trailing `"?` after the
18172
+ // keyword absorbs the closing quote in JSON-style `"apikey":
18173
+ // "value"` so the colon is still seen as the separator.
18174
+ pattern: /(?<![A-Za-z0-9_])(?:api[_-]?key|apikey|secret|password|token)"?\s*[:=]\s*"(?:[^"\\]|\\.)*"/gi
18175
+ },
18176
+ {
18177
+ name: "key-value-secret-bare",
18178
+ // Unquoted variant: (key) [:=] <bare-value>. The bare value
18179
+ // capture stops at common JSON/text delimiters so we redact only
18180
+ // the value, not surrounding structure. Listed AFTER the quoted
18181
+ // variant so a quoted value's surrounding `"` are consumed by
18182
+ // the first pattern and we never fall through here for a quoted
18183
+ // secret.
18184
+ pattern: /(?<![A-Za-z0-9_])(?:api[_-]?key|apikey|secret|password|token)"?\s*[:=]\s*[^\s,;}\]"]+/gi
18185
+ }
18186
+ ];
18187
+ function sanitizeErrorResponseBody(body) {
18188
+ let out = body;
18189
+ for (const { pattern } of REDACTION_PATTERNS) {
18190
+ out = out.replace(pattern, REDACTED);
18191
+ }
18192
+ return out;
18193
+ }
18194
+ function truncateErrorResponseBody(body) {
18195
+ const encoder = new TextEncoder();
18196
+ const encoded = encoder.encode(body);
18197
+ if (encoded.byteLength <= ERROR_RESPONSE_BODY_MAX_BYTES) {
18198
+ return body;
18199
+ }
18200
+ let cut = ERROR_RESPONSE_BODY_MAX_BYTES;
18201
+ let scan = cut - 1;
18202
+ while (scan >= 0 && (encoded[scan] & 192) === 128) {
18203
+ scan -= 1;
18204
+ }
18205
+ if (scan >= 0) {
18206
+ const leading = encoded[scan];
18207
+ let expected = 1;
18208
+ if ((leading & 128) === 0) {
18209
+ expected = 1;
18210
+ } else if ((leading & 224) === 192) {
18211
+ expected = 2;
18212
+ } else if ((leading & 240) === 224) {
18213
+ expected = 3;
18214
+ } else if ((leading & 248) === 240) {
18215
+ expected = 4;
18216
+ }
18217
+ if (scan + expected > cut) {
18218
+ cut = scan;
18219
+ }
18220
+ }
18221
+ const decoder = new TextDecoder("utf-8", { fatal: false });
18222
+ const sliced = encoded.subarray(0, cut);
18223
+ const decoded = decoder.decode(sliced);
18224
+ return decoded + ERROR_RESPONSE_BODY_TRUNCATION_MARKER;
18225
+ }
18226
+ function prepareErrorResponseBody(body) {
18227
+ if (body.length === 0) return null;
18228
+ if (body.trim().length === 0) return null;
18229
+ const sanitized = sanitizeErrorResponseBody(body);
18230
+ return truncateErrorResponseBody(sanitized);
18231
+ }
18232
+
18233
+ // src/enriching-exporter.ts
18112
18234
  var ATTR2 = GLASSTRACE_ATTRIBUTE_NAMES;
18113
18235
  var API_KEY_PENDING = "pending";
18114
18236
  var MAX_PENDING_SPANS = 1024;
@@ -18336,7 +18458,14 @@ var GlasstraceExporter = class {
18336
18458
  if (this.getConfig().errorResponseBodies) {
18337
18459
  const responseBody = attrs["glasstrace.internal.response_body"];
18338
18460
  if (typeof responseBody === "string") {
18339
- extra[ATTR2.ERROR_RESPONSE_BODY] = responseBody.slice(0, 500);
18461
+ const enrichedStatus = extra[ATTR2.HTTP_STATUS_CODE];
18462
+ const effectiveStatus = typeof enrichedStatus === "number" ? enrichedStatus : statusCode;
18463
+ if (isHttpErrorStatus(effectiveStatus)) {
18464
+ const prepared = prepareErrorResponseBody(responseBody);
18465
+ if (prepared !== null) {
18466
+ extra[ATTR2.ERROR_RESPONSE_BODY] = prepared;
18467
+ }
18468
+ }
18340
18469
  }
18341
18470
  }
18342
18471
  const spanAny = span;
@@ -22202,7 +22331,7 @@ function registerGlasstrace(options) {
22202
22331
  setCoreState(CoreState.REGISTERING);
22203
22332
  startRuntimeStateWriter({
22204
22333
  projectRoot: process.cwd(),
22205
- sdkVersion: "1.1.1"
22334
+ sdkVersion: "1.1.2"
22206
22335
  });
22207
22336
  const config2 = resolveConfig(options);
22208
22337
  if (config2.verbose) {
@@ -22368,8 +22497,8 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
22368
22497
  if (config2.verbose) {
22369
22498
  console.info("[glasstrace] Background init firing.");
22370
22499
  }
22371
- const healthReport = collectHealthReport("1.1.1");
22372
- const initResult = await performInit(config2, anonKeyForInit, "1.1.1", healthReport);
22500
+ const healthReport = collectHealthReport("1.1.2");
22501
+ const initResult = await performInit(config2, anonKeyForInit, "1.1.2", healthReport);
22373
22502
  if (generation !== registrationGeneration) return;
22374
22503
  const currentState = getCoreState();
22375
22504
  if (currentState === CoreState.SHUTTING_DOWN || currentState === CoreState.SHUTDOWN) {
@@ -22392,7 +22521,7 @@ async function backgroundInit(config2, anonKeyForInit, generation) {
22392
22521
  }
22393
22522
  maybeInstallConsoleCapture();
22394
22523
  if (didLastInitSucceed()) {
22395
- startHeartbeat(config2, anonKeyForInit, "1.1.1", generation, (newApiKey, accountId) => {
22524
+ startHeartbeat(config2, anonKeyForInit, "1.1.2", generation, (newApiKey, accountId) => {
22396
22525
  setAuthState(AuthState.CLAIMING);
22397
22526
  emitLifecycleEvent("auth:claim_started", { accountId });
22398
22527
  setResolvedApiKey(newApiKey);