oh-my-opencode 5.0.0-beta.12 → 5.0.0-beta.13

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 (98) hide show
  1. package/.agents/skills/senpi-qa/SKILL.md +80 -0
  2. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
  3. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
  4. package/dist/cli/index.js +6774 -4320
  5. package/dist/cli-node/index.js +6774 -4320
  6. package/dist/create-hooks.d.ts +1 -0
  7. package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
  8. package/dist/features/btw-side/context-injector.d.ts +15 -0
  9. package/dist/features/btw-side/index.d.ts +8 -0
  10. package/dist/features/btw-side/metadata.d.ts +15 -0
  11. package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
  12. package/dist/features/btw-side/server-session-registry.d.ts +8 -0
  13. package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
  14. package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
  15. package/dist/features/btw-side/tui-controller-types.d.ts +63 -0
  16. package/dist/features/btw-side/tui-controller.d.ts +14 -0
  17. package/dist/features/btw-side/tui-keymap.d.ts +10 -0
  18. package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
  19. package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
  20. package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
  21. package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
  22. package/dist/features/btw-side/tui-side-start.d.ts +9 -0
  23. package/dist/features/btw-side/tui-wiring.d.ts +8 -0
  24. package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
  25. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
  26. package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
  27. package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
  28. package/dist/hooks/runtime-fallback/types.d.ts +3 -1
  29. package/dist/index.js +6502 -3850
  30. package/dist/plugin/event-session-lifecycle.d.ts +1 -0
  31. package/dist/plugin/hooks/create-core-hooks.d.ts +1 -0
  32. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  33. package/dist/plugin/messages-transform.d.ts +1 -0
  34. package/dist/shared/index.d.ts +1 -0
  35. package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
  36. package/dist/tui.js +8092 -6792
  37. package/package.json +24 -23
  38. package/packages/git-bash-mcp/dist/cli.js +5 -1
  39. package/packages/lsp-daemon/dist/cli.js +5 -1
  40. package/packages/lsp-daemon/dist/client.js +5 -1
  41. package/packages/lsp-daemon/dist/index.js +5 -1
  42. package/packages/lsp-tools-mcp/dist/cli.js +5 -1
  43. package/packages/lsp-tools-mcp/dist/mcp.js +5 -1
  44. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  45. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  46. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +5 -1
  48. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +5 -1
  49. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  50. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  51. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  52. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  53. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  54. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  55. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  56. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  57. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  58. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  59. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  60. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  62. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  63. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  64. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  65. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2242 -381
  66. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2247 -386
  67. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  68. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  69. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  70. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  71. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  72. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  73. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  74. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  75. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  76. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  77. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  78. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  79. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  80. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  81. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  82. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  83. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  84. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  85. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  86. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  87. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  88. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  89. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  90. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  91. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  92. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  93. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  94. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  95. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  96. package/packages/omo-codex/plugin/package-lock.json +13 -13
  97. package/packages/omo-codex/plugin/package.json +1 -1
  98. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2307 -401
@@ -338,7 +338,7 @@ function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST)
338
338
  return env["POSTHOG_HOST"]?.trim() || defaultHost;
339
339
  }
340
340
 
341
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
341
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
342
342
  import { dirname, posix, sep } from "node:path";
343
343
  function createModulerModifier() {
344
344
  const getModuleFromFileName = createGetModuleFromFilename();
@@ -374,7 +374,7 @@ function normalizeWindowsPath(path2) {
374
374
  return path2.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
375
375
  }
376
376
 
377
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/featureFlagUtils.mjs
377
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/featureFlagUtils.mjs
378
378
  var normalizeFlagsResponse = (flagsResponse) => {
379
379
  if ("flags" in flagsResponse) {
380
380
  const featureFlags = getFlagValuesFromFlags(flagsResponse.flags);
@@ -444,8 +444,69 @@ var parsePayload = (response) => {
444
444
  return response;
445
445
  }
446
446
  };
447
+ var MINIMAL_FLAG_CALLED_EVENT_CAMPAIGN_PROPERTIES = [
448
+ "utm_source",
449
+ "utm_medium",
450
+ "utm_campaign",
451
+ "utm_content",
452
+ "utm_term",
453
+ "gad_source",
454
+ "mc_cid",
455
+ "gclid",
456
+ "gclsrc",
457
+ "dclid",
458
+ "gbraid",
459
+ "wbraid",
460
+ "fbclid",
461
+ "msclkid",
462
+ "twclid",
463
+ "li_fat_id",
464
+ "igshid",
465
+ "ttclid",
466
+ "rdt_cid",
467
+ "epik",
468
+ "qclid",
469
+ "sccid",
470
+ "irclid",
471
+ "_kx"
472
+ ];
473
+ var MINIMAL_FLAG_CALLED_EVENT_PROPERTIES = [
474
+ "$feature_flag",
475
+ "$feature_flag_response",
476
+ "$feature_flag_has_experiment",
477
+ "$feature_flag_id",
478
+ "$feature_flag_version",
479
+ "$feature_flag_reason",
480
+ "$feature_flag_request_id",
481
+ "$feature_flag_evaluated_at",
482
+ "$feature_flag_error",
483
+ "locally_evaluated",
484
+ "$groups",
485
+ "$process_person_profile",
486
+ "$geoip_disable",
487
+ "$current_url",
488
+ "$pathname",
489
+ "$referring_domain",
490
+ ...MINIMAL_FLAG_CALLED_EVENT_CAMPAIGN_PROPERTIES,
491
+ "$session_id",
492
+ "$window_id",
493
+ "$lib",
494
+ "$lib_version",
495
+ "$device_id",
496
+ "$is_server"
497
+ ];
498
+ var minimizeFlagCalledEventProperties = (properties, transportKeys = []) => {
499
+ const minimal = {};
500
+ const copyKey = (key) => {
501
+ if (properties[key] !== undefined)
502
+ minimal[key] = properties[key];
503
+ };
504
+ MINIMAL_FLAG_CALLED_EVENT_PROPERTIES.forEach(copyKey);
505
+ transportKeys.forEach(copyKey);
506
+ return minimal;
507
+ };
447
508
 
448
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/types.mjs
509
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/types.mjs
449
510
  var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedProperty) {
450
511
  PostHogPersistedProperty["AnonymousId"] = "anonymous_id";
451
512
  PostHogPersistedProperty["DistinctId"] = "distinct_id";
@@ -460,6 +521,8 @@ var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedPr
460
521
  PostHogPersistedProperty["BootstrapFeatureFlagPayloads"] = "bootstrap_feature_flag_payloads";
461
522
  PostHogPersistedProperty["OverrideFeatureFlags"] = "override_feature_flags";
462
523
  PostHogPersistedProperty["Queue"] = "queue";
524
+ PostHogPersistedProperty["AiQueue"] = "ai_queue";
525
+ PostHogPersistedProperty["AiCaptureQueue"] = "ai_capture_queue";
463
526
  PostHogPersistedProperty["LogsQueue"] = "logs_queue";
464
527
  PostHogPersistedProperty["OptedOut"] = "opted_out";
465
528
  PostHogPersistedProperty["SessionId"] = "session_id";
@@ -470,6 +533,8 @@ var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedPr
470
533
  PostHogPersistedProperty["InstalledAppBuild"] = "installed_app_build";
471
534
  PostHogPersistedProperty["InstalledAppVersion"] = "installed_app_version";
472
535
  PostHogPersistedProperty["SessionReplay"] = "session_replay";
536
+ PostHogPersistedProperty["PushRegistered"] = "push_registered";
537
+ PostHogPersistedProperty["SessionReplayEventTriggerActivatedSession"] = "session_replay_event_trigger_activated_session";
473
538
  PostHogPersistedProperty["SurveyLastSeenDate"] = "survey_last_seen_date";
474
539
  PostHogPersistedProperty["SurveysSeen"] = "surveys_seen";
475
540
  PostHogPersistedProperty["Surveys"] = "surveys";
@@ -479,7 +544,7 @@ var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedPr
479
544
  return PostHogPersistedProperty;
480
545
  }({});
481
546
 
482
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/gzip.mjs
547
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/gzip.mjs
483
548
  function isGzipSupported() {
484
549
  return "CompressionStream" in globalThis && "TextEncoder" in globalThis && "Response" in globalThis && typeof Response.prototype.blob == "function";
485
550
  }
@@ -529,7 +594,7 @@ var validateNativeGzip = async (compressed, inputBytes) => {
529
594
  async function gzipCompress(input, isDebug = true, options) {
530
595
  try {
531
596
  const inputBytes = new TextEncoder().encode(input);
532
- const compressedStream = new CompressionStream("gzip");
597
+ const compressedStream = new globalThis.CompressionStream("gzip");
533
598
  const writer = compressedStream.writable.getWriter();
534
599
  const writePromise = writer.write(inputBytes).then(() => writer.close()).catch(async (err) => {
535
600
  try {
@@ -553,7 +618,7 @@ async function gzipCompress(input, isDebug = true, options) {
553
618
  }
554
619
  }
555
620
 
556
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/bot-detection.mjs
621
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/bot-detection.mjs
557
622
  var DEFAULT_BLOCKED_UA_STRS = [
558
623
  "amazonbot",
559
624
  "amazonproductbot",
@@ -642,7 +707,31 @@ var isBlockedUA = function(ua, customBlockedUserAgents = []) {
642
707
  return uaLower.indexOf(blockedUaLower) !== -1;
643
708
  });
644
709
  };
645
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/type-utils.mjs
710
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/string-utils.mjs
711
+ function safeJsonStringify(value) {
712
+ const ancestors = [];
713
+ return JSON.stringify(value, function(_key, replacementValue) {
714
+ if (typeof replacementValue == "bigint")
715
+ return replacementValue.toString();
716
+ if (typeof replacementValue == "function" || typeof replacementValue == "symbol")
717
+ return;
718
+ if (replacementValue instanceof Error)
719
+ return {
720
+ name: replacementValue.name,
721
+ message: replacementValue.message,
722
+ stack: replacementValue.stack
723
+ };
724
+ if (replacementValue && typeof replacementValue == "object") {
725
+ while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this)
726
+ ancestors.pop();
727
+ if (ancestors.includes(replacementValue))
728
+ return "[Circular]";
729
+ ancestors.push(replacementValue);
730
+ }
731
+ return replacementValue;
732
+ }) ?? "null";
733
+ }
734
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/type-utils.mjs
646
735
  var nativeIsArray = Array.isArray;
647
736
  var ObjProto = Object.prototype;
648
737
  var type_utils_hasOwnProperty = ObjProto.hasOwnProperty;
@@ -654,14 +743,27 @@ var isObject = (x) => x === Object(x) && !isArray(x);
654
743
  var isUndefined = (x) => x === undefined;
655
744
  var isString = (x) => type_utils_toString.call(x) == "[object String]";
656
745
  var isEmptyString = (x) => isString(x) && x.trim().length === 0;
746
+ var isNull = (x) => x === null;
657
747
  var isNumber = (x) => type_utils_toString.call(x) == "[object Number]" && x === x;
658
- var isPlainError = (x) => x instanceof Error;
748
+ var isBoolean = (x) => type_utils_toString.call(x) === "[object Boolean]";
659
749
  function isPrimitive(value) {
660
750
  return value === null || typeof value != "object";
661
751
  }
662
752
  function isBuiltin(candidate, className) {
663
753
  return Object.prototype.toString.call(candidate) === `[object ${className}]`;
664
754
  }
755
+ function isError(candidate) {
756
+ switch (Object.prototype.toString.call(candidate)) {
757
+ case "[object Error]":
758
+ case "[object Exception]":
759
+ case "[object DOMException]":
760
+ case "[object DOMError]":
761
+ case "[object WebAssembly.Exception]":
762
+ return true;
763
+ default:
764
+ return isInstanceOf(candidate, Error);
765
+ }
766
+ }
665
767
  function isErrorEvent(event) {
666
768
  return isBuiltin(event, "ErrorEvent");
667
769
  }
@@ -679,7 +781,7 @@ function isInstanceOf(candidate, base) {
679
781
  }
680
782
  }
681
783
 
682
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/number-utils.mjs
784
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/number-utils.mjs
683
785
  function clampToRange(value, min, max, logger, fallbackValue) {
684
786
  if (min > max) {
685
787
  logger.warn("min cannot be greater than max.");
@@ -699,8 +801,16 @@ function clampToRange(value, min, max, logger, fallbackValue) {
699
801
  return clampToRange(fallbackValue || max, min, max, logger);
700
802
  }
701
803
 
702
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/bucketed-rate-limiter.mjs
804
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/bucketed-rate-limiter.mjs
703
805
  var ONE_DAY_IN_MS = 86400000;
806
+ var DEFAULT_EXCEPTION_RATE_LIMITER_REFILL_RATE = 1;
807
+ var DEFAULT_EXCEPTION_RATE_LIMITER_BUCKET_SIZE = 10;
808
+ function resolveExceptionRateLimiterConfig(config = {}) {
809
+ return {
810
+ refillRate: config.exceptionRateLimiterRefillRate ?? config.__exceptionRateLimiterRefillRate ?? DEFAULT_EXCEPTION_RATE_LIMITER_REFILL_RATE,
811
+ bucketSize: config.exceptionRateLimiterBucketSize ?? config.__exceptionRateLimiterBucketSize ?? DEFAULT_EXCEPTION_RATE_LIMITER_BUCKET_SIZE
812
+ };
813
+ }
704
814
 
705
815
  class BucketedRateLimiter {
706
816
  constructor(options) {
@@ -743,7 +853,10 @@ class BucketedRateLimiter {
743
853
  this._buckets = {};
744
854
  }
745
855
  }
746
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/vendor/uuidv7.mjs
856
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/json-utils.mjs
857
+ var dateGetTime = Date.prototype.getTime;
858
+ var dateToISOString = Date.prototype.toISOString;
859
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/vendor/uuidv7.mjs
747
860
  /*! For license information please see uuidv7.mjs.LICENSE.txt */
748
861
  var DIGITS = "0123456789abcdef";
749
862
 
@@ -921,33 +1034,45 @@ var defaultGenerator;
921
1034
  var uuidv7 = () => uuidv7obj().toString();
922
1035
  var uuidv7obj = () => (defaultGenerator || (defaultGenerator = new V7Generator)).generate();
923
1036
 
924
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/promise-queue.mjs
1037
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/promise-queue.mjs
925
1038
  class PromiseQueue {
926
1039
  add(promise) {
927
1040
  const promiseUUID = uuidv7();
928
- this.promiseByIds[promiseUUID] = promise;
1041
+ const id = ++this.nextId;
1042
+ this.promiseByIds[promiseUUID] = {
1043
+ id,
1044
+ promise
1045
+ };
929
1046
  promise.catch(() => {}).finally(() => {
930
1047
  delete this.promiseByIds[promiseUUID];
931
1048
  });
932
1049
  return promise;
933
1050
  }
934
1051
  async join() {
935
- let promises = Object.values(this.promiseByIds);
1052
+ let promises = Object.values(this.promiseByIds).map((item) => item.promise);
936
1053
  let length = promises.length;
937
1054
  while (length > 0) {
938
1055
  await Promise.all(promises);
939
- promises = Object.values(this.promiseByIds);
1056
+ promises = Object.values(this.promiseByIds).map((item) => item.promise);
940
1057
  length = promises.length;
941
1058
  }
942
1059
  }
1060
+ getPromises(ignoredPromises = [], maxId = this.nextId) {
1061
+ const ignoredPromiseSet = new Set(ignoredPromises);
1062
+ return Object.values(this.promiseByIds).filter((item) => item.id <= maxId && !ignoredPromiseSet.has(item.promise)).map((item) => item.promise);
1063
+ }
1064
+ get maxId() {
1065
+ return this.nextId;
1066
+ }
943
1067
  get length() {
944
1068
  return Object.keys(this.promiseByIds).length;
945
1069
  }
946
1070
  constructor() {
947
1071
  this.promiseByIds = {};
1072
+ this.nextId = 0;
948
1073
  }
949
1074
  }
950
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/logger.mjs
1075
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/logger.mjs
951
1076
  function createConsole(consoleLike = console) {
952
1077
  const lockedMethods = {
953
1078
  log: consoleLike.log.bind(consoleLike),
@@ -988,7 +1113,7 @@ var passThrough = (fn) => fn();
988
1113
  function createLogger(prefix, maybeCall = passThrough) {
989
1114
  return _createLogger(prefix, maybeCall, createConsole());
990
1115
  }
991
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/user-agent-utils.mjs
1116
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/user-agent-utils.mjs
992
1117
  var MOBILE = "Mobile";
993
1118
  var IOS = "iOS";
994
1119
  var ANDROID = "Android";
@@ -1031,6 +1156,7 @@ var DUCKDUCKGO = "DuckDuckGo";
1031
1156
  var PALE_MOON = "Pale Moon";
1032
1157
  var WATERFOX = "Waterfox";
1033
1158
  var BRAVE = "Brave";
1159
+ var GOOGLE_SEARCH_APP = "Google Search App";
1034
1160
  var BROWSER_VERSION_REGEX_SUFFIX = "(\\d+(\\.\\d+)?)";
1035
1161
  var DEFAULT_BROWSER_VERSION_REGEX = new RegExp("Version/" + BROWSER_VERSION_REGEX_SUFFIX);
1036
1162
  var XBOX_REGEX = new RegExp(XBOX, "i");
@@ -1118,6 +1244,9 @@ var versionRegexes = {
1118
1244
  [WATERFOX]: [
1119
1245
  new RegExp(WATERFOX + "\\/" + BROWSER_VERSION_REGEX_SUFFIX)
1120
1246
  ],
1247
+ [GOOGLE_SEARCH_APP]: [
1248
+ new RegExp("GSA\\/" + BROWSER_VERSION_REGEX_SUFFIX)
1249
+ ],
1121
1250
  [INTERNET_EXPLORER]: [
1122
1251
  new RegExp("(rv:|MSIE )" + BROWSER_VERSION_REGEX_SUFFIX)
1123
1252
  ],
@@ -1277,8 +1406,15 @@ var osMatchers = [
1277
1406
  ]
1278
1407
  ];
1279
1408
 
1280
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/index.mjs
1409
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/index.mjs
1281
1410
  var STRING_FORMAT = "utf8";
1411
+ var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1412
+ function isValidUUID(value) {
1413
+ return typeof value == "string" && UUID_REGEX.test(value);
1414
+ }
1415
+ function getEventUuid(uuid, generateUuid) {
1416
+ return isValidUUID(uuid) ? uuid : generateUuid();
1417
+ }
1282
1418
  function removeTrailingSlash(url) {
1283
1419
  return url?.replace(/\/+$/, "");
1284
1420
  }
@@ -1306,7 +1442,26 @@ function safeSetTimeout(fn, timeout) {
1306
1442
  t?.unref && t?.unref();
1307
1443
  return t;
1308
1444
  }
1309
- var isError = (x) => x instanceof Error;
1445
+ async function raceWithTimeout(promise, timeoutMs, onTimeout) {
1446
+ let timeoutHandle;
1447
+ try {
1448
+ return await Promise.race([
1449
+ promise,
1450
+ new Promise((resolve, reject) => {
1451
+ timeoutHandle = safeSetTimeout(() => {
1452
+ try {
1453
+ onTimeout?.();
1454
+ resolve();
1455
+ } catch (error) {
1456
+ reject(error);
1457
+ }
1458
+ }, timeoutMs);
1459
+ })
1460
+ ]);
1461
+ } finally {
1462
+ clearTimeout(timeoutHandle);
1463
+ }
1464
+ }
1310
1465
  function allSettled(promises) {
1311
1466
  return Promise.all(promises.map((p) => (p ?? Promise.resolve()).then((value) => ({
1312
1467
  status: "fulfilled",
@@ -1317,7 +1472,7 @@ function allSettled(promises) {
1317
1472
  }))));
1318
1473
  }
1319
1474
 
1320
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/logs/logs-utils.mjs
1475
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/logs/logs-utils.mjs
1321
1476
  var OTLP_SEVERITY_MAP = {
1322
1477
  trace: {
1323
1478
  text: "TRACE",
@@ -1345,7 +1500,464 @@ var OTLP_SEVERITY_MAP = {
1345
1500
  }
1346
1501
  };
1347
1502
  var DEFAULT_OTLP_SEVERITY = OTLP_SEVERITY_MAP.info;
1348
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/eventemitter.mjs
1503
+ function toOtlpAnyValue(value) {
1504
+ if (isBoolean(value))
1505
+ return {
1506
+ boolValue: value
1507
+ };
1508
+ if (typeof value == "number") {
1509
+ if (!Number.isFinite(value))
1510
+ return {
1511
+ stringValue: String(value)
1512
+ };
1513
+ if (Number.isInteger(value))
1514
+ return {
1515
+ intValue: value
1516
+ };
1517
+ return {
1518
+ doubleValue: value
1519
+ };
1520
+ }
1521
+ if (typeof value == "string")
1522
+ return {
1523
+ stringValue: value
1524
+ };
1525
+ if (isArray(value))
1526
+ return {
1527
+ arrayValue: {
1528
+ values: value.map((v) => toOtlpAnyValue(v))
1529
+ }
1530
+ };
1531
+ try {
1532
+ return {
1533
+ stringValue: JSON.stringify(value)
1534
+ };
1535
+ } catch {
1536
+ return {
1537
+ stringValue: String(value)
1538
+ };
1539
+ }
1540
+ }
1541
+ function toOtlpKeyValueList(attrs) {
1542
+ const result = [];
1543
+ for (const key in attrs) {
1544
+ const value = attrs[key];
1545
+ if (!(isNull(value) || isUndefined(value)))
1546
+ result.push({
1547
+ key,
1548
+ value: toOtlpAnyValue(value)
1549
+ });
1550
+ }
1551
+ return result;
1552
+ }
1553
+
1554
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/metrics/metrics-utils.mjs
1555
+ var DEFAULT_HISTOGRAM_BOUNDS = [
1556
+ 0,
1557
+ 5,
1558
+ 10,
1559
+ 25,
1560
+ 50,
1561
+ 75,
1562
+ 100,
1563
+ 250,
1564
+ 500,
1565
+ 750,
1566
+ 1000,
1567
+ 2500,
1568
+ 5000,
1569
+ 7500,
1570
+ 1e4
1571
+ ];
1572
+ function msToUnixNano(ms) {
1573
+ return String(ms) + "000000";
1574
+ }
1575
+ function seriesKey(type, name, unit, attributes) {
1576
+ let attrsKey = "";
1577
+ if (attributes) {
1578
+ const keys = Object.keys(attributes).sort();
1579
+ attrsKey = keys.map((k) => `${JSON.stringify(k)}:${JSON.stringify(attributes[k])}`).join(",");
1580
+ }
1581
+ return `${type}\x00${name}\x00${unit ?? ""}\x00${attrsKey}`;
1582
+ }
1583
+ function bucketIndexFor(value, bounds) {
1584
+ for (let i = 0;i < bounds.length; i++)
1585
+ if (value <= bounds[i])
1586
+ return i;
1587
+ return bounds.length;
1588
+ }
1589
+ function buildMetricsResourceAttributes(config, scopeName, scopeVersion) {
1590
+ return {
1591
+ ...config.resourceAttributes,
1592
+ "service.name": config.serviceName || "unknown_service",
1593
+ ...config.environment && {
1594
+ "deployment.environment": config.environment
1595
+ },
1596
+ ...config.serviceVersion && {
1597
+ "service.version": config.serviceVersion
1598
+ },
1599
+ "telemetry.sdk.name": scopeName,
1600
+ "telemetry.sdk.version": scopeVersion
1601
+ };
1602
+ }
1603
+ function buildOtlpMetricsPayload(metrics, resourceAttributes, scopeName, scopeVersion) {
1604
+ return {
1605
+ resourceMetrics: [
1606
+ {
1607
+ resource: {
1608
+ attributes: toOtlpKeyValueList(resourceAttributes)
1609
+ },
1610
+ scopeMetrics: [
1611
+ {
1612
+ scope: {
1613
+ name: scopeName,
1614
+ version: scopeVersion
1615
+ },
1616
+ metrics
1617
+ }
1618
+ ]
1619
+ }
1620
+ ]
1621
+ };
1622
+ }
1623
+
1624
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/metrics/config.mjs
1625
+ var DEFAULT_FLUSH_INTERVAL_MS = 1e4;
1626
+ var DEFAULT_MAX_SERIES_PER_FLUSH = 1000;
1627
+ function resolveMetricsConfig(config) {
1628
+ const resourceAttributes = config?.resourceAttributes;
1629
+ return {
1630
+ serviceName: resourceAttributes?.["service.name"] ?? config?.serviceName,
1631
+ serviceVersion: resourceAttributes?.["service.version"] ?? config?.serviceVersion,
1632
+ environment: resourceAttributes?.["deployment.environment"] ?? config?.environment,
1633
+ resourceAttributes,
1634
+ beforeSend: config?.beforeSend,
1635
+ flushIntervalMs: config?.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,
1636
+ maxSeriesPerFlush: config?.maxSeriesPerFlush ?? DEFAULT_MAX_SERIES_PER_FLUSH
1637
+ };
1638
+ }
1639
+
1640
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/metrics/index.mjs
1641
+ var OTLP_TEMPORALITY_DELTA = 1;
1642
+
1643
+ class PostHogMetrics {
1644
+ constructor(_instance, _config, _logger) {
1645
+ this._instance = _instance;
1646
+ this._config = _config;
1647
+ this._logger = _logger;
1648
+ this._series = new Map;
1649
+ this._flushPromise = null;
1650
+ this._seriesCapWarned = false;
1651
+ this._typeByName = new Map;
1652
+ this._typeCollisionWarned = new Set;
1653
+ this._generation = 0;
1654
+ }
1655
+ count(name, value = 1, options) {
1656
+ this._capture({
1657
+ name,
1658
+ type: "count",
1659
+ value,
1660
+ unit: options?.unit,
1661
+ attributes: options?.attributes
1662
+ });
1663
+ }
1664
+ gauge(name, value, options) {
1665
+ this._capture({
1666
+ name,
1667
+ type: "gauge",
1668
+ value,
1669
+ unit: options?.unit,
1670
+ attributes: options?.attributes
1671
+ });
1672
+ }
1673
+ histogram(name, value, options) {
1674
+ this._capture({
1675
+ name,
1676
+ type: "histogram",
1677
+ value,
1678
+ unit: options?.unit,
1679
+ attributes: options?.attributes
1680
+ });
1681
+ }
1682
+ flush() {
1683
+ const prev = this._flushPromise;
1684
+ const run = async () => {
1685
+ if (prev)
1686
+ await prev.catch(() => {});
1687
+ await this._doFlush();
1688
+ };
1689
+ const p = run().finally(() => {
1690
+ if (this._flushPromise === p)
1691
+ this._flushPromise = null;
1692
+ });
1693
+ this._flushPromise = p;
1694
+ return p;
1695
+ }
1696
+ drainWindow() {
1697
+ if (this._series.size === 0)
1698
+ return null;
1699
+ const window = this._series;
1700
+ this._series = new Map;
1701
+ this._seriesCapWarned = false;
1702
+ this._typeByName = new Map;
1703
+ this._typeCollisionWarned = new Set;
1704
+ return this._buildPayload(window);
1705
+ }
1706
+ reset() {
1707
+ this._generation++;
1708
+ this._clearFlushTimer();
1709
+ this._series = new Map;
1710
+ this._flushPromise = null;
1711
+ this._seriesCapWarned = false;
1712
+ this._typeByName = new Map;
1713
+ this._typeCollisionWarned = new Set;
1714
+ }
1715
+ _capture(sample) {
1716
+ if (this._instance.isDisabled || this._instance.optedOut)
1717
+ return;
1718
+ const filtered = this._runBeforeSend(sample);
1719
+ if (filtered === null)
1720
+ return;
1721
+ if (!filtered.name || typeof filtered.name != "string")
1722
+ return void this._logger.warn("Dropping metric with empty name");
1723
+ if (typeof filtered.value != "number" || !Number.isFinite(filtered.value))
1724
+ return void this._logger.warn(`Dropping metric '${filtered.name}': value must be a finite number`);
1725
+ if (filtered.type === "count" && filtered.value < 0)
1726
+ return void this._logger.warn(`Dropping count '${filtered.name}': counters are monotonic, value must be >= 0`);
1727
+ let attributes;
1728
+ let key;
1729
+ try {
1730
+ attributes = filtered.attributes ? {
1731
+ ...filtered.attributes
1732
+ } : undefined;
1733
+ key = seriesKey(filtered.type, filtered.name, filtered.unit, attributes);
1734
+ } catch (e) {
1735
+ this._logger.warn(`Dropping metric '${filtered.name}': attributes could not be serialized`, e);
1736
+ return;
1737
+ }
1738
+ let state = this._series.get(key);
1739
+ if (!state) {
1740
+ if (!this._admitNewSeries())
1741
+ return;
1742
+ state = {
1743
+ name: filtered.name,
1744
+ type: filtered.type,
1745
+ unit: filtered.unit,
1746
+ attributes,
1747
+ windowStartMs: Date.now()
1748
+ };
1749
+ this._series.set(key, state);
1750
+ }
1751
+ const seenType = this._typeByName.get(filtered.name);
1752
+ if (seenType === undefined)
1753
+ this._typeByName.set(filtered.name, filtered.type);
1754
+ else if (seenType !== filtered.type && !this._typeCollisionWarned.has(filtered.name)) {
1755
+ this._typeCollisionWarned.add(filtered.name);
1756
+ this._logger.warn(`Metric name '${filtered.name}' is already used as a ${seenType}; recording it as a ${filtered.type} too will blend both series in charts. Use a distinct name.`);
1757
+ }
1758
+ this._fold(state, filtered.value);
1759
+ this._armFlushTimer();
1760
+ }
1761
+ _admitNewSeries() {
1762
+ if (this._series.size < this._config.maxSeriesPerFlush)
1763
+ return true;
1764
+ if (!this._seriesCapWarned) {
1765
+ this._seriesCapWarned = true;
1766
+ this._logger.warn(`Metric series cap reached (${this._config.maxSeriesPerFlush} per flush window); dropping new series until the next flush. Reduce attribute cardinality.`);
1767
+ }
1768
+ return false;
1769
+ }
1770
+ _fold(state, value) {
1771
+ switch (state.type) {
1772
+ case "count":
1773
+ state.total = (state.total ?? 0) + value;
1774
+ break;
1775
+ case "gauge":
1776
+ state.last = value;
1777
+ break;
1778
+ case "histogram": {
1779
+ if (!state.hist)
1780
+ state.hist = {
1781
+ count: 0,
1782
+ sum: 0,
1783
+ min: value,
1784
+ max: value,
1785
+ bucketCounts: new Array(DEFAULT_HISTOGRAM_BOUNDS.length + 1).fill(0)
1786
+ };
1787
+ const hist = state.hist;
1788
+ hist.count += 1;
1789
+ hist.sum += value;
1790
+ hist.min = Math.min(hist.min, value);
1791
+ hist.max = Math.max(hist.max, value);
1792
+ hist.bucketCounts[bucketIndexFor(value, DEFAULT_HISTOGRAM_BOUNDS)] += 1;
1793
+ break;
1794
+ }
1795
+ }
1796
+ }
1797
+ _runBeforeSend(sample) {
1798
+ const beforeSend = this._config.beforeSend;
1799
+ if (!beforeSend)
1800
+ return sample;
1801
+ const fns = isArray(beforeSend) ? beforeSend : [
1802
+ beforeSend
1803
+ ];
1804
+ let result = sample;
1805
+ for (const fn of fns)
1806
+ try {
1807
+ const next = fn(result);
1808
+ if (!next) {
1809
+ this._logger.info("Metric was rejected in beforeSend function");
1810
+ return null;
1811
+ }
1812
+ result = next;
1813
+ } catch (e) {
1814
+ this._logger.error("Error in beforeSend function for metric:", e);
1815
+ return null;
1816
+ }
1817
+ return result;
1818
+ }
1819
+ _armFlushTimer() {
1820
+ if (this._flushTimer)
1821
+ return;
1822
+ this._flushTimer = safeSetTimeout(() => {
1823
+ this._flushTimer = undefined;
1824
+ this.flush().catch((e) => {
1825
+ this._logger.error("Metrics flush failed:", e);
1826
+ });
1827
+ }, this._config.flushIntervalMs);
1828
+ }
1829
+ _clearFlushTimer() {
1830
+ if (this._flushTimer) {
1831
+ clearTimeout(this._flushTimer);
1832
+ this._flushTimer = undefined;
1833
+ }
1834
+ }
1835
+ async _doFlush() {
1836
+ if (this._series.size === 0)
1837
+ return;
1838
+ const window = this._series;
1839
+ this._series = new Map;
1840
+ this._seriesCapWarned = false;
1841
+ this._typeByName = new Map;
1842
+ this._typeCollisionWarned = new Set;
1843
+ const generation = this._generation;
1844
+ const outcome = await this._instance._sendMetricsBatch(this._buildPayload(window));
1845
+ if (generation !== this._generation)
1846
+ return;
1847
+ switch (outcome.kind) {
1848
+ case "ok":
1849
+ return;
1850
+ case "retry-later":
1851
+ this._mergeWindowBack(window);
1852
+ this._armFlushTimer();
1853
+ return;
1854
+ case "too-large":
1855
+ this._logger.warn("Metrics batch exceeded the server size limit and was dropped");
1856
+ return;
1857
+ case "fatal":
1858
+ this._logger.error("Failed to send metrics batch:", outcome.error);
1859
+ return;
1860
+ }
1861
+ }
1862
+ _buildPayload(window) {
1863
+ return buildOtlpMetricsPayload(this._buildMetrics(window), buildMetricsResourceAttributes(this._config, this._instance.getLibraryId(), this._instance.getLibraryVersion()), this._instance.getLibraryId(), this._instance.getLibraryVersion());
1864
+ }
1865
+ _buildMetrics(window) {
1866
+ const nowNano = msToUnixNano(Date.now());
1867
+ const byMetric = new Map;
1868
+ for (const state of window.values()) {
1869
+ const metricKey = seriesKey(state.type, state.name, state.unit, undefined);
1870
+ let metric = byMetric.get(metricKey);
1871
+ if (!metric) {
1872
+ metric = {
1873
+ name: state.name,
1874
+ ...state.unit && {
1875
+ unit: state.unit
1876
+ }
1877
+ };
1878
+ if (state.type === "count")
1879
+ metric.sum = {
1880
+ aggregationTemporality: OTLP_TEMPORALITY_DELTA,
1881
+ isMonotonic: true,
1882
+ dataPoints: []
1883
+ };
1884
+ else if (state.type === "gauge")
1885
+ metric.gauge = {
1886
+ dataPoints: []
1887
+ };
1888
+ else
1889
+ metric.histogram = {
1890
+ aggregationTemporality: OTLP_TEMPORALITY_DELTA,
1891
+ dataPoints: []
1892
+ };
1893
+ byMetric.set(metricKey, metric);
1894
+ }
1895
+ const attributes = toOtlpKeyValueList(state.attributes ?? {});
1896
+ const startNano = msToUnixNano(state.windowStartMs);
1897
+ if (state.type === "count") {
1898
+ const dp = {
1899
+ attributes,
1900
+ startTimeUnixNano: startNano,
1901
+ timeUnixNano: nowNano,
1902
+ asDouble: state.total ?? 0
1903
+ };
1904
+ metric.sum.dataPoints.push(dp);
1905
+ } else if (state.type === "gauge") {
1906
+ const dp = {
1907
+ attributes,
1908
+ timeUnixNano: nowNano,
1909
+ asDouble: state.last ?? 0
1910
+ };
1911
+ metric.gauge.dataPoints.push(dp);
1912
+ } else if (state.hist) {
1913
+ const dp = {
1914
+ attributes,
1915
+ startTimeUnixNano: startNano,
1916
+ timeUnixNano: nowNano,
1917
+ count: state.hist.count,
1918
+ sum: state.hist.sum,
1919
+ min: state.hist.min,
1920
+ max: state.hist.max,
1921
+ bucketCounts: state.hist.bucketCounts,
1922
+ explicitBounds: DEFAULT_HISTOGRAM_BOUNDS
1923
+ };
1924
+ metric.histogram.dataPoints.push(dp);
1925
+ }
1926
+ }
1927
+ return Array.from(byMetric.values());
1928
+ }
1929
+ _mergeWindowBack(window) {
1930
+ for (const [key, old] of window) {
1931
+ const current = this._series.get(key);
1932
+ if (!current) {
1933
+ if (this._admitNewSeries())
1934
+ this._series.set(key, old);
1935
+ continue;
1936
+ }
1937
+ current.windowStartMs = Math.min(current.windowStartMs, old.windowStartMs);
1938
+ switch (current.type) {
1939
+ case "count":
1940
+ current.total = (current.total ?? 0) + (old.total ?? 0);
1941
+ break;
1942
+ case "gauge":
1943
+ break;
1944
+ case "histogram":
1945
+ if (old.hist)
1946
+ if (current.hist) {
1947
+ current.hist.count += old.hist.count;
1948
+ current.hist.sum += old.hist.sum;
1949
+ current.hist.min = Math.min(current.hist.min, old.hist.min);
1950
+ current.hist.max = Math.max(current.hist.max, old.hist.max);
1951
+ for (let i = 0;i < current.hist.bucketCounts.length; i++)
1952
+ current.hist.bucketCounts[i] += old.hist.bucketCounts[i];
1953
+ } else
1954
+ current.hist = old.hist;
1955
+ break;
1956
+ }
1957
+ }
1958
+ }
1959
+ }
1960
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/eventemitter.mjs
1349
1961
  class SimpleEventEmitter {
1350
1962
  constructor() {
1351
1963
  this.events = {};
@@ -1367,7 +1979,7 @@ class SimpleEventEmitter {
1367
1979
  }
1368
1980
  }
1369
1981
 
1370
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/index.mjs
1982
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/index.mjs
1371
1983
  var exports_error_tracking = {};
1372
1984
  __export(exports_error_tracking, {
1373
1985
  winjsStackLineParser: () => winjsStackLineParser,
@@ -1378,6 +1990,7 @@ __export(exports_error_tracking, {
1378
1990
  opera10StackLineParser: () => opera10StackLineParser,
1379
1991
  nodeStackLineParser: () => nodeStackLineParser,
1380
1992
  getUtf8ByteLength: () => getUtf8ByteLength,
1993
+ getInjectedReleaseId: () => getInjectedReleaseId,
1381
1994
  geckoStackLineParser: () => geckoStackLineParser,
1382
1995
  createStackParser: () => createStackParser,
1383
1996
  createDefaultStackParser: () => createDefaultStackParser,
@@ -1397,7 +2010,7 @@ __export(exports_error_tracking, {
1397
2010
  DEFAULT_EXCEPTION_STEPS_CONFIG: () => DEFAULT_EXCEPTION_STEPS_CONFIG
1398
2011
  });
1399
2012
 
1400
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/chunk-ids.mjs
2013
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/chunk-ids.mjs
1401
2014
  var parsedStackResults;
1402
2015
  var lastKeysCount;
1403
2016
  var cachedFilenameChunkIds;
@@ -1436,7 +2049,7 @@ function getFilenameToChunkIdMap(stackParser) {
1436
2049
  return cachedFilenameChunkIds;
1437
2050
  }
1438
2051
 
1439
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/error-properties-builder.mjs
2052
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/error-properties-builder.mjs
1440
2053
  var MAX_CAUSE_RECURSION = 4;
1441
2054
 
1442
2055
  class ErrorPropertiesBuilder {
@@ -1558,14 +2171,16 @@ class ErrorPropertiesBuilder {
1558
2171
  return context;
1559
2172
  }
1560
2173
  }
1561
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/base.mjs
2174
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/base.mjs
1562
2175
  var UNKNOWN_FUNCTION = "?";
2176
+ var MASKED_URL_PREFIX = "webkit-masked-url://";
2177
+ var ANONYMOUS_FILENAME = "<anonymous>";
1563
2178
  function createFrame(platform, filename, func, lineno, colno) {
1564
2179
  const frame = {
1565
2180
  platform,
1566
2181
  filename,
1567
2182
  function: func === "<anonymous>" ? UNKNOWN_FUNCTION : func,
1568
- in_app: true
2183
+ in_app: !filename?.startsWith(MASKED_URL_PREFIX) && filename !== ANONYMOUS_FILENAME
1569
2184
  };
1570
2185
  if (!isUndefined(lineno))
1571
2186
  frame.lineno = lineno;
@@ -1574,7 +2189,7 @@ function createFrame(platform, filename, func, lineno, colno) {
1574
2189
  return frame;
1575
2190
  }
1576
2191
 
1577
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/safari.mjs
2192
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/safari.mjs
1578
2193
  var extractSafariExtensionDetails = (func, filename) => {
1579
2194
  const isSafariExtension = func.indexOf("safari-extension") !== -1;
1580
2195
  const isSafariWebExtension = func.indexOf("safari-web-extension") !== -1;
@@ -1587,7 +2202,7 @@ var extractSafariExtensionDetails = (func, filename) => {
1587
2202
  ];
1588
2203
  };
1589
2204
 
1590
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/chrome.mjs
2205
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/chrome.mjs
1591
2206
  var chromeRegexNoFnName = /^\s*at (\S+?)(?::(\d+))(?::(\d+))\s*$/i;
1592
2207
  var chromeRegex = /^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
1593
2208
  var chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
@@ -1613,7 +2228,7 @@ var chromeStackLineParser = (line, platform) => {
1613
2228
  }
1614
2229
  };
1615
2230
 
1616
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/gecko.mjs
2231
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/gecko.mjs
1617
2232
  var geckoREgex = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
1618
2233
  var geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
1619
2234
  var geckoStackLineParser = (line, platform) => {
@@ -1636,14 +2251,14 @@ var geckoStackLineParser = (line, platform) => {
1636
2251
  }
1637
2252
  };
1638
2253
 
1639
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/winjs.mjs
2254
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/winjs.mjs
1640
2255
  var winjsRegex = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:[-a-z]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
1641
2256
  var winjsStackLineParser = (line, platform) => {
1642
2257
  const parts = winjsRegex.exec(line);
1643
2258
  return parts ? createFrame(platform, parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : undefined) : undefined;
1644
2259
  };
1645
2260
 
1646
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/opera.mjs
2261
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/opera.mjs
1647
2262
  var opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
1648
2263
  var opera10StackLineParser = (line, platform) => {
1649
2264
  const parts = opera10Regex.exec(line);
@@ -1655,9 +2270,12 @@ var opera11StackLineParser = (line, platform) => {
1655
2270
  return parts ? createFrame(platform, parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2]) : undefined;
1656
2271
  };
1657
2272
 
1658
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/node.mjs
2273
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/node.mjs
1659
2274
  var FILENAME_MATCH = /^\s*[-]{4,}$/;
1660
2275
  var FULL_MATCH = /at (?:async )?(?:(.+?)\s+\()?(?:(.+):(\d+):(\d+)?|([^)]+))\)?/;
2276
+ var PROMISE_COMBINATOR = /^Promise\.(?:all|any)$/;
2277
+ var PROMISE_INDEX = /^index \d+$/;
2278
+ var PROMISE_FRAME_FILENAME = "node:internal/promise";
1661
2279
  var nodeStackLineParser = (line, platform) => {
1662
2280
  const lineMatch = line.match(FULL_MATCH);
1663
2281
  if (lineMatch) {
@@ -1700,6 +2318,8 @@ var nodeStackLineParser = (line, platform) => {
1700
2318
  filename = filename.slice(1);
1701
2319
  if (!filename && lineMatch[5] && !isNative)
1702
2320
  filename = lineMatch[5];
2321
+ if (PROMISE_COMBINATOR.test(functionName) && PROMISE_INDEX.test(filename || ""))
2322
+ filename = PROMISE_FRAME_FILENAME;
1703
2323
  return {
1704
2324
  filename: filename ? decodeURI(filename) : undefined,
1705
2325
  module: undefined,
@@ -1724,7 +2344,7 @@ function _parseIntOrUndefined(input) {
1724
2344
  return parseInt(input || "", 10) || undefined;
1725
2345
  }
1726
2346
 
1727
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/index.mjs
2347
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/index.mjs
1728
2348
  var WEBPACK_ERROR_REGEXP = /\(error: (.*)\)/;
1729
2349
  var STACKTRACE_FRAME_LIMIT = 50;
1730
2350
  function reverseAndStripFrames(stack) {
@@ -1769,7 +2389,7 @@ function createStackParser(platform, ...parsers) {
1769
2389
  return reverseAndStripFrames(frames);
1770
2390
  };
1771
2391
  }
1772
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/dom-exception-coercer.mjs
2392
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/dom-exception-coercer.mjs
1773
2393
  class DOMExceptionCoercer {
1774
2394
  match(err) {
1775
2395
  return this.isDOMException(err) || this.isDOMError(err);
@@ -1799,18 +2419,20 @@ class DOMExceptionCoercer {
1799
2419
  return isBuiltin(err, "DOMError");
1800
2420
  }
1801
2421
  }
1802
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/error-coercer.mjs
2422
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/error-coercer.mjs
1803
2423
  class ErrorCoercer {
1804
2424
  match(err) {
1805
- return isPlainError(err);
2425
+ return isError(err);
1806
2426
  }
1807
2427
  coerce(err, ctx) {
2428
+ const stack = this.getStack(err);
2429
+ const synthetic = stack === undefined;
1808
2430
  return {
1809
2431
  type: this.getType(err),
1810
2432
  value: this.getMessage(err, ctx),
1811
- stack: this.getStack(err),
2433
+ stack: stack ?? ctx.syntheticException?.stack,
1812
2434
  cause: err.cause ? ctx.next(err.cause) : undefined,
1813
- synthetic: false
2435
+ synthetic
1814
2436
  };
1815
2437
  }
1816
2438
  getType(err) {
@@ -1826,25 +2448,41 @@ class ErrorCoercer {
1826
2448
  return err.stacktrace || err.stack || undefined;
1827
2449
  }
1828
2450
  }
1829
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/error-event-coercer.mjs
2451
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/error-event-coercer.mjs
1830
2452
  class ErrorEventCoercer {
1831
2453
  constructor() {}
1832
2454
  match(err) {
1833
- return isErrorEvent(err) && err.error != null;
2455
+ if (!isErrorEvent(err))
2456
+ return false;
2457
+ const errorEvent = err;
2458
+ return errorEvent.error != null || this._hasUsableMessage(errorEvent);
1834
2459
  }
1835
2460
  coerce(err, ctx) {
1836
- const exceptionLike = ctx.apply(err.error);
1837
- if (!exceptionLike)
1838
- return {
1839
- type: "ErrorEvent",
1840
- value: err.message,
1841
- stack: ctx.syntheticException?.stack,
1842
- synthetic: true
1843
- };
1844
- return exceptionLike;
2461
+ if (err.error != null)
2462
+ return ctx.apply(err.error);
2463
+ const exceptionLike = ctx.apply(err.message);
2464
+ return {
2465
+ ...exceptionLike,
2466
+ stack: this._buildLocationStack(err) ?? exceptionLike.stack,
2467
+ synthetic: true
2468
+ };
2469
+ }
2470
+ _hasUsableMessage(err) {
2471
+ return isString(err.message) && err.message.length > 0;
2472
+ }
2473
+ _buildLocationStack(err) {
2474
+ const location = err;
2475
+ const lineno = location.lineno ?? 0;
2476
+ const colno = location.colno ?? 0;
2477
+ if (!isString(location.filename) || location.filename.length === 0)
2478
+ return;
2479
+ if (lineno === 0)
2480
+ return;
2481
+ return `Error
2482
+ at ${location.filename}:${lineno}:${colno}`;
1845
2483
  }
1846
2484
  }
1847
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/string-coercer.mjs
2485
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/string-coercer.mjs
1848
2486
  var ERROR_TYPES_PATTERN = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i;
1849
2487
 
1850
2488
  class StringCoercer {
@@ -1874,7 +2512,7 @@ class StringCoercer {
1874
2512
  ];
1875
2513
  }
1876
2514
  }
1877
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/types.mjs
2515
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/types.mjs
1878
2516
  var severityLevels = [
1879
2517
  "fatal",
1880
2518
  "error",
@@ -1884,7 +2522,7 @@ var severityLevels = [
1884
2522
  "debug"
1885
2523
  ];
1886
2524
 
1887
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/utils.mjs
2525
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/utils.mjs
1888
2526
  function extractExceptionKeysForMessage(err, maxLength = 40) {
1889
2527
  const keys = Object.keys(err);
1890
2528
  keys.sort();
@@ -1901,7 +2539,7 @@ function extractExceptionKeysForMessage(err, maxLength = 40) {
1901
2539
  return "";
1902
2540
  }
1903
2541
 
1904
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/object-coercer.mjs
2542
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/object-coercer.mjs
1905
2543
  class ObjectCoercer {
1906
2544
  match(candidate) {
1907
2545
  return typeof candidate == "object" && candidate !== null;
@@ -1913,13 +2551,16 @@ class ObjectCoercer {
1913
2551
  return {
1914
2552
  type: this.getType(candidate),
1915
2553
  value: this.getValue(candidate),
1916
- stack: ctx.syntheticException?.stack,
2554
+ stack: this.getStack(candidate) ?? ctx.syntheticException?.stack,
1917
2555
  level: this.isSeverityLevel(candidate.level) ? candidate.level : "error",
1918
2556
  synthetic: true
1919
2557
  };
1920
2558
  }
1921
2559
  getType(err) {
1922
- return isEvent(err) ? err.constructor.name : "Error";
2560
+ if (isEvent(err))
2561
+ return err.constructor.name;
2562
+ const name = "name" in err ? err.name : undefined;
2563
+ return isString(name) && !isEmptyString(name) ? name : "Error";
1923
2564
  }
1924
2565
  getValue(err) {
1925
2566
  if ("name" in err && typeof err.name == "string") {
@@ -1937,6 +2578,15 @@ class ObjectCoercer {
1937
2578
  isSeverityLevel(x) {
1938
2579
  return isString(x) && !isEmptyString(x) && severityLevels.indexOf(x) >= 0;
1939
2580
  }
2581
+ getStack(candidate) {
2582
+ try {
2583
+ if (isString(candidate.stacktrace) && candidate.stacktrace.length > 0)
2584
+ return candidate.stacktrace;
2585
+ return isString(candidate.stack) && candidate.stack.length > 0 ? candidate.stack : undefined;
2586
+ } catch {
2587
+ return;
2588
+ }
2589
+ }
1940
2590
  getErrorPropertyFromObject(obj) {
1941
2591
  for (const prop in obj)
1942
2592
  if (Object.prototype.hasOwnProperty.call(obj, prop)) {
@@ -1954,7 +2604,7 @@ class ObjectCoercer {
1954
2604
  }
1955
2605
  }
1956
2606
  }
1957
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/event-coercer.mjs
2607
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/event-coercer.mjs
1958
2608
  class EventCoercer {
1959
2609
  match(err) {
1960
2610
  return isEvent(err);
@@ -1969,7 +2619,7 @@ class EventCoercer {
1969
2619
  };
1970
2620
  }
1971
2621
  }
1972
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/primitive-coercer.mjs
2622
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/primitive-coercer.mjs
1973
2623
  class PrimitiveCoercer {
1974
2624
  match(candidate) {
1975
2625
  return isPrimitive(candidate);
@@ -1983,7 +2633,7 @@ class PrimitiveCoercer {
1983
2633
  };
1984
2634
  }
1985
2635
  }
1986
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/promise-rejection-event.mjs
2636
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/promise-rejection-event.mjs
1987
2637
  class PromiseRejectionEventCoercer {
1988
2638
  match(err) {
1989
2639
  return isBuiltin(err, "PromiseRejectionEvent") || this.isCustomEventWrappingRejection(err);
@@ -2019,7 +2669,7 @@ class PromiseRejectionEventCoercer {
2019
2669
  return error;
2020
2670
  }
2021
2671
  }
2022
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/utils.mjs
2672
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/utils.mjs
2023
2673
  class ReduceableCache {
2024
2674
  constructor(_maxSize) {
2025
2675
  this._maxSize = _maxSize;
@@ -2044,7 +2694,7 @@ class ReduceableCache {
2044
2694
  }
2045
2695
  }
2046
2696
  }
2047
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/exception-steps.mjs
2697
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/exception-steps.mjs
2048
2698
  var EXCEPTION_STEP_INTERNAL_FIELDS = {
2049
2699
  MESSAGE: "$message",
2050
2700
  TIMESTAMP: "$timestamp"
@@ -2139,9 +2789,12 @@ function normalizePositiveInteger(input, fallback) {
2139
2789
  return normalized;
2140
2790
  }
2141
2791
  function normalizeAndSerializeStep(step) {
2142
- const json = safeStringify(step);
2143
- if (!json)
2792
+ let json;
2793
+ try {
2794
+ json = safeJsonStringify(step);
2795
+ } catch {
2144
2796
  return;
2797
+ }
2145
2798
  try {
2146
2799
  const parsed = JSON.parse(json);
2147
2800
  if (!isObject(parsed))
@@ -2161,33 +2814,6 @@ function normalizeAndSerializeStep(step) {
2161
2814
  return;
2162
2815
  }
2163
2816
  }
2164
- function safeStringify(value) {
2165
- const seen = new WeakSet;
2166
- try {
2167
- return JSON.stringify(value, (_key, replacementValue) => {
2168
- if (typeof replacementValue == "bigint")
2169
- return replacementValue.toString();
2170
- if (typeof replacementValue == "function" || typeof replacementValue == "symbol")
2171
- return;
2172
- if (replacementValue instanceof Date)
2173
- return replacementValue.toISOString();
2174
- if (replacementValue instanceof Error)
2175
- return {
2176
- name: replacementValue.name,
2177
- message: replacementValue.message,
2178
- stack: replacementValue.stack
2179
- };
2180
- if (replacementValue && typeof replacementValue == "object") {
2181
- if (seen.has(replacementValue))
2182
- return "[Circular]";
2183
- seen.add(replacementValue);
2184
- }
2185
- return replacementValue;
2186
- });
2187
- } catch {
2188
- return;
2189
- }
2190
- }
2191
2817
  function getUtf8ByteLength(value) {
2192
2818
  if (typeof TextEncoder != "undefined")
2193
2819
  return new TextEncoder().encode(value).length;
@@ -2201,19 +2827,65 @@ function getUtf8ByteLength(value) {
2201
2827
  byteLength += 1;
2202
2828
  return byteLength;
2203
2829
  }
2204
- // ../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/posthog-core-stateless.mjs
2830
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/release.mjs
2831
+ function getInjectedReleaseId() {
2832
+ const injected = globalThis._posthogReleaseId;
2833
+ return typeof injected == "string" && injected.length > 0 ? injected : undefined;
2834
+ }
2835
+ // ../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/posthog-core-stateless.mjs
2205
2836
  class PostHogFetchHttpError extends Error {
2206
- constructor(response, reqByteLength) {
2207
- super("HTTP error while fetching PostHog: status=" + response.status + ", reqByteLength=" + reqByteLength), this.response = response, this.reqByteLength = reqByteLength, this.name = "PostHogFetchHttpError";
2837
+ constructor(response, reqByteLength, responseBodyDeadline, abortController) {
2838
+ super("HTTP error while fetching PostHog: status=" + response.status + ", reqByteLength=" + reqByteLength), this.response = response, this.reqByteLength = reqByteLength, this.responseBodyDeadline = responseBodyDeadline, this.abortController = abortController, this.name = "PostHogFetchHttpError", this._bodyReadTimedOut = false;
2208
2839
  }
2209
2840
  get status() {
2210
2841
  return this.response.status;
2211
2842
  }
2843
+ get bodyReadTimedOut() {
2844
+ return this._bodyReadTimedOut;
2845
+ }
2212
2846
  get text() {
2213
- return this.response.text();
2847
+ if (!this.responseBodyTextPromise)
2848
+ if (Date.now() >= this.responseBodyDeadline) {
2849
+ this._bodyReadTimedOut = true;
2850
+ const timeoutError = new Error("Response body read timed out");
2851
+ timeoutError.name = "AbortError";
2852
+ this.cancelResponseBody(timeoutError);
2853
+ this.responseBodyTextPromise = Promise.reject(timeoutError);
2854
+ } else {
2855
+ const responseBodyTimeout = new Promise((_resolve, reject) => {
2856
+ this.responseBodyTimer = safeSetTimeout(() => {
2857
+ this._bodyReadTimedOut = true;
2858
+ const timeoutError = new Error("Response body read timed out");
2859
+ timeoutError.name = "AbortError";
2860
+ reject(timeoutError);
2861
+ this.cancelResponseBody(timeoutError);
2862
+ }, this.responseBodyDeadline - Date.now());
2863
+ });
2864
+ let responseBodyText;
2865
+ try {
2866
+ responseBodyText = Promise.resolve(this.response.text());
2867
+ } catch (error) {
2868
+ responseBodyText = Promise.reject(error);
2869
+ }
2870
+ this.responseBodyTextPromise = Promise.race([
2871
+ responseBodyText,
2872
+ responseBodyTimeout
2873
+ ]).finally(() => clearTimeout(this.responseBodyTimer));
2874
+ }
2875
+ return this.responseBodyTextPromise;
2214
2876
  }
2215
2877
  get json() {
2216
- return this.response.json();
2878
+ return this.text.then((text) => JSON.parse(text));
2879
+ }
2880
+ cancelResponseBody(reason) {
2881
+ clearTimeout(this.responseBodyTimer);
2882
+ if (!this.abortController.signal.aborted)
2883
+ this.abortController.abort(reason);
2884
+ (async () => {
2885
+ try {
2886
+ await this.response.body?.cancel();
2887
+ } catch {}
2888
+ })();
2217
2889
  }
2218
2890
  }
2219
2891
 
@@ -2224,12 +2896,20 @@ class PostHogFetchNetworkError extends Error {
2224
2896
  } : {}), this.error = error, this.name = "PostHogFetchNetworkError";
2225
2897
  }
2226
2898
  }
2899
+ var applyCallerFeatureFlagOverrides = (target, callerProperties) => {
2900
+ for (const key of Object.keys(callerProperties))
2901
+ if (key.startsWith("$feature/") || key === "$active_feature_flags")
2902
+ target[key] = callerProperties[key];
2903
+ };
2227
2904
  async function logFlushError(err) {
2228
2905
  if (err instanceof PostHogFetchHttpError) {
2229
2906
  let text = "";
2230
2907
  try {
2231
2908
  text = await err.text;
2232
- } catch {}
2909
+ } catch {
2910
+ if (err.bodyReadTimedOut)
2911
+ text = "<response body read timed out>";
2912
+ }
2233
2913
  console.error(`Error while flushing PostHog: message=${err.message}, response body=${text}`, err);
2234
2914
  } else
2235
2915
  console.error("Error while flushing PostHog", err);
@@ -2241,9 +2921,28 @@ function isPostHogFetchError(err) {
2241
2921
  function isPostHogFetchNetworkError(err) {
2242
2922
  return err instanceof PostHogFetchNetworkError;
2243
2923
  }
2924
+ function isRetryableFlagsFetchError(err) {
2925
+ if (err instanceof PostHogFetchHttpError)
2926
+ return err.status === 502 || err.status === 504;
2927
+ if (!(err instanceof PostHogFetchNetworkError))
2928
+ return false;
2929
+ const cause = err.error;
2930
+ const code = cause?.code ?? cause?.cause?.code;
2931
+ return code !== "ECONNREFUSED";
2932
+ }
2244
2933
  function isPostHogFetchContentTooLargeError(err) {
2245
2934
  return typeof err == "object" && err instanceof PostHogFetchHttpError && err.status === 413;
2246
2935
  }
2936
+ function isPostHogFetchRetryableError(err) {
2937
+ if (err instanceof PostHogFetchHttpError)
2938
+ return err.status === 408 || err.status === 429 || err.status >= 500;
2939
+ return isPostHogFetchNetworkError(err);
2940
+ }
2941
+ function isPostHogEventProperties(value) {
2942
+ return value !== null && typeof value == "object" && !Array.isArray(value);
2943
+ }
2944
+ var DEFAULT_QUEUE_ROUTE = "default";
2945
+
2247
2946
  class PostHogCoreStateless {
2248
2947
  getErrorPropertiesBuilder() {
2249
2948
  if (!this._errorPropertiesBuilder)
@@ -2260,6 +2959,9 @@ class PostHogCoreStateless {
2260
2959
  }
2261
2960
  constructor(apiKey, options = {}) {
2262
2961
  this.flushPromise = null;
2962
+ this.pendingFlushPromise = null;
2963
+ this.flushPromises = new Set;
2964
+ this._dequeuedMessagesCount = 0;
2263
2965
  this.shutdownPromise = null;
2264
2966
  this.promiseQueue = new PromiseQueue;
2265
2967
  this._events = new SimpleEventEmitter;
@@ -2282,10 +2984,11 @@ class PostHogCoreStateless {
2282
2984
  this._retryOptions = {
2283
2985
  retryCount: options.fetchRetryCount ?? 3,
2284
2986
  retryDelay: options.fetchRetryDelay ?? 3000,
2285
- retryCheck: isPostHogFetchError
2987
+ retryCheck: isPostHogFetchRetryableError
2286
2988
  };
2287
2989
  this.requestTimeout = options.requestTimeout ?? 1e4;
2288
2990
  this.featureFlagsRequestTimeoutMs = options.featureFlagsRequestTimeoutMs ?? 3000;
2991
+ this.featureFlagsRequestMaxRetries = options.featureFlagsRequestMaxRetries ?? 1;
2289
2992
  this.remoteConfigRequestTimeoutMs = options.remoteConfigRequestTimeoutMs ?? 3000;
2290
2993
  this.disableGeoip = options.disableGeoip ?? true;
2291
2994
  this.disabled = (options.disabled ?? false) || missingApiKey;
@@ -2347,15 +3050,23 @@ class PostHogCoreStateless {
2347
3050
  return this.disabled;
2348
3051
  }
2349
3052
  buildPayload(payload) {
3053
+ const userProperties = payload.properties || {};
3054
+ let properties = {
3055
+ ...userProperties,
3056
+ ...this.getCommonEventProperties()
3057
+ };
3058
+ applyCallerFeatureFlagOverrides(properties, userProperties);
3059
+ if (payload.event === "$feature_flag_called" && properties.$feature_flag_has_experiment === false && this.isMinimalFlagCalledEventsEnabled())
3060
+ properties = minimizeFlagCalledEventProperties(properties);
2350
3061
  return {
2351
3062
  distinct_id: payload.distinct_id,
2352
3063
  event: payload.event,
2353
- properties: {
2354
- ...payload.properties || {},
2355
- ...this.getCommonEventProperties()
2356
- }
3064
+ properties
2357
3065
  };
2358
3066
  }
3067
+ isMinimalFlagCalledEventsEnabled() {
3068
+ return false;
3069
+ }
2359
3070
  addPendingPromise(promise) {
2360
3071
  return this.promiseQueue.add(promise);
2361
3072
  }
@@ -2440,6 +3151,19 @@ class PostHogCoreStateless {
2440
3151
  this.enqueue("capture", payload, options);
2441
3152
  });
2442
3153
  }
3154
+ async groupIdentifyStatelessImmediate(groupType, groupKey, groupProperties, options, distinctId, eventProperties) {
3155
+ const payload = this.buildPayload({
3156
+ distinct_id: distinctId || `$${groupType}_${groupKey}`,
3157
+ event: "$groupidentify",
3158
+ properties: {
3159
+ $group_type: groupType,
3160
+ $group_key: groupKey,
3161
+ $group_set: groupProperties || {},
3162
+ ...eventProperties || {}
3163
+ }
3164
+ });
3165
+ await this.sendImmediate("capture", payload, options);
3166
+ }
2443
3167
  async getRemoteConfig() {
2444
3168
  await this._initPromise;
2445
3169
  let host = this.host;
@@ -2456,8 +3180,11 @@ class PostHogCoreStateless {
2456
3180
  }
2457
3181
  };
2458
3182
  return this.fetchWithRetry(url, fetchOptions, {
3183
+ type: "required",
3184
+ consume: (response) => response.json()
3185
+ }, {
2459
3186
  retryCount: 0
2460
- }, this.remoteConfigRequestTimeoutMs).then((response) => response.json()).catch((error) => {
3187
+ }, this.remoteConfigRequestTimeoutMs).catch((error) => {
2461
3188
  this._logger.error("Remote config could not be loaded", error);
2462
3189
  this._events.emit("error", error);
2463
3190
  });
@@ -2488,8 +3215,12 @@ class PostHogCoreStateless {
2488
3215
  };
2489
3216
  this._logger.info("Flags URL", url);
2490
3217
  return this.fetchWithRetry(url, fetchOptions, {
2491
- retryCount: 0
2492
- }, this.featureFlagsRequestTimeoutMs).then((response) => response.json()).then((response) => ({
3218
+ type: "required",
3219
+ consume: (response) => response.json()
3220
+ }, {
3221
+ retryCount: this.featureFlagsRequestMaxRetries,
3222
+ retryCheck: isRetryableFlagsFetchError
3223
+ }, this.featureFlagsRequestTimeoutMs).then((response) => ({
2493
3224
  success: true,
2494
3225
  response: normalizeFlagsResponse(response)
2495
3226
  })).catch((error) => {
@@ -2589,9 +3320,9 @@ class PostHogCoreStateless {
2589
3320
  }
2590
3321
  async getFeatureFlagDetailsStateless(distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip, flagKeysToEvaluate) {
2591
3322
  await this._initPromise;
2592
- const extraPayload = {};
2593
- if (disableGeoip ?? this.disableGeoip)
2594
- extraPayload["geoip_disable"] = true;
3323
+ const extraPayload = {
3324
+ geoip_disable: disableGeoip ?? this.disableGeoip
3325
+ };
2595
3326
  if (flagKeysToEvaluate)
2596
3327
  extraPayload["flag_keys_to_evaluate"] = flagKeysToEvaluate;
2597
3328
  const result = await this.getFlags(distinctId, groups, personProperties, groupProperties, extraPayload);
@@ -2628,15 +3359,18 @@ class PostHogCoreStateless {
2628
3359
  "Content-Type": "application/json"
2629
3360
  }
2630
3361
  };
2631
- const response = await this.fetchWithRetry(url, fetchOptions).then((response2) => {
2632
- if (response2.status !== 200 || !response2.json) {
2633
- const msg = `Surveys API could not be loaded: ${response2.status}`;
2634
- const error = new Error(msg);
2635
- this._logger.error(error);
2636
- this._events.emit("error", new Error(msg));
2637
- return;
3362
+ const response = await this.fetchWithRetry(url, fetchOptions, {
3363
+ type: "required",
3364
+ consume: (response2) => {
3365
+ if (response2.status !== 200 || !response2.json) {
3366
+ const msg = `Surveys API could not be loaded: ${response2.status}`;
3367
+ const error = new Error(msg);
3368
+ this._logger.error(error);
3369
+ this._events.emit("error", new Error(msg));
3370
+ return Promise.resolve(undefined);
3371
+ }
3372
+ return response2.json();
2638
3373
  }
2639
- return response2.json();
2640
3374
  }).catch((error) => {
2641
3375
  this._logger.error("Surveys API could not be loaded", error);
2642
3376
  this._events.emit("error", error);
@@ -2673,23 +3407,39 @@ class PostHogCoreStateless {
2673
3407
  return message;
2674
3408
  }
2675
3409
  async flushStorage() {}
2676
- enqueue(type, _message, options) {
3410
+ getQueueRouteKey(_message) {
3411
+ return DEFAULT_QUEUE_ROUTE;
3412
+ }
3413
+ persistedQueueKeyForRoute(_route) {
3414
+ return types_PostHogPersistedProperty.Queue;
3415
+ }
3416
+ getActiveQueueRoutes() {
3417
+ return [
3418
+ DEFAULT_QUEUE_ROUTE
3419
+ ];
3420
+ }
3421
+ getRouteQueue(route) {
3422
+ return this.getPersistedProperty(this.persistedQueueKeyForRoute(route)) || [];
3423
+ }
3424
+ enqueue(type, _message, options, explicitRoute) {
2677
3425
  this.wrap(() => {
2678
3426
  if (this.optedOut)
2679
3427
  return void this._events.emit(type, "Library is disabled. Not sending event. To re-enable, call posthog.optIn()");
2680
- let message = this.prepareMessage(type, _message, options);
3428
+ let message = this.prepareMessage(_message, options);
2681
3429
  message = this.processBeforeEnqueue(message);
2682
3430
  if (message === null)
2683
3431
  return;
2684
- const queue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
3432
+ message = this.normalizeMessage(message);
3433
+ const queueKey = this.persistedQueueKeyForRoute(explicitRoute ?? this.getQueueRouteKey(message));
3434
+ const queue = this.getPersistedProperty(queueKey) || [];
2685
3435
  if (queue.length >= this.maxQueueSize) {
2686
3436
  queue.shift();
2687
- this._logger.info("Queue is full, the oldest event is dropped.");
3437
+ this._logger.warn("Queue is full, the oldest event is dropped.");
2688
3438
  }
2689
3439
  queue.push({
2690
3440
  message
2691
3441
  });
2692
- this.setPersistedProperty(types_PostHogPersistedProperty.Queue, queue);
3442
+ this.setPersistedProperty(queueKey, queue);
2693
3443
  this._events.emit(type, message);
2694
3444
  if (queue.length >= this.flushAt)
2695
3445
  this.flushBackground();
@@ -2697,61 +3447,63 @@ class PostHogCoreStateless {
2697
3447
  this._flushTimer = safeSetTimeout(() => this.flushBackground(), this.flushInterval);
2698
3448
  });
2699
3449
  }
2700
- async sendImmediate(type, _message, options) {
3450
+ async sendImmediate(type, _message, options, explicitRoute) {
2701
3451
  if (this.disabled)
2702
3452
  return void this._logger.warn("The client is disabled");
2703
3453
  if (!this._isInitialized)
2704
3454
  await this._initPromise;
2705
3455
  if (this.optedOut)
2706
3456
  return void this._events.emit(type, "Library is disabled. Not sending event. To re-enable, call posthog.optIn()");
2707
- let message = this.prepareMessage(type, _message, options);
3457
+ let message = this.prepareMessage(_message, options);
2708
3458
  message = this.processBeforeEnqueue(message);
2709
3459
  if (message === null)
2710
3460
  return;
2711
- const data = {
2712
- api_key: this.apiKey,
2713
- batch: [
2714
- message
2715
- ],
2716
- sent_at: currentISOTime()
2717
- };
2718
- if (this.historicalMigration)
2719
- data.historical_migration = true;
2720
- const payload = JSON.stringify(data);
2721
- const url = `${this.host}/batch/`;
2722
- const gzippedPayload = this.disableCompression ? null : await gzipCompress(payload, this.isDebug);
2723
- const fetchOptions = {
2724
- method: "POST",
2725
- headers: {
2726
- ...this.getCustomHeaders(),
2727
- "Content-Type": "application/json",
2728
- ...gzippedPayload !== null && {
2729
- "Content-Encoding": "gzip"
2730
- }
2731
- },
2732
- body: gzippedPayload || payload
2733
- };
3461
+ message = this.normalizeMessage(message);
2734
3462
  try {
2735
- const response = await this.fetchWithRetry(url, fetchOptions);
2736
- await response.body?.cancel()?.catch(() => {});
3463
+ await this.sendBatch([
3464
+ message
3465
+ ], undefined, explicitRoute ?? this.getQueueRouteKey(message));
2737
3466
  } catch (err) {
2738
3467
  this._events.emit("error", err);
2739
3468
  }
2740
3469
  }
2741
- prepareMessage(type, _message, options) {
3470
+ normalizeMessage(message) {
3471
+ const { type: _type, library, library_version, ...sanitizedMessage } = message;
3472
+ let properties = isPostHogEventProperties(sanitizedMessage.properties) ? sanitizedMessage.properties : undefined;
3473
+ if (library !== undefined && properties?.$lib === undefined)
3474
+ properties = {
3475
+ ...properties || {},
3476
+ $lib: library
3477
+ };
3478
+ if (library_version !== undefined && properties?.$lib_version === undefined)
3479
+ properties = {
3480
+ ...properties || {},
3481
+ $lib_version: library_version
3482
+ };
3483
+ if (properties)
3484
+ sanitizedMessage.properties = properties;
3485
+ sanitizedMessage.uuid = getEventUuid(sanitizedMessage.uuid, uuidv7);
3486
+ return sanitizedMessage;
3487
+ }
3488
+ normalizeTimestampForWire(timestamp) {
3489
+ const parsedTimestamp = timestamp instanceof Date ? timestamp : typeof timestamp == "string" ? new Date(timestamp) : null;
3490
+ if (!parsedTimestamp || Number.isNaN(parsedTimestamp.getTime()))
3491
+ return timestamp;
3492
+ const normalized = parsedTimestamp.toISOString();
3493
+ const fractionalSeconds = typeof timestamp == "string" ? timestamp.match(/\.(\d+)(?:Z|[+-]\d{2}:?\d{2})?$/i)?.[1] : undefined;
3494
+ return fractionalSeconds && fractionalSeconds.length > 3 ? normalized.replace(/\.\d{3}Z$/, `.${fractionalSeconds}Z`) : normalized;
3495
+ }
3496
+ prepareMessage(_message, options) {
2742
3497
  const message = {
2743
3498
  ..._message,
2744
- type,
2745
- library: this.getLibraryId(),
2746
- library_version: this.getLibraryVersion(),
2747
3499
  timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
2748
- uuid: options?.uuid ? options.uuid : uuidv7()
3500
+ uuid: getEventUuid(options?.uuid, uuidv7)
2749
3501
  };
2750
3502
  const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
2751
3503
  if (addGeoipDisableProperty) {
2752
- if (!message.properties)
3504
+ if (!isPostHogEventProperties(message.properties))
2753
3505
  message.properties = {};
2754
- message["properties"]["$geoip_disable"] = true;
3506
+ message.properties["$geoip_disable"] = true;
2755
3507
  }
2756
3508
  if (message.distinctId) {
2757
3509
  message.distinct_id = message.distinctId;
@@ -2766,21 +3518,64 @@ class PostHogCoreStateless {
2766
3518
  }
2767
3519
  }
2768
3520
  flushBackground() {
3521
+ if (this.pendingFlushPromise)
3522
+ return;
2769
3523
  this.flush().catch(async (err) => {
2770
3524
  await logFlushError(err);
2771
3525
  });
2772
3526
  }
2773
- async flush() {
3527
+ async waitForPendingPromises(maxPromiseId, ignoredPromises = []) {
3528
+ const ignoredPendingPromises = ignoredPromises.filter((promise) => !!promise);
3529
+ let iteration = 0;
3530
+ while (true) {
3531
+ const promises = this.promiseQueue.getPromises([
3532
+ ...ignoredPendingPromises,
3533
+ ...this.flushPromises
3534
+ ], maxPromiseId);
3535
+ if (promises.length === 0)
3536
+ return;
3537
+ if (iteration > 0)
3538
+ this._logger.debug(`flush() re-checking ${promises.length} pending promise(s) before flushing`);
3539
+ await Promise.all(promises.map((promise) => promise.catch(() => {})));
3540
+ iteration++;
3541
+ }
3542
+ }
3543
+ flushWithPendingPromises() {
3544
+ return this.flushInternal(true);
3545
+ }
3546
+ flush() {
3547
+ return this.flushInternal(false);
3548
+ }
3549
+ flushInternal(waitForPendingPromises) {
2774
3550
  if (this.disabled)
2775
- return;
2776
- const nextFlushPromise = allSettled([
2777
- this.flushPromise
2778
- ]).then(() => this._flush());
3551
+ return Promise.resolve();
3552
+ if (!waitForPendingPromises && this.pendingFlushPromise)
3553
+ return this.pendingFlushPromise;
3554
+ const previousFlushPromise = this.flushPromise;
3555
+ const maxPromiseId = this.promiseQueue.maxId;
3556
+ const nextFlushPromise = Promise.resolve().then(() => {
3557
+ if (waitForPendingPromises)
3558
+ return this.waitForPendingPromises(maxPromiseId, [
3559
+ previousFlushPromise,
3560
+ nextFlushPromise
3561
+ ]);
3562
+ }).then(() => allSettled([
3563
+ previousFlushPromise
3564
+ ])).then(() => {
3565
+ if (this.pendingFlushPromise === nextFlushPromise)
3566
+ this.pendingFlushPromise = null;
3567
+ return this._flush();
3568
+ });
3569
+ this.pendingFlushPromise = nextFlushPromise;
2779
3570
  this.flushPromise = nextFlushPromise;
3571
+ this.flushPromises.add(nextFlushPromise);
2780
3572
  this.addPendingPromise(nextFlushPromise);
2781
3573
  allSettled([
2782
3574
  nextFlushPromise
2783
3575
  ]).then(() => {
3576
+ this.flushPromises.delete(nextFlushPromise);
3577
+ if (this.pendingFlushPromise === nextFlushPromise)
3578
+ this.pendingFlushPromise = null;
2784
3579
  if (this.flushPromise === nextFlushPromise)
2785
3580
  this.flushPromise = null;
2786
3581
  });
@@ -2793,55 +3588,102 @@ class PostHogCoreStateless {
2793
3588
  headers["User-Agent"] = customUserAgent;
2794
3589
  return headers;
2795
3590
  }
3591
+ compressPayload(payload) {
3592
+ return gzipCompress(payload, this.isDebug);
3593
+ }
3594
+ getBatchEndpointPath(_route) {
3595
+ return "/batch/";
3596
+ }
3597
+ async sendBatch(batchMessages, retryOptions, route = DEFAULT_QUEUE_ROUTE) {
3598
+ const data = {
3599
+ api_key: this.apiKey,
3600
+ batch: batchMessages.map((message) => {
3601
+ if (!message)
3602
+ return message;
3603
+ const timestamp = this.normalizeTimestampForWire(message.timestamp);
3604
+ return timestamp === message.timestamp ? message : {
3605
+ ...message,
3606
+ timestamp
3607
+ };
3608
+ }),
3609
+ sent_at: currentISOTime()
3610
+ };
3611
+ if (this.historicalMigration)
3612
+ data.historical_migration = true;
3613
+ const payload = safeJsonStringify(data);
3614
+ const url = `${this.host}${this.getBatchEndpointPath(route)}`;
3615
+ const gzippedPayload = this.disableCompression ? null : await this.compressPayload(payload);
3616
+ const fetchOptions = {
3617
+ method: "POST",
3618
+ headers: {
3619
+ ...this.getCustomHeaders(),
3620
+ "Content-Type": "application/json",
3621
+ ...gzippedPayload !== null && {
3622
+ "Content-Encoding": "gzip"
3623
+ }
3624
+ },
3625
+ body: gzippedPayload || payload
3626
+ };
3627
+ await this.fetchWithRetry(url, fetchOptions, {
3628
+ type: "successful-write"
3629
+ }, retryOptions);
3630
+ }
2796
3631
  async _flush() {
2797
3632
  this.clearFlushTimer();
2798
3633
  await this._initPromise;
2799
- let queue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
2800
- if (!queue.length)
3634
+ const routes = this.getActiveQueueRoutes();
3635
+ if (!routes.some((route) => this.getRouteQueue(route).length > 0))
2801
3636
  return;
2802
3637
  const sentMessages = [];
3638
+ let firstError;
3639
+ for (const route of routes)
3640
+ try {
3641
+ await this._flushRoute(route, sentMessages);
3642
+ } catch (err) {
3643
+ if (firstError === undefined)
3644
+ firstError = err;
3645
+ }
3646
+ if (firstError !== undefined)
3647
+ throw firstError;
3648
+ this._events.emit("flush", sentMessages);
3649
+ }
3650
+ async _flushRoute(route, sentMessages) {
3651
+ const queueKey = this.persistedQueueKeyForRoute(route);
3652
+ let queue = this.getPersistedProperty(queueKey) || [];
3653
+ if (!queue.length)
3654
+ return;
2803
3655
  const originalQueueLength = queue.length;
2804
- while (queue.length > 0 && sentMessages.length < originalQueueLength) {
3656
+ let sentFromRoute = 0;
3657
+ while (queue.length > 0 && sentFromRoute < originalQueueLength) {
2805
3658
  const batchItems = queue.slice(0, this.maxBatchSize);
2806
- const batchMessages = batchItems.map((item) => item.message);
3659
+ const batchMessages = batchItems.map((item) => item.message === undefined ? item.message : this.normalizeMessage(item.message));
2807
3660
  const persistQueueChange = async () => {
2808
- const refreshedQueue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
2809
- const newQueue = refreshedQueue.slice(batchItems.length);
2810
- this.setPersistedProperty(types_PostHogPersistedProperty.Queue, newQueue);
3661
+ const refreshedQueue = this.getPersistedProperty(queueKey) || [];
3662
+ const remainingBatchItems = [
3663
+ ...batchItems
3664
+ ];
3665
+ const newQueue = refreshedQueue.filter((item) => {
3666
+ const itemUuid = item.message?.uuid;
3667
+ const batchItemIndex = remainingBatchItems.findIndex((batchItem) => batchItem === item || typeof itemUuid == "string" && itemUuid.length > 0 && batchItem.message?.uuid === itemUuid);
3668
+ if (batchItemIndex === -1)
3669
+ return true;
3670
+ remainingBatchItems.splice(batchItemIndex, 1);
3671
+ return false;
3672
+ });
3673
+ this.setPersistedProperty(queueKey, newQueue);
2811
3674
  queue = newQueue;
3675
+ this._dequeuedMessagesCount += batchItems.length;
2812
3676
  await this.flushStorage();
2813
3677
  };
2814
- const data = {
2815
- api_key: this.apiKey,
2816
- batch: batchMessages,
2817
- sent_at: currentISOTime()
2818
- };
2819
- if (this.historicalMigration)
2820
- data.historical_migration = true;
2821
- const payload = JSON.stringify(data);
2822
- const url = `${this.host}/batch/`;
2823
- const gzippedPayload = this.disableCompression ? null : await gzipCompress(payload, this.isDebug);
2824
- const fetchOptions = {
2825
- method: "POST",
2826
- headers: {
2827
- ...this.getCustomHeaders(),
2828
- "Content-Type": "application/json",
2829
- ...gzippedPayload !== null && {
2830
- "Content-Encoding": "gzip"
2831
- }
2832
- },
2833
- body: gzippedPayload || payload
2834
- };
2835
3678
  const retryOptions = {
2836
3679
  retryCheck: (err) => {
2837
3680
  if (isPostHogFetchContentTooLargeError(err))
2838
3681
  return false;
2839
- return isPostHogFetchError(err);
3682
+ return isPostHogFetchRetryableError(err);
2840
3683
  }
2841
3684
  };
2842
3685
  try {
2843
- const response = await this.fetchWithRetry(url, fetchOptions, retryOptions);
2844
- await response.body?.cancel()?.catch(() => {});
3686
+ await this.sendBatch(batchMessages, retryOptions, route);
2845
3687
  } catch (err) {
2846
3688
  if (isPostHogFetchContentTooLargeError(err) && batchMessages.length > 1) {
2847
3689
  this.maxBatchSize = Math.max(1, Math.floor(batchMessages.length / 2));
@@ -2855,8 +3697,8 @@ class PostHogCoreStateless {
2855
3697
  }
2856
3698
  await persistQueueChange();
2857
3699
  sentMessages.push(...batchMessages);
3700
+ sentFromRoute += batchMessages.length;
2858
3701
  }
2859
- this._events.emit("flush", sentMessages);
2860
3702
  }
2861
3703
  async _sendLogsBatch(payload) {
2862
3704
  if (this.disabled)
@@ -2866,7 +3708,7 @@ class PostHogCoreStateless {
2866
3708
  };
2867
3709
  const serialized = JSON.stringify(payload);
2868
3710
  const url = `${this.host}/i/v1/logs?token=${encodeURIComponent(this.apiKey)}`;
2869
- const gzippedPayload = this.disableCompression ? null : await gzipCompress(serialized, this.isDebug);
3711
+ const gzippedPayload = this.disableCompression ? null : await this.compressPayload(serialized);
2870
3712
  const fetchOptions = {
2871
3713
  method: "POST",
2872
3714
  headers: {
@@ -2880,10 +3722,12 @@ class PostHogCoreStateless {
2880
3722
  };
2881
3723
  try {
2882
3724
  await this.fetchWithRetry(url, fetchOptions, {
3725
+ type: "successful-write"
3726
+ }, {
2883
3727
  retryCheck: (err) => {
2884
3728
  if (isPostHogFetchContentTooLargeError(err))
2885
3729
  return false;
2886
- return isPostHogFetchError(err);
3730
+ return isPostHogFetchRetryableError(err);
2887
3731
  }
2888
3732
  });
2889
3733
  return {
@@ -2905,7 +3749,56 @@ class PostHogCoreStateless {
2905
3749
  };
2906
3750
  }
2907
3751
  }
2908
- async fetchWithRetry(url, options, retryOptions, requestTimeout) {
3752
+ async _sendMetricsBatch(payload) {
3753
+ if (this.disabled)
3754
+ return {
3755
+ kind: "fatal",
3756
+ error: new Error("The client is disabled")
3757
+ };
3758
+ const serialized = JSON.stringify(payload);
3759
+ const url = `${this.host}/i/v1/metrics?token=${encodeURIComponent(this.apiKey)}`;
3760
+ const gzippedPayload = this.disableCompression ? null : await this.compressPayload(serialized);
3761
+ const fetchOptions = {
3762
+ method: "POST",
3763
+ headers: {
3764
+ ...this.getCustomHeaders(),
3765
+ "Content-Type": "application/json",
3766
+ ...gzippedPayload !== null && {
3767
+ "Content-Encoding": "gzip"
3768
+ }
3769
+ },
3770
+ body: gzippedPayload || serialized
3771
+ };
3772
+ try {
3773
+ await this.fetchWithRetry(url, fetchOptions, {
3774
+ type: "successful-write"
3775
+ }, {
3776
+ retryCheck: (err) => {
3777
+ if (isPostHogFetchContentTooLargeError(err))
3778
+ return false;
3779
+ return isPostHogFetchRetryableError(err);
3780
+ }
3781
+ });
3782
+ return {
3783
+ kind: "ok"
3784
+ };
3785
+ } catch (err) {
3786
+ if (isPostHogFetchContentTooLargeError(err))
3787
+ return {
3788
+ kind: "too-large"
3789
+ };
3790
+ if (isPostHogFetchRetryableError(err))
3791
+ return {
3792
+ kind: "retry-later",
3793
+ error: err
3794
+ };
3795
+ return {
3796
+ kind: "fatal",
3797
+ error: err
3798
+ };
3799
+ }
3800
+ }
3801
+ async fetchWithRetry(url, options, responseHandling, retryOptions, requestTimeout) {
2909
3802
  const body = options.body ? options.body : "";
2910
3803
  let reqByteLength = -1;
2911
3804
  try {
@@ -2918,28 +3811,91 @@ class PostHogCoreStateless {
2918
3811
  reqByteLength = encoded.length;
2919
3812
  }
2920
3813
  }
3814
+ const retriableOptions = {
3815
+ ...this._retryOptions,
3816
+ ...retryOptions
3817
+ };
3818
+ let attempt = 0;
2921
3819
  return await retriable(async () => {
3820
+ attempt++;
2922
3821
  const ctrl = new AbortController;
2923
3822
  const timeoutMs = requestTimeout ?? this.requestTimeout;
2924
- const timer = safeSetTimeout(() => ctrl.abort(), timeoutMs);
2925
- let res = null;
3823
+ const requestDeadline = Date.now() + timeoutMs;
3824
+ let timer;
3825
+ const deadline = new Promise((_resolve, reject) => {
3826
+ timer = safeSetTimeout(() => {
3827
+ const timeoutError = new Error(`Request timed out after ${timeoutMs}ms`);
3828
+ timeoutError.name = "AbortError";
3829
+ reject(timeoutError);
3830
+ ctrl.abort(timeoutError);
3831
+ }, timeoutMs);
3832
+ });
3833
+ let res;
3834
+ let responseAccepted = false;
3835
+ let cancellation;
3836
+ const cancelBody = () => cancellation ??= (async () => {
3837
+ try {
3838
+ await res?.body?.cancel();
3839
+ } catch {}
3840
+ })();
2926
3841
  try {
2927
- res = await this.fetch(url, {
2928
- signal: ctrl.signal,
2929
- ...options
2930
- });
2931
- } catch (e) {
2932
- throw new PostHogFetchNetworkError(e);
3842
+ let fetchPromise;
3843
+ try {
3844
+ fetchPromise = this.fetch(url, {
3845
+ signal: ctrl.signal,
3846
+ ...options
3847
+ });
3848
+ } catch (e) {
3849
+ throw new PostHogFetchNetworkError(e);
3850
+ }
3851
+ fetchPromise.then((lateResponse) => {
3852
+ if (ctrl.signal.aborted && !responseAccepted)
3853
+ Promise.resolve(lateResponse.body?.cancel()).catch(() => {});
3854
+ }).catch(() => {});
3855
+ try {
3856
+ res = await Promise.race([
3857
+ fetchPromise,
3858
+ deadline
3859
+ ]);
3860
+ responseAccepted = true;
3861
+ } catch (e) {
3862
+ throw new PostHogFetchNetworkError(e);
3863
+ }
3864
+ const isNoCors = options.mode === "no-cors";
3865
+ if (!isNoCors && (res.status < 200 || res.status >= 400))
3866
+ throw new PostHogFetchHttpError(res, reqByteLength, requestDeadline, ctrl);
3867
+ if (responseHandling.type === "successful-write") {
3868
+ try {
3869
+ await Promise.race([
3870
+ cancelBody(),
3871
+ deadline
3872
+ ]);
3873
+ } catch {}
3874
+ return;
3875
+ }
3876
+ try {
3877
+ return await Promise.race([
3878
+ responseHandling.consume(res),
3879
+ deadline
3880
+ ]);
3881
+ } catch (e) {
3882
+ if (ctrl.signal.aborted)
3883
+ throw new PostHogFetchNetworkError(e);
3884
+ throw e;
3885
+ }
2933
3886
  } finally {
2934
3887
  clearTimeout(timer);
3888
+ if (ctrl.signal.aborted && res)
3889
+ cancelBody();
2935
3890
  }
2936
- const isNoCors = options.mode === "no-cors";
2937
- if (!isNoCors && (res.status < 200 || res.status >= 400))
2938
- throw new PostHogFetchHttpError(res, reqByteLength);
2939
- return res;
2940
3891
  }, {
2941
- ...this._retryOptions,
2942
- ...retryOptions
3892
+ ...retriableOptions,
3893
+ retryCheck: (error) => {
3894
+ const shouldRetry = retriableOptions.retryCheck(error);
3895
+ if (shouldRetry && attempt <= retriableOptions.retryCount && error instanceof PostHogFetchHttpError)
3896
+ error.cancelResponseBody();
3897
+ return shouldRetry;
3898
+ }
2943
3899
  });
2944
3900
  }
2945
3901
  async _shutdown(shutdownTimeoutMs = 30000) {
@@ -2952,12 +3908,17 @@ class PostHogCoreStateless {
2952
3908
  try {
2953
3909
  await this.promiseQueue.join();
2954
3910
  while (true) {
2955
- const queue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
2956
- if (queue.length === 0)
3911
+ const hasQueuedEvents = this.getActiveQueueRoutes().some((route) => this.getRouteQueue(route).length > 0);
3912
+ if (!hasQueuedEvents)
2957
3913
  break;
3914
+ const dequeuedBeforeFlush = this._dequeuedMessagesCount;
2958
3915
  await this.flush();
2959
3916
  if (hasTimedOut)
2960
3917
  break;
3918
+ if (this._dequeuedMessagesCount === dequeuedBeforeFlush) {
3919
+ this._logger.warn("Shutdown flush completed but did not send any queued events. Stopping drain to avoid a loop.");
3920
+ break;
3921
+ }
2961
3922
  }
2962
3923
  } catch (e) {
2963
3924
  if (!isPostHogFetchError(e))
@@ -2965,21 +3926,12 @@ class PostHogCoreStateless {
2965
3926
  await logFlushError(e);
2966
3927
  }
2967
3928
  };
2968
- let timeoutHandle;
2969
- try {
2970
- return await Promise.race([
2971
- new Promise((_, reject) => {
2972
- timeoutHandle = safeSetTimeout(() => {
2973
- this._logger.error("Timed out while shutting down PostHog");
2974
- hasTimedOut = true;
2975
- reject("Timeout while shutting down PostHog. Some events may not have been sent.");
2976
- }, shutdownTimeoutMs);
2977
- }),
2978
- doShutdown()
2979
- ]);
2980
- } finally {
2981
- clearTimeout(timeoutHandle);
2982
- }
3929
+ return raceWithTimeout(doShutdown(), shutdownTimeoutMs, () => {
3930
+ this._logger.critical("Timeout while shutting down PostHog. Some events may not have been sent.", {
3931
+ shutdownTimeoutMs
3932
+ });
3933
+ hasTimedOut = true;
3934
+ });
2983
3935
  }
2984
3936
  async shutdown(shutdownTimeoutMs = 30000) {
2985
3937
  if (this.shutdownPromise)
@@ -2991,21 +3943,30 @@ class PostHogCoreStateless {
2991
3943
  return this.shutdownPromise;
2992
3944
  }
2993
3945
  }
2994
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs
2995
- import { createReadStream } from "node:fs";
3946
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs
3947
+ import { constants as constants2 } from "node:fs";
3948
+ import { open as promises_open } from "node:fs/promises";
3949
+ import { isAbsolute } from "node:path";
2996
3950
  import { createInterface } from "node:readline";
2997
3951
  var LRU_FILE_CONTENTS_CACHE = new exports_error_tracking.ReduceableCache(25);
2998
3952
  var LRU_FILE_CONTENTS_FS_READ_FAILED = new exports_error_tracking.ReduceableCache(20);
2999
3953
  var DEFAULT_LINES_OF_CONTEXT = 7;
3000
3954
  var MAX_CONTEXTLINES_COLNO = 1000;
3001
3955
  var MAX_CONTEXTLINES_LINENO = 1e4;
3002
- async function addSourceContext(frames) {
3956
+ var MAX_CONTEXTLINES_FILE_SIZE = 10485760;
3957
+ async function addSourceContext(frames, openSourceFile = promises_open, logger2) {
3003
3958
  const filesToLines = {};
3959
+ let basePath;
3960
+ try {
3961
+ basePath = process.cwd();
3962
+ } catch {}
3004
3963
  for (let i = frames.length - 1;i >= 0; i--) {
3005
3964
  const frame = frames[i];
3006
3965
  const filename = frame?.filename;
3007
3966
  if (!frame || typeof filename != "string" || typeof frame.lineno != "number" || shouldSkipContextLinesForFile(filename) || shouldSkipContextLinesForFrame(frame))
3008
3967
  continue;
3968
+ if (!isAbsolute(filename) && basePath === undefined)
3969
+ continue;
3009
3970
  const filesToLinesOutput = filesToLines[filename];
3010
3971
  if (!filesToLinesOutput)
3011
3972
  filesToLines[filename] = [];
@@ -3016,50 +3977,98 @@ async function addSourceContext(frames) {
3016
3977
  return frames;
3017
3978
  const readlinePromises = [];
3018
3979
  for (const file of files) {
3019
- if (LRU_FILE_CONTENTS_FS_READ_FAILED.get(file))
3980
+ const cacheKey = makeSourceCacheKey(file, basePath);
3981
+ if (cacheKey === undefined)
3982
+ continue;
3983
+ if (LRU_FILE_CONTENTS_FS_READ_FAILED.get(cacheKey))
3020
3984
  continue;
3021
3985
  const filesToLineRanges = filesToLines[file];
3022
3986
  if (!filesToLineRanges)
3023
3987
  continue;
3024
3988
  filesToLineRanges.sort((a, b) => a - b);
3025
3989
  const ranges = makeLineReaderRanges(filesToLineRanges);
3026
- if (ranges.every((r) => rangeExistsInContentCache(file, r)))
3990
+ if (ranges.every((r) => rangeExistsInContentCache(cacheKey, r)))
3027
3991
  continue;
3028
- const cache = emplace(LRU_FILE_CONTENTS_CACHE, file, {});
3029
- readlinePromises.push(getContextLinesFromFile(file, ranges, cache));
3992
+ const cache = emplace(LRU_FILE_CONTENTS_CACHE, cacheKey, {});
3993
+ readlinePromises.push(getContextLinesFromFile(file, ranges, cache, cacheKey, openSourceFile, logger2));
3030
3994
  }
3031
3995
  await Promise.all(readlinePromises).catch(() => {});
3032
3996
  if (frames && frames.length > 0)
3033
- addSourceContextToFrames(frames, LRU_FILE_CONTENTS_CACHE);
3997
+ addSourceContextToFrames(frames, LRU_FILE_CONTENTS_CACHE, basePath);
3034
3998
  LRU_FILE_CONTENTS_CACHE.reduce();
3035
3999
  return frames;
3036
4000
  }
3037
- function getContextLinesFromFile(path2, ranges, output) {
4001
+ async function openRegularSourceFile(path2, openSourceFile, logger2) {
4002
+ let fileHandle;
4003
+ let isValid = false;
4004
+ try {
4005
+ fileHandle = await openSourceFile(path2, constants2.O_RDONLY | constants2.O_NONBLOCK);
4006
+ const fileStat = await fileHandle.stat();
4007
+ if (!fileStat.isFile())
4008
+ return;
4009
+ if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE)
4010
+ return void logger2?.debug(`Skipping source context for oversized file ${path2}: ${fileStat.size} bytes exceeds ${MAX_CONTEXTLINES_FILE_SIZE}`);
4011
+ isValid = true;
4012
+ return fileHandle;
4013
+ } catch {
4014
+ return;
4015
+ } finally {
4016
+ if (fileHandle && !isValid)
4017
+ await fileHandle.close().catch(() => {});
4018
+ }
4019
+ }
4020
+ async function getContextLinesFromFile(path2, ranges, output, cacheKey, openSourceFile, logger2) {
4021
+ const fileHandle = await openRegularSourceFile(path2, openSourceFile, logger2);
4022
+ if (fileHandle === undefined)
4023
+ return void LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
4024
+ const openedFileHandle = fileHandle;
3038
4025
  return new Promise((resolve) => {
3039
- const stream = createReadStream(path2);
3040
- const lineReaded = createInterface({
3041
- input: stream
3042
- });
3043
- function destroyStreamAndResolve() {
3044
- stream.destroy();
3045
- resolve();
4026
+ let finished = false;
4027
+ function destroyStreamAndResolve(stream2) {
4028
+ if (finished)
4029
+ return;
4030
+ finished = true;
4031
+ stream2?.destroy();
4032
+ openedFileHandle.close().then(resolve, resolve);
4033
+ }
4034
+ let stream;
4035
+ try {
4036
+ stream = openedFileHandle.createReadStream({
4037
+ autoClose: false,
4038
+ start: 0,
4039
+ end: MAX_CONTEXTLINES_FILE_SIZE - 1
4040
+ });
4041
+ } catch {
4042
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
4043
+ destroyStreamAndResolve();
4044
+ return;
4045
+ }
4046
+ let lineReaded;
4047
+ try {
4048
+ lineReaded = createInterface({
4049
+ input: stream
4050
+ });
4051
+ } catch {
4052
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
4053
+ destroyStreamAndResolve(stream);
4054
+ return;
3046
4055
  }
3047
4056
  let lineNumber = 0;
3048
4057
  let currentRangeIndex = 0;
3049
4058
  const range = ranges[currentRangeIndex];
3050
4059
  if (range === undefined)
3051
- return void destroyStreamAndResolve();
4060
+ return void destroyStreamAndResolve(stream);
3052
4061
  let rangeStart = range[0];
3053
4062
  let rangeEnd = range[1];
3054
4063
  function onStreamError() {
3055
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path2, 1);
4064
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
3056
4065
  lineReaded.close();
3057
4066
  lineReaded.removeAllListeners();
3058
- destroyStreamAndResolve();
4067
+ destroyStreamAndResolve(stream);
3059
4068
  }
3060
4069
  stream.on("error", onStreamError);
3061
4070
  lineReaded.on("error", onStreamError);
3062
- lineReaded.on("close", destroyStreamAndResolve);
4071
+ lineReaded.on("close", () => destroyStreamAndResolve(stream));
3063
4072
  lineReaded.on("line", (line) => {
3064
4073
  lineNumber++;
3065
4074
  if (lineNumber < rangeStart)
@@ -3084,10 +4093,11 @@ function getContextLinesFromFile(path2, ranges, output) {
3084
4093
  });
3085
4094
  });
3086
4095
  }
3087
- function addSourceContextToFrames(frames, cache) {
4096
+ function addSourceContextToFrames(frames, cache, basePath) {
3088
4097
  for (const frame of frames)
3089
4098
  if (frame.filename && frame.context_line === undefined && typeof frame.lineno == "number") {
3090
- const contents = cache.get(frame.filename);
4099
+ const cacheKey = makeSourceCacheKey(frame.filename, basePath);
4100
+ const contents = cacheKey === undefined ? undefined : cache.get(cacheKey);
3091
4101
  if (contents === undefined)
3092
4102
  continue;
3093
4103
  addContextToFrame(frame.lineno, frame, contents);
@@ -3130,8 +4140,19 @@ function shouldSkipContextLinesForFrame(frame) {
3130
4140
  return true;
3131
4141
  return false;
3132
4142
  }
3133
- function rangeExistsInContentCache(file, range) {
3134
- const contents = LRU_FILE_CONTENTS_CACHE.get(file);
4143
+ function makeSourceCacheKey(path2, basePath) {
4144
+ if (isAbsolute(path2))
4145
+ return JSON.stringify([
4146
+ null,
4147
+ path2
4148
+ ]);
4149
+ return basePath === undefined ? undefined : JSON.stringify([
4150
+ basePath,
4151
+ path2
4152
+ ]);
4153
+ }
4154
+ function rangeExistsInContentCache(cacheKey, range) {
4155
+ const contents = LRU_FILE_CONTENTS_CACHE.get(cacheKey);
3135
4156
  if (contents === undefined)
3136
4157
  return false;
3137
4158
  for (let i = range[0];i <= range[1]; i++)
@@ -3209,8 +4230,8 @@ function snipLine(line, colno) {
3209
4230
  return newLine;
3210
4231
  }
3211
4232
 
3212
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/relative-path.node.mjs
3213
- import { isAbsolute, relative, sep as sep2 } from "node:path";
4233
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/relative-path.node.mjs
4234
+ import { isAbsolute as isAbsolute2, relative, sep as sep2 } from "node:path";
3214
4235
  function createRelativePathModifier(basePath = process.cwd()) {
3215
4236
  const isWindows = sep2 === "\\";
3216
4237
  const toUnix = (p) => isWindows ? p.replace(/\\/g, "/") : p;
@@ -3218,17 +4239,17 @@ function createRelativePathModifier(basePath = process.cwd()) {
3218
4239
  return async (frames) => {
3219
4240
  for (const frame of frames)
3220
4241
  if (!(!frame.filename || frame.filename.startsWith("node:") || frame.filename.startsWith("data:"))) {
3221
- if (isAbsolute(frame.filename))
4242
+ if (isAbsolute2(frame.filename))
3222
4243
  frame.filename = toUnix(relative(normalizedBase, toUnix(frame.filename)));
3223
4244
  }
3224
4245
  return frames;
3225
4246
  };
3226
4247
  }
3227
4248
 
3228
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/version.mjs
3229
- var version = "5.35.12";
4249
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/version.mjs
4250
+ var version = "5.49.2";
3230
4251
 
3231
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/types.mjs
4252
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/types.mjs
3232
4253
  var FeatureFlagError2 = {
3233
4254
  ERRORS_WHILE_COMPUTING: "errors_while_computing_flags",
3234
4255
  FLAG_MISSING: "flag_missing",
@@ -3236,7 +4257,7 @@ var FeatureFlagError2 = {
3236
4257
  UNKNOWN_ERROR: "unknown_error"
3237
4258
  };
3238
4259
 
3239
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/feature-flag-evaluations.mjs
4260
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/feature-flag-evaluations.mjs
3240
4261
  class FeatureFlagEvaluations {
3241
4262
  constructor(init) {
3242
4263
  this._host = init.host;
@@ -3345,6 +4366,8 @@ class FeatureFlagEvaluations {
3345
4366
  $feature_flag_request_id: this._requestId,
3346
4367
  $feature_flag_evaluated_at: flag?.locallyEvaluated ? Date.now() : this._evaluatedAt
3347
4368
  };
4369
+ if (flag?.hasExperiment !== undefined)
4370
+ properties.$feature_flag_has_experiment = flag.hasExperiment;
3348
4371
  if (flag?.locallyEvaluated && this._flagDefinitionsLoadedAt !== undefined)
3349
4372
  properties.$feature_flag_definitions_loaded_at = this._flagDefinitionsLoadedAt;
3350
4373
  const errors = [];
@@ -3367,7 +4390,7 @@ class FeatureFlagEvaluations {
3367
4390
  }
3368
4391
  }
3369
4392
 
3370
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/feature-flags/crypto.mjs
4393
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/feature-flags/crypto.mjs
3371
4394
  async function hashSHA1(text) {
3372
4395
  const subtle = globalThis.crypto?.subtle;
3373
4396
  if (!subtle)
@@ -3377,7 +4400,7 @@ async function hashSHA1(text) {
3377
4400
  return hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
3378
4401
  }
3379
4402
 
3380
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/feature-flags/feature-flags.mjs
4403
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/feature-flags/feature-flags.mjs
3381
4404
  var SIXTY_SECONDS = 60000;
3382
4405
  var LONG_SCALE = 1152921504606847000;
3383
4406
  var NULL_VALUES_ALLOWED_OPERATORS = [
@@ -3394,22 +4417,23 @@ class ClientError extends Error {
3394
4417
  Object.setPrototypeOf(this, ClientError.prototype);
3395
4418
  }
3396
4419
  }
4420
+ function setCustomErrorPrototype(error, constructor) {
4421
+ error.name = constructor.name;
4422
+ Error.captureStackTrace(error, constructor);
4423
+ Object.setPrototypeOf(error, constructor.prototype);
4424
+ }
3397
4425
 
3398
4426
  class InconclusiveMatchError extends Error {
3399
4427
  constructor(message) {
3400
4428
  super(message);
3401
- this.name = this.constructor.name;
3402
- Error.captureStackTrace(this, this.constructor);
3403
- Object.setPrototypeOf(this, InconclusiveMatchError.prototype);
4429
+ setCustomErrorPrototype(this, InconclusiveMatchError);
3404
4430
  }
3405
4431
  }
3406
4432
 
3407
4433
  class RequiresServerEvaluation extends Error {
3408
4434
  constructor(message) {
3409
4435
  super(message);
3410
- this.name = this.constructor.name;
3411
- Error.captureStackTrace(this, this.constructor);
3412
- Object.setPrototypeOf(this, RequiresServerEvaluation.prototype);
4436
+ setCustomErrorPrototype(this, RequiresServerEvaluation);
3413
4437
  }
3414
4438
  }
3415
4439
 
@@ -3418,6 +4442,7 @@ class FeatureFlagsPoller {
3418
4442
  this.debugMode = false;
3419
4443
  this.shouldBeginExponentialBackoff = false;
3420
4444
  this.backOffCount = 0;
4445
+ this.pollerStopped = false;
3421
4446
  this.pollingInterval = pollingInterval;
3422
4447
  this.personalApiKey = personalApiKey;
3423
4448
  this.featureFlags = [];
@@ -3433,6 +4458,7 @@ class FeatureFlagsPoller {
3433
4458
  this.onError = options.onError;
3434
4459
  this.customHeaders = customHeaders;
3435
4460
  this.onLoad = options.onLoad;
4461
+ this.onMinimalFlagCalledEvents = options.onMinimalFlagCalledEvents;
3436
4462
  this.cacheProvider = options.cacheProvider;
3437
4463
  this.strictLocalEvaluation = options.strictLocalEvaluation ?? false;
3438
4464
  this.loadFeatureFlags();
@@ -3630,6 +4656,7 @@ class FeatureFlagsPoller {
3630
4656
  const flagFilters = flag.filters || {};
3631
4657
  const flagConditions = flagFilters.groups || [];
3632
4658
  const flagAggregation = flagFilters.aggregation_group_type_index;
4659
+ const earlyExitEnabled = flagFilters.early_exit ?? false;
3633
4660
  const { groups, groupProperties } = evaluationContext;
3634
4661
  let isInconclusive = false;
3635
4662
  let result;
@@ -3653,12 +4680,15 @@ class FeatureFlagsPoller {
3653
4680
  effectiveBucketingValue = groups[groupName];
3654
4681
  }
3655
4682
  }
3656
- if (await this.isConditionMatch(flag, effectiveBucketingValue, condition, effectiveProperties, evaluationContext)) {
4683
+ const matchResult = await this.isConditionMatch(flag, effectiveBucketingValue, condition, effectiveProperties, evaluationContext);
4684
+ if (matchResult === "match") {
3657
4685
  const variantOverride = condition.variant;
3658
4686
  const flagVariants = flagFilters.multivariate?.variants || [];
3659
4687
  result = variantOverride && flagVariants.some((variant) => variant.key === variantOverride) ? variantOverride : await this.getMatchingVariant(flag, effectiveBucketingValue) || true;
3660
4688
  break;
3661
4689
  }
4690
+ if (earlyExitEnabled && matchResult === "out_of_rollout_bound")
4691
+ return false;
3662
4692
  } catch (e) {
3663
4693
  if (e instanceof RequiresServerEvaluation)
3664
4694
  throw e;
@@ -3682,16 +4712,20 @@ class FeatureFlagsPoller {
3682
4712
  for (const prop of condition.properties) {
3683
4713
  const propertyType = prop.type;
3684
4714
  let matches = false;
3685
- matches = propertyType === "cohort" ? await matchCohort(prop, properties, this.cohorts, this.debugMode, (depProp) => this.evaluateFlagDependency(depProp, properties, evaluationContext)) : propertyType === "flag" ? await this.evaluateFlagDependency(prop, properties, evaluationContext) : matchProperty(prop, properties, warnFunction);
4715
+ if (propertyType === "cohort") {
4716
+ const inCohort = await matchCohort(prop, properties, this.cohorts, this.debugMode, (depProp) => this.evaluateFlagDependency(depProp, properties, evaluationContext));
4717
+ matches = prop.operator === "not_in" ? !inCohort : inCohort;
4718
+ } else
4719
+ matches = propertyType === "flag" ? await this.evaluateFlagDependency(prop, properties, evaluationContext) : matchProperty(prop, properties, warnFunction);
3686
4720
  if (!matches)
3687
- return false;
4721
+ return "no_match";
3688
4722
  }
3689
4723
  if (rolloutPercentage == undefined)
3690
- return true;
4724
+ return "match";
3691
4725
  }
3692
4726
  if (rolloutPercentage != null && await _hash(flag.key, bucketingValue) > rolloutPercentage / 100)
3693
- return false;
3694
- return true;
4727
+ return "out_of_rollout_bound";
4728
+ return "match";
3695
4729
  }
3696
4730
  async getMatchingVariant(flag, bucketingValue) {
3697
4731
  const hashValue = await _hash(flag.key, bucketingValue, "variant");
@@ -3722,6 +4756,7 @@ class FeatureFlagsPoller {
3722
4756
  this.groupTypeMapping = flagData.groupTypeMapping;
3723
4757
  this.cohorts = flagData.cohorts;
3724
4758
  this.loadedSuccessfullyOnce = true;
4759
+ this.onMinimalFlagCalledEvents?.(flagData.minimalFlagCalledEvents === true);
3725
4760
  }
3726
4761
  warnAboutExperienceContinuityFlags(flags) {
3727
4762
  if (this.strictLocalEvaluation)
@@ -3785,7 +4820,6 @@ class FeatureFlagsPoller {
3785
4820
  clearTimeout(this.poller);
3786
4821
  this.poller = undefined;
3787
4822
  }
3788
- this.poller = setTimeout(() => this.loadFeatureFlags(true), this.getPollingInterval());
3789
4823
  try {
3790
4824
  let shouldFetch = true;
3791
4825
  if (this.cacheProvider)
@@ -3813,17 +4847,18 @@ class FeatureFlagsPoller {
3813
4847
  return;
3814
4848
  case 401:
3815
4849
  this.beginBackoff();
3816
- throw new ClientError(`Your project key or personal API key is invalid. Setting next polling interval to ${this.getPollingInterval()}ms. More information: https://posthog.com/docs/api#rate-limiting`);
4850
+ throw new ClientError(`Your project key or secret key is invalid. Setting next polling interval to ${this.getPollingInterval()}ms. More information: https://posthog.com/docs/api#rate-limiting`);
3817
4851
  case 402:
3818
4852
  console.warn("[FEATURE FLAGS] Feature flags quota limit exceeded - unsetting all local flags. Learn more about billing limits at https://posthog.com/docs/billing/limits-alerts");
3819
4853
  this.featureFlags = [];
3820
4854
  this.featureFlagsByKey = {};
3821
4855
  this.groupTypeMapping = {};
3822
4856
  this.cohorts = {};
4857
+ this.onMinimalFlagCalledEvents?.(false);
3823
4858
  return;
3824
4859
  case 403:
3825
4860
  this.beginBackoff();
3826
- throw new ClientError(`Your personal API key does not have permission to fetch feature flag definitions for local evaluation. Setting next polling interval to ${this.getPollingInterval()}ms. Are you sure you're using the correct personal and Project API key pair? More information: https://posthog.com/docs/api/overview`);
4861
+ throw new ClientError(`Your secret key does not have permission to fetch feature flag definitions for local evaluation. Setting next polling interval to ${this.getPollingInterval()}ms. Are you sure you're using the correct secret and Project API key pair? More information: https://posthog.com/docs/api/overview`);
3827
4862
  case 429:
3828
4863
  this.beginBackoff();
3829
4864
  throw new ClientError(`You are being rate limited. Setting next polling interval to ${this.getPollingInterval()}ms. More information: https://posthog.com/docs/api#rate-limiting`);
@@ -3835,7 +4870,8 @@ class FeatureFlagsPoller {
3835
4870
  const flagData = {
3836
4871
  flags: responseJson.flags ?? [],
3837
4872
  groupTypeMapping: responseJson.group_type_mapping || {},
3838
- cohorts: responseJson.cohorts || {}
4873
+ cohorts: responseJson.cohorts || {},
4874
+ minimalFlagCalledEvents: responseJson.minimal_flag_called_events === true
3839
4875
  };
3840
4876
  this.updateFlagState(flagData);
3841
4877
  this.flagDefinitionsLoadedAt = Date.now();
@@ -3856,6 +4892,9 @@ class FeatureFlagsPoller {
3856
4892
  } catch (err) {
3857
4893
  if (err instanceof ClientError)
3858
4894
  this.onError?.(err);
4895
+ } finally {
4896
+ if (!this.pollerStopped)
4897
+ this.poller = setTimeout(() => this.loadFeatureFlags(true), this.getPollingInterval());
3859
4898
  }
3860
4899
  }
3861
4900
  getPersonalApiKeyRequestOptions(method = "GET", etag) {
@@ -3871,7 +4910,7 @@ class FeatureFlagsPoller {
3871
4910
  headers
3872
4911
  };
3873
4912
  }
3874
- _requestFeatureFlagDefinitions() {
4913
+ async _requestFeatureFlagDefinitions() {
3875
4914
  const url = `${this.host}/flags/definitions?token=${this.projectApiKey}&send_cohorts`;
3876
4915
  const options = this.getPersonalApiKeyRequestOptions("GET", this.flagsEtag);
3877
4916
  let abortTimeout = null;
@@ -3882,23 +4921,49 @@ class FeatureFlagsPoller {
3882
4921
  }, this.timeout);
3883
4922
  options.signal = controller.signal;
3884
4923
  }
4924
+ const clearAbortTimeout = () => clearTimeout(abortTimeout);
3885
4925
  try {
3886
4926
  const fetch1 = this.fetch;
3887
- return fetch1(url, options);
3888
- } finally {
3889
- clearTimeout(abortTimeout);
4927
+ const res = await fetch1(url, options);
4928
+ if (res.status !== 200) {
4929
+ clearAbortTimeout();
4930
+ return res;
4931
+ }
4932
+ return {
4933
+ status: res.status,
4934
+ headers: res.headers,
4935
+ body: res.body,
4936
+ text: async () => {
4937
+ try {
4938
+ return await res.text();
4939
+ } finally {
4940
+ clearAbortTimeout();
4941
+ }
4942
+ },
4943
+ json: async () => {
4944
+ try {
4945
+ return await res.json();
4946
+ } finally {
4947
+ clearAbortTimeout();
4948
+ }
4949
+ }
4950
+ };
4951
+ } catch (err) {
4952
+ clearAbortTimeout();
4953
+ throw err;
3890
4954
  }
3891
4955
  }
3892
4956
  async stopPoller(timeoutMs = 30000) {
4957
+ this.pollerStopped = true;
3893
4958
  clearTimeout(this.poller);
4959
+ this.poller = undefined;
3894
4960
  if (this.cacheProvider)
3895
4961
  try {
3896
4962
  const shutdownResult = this.cacheProvider.shutdown();
3897
4963
  if (shutdownResult instanceof Promise)
3898
- await Promise.race([
3899
- shutdownResult,
3900
- new Promise((_, reject) => setTimeout(() => reject(new Error(`Cache shutdown timeout after ${timeoutMs}ms`)), timeoutMs))
3901
- ]);
4964
+ await raceWithTimeout(shutdownResult, timeoutMs, () => {
4965
+ throw new Error(`Cache shutdown timeout after ${timeoutMs}ms`);
4966
+ });
3902
4967
  } catch (err) {
3903
4968
  this.onError?.(new Error(`Error during cache shutdown: ${err}`));
3904
4969
  }
@@ -3953,6 +5018,14 @@ function matchProperty(property, propertyValues, warnFunction) {
3953
5018
  return String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
3954
5019
  case "not_icontains":
3955
5020
  return !String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
5021
+ case "starts_with":
5022
+ return String(overrideValue).toLowerCase().startsWith(String(value).toLowerCase());
5023
+ case "not_starts_with":
5024
+ return !String(overrideValue).toLowerCase().startsWith(String(value).toLowerCase());
5025
+ case "ends_with":
5026
+ return String(overrideValue).toLowerCase().endsWith(String(value).toLowerCase());
5027
+ case "not_ends_with":
5028
+ return !String(overrideValue).toLowerCase().endsWith(String(value).toLowerCase());
3956
5029
  case "regex":
3957
5030
  return isValidRegex(String(value)) && String(overrideValue).match(String(value)) !== null;
3958
5031
  case "not_regex":
@@ -4279,19 +5352,75 @@ function relativeDateParseForFeatureFlagMatching(value) {
4279
5352
  }
4280
5353
  }
4281
5354
 
4282
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/autocapture.mjs
5355
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/autocapture.mjs
5356
+ var UNHANDLED_REJECTION_OPTION_NAMES = [
5357
+ "--unhandled-rejections",
5358
+ "--unhandled_rejections"
5359
+ ];
5360
+ var UNHANDLED_REJECTION_MODES = new Set([
5361
+ "throw",
5362
+ "strict",
5363
+ "warn",
5364
+ "warn-with-error-code",
5365
+ "none"
5366
+ ]);
5367
+ var STARTUP_EXEC_ARGV = [
5368
+ ...globalThis.process?.execArgv ?? []
5369
+ ];
5370
+ var STARTUP_NODE_OPTIONS = globalThis.process?.env?.NODE_OPTIONS;
5371
+ function splitNodeOptions(nodeOptions) {
5372
+ const args = [];
5373
+ let current = "";
5374
+ let isInString = false;
5375
+ for (let index = 0;index < nodeOptions.length; index++) {
5376
+ const character = nodeOptions[index];
5377
+ if (character === "\\" && isInString && index + 1 < nodeOptions.length)
5378
+ current += nodeOptions[++index];
5379
+ else if (character !== " " || isInString)
5380
+ if (character === '"')
5381
+ isInString = !isInString;
5382
+ else
5383
+ current += character;
5384
+ else if (current) {
5385
+ args.push(current);
5386
+ current = "";
5387
+ }
5388
+ }
5389
+ if (current)
5390
+ args.push(current);
5391
+ return args;
5392
+ }
5393
+ function findUnhandledRejectionMode(args) {
5394
+ let mode;
5395
+ for (let index = 0;index < args.length; index++) {
5396
+ const argument = args[index];
5397
+ const optionName = UNHANDLED_REJECTION_OPTION_NAMES.find((name) => argument === name || argument.startsWith(`${name}=`));
5398
+ if (!optionName)
5399
+ continue;
5400
+ const value = argument === optionName ? args[++index] : argument.slice(optionName.length + 1);
5401
+ if (UNHANDLED_REJECTION_MODES.has(value))
5402
+ mode = value;
5403
+ }
5404
+ return mode;
5405
+ }
5406
+ function getUnhandledRejectionMode(execArgv = STARTUP_EXEC_ARGV, nodeOptions = STARTUP_NODE_OPTIONS) {
5407
+ return findUnhandledRejectionMode(execArgv) ?? findUnhandledRejectionMode(splitNodeOptions(nodeOptions ?? "")) ?? "throw";
5408
+ }
5409
+ var STARTUP_UNHANDLED_REJECTION_MODE = getUnhandledRejectionMode();
5410
+ function captureUncaughtException(captureFn, error, origin) {
5411
+ captureFn(error, {
5412
+ mechanism: {
5413
+ type: origin === "unhandledRejection" ? "onunhandledrejection" : "onuncaughtexception",
5414
+ handled: false
5415
+ }
5416
+ });
5417
+ }
4283
5418
  function makeUncaughtExceptionHandler(captureFn, onFatalFn) {
4284
5419
  let calledFatalError = false;
4285
- return Object.assign((error) => {
5420
+ return Object.assign((error, origin) => {
4286
5421
  const userProvidedListenersCount = global.process.listeners("uncaughtException").filter((listener) => listener.name !== "domainUncaughtExceptionClear" && listener._posthogErrorHandler !== true).length;
4287
- const processWouldExit = userProvidedListenersCount === 0;
4288
- captureFn(error, {
4289
- mechanism: {
4290
- type: "onuncaughtexception",
4291
- handled: false
4292
- }
4293
- });
4294
- if (!calledFatalError && processWouldExit) {
5422
+ captureUncaughtException(captureFn, error, origin);
5423
+ if (!calledFatalError && userProvidedListenersCount === 0) {
4295
5424
  calledFatalError = true;
4296
5425
  onFatalFn(error);
4297
5426
  }
@@ -4299,29 +5428,38 @@ function makeUncaughtExceptionHandler(captureFn, onFatalFn) {
4299
5428
  _posthogErrorHandler: true
4300
5429
  });
4301
5430
  }
4302
- function addUncaughtExceptionListener(captureFn, onFatalFn) {
4303
- globalThis.process?.on("uncaughtException", makeUncaughtExceptionHandler(captureFn, onFatalFn));
5431
+ function addUncaughtExceptionListener(captureFn, onFatalFn, mode = STARTUP_UNHANDLED_REJECTION_MODE) {
5432
+ const process2 = globalThis.process;
5433
+ if (!process2)
5434
+ return;
5435
+ if (mode === "strict")
5436
+ return void process2.on("uncaughtExceptionMonitor", (error, origin) => captureUncaughtException(captureFn, error, origin));
5437
+ process2.on("uncaughtException", makeUncaughtExceptionHandler(captureFn, onFatalFn));
4304
5438
  }
4305
- function addUnhandledRejectionListener(captureFn) {
4306
- globalThis.process?.on("unhandledRejection", (reason) => captureFn(reason, {
4307
- mechanism: {
4308
- type: "onunhandledrejection",
4309
- handled: false
4310
- }
4311
- }));
5439
+ function addUnhandledRejectionListener(captureFn, mode = STARTUP_UNHANDLED_REJECTION_MODE) {
5440
+ const process2 = globalThis.process;
5441
+ if (!process2 || mode === "throw" || mode === "strict" || mode === "warn-with-error-code")
5442
+ return;
5443
+ process2.on("unhandledRejection", (reason) => {
5444
+ captureFn(reason, {
5445
+ mechanism: {
5446
+ type: "onunhandledrejection",
5447
+ handled: false
5448
+ }
5449
+ });
5450
+ });
4312
5451
  }
4313
5452
 
4314
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/index.mjs
5453
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/index.mjs
4315
5454
  var SHUTDOWN_TIMEOUT = 2000;
4316
5455
 
4317
- class ErrorTracking {
5456
+ class error_tracking_ErrorTracking {
4318
5457
  constructor(client, options, _logger) {
4319
5458
  this.client = client;
4320
5459
  this._exceptionAutocaptureEnabled = options.enableExceptionAutocapture || false;
4321
5460
  this._logger = _logger;
4322
5461
  this._rateLimiter = new BucketedRateLimiter({
4323
- refillRate: 1,
4324
- bucketSize: 10,
5462
+ ...resolveExceptionRateLimiterConfig(options),
4325
5463
  refillInterval: 1e4,
4326
5464
  _logger: this._logger
4327
5465
  });
@@ -4336,6 +5474,9 @@ class ErrorTracking {
4336
5474
  };
4337
5475
  const exceptionProperties = builder.buildFromUnknown(error, hint);
4338
5476
  exceptionProperties.$exception_list = await builder.modifyFrames(exceptionProperties.$exception_list);
5477
+ const injectedReleaseId = exports_error_tracking.getInjectedReleaseId();
5478
+ if (injectedReleaseId)
5479
+ properties.$release_id = injectedReleaseId;
4339
5480
  return {
4340
5481
  event: "$exception",
4341
5482
  distinctId,
@@ -4354,8 +5495,8 @@ class ErrorTracking {
4354
5495
  }
4355
5496
  onException(exception, hint) {
4356
5497
  this.client.addPendingPromise((async () => {
4357
- if (!ErrorTracking.isPreviouslyCapturedError(exception)) {
4358
- const eventMessage = await ErrorTracking.buildEventMessage(this.client.getErrorPropertiesBuilder(), exception, hint);
5498
+ if (!error_tracking_ErrorTracking.isPreviouslyCapturedError(exception)) {
5499
+ const eventMessage = await error_tracking_ErrorTracking.buildEventMessage(this.client.getErrorPropertiesBuilder(), exception, hint);
4359
5500
  const exceptionProperties = eventMessage.properties;
4360
5501
  const exceptionType = exceptionProperties?.$exception_list[0]?.type ?? "Exception";
4361
5502
  const isRateLimited = this._rateLimiter.consumeRateLimit(exceptionType);
@@ -4363,14 +5504,14 @@ class ErrorTracking {
4363
5504
  return void this._logger.info("Skipping exception capture because of client rate limiting.", {
4364
5505
  exception: exceptionType
4365
5506
  });
4366
- return this.client.capture(eventMessage);
5507
+ return this.client._capturePreparedEvent(eventMessage, false);
4367
5508
  }
4368
5509
  })());
4369
5510
  }
4370
5511
  async onFatalError(exception) {
4371
5512
  console.error(exception);
4372
5513
  await this.client.shutdown(SHUTDOWN_TIMEOUT);
4373
- process.exit(1);
5514
+ globalThis.process.exit(1);
4374
5515
  }
4375
5516
  isEnabled() {
4376
5517
  return !this.client.isDisabled && this._exceptionAutocaptureEnabled;
@@ -4380,7 +5521,7 @@ class ErrorTracking {
4380
5521
  }
4381
5522
  }
4382
5523
 
4383
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/storage-memory.mjs
5524
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/storage-memory.mjs
4384
5525
  class PostHogMemoryStorage {
4385
5526
  getProperty(key) {
4386
5527
  return this._memoryStorage[key];
@@ -4393,7 +5534,452 @@ class PostHogMemoryStorage {
4393
5534
  }
4394
5535
  }
4395
5536
 
4396
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/client.mjs
5537
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/config.mjs
5538
+ function isCaptureMode(value) {
5539
+ return value === "v0" || value === "v1";
5540
+ }
5541
+ function resolveCaptureMode() {
5542
+ const envMode = typeof process != "undefined" ? process.env?.POSTHOG_CAPTURE_MODE : undefined;
5543
+ return isCaptureMode(envMode) ? envMode : "v0";
5544
+ }
5545
+
5546
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/routing.mjs
5547
+ var AI_EVENT_PREFIX = "$ai_";
5548
+ var ANALYTICS_ROUTE = "analytics";
5549
+ var AI_ROUTE = "ai";
5550
+ function isLegacyOnlyEvent(message) {
5551
+ return typeof message.event == "string" && message.event.startsWith(AI_EVENT_PREFIX);
5552
+ }
5553
+
5554
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/errors.mjs
5555
+ class CaptureV1Error extends Error {
5556
+ constructor({ requestId, drops, retryExhausted, cause }) {
5557
+ super(CaptureV1Error.buildMessage(requestId, drops, retryExhausted, cause)), this.name = "CaptureV1Error";
5558
+ this.requestId = requestId;
5559
+ this.drops = drops;
5560
+ this.retryExhausted = retryExhausted;
5561
+ this.cause = cause;
5562
+ }
5563
+ static buildMessage(requestId, drops, retryExhausted, cause) {
5564
+ let message = `Capture V1 batch ${requestId} did not fully deliver: ${drops.length} dropped, ${retryExhausted.length} undelivered`;
5565
+ if (cause instanceof Error)
5566
+ message += ` (${cause.message})`;
5567
+ return message;
5568
+ }
5569
+ }
5570
+
5571
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/transform.mjs
5572
+ function coerceBool(value) {
5573
+ if (typeof value == "boolean")
5574
+ return value;
5575
+ if (typeof value == "number")
5576
+ return value !== 0;
5577
+ if (typeof value == "string") {
5578
+ const normalized = value.trim().toLowerCase();
5579
+ if (normalized === "true" || normalized === "1")
5580
+ return true;
5581
+ if (normalized === "false" || normalized === "0")
5582
+ return false;
5583
+ }
5584
+ }
5585
+ function coerceString(value) {
5586
+ return typeof value == "string" ? value : undefined;
5587
+ }
5588
+ var OPTION_SENTINELS = [
5589
+ {
5590
+ property: "$cookieless_mode",
5591
+ optionKey: "cookieless_mode",
5592
+ coerce: coerceBool
5593
+ },
5594
+ {
5595
+ property: "$ignore_sent_at",
5596
+ optionKey: "disable_skew_correction",
5597
+ coerce: coerceBool
5598
+ },
5599
+ {
5600
+ property: "$process_person_profile",
5601
+ optionKey: "process_person_profile",
5602
+ coerce: coerceBool
5603
+ },
5604
+ {
5605
+ property: "$product_tour_id",
5606
+ optionKey: "product_tour_id",
5607
+ coerce: coerceString
5608
+ }
5609
+ ];
5610
+ var TOPLEVEL_SENTINELS = [
5611
+ {
5612
+ property: "$session_id",
5613
+ field: "session_id"
5614
+ },
5615
+ {
5616
+ property: "$window_id",
5617
+ field: "window_id"
5618
+ }
5619
+ ];
5620
+ function isRecord2(value) {
5621
+ return typeof value == "object" && value !== null && !Array.isArray(value);
5622
+ }
5623
+ function toRfc3339(timestamp) {
5624
+ if (typeof timestamp == "string") {
5625
+ const asDate2 = new Date(timestamp);
5626
+ if (Number.isNaN(asDate2.getTime()))
5627
+ return new Date().toISOString();
5628
+ const normalized = asDate2.toISOString();
5629
+ const fractionalSeconds = timestamp.match(/\.(\d+)(?:Z|[+-]\d{2}:?\d{2})?$/i)?.[1];
5630
+ return fractionalSeconds && fractionalSeconds.length > 3 ? normalized.replace(/\.\d{3}Z$/, `.${fractionalSeconds}Z`) : normalized;
5631
+ }
5632
+ if (timestamp instanceof Date)
5633
+ return Number.isNaN(timestamp.getTime()) ? new Date().toISOString() : timestamp.toISOString();
5634
+ const asDate = timestamp == null ? new Date : new Date(timestamp);
5635
+ return Number.isNaN(asDate.getTime()) ? new Date().toISOString() : asDate.toISOString();
5636
+ }
5637
+ function relocateInto(properties, key, value) {
5638
+ if (value !== undefined && !(key in properties))
5639
+ properties[key] = value;
5640
+ }
5641
+ function buildV1Event(message) {
5642
+ const sourceProperties = isRecord2(message.properties) ? message.properties : {};
5643
+ const properties = {
5644
+ ...sourceProperties
5645
+ };
5646
+ const options = {};
5647
+ for (const { property, optionKey, coerce } of OPTION_SENTINELS)
5648
+ if (property in properties) {
5649
+ const coerced = coerce(properties[property]);
5650
+ if (coerced !== undefined)
5651
+ options[optionKey] = coerced;
5652
+ delete properties[property];
5653
+ }
5654
+ const topLevel = {};
5655
+ for (const { property, field } of TOPLEVEL_SENTINELS)
5656
+ if (property in properties) {
5657
+ const value = properties[property];
5658
+ if (typeof value == "string")
5659
+ topLevel[field] = value;
5660
+ delete properties[property];
5661
+ }
5662
+ delete properties.$lib;
5663
+ delete properties.$lib_version;
5664
+ relocateInto(properties, "$set", message.$set);
5665
+ relocateInto(properties, "$set_once", message.$set_once);
5666
+ return {
5667
+ event: String(message.event ?? ""),
5668
+ uuid: String(message.uuid ?? ""),
5669
+ distinct_id: String(message.distinct_id ?? ""),
5670
+ timestamp: toRfc3339(message.timestamp),
5671
+ ...topLevel,
5672
+ options,
5673
+ properties
5674
+ };
5675
+ }
5676
+ function buildV1Batch(messages, { createdAt, historicalMigration }) {
5677
+ const batch = {
5678
+ created_at: createdAt,
5679
+ batch: messages.map(buildV1Event)
5680
+ };
5681
+ if (historicalMigration)
5682
+ batch.historical_migration = true;
5683
+ return batch;
5684
+ }
5685
+
5686
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/sender.mjs
5687
+ var V1_ANALYTICS_PATH = "/i/v1/analytics/events";
5688
+ var DEFAULT_MAX_BACKOFF_MS = 30000;
5689
+ var RETRYABLE_STATUSES = new Set([
5690
+ 408,
5691
+ 500,
5692
+ 502,
5693
+ 503,
5694
+ 504
5695
+ ]);
5696
+
5697
+ class V1CaptureSender {
5698
+ constructor(config, hooks) {
5699
+ this.config = config;
5700
+ this.maxBackoffMs = config.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
5701
+ this.fetchFn = hooks.fetch;
5702
+ this.onError = hooks.onError;
5703
+ this.now = hooks.now ?? Date.now;
5704
+ this.sleep = hooks.sleep ?? ((ms) => new Promise((resolve) => safeSetTimeout(resolve, ms)));
5705
+ this.generateRequestId = hooks.generateRequestId ?? uuidv7;
5706
+ this.compress = hooks.compress ?? gzipCompress;
5707
+ }
5708
+ async sendV1Batch(messages) {
5709
+ if (messages.length === 0)
5710
+ return;
5711
+ const requestId = this.generateRequestId();
5712
+ const createdAt = new Date(this.now()).toISOString();
5713
+ const { batch } = buildV1Batch(messages, {
5714
+ createdAt,
5715
+ historicalMigration: this.config.historicalMigration
5716
+ });
5717
+ const url = `${this.config.host}${V1_ANALYTICS_PATH}`;
5718
+ const drops = [];
5719
+ let pending = batch;
5720
+ const maxAttempts = Math.max(1, this.config.maxAttempts);
5721
+ for (let attempt = 1;attempt <= maxAttempts; attempt++) {
5722
+ const isLastAttempt = attempt === maxAttempts;
5723
+ const payload = safeJsonStringify({
5724
+ created_at: createdAt,
5725
+ ...this.config.historicalMigration ? {
5726
+ historical_migration: true
5727
+ } : {},
5728
+ batch: pending
5729
+ });
5730
+ let captureAttempt;
5731
+ let retryDelayMs;
5732
+ try {
5733
+ captureAttempt = await this.sendOnce(url, payload, attempt, requestId);
5734
+ const { response, signal } = captureAttempt;
5735
+ const { status } = response;
5736
+ if (status < 200 || status >= 300)
5737
+ if (!isLastAttempt && RETRYABLE_STATUSES.has(status)) {
5738
+ const retryAfterMs = this.parseRetryAfter(response);
5739
+ await captureAttempt.waitFor(captureAttempt.cancelBody()).catch(() => {});
5740
+ retryDelayMs = this.backoffDelay(attempt, retryAfterMs);
5741
+ } else {
5742
+ const httpError = await this.buildHttpError(response, status, captureAttempt.waitFor);
5743
+ return this.surfaceBatchFailure(requestId, drops, pending, httpError);
5744
+ }
5745
+ else {
5746
+ let parsed;
5747
+ try {
5748
+ parsed = await captureAttempt.waitFor(this.parseResponse(response));
5749
+ } catch (error) {
5750
+ if (signal.aborted)
5751
+ throw error;
5752
+ return this.surfaceBatchFailure(requestId, drops, pending, new Error(`Capture V1 returned an unparseable ${status} response body`));
5753
+ }
5754
+ const retryable = this.classify(pending, parsed, drops);
5755
+ if (retryable.length === 0)
5756
+ return this.surfacePartialDrops(requestId, drops);
5757
+ if (isLastAttempt)
5758
+ return void this.onError(new CaptureV1Error({
5759
+ requestId,
5760
+ drops,
5761
+ retryExhausted: retryable.map((event) => event.uuid)
5762
+ }));
5763
+ pending = retryable;
5764
+ const retryAfterMs = this.parseRetryAfter(response);
5765
+ retryDelayMs = this.backoffDelay(attempt, retryAfterMs);
5766
+ }
5767
+ } catch (transportError) {
5768
+ if (captureAttempt && !captureAttempt.signal.aborted)
5769
+ throw transportError;
5770
+ if (isLastAttempt)
5771
+ return this.surfaceBatchFailure(requestId, drops, pending, transportError);
5772
+ retryDelayMs = this.backoffDelay(attempt);
5773
+ } finally {
5774
+ captureAttempt?.cleanup();
5775
+ }
5776
+ if (retryDelayMs !== undefined)
5777
+ await this.sleep(retryDelayMs);
5778
+ }
5779
+ }
5780
+ async sendOnce(url, payload, attempt, requestId) {
5781
+ const headers = this.buildHeaders(attempt, requestId);
5782
+ let body = payload;
5783
+ if (this.config.compressionEnabled) {
5784
+ const compressed = await this.compress(payload, this.config.isDebug);
5785
+ if (compressed !== null) {
5786
+ body = compressed;
5787
+ headers["Content-Encoding"] = "gzip";
5788
+ }
5789
+ }
5790
+ const controller = new AbortController;
5791
+ let timeoutPhase = "waiting for response headers";
5792
+ let timer;
5793
+ const deadline = new Promise((_resolve, reject) => {
5794
+ timer = safeSetTimeout(() => {
5795
+ const timeoutError = new Error(`Capture V1 request timed out ${timeoutPhase} after ${this.config.requestTimeoutMs}ms`);
5796
+ timeoutError.name = "AbortError";
5797
+ reject(timeoutError);
5798
+ controller.abort(timeoutError);
5799
+ }, this.config.requestTimeoutMs);
5800
+ });
5801
+ try {
5802
+ const fetchPromise = this.fetchFn(url, {
5803
+ method: "POST",
5804
+ headers,
5805
+ body,
5806
+ signal: controller.signal
5807
+ });
5808
+ let responseAccepted = false;
5809
+ fetchPromise.then((lateResponse) => {
5810
+ if (controller.signal.aborted && !responseAccepted)
5811
+ this.cancelBody(lateResponse);
5812
+ }).catch(() => {});
5813
+ const response = await Promise.race([
5814
+ fetchPromise,
5815
+ deadline
5816
+ ]);
5817
+ responseAccepted = true;
5818
+ timeoutPhase = "while reading the response body";
5819
+ let cleanedUp = false;
5820
+ let cancellation;
5821
+ const cancelBody = () => cancellation ??= this.cancelBody(response);
5822
+ return {
5823
+ response,
5824
+ signal: controller.signal,
5825
+ waitFor: (operation) => Promise.race([
5826
+ operation,
5827
+ deadline
5828
+ ]),
5829
+ cancelBody,
5830
+ cleanup: () => {
5831
+ if (cleanedUp)
5832
+ return;
5833
+ cleanedUp = true;
5834
+ clearTimeout(timer);
5835
+ if (controller.signal.aborted)
5836
+ cancelBody();
5837
+ }
5838
+ };
5839
+ } catch (error) {
5840
+ clearTimeout(timer);
5841
+ throw error;
5842
+ }
5843
+ }
5844
+ buildHeaders(attempt, requestId) {
5845
+ const sdkInfo = `${this.config.libraryId}/${this.config.libraryVersion}`;
5846
+ const headers = {
5847
+ "Content-Type": "application/json",
5848
+ Authorization: `Bearer ${this.config.apiKey}`,
5849
+ "PostHog-Sdk-Info": sdkInfo,
5850
+ "PostHog-Attempt": String(attempt),
5851
+ "PostHog-Request-Id": requestId,
5852
+ "PostHog-Request-Timestamp": new Date(this.now()).toISOString()
5853
+ };
5854
+ if (this.config.userAgent)
5855
+ headers["User-Agent"] = this.config.userAgent;
5856
+ return headers;
5857
+ }
5858
+ classify(pending, parsed, drops) {
5859
+ const results = parsed.results ?? {};
5860
+ const retryable = [];
5861
+ for (const event of pending) {
5862
+ const result = results[event.uuid];
5863
+ if (result) {
5864
+ if (result.result === "drop")
5865
+ drops.push({
5866
+ uuid: event.uuid,
5867
+ details: result.details ?? undefined
5868
+ });
5869
+ else if (result.result === "retry")
5870
+ retryable.push(event);
5871
+ }
5872
+ }
5873
+ return retryable;
5874
+ }
5875
+ backoffDelay(attempt, retryAfterMs) {
5876
+ const exponential = Math.min(this.config.initialRetryDelayMs * 2 ** (attempt - 1), this.maxBackoffMs);
5877
+ if (retryAfterMs === undefined)
5878
+ return exponential;
5879
+ return Math.max(exponential, Math.min(retryAfterMs, this.maxBackoffMs));
5880
+ }
5881
+ parseRetryAfter(response) {
5882
+ const raw = response.headers?.get("Retry-After");
5883
+ if (!raw)
5884
+ return;
5885
+ const trimmed = raw.trim();
5886
+ if (/^\d+$/.test(trimmed)) {
5887
+ const seconds = parseInt(trimmed, 10);
5888
+ return Number.isFinite(seconds) && seconds > 0 ? 1000 * seconds : undefined;
5889
+ }
5890
+ const dateMs = Date.parse(trimmed);
5891
+ if (Number.isNaN(dateMs))
5892
+ return;
5893
+ const delta = dateMs - this.now();
5894
+ return delta > 0 ? delta : undefined;
5895
+ }
5896
+ async parseResponse(response) {
5897
+ const text = await response.text();
5898
+ const parsed = JSON.parse(text);
5899
+ if (typeof parsed != "object" || parsed === null || Array.isArray(parsed))
5900
+ throw new Error("unexpected response shape");
5901
+ const results = parsed.results;
5902
+ if (results !== undefined && (typeof results != "object" || results === null || Array.isArray(results)))
5903
+ throw new Error("unexpected results shape");
5904
+ return {
5905
+ results: results ?? {}
5906
+ };
5907
+ }
5908
+ async buildHttpError(response, status, waitFor) {
5909
+ let bodyText = "";
5910
+ try {
5911
+ bodyText = (await waitFor(response.text())).slice(0, 512);
5912
+ } catch {}
5913
+ const suffix = bodyText ? `: ${bodyText}` : "";
5914
+ return new Error(`Capture V1 request failed with HTTP ${status}${suffix}`);
5915
+ }
5916
+ surfaceBatchFailure(requestId, drops, pending, cause) {
5917
+ this.onError(new CaptureV1Error({
5918
+ requestId,
5919
+ drops,
5920
+ retryExhausted: pending.map((event) => event.uuid),
5921
+ cause
5922
+ }));
5923
+ }
5924
+ surfacePartialDrops(requestId, drops) {
5925
+ if (drops.length > 0)
5926
+ this.onError(new CaptureV1Error({
5927
+ requestId,
5928
+ drops,
5929
+ retryExhausted: []
5930
+ }));
5931
+ }
5932
+ async cancelBody(response) {
5933
+ try {
5934
+ await response.body?.cancel();
5935
+ } catch {}
5936
+ }
5937
+ }
5938
+
5939
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/ai-capture/routing.mjs
5940
+ var AI_CAPTURE_ROUTE = "ai-capture";
5941
+ var AI_CAPTURE_ENDPOINT_PATH = "/i/v0/ai/batch/";
5942
+ var AI_MAX_EVENT_BYTES = 8388608;
5943
+ var AI_BATCH_TARGET_BYTES = 5242880;
5944
+
5945
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/ai-capture/batching.mjs
5946
+ var encoder = new TextEncoder;
5947
+ function eventByteSize(message) {
5948
+ return encoder.encode(safeJsonStringify(message)).length;
5949
+ }
5950
+ function partitionAiBatch(messages, maxEventBytes = AI_MAX_EVENT_BYTES, targetBatchBytes = AI_BATCH_TARGET_BYTES) {
5951
+ const batches = [];
5952
+ const dropped = [];
5953
+ let current = [];
5954
+ let currentBytes = 0;
5955
+ for (const message of messages) {
5956
+ if (message === undefined)
5957
+ continue;
5958
+ const bytes = eventByteSize(message);
5959
+ if (bytes > maxEventBytes) {
5960
+ dropped.push({
5961
+ event: typeof message.event == "string" ? message.event : "unknown",
5962
+ bytes
5963
+ });
5964
+ continue;
5965
+ }
5966
+ if (current.length > 0 && currentBytes + bytes > targetBatchBytes) {
5967
+ batches.push(current);
5968
+ current = [];
5969
+ currentBytes = 0;
5970
+ }
5971
+ current.push(message);
5972
+ currentBytes += bytes;
5973
+ }
5974
+ if (current.length > 0)
5975
+ batches.push(current);
5976
+ return {
5977
+ batches,
5978
+ dropped
5979
+ };
5980
+ }
5981
+
5982
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/client.mjs
4397
5983
  var MINIMUM_POLLING_INTERVAL = 100;
4398
5984
  var THIRTY_SECONDS = 30000;
4399
5985
  var MAX_CACHE_SIZE = 50000;
@@ -4418,6 +6004,12 @@ function normalizeHost(value) {
4418
6004
  const normalizedValue = typeof value == "string" ? value.trim() : "";
4419
6005
  return normalizedValue || DEFAULT_NODE_HOST;
4420
6006
  }
6007
+ function normalizeUnsetPersonProperties(value) {
6008
+ const propertyNames = Array.isArray(value) ? value : [
6009
+ value
6010
+ ];
6011
+ return propertyNames.filter((propertyName) => typeof propertyName == "string" && propertyName.trim().length > 0);
6012
+ }
4421
6013
  function buildFlagEventProperties(flagValues) {
4422
6014
  if (!flagValues)
4423
6015
  return {};
@@ -4435,11 +6027,15 @@ class PostHogBackendClient extends PostHogCoreStateless {
4435
6027
  const normalizedApiKey = normalizeApiKey(apiKey);
4436
6028
  const normalizedOptions = {
4437
6029
  ...options,
6030
+ maxQueueSize: options.maxQueueSize ?? 1e4,
6031
+ flushInterval: options.flushInterval ?? 5000,
4438
6032
  host: normalizeHost(options.host),
4439
- personalApiKey: normalizePersonalApiKey(options.personalApiKey)
6033
+ personalApiKey: normalizePersonalApiKey(options.secretKey ?? options.personalApiKey)
4440
6034
  };
4441
- super(normalizedApiKey, normalizedOptions), this._memoryStorage = new PostHogMemoryStorage;
6035
+ super(normalizedApiKey, normalizedOptions), this._memoryStorage = new PostHogMemoryStorage, this._aiCaptureRouteActive = false, this._minimalFlagCalledEvents = false;
4442
6036
  this.options = normalizedOptions;
6037
+ this.captureMode = resolveCaptureMode();
6038
+ this.enableFullAiCapture = normalizedOptions.enableFullAiCapture === true;
4443
6039
  this.context = this.initializeContext();
4444
6040
  this.options.featureFlagsPollingInterval = typeof normalizedOptions.featureFlagsPollingInterval == "number" ? Math.max(normalizedOptions.featureFlagsPollingInterval, MINIMUM_POLLING_INTERVAL) : THIRTY_SECONDS;
4445
6041
  if (typeof normalizedOptions.waitUntilDebounceMs == "number")
@@ -4464,21 +6060,24 @@ class PostHogBackendClient extends PostHogCoreStateless {
4464
6060
  onLoad: (count) => {
4465
6061
  this._events.emit("localEvaluationFlagsLoaded", count);
4466
6062
  },
6063
+ onMinimalFlagCalledEvents: (enabled) => {
6064
+ this._minimalFlagCalledEvents = enabled;
6065
+ },
4467
6066
  customHeaders: this.getCustomHeaders(),
4468
6067
  cacheProvider: normalizedOptions.flagDefinitionCacheProvider,
4469
6068
  strictLocalEvaluation: normalizedOptions.strictLocalEvaluation
4470
6069
  });
4471
6070
  }
4472
- this.errorTracking = new ErrorTracking(this, normalizedOptions, this._logger);
6071
+ this.errorTracking = new error_tracking_ErrorTracking(this, normalizedOptions, this._logger);
4473
6072
  this.distinctIdHasSentFlagCalls = {};
4474
6073
  this.maxCacheSize = normalizedOptions.maxCacheSize || MAX_CACHE_SIZE;
4475
6074
  }
4476
- enqueue(type, message, options) {
4477
- super.enqueue(type, message, options);
6075
+ enqueue(type, message, options, explicitRoute) {
6076
+ super.enqueue(type, message, options, explicitRoute);
4478
6077
  this.scheduleDebouncedFlush();
4479
6078
  }
4480
6079
  async flush() {
4481
- const flushPromise = super.flush();
6080
+ const flushPromise = this.flushWithPendingPromises();
4482
6081
  const waitUntil = this.options.waitUntil;
4483
6082
  if (waitUntil && !this._waitUntilCycle)
4484
6083
  try {
@@ -4531,7 +6130,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4531
6130
  async resolveWaitUntilFlush() {
4532
6131
  const resolve = this._consumeWaitUntilCycle();
4533
6132
  try {
4534
- await super.flush();
6133
+ await this.flushWithPendingPromises();
4535
6134
  } catch {} finally {
4536
6135
  resolve?.();
4537
6136
  }
@@ -4545,12 +6144,103 @@ class PostHogBackendClient extends PostHogCoreStateless {
4545
6144
  fetch(url, options) {
4546
6145
  return this.options.fetch ? this.options.fetch(url, options) : fetch(url, options);
4547
6146
  }
6147
+ getQueueRouteKey(message) {
6148
+ return this.captureMode === "v1" && isLegacyOnlyEvent(message) ? AI_ROUTE : ANALYTICS_ROUTE;
6149
+ }
6150
+ persistedQueueKeyForRoute(route) {
6151
+ if (route === AI_CAPTURE_ROUTE)
6152
+ return types_PostHogPersistedProperty.AiCaptureQueue;
6153
+ return route === AI_ROUTE ? types_PostHogPersistedProperty.AiQueue : types_PostHogPersistedProperty.Queue;
6154
+ }
6155
+ getActiveQueueRoutes() {
6156
+ const routes = this.captureMode === "v1" ? [
6157
+ ANALYTICS_ROUTE,
6158
+ AI_ROUTE
6159
+ ] : [
6160
+ ANALYTICS_ROUTE
6161
+ ];
6162
+ if (this._aiCaptureRouteActive)
6163
+ routes.push(AI_CAPTURE_ROUTE);
6164
+ return routes;
6165
+ }
6166
+ getBatchEndpointPath(route) {
6167
+ return route === AI_CAPTURE_ROUTE ? AI_CAPTURE_ENDPOINT_PATH : super.getBatchEndpointPath(route);
6168
+ }
6169
+ async sendBatch(batchMessages, retryOptions, route = ANALYTICS_ROUTE) {
6170
+ if (route === AI_CAPTURE_ROUTE)
6171
+ return this.sendAiCaptureBatch(batchMessages, retryOptions);
6172
+ if (this.captureMode !== "v1" || route === AI_ROUTE)
6173
+ return super.sendBatch(batchMessages, retryOptions, route);
6174
+ const v1Events = batchMessages.filter((message) => message !== undefined);
6175
+ await this.getV1Sender().sendV1Batch(v1Events);
6176
+ }
6177
+ async sendAiCaptureBatch(batchMessages, retryOptions) {
6178
+ const { batches, dropped } = partitionAiBatch(batchMessages);
6179
+ for (const { event, bytes } of dropped) {
6180
+ const message = `Event ${event} (${bytes} bytes) exceeds the ${AI_MAX_EVENT_BYTES / 1048576}MiB limit for ${AI_CAPTURE_ENDPOINT_PATH}, dropping.`;
6181
+ this._logger.error(message);
6182
+ this._events.emit("error", new Error(message));
6183
+ }
6184
+ for (const batch of batches)
6185
+ await this.sendAiSubBatch(batch, retryOptions);
6186
+ }
6187
+ async sendAiSubBatch(batch, retryOptions) {
6188
+ try {
6189
+ await super.sendBatch(batch, retryOptions, AI_CAPTURE_ROUTE);
6190
+ } catch (err) {
6191
+ if (!isPostHogFetchContentTooLargeError(err))
6192
+ throw err;
6193
+ if (batch.length === 1) {
6194
+ const [event] = batch;
6195
+ const eventName = typeof event.event == "string" ? event.event : "unknown";
6196
+ const message = `Event ${eventName} (${eventByteSize(event)} bytes) was rejected with 413 by ${AI_CAPTURE_ENDPOINT_PATH} on its own, dropping.`;
6197
+ this._logger.error(message);
6198
+ this._events.emit("error", new Error(message));
6199
+ return;
6200
+ }
6201
+ const mid = Math.ceil(batch.length / 2);
6202
+ await this.sendAiSubBatch(batch.slice(0, mid), retryOptions);
6203
+ await this.sendAiSubBatch(batch.slice(mid), retryOptions);
6204
+ }
6205
+ }
6206
+ getV1Sender() {
6207
+ if (!this._v1Sender)
6208
+ this._v1Sender = new V1CaptureSender({
6209
+ host: this.host,
6210
+ apiKey: this.apiKey,
6211
+ libraryId: this.getLibraryId(),
6212
+ libraryVersion: this.getLibraryVersion(),
6213
+ userAgent: this.getCustomUserAgent() || undefined,
6214
+ historicalMigration: this.historicalMigration,
6215
+ compressionEnabled: !this.disableCompression,
6216
+ requestTimeoutMs: this.requestTimeout,
6217
+ maxAttempts: (this.options.fetchRetryCount ?? 3) + 1,
6218
+ initialRetryDelayMs: this.options.fetchRetryDelay ?? 3000,
6219
+ isDebug: this.isDebug
6220
+ }, {
6221
+ fetch: (url, fetchOptions) => this.fetch(url, fetchOptions),
6222
+ onError: (error) => this._events.emit("error", error),
6223
+ compress: (payload) => this.compressPayload(payload)
6224
+ });
6225
+ return this._v1Sender;
6226
+ }
4548
6227
  getLibraryVersion() {
4549
6228
  return version;
4550
6229
  }
6230
+ get metrics() {
6231
+ if (!this._metrics)
6232
+ this._metrics = new PostHogMetrics(this, resolveMetricsConfig(this.options.metrics), this._logger);
6233
+ return this._metrics;
6234
+ }
4551
6235
  getCustomUserAgent() {
4552
6236
  return `${this.getLibraryId()}/${this.getLibraryVersion()}`;
4553
6237
  }
6238
+ getCommonEventProperties() {
6239
+ const commonProperties = super.getCommonEventProperties();
6240
+ if (this.options.isServer ?? true)
6241
+ commonProperties.$is_server = true;
6242
+ return commonProperties;
6243
+ }
4554
6244
  enable() {
4555
6245
  return super.optIn();
4556
6246
  }
@@ -4561,33 +6251,69 @@ class PostHogBackendClient extends PostHogCoreStateless {
4561
6251
  super.debug(enabled);
4562
6252
  this.featureFlagsPoller?.debug(enabled);
4563
6253
  }
4564
- capture(props) {
6254
+ _warnIfInvalidCapture(props, stringArgumentWarning, exceptionCaptureWarning) {
4565
6255
  if (typeof props == "string")
4566
- this._logger.warn("Called capture() with a string as the first argument when an object was expected.");
6256
+ this._logger.warn(stringArgumentWarning);
4567
6257
  if (props.event === "$exception" && !props._originatedFromCaptureException)
4568
- this._logger.warn("Using `posthog.capture('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureException(error)` instead, which attaches required metadata automatically.");
4569
- this.addPendingPromise(this.prepareEventMessage(props).then(({ distinctId, event, properties, options }) => super.captureStateless(distinctId, event, properties, {
4570
- timestamp: options.timestamp,
4571
- disableGeoip: options.disableGeoip,
4572
- uuid: options.uuid
4573
- })).catch((err) => {
6258
+ this._logger.warn(exceptionCaptureWarning);
6259
+ }
6260
+ _sendPreparedEvent(type, props, immediate, prepareOptions, explicitRoute) {
6261
+ return this.addPendingPromise(this._prepareEventMessage(props, prepareOptions).then(({ distinctId, event, properties, options }) => {
6262
+ const captureOptions = {
6263
+ timestamp: options.timestamp,
6264
+ disableGeoip: options.disableGeoip,
6265
+ uuid: options.uuid
6266
+ };
6267
+ const message = {
6268
+ distinctId,
6269
+ event,
6270
+ properties: {
6271
+ ...properties,
6272
+ ...this.getCommonEventProperties()
6273
+ }
6274
+ };
6275
+ return immediate ? this.sendImmediate(type, message, captureOptions, explicitRoute) : this.enqueue(type, message, captureOptions, explicitRoute);
6276
+ }).catch((err) => {
4574
6277
  if (err)
4575
6278
  console.error(err);
4576
6279
  }));
4577
6280
  }
6281
+ _capturePreparedEvent(props, immediate) {
6282
+ return this._sendPreparedEvent("capture", props, immediate);
6283
+ }
6284
+ capture(props) {
6285
+ this._warnIfInvalidCapture(props, "Called capture() with a string as the first argument when an object was expected.", "Using `posthog.capture('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureException(error)` instead, which attaches required metadata automatically.");
6286
+ this._capturePreparedEvent(props, false);
6287
+ }
4578
6288
  async captureImmediate(props) {
4579
- if (typeof props == "string")
4580
- this._logger.warn("Called captureImmediate() with a string as the first argument when an object was expected.");
4581
- if (props.event === "$exception" && !props._originatedFromCaptureException)
4582
- this._logger.warn("Capturing a `$exception` event via `posthog.captureImmediate('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureExceptionImmediate(error)` instead, which attaches this metadata by default.");
4583
- return this.addPendingPromise(this.prepareEventMessage(props).then(({ distinctId, event, properties, options }) => super.captureStatelessImmediate(distinctId, event, properties, {
4584
- timestamp: options.timestamp,
4585
- disableGeoip: options.disableGeoip,
4586
- uuid: options.uuid
4587
- })).catch((err) => {
4588
- if (err)
4589
- console.error(err);
4590
- }));
6289
+ this._warnIfInvalidCapture(props, "Called captureImmediate() with a string as the first argument when an object was expected.", "Capturing a `$exception` event via `posthog.captureImmediate('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureExceptionImmediate(error)` instead, which attaches this metadata by default.");
6290
+ return this._capturePreparedEvent(props, true);
6291
+ }
6292
+ captureAi(props) {
6293
+ if (this.disabled)
6294
+ return;
6295
+ const uuid = getEventUuid(props.uuid, uuidv7);
6296
+ this._sendPreparedAiEvent({
6297
+ ...props,
6298
+ uuid
6299
+ }, false);
6300
+ return uuid;
6301
+ }
6302
+ async captureAiImmediate(props) {
6303
+ if (this.disabled)
6304
+ return;
6305
+ const uuid = getEventUuid(props.uuid, uuidv7);
6306
+ await this._sendPreparedAiEvent({
6307
+ ...props,
6308
+ uuid
6309
+ }, true);
6310
+ return uuid;
6311
+ }
6312
+ _sendPreparedAiEvent(props, immediate) {
6313
+ if (typeof props?.event == "string" && !props.event.startsWith("$ai_"))
6314
+ this._logger.debug(`captureAi called with non-AI event ${props.event}; routing it to the AI endpoint anyway.`);
6315
+ this._aiCaptureRouteActive = true;
6316
+ return this._sendPreparedEvent("capture", props, immediate, undefined, AI_CAPTURE_ROUTE);
4591
6317
  }
4592
6318
  identify({ distinctId, properties = {}, disableGeoip }) {
4593
6319
  const { $set, $set_once, $anon_distinct_id, ...rest } = properties;
@@ -4598,8 +6324,13 @@ class PostHogBackendClient extends PostHogCoreStateless {
4598
6324
  $set_once: setOnceProps,
4599
6325
  $anon_distinct_id: $anon_distinct_id ?? undefined
4600
6326
  };
4601
- super.identifyStateless(distinctId, eventProperties, {
6327
+ this._sendPreparedEvent("identify", {
6328
+ distinctId,
6329
+ event: "$identify",
6330
+ properties: eventProperties,
4602
6331
  disableGeoip
6332
+ }, false, {
6333
+ includeContextProperties: false
4603
6334
  });
4604
6335
  }
4605
6336
  async identifyImmediate({ distinctId, properties = {}, disableGeoip }) {
@@ -4611,18 +6342,65 @@ class PostHogBackendClient extends PostHogCoreStateless {
4611
6342
  $set_once: setOnceProps,
4612
6343
  $anon_distinct_id: $anon_distinct_id ?? undefined
4613
6344
  };
4614
- await super.identifyStatelessImmediate(distinctId, eventProperties, {
6345
+ await this._sendPreparedEvent("identify", {
6346
+ distinctId,
6347
+ event: "$identify",
6348
+ properties: eventProperties,
4615
6349
  disableGeoip
6350
+ }, true, {
6351
+ includeContextProperties: false
6352
+ });
6353
+ }
6354
+ setPersonProperties({ distinctId, properties = {}, propertiesOnce = {} }) {
6355
+ if (Object.keys(properties).length === 0 && Object.keys(propertiesOnce).length === 0)
6356
+ return;
6357
+ const eventProperties = {};
6358
+ if (Object.keys(properties).length > 0)
6359
+ eventProperties.$set = properties;
6360
+ if (Object.keys(propertiesOnce).length > 0)
6361
+ eventProperties.$set_once = propertiesOnce;
6362
+ this.capture({
6363
+ distinctId,
6364
+ event: "$set",
6365
+ properties: eventProperties
6366
+ });
6367
+ }
6368
+ unsetPersonProperties({ distinctId, properties }) {
6369
+ const propertyNames = normalizeUnsetPersonProperties(properties);
6370
+ if (propertyNames.length === 0)
6371
+ return;
6372
+ this.capture({
6373
+ distinctId,
6374
+ event: "$set",
6375
+ properties: {
6376
+ $unset: propertyNames
6377
+ }
4616
6378
  });
4617
6379
  }
4618
6380
  alias(data) {
4619
- super.aliasStateless(data.alias, data.distinctId, undefined, {
6381
+ this._sendPreparedEvent("alias", {
6382
+ distinctId: data.distinctId,
6383
+ event: "$create_alias",
6384
+ properties: {
6385
+ distinct_id: data.distinctId,
6386
+ alias: data.alias
6387
+ },
4620
6388
  disableGeoip: data.disableGeoip
6389
+ }, false, {
6390
+ includeContextProperties: false
4621
6391
  });
4622
6392
  }
4623
6393
  async aliasImmediate(data) {
4624
- await super.aliasStatelessImmediate(data.alias, data.distinctId, undefined, {
6394
+ await this._sendPreparedEvent("alias", {
6395
+ distinctId: data.distinctId,
6396
+ event: "$create_alias",
6397
+ properties: {
6398
+ distinct_id: data.distinctId,
6399
+ alias: data.alias
6400
+ },
4625
6401
  disableGeoip: data.disableGeoip
6402
+ }, true, {
6403
+ includeContextProperties: false
4626
6404
  });
4627
6405
  }
4628
6406
  isLocalEvaluationReady() {
@@ -4677,7 +6455,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4677
6455
  const adjustedProperties = this.addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties);
4678
6456
  personProperties = adjustedProperties.allPersonProperties;
4679
6457
  groupProperties = adjustedProperties.allGroupProperties;
4680
- const evaluationContext = this.createFeatureFlagEvaluationContext(distinctId, groups, personProperties, groupProperties);
6458
+ const evaluationContext = this.createFeatureFlagEvaluationContext(distinctId, groups, this.personPropertiesForLocalEvaluation(distinctId, personProperties), groupProperties);
4681
6459
  if (onlyEvaluateLocally == undefined)
4682
6460
  onlyEvaluateLocally = this.options.strictLocalEvaluation ?? false;
4683
6461
  let result;
@@ -4688,6 +6466,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4688
6466
  let flagId;
4689
6467
  let flagVersion;
4690
6468
  let flagReason;
6469
+ let flagHasExperiment;
4691
6470
  const localEvaluationEnabled = this.featureFlagsPoller !== undefined;
4692
6471
  if (localEvaluationEnabled) {
4693
6472
  await this.featureFlagsPoller?.loadFeatureFlags();
@@ -4702,6 +6481,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4702
6481
  const value = localResult.value;
4703
6482
  flagId = flag.id;
4704
6483
  flagReason = "Evaluated locally";
6484
+ flagHasExperiment = flag.has_experiment;
4705
6485
  result = {
4706
6486
  key,
4707
6487
  enabled: value !== false,
@@ -4717,12 +6497,13 @@ class PostHogBackendClient extends PostHogCoreStateless {
4717
6497
  }
4718
6498
  }
4719
6499
  if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
4720
- const flagsResponse = await super.getFeatureFlagDetailsStateless(evaluationContext.distinctId, evaluationContext.groups, evaluationContext.personProperties, evaluationContext.groupProperties, disableGeoip, [
6500
+ const flagsResponse = await super.getFeatureFlagDetailsStateless(evaluationContext.distinctId, evaluationContext.groups, personProperties, groupProperties, disableGeoip, [
4721
6501
  key
4722
6502
  ]);
4723
6503
  if (flagsResponse === undefined)
4724
6504
  featureFlagError = FeatureFlagError2.UNKNOWN_ERROR;
4725
6505
  else {
6506
+ this._minimalFlagCalledEvents = flagsResponse.minimalFlagCalledEvents === true;
4726
6507
  requestId = flagsResponse.requestId;
4727
6508
  evaluatedAt = flagsResponse.evaluatedAt;
4728
6509
  const errors = [];
@@ -4737,6 +6518,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4737
6518
  flagId = flagDetail.metadata?.id;
4738
6519
  flagVersion = flagDetail.metadata?.version;
4739
6520
  flagReason = flagDetail.reason?.description ?? flagDetail.reason?.code;
6521
+ flagHasExperiment = flagDetail.metadata?.has_experiment;
4740
6522
  let parsedPayload;
4741
6523
  if (flagDetail.metadata?.payload !== undefined)
4742
6524
  try {
@@ -4768,6 +6550,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
4768
6550
  $feature_flag_request_id: requestId,
4769
6551
  $feature_flag_evaluated_at: flagWasLocallyEvaluated ? Date.now() : evaluatedAt
4770
6552
  };
6553
+ if (flagHasExperiment !== undefined)
6554
+ properties.$feature_flag_has_experiment = flagHasExperiment;
4771
6555
  if (flagWasLocallyEvaluated && this.featureFlagsPoller) {
4772
6556
  const flagDefinitionsLoadedAt = this.featureFlagsPoller.getFlagDefinitionsLoadedAt();
4773
6557
  if (flagDefinitionsLoadedAt !== undefined)
@@ -4882,7 +6666,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4882
6666
  const adjustedProperties = this.addLocalPersonAndGroupProperties(resolvedDistinctId, groups, personProperties, groupProperties);
4883
6667
  personProperties = adjustedProperties.allPersonProperties;
4884
6668
  groupProperties = adjustedProperties.allGroupProperties;
4885
- const evaluationContext = this.createFeatureFlagEvaluationContext(resolvedDistinctId, groups, personProperties, groupProperties);
6669
+ const evaluationContext = this.createFeatureFlagEvaluationContext(resolvedDistinctId, groups, this.personPropertiesForLocalEvaluation(resolvedDistinctId, personProperties), groupProperties);
4886
6670
  if (onlyEvaluateLocally == undefined)
4887
6671
  onlyEvaluateLocally = this.options.strictLocalEvaluation ?? false;
4888
6672
  const localEvaluationResult = await this.featureFlagsPoller?.getAllFlagsAndPayloads(evaluationContext, flagKeys);
@@ -4895,7 +6679,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4895
6679
  fallbackToFlags = localEvaluationResult.fallbackToFlags;
4896
6680
  }
4897
6681
  if (fallbackToFlags && !onlyEvaluateLocally) {
4898
- const remoteEvaluationResult = await super.getFeatureFlagsAndPayloadsStateless(evaluationContext.distinctId, evaluationContext.groups, evaluationContext.personProperties, evaluationContext.groupProperties, disableGeoip, flagKeys);
6682
+ const remoteEvaluationResult = await super.getFeatureFlagsAndPayloadsStateless(evaluationContext.distinctId, evaluationContext.groups, personProperties, groupProperties, disableGeoip, flagKeys);
4899
6683
  featureFlags = {
4900
6684
  ...featureFlags,
4901
6685
  ...remoteEvaluationResult.flags || {}
@@ -4943,7 +6727,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4943
6727
  const adjustedProperties = this.addLocalPersonAndGroupProperties(resolvedDistinctId, groups, personProperties, groupProperties);
4944
6728
  personProperties = adjustedProperties.allPersonProperties;
4945
6729
  groupProperties = adjustedProperties.allGroupProperties;
4946
- const evaluationContext = this.createFeatureFlagEvaluationContext(resolvedDistinctId, groups, personProperties, groupProperties);
6730
+ const evaluationContext = this.createFeatureFlagEvaluationContext(resolvedDistinctId, groups, this.personPropertiesForLocalEvaluation(resolvedDistinctId, personProperties), groupProperties);
4947
6731
  if (onlyEvaluateLocally == undefined)
4948
6732
  onlyEvaluateLocally = this.options.strictLocalEvaluation ?? false;
4949
6733
  const records = {};
@@ -4964,14 +6748,16 @@ class PostHogBackendClient extends PostHogCoreStateless {
4964
6748
  id: flagDef?.id,
4965
6749
  version: undefined,
4966
6750
  reason: "Evaluated locally",
4967
- locallyEvaluated: true
6751
+ locallyEvaluated: true,
6752
+ hasExperiment: flagDef?.has_experiment
4968
6753
  };
4969
6754
  locallyEvaluatedKeys.add(key);
4970
6755
  }
4971
6756
  const fallbackToFlags = localResult ? localResult.fallbackToFlags : true;
4972
6757
  if (fallbackToFlags && !onlyEvaluateLocally) {
4973
- const details = await super.getFeatureFlagDetailsStateless(evaluationContext.distinctId, evaluationContext.groups, evaluationContext.personProperties, evaluationContext.groupProperties, disableGeoip, flagKeys);
6758
+ const details = await super.getFeatureFlagDetailsStateless(evaluationContext.distinctId, evaluationContext.groups, personProperties, groupProperties, disableGeoip, flagKeys);
4974
6759
  if (details) {
6760
+ this._minimalFlagCalledEvents = details.minimalFlagCalledEvents === true;
4975
6761
  requestId = details.requestId;
4976
6762
  evaluatedAt = details.evaluatedAt;
4977
6763
  errorsWhileComputing = Boolean(details.errorsWhileComputingFlags);
@@ -4994,7 +6780,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
4994
6780
  id: detail.metadata?.id,
4995
6781
  version: detail.metadata?.version,
4996
6782
  reason: detail.reason?.description ?? detail.reason?.code,
4997
- locallyEvaluated: false
6783
+ locallyEvaluated: false,
6784
+ hasExperiment: detail.metadata?.has_experiment
4998
6785
  };
4999
6786
  }
5000
6787
  }
@@ -5014,7 +6801,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
5014
6801
  id: existing?.id,
5015
6802
  version: existing?.version,
5016
6803
  reason: existing?.reason,
5017
- locallyEvaluated: existing?.locallyEvaluated ?? false
6804
+ locallyEvaluated: existing?.locallyEvaluated ?? false,
6805
+ hasExperiment: existing?.hasExperiment
5018
6806
  };
5019
6807
  }
5020
6808
  if (this._payloadOverrides !== undefined)
@@ -5039,6 +6827,9 @@ class PostHogBackendClient extends PostHogCoreStateless {
5039
6827
  quotaLimited
5040
6828
  });
5041
6829
  }
6830
+ _shouldSendMinimalFlagCalledEvent(event, properties) {
6831
+ return event === "$feature_flag_called" && this._minimalFlagCalledEvents && properties.$feature_flag_has_experiment === false;
6832
+ }
5042
6833
  _captureFlagCalledEventIfNeeded(params) {
5043
6834
  const { distinctId, key, response, groups, disableGeoip, properties } = params;
5044
6835
  const groupSuffix = groups && Object.keys(groups).length > 0 ? `_${JSON.stringify(Object.entries(groups).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0))}` : "";
@@ -5073,9 +6864,32 @@ class PostHogBackendClient extends PostHogCoreStateless {
5073
6864
  return this._featureFlagEvaluationsHost;
5074
6865
  }
5075
6866
  groupIdentify({ groupType, groupKey, properties, distinctId, disableGeoip }) {
5076
- super.groupIdentifyStateless(groupType, groupKey, properties, {
6867
+ this._sendPreparedEvent("capture", {
6868
+ distinctId: distinctId || `$${groupType}_${groupKey}`,
6869
+ event: "$groupidentify",
6870
+ properties: {
6871
+ $group_type: groupType,
6872
+ $group_key: groupKey,
6873
+ $group_set: properties || {}
6874
+ },
6875
+ disableGeoip
6876
+ }, false, {
6877
+ includeContextProperties: false
6878
+ });
6879
+ }
6880
+ async groupIdentifyImmediate({ groupType, groupKey, properties, distinctId, disableGeoip }) {
6881
+ await this._sendPreparedEvent("capture", {
6882
+ distinctId: distinctId || `$${groupType}_${groupKey}`,
6883
+ event: "$groupidentify",
6884
+ properties: {
6885
+ $group_type: groupType,
6886
+ $group_key: groupKey,
6887
+ $group_set: properties || {}
6888
+ },
5077
6889
  disableGeoip
5078
- }, distinctId);
6890
+ }, true, {
6891
+ includeContextProperties: false
6892
+ });
5079
6893
  }
5080
6894
  async reloadFeatureFlags() {
5081
6895
  await this.featureFlagsPoller?.loadFeatureFlags(true);
@@ -5147,12 +6961,18 @@ class PostHogBackendClient extends PostHogCoreStateless {
5147
6961
  this.context?.enter(data, options);
5148
6962
  }
5149
6963
  async _shutdown(shutdownTimeoutMs) {
6964
+ const shutdownDeadlineMs = Date.now() + (shutdownTimeoutMs ?? 30000);
5150
6965
  const resolve = this._consumeWaitUntilCycle();
5151
6966
  await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
5152
6967
  this.errorTracking.shutdown();
6968
+ if (this._metrics) {
6969
+ await raceWithTimeout(this._metrics.flush().catch(() => {}), Math.max(0, shutdownDeadlineMs - Date.now()));
6970
+ this._metrics.reset();
6971
+ }
5153
6972
  try {
5154
- return await super._shutdown(shutdownTimeoutMs);
6973
+ return await super._shutdown(Math.max(0, shutdownDeadlineMs - Date.now()));
5155
6974
  } finally {
6975
+ this.distinctIdHasSentFlagCalls = {};
5156
6976
  resolve?.();
5157
6977
  }
5158
6978
  }
@@ -5247,7 +7067,6 @@ class PostHogBackendClient extends PostHogCoreStateless {
5247
7067
  }
5248
7068
  addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties) {
5249
7069
  const allPersonProperties = {
5250
- distinct_id: distinctId,
5251
7070
  ...personProperties || {}
5252
7071
  };
5253
7072
  const allGroupProperties = {};
@@ -5262,6 +7081,12 @@ class PostHogBackendClient extends PostHogCoreStateless {
5262
7081
  allGroupProperties
5263
7082
  };
5264
7083
  }
7084
+ personPropertiesForLocalEvaluation(distinctId, personProperties) {
7085
+ return {
7086
+ distinct_id: distinctId,
7087
+ ...personProperties || {}
7088
+ };
7089
+ }
5265
7090
  createFeatureFlagEvaluationContext(distinctId, groups, personProperties, groupProperties) {
5266
7091
  return {
5267
7092
  distinctId,
@@ -5272,21 +7097,21 @@ class PostHogBackendClient extends PostHogCoreStateless {
5272
7097
  };
5273
7098
  }
5274
7099
  captureException(error, distinctId, additionalProperties, uuid, flags) {
5275
- if (!ErrorTracking.isPreviouslyCapturedError(error)) {
7100
+ if (!error_tracking_ErrorTracking.isPreviouslyCapturedError(error)) {
5276
7101
  const syntheticException = new Error("PostHog syntheticException");
5277
- this.addPendingPromise(ErrorTracking.buildEventMessage(this.getErrorPropertiesBuilder(), error, {
7102
+ this.addPendingPromise(error_tracking_ErrorTracking.buildEventMessage(this.getErrorPropertiesBuilder(), error, {
5278
7103
  syntheticException
5279
- }, distinctId, additionalProperties).then((msg) => this.capture({
7104
+ }, distinctId, additionalProperties).then((msg) => this._capturePreparedEvent({
5280
7105
  ...msg,
5281
7106
  uuid,
5282
7107
  flags
5283
- })));
7108
+ }, false)));
5284
7109
  }
5285
7110
  }
5286
7111
  async captureExceptionImmediate(error, distinctId, additionalProperties, flags) {
5287
- if (!ErrorTracking.isPreviouslyCapturedError(error)) {
7112
+ if (!error_tracking_ErrorTracking.isPreviouslyCapturedError(error)) {
5288
7113
  const syntheticException = new Error("PostHog syntheticException");
5289
- return this.addPendingPromise(ErrorTracking.buildEventMessage(this.getErrorPropertiesBuilder(), error, {
7114
+ return this.addPendingPromise(error_tracking_ErrorTracking.buildEventMessage(this.getErrorPropertiesBuilder(), error, {
5290
7115
  syntheticException
5291
7116
  }, distinctId, additionalProperties).then((msg) => this.captureImmediate({
5292
7117
  ...msg,
@@ -5295,24 +7120,31 @@ class PostHogBackendClient extends PostHogCoreStateless {
5295
7120
  }
5296
7121
  }
5297
7122
  async prepareEventMessage(props) {
7123
+ return this._prepareEventMessage(props);
7124
+ }
7125
+ async _prepareEventMessage(props, options = {}) {
5298
7126
  const { distinctId, event, properties, groups, flags, sendFeatureFlags, timestamp, disableGeoip, uuid } = props;
5299
7127
  const contextData = this.context?.get();
7128
+ const includeContextProperties = options.includeContextProperties ?? true;
5300
7129
  let mergedDistinctId = distinctId || contextData?.distinctId;
5301
- const mergedProperties = {
7130
+ const mergedProperties = includeContextProperties ? {
5302
7131
  ...this.props,
5303
7132
  ...contextData?.properties || {},
5304
7133
  ...properties || {}
7134
+ } : {
7135
+ ...properties || {}
5305
7136
  };
5306
7137
  if (!mergedDistinctId) {
5307
7138
  mergedDistinctId = uuidv7();
5308
7139
  mergedProperties.$process_person_profile = false;
5309
7140
  }
5310
- if (contextData?.sessionId && !mergedProperties.$session_id)
7141
+ if (includeContextProperties && contextData?.sessionId && !mergedProperties.$session_id)
5311
7142
  mergedProperties.$session_id = contextData.sessionId;
7143
+ const finalProperties = this._shouldSendMinimalFlagCalledEvent(event, mergedProperties) ? minimizeFlagCalledEventProperties(mergedProperties) : mergedProperties;
5312
7144
  const eventMessage = this._runBeforeSend({
5313
7145
  distinctId: mergedDistinctId,
5314
7146
  event,
5315
- properties: mergedProperties,
7147
+ properties: finalProperties,
5316
7148
  groups,
5317
7149
  flags,
5318
7150
  sendFeatureFlags,
@@ -5336,12 +7168,14 @@ class PostHogBackendClient extends PostHogCoreStateless {
5336
7168
  }
5337
7169
  return {};
5338
7170
  }).catch(() => ({})).then((additionalProperties) => {
5339
- const props2 = {
7171
+ const resolvedGroups = eventMessage.groups || groups;
7172
+ return {
5340
7173
  ...additionalProperties,
5341
7174
  ...eventMessage.properties || {},
5342
- $groups: eventMessage.groups || groups
7175
+ ...resolvedGroups !== undefined && Object.keys(resolvedGroups).length > 0 ? {
7176
+ $groups: resolvedGroups
7177
+ } : {}
5343
7178
  };
5344
- return props2;
5345
7179
  });
5346
7180
  if (eventMessage.event === "$pageview" && this.options.__preview_capture_bot_pageviews && typeof eventProperties.$raw_user_agent == "string") {
5347
7181
  if (isBlockedUA(eventProperties.$raw_user_agent, this.options.custom_blocked_useragents || [])) {
@@ -5368,22 +7202,26 @@ class PostHogBackendClient extends PostHogCoreStateless {
5368
7202
  beforeSend
5369
7203
  ];
5370
7204
  let result = eventMessage;
5371
- for (const fn of fns) {
5372
- result = fn(result);
5373
- if (!result) {
5374
- this._logger.info(`Event '${eventMessage.event}' was rejected in beforeSend function`);
7205
+ for (const fn of fns)
7206
+ try {
7207
+ result = fn(result);
7208
+ if (!result) {
7209
+ this._logger.info(`Event '${eventMessage.event}' was rejected in beforeSend function`);
7210
+ return null;
7211
+ }
7212
+ if (!result.properties || Object.keys(result.properties).length === 0) {
7213
+ const message = `Event '${result.event}' has no properties after beforeSend function, this is likely an error.`;
7214
+ this._logger.warn(message);
7215
+ }
7216
+ } catch (error) {
7217
+ this._logger.error(`Error in before_send function for event '${eventMessage.event}':`, error);
5375
7218
  return null;
5376
7219
  }
5377
- if (!result.properties || Object.keys(result.properties).length === 0) {
5378
- const message = `Event '${result.event}' has no properties after beforeSend function, this is likely an error.`;
5379
- this._logger.warn(message);
5380
- }
5381
- }
5382
7220
  return result;
5383
7221
  }
5384
7222
  }
5385
7223
 
5386
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/context/context.mjs
7224
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/context/context.mjs
5387
7225
  import { AsyncLocalStorage } from "node:async_hooks";
5388
7226
 
5389
7227
  class PostHogContext {
@@ -5414,7 +7252,24 @@ class PostHogContext {
5414
7252
  }
5415
7253
  }
5416
7254
 
5417
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/sentry-integration.mjs
7255
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/gzip.node.mjs
7256
+ import { gzip } from "node:zlib";
7257
+ import { promisify } from "node:util";
7258
+ var gzipAsync = promisify(gzip);
7259
+ async function gzipCompress2(input, isDebug = true) {
7260
+ try {
7261
+ const compressed = await gzipAsync(input);
7262
+ return new Blob([
7263
+ new Uint8Array(compressed)
7264
+ ]);
7265
+ } catch (error) {
7266
+ if (isDebug)
7267
+ console.error("Failed to gzip compress data", error);
7268
+ return null;
7269
+ }
7270
+ }
7271
+
7272
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/sentry-integration.mjs
5418
7273
  var NAME = "posthog-node";
5419
7274
  function createEventProcessor(_posthog, { organization, projectId, prefix, severityAllowList = [
5420
7275
  "error"
@@ -5454,6 +7309,9 @@ function createEventProcessor(_posthog, { organization, projectId, prefix, sever
5454
7309
  $sentry_exception_type: exceptions[0]?.type,
5455
7310
  $sentry_tags: event.tags
5456
7311
  };
7312
+ const injectedReleaseId = exports_error_tracking.getInjectedReleaseId();
7313
+ if (injectedReleaseId)
7314
+ properties.$release_id = injectedReleaseId;
5457
7315
  if (organization && projectId)
5458
7316
  properties["$sentry_url"] = (prefix || "https://sentry.io/organizations/") + organization + "/issues/?project=" + projectId + "&query=" + event.event_id;
5459
7317
  if (sendExceptionsToPostHog)
@@ -5482,11 +7340,14 @@ class PostHogSentryIntegration {
5482
7340
  };
5483
7341
  }
5484
7342
  }
5485
- // ../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/entrypoints/index.node.mjs
7343
+ // ../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/entrypoints/index.node.mjs
5486
7344
  class PostHog extends PostHogBackendClient {
5487
7345
  getLibraryId() {
5488
7346
  return "posthog-node";
5489
7347
  }
7348
+ compressPayload(payload) {
7349
+ return gzipCompress2(payload, this.isDebug);
7350
+ }
5490
7351
  initializeContext() {
5491
7352
  return new PostHogContext;
5492
7353
  }
@@ -5499,7 +7360,7 @@ class PostHog extends PostHogBackendClient {
5499
7360
  new exports_error_tracking.PrimitiveCoercer
5500
7361
  ], exports_error_tracking.createStackParser("node:javascript", exports_error_tracking.nodeStackLineParser), [
5501
7362
  createModulerModifier(),
5502
- addSourceContext,
7363
+ (frames) => addSourceContext(frames, undefined, this._logger),
5503
7364
  createRelativePathModifier()
5504
7365
  ]);
5505
7366
  }
@@ -5884,12 +7745,12 @@ function parseHookInput(raw) {
5884
7745
  }
5885
7746
  }
5886
7747
  function isCodexSessionStartInput(value) {
5887
- return isRecord2(value) && value["hook_event_name"] === "SessionStart" && typeof value["session_id"] === "string" && isStringOrNull(value["transcript_path"]) && typeof value["cwd"] === "string" && typeof value["model"] === "string" && typeof value["permission_mode"] === "string" && typeof value["source"] === "string";
7748
+ return isRecord3(value) && value["hook_event_name"] === "SessionStart" && typeof value["session_id"] === "string" && isStringOrNull(value["transcript_path"]) && typeof value["cwd"] === "string" && typeof value["model"] === "string" && typeof value["permission_mode"] === "string" && typeof value["source"] === "string";
5888
7749
  }
5889
7750
  function isStringOrNull(value) {
5890
7751
  return typeof value === "string" || value === null;
5891
7752
  }
5892
- function isRecord2(value) {
7753
+ function isRecord3(value) {
5893
7754
  return typeof value === "object" && value !== null && !Array.isArray(value);
5894
7755
  }
5895
7756
  function readStdin() {