@rasputin-ai/node 0.5.0-alpha.13 → 0.5.0-alpha.14

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 (79) hide show
  1. package/README.md +62 -33
  2. package/dist/auto-instrumentation/bun-plugin.d.ts.map +1 -1
  3. package/dist/auto-instrumentation/format-configuration-report.d.ts +4 -0
  4. package/dist/auto-instrumentation/format-configuration-report.d.ts.map +1 -1
  5. package/dist/auto-instrumentation/instrument-compiled-esm.d.ts +1 -3
  6. package/dist/auto-instrumentation/instrument-compiled-esm.d.ts.map +1 -1
  7. package/dist/auto-instrumentation/instrumentation-manifest-delta.d.ts +8 -4
  8. package/dist/auto-instrumentation/instrumentation-manifest-delta.d.ts.map +1 -1
  9. package/dist/auto-instrumentation/instrumentation-manifest-registry.d.ts +6 -0
  10. package/dist/auto-instrumentation/instrumentation-manifest-registry.d.ts.map +1 -1
  11. package/dist/auto-instrumentation/node-hooks.d.ts.map +1 -1
  12. package/dist/auto-instrumentation/parameter-initializer-may-run-code.d.ts +3 -0
  13. package/dist/auto-instrumentation/parameter-initializer-may-run-code.d.ts.map +1 -0
  14. package/dist/auto-instrumentation/schedule-instrumentation-manifest-upload.d.ts +1 -1
  15. package/dist/auto-instrumentation/schedule-instrumentation-manifest-upload.d.ts.map +1 -1
  16. package/dist/auto-instrumentation/source-map-locations.d.ts +1 -0
  17. package/dist/auto-instrumentation/source-map-locations.d.ts.map +1 -1
  18. package/dist/auto-instrumentation/suspension-whitelist.d.ts +33 -0
  19. package/dist/auto-instrumentation/suspension-whitelist.d.ts.map +1 -0
  20. package/dist/auto-instrumentation/transform-disk-cache.d.ts +7 -0
  21. package/dist/auto-instrumentation/transform-disk-cache.d.ts.map +1 -0
  22. package/dist/auto-instrumentation/transform-source.d.ts +9 -6
  23. package/dist/auto-instrumentation/transform-source.d.ts.map +1 -1
  24. package/dist/auto-instrumentation/verify-instrumentation-isomorphism.d.ts +2 -0
  25. package/dist/auto-instrumentation/verify-instrumentation-isomorphism.d.ts.map +1 -0
  26. package/dist/auto-instrumentation/verify-transformed-source.d.ts +2 -0
  27. package/dist/auto-instrumentation/verify-transformed-source.d.ts.map +1 -0
  28. package/dist/execution-recorder/automatic-runtime.d.ts +17 -7
  29. package/dist/execution-recorder/automatic-runtime.d.ts.map +1 -1
  30. package/dist/execution-recorder/encode-frozen.d.ts +16 -0
  31. package/dist/execution-recorder/encode-frozen.d.ts.map +1 -0
  32. package/dist/execution-recorder/execution-journal.d.ts.map +1 -1
  33. package/dist/execution-recorder/execution-recorder-types.d.ts +122 -38
  34. package/dist/execution-recorder/execution-recorder-types.d.ts.map +1 -1
  35. package/dist/execution-recorder/execution-recorder.d.ts +2 -2
  36. package/dist/execution-recorder/execution-recorder.d.ts.map +1 -1
  37. package/dist/execution-recorder/function-plan.d.ts +8 -1
  38. package/dist/execution-recorder/function-plan.d.ts.map +1 -1
  39. package/dist/execution-recorder/index.d.ts +1 -1
  40. package/dist/execution-recorder/index.d.ts.map +1 -1
  41. package/dist/execution-recorder/recorder-memory-budget.d.ts +1 -0
  42. package/dist/execution-recorder/recorder-memory-budget.d.ts.map +1 -1
  43. package/dist/execution-recorder/redact-keys.d.ts +4 -0
  44. package/dist/execution-recorder/redact-keys.d.ts.map +1 -0
  45. package/dist/execution-recorder/run-exactly-once.d.ts +7 -0
  46. package/dist/execution-recorder/run-exactly-once.d.ts.map +1 -0
  47. package/dist/execution-recorder/runtime-state-size-budget.d.ts +3 -3
  48. package/dist/execution-recorder/runtime-state-size-budget.d.ts.map +1 -1
  49. package/dist/execution-recorder/safe-serialize.d.ts +9 -3
  50. package/dist/execution-recorder/safe-serialize.d.ts.map +1 -1
  51. package/dist/execution-recorder/value-freeze.d.ts +43 -0
  52. package/dist/execution-recorder/value-freeze.d.ts.map +1 -0
  53. package/dist/execution-recorder/warn-missing-async-context-frame.d.ts +10 -0
  54. package/dist/execution-recorder/warn-missing-async-context-frame.d.ts.map +1 -0
  55. package/dist/index.d.ts +1 -6
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +2420 -954
  58. package/dist/install-global-handlers.d.ts +29 -8
  59. package/dist/install-global-handlers.d.ts.map +1 -1
  60. package/dist/instrument/build.js +947 -805
  61. package/dist/instrument/bun.js +1098 -778
  62. package/dist/instrument/node.js +1078 -780
  63. package/dist/internal.d.ts +7 -0
  64. package/dist/internal.d.ts.map +1 -0
  65. package/dist/internal.js +4072 -0
  66. package/dist/rasputin-init.d.ts +25 -5
  67. package/dist/rasputin-init.d.ts.map +1 -1
  68. package/dist/sdk-meta.d.ts +1 -1
  69. package/package.json +7 -2
  70. package/dist/derivation/analyze-function.d.ts +0 -47
  71. package/dist/derivation/analyze-function.d.ts.map +0 -1
  72. package/dist/derivation/build-dependency-graph.d.ts +0 -26
  73. package/dist/derivation/build-dependency-graph.d.ts.map +0 -1
  74. package/dist/derivation/derivation-ir.d.ts +0 -38
  75. package/dist/derivation/derivation-ir.d.ts.map +0 -1
  76. package/dist/derivation/emit-capture-plan.d.ts +0 -14
  77. package/dist/derivation/emit-capture-plan.d.ts.map +0 -1
  78. package/dist/derivation/plan-is-exact.d.ts +0 -7
  79. package/dist/derivation/plan-is-exact.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,107 +1,10 @@
1
- // src/auto-instrumentation/schedule-instrumentation-manifest-upload.ts
1
+ // src/rasputin-init.ts
2
+ import { join } from "node:path";
2
3
  import {
3
- detectRelease,
4
- resolveEndpointUrls,
5
- uploadInstrumentationManifest
4
+ createClient,
5
+ isClientEnabled
6
6
  } from "@rasputin-ai/core";
7
7
 
8
- // src/auto-instrumentation/format-configuration-report.ts
9
- var RULE = "-".repeat(64);
10
- var BANNER = [
11
- RULE,
12
- " ____ _ ____ ____ _ _ _____ ___ _ _",
13
- "| _ \\ / \\ / ___| | _ \\ | | | | |_ _| |_ _| | \\ | |",
14
- "| |_) | / _ \\ \\___ \\ | |_) | | | | | | | | | | \\| |",
15
- "| _ < / ___ \\ ___) | | __/ | |_| | | | | | | |\\ |",
16
- "|_| \\_\\ /_/ \\_\\ |____/ |_| \\___/ |_| |___| |_| \\_|",
17
- "",
18
- "",
19
- "CONFIGURATION:"
20
- ];
21
- var counted = (n, singular, plural) => `${n} ${n === 1 ? singular : plural}`;
22
- var issueHeadline = (issue) => {
23
- const target = issue.packageName ? `package ${issue.packageName}` : issue.packageRelativePath;
24
- if (issue.reason === "ambiguous") return `Could not uniquely locate ${target}.`;
25
- if (issue.reason === "not_found") return `Could not find ${target} in this Git release.`;
26
- if (issue.reason === "invalid_mapping") {
27
- return `The configured package root for ${target} does not match this Git release.`;
28
- }
29
- return `GitHub could not be reached while locating ${target}.`;
30
- };
31
- var formatIssue = (issue) => {
32
- const lines = [
33
- `! ${issueHeadline(issue)}`,
34
- "",
35
- " Captured:",
36
- ` ${issue.packageRelativePath}`
37
- ];
38
- if (issue.candidates?.length) {
39
- lines.push("", " Possible repository locations:");
40
- for (const candidate of issue.candidates) lines.push(` ${candidate}`);
41
- }
42
- return lines;
43
- };
44
- var formatConfigurationReport = (input) => {
45
- const packages = input.verification.packages ?? [];
46
- const unresolved = input.verification.unresolved;
47
- const mappingIssues = unresolved.filter((issue) => issue.reason !== "github_unavailable");
48
- const githubUnavailable = input.verification.status === "unavailable" || unresolved.some((issue) => issue.reason === "github_unavailable");
49
- const verified = input.uploaded && input.verification.status === "verified";
50
- const lines = [
51
- ...BANNER,
52
- "",
53
- "Release",
54
- `\u2713 ${input.release}`,
55
- "",
56
- "Runtime",
57
- `\u2713 ${input.runtime}`,
58
- "",
59
- "Instrumentation",
60
- `\u2713 ${counted(input.modules, "application module", "application modules")} observed`,
61
- `\u2713 ${counted(input.functions, "function", "functions")} instrumented`,
62
- `\u2713 ${counted(input.packageNames.length, "workspace package", "workspace packages")} detected`
63
- ];
64
- if (packages.length > 0 || mappingIssues.length > 0) {
65
- lines.push("", "Package roots");
66
- for (const mapping of packages) {
67
- lines.push(
68
- mapping.packageName ? `\u2713 ${mapping.packageName} \u2192 ${mapping.repositoryRoot}` : `\u2713 ${mapping.repositoryRoot}`
69
- );
70
- }
71
- for (const [index, issue] of mappingIssues.entries()) {
72
- if (packages.length > 0 || index > 0) lines.push("");
73
- lines.push(...formatIssue(issue));
74
- }
75
- }
76
- lines.push("", "Manifest");
77
- if (!input.uploaded) {
78
- lines.push("! upload failed");
79
- } else {
80
- lines.push("\u2713 uploaded");
81
- lines.push(
82
- verified ? "\u2713 verified against GitHub" : "! some source files could not be mapped to this Git release"
83
- );
84
- }
85
- lines.push("", "GitHub");
86
- if (!input.uploaded) {
87
- lines.push("! not verified");
88
- } else if (githubUnavailable) {
89
- lines.push("! repository is not connected, or this release could not be read");
90
- } else {
91
- lines.push("\u2713 repository connected");
92
- }
93
- if (input.uploaded && input.verification.status !== "verified") {
94
- lines.push("", "Runtime recording is unaffected.");
95
- }
96
- lines.push(RULE);
97
- return lines.join("\n");
98
- };
99
- var runtimeLabel = () => {
100
- const bun = globalThis.Bun;
101
- if (typeof bun?.version === "string" && bun.version) return `Bun ${bun.version}`;
102
- return `Node ${process.versions.node}`;
103
- };
104
-
105
8
  // src/auto-instrumentation/instrumentation-manifest-registry.ts
106
9
  import { createHash } from "node:crypto";
107
10
  import { existsSync, readFileSync } from "node:fs";
@@ -115,6 +18,8 @@ import {
115
18
  runtimeFunctionId,
116
19
  sourceLocatorFromFile
117
20
  } from "@rasputin-ai/core";
21
+ var encodedPlanOmitsCallValues = (plan) => plan[6] === 1;
22
+ var encodedPlanHasPreBodyParameterEvaluation = (plan) => plan[7] === 1;
118
23
  var EVENT_PAIR_BASE_ESTIMATED_BYTES = 512;
119
24
  var definitionFromEncodedPlan = (plan) => {
120
25
  const [functionId, name, packageName, packageRelativePath, line, column] = plan;
@@ -127,7 +32,8 @@ var definitionFromEncodedPlan = (plan) => {
127
32
  return {
128
33
  functionId,
129
34
  name,
130
- ...source ? { source } : {}
35
+ ...source ? { source } : {},
36
+ ...encodedPlanHasPreBodyParameterEvaluation(plan) ? { parentAttribution: "pre_body_parameter_evaluation" } : {}
131
37
  };
132
38
  };
133
39
  var estimatedCallBytesFor = (functionId) => EVENT_PAIR_BASE_ESTIMATED_BYTES + Buffer.byteLength(functionId, "utf8") * 2;
@@ -138,13 +44,16 @@ var registrySymbol = Symbol.for(INSTRUMENTATION_MANIFEST_SYMBOL);
138
44
  var getRegistry = () => {
139
45
  const existing = Reflect.get(globalThis, registrySymbol);
140
46
  if (existing?.__rasputinManifestRegistry && existing.files instanceof Map && typeof existing.generation === "number" && typeof existing.uploadedGeneration === "number") {
141
- return existing;
47
+ const registry2 = existing;
48
+ if (typeof registry2.alreadyInstrumented !== "number") registry2.alreadyInstrumented = 0;
49
+ return registry2;
142
50
  }
143
51
  const registry = {
144
52
  __rasputinManifestRegistry: true,
145
53
  files: /* @__PURE__ */ new Map(),
146
54
  generation: 0,
147
- uploadedGeneration: 0
55
+ uploadedGeneration: 0,
56
+ alreadyInstrumented: 0
148
57
  };
149
58
  Reflect.set(globalThis, registrySymbol, registry);
150
59
  return registry;
@@ -180,18 +89,60 @@ var isInstrumentationManifestDirty = () => {
180
89
  return registry.generation !== registry.uploadedGeneration && (registry.files.size > 0 || registry.prebuilt !== void 0);
181
90
  };
182
91
  var instrumentationManifestGeneration = () => getRegistry().generation;
92
+ var instrumentationCoverageStats = () => {
93
+ const registry = getRegistry();
94
+ let instrumented = 0;
95
+ let instrumentedAsync = 0;
96
+ const skippedByReason = {};
97
+ for (const delta of registry.files.values()) {
98
+ for (const fn of delta.functions) {
99
+ if (fn.instrumented === false) {
100
+ if (!fn.skipReason) continue;
101
+ skippedByReason[fn.skipReason] = (skippedByReason[fn.skipReason] ?? 0) + 1;
102
+ } else {
103
+ instrumented += 1;
104
+ if (fn.asyncFunction) instrumentedAsync += 1;
105
+ }
106
+ }
107
+ }
108
+ if (registry.alreadyInstrumented > 0) {
109
+ skippedByReason.already_instrumented = registry.alreadyInstrumented;
110
+ }
111
+ return {
112
+ instrumented,
113
+ instrumentedAsync,
114
+ alreadyInstrumented: registry.alreadyInstrumented,
115
+ skippedByReason
116
+ };
117
+ };
183
118
  var instrumentationManifestModuleCount = () => {
184
119
  const registry = getRegistry();
185
120
  if (registry.files.size > 0) return registry.files.size;
186
121
  if (!registry.prebuilt) return 0;
187
122
  return new Set(registry.prebuilt.functions.map((fn) => fn.source.packageRelativePath)).size;
188
123
  };
124
+ var snapshotOptionsKey = (options) => JSON.stringify({
125
+ sourceRoot: options.sourceRoot ?? "",
126
+ sourceRoots: options.sourceRoots ?? {}
127
+ });
189
128
  var snapshotInstrumentationManifest = (options = {}) => {
129
+ const registry = getRegistry();
130
+ const optionsKey = snapshotOptionsKey(options);
131
+ if (registry.snapshotCache && registry.snapshotCache.generation === registry.generation && registry.snapshotCache.optionsKey === optionsKey) {
132
+ return registry.snapshotCache.manifest;
133
+ }
190
134
  const functions = [];
191
135
  const callSites = [];
192
136
  const destructures = [];
193
- const derivationPlans = [];
194
- for (const delta of getRegistry().files.values()) {
137
+ const remember = (manifest) => {
138
+ registry.snapshotCache = {
139
+ generation: registry.generation,
140
+ optionsKey,
141
+ manifest
142
+ };
143
+ return manifest;
144
+ };
145
+ for (const delta of registry.files.values()) {
195
146
  for (const fn of delta.functions) {
196
147
  const definition = definitionFromEncodedPlan(fn.plan);
197
148
  if (!definition.source) continue;
@@ -203,7 +154,8 @@ var snapshotInstrumentationManifest = (options = {}) => {
203
154
  startColumn: fn.startColumn,
204
155
  endLine: fn.endLine,
205
156
  endColumn: fn.endColumn,
206
- params: fn.params
157
+ params: fn.params,
158
+ ...fn.instrumented === false ? { instrumented: false, skipReason: fn.skipReason } : {}
207
159
  });
208
160
  }
209
161
  for (const site of delta.callSites) {
@@ -242,25 +194,23 @@ var snapshotInstrumentationManifest = (options = {}) => {
242
194
  binding: destructure.binding
243
195
  });
244
196
  }
245
- derivationPlans.push(...delta.derivationPlans ?? []);
246
197
  }
247
- const registry = getRegistry();
248
198
  if (registry.prebuilt && registry.files.size === 0) {
249
199
  const prebuilt = registry.prebuilt;
250
- if (!options.sourceRoot && !options.sourceRoots) return prebuilt;
251
- return {
200
+ if (!options.sourceRoot && !options.sourceRoots) return remember(prebuilt);
201
+ return remember({
252
202
  ...prebuilt,
253
203
  sourceRoots: {
254
204
  ...options.sourceRoot ? { default: options.sourceRoot } : {},
255
205
  packages: { ...options.sourceRoots ?? {} }
256
206
  }
257
- };
207
+ });
258
208
  }
259
209
  if (functions.length === 0 && callSites.length === 0 && destructures.length === 0) {
260
- return void 0;
210
+ return remember(void 0);
261
211
  }
262
212
  const packages = { ...options.sourceRoots ?? {} };
263
- return {
213
+ return remember({
264
214
  schema_version: INSTRUMENTATION_MANIFEST_SCHEMA_VERSION,
265
215
  ...options.sourceRoot || Object.keys(packages).length > 0 ? {
266
216
  sourceRoots: {
@@ -270,9 +220,8 @@ var snapshotInstrumentationManifest = (options = {}) => {
270
220
  } : {},
271
221
  functions,
272
222
  callSites,
273
- destructures,
274
- derivationPlans
275
- };
223
+ destructures
224
+ });
276
225
  };
277
226
  var markInstrumentationManifestUploaded = (generation) => {
278
227
  const registry = getRegistry();
@@ -282,6 +231,116 @@ var setInstrumentationManifestOnDirty = (onDirty) => {
282
231
  getRegistry().onDirty = onDirty;
283
232
  };
284
233
 
234
+ // src/auto-instrumentation/schedule-instrumentation-manifest-upload.ts
235
+ import {
236
+ detectRelease,
237
+ resolveEndpointUrls,
238
+ uploadInstrumentationManifest
239
+ } from "@rasputin-ai/core";
240
+
241
+ // src/auto-instrumentation/format-configuration-report.ts
242
+ var RULE = "-".repeat(64);
243
+ var BANNER = [
244
+ RULE,
245
+ " ____ _ ____ ____ _ _ _____ ___ _ _",
246
+ "| _ \\ / \\ / ___| | _ \\ | | | | |_ _| |_ _| | \\ | |",
247
+ "| |_) | / _ \\ \\___ \\ | |_) | | | | | | | | | | \\| |",
248
+ "| _ < / ___ \\ ___) | | __/ | |_| | | | | | | |\\ |",
249
+ "|_| \\_\\ /_/ \\_\\ |____/ |_| \\___/ |_| |___| |_| \\_|",
250
+ "",
251
+ "",
252
+ "CONFIGURATION:"
253
+ ];
254
+ var counted = (n, singular, plural) => `${n} ${n === 1 ? singular : plural}`;
255
+ var issueHeadline = (issue) => {
256
+ const target = issue.packageName ? `package ${issue.packageName}` : issue.packageRelativePath;
257
+ if (issue.reason === "ambiguous") return `Could not uniquely locate ${target}.`;
258
+ if (issue.reason === "not_found") return `Could not find ${target} in this Git release.`;
259
+ if (issue.reason === "invalid_mapping") {
260
+ return `The configured package root for ${target} does not match this Git release.`;
261
+ }
262
+ return `GitHub could not be reached while locating ${target}.`;
263
+ };
264
+ var formatIssue = (issue) => {
265
+ const lines = [
266
+ `! ${issueHeadline(issue)}`,
267
+ "",
268
+ " Captured:",
269
+ ` ${issue.packageRelativePath}`
270
+ ];
271
+ if (issue.candidates?.length) {
272
+ lines.push("", " Possible repository locations:");
273
+ for (const candidate of issue.candidates) lines.push(` ${candidate}`);
274
+ }
275
+ return lines;
276
+ };
277
+ var formatConfigurationReport = (input) => {
278
+ const packages = input.verification.packages ?? [];
279
+ const unresolved = input.verification.unresolved;
280
+ const mappingIssues = unresolved.filter((issue) => issue.reason !== "github_unavailable");
281
+ const githubUnavailable = input.verification.status === "unavailable" || unresolved.some((issue) => issue.reason === "github_unavailable");
282
+ const verified = input.uploaded && input.verification.status === "verified";
283
+ const lines = [
284
+ ...BANNER,
285
+ "",
286
+ "Release",
287
+ `\u2713 ${input.release}`,
288
+ "",
289
+ "Runtime",
290
+ `\u2713 ${input.runtime}`,
291
+ "",
292
+ "Instrumentation",
293
+ `\u2713 ${counted(input.modules, "application module", "application modules")} observed`,
294
+ `\u2713 ${counted(input.functions, "function", "functions")} instrumented`,
295
+ ...input.instrumentedAsync ? [`\u2713 ${counted(input.instrumentedAsync, "async function", "async functions")} instrumented`] : [],
296
+ ...input.skippedFunctions ? [`! ${counted(input.skippedFunctions, "function", "functions")} skipped`] : [],
297
+ ...Object.entries(input.skippedByReason ?? {}).filter(([, count]) => (count ?? 0) > 0).sort(([left], [right]) => left.localeCompare(right)).map(([reason, count]) => ` ${reason}: ${count}`),
298
+ ...input.attributionDegradations ? [
299
+ `! ${counted(input.attributionDegradations, "runtime attribution degradation", "runtime attribution degradations")}`
300
+ ] : [],
301
+ `\u2713 ${counted(input.packageNames.length, "workspace package", "workspace packages")} detected`
302
+ ];
303
+ if (packages.length > 0 || mappingIssues.length > 0) {
304
+ lines.push("", "Package roots");
305
+ for (const mapping of packages) {
306
+ lines.push(
307
+ mapping.packageName ? `\u2713 ${mapping.packageName} \u2192 ${mapping.repositoryRoot}` : `\u2713 ${mapping.repositoryRoot}`
308
+ );
309
+ }
310
+ for (const [index, issue] of mappingIssues.entries()) {
311
+ if (packages.length > 0 || index > 0) lines.push("");
312
+ lines.push(...formatIssue(issue));
313
+ }
314
+ }
315
+ lines.push("", "Manifest");
316
+ if (!input.uploaded) {
317
+ lines.push("! upload failed");
318
+ } else {
319
+ lines.push("\u2713 uploaded");
320
+ lines.push(
321
+ verified ? "\u2713 verified against GitHub" : "! some source files could not be mapped to this Git release"
322
+ );
323
+ }
324
+ lines.push("", "GitHub");
325
+ if (!input.uploaded) {
326
+ lines.push("! not verified");
327
+ } else if (githubUnavailable) {
328
+ lines.push("! repository is not connected, or this release could not be read");
329
+ } else {
330
+ lines.push("\u2713 repository connected");
331
+ }
332
+ if (input.uploaded && input.verification.status !== "verified") {
333
+ lines.push("", "Runtime recording is unaffected.");
334
+ }
335
+ lines.push(RULE);
336
+ return lines.join("\n");
337
+ };
338
+ var runtimeLabel = () => {
339
+ const bun = globalThis.Bun;
340
+ if (typeof bun?.version === "string" && bun.version) return `Bun ${bun.version}`;
341
+ return `Node ${process.versions.node}`;
342
+ };
343
+
285
344
  // src/auto-instrumentation/schedule-instrumentation-manifest-upload.ts
286
345
  var unavailable = () => ({
287
346
  status: "unavailable",
@@ -301,81 +360,162 @@ var noopHandle = {
301
360
  }
302
361
  };
303
362
  var scheduleInstrumentationManifestUpload = (options) => {
304
- const release = detectRelease({ release: options.release });
305
- if (!options.enabled || !release || !options.projectApiKey.trim()) {
363
+ if (!options.enabled || !(options.projectApiKey ?? "").trim()) {
306
364
  return noopHandle;
307
365
  }
366
+ const release = detectRelease({ release: options.release });
367
+ if (!release) return noopHandle;
308
368
  const { instrumentationManifestUrl } = resolveEndpointUrls(options.apiUrl);
309
- let inflight;
369
+ let inflight = Promise.resolve();
310
370
  let verification = unavailable();
311
371
  let loggedSuccess = false;
312
372
  let loggedFailure = false;
373
+ let stopped = false;
374
+ let working = false;
375
+ let debounceTimer;
376
+ const sessionAbort = new AbortController();
377
+ const debounceMs = 500;
313
378
  const packageNamesOf = (manifest) => [
314
379
  ...new Set(
315
380
  manifest.functions.map((fn) => fn.source.packageName).filter((name) => Boolean(name))
316
381
  )
317
382
  ].sort();
318
383
  const report = (manifest, uploaded, next) => {
384
+ const coverage = instrumentationCoverageStats();
319
385
  return formatConfigurationReport({
320
386
  release,
321
387
  runtime: runtimeLabel(),
322
388
  modules: instrumentationManifestModuleCount(),
323
- functions: manifest.functions.length,
389
+ functions: manifest.functions.filter((fn) => fn.instrumented !== false).length,
390
+ skippedFunctions: manifest.functions.filter((fn) => fn.instrumented === false).length,
391
+ instrumentedAsync: coverage.instrumentedAsync,
392
+ skippedByReason: coverage.skippedByReason,
324
393
  packageNames: packageNamesOf(manifest),
325
394
  verification: next,
326
395
  uploaded
327
396
  });
328
397
  };
398
+ const clearDebounce = () => {
399
+ if (debounceTimer === void 0) return;
400
+ clearTimeout(debounceTimer);
401
+ debounceTimer = void 0;
402
+ };
329
403
  const flushSoon = () => {
330
- if (!isInstrumentationManifestDirty()) return;
331
- const generation = instrumentationManifestGeneration();
332
- const manifest = snapshotInstrumentationManifest({
333
- sourceRoot: options.sourceRoot,
334
- sourceRoots: options.sourceRoots
335
- });
336
- if (!manifest) {
337
- markInstrumentationManifestUploaded(generation);
338
- return;
339
- }
340
- const work = uploadInstrumentationManifest({
341
- url: instrumentationManifestUrl,
342
- projectApiKey: options.projectApiKey,
343
- release,
344
- manifest,
345
- fetch: options.fetch
346
- }).then((result) => {
347
- if (result.ok) {
348
- verification = result.verification;
349
- markInstrumentationManifestUploaded(generation);
350
- if (verification.status === "verified") {
351
- if (!loggedSuccess && options.logSuccess !== false) {
352
- loggedSuccess = true;
353
- console.info(report(manifest, true, verification));
404
+ clearDebounce();
405
+ if (stopped || !isInstrumentationManifestDirty() || working) return;
406
+ working = true;
407
+ inflight = inflight.catch(() => {
408
+ }).then(async () => {
409
+ try {
410
+ while (!stopped && isInstrumentationManifestDirty()) {
411
+ const generation = instrumentationManifestGeneration();
412
+ const manifest = snapshotInstrumentationManifest({
413
+ sourceRoot: options.sourceRoot,
414
+ sourceRoots: options.sourceRoots
415
+ });
416
+ if (!manifest) {
417
+ markInstrumentationManifestUploaded(generation);
418
+ continue;
419
+ }
420
+ const controller = new AbortController();
421
+ const timeout = setTimeout(() => controller.abort(), 2e3);
422
+ timeout.unref?.();
423
+ const abortUpload = () => controller.abort();
424
+ sessionAbort.signal.addEventListener("abort", abortUpload, { once: true });
425
+ if (sessionAbort.signal.aborted) controller.abort();
426
+ const aborted = new Promise((_, reject) => {
427
+ const fail = () => reject(controller.signal.reason ?? new Error("aborted"));
428
+ if (controller.signal.aborted) {
429
+ fail();
430
+ return;
431
+ }
432
+ controller.signal.addEventListener("abort", fail, { once: true });
433
+ });
434
+ try {
435
+ const result = await Promise.race([
436
+ uploadInstrumentationManifest({
437
+ url: instrumentationManifestUrl,
438
+ projectApiKey: options.projectApiKey,
439
+ release,
440
+ manifest,
441
+ fetch: options.fetch,
442
+ signal: controller.signal
443
+ }),
444
+ aborted
445
+ ]);
446
+ if (stopped) return;
447
+ if (result.ok) {
448
+ verification = result.verification;
449
+ markInstrumentationManifestUploaded(generation);
450
+ if (verification.status === "verified") {
451
+ if (!loggedSuccess && options.logSuccess !== false) {
452
+ loggedSuccess = true;
453
+ console.info(report(manifest, true, verification));
454
+ }
455
+ continue;
456
+ }
457
+ if (!loggedFailure) {
458
+ loggedFailure = true;
459
+ console.warn(report(manifest, true, verification));
460
+ }
461
+ continue;
462
+ }
463
+ if (!loggedFailure) {
464
+ loggedFailure = true;
465
+ console.warn(report(manifest, false, unavailable()));
466
+ }
467
+ break;
468
+ } catch {
469
+ if (stopped) return;
470
+ break;
471
+ } finally {
472
+ clearTimeout(timeout);
473
+ sessionAbort.signal.removeEventListener("abort", abortUpload);
354
474
  }
355
- return;
356
- }
357
- if (!loggedFailure) {
358
- loggedFailure = true;
359
- console.warn(report(manifest, true, verification));
360
475
  }
361
- return;
362
- }
363
- if (!loggedFailure) {
364
- loggedFailure = true;
365
- console.warn(report(manifest, false, unavailable()));
476
+ } finally {
477
+ working = false;
366
478
  }
367
479
  });
368
- inflight = inflight ? inflight.then(() => work) : work;
369
480
  };
370
- setInstrumentationManifestOnDirty(flushSoon);
371
- flushSoon();
481
+ const armFlush = () => {
482
+ if (stopped || !isInstrumentationManifestDirty()) return;
483
+ clearDebounce();
484
+ debounceTimer = setTimeout(() => {
485
+ debounceTimer = void 0;
486
+ flushSoon();
487
+ }, debounceMs);
488
+ debounceTimer.unref?.();
489
+ };
490
+ setInstrumentationManifestOnDirty(armFlush);
491
+ if (isInstrumentationManifestDirty()) armFlush();
372
492
  return {
373
493
  flushSoon,
374
- wait: async () => {
375
- await inflight;
376
- },
494
+ wait: async (timeoutMs) => {
495
+ flushSoon();
496
+ if (timeoutMs === void 0) {
497
+ await inflight;
498
+ return;
499
+ }
500
+ await new Promise((resolve) => {
501
+ const timer = setTimeout(resolve, timeoutMs);
502
+ void inflight.then(
503
+ () => {
504
+ clearTimeout(timer);
505
+ resolve();
506
+ },
507
+ () => {
508
+ clearTimeout(timer);
509
+ resolve();
510
+ }
511
+ );
512
+ });
513
+ },
377
514
  disconnect: () => {
515
+ stopped = true;
516
+ clearDebounce();
378
517
  setInstrumentationManifestOnDirty(void 0);
518
+ sessionAbort.abort();
379
519
  },
380
520
  verify: async () => {
381
521
  flushSoon();
@@ -388,8 +528,6 @@ var scheduleInstrumentationManifestUpload = (options) => {
388
528
  // src/execution-recorder/execution-recorder.ts
389
529
  import { AsyncLocalStorage } from "node:async_hooks";
390
530
  import {
391
- capturedValueCompleteness,
392
- hashInstrumentationManifest,
393
531
  rasputinOmitted,
394
532
  rasputinTagKind,
395
533
  runtimeFunctionId as runtimeFunctionId2
@@ -476,13 +614,18 @@ var ExecutionJournal = class {
476
614
  args,
477
615
  NO_SUPPRESSION
478
616
  )) {
617
+ this.dropped += 2;
479
618
  return;
480
619
  }
481
620
  this.openCallIds.add(callId);
482
621
  }
483
622
  finishCall(kind, callId, timestampNs, durationNs, payload) {
484
- if (!this.openCallIds.delete(callId)) return;
485
- this.write(kind, 0, callId, void 0, timestampNs, durationNs, payload, NO_SUPPRESSION);
623
+ if (!this.openCallIds.has(callId)) return;
624
+ if (!this.write(kind, 0, callId, void 0, timestampNs, durationNs, payload, NO_SUPPRESSION)) {
625
+ this.dropped++;
626
+ return;
627
+ }
628
+ this.openCallIds.delete(callId);
486
629
  }
487
630
  dropCall() {
488
631
  this.dropped += 2;
@@ -813,6 +956,10 @@ var RecorderMemoryBudget = class {
813
956
  return allocation;
814
957
  }
815
958
  captureValue(allocation, serialize) {
959
+ if (allocation.released) {
960
+ this.dropValues(allocation, 1);
961
+ return MEMORY_BUDGET_VALUE_MARKER;
962
+ }
816
963
  if (allocation.mode !== "full") {
817
964
  this.dropValues(allocation, 1);
818
965
  return MEMORY_BUDGET_VALUE_MARKER;
@@ -857,6 +1004,13 @@ var RecorderMemoryBudget = class {
857
1004
  this.markPressure(allocation, "metadata-only");
858
1005
  return false;
859
1006
  }
1007
+ releaseStorage(allocation, bytes) {
1008
+ if (allocation.released) return;
1009
+ const boundedBytes = Math.max(0, Math.ceil(bytes));
1010
+ allocation.estimatedBytes = Math.max(0, allocation.estimatedBytes - boundedBytes);
1011
+ this.activeEstimatedBytes = Math.max(0, this.activeEstimatedBytes - boundedBytes);
1012
+ this.stats.activeEstimatedBytes = this.activeEstimatedBytes;
1013
+ }
860
1014
  release(allocation) {
861
1015
  if (allocation.released) return;
862
1016
  allocation.released = true;
@@ -867,6 +1021,7 @@ var RecorderMemoryBudget = class {
867
1021
  return { ...this.stats };
868
1022
  }
869
1023
  reserve(allocation, bytes) {
1024
+ if (allocation.released) return false;
870
1025
  const boundedBytes = Math.max(0, Math.ceil(bytes));
871
1026
  if (this.activeEstimatedBytes + boundedBytes > this.maximumBytes) return false;
872
1027
  this.activeEstimatedBytes += boundedBytes;
@@ -899,13 +1054,34 @@ var RecorderMemoryBudget = class {
899
1054
  }
900
1055
  };
901
1056
 
1057
+ // src/execution-recorder/run-exactly-once.ts
1058
+ var runExactlyOnce = function __rasputinHandleRun__(invoke, callback) {
1059
+ let outcome;
1060
+ const wrapped = function __rasputinHandleRun__3() {
1061
+ try {
1062
+ const value = callback();
1063
+ outcome = { kind: "value", value };
1064
+ return value;
1065
+ } catch (caught) {
1066
+ outcome = { kind: "throw", error: caught };
1067
+ throw caught;
1068
+ }
1069
+ };
1070
+ try {
1071
+ invoke(wrapped);
1072
+ } catch {
1073
+ }
1074
+ if (outcome?.kind === "throw") throw outcome.error;
1075
+ if (outcome?.kind === "value") return outcome.value;
1076
+ return callback();
1077
+ };
1078
+
902
1079
  // src/execution-recorder/runtime-state-size-budget.ts
903
1080
  import {
904
1081
  rasputinUnavailable
905
1082
  } from "@rasputin-ai/core";
906
1083
  var DEFAULT_RUNTIME_STATE_TARGET_BYTES = 256 * 1024;
907
1084
  var DEFAULT_MAX_RUNTIME_STATE_BYTES = 512 * 1024;
908
- var SIZE_METADATA_HEADROOM_BYTES = 256;
909
1085
  var VALUE_OMITTED_REASON = "runtime_state_size_budget";
910
1086
  var encodedBytes = (value) => Buffer.byteLength(JSON.stringify(value), "utf8");
911
1087
  var boundedLimit = (value, fallback) => Number.isFinite(value) ? Math.max(4 * 1024, Math.floor(value)) : fallback;
@@ -915,8 +1091,6 @@ var sizeMetadata = (originalBytes, targetBytes, maximumBytes) => ({
915
1091
  finalBytes: 0,
916
1092
  targetBytes,
917
1093
  maximumBytes,
918
- derivationRootsDropped: 0,
919
- derivationControlFactsDropped: 0,
920
1094
  eventValuesDropped: 0,
921
1095
  eventsDropped: 0,
922
1096
  functionDefinitionsDropped: 0
@@ -932,10 +1106,10 @@ var withSizeMetadata = (state, size) => ({
932
1106
  var settleFinalBytes = (state) => {
933
1107
  const size = state.truncated?.size;
934
1108
  if (!size) return state;
935
- for (let attempt = 0; attempt < 4; attempt++) {
936
- const bytes = encodedBytes(state);
937
- if (size.finalBytes === bytes) break;
938
- size.finalBytes = bytes;
1109
+ for (let attempt = 0; attempt < 3; attempt++) {
1110
+ const encoded = encodedBytes(state);
1111
+ if (size.finalBytes === encoded) break;
1112
+ size.finalBytes = encoded;
939
1113
  }
940
1114
  return state;
941
1115
  };
@@ -990,8 +1164,7 @@ var minimalState = (state, size) => {
990
1164
  source: state.captureProfile.source,
991
1165
  functionBoundaries: state.captureProfile.functionBoundaries === "none" ? "none" : "partial",
992
1166
  functionValues: "none",
993
- timings: state.captureProfile.timings === "none" ? "none" : "partial",
994
- derivation: "none"
1167
+ timings: state.captureProfile.timings === "none" ? "none" : "partial"
995
1168
  },
996
1169
  executionId: truncateUtf8(state.executionId, 256) ?? "",
997
1170
  startedAt: truncateUtf8(state.startedAt, 128) ?? "",
@@ -1016,54 +1189,10 @@ var enforceRuntimeStateSizeBudget = (input, options = {}) => {
1016
1189
  const initialBytes = encodedBytes(input);
1017
1190
  const existingSize = input.truncated?.size;
1018
1191
  if (existingSize && initialBytes <= maximumBytes) return settleFinalBytes(input);
1019
- if (initialBytes <= targetBytes) return input;
1192
+ if (initialBytes <= maximumBytes) return input;
1020
1193
  const originalBytes = existingSize?.originalBytes ?? initialBytes;
1021
1194
  const size = sizeMetadata(originalBytes, targetBytes, maximumBytes);
1022
1195
  let state = input;
1023
- const roots = input.derivation?.roots ?? [];
1024
- const controlFacts = input.derivation?.controlFacts ?? [];
1025
- if (input.derivation && (roots.length > 0 || controlFacts.length > 0)) {
1026
- const targetWithHeadroom = Math.max(0, targetBytes - SIZE_METADATA_HEADROOM_BYTES);
1027
- const candidate = (retainedRoots, retainControlFacts) => {
1028
- const derivationRoots = retainedRoots === 0 ? [] : roots.slice(roots.length - retainedRoots);
1029
- const candidateSize = {
1030
- ...size,
1031
- derivationRootsDropped: roots.length - retainedRoots,
1032
- derivationControlFactsDropped: retainControlFacts ? 0 : controlFacts.length
1033
- };
1034
- return withSizeMetadata(
1035
- {
1036
- ...input,
1037
- derivation: {
1038
- ...input.derivation,
1039
- roots: derivationRoots,
1040
- controlFacts: retainControlFacts ? controlFacts.slice() : []
1041
- }
1042
- },
1043
- candidateSize
1044
- );
1045
- };
1046
- let low = 0;
1047
- let high = roots.length;
1048
- let best = null;
1049
- while (low <= high) {
1050
- const retained = Math.floor((low + high) / 2);
1051
- const attempt = candidate(retained, true);
1052
- if (encodedBytes(attempt) <= targetWithHeadroom) {
1053
- best = attempt;
1054
- low = retained + 1;
1055
- } else {
1056
- high = retained - 1;
1057
- }
1058
- }
1059
- state = best ?? candidate(0, false);
1060
- Object.assign(size, state.truncated.size);
1061
- }
1062
- if (size.derivationRootsDropped === 0 && size.derivationControlFactsDropped === 0 && initialBytes <= maximumBytes) {
1063
- return input;
1064
- }
1065
- state = settleFinalBytes(withSizeMetadata(state, size));
1066
- if (encodedBytes(state) <= maximumBytes) return state;
1067
1196
  const stripped = dropEventValues(state.events);
1068
1197
  size.eventValuesDropped += stripped.dropped;
1069
1198
  state = settleFinalBytes(
@@ -1090,12 +1219,10 @@ var enforceRuntimeStateSizeBudget = (input, options = {}) => {
1090
1219
  ...state.captureProfile,
1091
1220
  functionBoundaries: state.captureProfile.functionBoundaries === "none" ? "none" : "partial",
1092
1221
  functionValues: "none",
1093
- timings: state.captureProfile.timings === "none" ? "none" : "partial",
1094
- derivation: "none"
1222
+ timings: state.captureProfile.timings === "none" ? "none" : "partial"
1095
1223
  },
1096
1224
  functions: [],
1097
1225
  events: [],
1098
- derivation: void 0,
1099
1226
  truncated: {
1100
1227
  eventsDropped: (state.truncated?.eventsDropped ?? 0) + size.eventsDropped,
1101
1228
  size
@@ -1113,8 +1240,7 @@ var enforceRuntimeStateSizeBudget = (input, options = {}) => {
1113
1240
  source: state.captureProfile.source,
1114
1241
  functionBoundaries: "partial",
1115
1242
  functionValues: "none",
1116
- timings: "partial",
1117
- derivation: "none"
1243
+ timings: "partial"
1118
1244
  },
1119
1245
  executionId: "",
1120
1246
  startedAt: "",
@@ -1127,17 +1253,49 @@ var enforceRuntimeStateSizeBudget = (input, options = {}) => {
1127
1253
  return settleFinalBytes(emergency);
1128
1254
  };
1129
1255
 
1130
- // src/execution-recorder/safe-serialize.ts
1256
+ // src/execution-recorder/encode-frozen.ts
1257
+ import { Buffer as Buffer3 } from "node:buffer";
1258
+
1259
+ // src/execution-recorder/value-freeze.ts
1131
1260
  import { Buffer as Buffer2 } from "node:buffer";
1132
- var DEFAULT_REDACT_KEYS = [
1133
- "password",
1134
- "token",
1135
- "authorization",
1136
- "cookie",
1137
- "secret",
1138
- "apikey",
1139
- "creditcard"
1140
- ];
1261
+ import { types } from "node:util";
1262
+ import { RASPUTIN_WIRE_TAG } from "@rasputin-ai/core";
1263
+
1264
+ // src/execution-recorder/redact-keys.ts
1265
+ import { defaultSensitivePropertyNames, propertyNameIsSensitive } from "@rasputin-ai/core";
1266
+ var compactKey = (key) => {
1267
+ let compacted = "";
1268
+ for (let index = 0; index < key.length; index++) {
1269
+ const code = key.charCodeAt(index);
1270
+ if (code === 45 || code === 46 || code === 95) continue;
1271
+ compacted += code >= 65 && code <= 90 ? String.fromCharCode(code + 32) : key[index];
1272
+ }
1273
+ return compacted;
1274
+ };
1275
+ var stripTrailingDigits = (value) => {
1276
+ let end = value.length;
1277
+ while (end > 0) {
1278
+ const code = value.charCodeAt(end - 1);
1279
+ if (code < 48 || code > 57) break;
1280
+ end--;
1281
+ }
1282
+ return end === 0 ? value : value.slice(0, end);
1283
+ };
1284
+ var normalizeKey = (key) => stripTrailingDigits(compactKey(key));
1285
+ var compileRedactKeys = (extra) => {
1286
+ if (!extra?.length) return defaultSensitivePropertyNames();
1287
+ return /* @__PURE__ */ new Set([...defaultSensitivePropertyNames(), ...extra.map(normalizeKey)]);
1288
+ };
1289
+ var keyIsRedacted = (key, redactKeys) => {
1290
+ if (propertyNameIsSensitive(key)) return true;
1291
+ if (redactKeys.has(key)) return true;
1292
+ const compacted = compactKey(key);
1293
+ if (redactKeys.has(compacted)) return true;
1294
+ return redactKeys.has(stripTrailingDigits(compacted));
1295
+ };
1296
+
1297
+ // src/execution-recorder/value-freeze.ts
1298
+ var REDACTED = "[RASPUTIN_REDACTED]";
1141
1299
  var defaults = {
1142
1300
  maxDepth: 3,
1143
1301
  maxObjectKeys: 30,
@@ -1145,441 +1303,1017 @@ var defaults = {
1145
1303
  maxStringLength: 500,
1146
1304
  maxSerializedValueBytes: 8 * 1024
1147
1305
  };
1148
- var REDACTED = "[RASPUTIN_REDACTED]";
1149
- var truncation = (reason, extra = {}) => ({
1150
- __rasputin_truncated: true,
1151
- __reason: reason,
1152
- ...extra
1306
+ var compileFreezeLimits = (options) => ({
1307
+ maxDepth: options.maxDepth ?? defaults.maxDepth,
1308
+ maxObjectKeys: options.maxObjectKeys ?? defaults.maxObjectKeys,
1309
+ maxArrayElements: options.maxArrayElements ?? defaults.maxArrayElements,
1310
+ maxStringLength: options.maxStringLength ?? defaults.maxStringLength,
1311
+ maxSerializedValueBytes: options.maxSerializedValueBytes ?? defaults.maxSerializedValueBytes
1153
1312
  });
1154
- var typeMarker = (type, value) => ({
1155
- __rasputin_type: type,
1156
- ...value === void 0 ? {} : { value }
1313
+ var FROZEN = Symbol("rasputin.frozen");
1314
+ var NODE = 24;
1315
+ var taggedNumberKind = (value) => {
1316
+ if (Number.isNaN(value)) return "NaN";
1317
+ if (value === Infinity) return "Infinity";
1318
+ if (value === -Infinity) return "-Infinity";
1319
+ if (Object.is(value, -0)) return "-0";
1320
+ return void 0;
1321
+ };
1322
+ var atom = (kind, extra = {}) => ({
1323
+ [FROZEN]: kind,
1324
+ ...extra
1157
1325
  });
1158
- var jsonStringUtf8Bytes = (value) => {
1159
- let bytes = 2;
1160
- for (let index = 0; index < value.length; index++) {
1161
- const code = value.charCodeAt(index);
1162
- if (code === 34 || code === 92) {
1163
- bytes += 2;
1164
- continue;
1165
- }
1166
- if (code === 8 || code === 9 || code === 10 || code === 12 || code === 13) {
1167
- bytes += 2;
1168
- continue;
1326
+ var ownData = (value, key) => {
1327
+ try {
1328
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1329
+ if (!descriptor) return void 0;
1330
+ if ("value" in descriptor) return { present: true, value: descriptor.value };
1331
+ return void 0;
1332
+ } catch {
1333
+ return void 0;
1334
+ }
1335
+ };
1336
+ var nativeErrorStackGet = (() => {
1337
+ try {
1338
+ return Object.getOwnPropertyDescriptor(Error.prototype, "stack")?.get;
1339
+ } catch {
1340
+ return void 0;
1341
+ }
1342
+ })();
1343
+ var nativeInstanceStackGet = (() => {
1344
+ try {
1345
+ const probe = new Error("rasputin-stack-probe");
1346
+ return Object.getOwnPropertyDescriptor(probe, "stack")?.get;
1347
+ } catch {
1348
+ return void 0;
1349
+ }
1350
+ })();
1351
+ var nativeErrorMessageGet = (() => {
1352
+ try {
1353
+ return Object.getOwnPropertyDescriptor(Error.prototype, "message")?.get;
1354
+ } catch {
1355
+ return void 0;
1356
+ }
1357
+ })();
1358
+ var typedArrayProto = Object.getPrototypeOf(Uint8Array.prototype);
1359
+ var typedArrayByteLengthGet = typedArrayProto ? Object.getOwnPropertyDescriptor(typedArrayProto, "byteLength")?.get : void 0;
1360
+ var typedArrayByteOffsetGet = typedArrayProto ? Object.getOwnPropertyDescriptor(typedArrayProto, "byteOffset")?.get : void 0;
1361
+ var typedArrayBufferGet = typedArrayProto ? Object.getOwnPropertyDescriptor(typedArrayProto, "buffer")?.get : void 0;
1362
+ var dataViewByteLengthGet = Object.getOwnPropertyDescriptor(
1363
+ DataView.prototype,
1364
+ "byteLength"
1365
+ )?.get;
1366
+ var domExceptionNameGet = typeof DOMException === "undefined" ? void 0 : Object.getOwnPropertyDescriptor(DOMException.prototype, "name")?.get;
1367
+ var domExceptionMessageGet = typeof DOMException === "undefined" ? void 0 : Object.getOwnPropertyDescriptor(DOMException.prototype, "message")?.get;
1368
+ var prepareStackTraceDepth = 0;
1369
+ var savedPrepareStackTrace;
1370
+ var withoutPrepareStackTrace = (read) => {
1371
+ if (prepareStackTraceDepth === 0) {
1372
+ savedPrepareStackTrace = Error.prepareStackTrace;
1373
+ Error.prepareStackTrace = void 0;
1374
+ }
1375
+ prepareStackTraceDepth += 1;
1376
+ try {
1377
+ return read();
1378
+ } finally {
1379
+ prepareStackTraceDepth -= 1;
1380
+ if (prepareStackTraceDepth === 0) Error.prepareStackTrace = savedPrepareStackTrace;
1381
+ }
1382
+ };
1383
+ var isDomException = (value) => {
1384
+ try {
1385
+ return typeof DOMException !== "undefined" && value instanceof DOMException;
1386
+ } catch {
1387
+ return false;
1388
+ }
1389
+ };
1390
+ var functionNameOf = (value) => {
1391
+ const own = ownData(value, "name");
1392
+ if (own && typeof own.value === "string" && own.value.length > 0) return own.value;
1393
+ return "anonymous";
1394
+ };
1395
+ var errorNameOf = (value) => {
1396
+ if (isDomException(value) && domExceptionNameGet) {
1397
+ try {
1398
+ const name = domExceptionNameGet.call(value);
1399
+ if (typeof name === "string" && name.length > 0) return name;
1400
+ } catch {
1169
1401
  }
1170
- if (code < 32) {
1171
- bytes += 6;
1172
- continue;
1402
+ }
1403
+ let current = value;
1404
+ while (current) {
1405
+ const slot = ownData(current, "name");
1406
+ if (slot && typeof slot.value === "string" && slot.value.length > 0) return slot.value;
1407
+ try {
1408
+ current = Object.getPrototypeOf(current);
1409
+ } catch {
1410
+ break;
1173
1411
  }
1174
- if (code < 128) {
1175
- bytes += 1;
1176
- continue;
1412
+ }
1413
+ return "Error";
1414
+ };
1415
+ var errorMessageOf = (value) => {
1416
+ if (isDomException(value) && domExceptionMessageGet) {
1417
+ try {
1418
+ return domExceptionMessageGet.call(value);
1419
+ } catch {
1177
1420
  }
1178
- if (code < 2048) {
1179
- bytes += 2;
1180
- continue;
1421
+ }
1422
+ const own = ownData(value, "message");
1423
+ if (own) return own.value;
1424
+ if (!nativeErrorMessageGet) return void 0;
1425
+ try {
1426
+ return nativeErrorMessageGet.call(value);
1427
+ } catch {
1428
+ return void 0;
1429
+ }
1430
+ };
1431
+ var errorStackOf = (value) => withoutPrepareStackTrace(() => {
1432
+ const own = ownData(value, "stack");
1433
+ if (own && typeof own.value === "string" && own.value.length > 0) return own.value;
1434
+ try {
1435
+ const getter = Object.getOwnPropertyDescriptor(value, "stack")?.get;
1436
+ if (getter && nativeInstanceStackGet && getter === nativeInstanceStackGet) {
1437
+ const stack = getter.call(value);
1438
+ if (typeof stack === "string" && stack.length > 0) return stack;
1181
1439
  }
1182
- if (code >= 55296 && code <= 56319) {
1183
- const next = value.charCodeAt(index + 1);
1184
- if (index + 1 < value.length && next >= 56320 && next <= 57343) {
1185
- bytes += 4;
1186
- index++;
1187
- continue;
1188
- }
1189
- bytes += 6;
1190
- continue;
1440
+ } catch {
1441
+ }
1442
+ if (!nativeErrorStackGet) return void 0;
1443
+ try {
1444
+ const stack = nativeErrorStackGet.call(value);
1445
+ return typeof stack === "string" && stack.length > 0 ? stack : void 0;
1446
+ } catch {
1447
+ return void 0;
1448
+ }
1449
+ });
1450
+ var viewByteLength = (value) => {
1451
+ try {
1452
+ if (types.isDataView(value)) {
1453
+ return dataViewByteLengthGet ? dataViewByteLengthGet.call(value) : 0;
1191
1454
  }
1192
- if (code >= 56320 && code <= 57343) {
1193
- bytes += 6;
1194
- continue;
1455
+ return typedArrayByteLengthGet ? typedArrayByteLengthGet.call(value) : 0;
1456
+ } catch {
1457
+ return 0;
1458
+ }
1459
+ };
1460
+ var typedArrayName = (value) => {
1461
+ if (types.isUint8Array(value)) return "Uint8Array";
1462
+ if (types.isUint8ClampedArray(value)) return "Uint8ClampedArray";
1463
+ if (types.isInt8Array(value)) return "Int8Array";
1464
+ if (types.isUint16Array(value)) return "Uint16Array";
1465
+ if (types.isInt16Array(value)) return "Int16Array";
1466
+ if (types.isUint32Array(value)) return "Uint32Array";
1467
+ if (types.isInt32Array(value)) return "Int32Array";
1468
+ if (types.isFloat32Array(value)) return "Float32Array";
1469
+ if (types.isFloat64Array(value)) return "Float64Array";
1470
+ if (types.isBigUint64Array(value)) return "BigUint64Array";
1471
+ if (types.isBigInt64Array(value)) return "BigInt64Array";
1472
+ return "TypedArray";
1473
+ };
1474
+ var prototypeChainHasProxy = (value) => {
1475
+ let current = value;
1476
+ for (let depth = 0; depth < 8; depth++) {
1477
+ try {
1478
+ current = Object.getPrototypeOf(current);
1479
+ } catch {
1480
+ return true;
1195
1481
  }
1196
- bytes += 3;
1482
+ if (!current) return false;
1483
+ if (types.isProxy(current)) return true;
1197
1484
  }
1198
- return bytes;
1485
+ return true;
1199
1486
  };
1200
- var jsonLiteralUtf8Bytes = (value) => {
1201
- if (value === null) return 4;
1202
- switch (typeof value) {
1203
- case "boolean":
1204
- return value ? 4 : 5;
1205
- case "number":
1206
- if (!Number.isFinite(value)) return 4;
1207
- if (Object.is(value, -0)) return 1;
1208
- return String(value).length;
1209
- case "string":
1210
- return jsonStringUtf8Bytes(value);
1211
- case "object": {
1212
- if (Array.isArray(value)) {
1213
- let bytes2 = 2;
1214
- for (let index = 0; index < value.length; index++) {
1215
- if (index > 0) bytes2 += 1;
1216
- bytes2 += jsonLiteralUtf8Bytes(value[index]);
1217
- }
1218
- return bytes2;
1219
- }
1220
- const record = value;
1221
- let bytes = 2;
1222
- let first = true;
1223
- for (const key of Object.keys(record)) {
1224
- if (!first) bytes += 1;
1225
- first = false;
1226
- bytes += jsonStringUtf8Bytes(key) + 1;
1227
- bytes += jsonLiteralUtf8Bytes(record[key]);
1228
- }
1229
- return bytes;
1487
+ var sampleBytes = (bytes, max) => {
1488
+ const length = Math.min(max, bytes.length);
1489
+ const sample = new Array(length);
1490
+ for (let index = 0; index < length; index++) sample[index] = bytes[index] ?? 0;
1491
+ return sample;
1492
+ };
1493
+ var RESERVED_USER_KEYS = /* @__PURE__ */ new Set([
1494
+ "__proto__",
1495
+ "__rasputin_type",
1496
+ "__rasputin_truncated",
1497
+ "__rasputin_fields",
1498
+ "__reason",
1499
+ "__original_length",
1500
+ "__serialized_bytes"
1501
+ ]);
1502
+ var assignFrozenField = (fields, key, value) => {
1503
+ if (RESERVED_USER_KEYS.has(key) || key.startsWith("__rasputin_")) {
1504
+ const escaped = fields.__rasputin_fields ?? [];
1505
+ escaped.push({ name: key, value });
1506
+ fields.__rasputin_fields = escaped;
1507
+ return;
1508
+ }
1509
+ fields[key] = value;
1510
+ };
1511
+ var ownEnumerableKeys = (value, maxKeys) => {
1512
+ const keys = [];
1513
+ let proto = null;
1514
+ try {
1515
+ proto = Object.getPrototypeOf(value);
1516
+ } catch {
1517
+ proto = null;
1518
+ }
1519
+ const protoIsProxy = proto !== null && types.isProxy(proto);
1520
+ try {
1521
+ for (const key in value) {
1522
+ if (protoIsProxy && !Object.hasOwn(value, key)) break;
1523
+ if (!Object.hasOwn(value, key)) continue;
1524
+ if (keys.length >= maxKeys) return { keys, truncated: true };
1525
+ keys.push(key);
1230
1526
  }
1231
- default:
1232
- return Buffer2.byteLength(JSON.stringify(value) ?? "null", "utf8");
1527
+ } catch {
1528
+ return { keys, truncated: keys.length >= maxKeys };
1233
1529
  }
1530
+ return { keys, truncated: false };
1234
1531
  };
1235
- var compileLimits = (options) => ({
1236
- maxDepth: options.maxDepth ?? defaults.maxDepth,
1237
- maxObjectKeys: options.maxObjectKeys ?? defaults.maxObjectKeys,
1238
- maxArrayElements: options.maxArrayElements ?? defaults.maxArrayElements,
1239
- maxStringLength: options.maxStringLength ?? defaults.maxStringLength,
1240
- maxSerializedValueBytes: options.maxSerializedValueBytes ?? defaults.maxSerializedValueBytes
1241
- });
1242
- var compileRedactKeys = (options) => {
1243
- if (!options.redactKeys?.length) return new Set(DEFAULT_REDACT_KEYS);
1244
- return /* @__PURE__ */ new Set([...DEFAULT_REDACT_KEYS, ...options.redactKeys.map((key) => key.toLowerCase())]);
1532
+ var bufferByteLength = (value) => {
1533
+ try {
1534
+ return Buffer2.byteLength(value);
1535
+ } catch {
1536
+ return 0;
1537
+ }
1245
1538
  };
1246
- var keyNeedsCaseFold = (key) => {
1539
+ var stringEstimate = (value) => NODE + 2 + Buffer2.byteLength(value, "utf8");
1540
+ var URL_LIKE_PROPERTY_NAMES = /* @__PURE__ */ new Set([
1541
+ "url",
1542
+ "href",
1543
+ "originalurl",
1544
+ "path",
1545
+ "pathname",
1546
+ "search",
1547
+ "query",
1548
+ "requesturl",
1549
+ "requesturi",
1550
+ "location",
1551
+ "referer",
1552
+ "referrer",
1553
+ "uri",
1554
+ "connectionuri",
1555
+ "connectionurl",
1556
+ "databaseuri",
1557
+ "databaseurl",
1558
+ "mongouri",
1559
+ "mongourl",
1560
+ "redisuri",
1561
+ "redisurl",
1562
+ "postgresuri",
1563
+ "postgresurl"
1564
+ ]);
1565
+ var compactPropertyName = (key) => {
1566
+ let compacted = "";
1247
1567
  for (let index = 0; index < key.length; index++) {
1248
1568
  const code = key.charCodeAt(index);
1249
- if (code > 127 || code >= 65 && code <= 90) return true;
1569
+ if (code === 45 || code === 46 || code === 95) continue;
1570
+ compacted += code >= 65 && code <= 90 ? String.fromCharCode(code + 32) : key[index];
1250
1571
  }
1251
- return false;
1572
+ return compacted;
1252
1573
  };
1253
- var isJsonSafeString = (value) => {
1254
- for (let index = 0; index < value.length; index++) {
1255
- const code = value.charCodeAt(index);
1256
- if (code < 32 || code === 34 || code === 92) return false;
1257
- if (code >= 55296 && code <= 56319) {
1258
- const next = value.charCodeAt(index + 1);
1259
- if (index + 1 >= value.length || next < 56320 || next > 57343) return false;
1260
- index++;
1261
- continue;
1262
- }
1263
- if (code >= 56320 && code <= 57343) return false;
1574
+ var propertyNameLooksLikeUrl = (key) => URL_LIKE_PROPERTY_NAMES.has(compactPropertyName(key));
1575
+ var looksLikeBareQueryString = (text) => {
1576
+ if (!text.includes("=") || /\s/.test(text)) return false;
1577
+ if (/^[a-z][a-z0-9+.-]*:/i.test(text) || text.startsWith("/")) return false;
1578
+ return /^[^\s=]+=[^\s]*(&[^\s=]+=[^\s]*)*$/.test(text);
1579
+ };
1580
+ var redactSensitiveQuery = (text, redactKeys) => {
1581
+ const queryAt = text.indexOf("?");
1582
+ let prefix = "";
1583
+ let query = "";
1584
+ let suffix = "";
1585
+ if (queryAt >= 0) {
1586
+ if (queryAt === text.length - 1) return text;
1587
+ const hashAt = text.indexOf("#", queryAt + 1);
1588
+ prefix = text.slice(0, queryAt + 1);
1589
+ query = hashAt < 0 ? text.slice(queryAt + 1) : text.slice(queryAt + 1, hashAt);
1590
+ suffix = hashAt < 0 ? "" : text.slice(hashAt);
1591
+ } else if (looksLikeBareQueryString(text)) {
1592
+ query = text;
1593
+ } else {
1594
+ return text;
1264
1595
  }
1265
- return true;
1596
+ if (!query.includes("=")) return text;
1597
+ let changed = false;
1598
+ const next = query.split("&").map((part) => {
1599
+ const equals = part.indexOf("=");
1600
+ const rawKey = equals < 0 ? part : part.slice(0, equals);
1601
+ if (!rawKey) return part;
1602
+ let decoded = rawKey;
1603
+ try {
1604
+ decoded = decodeURIComponent(rawKey.replace(/\+/g, " "));
1605
+ } catch {
1606
+ decoded = rawKey;
1607
+ }
1608
+ if (!keyIsRedacted(decoded, redactKeys) && !keyIsRedacted(rawKey, redactKeys)) return part;
1609
+ changed = true;
1610
+ return `${rawKey}=${REDACTED}`;
1611
+ });
1612
+ if (!changed) return text;
1613
+ return `${prefix}${next.join("&")}${suffix}`;
1266
1614
  };
1267
- var primitiveFastPath = (value, maxStringLength) => {
1268
- if (value === null) return { value: null, bytes: 4, visitedNodes: 1 };
1269
- if (typeof value === "boolean") return { value, bytes: value ? 4 : 5, visitedNodes: 1 };
1270
- if (typeof value === "number") {
1271
- if (!Number.isFinite(value)) return { value, bytes: 4, visitedNodes: 1 };
1272
- if (Object.is(value, -0)) return { value, bytes: 1, visitedNodes: 1 };
1273
- return { value, bytes: String(value).length, visitedNodes: 1 };
1274
- }
1275
- if (typeof value === "string") {
1276
- if (value.length > maxStringLength || !isJsonSafeString(value)) return void 0;
1277
- return { value, bytes: 2 + Buffer2.byteLength(value, "utf8"), visitedNodes: 1 };
1278
- }
1279
- if (typeof value === "undefined") {
1280
- const serialized = typeMarker("undefined");
1281
- return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
1282
- }
1283
- if (typeof value === "bigint") {
1284
- const serialized = typeMarker("bigint", value.toString());
1285
- return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
1286
- }
1287
- if (typeof value === "symbol") {
1288
- const text = String(value);
1289
- if (!isJsonSafeString(text)) return void 0;
1290
- const serialized = typeMarker("symbol", text);
1291
- return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
1292
- }
1293
- if (typeof value === "function") {
1294
- const name = value.name || "anonymous";
1295
- if (!isJsonSafeString(name)) return void 0;
1296
- const serialized = typeMarker("function", name);
1297
- return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
1615
+ var redactUrlUserinfo = (text) => {
1616
+ const schemeEnd = text.indexOf("://");
1617
+ if (schemeEnd <= 0) return text;
1618
+ const rest = text.slice(schemeEnd + 3);
1619
+ let authorityEnd = rest.length;
1620
+ for (const marker of ["/", "?", "#"]) {
1621
+ const at = rest.indexOf(marker);
1622
+ if (at >= 0 && at < authorityEnd) authorityEnd = at;
1298
1623
  }
1299
- return void 0;
1624
+ const authority = rest.slice(0, authorityEnd);
1625
+ const userinfoEnd = authority.lastIndexOf("@");
1626
+ if (userinfoEnd < 0) return text;
1627
+ return `${text.slice(0, schemeEnd + 3)}${REDACTED}@${authority.slice(userinfoEnd + 1)}${rest.slice(authorityEnd)}`;
1300
1628
  };
1301
- var createSafeSerializer = (options = {}) => {
1302
- const limits = compileLimits(options);
1303
- const redactKeys = compileRedactKeys(options);
1629
+ var redactUrlLikeString = (text, redactKeys) => redactSensitiveQuery(redactUrlUserinfo(text), redactKeys);
1630
+ var isFrozenAtom = (value) => typeof value === "object" && value !== null && FROZEN in value;
1631
+ var createValueFreezer = (options = {}) => {
1632
+ const limits = compileFreezeLimits(options);
1633
+ const redactKeys = compileRedactKeys(options.redactKeys);
1304
1634
  const sharedPath = /* @__PURE__ */ new Set();
1305
- let serializing = false;
1306
- const isRedactedKey = (key) => {
1307
- if (redactKeys.has(key)) return true;
1308
- if (!keyNeedsCaseFold(key)) return false;
1309
- return redactKeys.has(key.toLowerCase());
1310
- };
1311
- const addBytes = (metrics, count) => {
1312
- metrics.bytes += count;
1313
- if (metrics.bytes > limits.maxSerializedValueBytes) metrics.oversize = true;
1314
- };
1315
- const boundedOversize = (bytes, visitedNodes) => {
1316
- const bounded = truncation("max_serialized_value_bytes", { __serialized_bytes: bytes });
1317
- return { value: bounded, bytes: jsonLiteralUtf8Bytes(bounded), visitedNodes };
1635
+ let freezing = false;
1636
+ const add = (metrics, count) => {
1637
+ metrics.estimatedBytes += count;
1638
+ if (metrics.estimatedBytes > limits.maxSerializedValueBytes) metrics.oversize = true;
1318
1639
  };
1319
- const openObject = (metrics, allocate) => {
1320
- addBytes(metrics, 2);
1321
- return {
1322
- target: allocate && !metrics.oversize ? {} : void 0,
1323
- first: true
1324
- };
1325
- };
1326
- const openArray = (metrics, allocate) => {
1327
- addBytes(metrics, 2);
1328
- return {
1329
- items: allocate && !metrics.oversize ? [] : void 0,
1330
- first: true
1331
- };
1332
- };
1333
- const beginField = (metrics, object, key) => {
1334
- if (!object.first) addBytes(metrics, 1);
1335
- object.first = false;
1336
- addBytes(metrics, jsonStringUtf8Bytes(key) + 1);
1337
- };
1338
- const assignField = (object, key, fieldValue) => {
1339
- if (object.target) object.target[key] = fieldValue;
1340
- };
1341
- const writeLiteralField = (metrics, object, key, jsonValue) => {
1342
- beginField(metrics, object, key);
1343
- addBytes(metrics, jsonLiteralUtf8Bytes(jsonValue));
1344
- assignField(object, key, jsonValue);
1345
- };
1346
- const writeTypeMarker = (metrics, allocate, type, nestedValue) => {
1347
- const object = openObject(metrics, allocate);
1348
- writeLiteralField(metrics, object, "__rasputin_type", type);
1349
- if (nestedValue !== void 0) writeLiteralField(metrics, object, "value", nestedValue);
1350
- return object.target;
1351
- };
1352
- const writeTruncation = (metrics, allocate, reason, extra = {}) => {
1353
- const object = openObject(metrics, allocate);
1354
- writeLiteralField(metrics, object, "__rasputin_truncated", true);
1355
- writeLiteralField(metrics, object, "__reason", reason);
1356
- for (const key of Object.keys(extra)) writeLiteralField(metrics, object, key, extra[key]);
1357
- return object.target;
1358
- };
1359
- const serializeInner = (value, depth, path, allocate, metrics) => {
1640
+ const freezeInner = (value, depth, path, metrics) => {
1641
+ if (metrics.oversize) return void 0;
1360
1642
  metrics.visitedNodes++;
1361
- const store = allocate && !metrics.oversize;
1362
1643
  if (value === null) {
1363
- addBytes(metrics, 4);
1364
- return store ? null : void 0;
1644
+ add(metrics, 4);
1645
+ return null;
1365
1646
  }
1366
1647
  if (typeof value === "boolean") {
1367
- addBytes(metrics, value ? 4 : 5);
1368
- return store ? value : void 0;
1648
+ add(metrics, value ? 4 : 5);
1649
+ return value;
1369
1650
  }
1370
1651
  if (typeof value === "number") {
1371
- if (!Number.isFinite(value)) addBytes(metrics, 4);
1372
- else if (Object.is(value, -0)) addBytes(metrics, 1);
1373
- else addBytes(metrics, String(value).length);
1374
- return store ? value : void 0;
1652
+ const kind = taggedNumberKind(value);
1653
+ if (kind) {
1654
+ add(metrics, NODE + 16);
1655
+ return atom(kind);
1656
+ }
1657
+ add(metrics, NODE + String(value).length);
1658
+ return value;
1375
1659
  }
1376
1660
  if (typeof value === "string") {
1377
1661
  if (value.length <= limits.maxStringLength) {
1378
- addBytes(metrics, jsonStringUtf8Bytes(value));
1379
- return store ? value : void 0;
1662
+ add(metrics, stringEstimate(value));
1663
+ return value;
1380
1664
  }
1381
- return writeTruncation(metrics, store, "max_string_length", {
1382
- __original_length: value.length,
1383
- value: value.slice(0, limits.maxStringLength)
1665
+ const sliced = value.slice(0, limits.maxStringLength);
1666
+ add(metrics, NODE + stringEstimate(sliced) + 48);
1667
+ return atom("truncated", {
1668
+ reason: "max_string_length",
1669
+ originalLength: value.length,
1670
+ value: sliced
1384
1671
  });
1385
1672
  }
1386
- if (typeof value === "undefined") return writeTypeMarker(metrics, store, "undefined");
1673
+ if (typeof value === "undefined") {
1674
+ add(metrics, NODE + 16);
1675
+ return atom("undefined");
1676
+ }
1387
1677
  if (typeof value === "bigint") {
1388
- return writeTypeMarker(metrics, store, "bigint", value.toString());
1678
+ const text = value.toString();
1679
+ add(metrics, NODE + stringEstimate(text));
1680
+ return atom("bigint", { value: text });
1389
1681
  }
1390
1682
  if (typeof value === "symbol") {
1391
- return writeTypeMarker(metrics, store, "symbol", String(value));
1683
+ const text = String(value);
1684
+ add(metrics, NODE + stringEstimate(text));
1685
+ return atom("symbol", { value: text });
1392
1686
  }
1393
1687
  if (typeof value === "function") {
1394
- return writeTypeMarker(metrics, store, "function", value.name || "anonymous");
1688
+ if (types.isProxy(value)) {
1689
+ add(metrics, NODE + 16);
1690
+ return atom("Proxy");
1691
+ }
1692
+ const name = functionNameOf(value);
1693
+ add(metrics, NODE + stringEstimate(name));
1694
+ return atom("function", { value: name });
1695
+ }
1696
+ if (typeof value !== "object") {
1697
+ add(metrics, NODE + 16);
1698
+ return atom("unserializable");
1699
+ }
1700
+ if (path.has(value)) {
1701
+ add(metrics, NODE + 16);
1702
+ return atom("circular");
1395
1703
  }
1396
- if (typeof value !== "object") return writeTypeMarker(metrics, store, typeof value);
1397
- if (path.has(value)) return writeTypeMarker(metrics, store, "circular");
1398
1704
  path.add(value);
1399
- const bytesBefore = metrics.bytes;
1400
- const oversizeBefore = metrics.oversize;
1401
1705
  try {
1402
- const childAllocate = allocate && !metrics.oversize;
1403
- if (value instanceof Date) {
1404
- return writeTypeMarker(metrics, childAllocate, "Date", value.toISOString());
1405
- }
1406
- if (depth >= limits.maxDepth) return writeTruncation(metrics, childAllocate, "max_depth");
1407
- if (value instanceof Error) {
1408
- const object2 = openObject(metrics, childAllocate);
1409
- writeLiteralField(metrics, object2, "__rasputin_type", "Error");
1410
- writeLiteralField(metrics, object2, "name", value.name);
1411
- beginField(metrics, object2, "message");
1412
- assignField(
1413
- object2,
1414
- "message",
1415
- serializeInner(value.message, depth + 1, path, childAllocate, metrics)
1416
- );
1417
- if (value.stack) {
1418
- beginField(metrics, object2, "stack");
1419
- assignField(
1420
- object2,
1421
- "stack",
1422
- serializeInner(value.stack, depth + 1, path, childAllocate, metrics)
1423
- );
1706
+ if (types.isProxy(value) || prototypeChainHasProxy(value)) {
1707
+ add(metrics, NODE + 16);
1708
+ return atom("Proxy");
1709
+ }
1710
+ if (types.isDate(value)) {
1711
+ const time = Date.prototype.getTime.call(value);
1712
+ const iso = Number.isFinite(time) ? new Date(time).toISOString() : "Invalid Date";
1713
+ add(metrics, NODE + stringEstimate(iso));
1714
+ return atom("Date", { value: iso });
1715
+ }
1716
+ if (depth >= limits.maxDepth) {
1717
+ add(metrics, NODE + 32);
1718
+ return atom("truncated", { reason: "max_depth" });
1719
+ }
1720
+ if (types.isNativeError(value) || isDomException(value)) {
1721
+ add(metrics, NODE + 32);
1722
+ const name = errorNameOf(value);
1723
+ add(metrics, stringEstimate(name));
1724
+ const message = freezeInner(errorMessageOf(value), depth + 1, path, metrics);
1725
+ const stack = errorStackOf(value);
1726
+ const extras = {};
1727
+ for (const key of ["code", "cause", "statusCode"]) {
1728
+ const slot = ownData(value, key);
1729
+ if (!slot) continue;
1730
+ extras[key] = freezeInner(slot.value, depth + 1, path, metrics);
1424
1731
  }
1425
- return object2.target;
1732
+ return atom("Error", {
1733
+ name,
1734
+ message,
1735
+ ...extras,
1736
+ ...stack ? { stack: freezeInner(stack, depth + 1, path, metrics) } : {}
1737
+ });
1426
1738
  }
1427
1739
  if (Buffer2.isBuffer(value)) {
1428
- return writeTypeMarker(metrics, childAllocate, "Buffer", {
1429
- byteLength: value.byteLength,
1430
- base64: value.subarray(0, limits.maxStringLength).toString("base64"),
1431
- ...value.byteLength > limits.maxStringLength ? { __rasputin_truncated: true } : {}
1740
+ const byteLength = bufferByteLength(value);
1741
+ const slice = Buffer2.prototype.subarray.call(value, 0, limits.maxStringLength);
1742
+ const base64 = Buffer2.prototype.toString.call(slice, "base64");
1743
+ add(metrics, NODE + stringEstimate(base64) + 24);
1744
+ return atom("Buffer", {
1745
+ byteLength,
1746
+ base64,
1747
+ ...byteLength > limits.maxStringLength ? { truncated: true } : {}
1432
1748
  });
1433
1749
  }
1434
- if (value instanceof Promise) return writeTypeMarker(metrics, childAllocate, "Promise");
1435
- if (value instanceof Map) {
1436
- const object2 = openObject(metrics, childAllocate);
1437
- writeLiteralField(metrics, object2, "__rasputin_type", "Map");
1438
- beginField(metrics, object2, "entries");
1439
- const entries = openArray(metrics, childAllocate);
1750
+ if (types.isPromise(value)) {
1751
+ add(metrics, NODE + 16);
1752
+ return atom("Promise");
1753
+ }
1754
+ if (types.isMap(value)) {
1755
+ add(metrics, NODE + 16);
1756
+ const entries = [];
1440
1757
  let counted2 = 0;
1441
- for (const entry of value.entries()) {
1442
- if (counted2 >= limits.maxArrayElements) break;
1443
- if (!entries.first) addBytes(metrics, 1);
1444
- entries.first = false;
1445
- addBytes(metrics, 2);
1446
- const key = serializeInner(entry[0], depth + 1, path, childAllocate, metrics);
1447
- addBytes(metrics, 1);
1448
- const mapped = serializeInner(entry[1], depth + 1, path, childAllocate, metrics);
1449
- entries.items?.push([key, mapped]);
1758
+ const mapSize = Object.getOwnPropertyDescriptor(Map.prototype, "size")?.get;
1759
+ const size = mapSize ? mapSize.call(value) : 0;
1760
+ for (const mapKey of Map.prototype.keys.call(value)) {
1761
+ if (counted2 >= limits.maxArrayElements || metrics.oversize) break;
1762
+ const key = freezeInner(mapKey, depth + 1, path, metrics);
1763
+ if (typeof mapKey === "string" && keyIsRedacted(mapKey, redactKeys)) {
1764
+ add(metrics, stringEstimate(REDACTED));
1765
+ entries.push([key, REDACTED]);
1766
+ } else {
1767
+ entries.push([
1768
+ key,
1769
+ freezeInner(Map.prototype.get.call(value, mapKey), depth + 1, path, metrics)
1770
+ ]);
1771
+ }
1450
1772
  counted2++;
1451
1773
  }
1452
- assignField(object2, "entries", entries.items ?? []);
1453
- if (value.size > limits.maxArrayElements) {
1454
- writeLiteralField(metrics, object2, "__rasputin_truncated", true);
1455
- writeLiteralField(metrics, object2, "__reason", "max_array_elements");
1456
- writeLiteralField(metrics, object2, "__original_length", value.size);
1457
- }
1458
- return object2.target;
1774
+ return atom("Map", {
1775
+ entries,
1776
+ ...size > limits.maxArrayElements ? { truncated: true, reason: "max_array_elements", originalLength: size } : {}
1777
+ });
1459
1778
  }
1460
- if (value instanceof Set) {
1461
- const object2 = openObject(metrics, childAllocate);
1462
- writeLiteralField(metrics, object2, "__rasputin_type", "Set");
1463
- beginField(metrics, object2, "values");
1464
- const items = openArray(metrics, childAllocate);
1779
+ if (types.isSet(value)) {
1780
+ add(metrics, NODE + 16);
1781
+ const values = [];
1465
1782
  let counted2 = 0;
1466
- for (const item of value.values()) {
1467
- if (counted2 >= limits.maxArrayElements) break;
1468
- if (!items.first) addBytes(metrics, 1);
1469
- items.first = false;
1470
- const serializedItem = serializeInner(item, depth + 1, path, childAllocate, metrics);
1471
- items.items?.push(serializedItem);
1783
+ const setSize = Object.getOwnPropertyDescriptor(Set.prototype, "size")?.get;
1784
+ const size = setSize ? setSize.call(value) : 0;
1785
+ for (const item of Set.prototype.values.call(value)) {
1786
+ if (counted2 >= limits.maxArrayElements || metrics.oversize) break;
1787
+ values.push(freezeInner(item, depth + 1, path, metrics));
1472
1788
  counted2++;
1473
1789
  }
1474
- assignField(object2, "values", items.items ?? []);
1475
- if (value.size > limits.maxArrayElements) {
1476
- writeLiteralField(metrics, object2, "__rasputin_truncated", true);
1477
- writeLiteralField(metrics, object2, "__reason", "max_array_elements");
1478
- writeLiteralField(metrics, object2, "__original_length", value.size);
1479
- }
1480
- return object2.target;
1790
+ return atom("Set", {
1791
+ values,
1792
+ ...size > limits.maxArrayElements ? { truncated: true, reason: "max_array_elements", originalLength: size } : {}
1793
+ });
1481
1794
  }
1482
1795
  if (Array.isArray(value)) {
1483
- const items = openArray(metrics, childAllocate);
1796
+ add(metrics, 2);
1797
+ const items = [];
1484
1798
  const maxItems = value.length > limits.maxArrayElements ? limits.maxArrayElements - 1 : value.length;
1799
+ let redactNext = false;
1485
1800
  for (let index = 0; index < maxItems; index++) {
1486
- if (!items.first) addBytes(metrics, 1);
1487
- items.first = false;
1488
- items.items?.push(serializeInner(value[index], depth + 1, path, childAllocate, metrics));
1801
+ if (metrics.oversize) break;
1802
+ let descriptor;
1803
+ try {
1804
+ descriptor = Object.getOwnPropertyDescriptor(value, index);
1805
+ } catch {
1806
+ descriptor = void 0;
1807
+ }
1808
+ if (!descriptor) {
1809
+ add(metrics, NODE + 16);
1810
+ items.push(atom("hole"));
1811
+ redactNext = false;
1812
+ continue;
1813
+ }
1814
+ if (!("value" in descriptor)) {
1815
+ add(metrics, NODE + 16);
1816
+ items.push(atom("accessor"));
1817
+ redactNext = false;
1818
+ continue;
1819
+ }
1820
+ if (redactNext) {
1821
+ add(metrics, stringEstimate(REDACTED));
1822
+ items.push(REDACTED);
1823
+ redactNext = false;
1824
+ } else {
1825
+ items.push(freezeInner(descriptor.value, depth + 1, path, metrics));
1826
+ redactNext = typeof descriptor.value === "string" && keyIsRedacted(descriptor.value, redactKeys);
1827
+ }
1489
1828
  }
1490
1829
  if (value.length > limits.maxArrayElements) {
1491
- if (!items.first) addBytes(metrics, 1);
1492
- items.first = false;
1493
- items.items?.push(
1494
- writeTruncation(metrics, childAllocate, "max_array_elements", {
1495
- __original_length: value.length
1830
+ add(metrics, NODE + 32);
1831
+ items.push(
1832
+ atom("truncated", {
1833
+ reason: "max_array_elements",
1834
+ originalLength: value.length
1496
1835
  })
1497
1836
  );
1498
1837
  }
1499
- return items.items;
1838
+ if (items[0] === RASPUTIN_WIRE_TAG) {
1839
+ return atom("instance", { type: "Array", value: { items } });
1840
+ }
1841
+ return items;
1842
+ }
1843
+ if (types.isTypedArray(value)) {
1844
+ const view = value;
1845
+ const byteLength = viewByteLength(view);
1846
+ const sampleLimit = Math.min(32, limits.maxStringLength);
1847
+ let sample = [];
1848
+ try {
1849
+ const buffer = typedArrayBufferGet?.call(view);
1850
+ const byteOffset = typedArrayByteOffsetGet?.call(view);
1851
+ if (buffer) {
1852
+ const bytes = new Uint8Array(
1853
+ buffer,
1854
+ byteOffset ?? 0,
1855
+ Math.min(sampleLimit, byteLength)
1856
+ );
1857
+ sample = sampleBytes(bytes, sampleLimit);
1858
+ }
1859
+ } catch {
1860
+ sample = [];
1861
+ }
1862
+ const typeName2 = typedArrayName(value);
1863
+ add(metrics, NODE + stringEstimate(typeName2) + 48);
1864
+ return atom("instance", {
1865
+ type: typeName2,
1866
+ value: {
1867
+ byteLength,
1868
+ ...sample.length > 0 ? { sample } : {},
1869
+ ...byteLength > sampleLimit ? { truncated: true } : {}
1870
+ }
1871
+ });
1872
+ }
1873
+ if (types.isDataView(value)) {
1874
+ const view = value;
1875
+ const byteLength = viewByteLength(view);
1876
+ add(metrics, NODE + 32);
1877
+ return atom("instance", {
1878
+ type: "DataView",
1879
+ value: { byteLength }
1880
+ });
1881
+ }
1882
+ if (types.isArrayBuffer(value) || types.isSharedArrayBuffer(value)) {
1883
+ const buffer = value;
1884
+ let byteLength = 0;
1885
+ try {
1886
+ byteLength = buffer.byteLength;
1887
+ } catch {
1888
+ byteLength = 0;
1889
+ }
1890
+ add(metrics, NODE + 32);
1891
+ return atom("instance", {
1892
+ type: types.isSharedArrayBuffer(value) ? "SharedArrayBuffer" : "ArrayBuffer",
1893
+ value: { byteLength }
1894
+ });
1895
+ }
1896
+ if (types.isStringObject(value) || types.isNumberObject(value) || types.isBooleanObject(value)) {
1897
+ try {
1898
+ if (types.isStringObject(value)) {
1899
+ return freezeInner(String.prototype.valueOf.call(value), depth, path, metrics);
1900
+ }
1901
+ if (types.isNumberObject(value)) {
1902
+ return freezeInner(Number.prototype.valueOf.call(value), depth, path, metrics);
1903
+ }
1904
+ return freezeInner(Boolean.prototype.valueOf.call(value), depth, path, metrics);
1905
+ } catch {
1906
+ return atom("unserializable");
1907
+ }
1908
+ }
1909
+ add(metrics, 2);
1910
+ const fields = /* @__PURE__ */ Object.create(null);
1911
+ let typeName;
1912
+ let prototype = null;
1913
+ try {
1914
+ prototype = Object.getPrototypeOf(value);
1915
+ } catch {
1916
+ prototype = null;
1917
+ }
1918
+ if (prototype && types.isProxy(prototype)) {
1919
+ add(metrics, NODE + 16);
1920
+ return atom("instance", { type: "Proxy", value: fields });
1500
1921
  }
1501
- const object = openObject(metrics, childAllocate);
1502
- const prototype = Object.getPrototypeOf(value);
1503
1922
  if (prototype && prototype !== Object.prototype) {
1504
- writeLiteralField(
1505
- metrics,
1506
- object,
1507
- "__rasputin_type",
1508
- prototype.constructor?.name ?? "instance"
1509
- );
1923
+ typeName = "instance";
1924
+ if (!types.isProxy(prototype)) {
1925
+ const ctor = ownData(prototype, "constructor")?.value;
1926
+ if (typeof ctor === "function") {
1927
+ const name = functionNameOf(ctor);
1928
+ if (name && name !== "anonymous") typeName = name;
1929
+ }
1930
+ }
1931
+ add(metrics, NODE + stringEstimate(typeName));
1510
1932
  }
1511
- const keys = Object.keys(value);
1512
- const maxKeys = keys.length > limits.maxObjectKeys ? limits.maxObjectKeys - 1 : keys.length;
1933
+ const pairLabel = ownData(value, "name") ?? ownData(value, "key");
1934
+ const pairIsSensitive = pairLabel !== void 0 && typeof pairLabel.value === "string" && keyIsRedacted(pairLabel.value, redactKeys);
1935
+ const { keys, truncated } = ownEnumerableKeys(value, limits.maxObjectKeys);
1936
+ const maxKeys = truncated ? Math.max(0, limits.maxObjectKeys - 1) : keys.length;
1513
1937
  for (let index = 0; index < maxKeys; index++) {
1514
1938
  const key = keys[index];
1515
- if (key === void 0) continue;
1516
- if (isRedactedKey(key)) {
1517
- writeLiteralField(metrics, object, key, REDACTED);
1939
+ if (key === void 0 || metrics.oversize) continue;
1940
+ add(metrics, stringEstimate(key));
1941
+ if (keyIsRedacted(key, redactKeys) || key === "value" && pairIsSensitive) {
1942
+ add(metrics, stringEstimate(REDACTED));
1943
+ assignFrozenField(fields, key, REDACTED);
1518
1944
  continue;
1519
1945
  }
1520
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
1521
- if (descriptor && "value" in descriptor) {
1522
- beginField(metrics, object, key);
1523
- assignField(
1524
- object,
1525
- key,
1526
- serializeInner(descriptor.value, depth + 1, path, childAllocate, metrics)
1527
- );
1946
+ const slot = ownData(value, key);
1947
+ if (slot) {
1948
+ const field = typeof slot.value === "string" && propertyNameLooksLikeUrl(key) ? redactUrlLikeString(slot.value, redactKeys) : slot.value;
1949
+ assignFrozenField(fields, key, freezeInner(field, depth + 1, path, metrics));
1528
1950
  } else {
1529
- beginField(metrics, object, key);
1530
- assignField(object, key, writeTypeMarker(metrics, childAllocate, "accessor"));
1951
+ add(metrics, NODE + 16);
1952
+ assignFrozenField(fields, key, atom("accessor"));
1531
1953
  }
1532
1954
  }
1533
- if (keys.length > limits.maxObjectKeys) {
1534
- writeLiteralField(metrics, object, "__rasputin_truncated", true);
1535
- writeLiteralField(metrics, object, "__reason", "max_object_keys");
1536
- writeLiteralField(metrics, object, "__original_length", keys.length);
1955
+ if (truncated) {
1956
+ return atom("instance", {
1957
+ type: typeName,
1958
+ value: fields,
1959
+ truncated: true,
1960
+ reason: "max_object_keys"
1961
+ });
1537
1962
  }
1538
- return object.target;
1963
+ if (typeName) return atom("instance", { type: typeName, value: fields });
1964
+ return fields;
1539
1965
  } catch (error) {
1540
- metrics.bytes = bytesBefore;
1541
- metrics.oversize = oversizeBefore;
1542
- return writeTypeMarker(
1543
- metrics,
1544
- allocate && !metrics.oversize,
1545
- "unserializable",
1546
- error instanceof Error ? error.message : void 0
1547
- );
1966
+ add(metrics, NODE + 32);
1967
+ return atom("unserializable", {
1968
+ value: error instanceof Error ? error.message : void 0
1969
+ });
1548
1970
  } finally {
1549
1971
  path.delete(value);
1550
1972
  }
1551
1973
  };
1552
- const serializeWithBytes = (value) => {
1553
- const fast = primitiveFastPath(value, limits.maxStringLength);
1554
- if (fast) {
1555
- return fast.bytes <= limits.maxSerializedValueBytes ? fast : boundedOversize(fast.bytes, fast.visitedNodes);
1556
- }
1557
- const metrics = { visitedNodes: 0, bytes: 0, oversize: false };
1558
- const reentrant = serializing;
1974
+ const freeze = (value) => {
1975
+ const metrics = { visitedNodes: 0, estimatedBytes: 0, oversize: false };
1976
+ const reentrant = freezing;
1559
1977
  const path = reentrant ? /* @__PURE__ */ new Set() : sharedPath;
1560
1978
  if (!reentrant) {
1561
- serializing = true;
1979
+ freezing = true;
1562
1980
  sharedPath.clear();
1563
1981
  }
1564
1982
  try {
1565
- const serialized = serializeInner(value, 0, path, true, metrics);
1566
- if (metrics.bytes > limits.maxSerializedValueBytes) {
1567
- return boundedOversize(metrics.bytes, metrics.visitedNodes);
1983
+ const frozen = freezeInner(value, 0, path, metrics);
1984
+ if (metrics.oversize) {
1985
+ return {
1986
+ value: atom("truncated", {
1987
+ reason: "max_serialized_value_bytes",
1988
+ serializedBytes: metrics.estimatedBytes
1989
+ }),
1990
+ estimatedBytes: metrics.estimatedBytes,
1991
+ visitedNodes: metrics.visitedNodes,
1992
+ oversize: true
1993
+ };
1568
1994
  }
1569
- return { value: serialized, bytes: metrics.bytes, visitedNodes: metrics.visitedNodes };
1995
+ return {
1996
+ value: frozen,
1997
+ estimatedBytes: metrics.estimatedBytes,
1998
+ visitedNodes: metrics.visitedNodes,
1999
+ oversize: false
2000
+ };
1570
2001
  } catch {
1571
- const failed = typeMarker("unserializable");
1572
2002
  return {
1573
- value: failed,
1574
- bytes: jsonLiteralUtf8Bytes(failed),
1575
- visitedNodes: metrics.visitedNodes
2003
+ value: atom("unserializable"),
2004
+ estimatedBytes: NODE + 16,
2005
+ visitedNodes: Math.max(1, metrics.visitedNodes),
2006
+ oversize: false
1576
2007
  };
1577
2008
  } finally {
1578
2009
  path.clear();
1579
- if (!reentrant) serializing = false;
2010
+ if (!reentrant) freezing = false;
2011
+ }
2012
+ };
2013
+ return { freeze, limits };
2014
+ };
2015
+
2016
+ // src/execution-recorder/encode-frozen.ts
2017
+ var typeMarker = (type, value) => ({
2018
+ __rasputin_type: type,
2019
+ ...value === void 0 ? {} : { value }
2020
+ });
2021
+ var truncation = (reason, extra = {}) => ({
2022
+ __rasputin_truncated: true,
2023
+ __reason: reason,
2024
+ ...extra
2025
+ });
2026
+ var taggedNumber = (value) => {
2027
+ if (Number.isNaN(value)) return { __rasputin_type: "NaN" };
2028
+ if (value === Infinity) return { __rasputin_type: "Infinity" };
2029
+ if (value === -Infinity) return { __rasputin_type: "-Infinity" };
2030
+ if (Object.is(value, -0)) return { __rasputin_type: "-0" };
2031
+ return void 0;
2032
+ };
2033
+ var jsonStringUtf8Bytes = (value) => {
2034
+ let bytes = 2;
2035
+ for (let index = 0; index < value.length; index++) {
2036
+ const code = value.charCodeAt(index);
2037
+ if (code === 34 || code === 92) {
2038
+ bytes += 2;
2039
+ continue;
2040
+ }
2041
+ if (code === 8 || code === 9 || code === 10 || code === 12 || code === 13) {
2042
+ bytes += 2;
2043
+ continue;
2044
+ }
2045
+ if (code < 32) {
2046
+ bytes += 6;
2047
+ continue;
2048
+ }
2049
+ if (code < 128) {
2050
+ bytes += 1;
2051
+ continue;
2052
+ }
2053
+ if (code < 2048) {
2054
+ bytes += 2;
2055
+ continue;
2056
+ }
2057
+ if (code >= 55296 && code <= 56319) {
2058
+ const next = value.charCodeAt(index + 1);
2059
+ if (index + 1 < value.length && next >= 56320 && next <= 57343) {
2060
+ bytes += 4;
2061
+ index++;
2062
+ continue;
2063
+ }
2064
+ bytes += 6;
2065
+ continue;
2066
+ }
2067
+ if (code >= 56320 && code <= 57343) {
2068
+ bytes += 6;
2069
+ continue;
2070
+ }
2071
+ bytes += 3;
2072
+ }
2073
+ return bytes;
2074
+ };
2075
+ var ownData2 = (value, key) => {
2076
+ try {
2077
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
2078
+ if (descriptor && "value" in descriptor) return descriptor.value;
2079
+ return void 0;
2080
+ } catch {
2081
+ return void 0;
2082
+ }
2083
+ };
2084
+ var jsonLiteralUtf8Bytes = (value) => {
2085
+ if (value === null) return 4;
2086
+ switch (typeof value) {
2087
+ case "boolean":
2088
+ return value ? 4 : 5;
2089
+ case "number": {
2090
+ const tagged = taggedNumber(value);
2091
+ if (tagged) return jsonLiteralUtf8Bytes(tagged);
2092
+ return String(value).length;
2093
+ }
2094
+ case "string":
2095
+ return jsonStringUtf8Bytes(value);
2096
+ case "object": {
2097
+ if (Array.isArray(value)) {
2098
+ let bytes2 = 2;
2099
+ for (let index = 0; index < value.length; index++) {
2100
+ if (index > 0) bytes2 += 1;
2101
+ bytes2 += jsonLiteralUtf8Bytes(ownData2(value, index));
2102
+ }
2103
+ return bytes2;
2104
+ }
2105
+ const record = value;
2106
+ let bytes = 2;
2107
+ let first = true;
2108
+ for (const key of Object.keys(record)) {
2109
+ if (!first) bytes += 1;
2110
+ first = false;
2111
+ bytes += jsonStringUtf8Bytes(key) + 1;
2112
+ bytes += jsonLiteralUtf8Bytes(ownData2(record, key));
2113
+ }
2114
+ return bytes;
2115
+ }
2116
+ default:
2117
+ return Buffer3.byteLength(JSON.stringify(value) ?? "null", "utf8");
2118
+ }
2119
+ };
2120
+ var BUILTIN_INSTANCE_TYPES = /* @__PURE__ */ new Set([
2121
+ "Uint8Array",
2122
+ "Uint8ClampedArray",
2123
+ "Int8Array",
2124
+ "Uint16Array",
2125
+ "Int16Array",
2126
+ "Uint32Array",
2127
+ "Int32Array",
2128
+ "Float32Array",
2129
+ "Float64Array",
2130
+ "BigUint64Array",
2131
+ "BigInt64Array",
2132
+ "TypedArray",
2133
+ "ArrayBuffer",
2134
+ "SharedArrayBuffer",
2135
+ "DataView",
2136
+ "Proxy"
2137
+ ]);
2138
+ var RESERVED_WIRE_KEYS = /* @__PURE__ */ new Set([
2139
+ "__proto__",
2140
+ "__rasputin_type",
2141
+ "__rasputin_truncated",
2142
+ "__rasputin_fields",
2143
+ "__reason",
2144
+ "__original_length",
2145
+ "__serialized_bytes"
2146
+ ]);
2147
+ var encodePlainObject = (value) => {
2148
+ const record = value;
2149
+ if (typeof record.__rasputin_type === "string") {
2150
+ const encoded2 = /* @__PURE__ */ Object.create(null);
2151
+ for (const key of Object.keys(record)) {
2152
+ if (key === "__proto__") continue;
2153
+ encoded2[key] = encodeFrozen(record[key]);
2154
+ }
2155
+ encoded2.__rasputin_type = record.__rasputin_type;
2156
+ return encoded2;
2157
+ }
2158
+ const encoded = /* @__PURE__ */ Object.create(null);
2159
+ const escaped = [];
2160
+ for (const key of Object.keys(record)) {
2161
+ const encodedValue = encodeFrozen(record[key]);
2162
+ if (key === "__proto__" || RESERVED_WIRE_KEYS.has(key) || key.startsWith("__rasputin_")) {
2163
+ if (key === "__rasputin_fields") {
2164
+ encoded.__rasputin_fields = encodedValue;
2165
+ continue;
2166
+ }
2167
+ escaped.push({ name: key, value: encodedValue });
2168
+ } else {
2169
+ encoded[key] = encodedValue;
2170
+ }
2171
+ }
2172
+ if (escaped.length > 0) {
2173
+ const existing = Array.isArray(encoded.__rasputin_fields) ? encoded.__rasputin_fields : [];
2174
+ encoded.__rasputin_fields = [...existing, ...escaped];
2175
+ }
2176
+ return encoded;
2177
+ };
2178
+ var encodeAtom = (frozen) => {
2179
+ const kind = frozen[FROZEN];
2180
+ switch (kind) {
2181
+ case "undefined":
2182
+ case "NaN":
2183
+ case "Infinity":
2184
+ case "-Infinity":
2185
+ case "-0":
2186
+ case "Proxy":
2187
+ case "circular":
2188
+ case "Promise":
2189
+ case "accessor":
2190
+ case "hole":
2191
+ return typeMarker(kind);
2192
+ case "bigint":
2193
+ case "symbol":
2194
+ case "function":
2195
+ case "Date":
2196
+ return typeMarker(kind, encodeFrozen(frozen.value));
2197
+ case "unserializable":
2198
+ return frozen.value === void 0 ? typeMarker("unserializable") : typeMarker("unserializable", encodeFrozen(frozen.value));
2199
+ case "Error": {
2200
+ const encoded = {
2201
+ __rasputin_type: "Error",
2202
+ name: frozen.name,
2203
+ message: encodeFrozen(frozen.message)
2204
+ };
2205
+ if (frozen.stack !== void 0) encoded.stack = encodeFrozen(frozen.stack);
2206
+ if (frozen.code !== void 0) encoded.code = encodeFrozen(frozen.code);
2207
+ if (frozen.cause !== void 0) encoded.cause = encodeFrozen(frozen.cause);
2208
+ if (frozen.statusCode !== void 0) encoded.statusCode = encodeFrozen(frozen.statusCode);
2209
+ return encoded;
2210
+ }
2211
+ case "Buffer":
2212
+ return typeMarker("Buffer", {
2213
+ byteLength: frozen.byteLength,
2214
+ base64: frozen.base64,
2215
+ ...frozen.truncated ? { __rasputin_truncated: true } : {}
2216
+ });
2217
+ case "Map": {
2218
+ const encoded = {
2219
+ __rasputin_type: "Map",
2220
+ entries: encodeFrozen(frozen.entries)
2221
+ };
2222
+ if (frozen.truncated) {
2223
+ encoded.__rasputin_truncated = true;
2224
+ encoded.__reason = frozen.reason;
2225
+ encoded.__original_length = frozen.originalLength;
2226
+ }
2227
+ return encoded;
2228
+ }
2229
+ case "Set": {
2230
+ const encoded = {
2231
+ __rasputin_type: "Set",
2232
+ values: encodeFrozen(frozen.values)
2233
+ };
2234
+ if (frozen.truncated) {
2235
+ encoded.__rasputin_truncated = true;
2236
+ encoded.__reason = frozen.reason;
2237
+ encoded.__original_length = frozen.originalLength;
2238
+ }
2239
+ return encoded;
2240
+ }
2241
+ case "truncated":
2242
+ return truncation(frozen.reason ?? "max_depth", {
2243
+ ...frozen.originalLength === void 0 ? {} : { __original_length: frozen.originalLength },
2244
+ ...frozen.serializedBytes === void 0 ? {} : { __serialized_bytes: frozen.serializedBytes },
2245
+ ...frozen.value === void 0 ? {} : { value: encodeFrozen(frozen.value) }
2246
+ });
2247
+ case "instance": {
2248
+ const fields = typeof frozen.value === "object" && frozen.value !== null && !Array.isArray(frozen.value) ? encodePlainObject(frozen.value) : encodeFrozen(frozen.value);
2249
+ const encoded = /* @__PURE__ */ Object.create(null);
2250
+ if (typeof fields === "object" && fields !== null && !Array.isArray(fields)) {
2251
+ for (const key of Object.keys(fields)) {
2252
+ encoded[key] = fields[key];
2253
+ }
2254
+ }
2255
+ if (frozen.type && BUILTIN_INSTANCE_TYPES.has(frozen.type)) {
2256
+ encoded.__rasputin_type = frozen.type;
2257
+ } else if (frozen.type) {
2258
+ encoded.__rasputin_type = "instance";
2259
+ encoded.__rasputin_class = frozen.type;
2260
+ } else if (!frozen.truncated) {
2261
+ encoded.__rasputin_type = "instance";
2262
+ }
2263
+ if (frozen.truncated) {
2264
+ encoded.__rasputin_truncated = true;
2265
+ encoded.__reason = frozen.reason;
2266
+ if (frozen.originalLength !== void 0) encoded.__original_length = frozen.originalLength;
2267
+ }
2268
+ return encoded;
2269
+ }
2270
+ default:
2271
+ return typeMarker("unserializable");
2272
+ }
2273
+ };
2274
+ var encodeFrozen = (value) => {
2275
+ if (value === REDACTED) return REDACTED;
2276
+ if (isFrozenAtom(value)) return encodeAtom(value);
2277
+ if (Array.isArray(value)) {
2278
+ const items = new Array(value.length);
2279
+ for (let index = 0; index < value.length; index++) {
2280
+ items[index] = encodeFrozen(value[index]);
1580
2281
  }
2282
+ return items;
2283
+ }
2284
+ if (typeof value === "object" && value !== null) {
2285
+ return encodePlainObject(value);
2286
+ }
2287
+ return value;
2288
+ };
2289
+ var encodeFrozenWithBytes = (frozen, visitedNodes, maxSerializedValueBytes) => {
2290
+ const encoded = encodeFrozen(frozen);
2291
+ if (typeof encoded === "object" && encoded !== null && !Array.isArray(encoded) && encoded.__reason === "max_serialized_value_bytes") {
2292
+ const bytes2 = jsonLiteralUtf8Bytes(encoded);
2293
+ return { value: encoded, bytes: bytes2, visitedNodes };
2294
+ }
2295
+ const bytes = jsonLiteralUtf8Bytes(encoded);
2296
+ if (bytes > maxSerializedValueBytes) {
2297
+ const bounded = truncation("max_serialized_value_bytes", { __serialized_bytes: bytes });
2298
+ return { value: bounded, bytes: jsonLiteralUtf8Bytes(bounded), visitedNodes };
2299
+ }
2300
+ return { value: encoded, bytes, visitedNodes };
2301
+ };
2302
+
2303
+ // src/execution-recorder/safe-serialize.ts
2304
+ var createSafeSerializer = (options = {}) => {
2305
+ const freezer = createValueFreezer(options);
2306
+ const serializeWithBytes = (value) => {
2307
+ const frozen = freezer.freeze(value);
2308
+ return encodeFrozenWithBytes(
2309
+ frozen.value,
2310
+ frozen.visitedNodes,
2311
+ freezer.limits.maxSerializedValueBytes
2312
+ );
1581
2313
  };
1582
2314
  return {
2315
+ freeze: freezer.freeze,
2316
+ encode: encodeFrozen,
1583
2317
  serialize: (value) => serializeWithBytes(value).value,
1584
2318
  serializeWithBytes
1585
2319
  };
@@ -1650,9 +2384,40 @@ var createSourceExclusionMatcher = (exclusions) => {
1650
2384
  return matchers.length === 0 ? () => false : (definition) => matchers.some((matcher) => matcher(definition));
1651
2385
  };
1652
2386
 
2387
+ // src/execution-recorder/warn-missing-async-context-frame.ts
2388
+ var ASYNC_CONTEXT_FRAME_FLAG = "--experimental-async-context-frame";
2389
+ var ASYNC_CONTEXT_FRAME_WARNING_SUPPRESS_ENV = "RASPUTIN_SUPPRESS_ASYNC_CONTEXT_FRAME_WARNING";
2390
+ var warnedSymbol = Symbol.for("rasputin.asyncContextFrameWarning");
2391
+ var hasFlag = (execArgv, nodeOptions) => {
2392
+ if (execArgv.includes(ASYNC_CONTEXT_FRAME_FLAG)) return true;
2393
+ if (!nodeOptions) return false;
2394
+ return nodeOptions.split(/\s+/).includes(ASYNC_CONTEXT_FRAME_FLAG);
2395
+ };
2396
+ var missingAsyncContextFrameWarning = (runtime) => {
2397
+ if (runtime.bun || !runtime.node) return void 0;
2398
+ const major = Number(runtime.node.split(".")[0]);
2399
+ if (!Number.isInteger(major) || major >= 24) return void 0;
2400
+ if (hasFlag(runtime.execArgv, runtime.nodeOptions)) return void 0;
2401
+ return `[rasputin] Node.js ${major} is running without ${ASYNC_CONTEXT_FRAME_FLAG}. AsyncLocalStorage is faster with that flag, which is the default on Node.js 24+. Start Node with ${ASYNC_CONTEXT_FRAME_FLAG}, or use Node.js 24 or newer. Set ${ASYNC_CONTEXT_FRAME_WARNING_SUPPRESS_ENV}=1 to hide this warning.`;
2402
+ };
2403
+ var warnIfMissingAsyncContextFrame = () => {
2404
+ if (process.env[ASYNC_CONTEXT_FRAME_WARNING_SUPPRESS_ENV] === "1") return;
2405
+ if (Reflect.get(globalThis, warnedSymbol)) return;
2406
+ const message = missingAsyncContextFrameWarning({
2407
+ bun: process.versions.bun,
2408
+ node: process.versions.node,
2409
+ execArgv: process.execArgv,
2410
+ nodeOptions: process.env.NODE_OPTIONS
2411
+ });
2412
+ if (!message) return;
2413
+ Reflect.set(globalThis, warnedSymbol, true);
2414
+ console.warn(message);
2415
+ };
2416
+
1653
2417
  // src/execution-recorder/execution-recorder.ts
1654
2418
  var DEFAULT_MAX_ACTIVE_MEMORY_BYTES = 64 * 1024 * 1024;
1655
- var DERIVATION_ROOT_RECORD_BYTES = 64;
2419
+ var DEFAULT_MAX_EXECUTION_HOLD_MS = 6e4;
2420
+ var DEFAULT_MAX_RETAINED_ERROR_RECORDINGS = 32;
1656
2421
  var phaseTimingEnabled = process.env.RASPUTIN_RECORDER_PHASE_TIMING === "1";
1657
2422
  var manualFunctionDefinition = (value) => {
1658
2423
  const located = /^(.+):([^:@]+)@(\d+):(\d+)$/.exec(value);
@@ -1671,72 +2436,39 @@ var normalizeFunctionDefinition = (value) => typeof value === "string" ? manualF
1671
2436
  var elapsedMs2 = (startedAtNs, endedAtNs = process.hrtime.bigint()) => Number(endedAtNs - startedAtNs) / 1e6;
1672
2437
  var roundedMilliseconds2 = (nanoseconds) => Math.round(Number(nanoseconds) / 1e6 * 1e4) / 1e4;
1673
2438
  var addRecorderTime = (recording, nanoseconds) => {
1674
- if (nanoseconds > 0n) recording.inlineRecorderTimeNs += nanoseconds;
2439
+ if (process.env.RASPUTIN_RECORDER_PHASE_TIMING !== "1" || nanoseconds <= 0n) return;
2440
+ recording.inlineRecorderTimeNs += nanoseconds;
2441
+ };
2442
+ var mapArrayLike = (args, map) => {
2443
+ const mapped = new Array(args.length);
2444
+ for (let index = 0; index < args.length; index++) {
2445
+ mapped[index] = map(args[index], index);
2446
+ }
2447
+ return mapped;
1675
2448
  };
1676
- var isPromiseLike = (value) => Boolean(value) && typeof value.then === "function";
1677
2449
  var notifyObserver = (observer, value) => {
1678
2450
  try {
1679
2451
  observer(value);
1680
2452
  } catch {
1681
2453
  }
1682
2454
  };
1683
- var observeCallback = (callback, onReturn, onThrow) => {
1684
- let result;
1685
- try {
1686
- result = callback();
1687
- } catch (error) {
1688
- notifyObserver(onThrow, error);
1689
- throw error;
1690
- }
1691
- if (isPromiseLike(result)) {
1692
- return result.then(
1693
- (value) => {
1694
- notifyObserver(onReturn, value);
1695
- return value;
1696
- },
1697
- (error) => {
1698
- notifyObserver(onThrow, error);
1699
- throw error;
1700
- }
1701
- );
1702
- }
1703
- notifyObserver(onReturn, result);
1704
- return result;
1705
- };
1706
- var observeRecordedCallback = (recording, recorderStartedAtNs, callback, onReturn, onThrow) => {
1707
- const callbackStartedAtNs = process.hrtime.bigint();
1708
- const recordExitWork = (callbackEndedAtNs2) => {
2455
+ var observeRecordedCallback = function __rasputinHandleRun__2(recording, recorderStartedAtNs, callback, onReturn, onThrow) {
2456
+ const callbackStartedAtNs = phaseTimingEnabled ? process.hrtime.bigint() : recorderStartedAtNs;
2457
+ const recordExitWork = (callbackEndedAtNs) => {
2458
+ if (!phaseTimingEnabled) return;
1709
2459
  addRecorderTime(recording, callbackStartedAtNs - recorderStartedAtNs);
1710
- addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
2460
+ addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
1711
2461
  };
1712
2462
  let result;
1713
2463
  try {
1714
2464
  result = callback();
1715
2465
  } catch (error) {
1716
- const callbackEndedAtNs2 = process.hrtime.bigint();
1717
2466
  notifyObserver(onThrow, error);
1718
- recordExitWork(callbackEndedAtNs2);
2467
+ recordExitWork(phaseTimingEnabled ? process.hrtime.bigint() : recorderStartedAtNs);
1719
2468
  throw error;
1720
2469
  }
1721
- if (isPromiseLike(result)) {
1722
- return result.then(
1723
- (value) => {
1724
- const callbackEndedAtNs2 = process.hrtime.bigint();
1725
- notifyObserver(onReturn, value);
1726
- recordExitWork(callbackEndedAtNs2);
1727
- return value;
1728
- },
1729
- (error) => {
1730
- const callbackEndedAtNs2 = process.hrtime.bigint();
1731
- notifyObserver(onThrow, error);
1732
- recordExitWork(callbackEndedAtNs2);
1733
- throw error;
1734
- }
1735
- );
1736
- }
1737
- const callbackEndedAtNs = process.hrtime.bigint();
1738
2470
  notifyObserver(onReturn, result);
1739
- recordExitWork(callbackEndedAtNs);
2471
+ recordExitWork(phaseTimingEnabled ? process.hrtime.bigint() : recorderStartedAtNs);
1740
2472
  return result;
1741
2473
  };
1742
2474
  var emptyStats = {
@@ -1766,32 +2498,34 @@ var emptyStats = {
1766
2498
  journalPoolMisses: 0,
1767
2499
  journalPoolSize: 0,
1768
2500
  journalAllocatedCapacity: 0,
1769
- derivationCandidateFunctions: 0,
1770
- derivationElidedFunctionCalls: 0,
1771
- derivationRootsCaptured: 0,
1772
- derivationControlFactsCaptured: 0,
1773
- derivationValuesAvoided: 0,
1774
- derivationFallbackFunctions: 0,
1775
- derivationFallbackExpressions: 0,
1776
- derivationFallbackReasons: {},
1777
- derivationRootBytes: 0
2501
+ attributionDegradations: 0
1778
2502
  };
1779
2503
  var noOpExecution = {
1780
2504
  createScope: () => ({
1781
2505
  run: (callback) => callback(),
1782
2506
  getErrorState: () => void 0,
2507
+ associateError: () => {
2508
+ },
1783
2509
  finish: () => {
1784
2510
  }
1785
2511
  }),
1786
- run: (_metadata, callback) => callback(),
1787
2512
  getErrorState: () => void 0,
1788
2513
  runFunction: (_functionId, _args, callback) => callback(),
1789
2514
  runFunctionPlans: (_plans, _planIndex, _args, callback) => callback(),
1790
2515
  prepareFunctionPlans: () => [],
1791
2516
  runPreparedFunction: (_plan, _args, callback) => callback(),
2517
+ enterPreparedFunction: () => ({
2518
+ leave: (value) => value,
2519
+ fail: () => {
2520
+ },
2521
+ end: () => {
2522
+ },
2523
+ run: (callback) => callback(),
2524
+ suspend: (value) => value,
2525
+ resume: (value) => value
2526
+ }),
1792
2527
  trace: (_functionId, fn) => fn,
1793
- getStats: () => ({ ...emptyStats, derivationFallbackReasons: {} }),
1794
- captureDerivationRoot: (_rootId, value) => value
2528
+ getStats: () => ({ ...emptyStats })
1795
2529
  };
1796
2530
  var mergeExecutionMetadata = (target, metadata) => {
1797
2531
  if (metadata.kind) target.kind = metadata.kind;
@@ -1816,7 +2550,41 @@ var newSuppression = (group, parentCallId, startedAtNs, endedAtNs) => ({
1816
2550
  });
1817
2551
  var createExecutionRecorder = (options) => {
1818
2552
  if (!options?.enabled) return noOpExecution;
2553
+ warnIfMissingAsyncContextFrame();
1819
2554
  const storage = new AsyncLocalStorage();
2555
+ const currentStore = () => {
2556
+ try {
2557
+ return storage.getStore();
2558
+ } catch {
2559
+ return void 0;
2560
+ }
2561
+ };
2562
+ const degradeAttribution = (recording, plan) => {
2563
+ if (!recording.attributionDegraded) {
2564
+ recording.attributionDegraded = true;
2565
+ stats.attributionDegradations++;
2566
+ const eventsDropped = Math.max(
2567
+ 1,
2568
+ recording.journal?.dropped ?? recording.memory.eventsDropped
2569
+ );
2570
+ recording.cachedState = {
2571
+ events: [],
2572
+ functions: [],
2573
+ truncated: { eventsDropped },
2574
+ capture: {
2575
+ completeness: "unavailable",
2576
+ reason: "attribution_invariant",
2577
+ valuesDropped: recording.memory.valuesDropped,
2578
+ eventsDropped
2579
+ }
2580
+ };
2581
+ }
2582
+ if (plan) plan.disabled = true;
2583
+ };
2584
+ const noteDisabledPlan = (recording) => {
2585
+ if (recording.finished || recording.evicted || recording.attributionDegraded) return;
2586
+ recording.disabledPlanEncountered = true;
2587
+ };
1820
2588
  const maxEventsPerExecution = sanitizeJournalCapacity(options.maxEventsPerExecution);
1821
2589
  const maxCapturedCallsPerFunction = Math.max(
1822
2590
  1,
@@ -1826,6 +2594,14 @@ var createExecutionRecorder = (options) => {
1826
2594
  0,
1827
2595
  Math.floor(options.maxActiveMemoryBytes ?? DEFAULT_MAX_ACTIVE_MEMORY_BYTES)
1828
2596
  );
2597
+ const maxExecutionHoldNs = BigInt(Math.max(1, Math.floor(options.maxExecutionHoldMs ?? DEFAULT_MAX_EXECUTION_HOLD_MS))) * 1000000n;
2598
+ const maxRetainedErrorRecordings = Math.max(
2599
+ 1,
2600
+ Math.floor(options.maxRetainedErrorRecordings ?? DEFAULT_MAX_RETAINED_ERROR_RECORDINGS)
2601
+ );
2602
+ const liveRecordings = [];
2603
+ let lastSweepNs = 0n;
2604
+ const sweepIntervalNs = maxExecutionHoldNs / 4n < 50000000n ? maxExecutionHoldNs / 4n : 50000000n;
1829
2605
  const memoryBudget = new RecorderMemoryBudget(
1830
2606
  maxActiveMemoryBytes,
1831
2607
  options.maxSerializedValueBytes ?? 8 * 1024
@@ -1843,6 +2619,7 @@ var createExecutionRecorder = (options) => {
1843
2619
  const internedPlans = /* @__PURE__ */ new Map();
1844
2620
  const preparedModules = /* @__PURE__ */ new WeakMap();
1845
2621
  const errorExecutions = /* @__PURE__ */ new WeakMap();
2622
+ const retainedErrorRecordings = [];
1846
2623
  const phases = phaseTimingEnabled ? { alsNs: 0n, materializeNs: 0n } : void 0;
1847
2624
  const stats = {
1848
2625
  functionCallsObserved: 0,
@@ -1861,15 +2638,7 @@ var createExecutionRecorder = (options) => {
1861
2638
  measuredExecutions: 0,
1862
2639
  totalInlineWallTimeMs: 0,
1863
2640
  maxInlineWallTimeMs: 0,
1864
- derivationCandidateFunctions: 0,
1865
- derivationElidedFunctionCalls: 0,
1866
- derivationRootsCaptured: 0,
1867
- derivationControlFactsCaptured: 0,
1868
- derivationValuesAvoided: 0,
1869
- derivationFallbackFunctions: 0,
1870
- derivationFallbackExpressions: 0,
1871
- derivationFallbackReasons: {},
1872
- derivationRootBytes: 0
2641
+ attributionDegradations: 0
1873
2642
  };
1874
2643
  const addPhase = (key, nanoseconds) => {
1875
2644
  if (phases && nanoseconds > 0n) phases[key] += nanoseconds;
@@ -1880,14 +2649,36 @@ var createExecutionRecorder = (options) => {
1880
2649
  stats.totalInlineWallTimeMs = Math.round((stats.totalInlineWallTimeMs + inlineWallTimeMs) * 1e4) / 1e4;
1881
2650
  stats.maxInlineWallTimeMs = Math.max(stats.maxInlineWallTimeMs, inlineWallTimeMs);
1882
2651
  };
1883
- const serializeAndCount = (value) => {
1884
- const serialized = serializer.serializeWithBytes(value);
2652
+ const freezeAndCount = (value) => {
2653
+ const frozen = serializer.freeze(value);
1885
2654
  stats.serializedValues++;
1886
- stats.serializedValueNodes += serialized.visitedNodes;
1887
- stats.serializedValueBytes += serialized.bytes;
1888
- return serialized;
2655
+ stats.serializedValueNodes += frozen.visitedNodes;
2656
+ stats.serializedValueBytes += frozen.estimatedBytes;
2657
+ return {
2658
+ value: frozen.value,
2659
+ bytes: frozen.estimatedBytes,
2660
+ visitedNodes: frozen.visitedNodes
2661
+ };
2662
+ };
2663
+ const captureValue = (recording, value) => {
2664
+ try {
2665
+ return memoryBudget.captureValue(recording.memory, () => freezeAndCount(value));
2666
+ } catch {
2667
+ return { __rasputin_type: "unserializable" };
2668
+ }
1889
2669
  };
1890
- const captureValue = (recording, value) => memoryBudget.captureValue(recording.memory, () => serializeAndCount(value));
2670
+ const encodeEventValues = (events) => events.map((event) => {
2671
+ if (event.type === "function_enter") {
2672
+ return { ...event, args: event.args.map((argument) => serializer.encode(argument)) };
2673
+ }
2674
+ if (event.type === "function_exit") {
2675
+ return { ...event, returnValue: serializer.encode(event.returnValue) };
2676
+ }
2677
+ if (event.type === "function_throw") {
2678
+ return { ...event, error: serializer.encode(event.error) };
2679
+ }
2680
+ return event;
2681
+ });
1891
2682
  const storePlan = (plan) => {
1892
2683
  plansByRuntimeId[plan.runtimePlanId] = plan;
1893
2684
  return plan;
@@ -1900,7 +2691,8 @@ var createExecutionRecorder = (options) => {
1900
2691
  definition,
1901
2692
  functionId: definition.functionId,
1902
2693
  excluded: excludesSource(definition),
1903
- estimatedCallBytes: estimatedCallBytesFor(definition.functionId)
2694
+ estimatedCallBytes: estimatedCallBytesFor(definition.functionId),
2695
+ omitCallValues: false
1904
2696
  });
1905
2697
  internedPlans.set(definition.functionId, plan);
1906
2698
  return plan;
@@ -1915,28 +2707,13 @@ var createExecutionRecorder = (options) => {
1915
2707
  definition,
1916
2708
  functionId: definition.functionId,
1917
2709
  excluded: excludesSource(definition),
1918
- estimatedCallBytes: estimatedCallBytesFor(definition.functionId)
2710
+ estimatedCallBytes: estimatedCallBytesFor(definition.functionId),
2711
+ omitCallValues: encodedPlanOmitsCallValues(encoded)
1919
2712
  });
1920
2713
  });
1921
2714
  preparedModules.set(plans, prepared);
1922
2715
  return prepared;
1923
2716
  };
1924
- const derivationMetrics = (recording) => {
1925
- const manifest = snapshotInstrumentationManifest();
1926
- const plans = manifest?.derivationPlans ?? [];
1927
- const reasons = { ...stats.derivationFallbackReasons };
1928
- return {
1929
- derivationCandidateFunctions: plans.filter((plan) => !plan.fallbackReason).length,
1930
- derivationElidedFunctionCalls: stats.derivationElidedFunctionCalls,
1931
- derivationRootsCaptured: recording.derivationRoots.length,
1932
- derivationControlFactsCaptured: stats.derivationControlFactsCaptured,
1933
- derivationValuesAvoided: stats.derivationValuesAvoided,
1934
- derivationFallbackFunctions: plans.filter((plan) => plan.fallbackReason).length,
1935
- derivationFallbackExpressions: recording.derivationRoots.length,
1936
- derivationFallbackReasons: reasons,
1937
- derivationRootBytes: recording.derivationRootBytes
1938
- };
1939
- };
1940
2717
  const eventsHaveOmittedValues = (events) => {
1941
2718
  for (const event of events) {
1942
2719
  if (event.type === "function_enter" && event.args.some((arg) => rasputinTagKind(arg) === "omitted")) {
@@ -1948,15 +2725,38 @@ var createExecutionRecorder = (options) => {
1948
2725
  }
1949
2726
  return false;
1950
2727
  };
1951
- const resolveCaptureProfile = (recording, events, truncated, capture, derivation) => {
2728
+ const resolveCaptureProfile = (recording, events, truncated, capture) => {
1952
2729
  const source = recording.sawAutomatic ? "automatic" : recording.sawManual ? "manual" : "scope-only";
1953
2730
  if (source === "scope-only") {
1954
2731
  return {
1955
2732
  source,
1956
2733
  functionBoundaries: "none",
1957
2734
  functionValues: "none",
1958
- timings: "none",
1959
- derivation: derivation ? "available" : "none"
2735
+ timings: "none"
2736
+ };
2737
+ }
2738
+ if (recording.evicted || capture?.completeness === "unavailable") {
2739
+ return {
2740
+ source,
2741
+ functionBoundaries: "none",
2742
+ functionValues: "none",
2743
+ timings: "none"
2744
+ };
2745
+ }
2746
+ if (recording.budgetExpired || capture?.reason === "long_lived_execution_budget") {
2747
+ return {
2748
+ source,
2749
+ functionBoundaries: events.length > 0 ? "partial" : "none",
2750
+ functionValues: events.length > 0 ? "selective" : "none",
2751
+ timings: events.length > 0 ? "partial" : "none"
2752
+ };
2753
+ }
2754
+ if (capture?.reason === "plan_disabled_after_attribution_invariant") {
2755
+ return {
2756
+ source,
2757
+ functionBoundaries: events.length > 0 ? "partial" : "none",
2758
+ functionValues: eventsHaveOmittedValues(events) ? "selective" : events.length > 0 ? "full" : "none",
2759
+ timings: events.length > 0 ? "partial" : "none"
1960
2760
  };
1961
2761
  }
1962
2762
  const droppedEvents = Boolean(truncated?.eventsDropped || capture?.eventsDropped);
@@ -1964,22 +2764,7 @@ var createExecutionRecorder = (options) => {
1964
2764
  source,
1965
2765
  functionBoundaries: droppedEvents ? "partial" : "full",
1966
2766
  functionValues: eventsHaveOmittedValues(events) ? "selective" : "full",
1967
- timings: droppedEvents ? "partial" : "full",
1968
- derivation: derivation ? "available" : "none"
1969
- };
1970
- };
1971
- const derivationCapture = (recording, functions) => {
1972
- const manifest = snapshotInstrumentationManifest();
1973
- if (!manifest) return void 0;
1974
- const plans = manifest.derivationPlans ?? [];
1975
- const recordedIds = new Set(functions.map((fn) => fn.functionId));
1976
- if (!plans.some((plan) => recordedIds.has(plan.functionId))) {
1977
- return void 0;
1978
- }
1979
- return {
1980
- manifestHash: hashInstrumentationManifest(manifest),
1981
- roots: recording.derivationRoots.slice(),
1982
- controlFacts: []
2767
+ timings: droppedEvents ? "partial" : "full"
1983
2768
  };
1984
2769
  };
1985
2770
  const stateFrom = (recording, endedAtNs = process.hrtime.bigint()) => {
@@ -1988,40 +2773,58 @@ var createExecutionRecorder = (options) => {
1988
2773
  let functions = [];
1989
2774
  let truncated;
1990
2775
  let capture;
1991
- let derivation;
1992
2776
  if (recording.cachedState) {
1993
2777
  events = recording.cachedState.events;
1994
2778
  functions = recording.cachedState.functions;
1995
2779
  truncated = recording.cachedState.truncated;
1996
2780
  capture = recording.cachedState.capture;
1997
- derivation = recording.cachedState.derivation;
1998
2781
  } else {
1999
2782
  if (recording.journal) {
2000
2783
  const materialized = recording.journal.materialize(plansByRuntimeId, recording.startedAtNs);
2001
- events = materialized.events;
2784
+ events = encodeEventValues(materialized.events);
2785
+ if (recording.lateCapturedCallIds && recording.lateCapturedCallIds.size > 0) {
2786
+ events = events.map(
2787
+ (event) => event.type === "function_enter" && recording.lateCapturedCallIds?.has(event.callId) ? { ...event, capturedAt: "throw" } : event
2788
+ );
2789
+ }
2002
2790
  functions = materialized.functions;
2003
2791
  truncated = recording.journal.dropped > 0 ? { eventsDropped: recording.journal.dropped } : void 0;
2004
2792
  }
2005
- capture = recording.memory.underPressure ? {
2006
- completeness: "partial",
2007
- reason: "process_memory_budget",
2008
- valuesDropped: recording.memory.valuesDropped,
2009
- eventsDropped: recording.memory.eventsDropped
2010
- } : void 0;
2011
- derivation = derivationCapture(recording, functions);
2793
+ if (recording.budgetExpired) {
2794
+ capture = {
2795
+ completeness: "partial",
2796
+ reason: "long_lived_execution_budget",
2797
+ valuesDropped: recording.memory.valuesDropped,
2798
+ eventsDropped: recording.memory.eventsDropped
2799
+ };
2800
+ } else if (recording.disabledPlanEncountered) {
2801
+ capture = {
2802
+ completeness: "partial",
2803
+ reason: "plan_disabled_after_attribution_invariant",
2804
+ valuesDropped: recording.memory.valuesDropped,
2805
+ eventsDropped: recording.memory.eventsDropped
2806
+ };
2807
+ } else if (recording.memory.underPressure) {
2808
+ capture = {
2809
+ completeness: "partial",
2810
+ reason: "process_memory_budget",
2811
+ valuesDropped: recording.memory.valuesDropped,
2812
+ eventsDropped: recording.memory.eventsDropped
2813
+ };
2814
+ }
2012
2815
  if (recording.finished && recording.inFlightCalls === 0 && recording.journal) {
2013
- recording.cachedState = { events, functions, truncated, capture, derivation };
2816
+ recording.cachedState = { events, functions, truncated, capture };
2014
2817
  journalPool.release(recording.journal);
2015
2818
  recording.journal = void 0;
2016
2819
  }
2017
2820
  }
2018
2821
  const state = {
2019
2822
  version: 4,
2020
- captureProfile: resolveCaptureProfile(recording, events, truncated, capture, derivation),
2823
+ captureProfile: resolveCaptureProfile(recording, events, truncated, capture),
2021
2824
  executionId: recording.executionId,
2022
2825
  startedAt: recording.startedAt,
2023
2826
  durationMs: elapsedMs2(recording.startedAtNs, endedAtNs),
2024
- recorder: { inlineWallTimeMs: 0, derivation: derivationMetrics(recording) },
2827
+ recorder: { inlineWallTimeMs: 0 },
2025
2828
  execution: {
2026
2829
  ...recording.execution,
2027
2830
  ...recording.execution.request ? { request: { ...recording.execution.request } } : {}
@@ -2029,36 +2832,153 @@ var createExecutionRecorder = (options) => {
2029
2832
  functions: functions.slice(),
2030
2833
  events: events.slice(),
2031
2834
  ...truncated ? { truncated: { ...truncated } } : {},
2032
- ...capture ? { capture: { ...capture } } : {},
2033
- ...derivation ? { derivation: { ...derivation, roots: derivation.roots.slice() } } : {}
2835
+ ...capture ? { capture: { ...capture } } : {}
2034
2836
  };
2035
2837
  if (phaseTimingEnabled)
2036
2838
  addPhase("materializeNs", process.hrtime.bigint() - recorderStartedAtNs);
2037
2839
  const sizeBudgetStartedAtNs = process.hrtime.bigint();
2038
2840
  addRecorderTime(recording, sizeBudgetStartedAtNs - recorderStartedAtNs);
2039
2841
  state.recorder = {
2040
- inlineWallTimeMs: roundedMilliseconds2(recording.inlineRecorderTimeNs),
2041
- derivation: derivationMetrics(recording)
2842
+ inlineWallTimeMs: roundedMilliseconds2(recording.inlineRecorderTimeNs)
2042
2843
  };
2043
2844
  const boundedState = enforceRuntimeStateSizeBudget(state, runtimeStateSizeBudget);
2044
2845
  addRecorderTime(recording, process.hrtime.bigint() - sizeBudgetStartedAtNs);
2045
2846
  boundedState.recorder = {
2046
- inlineWallTimeMs: roundedMilliseconds2(recording.inlineRecorderTimeNs),
2047
- derivation: derivationMetrics(recording)
2847
+ inlineWallTimeMs: roundedMilliseconds2(recording.inlineRecorderTimeNs)
2048
2848
  };
2049
2849
  return boundedState.truncated?.size ? enforceRuntimeStateSizeBudget(boundedState, runtimeStateSizeBudget) : boundedState;
2050
2850
  };
2051
- const rememberError = (error, recording) => {
2052
- recording.hasError = true;
2053
- if (typeof error !== "object" && typeof error !== "function" || error === null) return;
2054
- if (!errorExecutions.has(error)) {
2055
- stats.errorSnapshots++;
2056
- if (recording.memory.underPressure && !recording.partialSnapshotCounted) {
2057
- recording.partialSnapshotCounted = true;
2058
- stats.partialErrorSnapshots++;
2059
- }
2851
+ const evictRetainedRecording = (recording) => {
2852
+ const eventCount = recording.cachedState?.events.length ?? recording.journal?.eventCount ?? 0;
2853
+ const dropped = (recording.cachedState?.truncated?.eventsDropped ?? recording.journal?.dropped ?? 0) + eventCount;
2854
+ try {
2855
+ memoryBudget.release(recording.memory);
2856
+ } catch {
2857
+ }
2858
+ if (recording.journal) {
2859
+ journalPool.release(recording.journal);
2860
+ recording.journal = void 0;
2861
+ }
2862
+ recording.evicted = true;
2863
+ detachLiveRecording(recording);
2864
+ recording.cachedState = {
2865
+ events: [],
2866
+ functions: [],
2867
+ truncated: { eventsDropped: Math.max(1, dropped) },
2868
+ capture: {
2869
+ completeness: "unavailable",
2870
+ reason: "retained_state_evicted",
2871
+ valuesDropped: 0,
2872
+ eventsDropped: Math.max(1, dropped)
2873
+ }
2874
+ };
2875
+ };
2876
+ const trimFinishedRetainedRecordings = (keep) => {
2877
+ while (retainedErrorRecordings.length > maxRetainedErrorRecordings) {
2878
+ const evictIndex = retainedErrorRecordings.findIndex(
2879
+ (candidate) => candidate !== keep && candidate.finished
2880
+ );
2881
+ if (evictIndex < 0) break;
2882
+ const [evicted] = retainedErrorRecordings.splice(evictIndex, 1);
2883
+ if (evicted) evictRetainedRecording(evicted);
2884
+ }
2885
+ };
2886
+ const retainErrorRecording = (recording) => {
2887
+ if (recording.retainedForError) return;
2888
+ recording.retainedForError = true;
2889
+ retainedErrorRecordings.push(recording);
2890
+ trimFinishedRetainedRecordings(recording);
2891
+ };
2892
+ const detachLiveRecording = (recording) => {
2893
+ const index = liveRecordings.indexOf(recording);
2894
+ if (index >= 0) liveRecordings.splice(index, 1);
2895
+ };
2896
+ const expireLongLivedRecording = (recording, nowNs) => {
2897
+ if (recording.evicted || recording.budgetExpired) return;
2898
+ recording.budgetExpired = true;
2899
+ recording.memory.underPressure = true;
2900
+ const journalEvents = recording.journal?.eventCount ?? 0;
2901
+ const cachedEvents = recording.cachedState?.events.length ?? 0;
2902
+ const eventsDropped = Math.max(
2903
+ 1,
2904
+ recording.memory.eventsDropped + journalEvents + cachedEvents
2905
+ );
2906
+ try {
2907
+ memoryBudget.release(recording.memory);
2908
+ } catch {
2909
+ }
2910
+ if (recording.journal) {
2911
+ journalPool.release(recording.journal);
2912
+ recording.journal = void 0;
2913
+ }
2914
+ recording.cachedState = {
2915
+ events: [],
2916
+ functions: [],
2917
+ truncated: { eventsDropped },
2918
+ capture: {
2919
+ completeness: "partial",
2920
+ reason: "long_lived_execution_budget",
2921
+ valuesDropped: recording.memory.valuesDropped,
2922
+ eventsDropped
2923
+ }
2924
+ };
2925
+ if (!recording.finished) {
2926
+ recording.finished = true;
2927
+ stats.activeExecutions = Math.max(0, stats.activeExecutions - 1);
2928
+ recording.finishedAtNs = nowNs;
2929
+ if (!recording.hasError) {
2930
+ stats.successfulExecutionsDiscarded++;
2931
+ }
2060
2932
  }
2061
- errorExecutions.set(error, recording);
2933
+ detachLiveRecording(recording);
2934
+ };
2935
+ const sweepLongLivedExecutions = (nowNs) => {
2936
+ if (nowNs - lastSweepNs < sweepIntervalNs && liveRecordings.length < 256) return;
2937
+ lastSweepNs = nowNs;
2938
+ for (let index = liveRecordings.length - 1; index >= 0; index--) {
2939
+ const recording = liveRecordings[index];
2940
+ if (!recording) continue;
2941
+ if (recording.evicted || recording.memory.released || recording.budgetExpired) {
2942
+ liveRecordings.splice(index, 1);
2943
+ continue;
2944
+ }
2945
+ if (nowNs - recording.startedAtNs < maxExecutionHoldNs) continue;
2946
+ try {
2947
+ expireLongLivedRecording(recording, nowNs);
2948
+ } catch {
2949
+ }
2950
+ }
2951
+ };
2952
+ const rememberError = (error, recording) => {
2953
+ recording.hasError = true;
2954
+ const key = (typeof error === "object" || typeof error === "function") && error !== null ? error : void 0;
2955
+ if (recording.budgetExpired && !(key && errorExecutions.has(key))) {
2956
+ const eventsDropped = Math.max(
2957
+ 1,
2958
+ recording.cachedState?.capture?.eventsDropped ?? recording.cachedState?.truncated?.eventsDropped ?? recording.memory.eventsDropped
2959
+ );
2960
+ recording.cachedState = {
2961
+ events: [],
2962
+ functions: [],
2963
+ truncated: { eventsDropped },
2964
+ capture: {
2965
+ completeness: "unavailable",
2966
+ reason: "long_lived_execution_budget",
2967
+ valuesDropped: recording.memory.valuesDropped,
2968
+ eventsDropped
2969
+ }
2970
+ };
2971
+ }
2972
+ retainErrorRecording(recording);
2973
+ if (!key) return;
2974
+ if (!errorExecutions.has(key)) {
2975
+ stats.errorSnapshots++;
2976
+ if (recording.memory.underPressure && !recording.partialSnapshotCounted) {
2977
+ recording.partialSnapshotCounted = true;
2978
+ stats.partialErrorSnapshots++;
2979
+ }
2980
+ }
2981
+ errorExecutions.set(key, recording);
2062
2982
  };
2063
2983
  const countDroppedEvents = (recording, droppedBefore) => {
2064
2984
  const dropped = recording.journal?.dropped ?? droppedBefore;
@@ -2108,13 +3028,19 @@ var createExecutionRecorder = (options) => {
2108
3028
  return {
2109
3029
  // Keep the bounded thrown value even after surrounding capture degrades. A partial
2110
3030
  // snapshot without the exception itself would not be useful for investigation.
2111
- value: serializeAndCount(error).value,
3031
+ value: (() => {
3032
+ try {
3033
+ return freezeAndCount(error).value;
3034
+ } catch {
3035
+ return { __rasputin_type: "unserializable" };
3036
+ }
3037
+ })(),
2112
3038
  commit: () => {
2113
3039
  if (key) recording.capturedErrors.set(key, callId);
2114
3040
  }
2115
3041
  };
2116
3042
  };
2117
- const captureCompletedThrow = (recording, plan, args, parentCallId, startedAtNs, error) => {
3043
+ const captureCompletedThrow = (recording, plan, args, parentCallId, startedAtNs, error, capturedArgs) => {
2118
3044
  if (!recording.journal) {
2119
3045
  rememberError(error, recording);
2120
3046
  return;
@@ -2125,7 +3051,7 @@ var createExecutionRecorder = (options) => {
2125
3051
  }
2126
3052
  const callId = ++recording.nextCallId;
2127
3053
  const capturedError = serializedError(recording, error, callId);
2128
- const capturedArgs = Array.from(args, (argument) => captureValue(recording, argument));
3054
+ const recordedArgs = capturedArgs ?? mapArrayLike(args, (argument) => captureValue(recording, argument));
2129
3055
  const endedAtNs = process.hrtime.bigint();
2130
3056
  const droppedBefore = recording.journal.dropped;
2131
3057
  const retained = recording.journal.forceCompletedCall(
@@ -2133,13 +3059,15 @@ var createExecutionRecorder = (options) => {
2133
3059
  callId,
2134
3060
  parentCallId,
2135
3061
  startedAtNs - recording.startedAtNs,
2136
- capturedArgs,
3062
+ recordedArgs,
2137
3063
  KIND_THROW,
2138
3064
  endedAtNs - recording.startedAtNs,
2139
3065
  endedAtNs - startedAtNs,
2140
3066
  capturedError.value
2141
3067
  );
2142
3068
  if (retained) {
3069
+ recording.lateCapturedCallIds ??= /* @__PURE__ */ new Set();
3070
+ recording.lateCapturedCallIds.add(callId);
2143
3071
  stats.functionCallsCaptured++;
2144
3072
  capturedError.commit();
2145
3073
  }
@@ -2184,35 +3112,47 @@ var createExecutionRecorder = (options) => {
2184
3112
  };
2185
3113
  const settleInFlight = (recording) => {
2186
3114
  if (recording.inFlightCalls > 0) recording.inFlightCalls--;
2187
- releaseJournalIfIdle(recording);
3115
+ releaseWhenIdle(recording);
2188
3116
  };
2189
- const finish = (store, metadata) => {
2190
- const { recording } = store;
2191
- if (recording.finished) return;
2192
- const recorderStartedAtNs = process.hrtime.bigint();
2193
- recording.finished = true;
2194
- if (metadata) mergeExecutionMetadata(recording.execution, metadata);
2195
- memoryBudget.release(recording.memory);
2196
- stats.activeExecutions = Math.max(0, stats.activeExecutions - 1);
2197
- if (!recording.hasError) {
2198
- stats.successfulExecutionsDiscarded++;
3117
+ const releaseWhenIdle = (recording) => {
3118
+ try {
3119
+ if (!recording.finished || recording.inFlightCalls > 0) return;
3120
+ memoryBudget.release(recording.memory);
2199
3121
  releaseJournalIfIdle(recording);
3122
+ } catch {
2200
3123
  }
2201
- recording.finishedAtNs = process.hrtime.bigint();
2202
- addRecorderTime(recording, recording.finishedAtNs - recorderStartedAtNs);
2203
- recordInlineTiming(recording);
2204
3124
  };
2205
- const runStore = (store, callback) => {
3125
+ const finish = (store, metadata) => {
3126
+ try {
3127
+ const { recording } = store;
3128
+ if (recording.finished) return;
3129
+ const recorderStartedAtNs = process.hrtime.bigint();
3130
+ recording.finished = true;
3131
+ if (metadata) mergeExecutionMetadata(recording.execution, metadata);
3132
+ stats.activeExecutions = Math.max(0, stats.activeExecutions - 1);
3133
+ if (!recording.hasError) {
3134
+ stats.successfulExecutionsDiscarded++;
3135
+ }
3136
+ recording.finishedAtNs = process.hrtime.bigint();
3137
+ addRecorderTime(recording, recording.finishedAtNs - recorderStartedAtNs);
3138
+ recordInlineTiming(recording);
3139
+ releaseWhenIdle(recording);
3140
+ if (recording.inFlightCalls === 0) detachLiveRecording(recording);
3141
+ } catch {
3142
+ }
3143
+ };
3144
+ const runStore = function __rasputinHandleRun__3(store, callback) {
2206
3145
  if (!phaseTimingEnabled) return storage.run(store, callback);
2207
3146
  const alsStartedAtNs = process.hrtime.bigint();
2208
- return storage.run(store, () => {
3147
+ return storage.run(store, function __rasputinHandleRun__4() {
2209
3148
  addPhase("alsNs", process.hrtime.bigint() - alsStartedAtNs);
2210
3149
  return callback();
2211
3150
  });
2212
3151
  };
2213
3152
  const createScope = (metadata) => {
2214
- const recorderStartedAtNs = process.hrtime.bigint();
2215
3153
  try {
3154
+ const recorderStartedAtNs = process.hrtime.bigint();
3155
+ sweepLongLivedExecutions(recorderStartedAtNs);
2216
3156
  const recording = {
2217
3157
  executionId: `${Date.now()}-${process.pid}-${++executionCounter}`,
2218
3158
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -2231,29 +3171,52 @@ var createExecutionRecorder = (options) => {
2231
3171
  hasError: false,
2232
3172
  memory: memoryBudget.startExecution(),
2233
3173
  partialSnapshotCounted: false,
2234
- derivationRoots: [],
2235
- derivationRootBytes: 0,
2236
3174
  sawAutomatic: false,
2237
3175
  sawManual: false
2238
3176
  };
2239
3177
  stats.activeExecutions++;
2240
3178
  stats.peakActiveExecutions = Math.max(stats.peakActiveExecutions, stats.activeExecutions);
3179
+ liveRecordings.push(recording);
2241
3180
  addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
2242
3181
  const store = { recording };
2243
3182
  return {
2244
- run: (callback) => {
2245
- const runStartedAtNs = process.hrtime.bigint();
2246
- return runStore(store, () => {
2247
- addRecorderTime(recording, process.hrtime.bigint() - runStartedAtNs);
3183
+ run: function __rasputinHandleRun__3(callback) {
3184
+ let startedCallback = false;
3185
+ try {
3186
+ const runStartedAtNs = process.hrtime.bigint();
3187
+ return runStore(store, function __rasputinHandleRun__4() {
3188
+ startedCallback = true;
3189
+ addRecorderTime(recording, process.hrtime.bigint() - runStartedAtNs);
3190
+ try {
3191
+ return callback();
3192
+ } catch (error) {
3193
+ if (recording.budgetExpired || recording.evicted) {
3194
+ rememberError(error, recording);
3195
+ }
3196
+ throw error;
3197
+ }
3198
+ });
3199
+ } catch (error) {
3200
+ if (startedCallback) throw error;
2248
3201
  return callback();
2249
- });
3202
+ }
2250
3203
  },
2251
3204
  getErrorState: (error, errorMetadata) => {
2252
- const getStateStartedAtNs = process.hrtime.bigint();
2253
- if (errorMetadata) mergeExecutionMetadata(recording.execution, errorMetadata);
2254
- rememberError(error, recording);
2255
- addRecorderTime(recording, process.hrtime.bigint() - getStateStartedAtNs);
2256
- return stateFrom(recording, recording.finishedAtNs);
3205
+ try {
3206
+ const getStateStartedAtNs = process.hrtime.bigint();
3207
+ if (errorMetadata) mergeExecutionMetadata(recording.execution, errorMetadata);
3208
+ rememberError(error, recording);
3209
+ addRecorderTime(recording, process.hrtime.bigint() - getStateStartedAtNs);
3210
+ return stateFrom(recording, recording.finishedAtNs);
3211
+ } catch {
3212
+ return void 0;
3213
+ }
3214
+ },
3215
+ associateError: (error) => {
3216
+ try {
3217
+ rememberError(error, recording);
3218
+ } catch {
3219
+ }
2257
3220
  },
2258
3221
  finish: (finishMetadata) => finish(store, finishMetadata)
2259
3222
  };
@@ -2261,32 +3224,11 @@ var createExecutionRecorder = (options) => {
2261
3224
  return noOpExecution.createScope(metadata);
2262
3225
  }
2263
3226
  };
2264
- const run = (metadata, callback) => {
2265
- const scope = createScope(metadata);
2266
- return scope.run(
2267
- () => observeCallback(
2268
- callback,
2269
- () => scope.finish(),
2270
- (error) => {
2271
- try {
2272
- const store = storage.getStore();
2273
- if (store) {
2274
- const recorderStartedAtNs = process.hrtime.bigint();
2275
- rememberError(error, store.recording);
2276
- addRecorderTime(store.recording, process.hrtime.bigint() - recorderStartedAtNs);
2277
- }
2278
- } finally {
2279
- scope.finish();
2280
- }
2281
- }
2282
- )
2283
- );
2284
- };
2285
3227
  const getErrorState = (error, metadata) => {
2286
3228
  const getStateStartedAtNs = process.hrtime.bigint();
2287
3229
  try {
2288
3230
  const weakKey = (typeof error === "object" || typeof error === "function") && error !== null ? error : void 0;
2289
- const recording = (weakKey ? errorExecutions.get(weakKey) : void 0) ?? storage.getStore()?.recording;
3231
+ const recording = (weakKey ? errorExecutions.get(weakKey) : void 0) ?? currentStore()?.recording;
2290
3232
  if (!recording) return void 0;
2291
3233
  if (metadata) mergeExecutionMetadata(recording.execution, metadata);
2292
3234
  rememberError(error, recording);
@@ -2296,13 +3238,46 @@ var createExecutionRecorder = (options) => {
2296
3238
  return void 0;
2297
3239
  }
2298
3240
  };
2299
- const runPreparedFunctionFromStore = (store, plan, args, callback, omitValues) => {
2300
- if (!store || store.recording.finished) return callback();
3241
+ const runPreparedFunctionFromStore = function __rasputinHandleRun__3(store, plan, args, callback, omitValues) {
3242
+ let startedCallback = false;
3243
+ try {
3244
+ return runPreparedFunctionFromStoreInner(
3245
+ store,
3246
+ plan,
3247
+ args,
3248
+ function __rasputinHandleRun__4() {
3249
+ startedCallback = true;
3250
+ return callback();
3251
+ },
3252
+ omitValues
3253
+ );
3254
+ } catch (error) {
3255
+ if (startedCallback) throw error;
3256
+ return callback();
3257
+ }
3258
+ };
3259
+ const runPreparedFunctionFromStoreInner = function __rasputinHandleRun__3(store, plan, args, callback, omitValues) {
3260
+ const omitCallValues = omitValues === true || plan.omitCallValues;
3261
+ if (!store) return callback();
3262
+ if (plan.disabled) {
3263
+ noteDisabledPlan(store.recording);
3264
+ return callback();
3265
+ }
3266
+ if (store.recording.finished) {
3267
+ try {
3268
+ return callback();
3269
+ } catch (error) {
3270
+ if (store.recording.budgetExpired || store.recording.evicted) {
3271
+ rememberError(error, store.recording);
3272
+ }
3273
+ throw error;
3274
+ }
3275
+ }
2301
3276
  stats.functionCallsObserved++;
2302
3277
  const recorderStartedAtNs = process.hrtime.bigint();
2303
3278
  if (store.suppressCapture || plan.excluded) {
2304
3279
  stats.functionCallsExcluded++;
2305
- return runStore({ ...store, suppressCapture: true }, () => {
3280
+ return runStore({ ...store, suppressCapture: true }, function __rasputinHandleRun__4() {
2306
3281
  addRecorderTime(store.recording, process.hrtime.bigint() - recorderStartedAtNs);
2307
3282
  return callback();
2308
3283
  });
@@ -2313,41 +3288,21 @@ var createExecutionRecorder = (options) => {
2313
3288
  const group = repeatedCallGroup(recording, plan, parentCallId);
2314
3289
  group.observedCalls++;
2315
3290
  const journal = acquireJournal(recording);
2316
- if (group.observedCalls === 1) journal?.notePlan(plan.runtimePlanId);
3291
+ try {
3292
+ if (group.observedCalls === 1) journal?.notePlan(plan.runtimePlanId);
3293
+ } catch {
3294
+ }
2317
3295
  if (group.observedCalls > maxCapturedCallsPerFunction) {
2318
3296
  const startedAtNs2 = process.hrtime.bigint();
2319
3297
  try {
2320
- const result = callback();
2321
- if (isPromiseLike(result)) {
2322
- addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
2323
- return result.then(
2324
- (value) => {
2325
- const callbackEndedAtNs2 = process.hrtime.bigint();
2326
- recordSuppressedCall(recording, group, parentCallId, startedAtNs2, callbackEndedAtNs2);
2327
- addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
2328
- settleInFlight(recording);
2329
- return value;
2330
- },
2331
- (error) => {
2332
- const callbackEndedAtNs2 = process.hrtime.bigint();
2333
- captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs2, error);
2334
- addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
2335
- settleInFlight(recording);
2336
- throw error;
2337
- }
2338
- );
2339
- }
2340
- const callbackEndedAtNs = process.hrtime.bigint();
2341
- recordSuppressedCall(recording, group, parentCallId, startedAtNs2, callbackEndedAtNs);
2342
- addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
2343
- addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
3298
+ const result = runStore(store, function __rasputinHandleRun__4() {
3299
+ return callback();
3300
+ });
3301
+ recordSuppressedCall(recording, group, parentCallId, startedAtNs2, process.hrtime.bigint());
2344
3302
  settleInFlight(recording);
2345
3303
  return result;
2346
3304
  } catch (error) {
2347
- const callbackEndedAtNs = process.hrtime.bigint();
2348
3305
  captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs2, error);
2349
- addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
2350
- addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
2351
3306
  settleInFlight(recording);
2352
3307
  throw error;
2353
3308
  }
@@ -2355,9 +3310,8 @@ var createExecutionRecorder = (options) => {
2355
3310
  const startedAtNs = process.hrtime.bigint();
2356
3311
  if (!journal) {
2357
3312
  memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes);
2358
- return runStore(
2359
- store,
2360
- () => observeRecordedCallback(
3313
+ return runStore(store, function __rasputinHandleRun__4() {
3314
+ return observeRecordedCallback(
2361
3315
  recording,
2362
3316
  recorderStartedAtNs,
2363
3317
  callback,
@@ -2366,8 +3320,8 @@ var createExecutionRecorder = (options) => {
2366
3320
  rememberError(error, recording);
2367
3321
  settleInFlight(recording);
2368
3322
  }
2369
- )
2370
- );
3323
+ );
3324
+ });
2371
3325
  }
2372
3326
  if (!journal.canStartCall()) {
2373
3327
  const captureSuccess = () => {
@@ -2376,9 +3330,8 @@ var createExecutionRecorder = (options) => {
2376
3330
  countDroppedEvents(recording, droppedBefore);
2377
3331
  settleInFlight(recording);
2378
3332
  };
2379
- return runStore(
2380
- store,
2381
- () => observeRecordedCallback(
3333
+ return runStore(store, function __rasputinHandleRun__4() {
3334
+ return observeRecordedCallback(
2382
3335
  recording,
2383
3336
  recorderStartedAtNs,
2384
3337
  callback,
@@ -2387,8 +3340,8 @@ var createExecutionRecorder = (options) => {
2387
3340
  captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs, error);
2388
3341
  settleInFlight(recording);
2389
3342
  }
2390
- )
2391
- );
3343
+ );
3344
+ });
2392
3345
  }
2393
3346
  if (!memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes)) {
2394
3347
  return observeRecordedCallback(
@@ -2404,12 +3357,27 @@ var createExecutionRecorder = (options) => {
2404
3357
  }
2405
3358
  const callId = ++recording.nextCallId;
2406
3359
  const enterTimestampNs = process.hrtime.bigint() - recording.startedAtNs;
2407
- const capturedArgs = omitValues ? Array.from(args, () => rasputinOmitted()) : Array.from(args, (argument) => captureValue(recording, argument));
2408
- journal.startCall(plan.runtimePlanId, callId, parentCallId, enterTimestampNs, capturedArgs);
3360
+ const capturedArgs = omitCallValues ? mapArrayLike(args, () => rasputinOmitted()) : mapArrayLike(args, (argument) => captureValue(recording, argument));
3361
+ try {
3362
+ journal.startCall(plan.runtimePlanId, callId, parentCallId, enterTimestampNs, capturedArgs);
3363
+ } catch {
3364
+ journal.dropCall();
3365
+ return runStore(store, function __rasputinHandleRun__4() {
3366
+ return observeRecordedCallback(
3367
+ recording,
3368
+ recorderStartedAtNs,
3369
+ callback,
3370
+ () => settleInFlight(recording),
3371
+ (error) => {
3372
+ rememberError(error, recording);
3373
+ settleInFlight(recording);
3374
+ }
3375
+ );
3376
+ });
3377
+ }
2409
3378
  const callStore = { recording, currentCallId: callId };
2410
- return runStore(
2411
- callStore,
2412
- () => observeRecordedCallback(
3379
+ return runStore(callStore, function __rasputinHandleRun__4() {
3380
+ return observeRecordedCallback(
2413
3381
  recording,
2414
3382
  recorderStartedAtNs,
2415
3383
  callback,
@@ -2417,7 +3385,7 @@ var createExecutionRecorder = (options) => {
2417
3385
  if (recording.journal) {
2418
3386
  const timestampNs = process.hrtime.bigint() - recording.startedAtNs;
2419
3387
  const durationNs = process.hrtime.bigint() - startedAtNs;
2420
- const returnValue = omitValues ? rasputinOmitted() : captureValue(recording, value);
3388
+ const returnValue = omitCallValues ? rasputinOmitted() : captureValue(recording, value);
2421
3389
  recording.journal.finishCall(KIND_EXIT, callId, timestampNs, durationNs, returnValue);
2422
3390
  stats.functionCallsCaptured++;
2423
3391
  }
@@ -2442,18 +3410,373 @@ var createExecutionRecorder = (options) => {
2442
3410
  rememberError(error, recording);
2443
3411
  settleInFlight(recording);
2444
3412
  }
2445
- )
2446
- );
3413
+ );
3414
+ });
3415
+ };
3416
+ const noopHandle2 = {
3417
+ leave: (value) => value,
3418
+ fail: () => {
3419
+ },
3420
+ end: () => {
3421
+ },
3422
+ run: function __rasputinHandleRun__3(callback) {
3423
+ return runExactlyOnce((invoke) => invoke(), callback);
3424
+ },
3425
+ suspend: (value) => value,
3426
+ resume: (value) => value
3427
+ };
3428
+ const bindStoreTransitions = (active, parent, recording, plan) => {
3429
+ let suspended = false;
3430
+ const enter = (next) => {
3431
+ try {
3432
+ storage.enterWith(next);
3433
+ } catch {
3434
+ degradeAttribution(recording, plan);
3435
+ }
3436
+ };
3437
+ const expectStore = (expected) => {
3438
+ if (currentStore() !== expected) degradeAttribution(recording, plan);
3439
+ };
3440
+ return {
3441
+ enterActive: () => enter(active),
3442
+ run: function __rasputinHandleRun__3(callback) {
3443
+ return runExactlyOnce((invoke) => {
3444
+ try {
3445
+ enter(parent);
3446
+ } catch {
3447
+ }
3448
+ return storage.run(active, invoke);
3449
+ }, callback);
3450
+ },
3451
+ suspend: (value) => {
3452
+ expectStore(active);
3453
+ suspended = true;
3454
+ enter(parent);
3455
+ return value;
3456
+ },
3457
+ resume: (value) => {
3458
+ if (suspended) {
3459
+ expectStore(parent);
3460
+ suspended = false;
3461
+ enter(active);
3462
+ } else {
3463
+ expectStore(active);
3464
+ }
3465
+ return value;
3466
+ },
3467
+ restore: () => {
3468
+ expectStore(active);
3469
+ enter(parent);
3470
+ }
3471
+ };
3472
+ };
3473
+ const enterPreparedFunctionFromStore = (store, plan, args, omitValues) => {
3474
+ if (!store) return noopHandle2;
3475
+ if (plan.disabled) {
3476
+ noteDisabledPlan(store.recording);
3477
+ return noopHandle2;
3478
+ }
3479
+ if (store.recording.finished) {
3480
+ if (!store.recording.budgetExpired && !store.recording.evicted) return noopHandle2;
3481
+ const expired = store.recording;
3482
+ const expiredStore = { recording: expired };
3483
+ return {
3484
+ leave: (value) => value,
3485
+ fail: (error) => {
3486
+ rememberError(error, expired);
3487
+ },
3488
+ end: () => {
3489
+ },
3490
+ run: function __rasputinHandleRun__3(callback) {
3491
+ return runExactlyOnce((invoke) => storage.run(expiredStore, invoke), callback);
3492
+ },
3493
+ suspend: (value) => value,
3494
+ resume: (value) => value
3495
+ };
3496
+ }
3497
+ stats.functionCallsObserved++;
3498
+ const recording = store.recording;
3499
+ const omitCallValues = omitValues === true || plan.omitCallValues;
3500
+ const parentCallId = store.currentCallId;
3501
+ if (store.suppressCapture || plan.excluded) {
3502
+ stats.functionCallsExcluded++;
3503
+ const excludedStore = { ...store, suppressCapture: true };
3504
+ const excluded = bindStoreTransitions(excludedStore, store, recording, plan);
3505
+ excluded.enterActive();
3506
+ let ended2 = false;
3507
+ return {
3508
+ leave: (value) => value,
3509
+ fail: () => {
3510
+ },
3511
+ end: () => {
3512
+ if (ended2) return;
3513
+ ended2 = true;
3514
+ excluded.restore();
3515
+ },
3516
+ run: excluded.run,
3517
+ suspend: excluded.suspend,
3518
+ resume: excluded.resume
3519
+ };
3520
+ }
3521
+ recording.inFlightCalls++;
3522
+ const group = repeatedCallGroup(recording, plan, parentCallId);
3523
+ group.observedCalls++;
3524
+ const journal = acquireJournal(recording);
3525
+ try {
3526
+ if (group.observedCalls === 1) journal?.notePlan(plan.runtimePlanId);
3527
+ } catch {
3528
+ }
3529
+ let status = "open";
3530
+ let pendingReturn;
3531
+ let ended = false;
3532
+ const startedAtNs = process.hrtime.bigint();
3533
+ const parentStore = store;
3534
+ const uncaptured = bindStoreTransitions(parentStore, parentStore, recording, plan);
3535
+ const finishEnd = () => {
3536
+ if (ended) return;
3537
+ ended = true;
3538
+ settleInFlight(recording);
3539
+ uncaptured.restore();
3540
+ };
3541
+ const context = {
3542
+ run: uncaptured.run,
3543
+ suspend: uncaptured.suspend,
3544
+ resume: uncaptured.resume
3545
+ };
3546
+ if (group.observedCalls > maxCapturedCallsPerFunction) {
3547
+ uncaptured.enterActive();
3548
+ return {
3549
+ leave: (value) => {
3550
+ if (status !== "failed") {
3551
+ status = "left";
3552
+ pendingReturn = value;
3553
+ }
3554
+ return value;
3555
+ },
3556
+ fail: (error, liveArgs) => {
3557
+ if (status === "failed") return;
3558
+ status = "failed";
3559
+ captureCompletedThrow(
3560
+ recording,
3561
+ plan,
3562
+ liveArgs ?? args,
3563
+ parentCallId,
3564
+ startedAtNs,
3565
+ error
3566
+ );
3567
+ },
3568
+ end: () => {
3569
+ if (status !== "failed") {
3570
+ recordSuppressedCall(
3571
+ recording,
3572
+ group,
3573
+ parentCallId,
3574
+ startedAtNs,
3575
+ process.hrtime.bigint()
3576
+ );
3577
+ }
3578
+ finishEnd();
3579
+ },
3580
+ ...context
3581
+ };
3582
+ }
3583
+ const dropWithoutCapture = (onThrow) => {
3584
+ uncaptured.enterActive();
3585
+ return {
3586
+ leave: (value) => {
3587
+ if (status !== "failed") {
3588
+ status = "left";
3589
+ pendingReturn = value;
3590
+ }
3591
+ return value;
3592
+ },
3593
+ fail: (error) => {
3594
+ if (status === "failed") return;
3595
+ status = "failed";
3596
+ onThrow(error);
3597
+ },
3598
+ end: () => {
3599
+ if (status !== "failed") {
3600
+ const droppedBefore = recording.journal?.dropped ?? 0;
3601
+ recording.journal?.dropCall();
3602
+ countDroppedEvents(recording, droppedBefore);
3603
+ }
3604
+ finishEnd();
3605
+ },
3606
+ ...context
3607
+ };
3608
+ };
3609
+ if (!journal) {
3610
+ memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes);
3611
+ uncaptured.enterActive();
3612
+ return {
3613
+ leave: (value) => {
3614
+ if (status !== "failed") {
3615
+ status = "left";
3616
+ pendingReturn = value;
3617
+ }
3618
+ return value;
3619
+ },
3620
+ fail: (error) => {
3621
+ if (status === "failed") return;
3622
+ status = "failed";
3623
+ rememberError(error, recording);
3624
+ },
3625
+ end: finishEnd,
3626
+ ...context
3627
+ };
3628
+ }
3629
+ if (!journal.canStartCall()) {
3630
+ return dropWithoutCapture((error) => {
3631
+ captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs, error);
3632
+ });
3633
+ }
3634
+ if (!memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes)) {
3635
+ uncaptured.enterActive();
3636
+ return {
3637
+ leave: (value) => {
3638
+ if (status !== "failed") {
3639
+ status = "left";
3640
+ pendingReturn = value;
3641
+ }
3642
+ return value;
3643
+ },
3644
+ fail: (error) => {
3645
+ if (status === "failed") return;
3646
+ status = "failed";
3647
+ rememberError(error, recording);
3648
+ },
3649
+ end: finishEnd,
3650
+ ...context
3651
+ };
3652
+ }
3653
+ const callId = ++recording.nextCallId;
3654
+ const enterTimestampNs = process.hrtime.bigint() - recording.startedAtNs;
3655
+ const capturedArgs = omitCallValues ? mapArrayLike(args, () => rasputinOmitted()) : mapArrayLike(args, (argument) => captureValue(recording, argument));
3656
+ try {
3657
+ journal.startCall(plan.runtimePlanId, callId, parentCallId, enterTimestampNs, capturedArgs);
3658
+ } catch {
3659
+ journal.dropCall();
3660
+ return dropWithoutCapture((error) => rememberError(error, recording));
3661
+ }
3662
+ const callStore = { recording, currentCallId: callId };
3663
+ const captured = bindStoreTransitions(callStore, parentStore, recording, plan);
3664
+ captured.enterActive();
3665
+ const writeExit = (value) => {
3666
+ if (!recording.journal) return;
3667
+ const timestampNs = process.hrtime.bigint() - recording.startedAtNs;
3668
+ const durationNs = process.hrtime.bigint() - startedAtNs;
3669
+ const returnValue = omitCallValues ? rasputinOmitted() : captureValue(recording, value);
3670
+ recording.journal.finishCall(KIND_EXIT, callId, timestampNs, durationNs, returnValue);
3671
+ stats.functionCallsCaptured++;
3672
+ };
3673
+ const writeThrow = (error) => {
3674
+ if (!recording.journal) {
3675
+ rememberError(error, recording);
3676
+ return;
3677
+ }
3678
+ const capturedError = serializedError(recording, error, callId);
3679
+ recording.journal.finishCall(
3680
+ KIND_THROW,
3681
+ callId,
3682
+ process.hrtime.bigint() - recording.startedAtNs,
3683
+ process.hrtime.bigint() - startedAtNs,
3684
+ capturedError.value
3685
+ );
3686
+ stats.functionCallsCaptured++;
3687
+ capturedError.commit();
3688
+ rememberError(error, recording);
3689
+ };
3690
+ return {
3691
+ leave: (value) => {
3692
+ if (status !== "failed") {
3693
+ status = "left";
3694
+ pendingReturn = value;
3695
+ }
3696
+ return value;
3697
+ },
3698
+ fail: (error) => {
3699
+ if (status === "failed") return;
3700
+ status = "failed";
3701
+ try {
3702
+ writeThrow(error);
3703
+ } catch {
3704
+ rememberError(error, recording);
3705
+ }
3706
+ },
3707
+ end: () => {
3708
+ try {
3709
+ if (status !== "failed") writeExit(status === "left" ? pendingReturn : void 0);
3710
+ } catch {
3711
+ }
3712
+ if (ended) return;
3713
+ ended = true;
3714
+ settleInFlight(recording);
3715
+ captured.restore();
3716
+ },
3717
+ run: captured.run,
3718
+ suspend: captured.suspend,
3719
+ resume: captured.resume
3720
+ };
2447
3721
  };
2448
3722
  const runPreparedFunction = (plan, args, callback, omitValues) => {
2449
- const store = storage.getStore();
3723
+ const store = currentStore();
2450
3724
  if (store && !store.recording.finished && !store.recording.sawAutomatic) {
2451
3725
  store.recording.sawAutomatic = true;
2452
3726
  }
2453
3727
  return runPreparedFunctionFromStore(store, plan, args, callback, omitValues);
2454
3728
  };
3729
+ const isolateHandle2 = (handle) => ({
3730
+ leave: (value) => {
3731
+ try {
3732
+ return handle.leave(value);
3733
+ } catch {
3734
+ return value;
3735
+ }
3736
+ },
3737
+ fail: (error, liveArgs) => {
3738
+ try {
3739
+ handle.fail(error, liveArgs);
3740
+ } catch {
3741
+ }
3742
+ },
3743
+ end: () => {
3744
+ try {
3745
+ handle.end();
3746
+ } catch {
3747
+ }
3748
+ },
3749
+ run: function __rasputinHandleRun__3(callback) {
3750
+ return runExactlyOnce((invoke) => handle.run(invoke), callback);
3751
+ },
3752
+ suspend: (value) => {
3753
+ try {
3754
+ return handle.suspend(value);
3755
+ } catch {
3756
+ return value;
3757
+ }
3758
+ },
3759
+ resume: (value) => {
3760
+ try {
3761
+ return handle.resume(value);
3762
+ } catch {
3763
+ return value;
3764
+ }
3765
+ }
3766
+ });
3767
+ const enterPreparedFunction = (plan, args, omitValues) => {
3768
+ try {
3769
+ const store = currentStore();
3770
+ if (store && !store.recording.finished && !store.recording.sawAutomatic) {
3771
+ store.recording.sawAutomatic = true;
3772
+ }
3773
+ return isolateHandle2(enterPreparedFunctionFromStore(store, plan, args, omitValues));
3774
+ } catch {
3775
+ return noopHandle2;
3776
+ }
3777
+ };
2455
3778
  const runFunction = (input, args, callback) => {
2456
- const store = storage.getStore();
3779
+ const store = currentStore();
2457
3780
  if (store && !store.recording.finished) store.recording.sawManual = true;
2458
3781
  return runPreparedFunctionFromStore(
2459
3782
  store,
@@ -2463,7 +3786,7 @@ var createExecutionRecorder = (options) => {
2463
3786
  );
2464
3787
  };
2465
3788
  const runFunctionPlans = (plans, planIndex, args, callback, omitValues) => {
2466
- const store = storage.getStore();
3789
+ const store = currentStore();
2467
3790
  const plan = preparedPlansFor(plans)[planIndex];
2468
3791
  if (store && !store.recording.finished && !store.recording.sawAutomatic) {
2469
3792
  store.recording.sawAutomatic = true;
@@ -2474,92 +3797,132 @@ var createExecutionRecorder = (options) => {
2474
3797
  function trace(input, fn) {
2475
3798
  const definition = typeof input === "string" ? manualFunctionDefinition(input) : { ...input, functionId: runtimeFunctionId2(input) };
2476
3799
  const plan = preparePlan(definition);
2477
- return function traced(...args) {
2478
- const store = storage.getStore();
3800
+ return function __rasputinHandleRun__3(...args) {
3801
+ if (new.target) {
3802
+ throw new TypeError("execution.trace() wraps function calls, not constructors");
3803
+ }
3804
+ const receiver = this;
3805
+ const store = currentStore();
2479
3806
  if (store && !store.recording.finished) store.recording.sawManual = true;
2480
- return runPreparedFunctionFromStore(store, plan, args, () => fn.apply(this, args));
3807
+ return runPreparedFunctionFromStore(store, plan, args, function __rasputinHandleRun__4() {
3808
+ return fn.apply(receiver, args);
3809
+ });
2481
3810
  };
2482
3811
  }
2483
- const captureDerivationRoot = (rootId, value) => {
2484
- const store = storage.getStore();
2485
- if (!store || store.recording.finished || store.suppressCapture) return value;
2486
- const recording = store.recording;
2487
- if (recording.memory.mode !== "full") return value;
2488
- if (recording.derivationRoots.length >= maxEventsPerExecution) return value;
2489
- const recorderStartedAtNs = process.hrtime.bigint();
2490
- try {
2491
- const serialized = captureValue(recording, value);
2492
- if (recording.memory.mode !== "full") return value;
2493
- if (!memoryBudget.reserveStorage(recording.memory, DERIVATION_ROOT_RECORD_BYTES)) {
2494
- return value;
2495
- }
2496
- const completeness = capturedValueCompleteness(serialized);
2497
- const bytes = jsonLiteralUtf8Bytes(serialized);
2498
- recording.derivationRoots.push({
2499
- rootId,
2500
- callId: store.currentCallId ?? 0,
2501
- value: serialized,
2502
- completeness
2503
- });
2504
- recording.derivationRootBytes += bytes;
2505
- stats.derivationRootsCaptured++;
2506
- stats.derivationRootBytes += bytes;
2507
- stats.derivationFallbackExpressions++;
2508
- return value;
2509
- } finally {
2510
- addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
2511
- }
2512
- };
2513
3812
  return {
2514
3813
  createScope,
2515
- run,
2516
3814
  getErrorState,
2517
3815
  runFunction,
2518
3816
  runFunctionPlans,
2519
3817
  prepareFunctionPlans,
2520
3818
  runPreparedFunction,
3819
+ enterPreparedFunction,
2521
3820
  trace,
2522
- captureDerivationRoot,
2523
- getStats: () => {
2524
- const manifest = snapshotInstrumentationManifest();
2525
- const plans = manifest?.derivationPlans ?? [];
2526
- return {
2527
- ...stats,
2528
- ...memoryBudget.getStats(),
2529
- ...journalPool.stats(),
2530
- derivationCandidateFunctions: plans.filter((plan) => !plan.fallbackReason).length,
2531
- derivationFallbackFunctions: plans.filter((plan) => plan.fallbackReason).length,
2532
- derivationFallbackReasons: { ...stats.derivationFallbackReasons },
2533
- ...phases ? {
2534
- phaseAlsNs: Number(phases.alsNs),
2535
- phaseMaterializeNs: Number(phases.materializeNs)
2536
- } : {}
2537
- };
2538
- }
3821
+ getStats: () => ({
3822
+ ...stats,
3823
+ ...memoryBudget.getStats(),
3824
+ ...journalPool.stats(),
3825
+ ...phases ? {
3826
+ phaseAlsNs: Number(phases.alsNs),
3827
+ phaseMaterializeNs: Number(phases.materializeNs)
3828
+ } : {}
3829
+ })
2539
3830
  };
2540
3831
  };
2541
3832
 
2542
3833
  // src/execution-recorder/automatic-runtime.ts
2543
- var AUTOMATIC_RUNTIME_SYMBOL = "rasputin.execution.runtime.v2";
3834
+ var AUTOMATIC_RUNTIME_SYMBOL = "rasputin.execution.runtime.v3";
2544
3835
  var runtimeSymbol = Symbol.for(AUTOMATIC_RUNTIME_SYMBOL);
2545
- var passthroughCapture = (_rootId, value) => value;
2546
- var passthrough = (_planIndex, _args, callback) => callback();
3836
+ var passthroughHandle = () => ({
3837
+ leave: (value) => value,
3838
+ fail: () => {
3839
+ },
3840
+ end: () => {
3841
+ },
3842
+ run: function __rasputinHandleRun__3(callback) {
3843
+ return runExactlyOnce((invoke) => invoke(), callback);
3844
+ },
3845
+ suspend: (value) => value,
3846
+ resume: (value) => value
3847
+ });
3848
+ var isolateHandle = (handle) => ({
3849
+ leave: (value) => {
3850
+ try {
3851
+ return handle.leave(value);
3852
+ } catch {
3853
+ return value;
3854
+ }
3855
+ },
3856
+ fail: (error, liveArgs) => {
3857
+ try {
3858
+ handle.fail(error, liveArgs);
3859
+ } catch {
3860
+ }
3861
+ },
3862
+ end: () => {
3863
+ try {
3864
+ handle.end();
3865
+ } catch {
3866
+ }
3867
+ },
3868
+ run: function __rasputinHandleRun__3(callback) {
3869
+ return runExactlyOnce((invoke) => handle.run(invoke), callback);
3870
+ },
3871
+ suspend: (value) => {
3872
+ try {
3873
+ return handle.suspend(value);
3874
+ } catch {
3875
+ return value;
3876
+ }
3877
+ },
3878
+ resume: (value) => {
3879
+ try {
3880
+ return handle.resume(value);
3881
+ } catch {
3882
+ return value;
3883
+ }
3884
+ }
3885
+ });
3886
+ var passthroughRun = (_planIndex, _args, callback) => callback();
3887
+ var passthroughEnter = () => passthroughHandle();
2547
3888
  var bindPassthrough = (module) => {
2548
- module.cell.run = passthrough;
3889
+ module.cell.run = passthroughRun;
3890
+ module.cell.enter = passthroughEnter;
3891
+ };
3892
+ var attachRunner = (cell) => {
3893
+ const run = ((planIndex, args, callback, omitValues) => cell.run(planIndex, args, callback, omitValues));
3894
+ run.enter = (planIndex, args, omitValues) => cell.enter(planIndex, args, omitValues);
3895
+ return run;
3896
+ };
3897
+ var bindExecution = (execution, module) => {
3898
+ const prepared = execution.prepareFunctionPlans(module.plans);
3899
+ module.cell.run = (planIndex, args, callback, omitValues) => {
3900
+ const plan = prepared[planIndex];
3901
+ return plan ? execution.runPreparedFunction(plan, args, callback, omitValues) : callback();
3902
+ };
3903
+ module.cell.enter = (planIndex, args, omitValues) => {
3904
+ try {
3905
+ const plan = prepared[planIndex];
3906
+ return isolateHandle(
3907
+ plan ? execution.enterPreparedFunction(plan, args, omitValues) : passthroughEnter(planIndex, args, omitValues)
3908
+ );
3909
+ } catch {
3910
+ return passthroughHandle();
3911
+ }
3912
+ };
2549
3913
  };
2550
3914
  var isRegistry = (value) => Array.isArray(Reflect.get(value, "runtimes")) && Array.isArray(Reflect.get(value, "modules")) && typeof Reflect.get(value, "register") === "function";
2551
3915
  var registerModule = (registry, plans) => {
2552
- const cell = { run: passthrough };
3916
+ const cell = { run: passthroughRun, enter: passthroughEnter };
2553
3917
  const module = { plans, cell };
2554
3918
  registry.modules.push(module);
2555
3919
  registry.runtimes.at(-1)?.bind(module);
2556
- return (planIndex, args, callback, omitValues) => cell.run(planIndex, args, callback, omitValues);
3920
+ return attachRunner(cell);
2557
3921
  };
2558
3922
  var createRegistry = () => {
2559
3923
  const registry = {
2560
3924
  runtimes: [],
2561
3925
  modules: [],
2562
- captureRoot: passthroughCapture,
2563
3926
  register(plans) {
2564
3927
  return registerModule(registry, plans);
2565
3928
  }
@@ -2569,9 +3932,6 @@ var createRegistry = () => {
2569
3932
  var getAutomaticRuntimeRegistry = () => {
2570
3933
  const existing = Reflect.get(globalThis, runtimeSymbol);
2571
3934
  if (existing && typeof existing === "object" && isRegistry(existing)) {
2572
- if (typeof existing.captureRoot !== "function") {
2573
- existing.captureRoot = passthroughCapture;
2574
- }
2575
3935
  return existing;
2576
3936
  }
2577
3937
  const registry = createRegistry();
@@ -2582,22 +3942,15 @@ var installAutomaticExecutionRuntime = (execution) => {
2582
3942
  const registry = getAutomaticRuntimeRegistry();
2583
3943
  const runtime = {
2584
3944
  bind(module) {
2585
- const prepared = execution.prepareFunctionPlans(module.plans);
2586
- module.cell.run = (planIndex, args, callback, omitValues) => {
2587
- const plan = prepared[planIndex];
2588
- return plan ? execution.runPreparedFunction(plan, args, callback, omitValues) : callback();
2589
- };
2590
- },
2591
- captureRoot: (rootId, value) => execution.captureDerivationRoot(rootId, value)
3945
+ bindExecution(execution, module);
3946
+ }
2592
3947
  };
2593
3948
  registry.runtimes.push(runtime);
2594
- registry.captureRoot = runtime.captureRoot;
2595
3949
  for (const module of registry.modules) runtime.bind(module);
2596
3950
  return () => {
2597
3951
  const index = registry.runtimes.lastIndexOf(runtime);
2598
3952
  if (index >= 0) registry.runtimes.splice(index, 1);
2599
3953
  const current = registry.runtimes.at(-1);
2600
- registry.captureRoot = current?.captureRoot ?? passthroughCapture;
2601
3954
  for (const module of registry.modules) {
2602
3955
  if (current) current.bind(module);
2603
3956
  else bindPassthrough(module);
@@ -2606,117 +3959,234 @@ var installAutomaticExecutionRuntime = (execution) => {
2606
3959
  };
2607
3960
 
2608
3961
  // src/install-global-handlers.ts
3962
+ var RASPUTIN_PROCESS_LISTENER = Symbol.for("rasputin.process.listener.v1");
3963
+ var unhandledRejectionMode = () => {
3964
+ const tokens = [
3965
+ ...process.execArgv,
3966
+ ...(process.env.NODE_OPTIONS?.match(/(?:[^\s"]+|"[^"]*")+/g) ?? []).map(
3967
+ (token) => token.replace(/^"|"$/g, "")
3968
+ )
3969
+ ];
3970
+ for (let index = tokens.length - 1; index >= 0; index--) {
3971
+ const token = tokens[index];
3972
+ if (!token) continue;
3973
+ if (token.startsWith("--unhandled-rejections="))
3974
+ return token.slice("--unhandled-rejections=".length);
3975
+ if (token === "--unhandled-rejections") return tokens[index + 1] ?? "";
3976
+ }
3977
+ return "throw";
3978
+ };
3979
+ var isBun = typeof process.versions.bun === "string";
3980
+ var unhandledRejectionIsFatal = () => {
3981
+ const mode = unhandledRejectionMode();
3982
+ return mode === "throw" || mode === "strict";
3983
+ };
3984
+ var printDiagnostic = (error) => {
3985
+ if (error instanceof Error) {
3986
+ console.error(error.stack ?? `${error.name}: ${error.message}`);
3987
+ return;
3988
+ }
3989
+ console.error(error);
3990
+ };
2609
3991
  var removeProcessListener = process.off.bind(process);
2610
- var installGlobalHandlers = (client, options = {}) => {
2611
- const exitOnUncaught = options.exitOnUncaughtException ?? true;
2612
- const flushTimeoutMs = options.flushTimeoutMs ?? 2e3;
2613
- let handlingUncaught = false;
2614
- const onUnhandledRejection = (reason) => {
3992
+ var tagListener = (listener) => {
3993
+ Object.defineProperty(listener, RASPUTIN_PROCESS_LISTENER, { value: true });
3994
+ return listener;
3995
+ };
3996
+ var hostListenerCount = (event) => {
3997
+ const listeners = event === "uncaughtException" ? process.listeners("uncaughtException") : process.listeners("unhandledRejection");
3998
+ return listeners.filter((listener) => !(RASPUTIN_PROCESS_LISTENER in listener)).length;
3999
+ };
4000
+ var registered = [];
4001
+ var uninstallProcess;
4002
+ var handlingUncaught = false;
4003
+ var captureOnAll = (error) => {
4004
+ for (const entry of registered) {
2615
4005
  try {
2616
- client.captureException(reason);
4006
+ entry.client.captureException(error);
2617
4007
  } catch {
2618
4008
  }
2619
- };
2620
- const onUncaughtException = (error) => {
4009
+ }
4010
+ };
4011
+ var flushAll = async (timeoutMs) => {
4012
+ await Promise.all(
4013
+ registered.map(
4014
+ (entry) => entry.client.flush(timeoutMs).catch(() => {
4015
+ })
4016
+ )
4017
+ );
4018
+ };
4019
+ var installSharedListeners = () => {
4020
+ if (uninstallProcess) return;
4021
+ const onUnhandledRejection = tagListener((reason) => {
4022
+ captureOnAll(reason);
4023
+ if (hostListenerCount("unhandledRejection") > 0) return;
4024
+ const mode = unhandledRejectionMode();
4025
+ if (mode !== "none") printDiagnostic(reason);
4026
+ if (mode === "warn-with-error-code") process.exitCode = 1;
4027
+ });
4028
+ const onUncaughtException = tagListener((error, origin) => {
4029
+ const exitOnUncaught = registered.some((entry) => entry.exitOnUncaught);
4030
+ const flushTimeoutMs = registered.reduce(
4031
+ (max, entry) => Math.max(max, entry.flushTimeoutMs),
4032
+ 2e3
4033
+ );
2621
4034
  if (handlingUncaught) {
2622
- process.exit(1);
4035
+ if (exitOnUncaught && hostListenerCount("uncaughtException") === 0) {
4036
+ process.exit(1);
4037
+ }
2623
4038
  return;
2624
4039
  }
2625
4040
  handlingUncaught = true;
2626
- try {
2627
- client.captureException(error);
2628
- } catch {
2629
- }
2630
- const soleListener = process.listenerCount("uncaughtException") <= 1;
4041
+ captureOnAll(error);
4042
+ const hostOwns = hostListenerCount("uncaughtException") > 0;
4043
+ const shouldExit = exitOnUncaught && !hostOwns && !(isBun && origin === "unhandledRejection");
4044
+ if (!hostOwns) printDiagnostic(error);
4045
+ if (shouldExit) process.exitCode = 1;
2631
4046
  const shutdown = async () => {
2632
4047
  try {
2633
- await client.flush(flushTimeoutMs);
4048
+ await flushAll(flushTimeoutMs);
2634
4049
  } catch {
2635
4050
  }
2636
- if (exitOnUncaught && soleListener) process.exit(1);
4051
+ if (shouldExit) {
4052
+ process.exit(1);
4053
+ return;
4054
+ }
4055
+ handlingUncaught = false;
2637
4056
  };
4057
+ if (shouldExit) {
4058
+ const watchdog = setTimeout(() => process.exit(1), flushTimeoutMs + 50);
4059
+ void shutdown().finally(() => clearTimeout(watchdog));
4060
+ return;
4061
+ }
2638
4062
  void shutdown();
2639
- };
4063
+ });
2640
4064
  try {
2641
4065
  process.on("uncaughtException", onUncaughtException);
2642
- process.on("unhandledRejection", onUnhandledRejection);
4066
+ if (!unhandledRejectionIsFatal()) {
4067
+ process.on("unhandledRejection", onUnhandledRejection);
4068
+ }
2643
4069
  } catch {
2644
- return () => {
2645
- };
4070
+ return;
2646
4071
  }
2647
- return () => {
4072
+ uninstallProcess = () => {
2648
4073
  try {
2649
4074
  removeProcessListener("uncaughtException", onUncaughtException);
2650
4075
  removeProcessListener("unhandledRejection", onUnhandledRejection);
2651
4076
  } catch {
2652
4077
  }
4078
+ uninstallProcess = void 0;
4079
+ handlingUncaught = false;
4080
+ };
4081
+ };
4082
+ var installGlobalHandlers = (client, options = {}) => {
4083
+ const entry = {
4084
+ client,
4085
+ exitOnUncaught: options.exitOnUncaughtException ?? true,
4086
+ flushTimeoutMs: options.flushTimeoutMs ?? 2e3
4087
+ };
4088
+ registered.push(entry);
4089
+ installSharedListeners();
4090
+ return () => {
4091
+ const index = registered.indexOf(entry);
4092
+ if (index >= 0) registered.splice(index, 1);
4093
+ if (registered.length === 0) uninstallProcess?.();
2653
4094
  };
2654
4095
  };
2655
-
2656
- // src/rasputin-init.ts
2657
- import { join } from "node:path";
2658
- import {
2659
- createClient,
2660
- isClientEnabled
2661
- } from "@rasputin-ai/core";
2662
4096
 
2663
4097
  // src/sdk-meta.ts
2664
4098
  var SDK_NAME = "@rasputin-ai/node";
2665
- var SDK_VERSION = "0.5.0-alpha.13";
4099
+ var SDK_VERSION = "0.5.0-alpha.14";
2666
4100
 
2667
4101
  // src/rasputin-init.ts
2668
- var withExecution = (client, execution, installRuntime, manifest) => {
2669
- const uninstallRuntime = installRuntime ? installAutomaticExecutionRuntime(execution) : () => {
4102
+ var publicExecution = (runtime) => ({
4103
+ createScope: (metadata) => {
4104
+ const scope = runtime.createScope(metadata);
4105
+ return {
4106
+ run: scope.run,
4107
+ associateError: scope.associateError,
4108
+ finish: scope.finish
4109
+ };
4110
+ },
4111
+ trace: runtime.trace,
4112
+ getStats: runtime.getStats
4113
+ });
4114
+ var withExecution = (client, runtime, installRuntime, manifest, uninstallHandlers = () => {
4115
+ }) => {
4116
+ const uninstallRuntime = installRuntime ? installAutomaticExecutionRuntime(runtime) : () => {
2670
4117
  };
2671
4118
  const manifestUpload = scheduleInstrumentationManifestUpload(manifest);
4119
+ const execution = publicExecution(runtime);
2672
4120
  return {
2673
4121
  ...client,
2674
4122
  execution,
2675
4123
  getStats: () => ({ ...client.getStats(), recorder: execution.getStats() }),
2676
4124
  verifyConfiguration: manifestUpload.verify,
2677
4125
  captureException: (error, context) => {
2678
- const runtimeState = context?.runtimeState ?? execution.getErrorState(
2679
- error,
2680
- context?.request ? { kind: "http", request: context.request } : void 0
2681
- );
2682
- const result = client.captureException(error, { ...context, runtimeState });
4126
+ const result = client.captureException(error, context);
2683
4127
  manifestUpload.flushSoon();
2684
4128
  return result;
2685
4129
  },
2686
4130
  flush: async (timeoutMs) => {
4131
+ const startedAt = Date.now();
2687
4132
  await client.flush(timeoutMs);
2688
- await manifestUpload.wait();
4133
+ if (timeoutMs === void 0) {
4134
+ await manifestUpload.wait();
4135
+ return;
4136
+ }
4137
+ await manifestUpload.wait(Math.max(0, timeoutMs - (Date.now() - startedAt)));
2689
4138
  },
2690
4139
  close: async () => {
4140
+ uninstallHandlers();
2691
4141
  uninstallRuntime();
2692
4142
  manifestUpload.disconnect();
4143
+ const startedAt = Date.now();
2693
4144
  await client.close();
2694
- await manifestUpload.wait();
4145
+ await manifestUpload.wait(Math.max(0, 2e3 - (Date.now() - startedAt)));
2695
4146
  }
2696
4147
  };
2697
4148
  };
2698
4149
  var RasputinInit = (options) => {
2699
4150
  try {
2700
- const client = createClient(options, { sdkVersion: SDK_VERSION, sdkName: SDK_NAME });
2701
- const recorderEnabled = isClientEnabled(options) && options.executionRecorder?.enabled !== false;
2702
- const execution = createExecutionRecorder({
4151
+ const enabled = isClientEnabled(options);
4152
+ const recorderEnabled = enabled && options.executionRecorder?.enabled !== false;
4153
+ const runtime = createExecutionRecorder({
2703
4154
  ...options.executionRecorder,
2704
4155
  enabled: recorderEnabled
2705
4156
  });
2706
- loadInstrumentationManifestIfPresent(
2707
- options.instrumentationManifestPath ?? process.env.RASPUTIN_INSTRUMENTATION_MANIFEST ?? join(process.cwd(), ".rasputin", "instrumentation-manifest.json")
2708
- );
2709
- const wrappedClient = withExecution(client, execution, recorderEnabled, {
2710
- projectApiKey: options.projectApiKey,
2711
- release: options.release,
2712
- apiUrl: options.apiUrl,
2713
- enabled: isClientEnabled(options),
2714
- sourceRoot: options.sourceRoot,
2715
- sourceRoots: options.sourceRoots,
2716
- logSuccess: options.logSuccess
4157
+ const client = createClient(options, {
4158
+ sdkVersion: SDK_VERSION,
4159
+ sdkName: SDK_NAME,
4160
+ installTransportSignalHandlers: options.installTransportSignalHandlers,
4161
+ resolveRuntimeState: (error, context) => runtime.getErrorState(
4162
+ error,
4163
+ context?.request ? { kind: "http", request: context.request } : void 0
4164
+ )
2717
4165
  });
2718
- if (isClientEnabled(options)) {
2719
- installGlobalHandlers(wrappedClient);
4166
+ if (enabled) {
4167
+ loadInstrumentationManifestIfPresent(
4168
+ options.instrumentationManifestPath ?? process.env.RASPUTIN_INSTRUMENTATION_MANIFEST ?? join(process.cwd(), ".rasputin", "instrumentation-manifest.json")
4169
+ );
4170
+ }
4171
+ let uninstallHandlers = () => {
4172
+ };
4173
+ const wrappedClient = withExecution(
4174
+ client,
4175
+ runtime,
4176
+ recorderEnabled,
4177
+ {
4178
+ projectApiKey: options.projectApiKey ?? "",
4179
+ release: options.release,
4180
+ apiUrl: options.apiUrl,
4181
+ enabled,
4182
+ sourceRoot: options.sourceRoot,
4183
+ sourceRoots: options.sourceRoots,
4184
+ logSuccess: options.logSuccess
4185
+ },
4186
+ () => uninstallHandlers()
4187
+ );
4188
+ if (enabled && options.installGlobalHandlers !== false) {
4189
+ uninstallHandlers = installGlobalHandlers(wrappedClient);
2720
4190
  }
2721
4191
  return wrappedClient;
2722
4192
  } catch {
@@ -2725,7 +4195,7 @@ var RasputinInit = (options) => {
2725
4195
  createExecutionRecorder({ enabled: false }),
2726
4196
  false,
2727
4197
  {
2728
- projectApiKey: options.projectApiKey,
4198
+ projectApiKey: options.projectApiKey ?? "",
2729
4199
  release: options.release,
2730
4200
  apiUrl: options.apiUrl,
2731
4201
  enabled: false,
@@ -2737,9 +4207,5 @@ var RasputinInit = (options) => {
2737
4207
  }
2738
4208
  };
2739
4209
  export {
2740
- RasputinInit,
2741
- createExecutionRecorder,
2742
- installAutomaticExecutionRuntime,
2743
- installGlobalHandlers,
2744
- scheduleInstrumentationManifestUpload
4210
+ RasputinInit
2745
4211
  };