brass-runtime 1.13.8 → 1.14.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 (36) hide show
  1. package/dist/agent/cli/main.cjs +43 -43
  2. package/dist/agent/cli/main.js +2 -2
  3. package/dist/agent/cli/main.mjs +2 -2
  4. package/dist/agent/index.cjs +3 -3
  5. package/dist/agent/index.d.ts +1 -1
  6. package/dist/agent/index.js +2 -2
  7. package/dist/agent/index.mjs +2 -2
  8. package/dist/chunk-4N2JEK4H.mjs +3897 -0
  9. package/dist/chunk-BKBFSOGT.cjs +3897 -0
  10. package/dist/{chunk-XNOTJSMZ.mjs → chunk-BMRF4FN6.js} +268 -8
  11. package/dist/chunk-JT7D6M5H.js +3897 -0
  12. package/dist/{chunk-3R7ZYRK2.mjs → chunk-MQF7HZ7Y.mjs} +1 -1
  13. package/dist/chunk-SKVY72E5.cjs +667 -0
  14. package/dist/{chunk-ATHSSDUF.js → chunk-UWMMYKVK.mjs} +268 -8
  15. package/dist/{chunk-INZBKOHY.js → chunk-WJESVBWN.js} +1 -1
  16. package/dist/{chunk-XDINDYNA.cjs → chunk-XTMZTVIT.cjs} +134 -134
  17. package/dist/{effect-ISvXPLgc.d.ts → effect-DM56H743.d.ts} +191 -21
  18. package/dist/http/index.cjs +808 -140
  19. package/dist/http/index.d.ts +181 -8
  20. package/dist/http/index.js +793 -125
  21. package/dist/http/index.mjs +793 -125
  22. package/dist/index.cjs +1785 -137
  23. package/dist/index.d.ts +979 -36
  24. package/dist/index.js +1675 -27
  25. package/dist/index.mjs +1675 -27
  26. package/dist/stream-Oqe6WeLE.d.ts +173 -0
  27. package/package.json +1 -1
  28. package/wasm/pkg/brass_runtime_wasm_engine.d.ts +95 -16
  29. package/wasm/pkg/brass_runtime_wasm_engine.js +715 -15
  30. package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm +0 -0
  31. package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm.d.ts +78 -7
  32. package/dist/chunk-2P4PD6D7.cjs +0 -2557
  33. package/dist/chunk-7F2R7A2V.mjs +0 -2557
  34. package/dist/chunk-L6KKKM66.js +0 -2557
  35. package/dist/chunk-ZTDK2DLG.cjs +0 -407
  36. package/dist/stream-BvukHxCv.d.ts +0 -66
package/dist/index.js CHANGED
@@ -8,29 +8,39 @@ import {
8
8
  foreachStream,
9
9
  fromArray,
10
10
  fromPull,
11
+ makeCircuitBreaker,
11
12
  managedStream,
12
13
  mapStream,
13
14
  merge,
14
15
  mergeStream,
15
16
  rangeStream,
17
+ retry,
18
+ retryN,
19
+ retryWithBackoff,
20
+ sleep,
16
21
  streamFromReadableStream,
22
+ timeout,
17
23
  uncons,
18
24
  unwrapScoped,
19
25
  widenOpt,
20
26
  zip
21
- } from "./chunk-ATHSSDUF.js";
27
+ } from "./chunk-BMRF4FN6.js";
22
28
  import {
29
+ ABI_VERSION,
23
30
  Async,
24
31
  Cause,
25
32
  DefaultHostExecutor,
33
+ EVENT_WORDS,
26
34
  EngineFiberHandle,
35
+ EventKindCode,
27
36
  Exit,
28
37
  HostRegistry,
29
38
  JsFiberEngine,
39
+ NONE_U32,
30
40
  NoopHooks,
41
+ OpcodeTagCode,
31
42
  ProgramBuilder,
32
43
  PushStatus,
33
- ReferenceWasmBridge,
34
44
  RingBuffer,
35
45
  Runtime,
36
46
  RuntimeFiber,
@@ -39,6 +49,7 @@ import {
39
49
  WasmFiberEngine,
40
50
  WasmFiberRegistryBridge,
41
51
  WasmPackFiberBridge,
52
+ abortablePromiseStats,
42
53
  acquireRelease,
43
54
  async,
44
55
  asyncCatchAll,
@@ -53,6 +64,10 @@ import {
53
64
  asyncTotal,
54
65
  catchAll,
55
66
  collectAllPar,
67
+ decodeEvent,
68
+ decodeEventBatch,
69
+ encodeOpcodeNodes,
70
+ encodeOpcodeProgram,
56
71
  end,
57
72
  fail,
58
73
  flatMap,
@@ -61,7 +76,10 @@ import {
61
76
  getBenchmarkBudget,
62
77
  getCurrentFiber,
63
78
  globalScheduler,
79
+ inferCallerLaneFromStack,
80
+ laneTag,
64
81
  makeBoundedRingBuffer,
82
+ makeFiberReadyQueue,
65
83
  map,
66
84
  mapAsync,
67
85
  mapError,
@@ -70,13 +88,17 @@ import {
70
88
  orElseOptional,
71
89
  race,
72
90
  raceWith,
91
+ resetAbortablePromiseStats,
73
92
  resolveWasmModule,
74
93
  runtimeCapabilities,
94
+ runtimeForCaller,
95
+ sanitizeLaneKey,
75
96
  setBenchmarkBudget,
76
97
  some,
77
98
  succeed,
78
99
  sync,
79
100
  toPromise,
101
+ toPromiseByCaller,
80
102
  unit,
81
103
  unsafeGetCurrentRuntime,
82
104
  unsafeRunAsync,
@@ -86,7 +108,7 @@ import {
86
108
  withScope,
87
109
  withScopeAsync,
88
110
  zipPar
89
- } from "./chunk-L6KKKM66.js";
111
+ } from "./chunk-JT7D6M5H.js";
90
112
 
91
113
  // src/core/types/cancel.ts
92
114
  function makeCancelToken() {
@@ -121,6 +143,135 @@ function linkAbortController(token, ac) {
121
143
  return token.onCancel(() => ac.abort());
122
144
  }
123
145
 
146
+ // src/core/runtime/resource.ts
147
+ function bracket(acquire, use, release) {
148
+ return async((env, cb) => {
149
+ const runtime = unsafeGetCurrentRuntime();
150
+ const scope = new Scope(runtime);
151
+ const acquireFiber = scope.fork(acquire);
152
+ acquireFiber.join((acquireExit) => {
153
+ if (acquireExit._tag === "Failure") {
154
+ scope.close(acquireExit);
155
+ cb(acquireExit);
156
+ return;
157
+ }
158
+ const resource = acquireExit.value;
159
+ const useFiber = scope.fork(use(resource));
160
+ useFiber.join((useExit) => {
161
+ const releaseEffect = safeRelease(release, resource, useExit);
162
+ const releaseFiber = runtime.fork(releaseEffect);
163
+ releaseFiber.join(() => {
164
+ scope.close(useExit);
165
+ cb(useExit);
166
+ });
167
+ });
168
+ });
169
+ return () => {
170
+ scope.close(Exit.failCause(Cause.interrupt()));
171
+ };
172
+ });
173
+ }
174
+ function safeRelease(release, resource, exit) {
175
+ return asyncFold(
176
+ (() => {
177
+ try {
178
+ return release(resource, exit);
179
+ } catch {
180
+ return unit();
181
+ }
182
+ })(),
183
+ () => unit(),
184
+ () => unit()
185
+ );
186
+ }
187
+ function ensuring(effect, finalizer) {
188
+ return async((env, cb) => {
189
+ const runtime = unsafeGetCurrentRuntime();
190
+ const fiber = runtime.fork(effect);
191
+ fiber.join((exit) => {
192
+ const fin = asyncFold(
193
+ (() => {
194
+ try {
195
+ return finalizer(exit);
196
+ } catch {
197
+ return unit();
198
+ }
199
+ })(),
200
+ () => unit(),
201
+ () => unit()
202
+ );
203
+ runtime.fork(fin).join(() => {
204
+ cb(exit);
205
+ });
206
+ });
207
+ return () => {
208
+ fiber.interrupt();
209
+ };
210
+ });
211
+ }
212
+ function managed(acquire, release) {
213
+ return {
214
+ _tag: "Managed",
215
+ acquire,
216
+ release: (resource, exit) => release(resource, exit)
217
+ };
218
+ }
219
+ function useManaged(m, body) {
220
+ return bracket(m.acquire, body, m.release);
221
+ }
222
+ function managedAll(manageds) {
223
+ const acquire = async((env, cb) => {
224
+ const runtime = unsafeGetCurrentRuntime();
225
+ const resources = [];
226
+ let i = 0;
227
+ const acquireNext = () => {
228
+ if (i >= manageds.length) {
229
+ cb({ _tag: "Success", value: resources });
230
+ return;
231
+ }
232
+ const m = manageds[i];
233
+ const fiber = runtime.fork(m.acquire);
234
+ fiber.join((exit) => {
235
+ if (exit._tag === "Failure") {
236
+ releaseAcquired(runtime, manageds, resources, exit).then(() => {
237
+ cb(exit);
238
+ });
239
+ return;
240
+ }
241
+ resources.push(exit.value);
242
+ i++;
243
+ acquireNext();
244
+ });
245
+ };
246
+ acquireNext();
247
+ });
248
+ const release = (resources, exit) => {
249
+ return async((_env, cb) => {
250
+ const runtime = unsafeGetCurrentRuntime();
251
+ releaseAcquired(runtime, manageds, resources, exit).then(() => {
252
+ cb({ _tag: "Success", value: void 0 });
253
+ });
254
+ });
255
+ };
256
+ return { _tag: "Managed", acquire, release };
257
+ }
258
+ async function releaseAcquired(runtime, manageds, resources, exit) {
259
+ for (let i = resources.length - 1; i >= 0; i--) {
260
+ try {
261
+ const m = manageds[i];
262
+ await new Promise((resolve) => {
263
+ const releaseEff = asyncFold(
264
+ m.release(resources[i], exit),
265
+ () => unit(),
266
+ () => unit()
267
+ );
268
+ runtime.fork(releaseEff).join(() => resolve());
269
+ });
270
+ } catch {
271
+ }
272
+ }
273
+ }
274
+
124
275
  // src/core/runtime/linkedQueue.ts
125
276
  var LinkedQueue = class {
126
277
  head = null;
@@ -163,6 +314,788 @@ var LinkedQueue = class {
163
314
  }
164
315
  };
165
316
 
317
+ // src/core/runtime/semaphore.ts
318
+ function makeSemaphore(n) {
319
+ const capacity = Math.max(1, Math.floor(n));
320
+ let available = capacity;
321
+ let totalAcquired = 0;
322
+ let totalReleased = 0;
323
+ const waiters = new LinkedQueue();
324
+ const acquire = () => {
325
+ return async((_env, cb) => {
326
+ if (available > 0) {
327
+ available--;
328
+ totalAcquired++;
329
+ cb({ _tag: "Success", value: void 0 });
330
+ return;
331
+ }
332
+ const node = waiters.push(cb);
333
+ return () => {
334
+ waiters.remove(node);
335
+ };
336
+ });
337
+ };
338
+ const release = () => {
339
+ totalReleased++;
340
+ if (waiters.length > 0) {
341
+ const waiter = waiters.shift();
342
+ totalAcquired++;
343
+ waiter({ _tag: "Success", value: void 0 });
344
+ return;
345
+ }
346
+ available++;
347
+ };
348
+ const withPermit = (effect) => {
349
+ return asyncFlatMap(
350
+ acquire(),
351
+ () => async((_env, cb) => {
352
+ const runtime = unsafeGetCurrentRuntime();
353
+ const fiber = runtime.fork(effect);
354
+ fiber.join((exit) => {
355
+ release();
356
+ cb(exit);
357
+ });
358
+ return () => {
359
+ fiber.interrupt();
360
+ release();
361
+ };
362
+ })
363
+ );
364
+ };
365
+ return {
366
+ capacity,
367
+ available: () => available,
368
+ waiting: () => waiters.length,
369
+ withPermit,
370
+ acquire,
371
+ release
372
+ };
373
+ }
374
+
375
+ // src/core/runtime/ref.ts
376
+ function makeRef(initial) {
377
+ let value = initial;
378
+ return {
379
+ get: () => asyncSync(() => value),
380
+ set: (v) => asyncSync(() => {
381
+ value = v;
382
+ }),
383
+ update: (f) => asyncSync(() => {
384
+ value = f(value);
385
+ return value;
386
+ }),
387
+ modify: (f) => asyncSync(() => {
388
+ const [result, next] = f(value);
389
+ value = next;
390
+ return result;
391
+ }),
392
+ unsafeGet: () => value
393
+ };
394
+ }
395
+ function derivedRef(parent, get, set) {
396
+ return {
397
+ get: () => asyncSync(() => get(parent.unsafeGet())),
398
+ set: (b) => asyncSync(() => {
399
+ const current = parent.unsafeGet();
400
+ parent.set(set(current, b));
401
+ }),
402
+ update: (f) => asyncSync(() => {
403
+ const parentVal = parent.unsafeGet();
404
+ const currentB = get(parentVal);
405
+ const newB = f(currentB);
406
+ const newParent = set(parentVal, newB);
407
+ parent.unsafeGet = () => newParent;
408
+ return newB;
409
+ }),
410
+ modify: (f) => asyncSync(() => {
411
+ const parentVal = parent.unsafeGet();
412
+ const currentB = get(parentVal);
413
+ const [result, newB] = f(currentB);
414
+ const newParent = set(parentVal, newB);
415
+ parent.unsafeGet = () => newParent;
416
+ return result;
417
+ }),
418
+ unsafeGet: () => get(parent.unsafeGet())
419
+ };
420
+ }
421
+
422
+ // src/core/runtime/schedule.ts
423
+ function recurs(n) {
424
+ return {
425
+ _tag: "Schedule",
426
+ initial: () => 0,
427
+ step: (count, _input) => {
428
+ const next = count + 1;
429
+ return [{ continue: next < n, delayMs: 0 }, next, next];
430
+ }
431
+ };
432
+ }
433
+ function fixed(delayMs) {
434
+ return {
435
+ _tag: "Schedule",
436
+ initial: () => 0,
437
+ step: (count, _input) => {
438
+ return [{ continue: true, delayMs }, count + 1, count + 1];
439
+ }
440
+ };
441
+ }
442
+ function exponential(baseMs, maxMs = Infinity) {
443
+ return {
444
+ _tag: "Schedule",
445
+ initial: () => 0,
446
+ step: (count, _input) => {
447
+ const delay = Math.min(baseMs * Math.pow(2, count), maxMs);
448
+ return [{ continue: true, delayMs: delay }, count + 1, count + 1];
449
+ }
450
+ };
451
+ }
452
+ function jittered(baseMs, maxMs = Infinity) {
453
+ return {
454
+ _tag: "Schedule",
455
+ initial: () => 0,
456
+ step: (count, _input) => {
457
+ const cap = Math.min(baseMs * Math.pow(2, count), maxMs);
458
+ const delay = Math.floor(Math.random() * cap);
459
+ return [{ continue: true, delayMs: delay }, count + 1, count + 1];
460
+ }
461
+ };
462
+ }
463
+ function elapsed(maxMs) {
464
+ return {
465
+ _tag: "Schedule",
466
+ initial: () => performance.now(),
467
+ step: (startedAt, _input) => {
468
+ const el = performance.now() - startedAt;
469
+ return [{ continue: el < maxMs, delayMs: 0 }, startedAt, el];
470
+ }
471
+ };
472
+ }
473
+ function whileInput(pred) {
474
+ return {
475
+ _tag: "Schedule",
476
+ initial: () => void 0,
477
+ step: (_state, input) => {
478
+ return [{ continue: pred(input), delayMs: 0 }, void 0, input];
479
+ }
480
+ };
481
+ }
482
+ function take(schedule, n) {
483
+ return {
484
+ _tag: "Schedule",
485
+ initial: () => ({ inner: schedule.initial(), count: 0 }),
486
+ step: (state, input) => {
487
+ if (state.count >= n) return [{ continue: false, delayMs: 0 }, state, void 0];
488
+ const [decision, nextInner, output] = schedule.step(state.inner, input);
489
+ const nextState = { inner: nextInner, count: state.count + 1 };
490
+ return [{ continue: decision.continue && state.count + 1 < n, delayMs: decision.delayMs }, nextState, output];
491
+ }
492
+ };
493
+ }
494
+ function andThen(first, second) {
495
+ return {
496
+ _tag: "Schedule",
497
+ initial: () => ({ phase: "first", inner: first.initial() }),
498
+ step: (state, input) => {
499
+ if (state.phase === "first") {
500
+ const [decision2, nextInner2, output2] = first.step(state.inner, input);
501
+ if (decision2.continue) {
502
+ return [decision2, { phase: "first", inner: nextInner2 }, output2];
503
+ }
504
+ return [{ continue: true, delayMs: decision2.delayMs }, { phase: "second", inner: second.initial() }, output2];
505
+ }
506
+ const [decision, nextInner, output] = second.step(state.inner, input);
507
+ return [decision, { phase: "second", inner: nextInner }, output];
508
+ }
509
+ };
510
+ }
511
+ function intersect(left, right) {
512
+ return {
513
+ _tag: "Schedule",
514
+ initial: () => ({ left: left.initial(), right: right.initial() }),
515
+ step: (state, input) => {
516
+ const [ld, ls, lo] = left.step(state.left, input);
517
+ const [rd, rs, ro] = right.step(state.right, input);
518
+ const cont = ld.continue && rd.continue;
519
+ const delay = Math.max(ld.delayMs, rd.delayMs);
520
+ return [{ continue: cont, delayMs: delay }, { left: ls, right: rs }, [lo, ro]];
521
+ }
522
+ };
523
+ }
524
+ function union(left, right) {
525
+ return {
526
+ _tag: "Schedule",
527
+ initial: () => ({ left: left.initial(), right: right.initial() }),
528
+ step: (state, input) => {
529
+ const [ld, ls, lo] = left.step(state.left, input);
530
+ const [rd, rs, ro] = right.step(state.right, input);
531
+ const cont = ld.continue || rd.continue;
532
+ const delay = Math.min(ld.delayMs, rd.delayMs);
533
+ return [{ continue: cont, delayMs: delay }, { left: ls, right: rs }, [lo, ro]];
534
+ }
535
+ };
536
+ }
537
+ function retryWithSchedule(effect, schedule) {
538
+ const loop = (state) => asyncFold(
539
+ effect,
540
+ (error) => {
541
+ const [decision, nextState, _output] = schedule.step(state, error);
542
+ if (!decision.continue) return asyncFail(error);
543
+ if (decision.delayMs <= 0) return loop(nextState);
544
+ return asyncFlatMap(sleep(decision.delayMs), () => loop(nextState));
545
+ },
546
+ (value) => asyncSucceed(value)
547
+ );
548
+ return loop(schedule.initial());
549
+ }
550
+ function repeatWithSchedule(effect, schedule) {
551
+ const loop = (state, lastValue) => {
552
+ const [decision, nextState, _output] = schedule.step(state, lastValue);
553
+ if (!decision.continue) return asyncSucceed(lastValue);
554
+ if (decision.delayMs <= 0) {
555
+ return asyncFold(
556
+ effect,
557
+ (error) => asyncFail(error),
558
+ (value) => loop(nextState, value)
559
+ );
560
+ }
561
+ return asyncFlatMap(
562
+ sleep(decision.delayMs),
563
+ () => asyncFold(
564
+ effect,
565
+ (error) => asyncFail(error),
566
+ (value) => loop(nextState, value)
567
+ )
568
+ );
569
+ };
570
+ return asyncFold(
571
+ effect,
572
+ (error) => asyncFail(error),
573
+ (value) => loop(schedule.initial(), value)
574
+ );
575
+ }
576
+
577
+ // src/core/runtime/shutdown.ts
578
+ async function gracefulShutdown(runtime, config = {}) {
579
+ const timeoutMs = config.timeoutMs ?? 3e4;
580
+ const startedAt = Date.now();
581
+ config.onStart?.();
582
+ let timedOut = false;
583
+ const shutdownPromise = (async () => {
584
+ try {
585
+ await runtime.shutdown();
586
+ } catch {
587
+ }
588
+ })();
589
+ const timeoutPromise = new Promise((resolve) => {
590
+ setTimeout(() => {
591
+ timedOut = true;
592
+ resolve();
593
+ }, timeoutMs);
594
+ });
595
+ await Promise.race([shutdownPromise, timeoutPromise]);
596
+ const completedAt = Date.now();
597
+ const stats = {
598
+ startedAt,
599
+ completedAt,
600
+ elapsedMs: completedAt - startedAt,
601
+ timedOut
602
+ };
603
+ if (timedOut) {
604
+ config.onTimeout?.(stats);
605
+ } else {
606
+ config.onComplete?.(stats);
607
+ }
608
+ return stats;
609
+ }
610
+ function registerShutdownHooks(runtime, config = {}) {
611
+ let shuttingDown = false;
612
+ const handler = (signal) => {
613
+ if (shuttingDown) {
614
+ process.exit(1);
615
+ }
616
+ shuttingDown = true;
617
+ console.log(`
618
+ [brass-runtime] Received ${signal}, shutting down gracefully...`);
619
+ gracefulShutdown(runtime, {
620
+ ...config,
621
+ onComplete: (stats) => {
622
+ config.onComplete?.(stats);
623
+ if (!config.onComplete) {
624
+ console.log(`[brass-runtime] Shutdown complete (${stats.elapsedMs}ms)`);
625
+ process.exit(0);
626
+ }
627
+ },
628
+ onTimeout: (stats) => {
629
+ config.onTimeout?.(stats);
630
+ if (!config.onTimeout) {
631
+ console.log(`[brass-runtime] Shutdown timed out after ${stats.elapsedMs}ms, forcing exit`);
632
+ process.exit(1);
633
+ }
634
+ }
635
+ });
636
+ };
637
+ process.on("SIGTERM", () => handler("SIGTERM"));
638
+ process.on("SIGINT", () => handler("SIGINT"));
639
+ return () => {
640
+ process.removeAllListeners("SIGTERM");
641
+ process.removeAllListeners("SIGINT");
642
+ };
643
+ }
644
+
645
+ // src/core/runtime/testing.ts
646
+ function makeTestRuntime(env, options) {
647
+ const runtime = Runtime.make(env ?? {});
648
+ const run = (effect) => runtime.toPromise(effect);
649
+ const runExit = (effect) => new Promise((resolve) => {
650
+ runtime.unsafeRunAsync(effect, resolve);
651
+ });
652
+ return { runtime, run, runExit };
653
+ }
654
+ async function assertSucceeds(effect, expected, runtime) {
655
+ const rt = runtime ?? Runtime.make({});
656
+ const exit = await new Promise((resolve) => {
657
+ rt.unsafeRunAsync(effect, resolve);
658
+ });
659
+ if (exit._tag !== "Success") {
660
+ throw new Error(`Expected success with ${JSON.stringify(expected)}, got failure: ${JSON.stringify(exit.cause)}`);
661
+ }
662
+ if (JSON.stringify(exit.value) !== JSON.stringify(expected)) {
663
+ throw new Error(`Expected ${JSON.stringify(expected)}, got ${JSON.stringify(exit.value)}`);
664
+ }
665
+ }
666
+ async function assertFails(effect, expectedError, runtime) {
667
+ const rt = runtime ?? Runtime.make({});
668
+ const exit = await new Promise((resolve) => {
669
+ rt.unsafeRunAsync(effect, resolve);
670
+ });
671
+ if (exit._tag !== "Failure") {
672
+ throw new Error(`Expected failure with ${JSON.stringify(expectedError)}, got success: ${JSON.stringify(exit.value)}`);
673
+ }
674
+ const error = exit.cause.error;
675
+ if (JSON.stringify(error) !== JSON.stringify(expectedError)) {
676
+ throw new Error(`Expected error ${JSON.stringify(expectedError)}, got ${JSON.stringify(error)}`);
677
+ }
678
+ }
679
+ async function assertFailsWith(effect, predicate, runtime) {
680
+ const rt = runtime ?? Runtime.make({});
681
+ const exit = await new Promise((resolve) => {
682
+ rt.unsafeRunAsync(effect, resolve);
683
+ });
684
+ if (exit._tag !== "Failure") {
685
+ throw new Error(`Expected failure, got success: ${JSON.stringify(exit.value)}`);
686
+ }
687
+ const error = exit.cause.error;
688
+ if (!predicate(error)) {
689
+ throw new Error(`Error did not match predicate: ${JSON.stringify(error)}`);
690
+ }
691
+ }
692
+ async function assertCompletesWithin(effect, maxMs, runtime) {
693
+ const rt = runtime ?? Runtime.make({});
694
+ const start = performance.now();
695
+ const result = await rt.toPromise(effect);
696
+ const elapsed2 = performance.now() - start;
697
+ if (elapsed2 > maxMs) {
698
+ throw new Error(`Effect took ${elapsed2.toFixed(1)}ms, expected < ${maxMs}ms`);
699
+ }
700
+ return result;
701
+ }
702
+ function flakyEffect(failCount, successValue, errorValue) {
703
+ let calls = 0;
704
+ return async((_env, cb) => {
705
+ calls++;
706
+ if (calls <= failCount) {
707
+ cb({ _tag: "Failure", cause: { _tag: "Fail", error: errorValue } });
708
+ } else {
709
+ cb({ _tag: "Success", value: successValue });
710
+ }
711
+ });
712
+ }
713
+ function delayedEffect(ms, value) {
714
+ return async((_env, cb) => {
715
+ const id = setTimeout(() => cb({ _tag: "Success", value }), ms);
716
+ return () => clearTimeout(id);
717
+ });
718
+ }
719
+ function neverEffect() {
720
+ return async(() => {
721
+ return () => {
722
+ };
723
+ });
724
+ }
725
+
726
+ // src/core/runtime/layer.ts
727
+ function layer(acquire, release) {
728
+ return {
729
+ _tag: "Layer",
730
+ build: (_deps) => asyncFlatMap(acquire(), (service) => asyncSucceed({
731
+ service,
732
+ release: release ? () => release(service) : () => unit()
733
+ }))
734
+ };
735
+ }
736
+ function layerFrom() {
737
+ return (acquire, release) => ({
738
+ _tag: "Layer",
739
+ build: (deps) => asyncFlatMap(acquire(deps), (service) => asyncSucceed({
740
+ service,
741
+ release: release ? () => release(service) : () => unit()
742
+ }))
743
+ });
744
+ }
745
+ function layerSucceed(value) {
746
+ return {
747
+ _tag: "Layer",
748
+ build: () => asyncSucceed({ service: value, release: () => unit() })
749
+ };
750
+ }
751
+ function layerFail(error) {
752
+ return {
753
+ _tag: "Layer",
754
+ build: () => asyncFail(error)
755
+ };
756
+ }
757
+ function compose(from, to) {
758
+ return {
759
+ _tag: "Layer",
760
+ build: (deps) => asyncFlatMap(
761
+ from.build(deps),
762
+ ({ service: mid, release: releaseMid }) => asyncFold(
763
+ to.build(mid),
764
+ (error) => asyncFlatMap(releaseMid(), () => asyncFail(error)),
765
+ ({ service: out, release: releaseOut }) => asyncSucceed({
766
+ service: out,
767
+ release: () => asyncFlatMap(releaseOut(), () => releaseMid())
768
+ })
769
+ )
770
+ )
771
+ };
772
+ }
773
+ function merge2(left, right) {
774
+ return {
775
+ _tag: "Layer",
776
+ build: (deps) => asyncFlatMap(
777
+ left.build(deps),
778
+ ({ service: a, release: releaseA }) => asyncFold(
779
+ right.build(deps),
780
+ (error) => asyncFlatMap(releaseA(), () => asyncFail(error)),
781
+ ({ service: b, release: releaseB }) => asyncSucceed({
782
+ service: { ...a, ...b },
783
+ release: () => asyncFlatMap(releaseB(), () => releaseA())
784
+ })
785
+ )
786
+ )
787
+ };
788
+ }
789
+ function mapLayer(l, f) {
790
+ return {
791
+ _tag: "Layer",
792
+ build: (deps) => asyncFlatMap(
793
+ l.build(deps),
794
+ ({ service, release }) => asyncSucceed({ service: f(service), release })
795
+ )
796
+ };
797
+ }
798
+ function provideLayer(l, use, deps) {
799
+ return asyncFlatMap(
800
+ l.build(deps ?? {}),
801
+ ({ service, release }) => asyncFold(
802
+ use(service),
803
+ (error) => asyncFlatMap(release(), () => asyncFail(error)),
804
+ (value) => asyncFlatMap(release(), () => asyncSucceed(value))
805
+ )
806
+ );
807
+ }
808
+
809
+ // src/core/runtime/workerPool.ts
810
+ function makeWorkerPool(config = {}) {
811
+ const size = config.size ?? 4;
812
+ const maxQueue = config.maxQueue ?? 1e3;
813
+ const taskTimeoutMs = config.taskTimeoutMs ?? 3e4;
814
+ let closed = false;
815
+ let busy = 0;
816
+ let completed = 0;
817
+ let failed = 0;
818
+ let timedOut = 0;
819
+ const queue = [];
820
+ const processNext = () => {
821
+ if (queue.length === 0 || busy >= size) return;
822
+ const task = queue.shift();
823
+ busy++;
824
+ setImmediate(() => {
825
+ if (task.timeoutId) clearTimeout(task.timeoutId);
826
+ try {
827
+ const result = task.fn();
828
+ busy--;
829
+ completed++;
830
+ task.resolve(result);
831
+ processNext();
832
+ } catch (e) {
833
+ busy--;
834
+ failed++;
835
+ task.reject({ _tag: "WorkerTaskError", message: String(e) });
836
+ processNext();
837
+ }
838
+ });
839
+ };
840
+ const execute = (fn) => {
841
+ if (closed) return asyncFail({ _tag: "WorkerPoolClosed" });
842
+ if (queue.length >= maxQueue) {
843
+ return asyncFail({ _tag: "WorkerPoolFull", queued: queue.length });
844
+ }
845
+ return async((_env, cb) => {
846
+ const task = {
847
+ fn,
848
+ resolve: (value) => cb({ _tag: "Success", value }),
849
+ reject: (error) => cb({ _tag: "Failure", cause: { _tag: "Fail", error } })
850
+ };
851
+ task.timeoutId = setTimeout(() => {
852
+ const idx = queue.indexOf(task);
853
+ if (idx >= 0) {
854
+ queue.splice(idx, 1);
855
+ timedOut++;
856
+ task.reject({ _tag: "WorkerTaskTimeout", ms: taskTimeoutMs });
857
+ }
858
+ }, taskTimeoutMs);
859
+ queue.push(task);
860
+ processNext();
861
+ return () => {
862
+ const idx = queue.indexOf(task);
863
+ if (idx >= 0) {
864
+ queue.splice(idx, 1);
865
+ if (task.timeoutId) clearTimeout(task.timeoutId);
866
+ }
867
+ };
868
+ });
869
+ };
870
+ const run = (taskSource, args = []) => {
871
+ return execute(() => {
872
+ const fn = new Function(...args.map((_, i) => `arg${i}`), taskSource);
873
+ return fn(...args);
874
+ });
875
+ };
876
+ return {
877
+ execute,
878
+ run,
879
+ stats: () => ({
880
+ size,
881
+ busy,
882
+ idle: size - busy,
883
+ queued: queue.length,
884
+ completed,
885
+ failed,
886
+ timedOut
887
+ }),
888
+ shutdown: async () => {
889
+ closed = true;
890
+ while (queue.length > 0) {
891
+ const task = queue.shift();
892
+ if (task.timeoutId) clearTimeout(task.timeoutId);
893
+ task.reject({ _tag: "WorkerPoolClosed" });
894
+ }
895
+ }
896
+ };
897
+ }
898
+
899
+ // src/core/runtime/tracing.ts
900
+ var idCounter = 0;
901
+ function generateId() {
902
+ return (++idCounter).toString(16).padStart(16, "0");
903
+ }
904
+ function makeTracer(config) {
905
+ const completedSpans = [];
906
+ const sampleRate = config.sampleRate ?? 1;
907
+ const shouldSample = () => {
908
+ if (sampleRate >= 1) return true;
909
+ if (sampleRate <= 0) return false;
910
+ return Math.random() < sampleRate;
911
+ };
912
+ const span = (name, effect, attributes) => {
913
+ if (!shouldSample()) return effect;
914
+ const spanObj = {
915
+ name,
916
+ context: {
917
+ traceId: generateId(),
918
+ spanId: generateId()
919
+ },
920
+ startTime: performance.now(),
921
+ status: "unset",
922
+ attributes: { "service.name": config.serviceName, ...attributes },
923
+ events: []
924
+ };
925
+ return asyncFold(
926
+ effect,
927
+ (error) => {
928
+ spanObj.endTime = performance.now();
929
+ spanObj.status = "error";
930
+ spanObj.events.push({
931
+ name: "error",
932
+ time: performance.now(),
933
+ attributes: { "error.message": String(error) }
934
+ });
935
+ completedSpans.push(spanObj);
936
+ config.onSpanEnd?.(spanObj);
937
+ return asyncFail(error);
938
+ },
939
+ (value) => {
940
+ spanObj.endTime = performance.now();
941
+ spanObj.status = "ok";
942
+ completedSpans.push(spanObj);
943
+ config.onSpanEnd?.(spanObj);
944
+ return asyncSucceed(value);
945
+ }
946
+ );
947
+ };
948
+ return {
949
+ span,
950
+ spans: () => completedSpans,
951
+ clear: () => {
952
+ completedSpans.length = 0;
953
+ }
954
+ };
955
+ }
956
+
957
+ // src/core/runtime/metrics.ts
958
+ var DEFAULT_BOUNDARIES = [1, 5, 10, 25, 50, 100, 250, 500, 1e3, 5e3, 1e4];
959
+ function makeMetrics() {
960
+ const counters = /* @__PURE__ */ new Map();
961
+ const gauges = /* @__PURE__ */ new Map();
962
+ const histograms = /* @__PURE__ */ new Map();
963
+ const key = (name, labels) => labels ? `${name}|${Object.entries(labels).sort().map(([k, v]) => `${k}=${v}`).join(",")}` : name;
964
+ const counter = (name, labels = {}) => {
965
+ const k = key(name, labels);
966
+ if (!counters.has(k)) counters.set(k, { labels, value: 0 });
967
+ const entry = counters.get(k);
968
+ return {
969
+ increment: (n = 1) => {
970
+ entry.value += Math.max(0, n);
971
+ },
972
+ value: () => entry.value
973
+ };
974
+ };
975
+ const gauge = (name, labels = {}) => {
976
+ const k = key(name, labels);
977
+ if (!gauges.has(k)) gauges.set(k, { labels, value: 0 });
978
+ const entry = gauges.get(k);
979
+ return {
980
+ set: (v) => {
981
+ entry.value = v;
982
+ },
983
+ increment: (n = 1) => {
984
+ entry.value += n;
985
+ },
986
+ decrement: (n = 1) => {
987
+ entry.value -= n;
988
+ },
989
+ value: () => entry.value
990
+ };
991
+ };
992
+ const histogram = (name, boundaries = DEFAULT_BOUNDARIES, labels = {}) => {
993
+ const k = key(name, labels);
994
+ if (!histograms.has(k)) {
995
+ const sorted = [...boundaries].sort((a, b) => a - b);
996
+ histograms.set(k, {
997
+ labels,
998
+ boundaries: sorted,
999
+ data: { boundaries: sorted, counts: new Array(sorted.length + 1).fill(0), sum: 0, count: 0, min: Infinity, max: -Infinity }
1000
+ });
1001
+ }
1002
+ const entry = histograms.get(k);
1003
+ return {
1004
+ observe: (value) => {
1005
+ entry.data.sum += value;
1006
+ entry.data.count++;
1007
+ entry.data.min = Math.min(entry.data.min, value);
1008
+ entry.data.max = Math.max(entry.data.max, value);
1009
+ let placed = false;
1010
+ for (let i = 0; i < entry.boundaries.length; i++) {
1011
+ if (value <= entry.boundaries[i]) {
1012
+ entry.data.counts[i]++;
1013
+ placed = true;
1014
+ break;
1015
+ }
1016
+ }
1017
+ if (!placed) entry.data.counts[entry.boundaries.length]++;
1018
+ },
1019
+ buckets: () => ({ ...entry.data }),
1020
+ percentile: (p) => {
1021
+ const target = Math.ceil(entry.data.count * (p / 100));
1022
+ let cumulative = 0;
1023
+ for (let i = 0; i < entry.boundaries.length; i++) {
1024
+ cumulative += entry.data.counts[i];
1025
+ if (cumulative >= target) return entry.boundaries[i];
1026
+ }
1027
+ return entry.data.max;
1028
+ }
1029
+ };
1030
+ };
1031
+ return {
1032
+ counter,
1033
+ gauge,
1034
+ histogram,
1035
+ snapshot: () => ({
1036
+ counters: Array.from(counters.entries()).map(([k, v]) => ({ name: k.split("|")[0], labels: v.labels, value: v.value })),
1037
+ gauges: Array.from(gauges.entries()).map(([k, v]) => ({ name: k.split("|")[0], labels: v.labels, value: v.value })),
1038
+ histograms: Array.from(histograms.entries()).map(([k, v]) => ({ name: k.split("|")[0], labels: v.labels, buckets: v.data }))
1039
+ }),
1040
+ reset: () => {
1041
+ counters.clear();
1042
+ gauges.clear();
1043
+ histograms.clear();
1044
+ }
1045
+ };
1046
+ }
1047
+
1048
+ // src/core/types/typedError.ts
1049
+ function catchTag(effect, tag, handler) {
1050
+ return asyncFold(
1051
+ effect,
1052
+ (error) => {
1053
+ if (typeof error === "object" && error !== null && "_tag" in error && error._tag === tag) {
1054
+ return handler(error);
1055
+ }
1056
+ return asyncFail(error);
1057
+ },
1058
+ (value) => asyncSucceed(value)
1059
+ );
1060
+ }
1061
+ function catchTags(effect, handlers) {
1062
+ return asyncFold(
1063
+ effect,
1064
+ (error) => {
1065
+ if (typeof error === "object" && error !== null && "_tag" in error) {
1066
+ const handler = handlers[error._tag];
1067
+ if (handler) return handler(error);
1068
+ }
1069
+ return asyncFail(error);
1070
+ },
1071
+ (value) => asyncSucceed(value)
1072
+ );
1073
+ }
1074
+ function mapError2(effect, f) {
1075
+ return asyncFold(
1076
+ effect,
1077
+ (error) => asyncFail(f(error)),
1078
+ (value) => asyncSucceed(value)
1079
+ );
1080
+ }
1081
+ function tagError(effect, tag, enrich) {
1082
+ return asyncFold(
1083
+ effect,
1084
+ (error) => {
1085
+ const fields = enrich ? enrich(error) : {};
1086
+ return asyncFail({ _tag: tag, ...fields });
1087
+ },
1088
+ (value) => asyncSucceed(value)
1089
+ );
1090
+ }
1091
+ function orElse(effect, fallback) {
1092
+ return asyncFold(
1093
+ effect,
1094
+ (error) => fallback(error),
1095
+ (value) => asyncSucceed(value)
1096
+ );
1097
+ }
1098
+
166
1099
  // src/core/stream/queue.ts
167
1100
  function bounded(capacity, strategy = "backpressure", options = {}) {
168
1101
  return asyncSync(() => makeQueue(capacity, strategy, options));
@@ -250,6 +1183,61 @@ function makeQueue(capacity, strategy, options) {
250
1183
  takers.remove(node);
251
1184
  };
252
1185
  return canceler;
1186
+ }),
1187
+ offerBatch: (values) => asyncSync(() => {
1188
+ const results = [];
1189
+ for (let i = 0; i < values.length; i++) {
1190
+ if (closed) {
1191
+ results.push(false);
1192
+ continue;
1193
+ }
1194
+ const a = values[i];
1195
+ if (takers.length > 0) {
1196
+ const t = takers.shift();
1197
+ t({ _tag: "Success", value: a });
1198
+ results.push(true);
1199
+ continue;
1200
+ }
1201
+ if (items.length < capacity) {
1202
+ items.push(a);
1203
+ results.push(true);
1204
+ continue;
1205
+ }
1206
+ if (strategy === "dropping") {
1207
+ results.push(false);
1208
+ } else if (strategy === "sliding") {
1209
+ items.shift();
1210
+ items.push(a);
1211
+ results.push(true);
1212
+ } else {
1213
+ results.push(false);
1214
+ }
1215
+ }
1216
+ return results;
1217
+ }),
1218
+ takeBatch: (n) => asyncSync(() => {
1219
+ const results = [];
1220
+ const count = Math.min(n, items.length + offerWaiters.length);
1221
+ for (let i = 0; i < count; i++) {
1222
+ if (items.length > 0) {
1223
+ results.push(items.shift());
1224
+ if (offerWaiters.length > 0 && items.length < capacity) {
1225
+ const w = offerWaiters.shift();
1226
+ items.push(w.a);
1227
+ w.cb(true);
1228
+ }
1229
+ } else if (offerWaiters.length > 0) {
1230
+ const w = offerWaiters.shift();
1231
+ w.cb(true);
1232
+ results.push(w.a);
1233
+ } else {
1234
+ break;
1235
+ }
1236
+ }
1237
+ if (results.length === 0 && closed) {
1238
+ throw QueueClosedErr;
1239
+ }
1240
+ return results;
253
1241
  })
254
1242
  };
255
1243
  }
@@ -431,14 +1419,12 @@ function resolveWasmChunkBuffer() {
431
1419
  cachedWasmChunkCtor = mod?.BrassWasmChunkBuffer ?? null;
432
1420
  return cachedWasmChunkCtor;
433
1421
  }
434
- var JsChunker = class {
435
- constructor(maxChunkSize, fallbackUsed = false) {
1422
+ var TsChunker = class {
1423
+ constructor(maxChunkSize) {
436
1424
  this.maxChunkSize = maxChunkSize;
437
- this.fallbackUsed = fallbackUsed;
438
1425
  }
439
1426
  maxChunkSize;
440
- fallbackUsed;
441
- engine = "js";
1427
+ engine = "ts";
442
1428
  values = [];
443
1429
  emittedChunks = 0;
444
1430
  emittedItems = 0;
@@ -472,8 +1458,8 @@ var JsChunker = class {
472
1458
  }
473
1459
  stats() {
474
1460
  return {
475
- engine: "js",
476
- fallbackUsed: this.fallbackUsed,
1461
+ engine: "ts",
1462
+ fallbackUsed: false,
477
1463
  data: {
478
1464
  len: this.values.length,
479
1465
  maxChunkSize: this.maxChunkSize,
@@ -522,10 +1508,10 @@ var WasmChunker = class {
522
1508
  };
523
1509
  function makeStreamChunker(chunkSize, options = {}) {
524
1510
  const size = Math.max(1, chunkSize | 0);
525
- const engine = options.engine ?? "auto";
526
- if (engine === "js") return new JsChunker(size, false);
1511
+ const engine = options.engine ?? "ts";
1512
+ if (engine === "ts") return new TsChunker(size);
527
1513
  if (engine === "wasm") return new WasmChunker(size);
528
- return resolveWasmChunkBuffer() ? new WasmChunker(size) : new JsChunker(size, true);
1514
+ throw new Error(`brass-runtime stream chunk engine must be 'ts' or 'wasm'; received '${String(engine)}'`);
529
1515
  }
530
1516
  function chunks(input, chunkSize, options = {}) {
531
1517
  const size = Math.max(1, chunkSize | 0);
@@ -591,21 +1577,430 @@ function mapChunksEffect(chunkSize, f, options = {}) {
591
1577
  });
592
1578
  }
593
1579
 
1580
+ // src/core/stream/fusion.ts
1581
+ var _fusionEnabled = true;
1582
+ var _fusionVerbose = false;
1583
+ function setFusionEnabled(enabled) {
1584
+ _fusionEnabled = enabled;
1585
+ }
1586
+ function isFusionEnabled() {
1587
+ return _fusionEnabled;
1588
+ }
1589
+ function setFusionVerbose(verbose) {
1590
+ _fusionVerbose = verbose;
1591
+ }
1592
+ function isFusionVerbose() {
1593
+ return _fusionVerbose;
1594
+ }
1595
+ function getStats(pipeline) {
1596
+ const p = pipeline;
1597
+ if (p._fusedSteps && Array.isArray(p._fusedSteps)) {
1598
+ const metas = p._fusedSteps;
1599
+ return buildStats(metas);
1600
+ }
1601
+ if (p[PURE_PIPELINE_TAG]) {
1602
+ return null;
1603
+ }
1604
+ return null;
1605
+ }
1606
+ var PURE_PIPELINE_TAG = /* @__PURE__ */ Symbol("brass:pure-pipeline");
1607
+ function makeMapStep(fn) {
1608
+ return (a, _state) => ({ tag: "emit", value: fn(a) });
1609
+ }
1610
+ function makeFilterStep(pred) {
1611
+ return (a, _state) => pred(a) ? { tag: "emit", value: a } : { tag: "skip" };
1612
+ }
1613
+ function makeTakeStep(n, counterIndex) {
1614
+ return (a, state) => {
1615
+ if (state.counters[counterIndex] >= n) {
1616
+ return { tag: "halt" };
1617
+ }
1618
+ state.counters[counterIndex]++;
1619
+ return { tag: "emit", value: a };
1620
+ };
1621
+ }
1622
+ function makeDropStep(n, counterIndex) {
1623
+ return (a, state) => {
1624
+ if (state.counters[counterIndex] < n) {
1625
+ state.counters[counterIndex]++;
1626
+ return { tag: "skip" };
1627
+ }
1628
+ return { tag: "emit", value: a };
1629
+ };
1630
+ }
1631
+ function initState(counterCount) {
1632
+ return () => ({
1633
+ counters: new Array(counterCount).fill(0)
1634
+ });
1635
+ }
1636
+ function composeSteps(step1, step2) {
1637
+ return (a, state) => {
1638
+ const r1 = step1(a, state);
1639
+ if (r1.tag !== "emit") return r1;
1640
+ return step2(r1.value, state);
1641
+ };
1642
+ }
1643
+ function getPureTag(pipeline) {
1644
+ const tagged = pipeline;
1645
+ return tagged[PURE_PIPELINE_TAG] ?? null;
1646
+ }
1647
+ function getFusedSteps(pipeline) {
1648
+ const p = pipeline;
1649
+ if (p._fusedSteps && Array.isArray(p._fusedSteps)) {
1650
+ return p._fusedSteps;
1651
+ }
1652
+ return null;
1653
+ }
1654
+ function buildStepFromMetadata(meta, counterIndex) {
1655
+ switch (meta.kind) {
1656
+ case "map":
1657
+ return makeMapStep(meta.fn);
1658
+ case "filter":
1659
+ return makeFilterStep(meta.pred);
1660
+ case "take":
1661
+ return makeTakeStep(meta.n, counterIndex);
1662
+ case "drop":
1663
+ return makeDropStep(meta.n, counterIndex);
1664
+ }
1665
+ }
1666
+ function buildStats(metas) {
1667
+ const steps = metas.map((m) => {
1668
+ switch (m.kind) {
1669
+ case "map":
1670
+ return { kind: "map" };
1671
+ case "filter":
1672
+ return { kind: "filter" };
1673
+ case "take":
1674
+ return { kind: "take", n: m.n };
1675
+ case "drop":
1676
+ return { kind: "drop", n: m.n };
1677
+ }
1678
+ });
1679
+ return {
1680
+ fusedSteps: steps.length,
1681
+ steps,
1682
+ hasTake: metas.some((m) => m.kind === "take"),
1683
+ hasDrop: metas.some((m) => m.kind === "drop")
1684
+ };
1685
+ }
1686
+ function countCounters(metas) {
1687
+ let count = 0;
1688
+ for (const m of metas) {
1689
+ if (m.kind === "take" || m.kind === "drop") {
1690
+ count++;
1691
+ }
1692
+ }
1693
+ return count;
1694
+ }
1695
+ function fuse(pipeline, options) {
1696
+ const verbose = options?.verbose ?? _fusionVerbose;
1697
+ if (options?.enabled === false || !_fusionEnabled && options?.enabled !== true) {
1698
+ if (verbose) {
1699
+ console.log("[FusionEngine] Fusion disabled by options");
1700
+ }
1701
+ return null;
1702
+ }
1703
+ const metas = collectMetadata(pipeline);
1704
+ if (!metas || metas.length === 0) {
1705
+ if (verbose) {
1706
+ console.log("[FusionEngine] Pipeline is not fusable (no pure tags detected)");
1707
+ }
1708
+ return null;
1709
+ }
1710
+ if (verbose) {
1711
+ console.log(
1712
+ `[FusionEngine] Fusing ${metas.length} steps: ${metas.map((m) => m.kind).join(" \u2192 ")}`
1713
+ );
1714
+ }
1715
+ let counterIndex = 0;
1716
+ let composedStep = buildStepFromMetadata(
1717
+ metas[0],
1718
+ metas[0].kind === "take" || metas[0].kind === "drop" ? counterIndex++ : -1
1719
+ );
1720
+ for (let i = 1; i < metas.length; i++) {
1721
+ const meta = metas[i];
1722
+ const idx = meta.kind === "take" || meta.kind === "drop" ? counterIndex++ : -1;
1723
+ composedStep = composeSteps(composedStep, buildStepFromMetadata(meta, idx));
1724
+ }
1725
+ const counterCount = countCounters(metas);
1726
+ const stats = buildStats(metas);
1727
+ return {
1728
+ _tag: "FusedPipeline",
1729
+ step: composedStep,
1730
+ initState: initState(counterCount),
1731
+ stats
1732
+ };
1733
+ }
1734
+ function collectMetadata(pipeline) {
1735
+ const fusedSteps = getFusedSteps(pipeline);
1736
+ if (fusedSteps) {
1737
+ return fusedSteps;
1738
+ }
1739
+ const tag = getPureTag(pipeline);
1740
+ if (tag) {
1741
+ return [tag];
1742
+ }
1743
+ return null;
1744
+ }
1745
+ function runFusedArray(input, fused) {
1746
+ const state = fused.initState();
1747
+ const output = [];
1748
+ for (let i = 0; i < input.length; i++) {
1749
+ const result = fused.step(input[i], state);
1750
+ switch (result.tag) {
1751
+ case "emit":
1752
+ output.push(result.value);
1753
+ break;
1754
+ case "skip":
1755
+ break;
1756
+ case "halt":
1757
+ return output;
1758
+ }
1759
+ }
1760
+ return output;
1761
+ }
1762
+ function drainStreamSync(stream) {
1763
+ const result = [];
1764
+ let cur = stream;
1765
+ while (true) {
1766
+ switch (cur._tag) {
1767
+ case "Empty":
1768
+ return result;
1769
+ case "FromArray": {
1770
+ const arr = cur.values;
1771
+ for (let i = 0; i < arr.length; i++) {
1772
+ result.push(arr[i]);
1773
+ }
1774
+ return result;
1775
+ }
1776
+ case "Emit": {
1777
+ const zio = cur.value;
1778
+ if (zio._tag === "Succeed") {
1779
+ result.push(zio.value);
1780
+ return result;
1781
+ }
1782
+ return null;
1783
+ }
1784
+ case "Concat": {
1785
+ const leftItems = drainStreamSync(cur.left);
1786
+ if (leftItems === null) return null;
1787
+ for (let i = 0; i < leftItems.length; i++) {
1788
+ result.push(leftItems[i]);
1789
+ }
1790
+ cur = cur.right;
1791
+ break;
1792
+ }
1793
+ default:
1794
+ return null;
1795
+ }
1796
+ }
1797
+ }
1798
+ function applyFused(stream, fused) {
1799
+ const inputArray = drainStreamSync(stream);
1800
+ if (inputArray !== null) {
1801
+ const outputArray = runFusedArray(inputArray, fused);
1802
+ return arrayToStream(outputArray);
1803
+ }
1804
+ const state = fused.initState();
1805
+ const loop = (cur) => fromPull(
1806
+ asyncFold(
1807
+ uncons(cur),
1808
+ // End-of-stream or error: propagate
1809
+ (opt) => asyncFail(opt),
1810
+ ([a, tail]) => {
1811
+ const result = fused.step(a, state);
1812
+ switch (result.tag) {
1813
+ case "emit":
1814
+ return asyncSucceed([result.value, loop(tail)]);
1815
+ case "skip":
1816
+ return uncons(loop(tail));
1817
+ case "halt":
1818
+ return asyncFail(none);
1819
+ }
1820
+ }
1821
+ )
1822
+ );
1823
+ return loop(stream);
1824
+ }
1825
+ function arrayToStream(values) {
1826
+ if (values.length === 0) return { _tag: "Empty" };
1827
+ return { _tag: "FromArray", values };
1828
+ }
1829
+ function serializeFusedPipeline(pipeline) {
1830
+ const p = pipeline;
1831
+ let metas = null;
1832
+ if (p._fusedSteps && Array.isArray(p._fusedSteps)) {
1833
+ metas = p._fusedSteps;
1834
+ } else if (p[PURE_PIPELINE_TAG]) {
1835
+ return null;
1836
+ }
1837
+ if (!metas || metas.length === 0) {
1838
+ return null;
1839
+ }
1840
+ const steps = metas.map((meta) => {
1841
+ switch (meta.kind) {
1842
+ case "map":
1843
+ return { kind: "map", fnSource: meta.fn.toString() };
1844
+ case "filter":
1845
+ return { kind: "filter", predSource: meta.pred.toString() };
1846
+ case "take":
1847
+ return { kind: "take", n: meta.n };
1848
+ case "drop":
1849
+ return { kind: "drop", n: meta.n };
1850
+ }
1851
+ });
1852
+ return { version: 1, steps };
1853
+ }
1854
+ function deserializeFusedPipeline(serialized) {
1855
+ try {
1856
+ if (serialized.version !== 1) {
1857
+ return null;
1858
+ }
1859
+ if (!serialized.steps || serialized.steps.length === 0) {
1860
+ return null;
1861
+ }
1862
+ const metas = [];
1863
+ for (const step of serialized.steps) {
1864
+ switch (step.kind) {
1865
+ case "map": {
1866
+ const fn = new Function("return " + step.fnSource)();
1867
+ if (typeof fn !== "function") return null;
1868
+ metas.push({ kind: "map", fn });
1869
+ break;
1870
+ }
1871
+ case "filter": {
1872
+ const pred = new Function("return " + step.predSource)();
1873
+ if (typeof pred !== "function") return null;
1874
+ metas.push({ kind: "filter", pred });
1875
+ break;
1876
+ }
1877
+ case "take": {
1878
+ if (typeof step.n !== "number" || step.n < 0) return null;
1879
+ metas.push({ kind: "take", n: step.n });
1880
+ break;
1881
+ }
1882
+ case "drop": {
1883
+ if (typeof step.n !== "number" || step.n < 0) return null;
1884
+ metas.push({ kind: "drop", n: step.n });
1885
+ break;
1886
+ }
1887
+ default:
1888
+ return null;
1889
+ }
1890
+ }
1891
+ const carrier = createDeserializedCarrier(metas);
1892
+ return carrier;
1893
+ } catch {
1894
+ return null;
1895
+ }
1896
+ }
1897
+ function createDeserializedCarrier(metas) {
1898
+ let counterIndex = 0;
1899
+ let composedStep = buildStepFromMetadata(
1900
+ metas[0],
1901
+ metas[0].kind === "take" || metas[0].kind === "drop" ? counterIndex++ : -1
1902
+ );
1903
+ for (let i = 1; i < metas.length; i++) {
1904
+ const meta = metas[i];
1905
+ const idx = meta.kind === "take" || meta.kind === "drop" ? counterIndex++ : -1;
1906
+ composedStep = composeSteps(composedStep, buildStepFromMetadata(meta, idx));
1907
+ }
1908
+ const counterCount = countCounters(metas);
1909
+ const stats = buildStats(metas);
1910
+ const fusedRepr = {
1911
+ _tag: "FusedPipeline",
1912
+ step: composedStep,
1913
+ initState: initState(counterCount),
1914
+ stats
1915
+ };
1916
+ const pipeline = ((input) => {
1917
+ return applyFused(input, fusedRepr);
1918
+ });
1919
+ pipeline._fusedSteps = metas;
1920
+ return pipeline;
1921
+ }
1922
+
594
1923
  // src/core/stream/pipeline.ts
595
1924
  function via(stream, pipeline) {
1925
+ if (isFusionEnabled()) {
1926
+ const p = pipeline;
1927
+ if (p._fusedSteps || p[PURE_PIPELINE_TAG]) {
1928
+ let fusedRepr = p._cachedFusedRepr;
1929
+ if (!fusedRepr) {
1930
+ fusedRepr = fuse(pipeline);
1931
+ if (fusedRepr) p._cachedFusedRepr = fusedRepr;
1932
+ }
1933
+ if (fusedRepr) {
1934
+ return applyFused(stream, fusedRepr);
1935
+ }
1936
+ }
1937
+ }
596
1938
  return pipeline(stream);
597
1939
  }
598
- function andThen(p1, p2) {
1940
+ function andThen2(p1, p2) {
1941
+ const fused = tryFuse(p1, p2);
1942
+ if (fused) return fused;
599
1943
  return ((input) => p2(p1(input)));
600
1944
  }
601
- function compose(p2, p1) {
602
- return andThen(p1, p2);
1945
+ function collectPureMetas(pipeline) {
1946
+ const p = pipeline;
1947
+ if (p._fusedSteps && Array.isArray(p._fusedSteps)) {
1948
+ return p._fusedSteps;
1949
+ }
1950
+ const tag = p[PURE_PIPELINE_TAG];
1951
+ if (tag) {
1952
+ return [tag];
1953
+ }
1954
+ return null;
1955
+ }
1956
+ function tryFuse(p1, p2) {
1957
+ if (!isFusionEnabled()) {
1958
+ if (isFusionVerbose()) {
1959
+ console.log("[FusionEngine] andThen: fusion globally disabled, skipping");
1960
+ }
1961
+ return null;
1962
+ }
1963
+ const metas1 = collectPureMetas(p1);
1964
+ const metas2 = collectPureMetas(p2);
1965
+ if (!metas1 || !metas2) {
1966
+ if (isFusionVerbose()) {
1967
+ const reason = !metas1 && !metas2 ? "neither operand is pure" : !metas1 ? "left operand is not pure" : "right operand is not pure";
1968
+ console.log(`[FusionEngine] andThen: cannot fuse \u2014 ${reason}`);
1969
+ }
1970
+ return null;
1971
+ }
1972
+ const combinedMetas = [...metas1, ...metas2];
1973
+ const fusedRepr = fuse(
1974
+ createMetadataCarrier(combinedMetas)
1975
+ );
1976
+ if (!fusedRepr) {
1977
+ return null;
1978
+ }
1979
+ if (isFusionVerbose()) {
1980
+ console.log(
1981
+ `[FusionEngine] andThen: fused ${combinedMetas.length} steps: ${combinedMetas.map((m) => m.kind).join(" \u2192 ")}`
1982
+ );
1983
+ }
1984
+ const fusedPipeline = ((input) => {
1985
+ return applyFused(input, fusedRepr);
1986
+ });
1987
+ fusedPipeline._fusedSteps = combinedMetas;
1988
+ return fusedPipeline;
1989
+ }
1990
+ function createMetadataCarrier(metas) {
1991
+ const carrier = (() => {
1992
+ });
1993
+ carrier._fusedSteps = metas;
1994
+ return carrier;
1995
+ }
1996
+ function compose2(p2, p1) {
1997
+ return andThen2(p1, p2);
603
1998
  }
604
1999
  function identity() {
605
2000
  return ((input) => input);
606
2001
  }
607
2002
  function mapP(f) {
608
- return ((input) => {
2003
+ const pipeline = ((input) => {
609
2004
  const onError = (opt) => asyncFail(opt);
610
2005
  const onSuccess = ([a, tail]) => asyncSucceed([f(a), loop(tail)]);
611
2006
  const loop = (cur) => fromPull(
@@ -613,15 +2008,19 @@ function mapP(f) {
613
2008
  );
614
2009
  return loop(input);
615
2010
  });
2011
+ pipeline[PURE_PIPELINE_TAG] = { kind: "map", fn: f };
2012
+ return pipeline;
616
2013
  }
617
2014
  function filterP(pred) {
618
- return ((input) => {
2015
+ const pipeline = ((input) => {
619
2016
  const onError = (opt) => asyncFail(opt);
620
2017
  const onSuccess = ([a, tail]) => pred(a) ? asyncSucceed([a, loop(tail)]) : next(tail);
621
2018
  const next = (cur) => asyncFold(uncons(cur), onError, onSuccess);
622
2019
  const loop = (cur) => fromPull(next(cur));
623
2020
  return loop(input);
624
2021
  });
2022
+ pipeline[PURE_PIPELINE_TAG] = { kind: "filter", pred };
2023
+ return pipeline;
625
2024
  }
626
2025
  function filterMapP(f) {
627
2026
  return ((input) => {
@@ -640,7 +2039,7 @@ function filterMapP(f) {
640
2039
  }
641
2040
  function takeP(n) {
642
2041
  const m = Math.max(0, n | 0);
643
- return ((input) => {
2042
+ const pipeline = ((input) => {
644
2043
  const loop = (cur, remaining) => {
645
2044
  if (remaining <= 0) return emptyStream();
646
2045
  return fromPull(
@@ -653,10 +2052,12 @@ function takeP(n) {
653
2052
  };
654
2053
  return loop(input, m);
655
2054
  });
2055
+ pipeline[PURE_PIPELINE_TAG] = { kind: "take", n: m };
2056
+ return pipeline;
656
2057
  }
657
2058
  function dropP(n) {
658
2059
  const m = Math.max(0, n | 0);
659
- return ((input) => {
2060
+ const pipeline = ((input) => {
660
2061
  const skip = (cur, remaining) => {
661
2062
  if (remaining <= 0) return cur;
662
2063
  return fromPull(
@@ -669,6 +2070,8 @@ function dropP(n) {
669
2070
  };
670
2071
  return skip(input, m);
671
2072
  });
2073
+ pipeline[PURE_PIPELINE_TAG] = { kind: "drop", n: m };
2074
+ return pipeline;
672
2075
  }
673
2076
  function mapEffectP(f) {
674
2077
  return ((input) => {
@@ -731,25 +2134,187 @@ function groupedP(n) {
731
2134
  });
732
2135
  }
733
2136
 
2137
+ // src/core/stream/operators.ts
2138
+ function throttle(stream, intervalMs) {
2139
+ let lastEmitTime = 0;
2140
+ const loop = (cur) => fromPull(
2141
+ asyncFold(
2142
+ uncons(cur),
2143
+ (opt) => asyncFail(opt),
2144
+ ([a, tail]) => {
2145
+ const now = Date.now();
2146
+ if (now - lastEmitTime >= intervalMs) {
2147
+ lastEmitTime = now;
2148
+ return asyncSucceed([a, loop(tail)]);
2149
+ }
2150
+ return uncons(loop(tail));
2151
+ }
2152
+ )
2153
+ );
2154
+ return loop(stream);
2155
+ }
2156
+ function debounce(stream, delayMs) {
2157
+ return fromPull(
2158
+ async((_env, cb) => {
2159
+ let lastValue;
2160
+ let hasValue = false;
2161
+ let timerId;
2162
+ let done = false;
2163
+ let tail = stream;
2164
+ const pullNext = () => {
2165
+ if (done) return;
2166
+ const pull = uncons(tail);
2167
+ pull(_env, (exit) => {
2168
+ if (done) return;
2169
+ if (exit._tag === "Failure") {
2170
+ if (hasValue) {
2171
+ const value = lastValue;
2172
+ hasValue = false;
2173
+ clearTimeout(timerId);
2174
+ cb({ _tag: "Success", value: [value, emptyStream()] });
2175
+ } else {
2176
+ cb(exit);
2177
+ }
2178
+ return;
2179
+ }
2180
+ const [a, nextTail] = exit.value;
2181
+ tail = nextTail;
2182
+ lastValue = a;
2183
+ hasValue = true;
2184
+ clearTimeout(timerId);
2185
+ timerId = setTimeout(() => {
2186
+ if (done) return;
2187
+ const value = lastValue;
2188
+ hasValue = false;
2189
+ done = true;
2190
+ cb({ _tag: "Success", value: [value, debounce(tail, delayMs)] });
2191
+ }, delayMs);
2192
+ pullNext();
2193
+ });
2194
+ };
2195
+ pullNext();
2196
+ return () => {
2197
+ done = true;
2198
+ clearTimeout(timerId);
2199
+ };
2200
+ })
2201
+ );
2202
+ }
2203
+ function zip2(left, right) {
2204
+ const loop = (l, r) => fromPull(
2205
+ asyncFold(
2206
+ uncons(l),
2207
+ (opt) => asyncFail(opt),
2208
+ ([a, lTail]) => asyncFold(
2209
+ uncons(r),
2210
+ (opt) => asyncFail(opt),
2211
+ ([b, rTail]) => asyncSucceed([[a, b], loop(lTail, rTail)])
2212
+ )
2213
+ )
2214
+ );
2215
+ return loop(left, right);
2216
+ }
2217
+ function zipWith(left, right, f) {
2218
+ const loop = (l, r) => fromPull(
2219
+ asyncFold(
2220
+ uncons(l),
2221
+ (opt) => asyncFail(opt),
2222
+ ([a, lTail]) => asyncFold(
2223
+ uncons(r),
2224
+ (opt) => asyncFail(opt),
2225
+ ([b, rTail]) => asyncSucceed([f(a, b), loop(lTail, rTail)])
2226
+ )
2227
+ )
2228
+ );
2229
+ return loop(left, right);
2230
+ }
2231
+ function scan(stream, initial, f) {
2232
+ const loop = (cur, acc) => fromPull(
2233
+ asyncFold(
2234
+ uncons(cur),
2235
+ (opt) => asyncFail(opt),
2236
+ ([a, tail]) => {
2237
+ const next = f(acc, a);
2238
+ return asyncSucceed([next, loop(tail, next)]);
2239
+ }
2240
+ )
2241
+ );
2242
+ return concatStream(
2243
+ emitStream(succeed(initial)),
2244
+ loop(stream, initial)
2245
+ );
2246
+ }
2247
+ function interleave(left, right) {
2248
+ const loop = (l, r, pickLeft) => fromPull(
2249
+ asyncFold(
2250
+ uncons(pickLeft ? l : r),
2251
+ // Current stream ended — drain the other
2252
+ (_opt) => uncons(pickLeft ? r : l),
2253
+ ([a, tail]) => {
2254
+ const nextL = pickLeft ? tail : l;
2255
+ const nextR = pickLeft ? r : tail;
2256
+ return asyncSucceed([a, loop(nextL, nextR, !pickLeft)]);
2257
+ }
2258
+ )
2259
+ );
2260
+ return loop(left, right, true);
2261
+ }
2262
+ function take2(stream, n) {
2263
+ if (n <= 0) return emptyStream();
2264
+ const loop = (cur, remaining) => {
2265
+ if (remaining <= 0) return emptyStream();
2266
+ return fromPull(
2267
+ asyncFold(
2268
+ uncons(cur),
2269
+ (opt) => asyncFail(opt),
2270
+ ([a, tail]) => asyncSucceed([a, loop(tail, remaining - 1)])
2271
+ )
2272
+ );
2273
+ };
2274
+ return loop(stream, n);
2275
+ }
2276
+ function drop(stream, n) {
2277
+ if (n <= 0) return stream;
2278
+ const skip = (cur, remaining) => {
2279
+ if (remaining <= 0) return cur;
2280
+ return fromPull(
2281
+ asyncFold(
2282
+ uncons(cur),
2283
+ (opt) => asyncFail(opt),
2284
+ ([_a, tail]) => uncons(skip(tail, remaining - 1))
2285
+ )
2286
+ );
2287
+ };
2288
+ return skip(stream, n);
2289
+ }
2290
+
734
2291
  // src/core/runtime/engineStats.ts
735
- function engineStats(engine, data, fallbackUsed = false) {
736
- return { engine, data, fallbackUsed };
2292
+ function engineStats(engine, data) {
2293
+ return { engine, data, fallbackUsed: false };
737
2294
  }
738
2295
  function selectedEngineStats(requested, engine, data) {
739
- return { requested, engine, data, fallbackUsed: requested === "auto" && engine !== "wasm" };
2296
+ if (requested !== engine) {
2297
+ throw new Error(`brass-runtime strict engine mismatch: requested '${requested}', got '${engine}'`);
2298
+ }
2299
+ return { requested, engine, data, fallbackUsed: false };
740
2300
  }
741
2301
  export {
2302
+ ABI_VERSION,
742
2303
  Async,
743
2304
  Cause,
744
2305
  DefaultHostExecutor,
2306
+ EVENT_WORDS,
745
2307
  EngineFiberHandle,
2308
+ EventKindCode,
746
2309
  Exit,
747
2310
  HostRegistry,
748
2311
  JsFiberEngine,
2312
+ NONE_U32,
749
2313
  NoopHooks,
2314
+ OpcodeTagCode,
2315
+ PURE_PIPELINE_TAG,
750
2316
  ProgramBuilder,
751
2317
  PushStatus,
752
- ReferenceWasmBridge,
753
2318
  RingBuffer,
754
2319
  Runtime,
755
2320
  RuntimeFiber,
@@ -758,9 +2323,16 @@ export {
758
2323
  WasmFiberEngine,
759
2324
  WasmFiberRegistryBridge,
760
2325
  WasmPackFiberBridge,
2326
+ abortablePromiseStats,
761
2327
  acquireRelease,
762
- andThen,
2328
+ andThen2 as andThen,
2329
+ andThen as andThenSchedule,
2330
+ applyFused,
2331
+ assertCompletesWithin,
2332
+ assertFails,
2333
+ assertFailsWith,
763
2334
  assertNever,
2335
+ assertSucceeds,
764
2336
  async,
765
2337
  asyncCatchAll,
766
2338
  asyncFail,
@@ -773,25 +2345,43 @@ export {
773
2345
  asyncSync,
774
2346
  asyncTotal,
775
2347
  bounded,
2348
+ bracket,
776
2349
  broadcast,
777
2350
  broadcastToHub,
778
2351
  buffer,
779
2352
  bufferP,
780
2353
  catchAll,
2354
+ catchTag,
2355
+ catchTags,
781
2356
  chunks,
782
2357
  chunksP,
783
2358
  collectAllPar,
784
2359
  collectStream,
785
- compose,
2360
+ compose2 as compose,
2361
+ compose as composeLayer,
786
2362
  concatStream,
2363
+ debounce,
2364
+ decodeEvent,
2365
+ decodeEventBatch,
2366
+ delayedEffect,
2367
+ derivedRef,
2368
+ deserializeFusedPipeline,
787
2369
  dropP,
2370
+ drop as dropStream,
2371
+ elapsed,
788
2372
  emitStream,
789
2373
  emptyStream,
2374
+ encodeOpcodeNodes,
2375
+ encodeOpcodeProgram,
790
2376
  end,
791
2377
  engineStats,
2378
+ ensuring,
2379
+ exponential,
792
2380
  fail,
793
2381
  filterMapP,
794
2382
  filterP,
2383
+ fixed,
2384
+ flakyEffect,
795
2385
  flatMap,
796
2386
  flattenStream,
797
2387
  foreachStream,
@@ -800,16 +2390,41 @@ export {
800
2390
  fromHub,
801
2391
  fromPromiseAbortable,
802
2392
  fromPull,
2393
+ fuse,
803
2394
  getBenchmarkBudget,
804
2395
  getCurrentFiber,
2396
+ getStats,
805
2397
  globalScheduler,
2398
+ gracefulShutdown,
806
2399
  groupedP,
807
2400
  identity,
2401
+ inferCallerLaneFromStack,
2402
+ initState,
2403
+ interleave,
2404
+ intersect,
2405
+ isFusionEnabled,
2406
+ isFusionVerbose,
2407
+ jittered,
2408
+ laneTag,
2409
+ layer,
2410
+ layerFail,
2411
+ layerFrom,
2412
+ layerSucceed,
808
2413
  linkAbortController,
809
2414
  makeBoundedRingBuffer,
810
2415
  makeCancelToken,
2416
+ makeCircuitBreaker,
2417
+ makeFiberReadyQueue,
811
2418
  makeHub,
2419
+ makeMetrics,
2420
+ makeRef,
2421
+ makeSemaphore,
812
2422
  makeStreamChunker,
2423
+ makeTestRuntime,
2424
+ makeTracer,
2425
+ makeWorkerPool,
2426
+ managed,
2427
+ managedAll,
813
2428
  managedStream,
814
2429
  map,
815
2430
  mapAsync,
@@ -818,38 +2433,71 @@ export {
818
2433
  mapChunksEffectP,
819
2434
  mapEffectP,
820
2435
  mapError,
2436
+ mapError2 as mapErrorTyped,
2437
+ mapLayer,
821
2438
  mapP,
822
2439
  mapStream,
823
2440
  mapTryAsync,
824
2441
  merge,
2442
+ merge2 as mergeLayer,
825
2443
  mergeStream,
2444
+ neverEffect,
826
2445
  none,
2446
+ orElse,
827
2447
  orElseOptional,
2448
+ provideLayer,
828
2449
  race,
829
2450
  raceWith,
830
2451
  rangeStream,
2452
+ recurs,
2453
+ registerShutdownHooks,
2454
+ repeatWithSchedule,
2455
+ resetAbortablePromiseStats,
2456
+ retry,
2457
+ retryN,
2458
+ retryWithBackoff,
2459
+ retryWithSchedule,
2460
+ runFusedArray,
831
2461
  runtimeCapabilities,
2462
+ runtimeForCaller,
2463
+ sanitizeLaneKey,
2464
+ scan,
832
2465
  selectedEngineStats,
2466
+ serializeFusedPipeline,
833
2467
  setBenchmarkBudget,
2468
+ setFusionEnabled,
2469
+ setFusionVerbose,
2470
+ sleep,
834
2471
  some,
835
2472
  streamFromReadableStream,
836
2473
  succeed,
837
2474
  sync,
2475
+ tagError,
838
2476
  takeP,
2477
+ take as takeSchedule,
2478
+ take2 as takeStream,
839
2479
  tapEffectP,
2480
+ throttle,
2481
+ timeout,
840
2482
  toPromise,
2483
+ toPromiseByCaller,
841
2484
  uncons,
2485
+ union,
842
2486
  unit,
843
2487
  unsafeGetCurrentRuntime,
844
2488
  unsafeRunAsync,
845
2489
  unsafeRunFoldWithEnv,
846
2490
  unwrapScoped,
2491
+ useManaged,
847
2492
  via,
2493
+ whileInput,
848
2494
  widenOpt,
849
2495
  withAsyncPromise,
850
2496
  withCurrentFiber,
851
2497
  withScope,
852
2498
  withScopeAsync,
853
2499
  zip,
854
- zipPar
2500
+ zipPar,
2501
+ zip2 as zipStream,
2502
+ zipWith
855
2503
  };