brass-runtime 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +287 -23
  3. package/dist/agent/cli/main.cjs +38 -38
  4. package/dist/agent/cli/main.js +6 -6
  5. package/dist/agent/cli/main.mjs +6 -6
  6. package/dist/agent/index.cjs +7 -7
  7. package/dist/agent/index.d.ts +1 -1
  8. package/dist/agent/index.js +6 -6
  9. package/dist/agent/index.mjs +6 -6
  10. package/dist/chunk-2HQTDLHF.mjs +683 -0
  11. package/dist/chunk-36I3M4UC.mjs +370 -0
  12. package/dist/{chunk-QY5FKYEQ.js → chunk-3AYM6WPJ.js} +570 -51
  13. package/dist/chunk-3LOYJFRR.cjs +300 -0
  14. package/dist/chunk-3Y2RIUMM.js +300 -0
  15. package/dist/{chunk-7XOPAB5Q.js → chunk-4P2HHGAX.mjs} +83 -5
  16. package/dist/{chunk-N6VHMOWB.cjs → chunk-4ROBZFL6.cjs} +128 -128
  17. package/dist/{chunk-NC5SDRYE.js → chunk-52OB2ROS.js} +4 -4
  18. package/dist/{chunk-JX3LZQJH.cjs → chunk-52PPNNI4.cjs} +82 -20
  19. package/dist/{chunk-5YOQOXEQ.cjs → chunk-5EC274J5.cjs} +676 -293
  20. package/dist/chunk-5QC7LRZ3.js +229 -0
  21. package/dist/{chunk-7TL2LHQJ.js → chunk-5VRJNBLZ.mjs} +524 -141
  22. package/dist/chunk-62AZW6UT.cjs +313 -0
  23. package/dist/chunk-6IXXWIUM.js +683 -0
  24. package/dist/chunk-6RY2FFN4.mjs +2024 -0
  25. package/dist/chunk-74ZTY6CP.js +2871 -0
  26. package/dist/chunk-7CMJS3QE.mjs +2871 -0
  27. package/dist/{chunk-2WC63LJK.mjs → chunk-7JIJOVCT.js} +20 -10
  28. package/dist/chunk-7X3K5RMS.js +2024 -0
  29. package/dist/chunk-7ZPEZ57L.cjs +2024 -0
  30. package/dist/{chunk-FM4W4QPL.js → chunk-A2OM6NEH.mjs} +5 -4
  31. package/dist/chunk-AGR5B2BC.cjs +683 -0
  32. package/dist/chunk-B33ICAKP.js +313 -0
  33. package/dist/{chunk-J3H54ZRV.mjs → chunk-B5JD23U7.mjs} +1 -1
  34. package/dist/{chunk-F5EUMJL7.mjs → chunk-BKK77SBA.js} +83 -5
  35. package/dist/{chunk-U5KWK3PX.mjs → chunk-C3MDXTRZ.js} +11 -0
  36. package/dist/{chunk-SPUEME2B.cjs → chunk-CZIVE6NT.cjs} +12 -1
  37. package/dist/{chunk-TDVMADDN.js → chunk-DNFJLJMW.mjs} +11 -0
  38. package/dist/{chunk-XDZOO4L5.js → chunk-EJ6BPYVR.mjs} +79 -17
  39. package/dist/chunk-EOC4UHBS.mjs +229 -0
  40. package/dist/chunk-F6XWZQY4.cjs +777 -0
  41. package/dist/{chunk-7LVI2GIN.js → chunk-FH2X7BVP.js} +507 -72
  42. package/dist/{chunk-OOGJ73B6.js → chunk-FHQGHPMO.mjs} +20 -10
  43. package/dist/{chunk-WQ5QNU5R.cjs → chunk-GLE2WY7Z.cjs} +652 -217
  44. package/dist/{chunk-G6IQOE4P.mjs → chunk-GYM3LLGS.mjs} +507 -72
  45. package/dist/{chunk-TVN5I4U6.cjs → chunk-JF5WGYJJ.cjs} +25 -24
  46. package/dist/{chunk-CY33PGEX.mjs → chunk-KH4SYAOS.mjs} +570 -51
  47. package/dist/chunk-KN32XNTH.mjs +313 -0
  48. package/dist/chunk-KQLYONSE.cjs +2871 -0
  49. package/dist/{chunk-7HUOJA4W.cjs → chunk-KZJQ723N.cjs} +90 -80
  50. package/dist/{chunk-CCKHV5BT.mjs → chunk-L2SYFEBS.js} +5 -4
  51. package/dist/{chunk-IJT6RRQ5.cjs → chunk-L6VB5N7Q.cjs} +20 -9
  52. package/dist/{chunk-ZGLD4TVZ.mjs → chunk-MBEJI5HF.mjs} +4 -4
  53. package/dist/{chunk-PRWCB3QL.mjs → chunk-MIIYDLGM.js} +524 -141
  54. package/dist/{chunk-H55LI6WY.js → chunk-MOO4L7F4.mjs} +15 -4
  55. package/dist/chunk-MVGUEJ5Z.cjs +370 -0
  56. package/dist/chunk-PD4EJTQC.cjs +229 -0
  57. package/dist/chunk-PWC3RBQE.mjs +300 -0
  58. package/dist/{chunk-MWXMNYJS.cjs → chunk-Q2I37RP3.cjs} +643 -124
  59. package/dist/{chunk-VFIUZG7J.mjs → chunk-RKGKFN2A.js} +79 -17
  60. package/dist/{chunk-NYL4D7SK.cjs → chunk-SA6HUJVI.cjs} +5 -5
  61. package/dist/chunk-SK7UZRNI.mjs +777 -0
  62. package/dist/{chunk-K2T3DV26.mjs → chunk-TRM4JUZQ.js} +15 -4
  63. package/dist/chunk-UB4B6OFY.js +370 -0
  64. package/dist/{chunk-G3XGCZDQ.js → chunk-UCUBNWM2.js} +1 -1
  65. package/dist/chunk-VWIPB6I5.js +777 -0
  66. package/dist/{chunk-JNFRRJYH.cjs → chunk-WBGRHGBP.cjs} +270 -192
  67. package/dist/{client-CtFmoDvM.d.ts → client-CZHU674n.d.ts} +211 -36
  68. package/dist/core/index.cjs +135 -9
  69. package/dist/core/index.d.ts +238 -33
  70. package/dist/core/index.js +155 -29
  71. package/dist/core/index.mjs +155 -29
  72. package/dist/{effect-CGNl5Rqp.d.ts → effect-DIUHZ9IN.d.ts} +89 -1
  73. package/dist/effectRunner-CFLC32IK.cjs +8 -0
  74. package/dist/{effectRunner-A4CHJXJI.js → effectRunner-L4S7IPT3.js} +2 -2
  75. package/dist/{effectRunner-OPUF6QRN.mjs → effectRunner-NNGG75QA.mjs} +2 -2
  76. package/dist/http/index.cjs +324 -2986
  77. package/dist/http/index.d.ts +54 -68
  78. package/dist/http/index.js +238 -2900
  79. package/dist/http/index.mjs +238 -2900
  80. package/dist/http/testing.cjs +14 -12
  81. package/dist/http/testing.d.ts +5 -4
  82. package/dist/http/testing.js +10 -8
  83. package/dist/http/testing.mjs +10 -8
  84. package/dist/index.cjs +423 -255
  85. package/dist/index.d.ts +87 -69
  86. package/dist/index.js +301 -133
  87. package/dist/index.mjs +301 -133
  88. package/dist/observability/index.cjs +18 -531
  89. package/dist/observability/index.d.ts +81 -8
  90. package/dist/observability/index.js +25 -538
  91. package/dist/observability/index.mjs +25 -538
  92. package/dist/perf/cli.cjs +401 -0
  93. package/dist/perf/cli.d.ts +1 -0
  94. package/dist/perf/cli.js +401 -0
  95. package/dist/perf/cli.mjs +401 -0
  96. package/dist/perf/index.cjs +141 -0
  97. package/dist/perf/index.d.ts +483 -0
  98. package/dist/perf/index.js +141 -0
  99. package/dist/perf/index.mjs +141 -0
  100. package/dist/schedule-CK3Ml_7p.d.ts +259 -0
  101. package/dist/schema/index.cjs +6 -2
  102. package/dist/schema/index.d.ts +3 -1
  103. package/dist/schema/index.js +5 -1
  104. package/dist/schema/index.mjs +5 -1
  105. package/dist/{server-C8hDXA74.d.ts → server-D6JZ15_e.d.ts} +16 -4
  106. package/dist/{stream-dvSs0QS5.d.ts → stream-B4oK9JFP.d.ts} +1 -1
  107. package/dist/{tracer-B5tRH9H7.d.ts → tracer-Hwt1cl7h.d.ts} +13 -54
  108. package/dist/{tracing-Dt9S_6V8.d.ts → tracing-DqbTKGcf.d.ts} +1 -1
  109. package/docs/ARCHITECTURE.md +292 -0
  110. package/docs/README.md +65 -0
  111. package/docs/adr/0001-ai-context-pack.md +32 -0
  112. package/docs/agent-apply-mode.md +104 -0
  113. package/docs/agent-approvals.md +110 -0
  114. package/docs/agent-batch.md +185 -0
  115. package/docs/agent-boundaries.md +112 -0
  116. package/docs/agent-chat-sessions.md +160 -0
  117. package/docs/agent-ci.md +17 -0
  118. package/docs/agent-cli.md +405 -0
  119. package/docs/agent-config.md +480 -0
  120. package/docs/agent-context-discovery.md +159 -0
  121. package/docs/agent-copilot-like-dx.md +126 -0
  122. package/docs/agent-declarative-optimized-planning.md +138 -0
  123. package/docs/agent-dx.md +224 -0
  124. package/docs/agent-env-files.md +126 -0
  125. package/docs/agent-follow-up-context.md +43 -0
  126. package/docs/agent-global-usage.md +180 -0
  127. package/docs/agent-init.md +109 -0
  128. package/docs/agent-install-and-configure.md +516 -0
  129. package/docs/agent-language-workspace-ux.md +99 -0
  130. package/docs/agent-llm-adapters.md +123 -0
  131. package/docs/agent-local-install.md +190 -0
  132. package/docs/agent-local-tests.md +51 -0
  133. package/docs/agent-observability.md +155 -0
  134. package/docs/agent-patch-quality-loop.md +162 -0
  135. package/docs/agent-presets.md +22 -0
  136. package/docs/agent-project-commands.md +237 -0
  137. package/docs/agent-project-intelligence.md +156 -0
  138. package/docs/agent-redaction.md +18 -0
  139. package/docs/agent-release-readiness.md +76 -0
  140. package/docs/agent-rollback-safety.md +162 -0
  141. package/docs/agent-rollback.md +23 -0
  142. package/docs/agent-run-artifacts.md +16 -0
  143. package/docs/agent-vscode-auto-discovery.md +137 -0
  144. package/docs/agent-vscode-batch-runner.md +100 -0
  145. package/docs/agent-vscode-chat-layout.md +90 -0
  146. package/docs/agent-vscode-clean-install.md +147 -0
  147. package/docs/agent-vscode-code-actions.md +70 -0
  148. package/docs/agent-vscode-diff-preview.md +45 -0
  149. package/docs/agent-vscode-inline-assist.md +56 -0
  150. package/docs/agent-vscode-install.md +186 -0
  151. package/docs/agent-vscode-model-setup.md +97 -0
  152. package/docs/agent-vscode-patch-preview.md +92 -0
  153. package/docs/agent-vscode-problems.md +79 -0
  154. package/docs/agent-vscode-project-dashboard.md +106 -0
  155. package/docs/agent-vscode-run-history.md +92 -0
  156. package/docs/agent-vscode-ux.md +73 -0
  157. package/docs/ai/INVARIANTS.md +84 -0
  158. package/docs/ai/PROJECT_MAP.md +338 -0
  159. package/docs/ai/PUBLIC_API.md +339 -0
  160. package/docs/ai/VALIDATION_MATRIX.md +67 -0
  161. package/docs/api-polish.md +37 -0
  162. package/docs/cancellation.md +162 -0
  163. package/docs/coverage.md +46 -0
  164. package/docs/framework-integrations.md +38 -0
  165. package/docs/frameworks/angular.md +153 -0
  166. package/docs/frameworks/express.md +125 -0
  167. package/docs/frameworks/fastify.md +124 -0
  168. package/docs/frameworks/nestjs.md +282 -0
  169. package/docs/frameworks/nextjs.md +147 -0
  170. package/docs/frameworks/react.md +139 -0
  171. package/docs/frameworks/vanilla.md +224 -0
  172. package/docs/getting-started.md +159 -0
  173. package/docs/guides/README.md +40 -0
  174. package/docs/guides/circuit-breaker.md +89 -0
  175. package/docs/guides/error-handling.md +91 -0
  176. package/docs/guides/getting-started.md +107 -0
  177. package/docs/guides/layers.md +189 -0
  178. package/docs/guides/metrics.md +101 -0
  179. package/docs/guides/resource-management.md +141 -0
  180. package/docs/guides/retry.md +215 -0
  181. package/docs/guides/semaphore.md +66 -0
  182. package/docs/guides/streams.md +117 -0
  183. package/docs/guides/supervisors.md +98 -0
  184. package/docs/guides/testing.md +162 -0
  185. package/docs/guides/tracing.md +71 -0
  186. package/docs/http-recipes.md +399 -0
  187. package/docs/http.md +749 -0
  188. package/docs/modules.md +285 -0
  189. package/docs/nestjs.md +6 -0
  190. package/docs/observability-collector-smoke.md +31 -0
  191. package/docs/observability-framework-examples.md +110 -0
  192. package/docs/observability.md +649 -0
  193. package/docs/otel-collector-smoke.yaml +27 -0
  194. package/docs/performance-profiler.md +199 -0
  195. package/docs/production-readiness.md +73 -0
  196. package/docs/recipes/README.md +12 -0
  197. package/docs/recipes/http-server.md +45 -0
  198. package/docs/recipes/layers.md +44 -0
  199. package/docs/recipes/performance.md +47 -0
  200. package/docs/recipes/runtime.md +41 -0
  201. package/docs/recipes/testing.md +41 -0
  202. package/docs/release.md +53 -0
  203. package/docs/wasm-bounded-queues.md +44 -0
  204. package/docs/wasm-engine-observability-benchmarks.md +85 -0
  205. package/docs/wasm-fiber-engine.md +117 -0
  206. package/docs/wasm-scheduler-state-machine.md +122 -0
  207. package/docs/wasm-stream-chunks.md +54 -0
  208. package/package.json +22 -2
  209. package/dist/chunk-45F7OKGT.cjs +0 -104
  210. package/dist/chunk-7V4KY4RL.mjs +0 -104
  211. package/dist/chunk-DJQ7OMMB.cjs +0 -144
  212. package/dist/chunk-GOV47PPB.mjs +0 -552
  213. package/dist/chunk-JF4XXPZ5.cjs +0 -552
  214. package/dist/chunk-KCPT2D6G.js +0 -552
  215. package/dist/chunk-NOYZIMUJ.mjs +0 -144
  216. package/dist/chunk-PNVFW245.js +0 -144
  217. package/dist/chunk-ROJC3NBJ.js +0 -104
  218. package/dist/effectRunner-3ZHAD3LE.cjs +0 -8
  219. package/dist/schedule-Fque9Abz.d.ts +0 -70
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  makeBoundedRingBuffer
3
- } from "./chunk-7LVI2GIN.js";
3
+ } from "./chunk-GYM3LLGS.mjs";
4
+ import {
5
+ Cause
6
+ } from "./chunk-36I3M4UC.mjs";
4
7
 
5
8
  // src/core/runtime/metrics.ts
6
9
  var DEFAULT_BOUNDARIES = [1, 5, 10, 25, 50, 100, 250, 500, 1e3, 5e3, 1e4];
@@ -212,6 +215,10 @@ var InMemoryTracer = class {
212
215
  options;
213
216
  spans = /* @__PURE__ */ new Map();
214
217
  // key: spanId
218
+ finishedSpanIds = [];
219
+ finishedSpanSet = /* @__PURE__ */ new Set();
220
+ finishedSpanOffset = 0;
221
+ finishedSpanCount = 0;
215
222
  prunedFinishedSpans = 0;
216
223
  emit(ev, ctx) {
217
224
  if (ctx.sampled === false) return;
@@ -237,8 +244,10 @@ var InMemoryTracer = class {
237
244
  if (!spanId) return;
238
245
  const sp = this.spans.get(spanId);
239
246
  if (sp) {
247
+ const wasOpen = sp.endWallTs == null;
240
248
  sp.endWallTs = wallTs;
241
249
  sp.events.push({ wallTs, name: "fiber.end", attrs: this.attrs({ status: ev.status, error: this.error(ev.error) }) });
250
+ if (wasOpen) this.markFinished(spanId);
242
251
  this.pruneFinished();
243
252
  }
244
253
  return;
@@ -269,13 +278,15 @@ var InMemoryTracer = class {
269
278
  if (!spanId) return;
270
279
  const sp = this.spans.get(spanId);
271
280
  if (sp) {
281
+ const wasOpen = sp.endWallTs == null;
272
282
  sp.endWallTs = wallTs;
273
283
  sp.events.push({ wallTs, name: "span.end", attrs: this.attrs({ status: ev.status, error: this.error(ev.error), ...ev.attributes ?? {} }) });
284
+ if (wasOpen) this.markFinished(spanId);
274
285
  this.pruneFinished();
275
286
  }
276
287
  return;
277
288
  }
278
- if (ev.type === "fiber.suspend" || ev.type === "fiber.resume" || ev.type === "scope.open" || ev.type === "scope.close") {
289
+ if (ev.type === "fiber.suspend" || ev.type === "fiber.resume" || ev.type === "scope.open" || ev.type === "scope.close" || ev.type === "schedule.decision") {
279
290
  if (!spanId) return;
280
291
  const sp = this.spans.get(spanId);
281
292
  if (!sp) return;
@@ -284,15 +295,20 @@ var InMemoryTracer = class {
284
295
  }
285
296
  exportFinished() {
286
297
  this.pruneFinished();
287
- return Array.from(this.spans.values()).filter((s) => s.endWallTs != null);
298
+ const out = [];
299
+ for (let i = this.finishedSpanOffset; i < this.finishedSpanIds.length; i++) {
300
+ const spanId = this.finishedSpanIds[i];
301
+ if (!this.finishedSpanSet.has(spanId)) continue;
302
+ const span = this.spans.get(spanId);
303
+ if (span?.endWallTs != null) out.push(span);
304
+ }
305
+ return out;
288
306
  }
289
307
  pruneFinished(spanIds) {
290
308
  let dropped = 0;
291
309
  if (spanIds) {
292
310
  for (const spanId of spanIds) {
293
- const span = this.spans.get(spanId);
294
- if (span?.endWallTs == null) continue;
295
- if (this.spans.delete(spanId)) dropped++;
311
+ if (this.deleteFinished(spanId)) dropped++;
296
312
  }
297
313
  this.prunedFinishedSpans += dropped;
298
314
  return dropped;
@@ -305,7 +321,7 @@ var InMemoryTracer = class {
305
321
  stats() {
306
322
  return {
307
323
  storedSpans: this.spans.size,
308
- finishedSpans: Array.from(this.spans.values()).filter((s) => s.endWallTs != null).length,
324
+ finishedSpans: this.finishedSpanCount,
309
325
  prunedFinishedSpans: this.prunedFinishedSpans
310
326
  };
311
327
  }
@@ -313,7 +329,8 @@ var InMemoryTracer = class {
313
329
  return this.options.sanitizeAttributes?.(attrs) ?? attrs;
314
330
  }
315
331
  error(error) {
316
- return error === void 0 ? void 0 : this.options.sanitizeError?.(error) ?? error;
332
+ const normalized = Cause.isCause(error) ? Cause.pretty(error, { singleLine: true }) : error;
333
+ return normalized === void 0 ? void 0 : this.options.sanitizeError?.(normalized) ?? normalized;
317
334
  }
318
335
  now() {
319
336
  return this.options.clock?.() ?? Date.now();
@@ -323,25 +340,70 @@ var InMemoryTracer = class {
323
340
  if (maxAgeMs === void 0 || maxAgeMs <= 0) return 0;
324
341
  const now = this.now();
325
342
  let dropped = 0;
326
- for (const [spanId, span] of this.spans) {
327
- if (span.endWallTs == null) continue;
328
- if (now - span.endWallTs > maxAgeMs && this.spans.delete(spanId)) dropped++;
343
+ while (true) {
344
+ const oldest = this.peekOldestFinished();
345
+ if (!oldest) break;
346
+ if (now - (oldest.span.endWallTs ?? now) <= maxAgeMs) break;
347
+ if (this.deleteOldestFinished()) dropped++;
329
348
  }
330
349
  return dropped;
331
350
  }
332
351
  pruneFinishedOverLimit() {
333
352
  const maxFinishedSpans = this.options.maxFinishedSpans;
334
353
  if (maxFinishedSpans === void 0 || maxFinishedSpans < 0) return 0;
335
- const finished = Array.from(this.spans.values()).filter((span) => span.endWallTs != null).sort((a, b) => (a.endWallTs ?? 0) - (b.endWallTs ?? 0));
336
- const overflow = finished.length - maxFinishedSpans;
337
- if (overflow <= 0) return 0;
338
354
  let dropped = 0;
339
- for (let i = 0; i < overflow; i++) {
340
- const span = finished[i];
341
- if (this.spans.delete(span.spanId)) dropped++;
355
+ while (this.finishedSpanCount > maxFinishedSpans) {
356
+ if (this.deleteOldestFinished()) dropped++;
357
+ else break;
342
358
  }
343
359
  return dropped;
344
360
  }
361
+ markFinished(spanId) {
362
+ if (this.finishedSpanSet.has(spanId)) return;
363
+ this.finishedSpanSet.add(spanId);
364
+ this.finishedSpanIds.push(spanId);
365
+ this.finishedSpanCount++;
366
+ this.compactFinishedIds();
367
+ }
368
+ deleteFinished(spanId) {
369
+ const span = this.spans.get(spanId);
370
+ if (span?.endWallTs == null) return false;
371
+ const deleted = this.spans.delete(spanId);
372
+ if (this.finishedSpanSet.delete(spanId)) {
373
+ this.finishedSpanCount = Math.max(0, this.finishedSpanCount - 1);
374
+ }
375
+ return deleted;
376
+ }
377
+ peekOldestFinished() {
378
+ while (this.finishedSpanOffset < this.finishedSpanIds.length) {
379
+ const spanId = this.finishedSpanIds[this.finishedSpanOffset];
380
+ if (!this.finishedSpanSet.has(spanId)) {
381
+ this.finishedSpanOffset++;
382
+ continue;
383
+ }
384
+ const span = this.spans.get(spanId);
385
+ if (!span || span.endWallTs == null) {
386
+ this.finishedSpanSet.delete(spanId);
387
+ this.finishedSpanCount = Math.max(0, this.finishedSpanCount - 1);
388
+ this.finishedSpanOffset++;
389
+ continue;
390
+ }
391
+ return { spanId, span };
392
+ }
393
+ this.compactFinishedIds();
394
+ return void 0;
395
+ }
396
+ deleteOldestFinished() {
397
+ const oldest = this.peekOldestFinished();
398
+ if (!oldest) return false;
399
+ this.finishedSpanOffset++;
400
+ return this.deleteFinished(oldest.spanId);
401
+ }
402
+ compactFinishedIds() {
403
+ if (this.finishedSpanOffset < 1024 || this.finishedSpanOffset * 2 < this.finishedSpanIds.length) return;
404
+ this.finishedSpanIds.splice(0, this.finishedSpanOffset);
405
+ this.finishedSpanOffset = 0;
406
+ }
345
407
  };
346
408
 
347
409
  export {
@@ -0,0 +1,229 @@
1
+ import {
2
+ makeRuntimeEventRecord
3
+ } from "./chunk-EJ6BPYVR.mjs";
4
+ import {
5
+ emptyContext,
6
+ getCurrentFiber
7
+ } from "./chunk-GYM3LLGS.mjs";
8
+ import {
9
+ Cause,
10
+ asyncFlatMap,
11
+ asyncSync
12
+ } from "./chunk-36I3M4UC.mjs";
13
+
14
+ // src/core/runtime/fiberRef.ts
15
+ var nextFiberRefId = 1;
16
+ function makeFiberRef(initial) {
17
+ const ref = {
18
+ id: nextFiberRefId++,
19
+ initial,
20
+ get: () => getFiberRef(ref),
21
+ set: (value) => setFiberRef(ref, value),
22
+ update: (f) => updateFiberRef(ref, f),
23
+ modify: (f) => modifyFiberRef(ref, f),
24
+ locally: (value, effect) => locallyFiberRef(ref, value, effect),
25
+ locallyWith: (f, effect) => locallyFiberRefWith(ref, f, effect),
26
+ unsafeGet: () => unsafeGetFiberRef(ref),
27
+ unsafeSet: (value) => unsafeSetFiberRef(ref, value)
28
+ };
29
+ return ref;
30
+ }
31
+ function getFiberRef(ref) {
32
+ return asyncSync(() => unsafeGetFiberRef(ref));
33
+ }
34
+ function setFiberRef(ref, value) {
35
+ return asyncSync(() => {
36
+ unsafeSetFiberRef(ref, value);
37
+ });
38
+ }
39
+ function updateFiberRef(ref, f) {
40
+ return asyncSync(() => {
41
+ const next = f(unsafeGetFiberRef(ref));
42
+ unsafeSetFiberRef(ref, next);
43
+ return next;
44
+ });
45
+ }
46
+ function modifyFiberRef(ref, f) {
47
+ return asyncSync(() => {
48
+ const [result, next] = f(unsafeGetFiberRef(ref));
49
+ unsafeSetFiberRef(ref, next);
50
+ return result;
51
+ });
52
+ }
53
+ function locallyFiberRef(ref, value, effect) {
54
+ return {
55
+ _tag: "FiberRefLocally",
56
+ refId: ref.id,
57
+ value,
58
+ effect
59
+ };
60
+ }
61
+ function locallyFiberRefWith(ref, f, effect) {
62
+ return asyncFlatMap(getFiberRef(ref), (value) => locallyFiberRef(ref, f(value), effect));
63
+ }
64
+ function unsafeGetFiberRef(ref) {
65
+ const refs = currentFiberRefs(false);
66
+ return refs?.has(ref.id) ? refs.get(ref.id) : ref.initial;
67
+ }
68
+ function unsafeSetFiberRef(ref, value) {
69
+ const refs = currentFiberRefs(true);
70
+ refs?.set(ref.id, value);
71
+ }
72
+ function fiberRefSnapshot() {
73
+ return new Map(currentFiberRefs(false));
74
+ }
75
+ function currentFiberRefs(create) {
76
+ const fiber = getCurrentFiber();
77
+ if (!fiber) return void 0;
78
+ fiber.fiberContext ??= { log: emptyContext, trace: null };
79
+ if (!fiber.fiberContext.fiberRefs && create) fiber.fiberContext.fiberRefs = /* @__PURE__ */ new Map();
80
+ return fiber.fiberContext.fiberRefs;
81
+ }
82
+
83
+ // src/core/runtime/recorder.ts
84
+ function makeRuntimeRecorder(options = {}) {
85
+ const capacity = Math.max(1, Math.floor(options.maxEvents ?? 2048));
86
+ const records = new Array(capacity);
87
+ let next = 0;
88
+ let size = 0;
89
+ let dropped = 0;
90
+ let seq = 1;
91
+ const snapshot = () => {
92
+ const out = [];
93
+ const start = size === capacity ? next : 0;
94
+ for (let i = 0; i < size; i++) {
95
+ const record = records[(start + i) % capacity];
96
+ if (record) out.push(record);
97
+ }
98
+ return out;
99
+ };
100
+ const emit = (ev, ctx) => {
101
+ records[next] = makeRuntimeEventRecord(ev, ctx, seq++);
102
+ next = (next + 1) % capacity;
103
+ if (size < capacity) size++;
104
+ else dropped++;
105
+ };
106
+ const clear = () => {
107
+ records.fill(void 0);
108
+ next = 0;
109
+ size = 0;
110
+ dropped = 0;
111
+ };
112
+ const stats = () => {
113
+ const current = snapshot();
114
+ return {
115
+ size,
116
+ capacity,
117
+ dropped,
118
+ ...current[0] ? { firstSeq: current[0].seq } : {},
119
+ ...current[current.length - 1] ? { lastSeq: current[current.length - 1].seq } : {}
120
+ };
121
+ };
122
+ const recorder = {
123
+ emit,
124
+ snapshot,
125
+ clear,
126
+ stats,
127
+ explain: (explainOptions = {}) => explainRuntimeEvents(snapshot(), dropped, explainOptions)
128
+ };
129
+ return Object.assign(recorder, { hooks: recorder });
130
+ }
131
+ function explainRuntimeEvents(events, dropped, options) {
132
+ const maxEvents = Math.max(1, Math.floor(options.maxEvents ?? 80));
133
+ const slice = events.length > maxEvents ? events.slice(events.length - maxEvents) : events;
134
+ const fiberStarts = /* @__PURE__ */ new Map();
135
+ const fiberSuspends = /* @__PURE__ */ new Map();
136
+ const lines = [`Runtime flight recorder: ${events.length} event${events.length === 1 ? "" : "s"}${dropped > 0 ? `, ${dropped} dropped` : ""}.`];
137
+ for (const event of slice) {
138
+ switch (event.type) {
139
+ case "fiber.start": {
140
+ fiberStarts.set(event.fiberId, event);
141
+ lines.push(`fiber#${event.fiberId} started${event.name ? ` "${event.name}"` : ""}${event.parentFiberId !== void 0 ? ` parent=fiber#${event.parentFiberId}` : ""}`);
142
+ break;
143
+ }
144
+ case "fiber.suspend": {
145
+ fiberSuspends.set(event.fiberId, event);
146
+ lines.push(`fiber#${event.fiberId} suspended awaiting ${event.reason ?? "unknown"}`);
147
+ break;
148
+ }
149
+ case "fiber.resume": {
150
+ const suspended = fiberSuspends.get(event.fiberId);
151
+ fiberSuspends.delete(event.fiberId);
152
+ lines.push(`fiber#${event.fiberId} resumed${suspended ? ` after ${durationMs(suspended, event)} awaiting ${fiberSuspendReason(suspended)}` : ""}`);
153
+ break;
154
+ }
155
+ case "fiber.end": {
156
+ const started = fiberStarts.get(event.fiberId);
157
+ const suspended = fiberSuspends.get(event.fiberId);
158
+ fiberSuspends.delete(event.fiberId);
159
+ lines.push(`fiber#${event.fiberId} ended ${event.status}${started ? ` after ${durationMs(started, event)}` : ""}${suspended ? ` while awaiting ${fiberSuspendReason(suspended)}` : ""}${event.error ? ` error=${formatUnknown(event.error)}` : ""}`);
160
+ break;
161
+ }
162
+ case "scope.open":
163
+ lines.push(`scope#${event.scopeId} opened${event.parentScopeId !== void 0 ? ` parent=scope#${event.parentScopeId}` : ""}`);
164
+ break;
165
+ case "scope.close":
166
+ lines.push(`scope#${event.scopeId} closed ${event.status}${event.error ? ` error=${formatUnknown(event.error)}` : ""}`);
167
+ break;
168
+ case "supervisor.child.restart":
169
+ lines.push(`supervisor#${event.supervisorId} restarting child#${event.childId} attempt=${event.restartCount} delay=${event.delayMs}ms${event.reason ? ` reason=${event.reason}` : ""}`);
170
+ break;
171
+ case "supervisor.child.escalate":
172
+ lines.push(`supervisor#${event.supervisorId} escalated child#${event.childId}${event.reason ? ` reason=${event.reason}` : ""}${event.error ? ` error=${formatUnknown(event.error)}` : ""}`);
173
+ break;
174
+ case "schedule.decision":
175
+ lines.push(`schedule${event.name ? ` "${event.name}"` : ""} attempt=${event.attempt} ${event.continue ? "continues" : "stops"} delay=${event.delayMs}ms elapsed=${Math.round(event.elapsedMs)}ms${event.reason ? ` reason=${event.reason}` : ""}`);
176
+ break;
177
+ case "log":
178
+ if (event.level === "warn" || event.level === "error") {
179
+ lines.push(`${event.level}: ${event.message ?? ""}${event.fields ? ` ${JSON.stringify(event.fields)}` : ""}`);
180
+ }
181
+ break;
182
+ case "span.start":
183
+ lines.push(`span started "${event.name}"${event.traceId ? ` trace=${event.traceId}` : ""}`);
184
+ break;
185
+ case "span.end":
186
+ lines.push(`span ended ${event.status}${event.name ? ` "${event.name}"` : ""}${event.error ? ` error=${formatUnknown(event.error)}` : ""}`);
187
+ break;
188
+ default:
189
+ break;
190
+ }
191
+ }
192
+ for (const suspended of fiberSuspends.values()) {
193
+ lines.push(`fiber#${suspended.fiberId} still suspended for ${durationFromNowMs(suspended)} awaiting ${fiberSuspendReason(suspended)}`);
194
+ }
195
+ return lines.join("\n");
196
+ }
197
+ function durationMs(start, end) {
198
+ return `${Math.max(0, Math.round(end.wallTs - start.wallTs))}ms`;
199
+ }
200
+ function durationFromNowMs(start) {
201
+ return `${Math.max(0, Math.round(Date.now() - start.wallTs))}ms`;
202
+ }
203
+ function formatUnknown(value) {
204
+ if (Cause.isCause(value)) return Cause.pretty(value, { singleLine: true });
205
+ if (value instanceof Error) return value.message;
206
+ if (typeof value === "string") return value;
207
+ try {
208
+ return JSON.stringify(value);
209
+ } catch {
210
+ return String(value);
211
+ }
212
+ }
213
+ function fiberSuspendReason(record) {
214
+ return record.type === "fiber.suspend" ? record.reason ?? "unknown" : "unknown";
215
+ }
216
+
217
+ export {
218
+ makeFiberRef,
219
+ getFiberRef,
220
+ setFiberRef,
221
+ updateFiberRef,
222
+ modifyFiberRef,
223
+ locallyFiberRef,
224
+ locallyFiberRefWith,
225
+ unsafeGetFiberRef,
226
+ unsafeSetFiberRef,
227
+ fiberRefSnapshot,
228
+ makeRuntimeRecorder
229
+ };