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.
- package/CHANGELOG.md +17 -0
- package/README.md +287 -23
- package/dist/agent/cli/main.cjs +38 -38
- package/dist/agent/cli/main.js +6 -6
- package/dist/agent/cli/main.mjs +6 -6
- package/dist/agent/index.cjs +7 -7
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +6 -6
- package/dist/agent/index.mjs +6 -6
- package/dist/chunk-2HQTDLHF.mjs +683 -0
- package/dist/chunk-36I3M4UC.mjs +370 -0
- package/dist/{chunk-QY5FKYEQ.js → chunk-3AYM6WPJ.js} +570 -51
- package/dist/chunk-3LOYJFRR.cjs +300 -0
- package/dist/chunk-3Y2RIUMM.js +300 -0
- package/dist/{chunk-7XOPAB5Q.js → chunk-4P2HHGAX.mjs} +83 -5
- package/dist/{chunk-N6VHMOWB.cjs → chunk-4ROBZFL6.cjs} +128 -128
- package/dist/{chunk-NC5SDRYE.js → chunk-52OB2ROS.js} +4 -4
- package/dist/{chunk-JX3LZQJH.cjs → chunk-52PPNNI4.cjs} +82 -20
- package/dist/{chunk-5YOQOXEQ.cjs → chunk-5EC274J5.cjs} +676 -293
- package/dist/chunk-5QC7LRZ3.js +229 -0
- package/dist/{chunk-7TL2LHQJ.js → chunk-5VRJNBLZ.mjs} +524 -141
- package/dist/chunk-62AZW6UT.cjs +313 -0
- package/dist/chunk-6IXXWIUM.js +683 -0
- package/dist/chunk-6RY2FFN4.mjs +2024 -0
- package/dist/chunk-74ZTY6CP.js +2871 -0
- package/dist/chunk-7CMJS3QE.mjs +2871 -0
- package/dist/{chunk-2WC63LJK.mjs → chunk-7JIJOVCT.js} +20 -10
- package/dist/chunk-7X3K5RMS.js +2024 -0
- package/dist/chunk-7ZPEZ57L.cjs +2024 -0
- package/dist/{chunk-FM4W4QPL.js → chunk-A2OM6NEH.mjs} +5 -4
- package/dist/chunk-AGR5B2BC.cjs +683 -0
- package/dist/chunk-B33ICAKP.js +313 -0
- package/dist/{chunk-J3H54ZRV.mjs → chunk-B5JD23U7.mjs} +1 -1
- package/dist/{chunk-F5EUMJL7.mjs → chunk-BKK77SBA.js} +83 -5
- package/dist/{chunk-U5KWK3PX.mjs → chunk-C3MDXTRZ.js} +11 -0
- package/dist/{chunk-SPUEME2B.cjs → chunk-CZIVE6NT.cjs} +12 -1
- package/dist/{chunk-TDVMADDN.js → chunk-DNFJLJMW.mjs} +11 -0
- package/dist/{chunk-XDZOO4L5.js → chunk-EJ6BPYVR.mjs} +79 -17
- package/dist/chunk-EOC4UHBS.mjs +229 -0
- package/dist/chunk-F6XWZQY4.cjs +777 -0
- package/dist/{chunk-7LVI2GIN.js → chunk-FH2X7BVP.js} +507 -72
- package/dist/{chunk-OOGJ73B6.js → chunk-FHQGHPMO.mjs} +20 -10
- package/dist/{chunk-WQ5QNU5R.cjs → chunk-GLE2WY7Z.cjs} +652 -217
- package/dist/{chunk-G6IQOE4P.mjs → chunk-GYM3LLGS.mjs} +507 -72
- package/dist/{chunk-TVN5I4U6.cjs → chunk-JF5WGYJJ.cjs} +25 -24
- package/dist/{chunk-CY33PGEX.mjs → chunk-KH4SYAOS.mjs} +570 -51
- package/dist/chunk-KN32XNTH.mjs +313 -0
- package/dist/chunk-KQLYONSE.cjs +2871 -0
- package/dist/{chunk-7HUOJA4W.cjs → chunk-KZJQ723N.cjs} +90 -80
- package/dist/{chunk-CCKHV5BT.mjs → chunk-L2SYFEBS.js} +5 -4
- package/dist/{chunk-IJT6RRQ5.cjs → chunk-L6VB5N7Q.cjs} +20 -9
- package/dist/{chunk-ZGLD4TVZ.mjs → chunk-MBEJI5HF.mjs} +4 -4
- package/dist/{chunk-PRWCB3QL.mjs → chunk-MIIYDLGM.js} +524 -141
- package/dist/{chunk-H55LI6WY.js → chunk-MOO4L7F4.mjs} +15 -4
- package/dist/chunk-MVGUEJ5Z.cjs +370 -0
- package/dist/chunk-PD4EJTQC.cjs +229 -0
- package/dist/chunk-PWC3RBQE.mjs +300 -0
- package/dist/{chunk-MWXMNYJS.cjs → chunk-Q2I37RP3.cjs} +643 -124
- package/dist/{chunk-VFIUZG7J.mjs → chunk-RKGKFN2A.js} +79 -17
- package/dist/{chunk-NYL4D7SK.cjs → chunk-SA6HUJVI.cjs} +5 -5
- package/dist/chunk-SK7UZRNI.mjs +777 -0
- package/dist/{chunk-K2T3DV26.mjs → chunk-TRM4JUZQ.js} +15 -4
- package/dist/chunk-UB4B6OFY.js +370 -0
- package/dist/{chunk-G3XGCZDQ.js → chunk-UCUBNWM2.js} +1 -1
- package/dist/chunk-VWIPB6I5.js +777 -0
- package/dist/{chunk-JNFRRJYH.cjs → chunk-WBGRHGBP.cjs} +270 -192
- package/dist/{client-CtFmoDvM.d.ts → client-CZHU674n.d.ts} +211 -36
- package/dist/core/index.cjs +135 -9
- package/dist/core/index.d.ts +238 -33
- package/dist/core/index.js +155 -29
- package/dist/core/index.mjs +155 -29
- package/dist/{effect-CGNl5Rqp.d.ts → effect-DIUHZ9IN.d.ts} +89 -1
- package/dist/effectRunner-CFLC32IK.cjs +8 -0
- package/dist/{effectRunner-A4CHJXJI.js → effectRunner-L4S7IPT3.js} +2 -2
- package/dist/{effectRunner-OPUF6QRN.mjs → effectRunner-NNGG75QA.mjs} +2 -2
- package/dist/http/index.cjs +324 -2986
- package/dist/http/index.d.ts +54 -68
- package/dist/http/index.js +238 -2900
- package/dist/http/index.mjs +238 -2900
- package/dist/http/testing.cjs +14 -12
- package/dist/http/testing.d.ts +5 -4
- package/dist/http/testing.js +10 -8
- package/dist/http/testing.mjs +10 -8
- package/dist/index.cjs +423 -255
- package/dist/index.d.ts +87 -69
- package/dist/index.js +301 -133
- package/dist/index.mjs +301 -133
- package/dist/observability/index.cjs +18 -531
- package/dist/observability/index.d.ts +81 -8
- package/dist/observability/index.js +25 -538
- package/dist/observability/index.mjs +25 -538
- package/dist/perf/cli.cjs +401 -0
- package/dist/perf/cli.d.ts +1 -0
- package/dist/perf/cli.js +401 -0
- package/dist/perf/cli.mjs +401 -0
- package/dist/perf/index.cjs +141 -0
- package/dist/perf/index.d.ts +483 -0
- package/dist/perf/index.js +141 -0
- package/dist/perf/index.mjs +141 -0
- package/dist/schedule-CK3Ml_7p.d.ts +259 -0
- package/dist/schema/index.cjs +6 -2
- package/dist/schema/index.d.ts +3 -1
- package/dist/schema/index.js +5 -1
- package/dist/schema/index.mjs +5 -1
- package/dist/{server-C8hDXA74.d.ts → server-D6JZ15_e.d.ts} +16 -4
- package/dist/{stream-dvSs0QS5.d.ts → stream-B4oK9JFP.d.ts} +1 -1
- package/dist/{tracer-B5tRH9H7.d.ts → tracer-Hwt1cl7h.d.ts} +13 -54
- package/dist/{tracing-Dt9S_6V8.d.ts → tracing-DqbTKGcf.d.ts} +1 -1
- package/docs/ARCHITECTURE.md +292 -0
- package/docs/README.md +65 -0
- package/docs/adr/0001-ai-context-pack.md +32 -0
- package/docs/agent-apply-mode.md +104 -0
- package/docs/agent-approvals.md +110 -0
- package/docs/agent-batch.md +185 -0
- package/docs/agent-boundaries.md +112 -0
- package/docs/agent-chat-sessions.md +160 -0
- package/docs/agent-ci.md +17 -0
- package/docs/agent-cli.md +405 -0
- package/docs/agent-config.md +480 -0
- package/docs/agent-context-discovery.md +159 -0
- package/docs/agent-copilot-like-dx.md +126 -0
- package/docs/agent-declarative-optimized-planning.md +138 -0
- package/docs/agent-dx.md +224 -0
- package/docs/agent-env-files.md +126 -0
- package/docs/agent-follow-up-context.md +43 -0
- package/docs/agent-global-usage.md +180 -0
- package/docs/agent-init.md +109 -0
- package/docs/agent-install-and-configure.md +516 -0
- package/docs/agent-language-workspace-ux.md +99 -0
- package/docs/agent-llm-adapters.md +123 -0
- package/docs/agent-local-install.md +190 -0
- package/docs/agent-local-tests.md +51 -0
- package/docs/agent-observability.md +155 -0
- package/docs/agent-patch-quality-loop.md +162 -0
- package/docs/agent-presets.md +22 -0
- package/docs/agent-project-commands.md +237 -0
- package/docs/agent-project-intelligence.md +156 -0
- package/docs/agent-redaction.md +18 -0
- package/docs/agent-release-readiness.md +76 -0
- package/docs/agent-rollback-safety.md +162 -0
- package/docs/agent-rollback.md +23 -0
- package/docs/agent-run-artifacts.md +16 -0
- package/docs/agent-vscode-auto-discovery.md +137 -0
- package/docs/agent-vscode-batch-runner.md +100 -0
- package/docs/agent-vscode-chat-layout.md +90 -0
- package/docs/agent-vscode-clean-install.md +147 -0
- package/docs/agent-vscode-code-actions.md +70 -0
- package/docs/agent-vscode-diff-preview.md +45 -0
- package/docs/agent-vscode-inline-assist.md +56 -0
- package/docs/agent-vscode-install.md +186 -0
- package/docs/agent-vscode-model-setup.md +97 -0
- package/docs/agent-vscode-patch-preview.md +92 -0
- package/docs/agent-vscode-problems.md +79 -0
- package/docs/agent-vscode-project-dashboard.md +106 -0
- package/docs/agent-vscode-run-history.md +92 -0
- package/docs/agent-vscode-ux.md +73 -0
- package/docs/ai/INVARIANTS.md +84 -0
- package/docs/ai/PROJECT_MAP.md +338 -0
- package/docs/ai/PUBLIC_API.md +339 -0
- package/docs/ai/VALIDATION_MATRIX.md +67 -0
- package/docs/api-polish.md +37 -0
- package/docs/cancellation.md +162 -0
- package/docs/coverage.md +46 -0
- package/docs/framework-integrations.md +38 -0
- package/docs/frameworks/angular.md +153 -0
- package/docs/frameworks/express.md +125 -0
- package/docs/frameworks/fastify.md +124 -0
- package/docs/frameworks/nestjs.md +282 -0
- package/docs/frameworks/nextjs.md +147 -0
- package/docs/frameworks/react.md +139 -0
- package/docs/frameworks/vanilla.md +224 -0
- package/docs/getting-started.md +159 -0
- package/docs/guides/README.md +40 -0
- package/docs/guides/circuit-breaker.md +89 -0
- package/docs/guides/error-handling.md +91 -0
- package/docs/guides/getting-started.md +107 -0
- package/docs/guides/layers.md +189 -0
- package/docs/guides/metrics.md +101 -0
- package/docs/guides/resource-management.md +141 -0
- package/docs/guides/retry.md +215 -0
- package/docs/guides/semaphore.md +66 -0
- package/docs/guides/streams.md +117 -0
- package/docs/guides/supervisors.md +98 -0
- package/docs/guides/testing.md +162 -0
- package/docs/guides/tracing.md +71 -0
- package/docs/http-recipes.md +399 -0
- package/docs/http.md +749 -0
- package/docs/modules.md +285 -0
- package/docs/nestjs.md +6 -0
- package/docs/observability-collector-smoke.md +31 -0
- package/docs/observability-framework-examples.md +110 -0
- package/docs/observability.md +649 -0
- package/docs/otel-collector-smoke.yaml +27 -0
- package/docs/performance-profiler.md +199 -0
- package/docs/production-readiness.md +73 -0
- package/docs/recipes/README.md +12 -0
- package/docs/recipes/http-server.md +45 -0
- package/docs/recipes/layers.md +44 -0
- package/docs/recipes/performance.md +47 -0
- package/docs/recipes/runtime.md +41 -0
- package/docs/recipes/testing.md +41 -0
- package/docs/release.md +53 -0
- package/docs/wasm-bounded-queues.md +44 -0
- package/docs/wasm-engine-observability-benchmarks.md +85 -0
- package/docs/wasm-fiber-engine.md +117 -0
- package/docs/wasm-scheduler-state-machine.md +122 -0
- package/docs/wasm-stream-chunks.md +54 -0
- package/package.json +22 -2
- package/dist/chunk-45F7OKGT.cjs +0 -104
- package/dist/chunk-7V4KY4RL.mjs +0 -104
- package/dist/chunk-DJQ7OMMB.cjs +0 -144
- package/dist/chunk-GOV47PPB.mjs +0 -552
- package/dist/chunk-JF4XXPZ5.cjs +0 -552
- package/dist/chunk-KCPT2D6G.js +0 -552
- package/dist/chunk-NOYZIMUJ.mjs +0 -144
- package/dist/chunk-PNVFW245.js +0 -144
- package/dist/chunk-ROJC3NBJ.js +0 -104
- package/dist/effectRunner-3ZHAD3LE.cjs +0 -8
- package/dist/schedule-Fque9Abz.d.ts +0 -70
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
makeBoundedRingBuffer
|
|
3
|
-
} from "./chunk-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
327
|
-
|
|
328
|
-
if (
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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
|
+
};
|