@guidelytech/shared 0.16.0 → 0.17.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.
@@ -14,18 +14,18 @@ function slugify(input) {
14
14
  return input.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "untitled";
15
15
  }
16
16
  var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
17
- function randomId(size = 16) {
17
+ function randomId(size2 = 16) {
18
18
  const g = typeof globalThis !== "undefined" ? globalThis : {};
19
19
  let bytes;
20
20
  if (g.crypto && typeof g.crypto.getRandomValues === "function") {
21
- bytes = new Uint8Array(size);
21
+ bytes = new Uint8Array(size2);
22
22
  g.crypto.getRandomValues(bytes);
23
23
  } else {
24
- bytes = new Uint8Array(size);
25
- for (let i = 0; i < size; i++) bytes[i] = Math.floor(Math.random() * 256);
24
+ bytes = new Uint8Array(size2);
25
+ for (let i = 0; i < size2; i++) bytes[i] = Math.floor(Math.random() * 256);
26
26
  }
27
27
  let out = "";
28
- for (let i = 0; i < size; i++) out += ALPHABET[bytes[i] % ALPHABET.length];
28
+ for (let i = 0; i < size2; i++) out += ALPHABET[bytes[i] % ALPHABET.length];
29
29
  return out;
30
30
  }
31
31
  function isPlainObject(v) {
@@ -428,19 +428,91 @@ function contrastIssues(colors) {
428
428
  return issues;
429
429
  }
430
430
 
431
+ // src/error-detail.ts
432
+ var MAX_EXCEPTION_DETAIL_BYTES = 64 * 1024;
433
+ var MAX_EXCEPTION_DETAIL_RAW_BYTES = 1024 * 1024;
434
+ var MAX_BREADCRUMBS = 100;
435
+ var MAX_EXCEPTION_CHAIN = 20;
436
+ var MAX_DETAIL_FRAMES = 250;
437
+ var MAX_DETAIL_THREADS = 100;
438
+ var MAX_DEBUG_IMAGES = 500;
439
+ var MAX_ERROR_TAGS = 50;
440
+ var size = (v) => {
441
+ try {
442
+ return JSON.stringify(v)?.length ?? 0;
443
+ } catch {
444
+ return Infinity;
445
+ }
446
+ };
447
+ function normalizeTags(tags) {
448
+ const out = {};
449
+ for (const [k, v] of Object.entries(tags ?? {})) {
450
+ if (Object.keys(out).length >= MAX_ERROR_TAGS) break;
451
+ if (!k || v === void 0 || v === null) continue;
452
+ out[k.slice(0, 32)] = String(v).slice(0, 200);
453
+ }
454
+ return out;
455
+ }
456
+ function trimExceptionDetail(detail, max = MAX_EXCEPTION_DETAIL_BYTES) {
457
+ const d = detail;
458
+ if (d.breadcrumbs?.values && d.breadcrumbs.values.length > MAX_BREADCRUMBS) d.breadcrumbs.values = d.breadcrumbs.values.slice(-MAX_BREADCRUMBS);
459
+ if (d.exception?.values && d.exception.values.length > MAX_EXCEPTION_CHAIN) d.exception.values = d.exception.values.slice(-MAX_EXCEPTION_CHAIN);
460
+ if (d.threads?.values && d.threads.values.length > MAX_DETAIL_THREADS) d.threads.values = d.threads.values.slice(0, MAX_DETAIL_THREADS);
461
+ if (d.debug_meta?.images && d.debug_meta.images.length > MAX_DEBUG_IMAGES) d.debug_meta.images = d.debug_meta.images.slice(0, MAX_DEBUG_IMAGES);
462
+ const stacks = () => [...d.exception?.values ?? [], ...d.threads?.values ?? []].map((x) => x.stacktrace).filter((s) => !!s);
463
+ for (const s of stacks()) if (s.frames && s.frames.length > MAX_DETAIL_FRAMES) s.frames = s.frames.slice(-MAX_DETAIL_FRAMES);
464
+ if (size(d) <= max) return d;
465
+ while (d.breadcrumbs?.values.length && size(d) > max) d.breadcrumbs.values = d.breadcrumbs.values.slice(Math.ceil(d.breadcrumbs.values.length / 2));
466
+ if (size(d) <= max) return d;
467
+ for (const s of stacks())
468
+ for (const f of s.frames ?? []) {
469
+ delete f.vars;
470
+ delete f.pre_context;
471
+ delete f.post_context;
472
+ }
473
+ if (size(d) <= max) return d;
474
+ if (d.threads?.values) d.threads.values = d.threads.values.filter((t) => t.crashed || t.current);
475
+ if (size(d) <= max) return d;
476
+ if (d.extra) d.extra = { _trimmed: true };
477
+ if (d.request) delete d.request.data;
478
+ for (const s of stacks()) while (s.frames && s.frames.length > 20 && size(d) > max) s.frames.splice(Math.floor(s.frames.length / 2) - 5, 10);
479
+ if (d.debug_meta?.images && size(d) > max) d.debug_meta.images = d.debug_meta.images.slice(0, 50);
480
+ return d;
481
+ }
482
+ var matches = (patterns, value) => patterns.some((p) => typeof p === "string" ? p !== "" && value.includes(p) : safeTest(p, value));
483
+ function safeTest(re, value) {
484
+ re.lastIndex = 0;
485
+ return re.test(value);
486
+ }
487
+ function errorFilterDrops(e, opts) {
488
+ const message = e.message ?? "";
489
+ if (opts.ignoreErrors?.length && (matches(opts.ignoreErrors, `${e.type || "Error"}: ${message}`) || matches(opts.ignoreErrors, message))) return true;
490
+ if (!e.file) return false;
491
+ if (opts.denyUrls?.length && matches(opts.denyUrls, e.file)) return true;
492
+ if (opts.allowUrls?.length && !matches(opts.allowUrls, e.file)) return true;
493
+ return false;
494
+ }
495
+
431
496
  // src/events-util.ts
432
497
  var SENSITIVE_PROPERTY_PATTERN = /(password|passwd|secret|token|credit|card|cvv|ssn|iban)/i;
433
498
  var MAX_PROPERTY_BYTES = 8 * 1024;
499
+ var MAX_APP_VERSION_LENGTH = 64;
500
+ function normalizeAppVersion(input) {
501
+ if (typeof input !== "string" && typeof input !== "number") return null;
502
+ const printable = Array.from(String(input)).filter((c) => c.charCodeAt(0) > 31 && c.charCodeAt(0) !== 127).join("");
503
+ const v = printable.trim().slice(0, MAX_APP_VERSION_LENGTH).trim();
504
+ return v || null;
505
+ }
434
506
  function sanitizeProperties(props) {
435
507
  if (!props) return {};
436
508
  const out = {};
437
- let size = 0;
509
+ let size2 = 0;
438
510
  for (const [k, v] of Object.entries(props)) {
439
511
  if (SENSITIVE_PROPERTY_PATTERN.test(k)) continue;
440
512
  if (typeof v === "function" || typeof v === "symbol") continue;
441
513
  const str2 = typeof v === "string" ? v : JSON.stringify(v ?? null);
442
- size += k.length + (str2?.length ?? 0);
443
- if (size > MAX_PROPERTY_BYTES) break;
514
+ size2 += k.length + (str2?.length ?? 0);
515
+ if (size2 > MAX_PROPERTY_BYTES) break;
444
516
  out[k.slice(0, 100)] = typeof v === "string" ? v.slice(0, 1e3) : v;
445
517
  }
446
518
  return out;
@@ -450,16 +522,23 @@ function sanitizeProperties(props) {
450
522
  var MAX_STACK_FRAMES = 30;
451
523
  var V8 = /^\s*at (?:(.+?) \()?((?:[a-z][\w+.-]*:)?[^\s()]+?):(\d+):(\d+)\)?\s*$/i;
452
524
  var GECKO = /^\s*(.*?)@(.+?):(\d+):(\d+)\s*$/;
525
+ var HERMES = /^\s*at (?:(.+?) \()?address at ([^\s()]+?):(\d+):(\d+)\)?\s*$/;
526
+ function reactNativeBundleUrl(file) {
527
+ const base = file.replace(/[?#].*$/, "").split("/").pop() || file;
528
+ return `app:///${base}`;
529
+ }
453
530
  function parseStack(stack, max = MAX_STACK_FRAMES) {
454
531
  if (!stack || typeof stack !== "string") return [];
455
532
  const frames = [];
456
533
  for (const raw of stack.split("\n")) {
457
534
  if (frames.length >= max) break;
458
535
  const line = raw.slice(0, 1e3);
459
- const m = V8.exec(line) ?? GECKO.exec(line);
536
+ const hermes = HERMES.exec(line);
537
+ const m = hermes ?? V8.exec(line) ?? GECKO.exec(line);
460
538
  if (!m) continue;
461
539
  const fn = (m[1] || "").trim();
462
- frames.push({ fn: fn ? fn.slice(0, 200) : void 0, file: m[2]?.slice(0, 500), line: Number(m[3]), col: Number(m[4]) });
540
+ const file = hermes ? reactNativeBundleUrl(m[2]) : m[2];
541
+ frames.push({ fn: fn ? fn.slice(0, 200) : void 0, file: file?.slice(0, 500), line: Number(m[3]), col: Number(m[4]) });
463
542
  }
464
543
  return frames;
465
544
  }
@@ -479,13 +558,23 @@ function normalizeFrameFile(file) {
479
558
  var SOURCEMAP_MAX_FILE_BYTES = 100 * 1024 * 1024;
480
559
  var SOURCEMAP_MAX_FILES_PER_UPLOAD = 200;
481
560
  function fingerprintError(input) {
482
- const top = (input.frames ?? []).find((f) => f.file);
483
- const frameKey = input.original ? `src:${input.original.source}:${input.original.name || "?"}` : top ? `${normalizeFrameFile(top.file)}:${top.fn || "?"}` : "";
561
+ const withFile = (input.frames ?? []).filter((f) => f.file || f.module);
562
+ const top = withFile.find((f) => f.inApp === true) ?? withFile.find((f) => f.inApp !== false) ?? withFile[0];
563
+ const frameKey = input.original ? `src:${input.original.source}:${input.original.name || "?"}` : top ? `${top.file ? normalizeFrameFile(top.file) : `mod:${top.module}`}:${top.fn || "?"}` : "";
484
564
  const key = [input.type || "Error", normalizeErrorMessage(input.message || ""), frameKey].join("|");
485
565
  const a = fnv1a(key).toString(16).padStart(8, "0");
486
566
  const b = fnv1a(`guidely:${key}`).toString(16).padStart(8, "0");
487
567
  return a + b;
488
568
  }
569
+ function customFingerprint(parts, computed) {
570
+ if (!Array.isArray(parts) || parts.length === 0) return computed;
571
+ const items = parts.filter((p) => typeof p === "string" || typeof p === "number").map((p) => String(p).slice(0, 200)).slice(0, 20);
572
+ if (items.length === 0) return computed;
573
+ const isDefault = (p) => /^\{\{\s*default\s*\}\}$/i.test(p);
574
+ if (items.every(isDefault)) return computed;
575
+ const key = items.map((p) => isDefault(p) ? computed : p).join("|");
576
+ return fnv1a(key).toString(16).padStart(8, "0") + fnv1a(`guidely:fp:${key}`).toString(16).padStart(8, "0");
577
+ }
489
578
 
490
579
  // src/complaints-limits.ts
491
580
  var COMPLAINT_STATUSES = ["open", "in_review", "resolved"];
@@ -498,6 +587,10 @@ var MAX_COMPLAINT_ANSWER_LENGTH = 500;
498
587
  var MAX_COMPLAINT_ATTACHMENT_BYTES = 2 * 1024 * 1024;
499
588
  var complaintReference = (number) => `CMP-${number}`;
500
589
 
590
+ // src/bug-reports-limits.ts
591
+ var MAX_BUG_REPORT_LENGTH = 4e3;
592
+ var MAX_BUG_REPORT_SCREENSHOT_BYTES = 4 * 1024 * 1024;
593
+
501
594
  // src/agents-limits.ts
502
595
  var AGENT_TURN_ROLES = ["user", "assistant", "tool", "system"];
503
596
  var AGENT_OUTCOMES = ["success", "failure", "escalated", "abandoned"];
@@ -1820,16 +1913,31 @@ export {
1820
1913
  contrastRatio,
1821
1914
  readableTextOn,
1822
1915
  contrastIssues,
1916
+ MAX_EXCEPTION_DETAIL_BYTES,
1917
+ MAX_EXCEPTION_DETAIL_RAW_BYTES,
1918
+ MAX_BREADCRUMBS,
1919
+ MAX_EXCEPTION_CHAIN,
1920
+ MAX_DETAIL_FRAMES,
1921
+ MAX_DETAIL_THREADS,
1922
+ MAX_DEBUG_IMAGES,
1923
+ MAX_ERROR_TAGS,
1924
+ normalizeTags,
1925
+ trimExceptionDetail,
1926
+ errorFilterDrops,
1823
1927
  SENSITIVE_PROPERTY_PATTERN,
1824
1928
  MAX_PROPERTY_BYTES,
1929
+ MAX_APP_VERSION_LENGTH,
1930
+ normalizeAppVersion,
1825
1931
  sanitizeProperties,
1826
1932
  MAX_STACK_FRAMES,
1933
+ reactNativeBundleUrl,
1827
1934
  parseStack,
1828
1935
  normalizeErrorMessage,
1829
1936
  normalizeFrameFile,
1830
1937
  SOURCEMAP_MAX_FILE_BYTES,
1831
1938
  SOURCEMAP_MAX_FILES_PER_UPLOAD,
1832
1939
  fingerprintError,
1940
+ customFingerprint,
1833
1941
  COMPLAINT_STATUSES,
1834
1942
  COMPLAINT_EVENTS,
1835
1943
  COMPLAINT_FIELD_TYPES,
@@ -1839,6 +1947,8 @@ export {
1839
1947
  MAX_COMPLAINT_ANSWER_LENGTH,
1840
1948
  MAX_COMPLAINT_ATTACHMENT_BYTES,
1841
1949
  complaintReference,
1950
+ MAX_BUG_REPORT_LENGTH,
1951
+ MAX_BUG_REPORT_SCREENSHOT_BYTES,
1842
1952
  AGENT_TURN_ROLES,
1843
1953
  AGENT_OUTCOMES,
1844
1954
  AGENT_TOOL_STATUSES,
@@ -1967,4 +2077,4 @@ export {
1967
2077
  sanitizeCustomCss,
1968
2078
  scopeCustomCss
1969
2079
  };
1970
- //# sourceMappingURL=chunk-7PWYIAJI.js.map
2080
+ //# sourceMappingURL=chunk-YL65O3FS.js.map