brass-runtime 1.13.8 → 1.15.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 (49) hide show
  1. package/README.md +6 -3
  2. package/dist/agent/cli/main.cjs +44 -43
  3. package/dist/agent/cli/main.js +5 -4
  4. package/dist/agent/cli/main.mjs +5 -4
  5. package/dist/agent/index.cjs +4 -3
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +3 -2
  8. package/dist/agent/index.mjs +3 -2
  9. package/dist/{chunk-3R7ZYRK2.mjs → chunk-3QMOKAS5.js} +9 -7
  10. package/dist/{chunk-ATHSSDUF.js → chunk-4NHES7VK.mjs} +113 -31
  11. package/dist/chunk-AR22SXML.js +1043 -0
  12. package/dist/chunk-BDF4AMWX.mjs +3773 -0
  13. package/dist/chunk-BDYEENHT.js +224 -0
  14. package/dist/chunk-BMH5AV44.js +3773 -0
  15. package/dist/chunk-ELOOF35R.mjs +131 -0
  16. package/dist/chunk-JFPU5GQI.mjs +1043 -0
  17. package/dist/{chunk-INZBKOHY.js → chunk-K6M7MDZ4.mjs} +9 -7
  18. package/dist/chunk-MS34J5LY.cjs +224 -0
  19. package/dist/{chunk-XNOTJSMZ.mjs → chunk-PPUXIH5R.js} +113 -31
  20. package/dist/chunk-R3R2FVLG.cjs +131 -0
  21. package/dist/{chunk-ZTDK2DLG.cjs → chunk-STVLQ3XD.cjs} +169 -87
  22. package/dist/chunk-TGIFUAK4.cjs +3773 -0
  23. package/dist/chunk-TO7IKXYT.js +131 -0
  24. package/dist/chunk-UMAZLXAB.mjs +224 -0
  25. package/dist/{chunk-XDINDYNA.cjs → chunk-VEZNF5GZ.cjs} +136 -134
  26. package/dist/chunk-XPZNXSVN.cjs +1043 -0
  27. package/dist/core/index.cjs +216 -0
  28. package/dist/core/index.d.ts +673 -0
  29. package/dist/core/index.js +216 -0
  30. package/dist/core/index.mjs +216 -0
  31. package/dist/{effect-ISvXPLgc.d.ts → effect-CMOQKX8y.d.ts} +202 -31
  32. package/dist/http/index.cjs +3177 -187
  33. package/dist/http/index.d.ts +1692 -9
  34. package/dist/http/index.js +3164 -174
  35. package/dist/http/index.mjs +3164 -174
  36. package/dist/index.cjs +936 -219
  37. package/dist/index.d.ts +313 -36
  38. package/dist/index.js +830 -113
  39. package/dist/index.mjs +830 -113
  40. package/dist/{stream-BvukHxCv.d.ts → stream-FQm9h4Mg.d.ts} +12 -4
  41. package/dist/tracing-DNT9jEbr.d.ts +106 -0
  42. package/package.json +11 -3
  43. package/wasm/pkg/brass_runtime_wasm_engine.d.ts +95 -16
  44. package/wasm/pkg/brass_runtime_wasm_engine.js +715 -15
  45. package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm +0 -0
  46. package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm.d.ts +78 -7
  47. package/dist/chunk-2P4PD6D7.cjs +0 -2557
  48. package/dist/chunk-7F2R7A2V.mjs +0 -2557
  49. package/dist/chunk-L6KKKM66.js +0 -2557
@@ -1,7 +1,10 @@
1
+ import {
2
+ race
3
+ } from "./chunk-ELOOF35R.mjs";
1
4
  import {
2
5
  Cause,
3
6
  Exit,
4
- async,
7
+ asyncEffect,
5
8
  asyncFail,
6
9
  asyncFlatMap,
7
10
  asyncFold,
@@ -9,9 +12,8 @@ import {
9
12
  asyncSucceed,
10
13
  asyncSync,
11
14
  fromPromiseAbortable,
12
- race,
13
15
  withScopeAsync
14
- } from "./chunk-L6KKKM66.js";
16
+ } from "./chunk-BDF4AMWX.mjs";
15
17
 
16
18
  // src/agent/core/state.ts
17
19
  var initialAgentState = (goal) => ({
@@ -1425,10 +1427,10 @@ var decideNextAction = (state) => {
1425
1427
  };
1426
1428
 
1427
1429
  // src/agent/core/events.ts
1428
- var nowMillis = () => async((_env, cb) => {
1430
+ var nowMillis = () => asyncEffect((_env, cb) => {
1429
1431
  cb({ _tag: "Success", value: Date.now() });
1430
1432
  });
1431
- var emitAgentEvent = (event) => async((env, cb) => {
1433
+ var emitAgentEvent = (event) => asyncEffect((env, cb) => {
1432
1434
  try {
1433
1435
  env.events?.emit(event);
1434
1436
  } catch {
@@ -1684,7 +1686,7 @@ var retry = (make, options) => {
1684
1686
  };
1685
1687
 
1686
1688
  // src/agent/tools/timeout.ts
1687
- var sleep = (ms) => async((_env, cb) => {
1689
+ var sleep = (ms) => asyncEffect((_env, cb) => {
1688
1690
  const id = setTimeout(() => cb({ _tag: "Success", value: void 0 }), ms);
1689
1691
  return () => clearTimeout(id);
1690
1692
  });
@@ -2124,7 +2126,7 @@ var chunkToString = (chunk) => {
2124
2126
  return typeof maybeToString === "function" ? maybeToString.call(chunk, "utf8") : String(chunk);
2125
2127
  };
2126
2128
  var NodeShell = {
2127
- exec: (command, options) => async((_env, cb) => {
2129
+ exec: (command, options) => asyncEffect((_env, cb) => {
2128
2130
  const [bin, ...args] = command;
2129
2131
  if (!bin) {
2130
2132
  cb(
@@ -0,0 +1,224 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+
7
+
8
+ var _chunkTGIFUAK4cjs = require('./chunk-TGIFUAK4.cjs');
9
+
10
+ // src/core/runtime/combinators.ts
11
+ function sleep(ms) {
12
+ return _chunkTGIFUAK4cjs.asyncEffect.call(void 0, (_env, cb) => {
13
+ const delay = Math.max(0, Math.floor(ms));
14
+ const id = setTimeout(() => cb({ _tag: "Success", value: void 0 }), delay);
15
+ return () => clearTimeout(id);
16
+ });
17
+ }
18
+ function timeout(effect, ms) {
19
+ return _chunkTGIFUAK4cjs.asyncEffect.call(void 0, (env, cb) => {
20
+ let done = false;
21
+ let timerId;
22
+ let effectRunning = true;
23
+ timerId = setTimeout(() => {
24
+ if (done) return;
25
+ done = true;
26
+ effectRunning = false;
27
+ cb({
28
+ _tag: "Failure",
29
+ cause: { _tag: "Fail", error: { _tag: "TimeoutError", ms } }
30
+ });
31
+ }, Math.max(0, Math.floor(ms)));
32
+ const runtime = _chunkTGIFUAK4cjs.unsafeGetCurrentRuntime.call(void 0, );
33
+ if (runtime) {
34
+ const fiber = runtime.fork(effect);
35
+ fiber.join((exit) => {
36
+ if (done) return;
37
+ done = true;
38
+ clearTimeout(timerId);
39
+ cb(exit);
40
+ });
41
+ return () => {
42
+ if (done) return;
43
+ done = true;
44
+ clearTimeout(timerId);
45
+ fiber.interrupt();
46
+ };
47
+ }
48
+ return () => {
49
+ if (done) return;
50
+ done = true;
51
+ clearTimeout(timerId);
52
+ };
53
+ });
54
+ }
55
+ function retry(effect, policy) {
56
+ const shouldRetry = _nullishCoalesce(policy.shouldRetry, () => ( (() => true)));
57
+ const jitter = _nullishCoalesce(policy.jitter, () => ( "full"));
58
+ const maxElapsedMs = policy.maxElapsedMs;
59
+ const computeDelay = (attempt) => {
60
+ const exp = policy.baseDelayMs * Math.pow(2, attempt);
61
+ const capped = Math.min(exp, policy.maxDelayMs);
62
+ if (jitter === "none") return capped;
63
+ return Math.floor(Math.random() * capped);
64
+ };
65
+ const loop = (attempt, startedAt) => _chunkTGIFUAK4cjs.asyncFold.call(void 0,
66
+ effect,
67
+ (error) => {
68
+ if (attempt >= policy.maxRetries) return _chunkTGIFUAK4cjs.asyncFail.call(void 0, error);
69
+ if (!shouldRetry(error, attempt)) return _chunkTGIFUAK4cjs.asyncFail.call(void 0, error);
70
+ if (maxElapsedMs !== void 0) {
71
+ const elapsed = performance.now() - startedAt;
72
+ if (elapsed >= maxElapsedMs) return _chunkTGIFUAK4cjs.asyncFail.call(void 0, error);
73
+ }
74
+ const delay = computeDelay(attempt);
75
+ return _chunkTGIFUAK4cjs.asyncFlatMap.call(void 0, sleep(delay), () => loop(attempt + 1, startedAt));
76
+ },
77
+ (value) => _chunkTGIFUAK4cjs.asyncSucceed.call(void 0, value)
78
+ );
79
+ return _chunkTGIFUAK4cjs.asyncFlatMap.call(void 0,
80
+ { _tag: "Sync", thunk: () => performance.now() },
81
+ (startedAt) => loop(0, startedAt)
82
+ );
83
+ }
84
+ function retryN(effect, n) {
85
+ return retry(effect, {
86
+ maxRetries: n,
87
+ baseDelayMs: 0,
88
+ maxDelayMs: 0,
89
+ jitter: "none"
90
+ });
91
+ }
92
+ function retryWithBackoff(effect, opts = {}) {
93
+ return retry(effect, {
94
+ maxRetries: _nullishCoalesce(opts.maxRetries, () => ( 3)),
95
+ baseDelayMs: _nullishCoalesce(opts.baseDelayMs, () => ( 100)),
96
+ maxDelayMs: _nullishCoalesce(opts.maxDelayMs, () => ( 1e4)),
97
+ maxElapsedMs: opts.maxElapsedMs,
98
+ shouldRetry: opts.shouldRetry,
99
+ jitter: "full"
100
+ });
101
+ }
102
+
103
+ // src/core/runtime/circuitBreaker.ts
104
+ function makeCircuitBreaker(config = {}) {
105
+ const failureThreshold = _nullishCoalesce(config.failureThreshold, () => ( 5));
106
+ const resetTimeoutMs = _nullishCoalesce(config.resetTimeoutMs, () => ( 3e4));
107
+ const successThreshold = _nullishCoalesce(config.successThreshold, () => ( 1));
108
+ const isFailure = _nullishCoalesce(config.isFailure, () => ( (() => true)));
109
+ const onStateChange = config.onStateChange;
110
+ let currentState = "closed";
111
+ let consecutiveFailures = 0;
112
+ let consecutiveSuccesses = 0;
113
+ let openedAt = 0;
114
+ let totalRequests = 0;
115
+ let totalFailures = 0;
116
+ let totalSuccesses = 0;
117
+ let totalRejected = 0;
118
+ let lastFailureTime = null;
119
+ let lastSuccessTime = null;
120
+ const transition = (to) => {
121
+ if (currentState === to) return;
122
+ const from = currentState;
123
+ currentState = to;
124
+ _optionalChain([onStateChange, 'optionalCall', _ => _(from, to)]);
125
+ };
126
+ const onSuccess = () => {
127
+ totalSuccesses++;
128
+ lastSuccessTime = Date.now();
129
+ consecutiveFailures = 0;
130
+ if (currentState === "half-open") {
131
+ consecutiveSuccesses++;
132
+ if (consecutiveSuccesses >= successThreshold) {
133
+ consecutiveSuccesses = 0;
134
+ transition("closed");
135
+ }
136
+ }
137
+ };
138
+ const onFailure = (error) => {
139
+ if (!isFailure(error)) {
140
+ onSuccess();
141
+ return;
142
+ }
143
+ totalFailures++;
144
+ lastFailureTime = Date.now();
145
+ consecutiveSuccesses = 0;
146
+ consecutiveFailures++;
147
+ if (currentState === "half-open") {
148
+ openedAt = Date.now();
149
+ transition("open");
150
+ } else if (currentState === "closed" && consecutiveFailures >= failureThreshold) {
151
+ openedAt = Date.now();
152
+ transition("open");
153
+ }
154
+ };
155
+ const shouldAllow = () => {
156
+ switch (currentState) {
157
+ case "closed":
158
+ return true;
159
+ case "open": {
160
+ const elapsed = Date.now() - openedAt;
161
+ if (elapsed >= resetTimeoutMs) {
162
+ transition("half-open");
163
+ return true;
164
+ }
165
+ return false;
166
+ }
167
+ case "half-open":
168
+ return true;
169
+ }
170
+ };
171
+ const protect = (effect) => {
172
+ totalRequests++;
173
+ if (!shouldAllow()) {
174
+ totalRejected++;
175
+ return _chunkTGIFUAK4cjs.asyncFail.call(void 0, {
176
+ _tag: "CircuitBreakerOpen",
177
+ openSince: openedAt,
178
+ failures: consecutiveFailures
179
+ });
180
+ }
181
+ return _chunkTGIFUAK4cjs.asyncFold.call(void 0,
182
+ effect,
183
+ (error) => {
184
+ onFailure(error);
185
+ return _chunkTGIFUAK4cjs.asyncFail.call(void 0, error);
186
+ },
187
+ (value) => {
188
+ onSuccess();
189
+ return _chunkTGIFUAK4cjs.asyncSucceed.call(void 0, value);
190
+ }
191
+ );
192
+ };
193
+ const stats = () => ({
194
+ state: currentState,
195
+ failures: consecutiveFailures,
196
+ successes: consecutiveSuccesses,
197
+ totalRequests,
198
+ totalFailures,
199
+ totalSuccesses,
200
+ totalRejected,
201
+ lastFailureTime,
202
+ lastSuccessTime
203
+ });
204
+ const reset = () => {
205
+ consecutiveFailures = 0;
206
+ consecutiveSuccesses = 0;
207
+ transition("closed");
208
+ };
209
+ return {
210
+ state: () => currentState,
211
+ protect,
212
+ stats,
213
+ reset
214
+ };
215
+ }
216
+
217
+
218
+
219
+
220
+
221
+
222
+
223
+
224
+ exports.sleep = sleep; exports.timeout = timeout; exports.retry = retry; exports.retryN = retryN; exports.retryWithBackoff = retryWithBackoff; exports.makeCircuitBreaker = makeCircuitBreaker;
@@ -1,8 +1,11 @@
1
+ import {
2
+ raceWith
3
+ } from "./chunk-TO7IKXYT.js";
1
4
  import {
2
5
  Cause,
3
6
  Exit,
4
7
  Scope,
5
- async,
8
+ asyncEffect,
6
9
  asyncFail,
7
10
  asyncFlatMap,
8
11
  asyncFold,
@@ -16,13 +19,12 @@ import {
16
19
  mapError,
17
20
  none,
18
21
  orElseOptional,
19
- raceWith,
20
22
  some,
21
23
  succeed,
22
24
  sync,
23
25
  unsafeGetCurrentRuntime,
24
26
  unsafeRunFoldWithEnv
25
- } from "./chunk-7F2R7A2V.mjs";
27
+ } from "./chunk-BMH5AV44.js";
26
28
 
27
29
  // src/core/stream/stream.ts
28
30
  var widenOpt = (opt) => opt._tag === "None" ? none : some(opt.value);
@@ -73,7 +75,7 @@ function streamToRaceWithHandler(winnerSide, leftStream, rightStream, flip, id)
73
75
  return asyncSucceed([a, next]);
74
76
  }
75
77
  if (exit.cause._tag === "Interrupt") {
76
- return async((_env, cb) => {
78
+ return asyncEffect((_env, cb) => {
77
79
  cb(Exit.failCause(Cause.interrupt()));
78
80
  });
79
81
  }
@@ -88,7 +90,7 @@ function makeMergePull(onLeft, onRight, flip, mergePullId) {
88
90
  const id = ++mergePullId;
89
91
  const onLeftHandler = streamToRaceWithHandler("L", onLeft, onRight, flip, id);
90
92
  const onRightHandler = streamToRaceWithHandler("R", onLeft, onRight, flip, id);
91
- return async((_env, cb) => {
93
+ return asyncEffect((_env, cb) => {
92
94
  const runtime = unsafeGetCurrentRuntime();
93
95
  const scope = new Scope(runtime);
94
96
  const handler = raceWith(
@@ -111,6 +113,12 @@ function uncons(self) {
111
113
  switch (self._tag) {
112
114
  case "Empty":
113
115
  return fail(none);
116
+ case "FromArray": {
117
+ const arr = self.values;
118
+ if (arr.length === 0) return fail(none);
119
+ const tail = arr.length === 1 ? EMPTY_STREAM : { _tag: "FromArray", values: arr.slice(1) };
120
+ return succeed([arr[0], tail]);
121
+ }
114
122
  case "Emit":
115
123
  return map(
116
124
  mapError(self.value, (e) => some(e)),
@@ -143,7 +151,7 @@ function uncons(self) {
143
151
  case "Merge":
144
152
  return makeMergePull(self.left, self.right, self.flip, 0);
145
153
  case "Scoped":
146
- return async((env, cb) => {
154
+ return asyncEffect((env, cb) => {
147
155
  const runtime = unsafeGetCurrentRuntime();
148
156
  const scope = new Scope(runtime);
149
157
  const fiber = getCurrentFiber();
@@ -164,7 +172,7 @@ function uncons(self) {
164
172
  scope.close(exit);
165
173
  };
166
174
  const wrap = (s) => fromPull(
167
- async((env2, cb2) => {
175
+ asyncEffect((env2, cb2) => {
168
176
  const pull = uncons(s);
169
177
  unsafeRunFoldWithEnv(
170
178
  pull,
@@ -192,7 +200,7 @@ function uncons(self) {
192
200
  });
193
201
  });
194
202
  case "Managed":
195
- return async((env, cb) => {
203
+ return asyncEffect((env, cb) => {
196
204
  const runtime = unsafeGetCurrentRuntime();
197
205
  const scope = new Scope(runtime);
198
206
  getCurrentFiber()?.addFinalizer((exit) => {
@@ -220,16 +228,19 @@ function uncons(self) {
220
228
  const { stream: inner, release } = ex.value;
221
229
  scope.addFinalizer((exit) => release(exit));
222
230
  const wrap = (s) => fromPull(
223
- async((env2, cb2) => {
224
- uncons(s)(env2, (ex2) => {
225
- if (ex2._tag === "Failure") {
231
+ asyncEffect((env2, cb2) => {
232
+ unsafeRunFoldWithEnv(
233
+ uncons(s),
234
+ env2,
235
+ (cause) => {
236
+ const ex2 = Exit.failCause(cause);
226
237
  closeWith(ex2);
227
238
  cb2(ex2);
228
- return;
239
+ },
240
+ ([a, tail]) => {
241
+ cb2(Exit.succeed([a, wrap(tail)]));
229
242
  }
230
- const [a, tail] = ex2.value;
231
- cb2(Exit.succeed([a, wrap(tail)]));
232
- });
243
+ );
233
244
  })
234
245
  );
235
246
  unsafeGetCurrentRuntime().fork(uncons(wrap(inner))).join(cb);
@@ -244,6 +255,8 @@ function mapStream(self, f) {
244
255
  switch (self._tag) {
245
256
  case "Empty":
246
257
  return emptyStream();
258
+ case "FromArray":
259
+ return { _tag: "FromArray", values: self.values.map(f) };
247
260
  case "Emit":
248
261
  return emitStream(map(self.value, f));
249
262
  case "FromPull":
@@ -327,58 +340,127 @@ function foreachStream(stream, f) {
327
340
  );
328
341
  }
329
342
  function fromArray(values) {
330
- let s = emptyStream();
331
- for (let i = values.length - 1; i >= 0; i--) {
332
- const head = emitStream(succeed(values[i]));
333
- s = concatStream(head, s);
334
- }
335
- return s;
343
+ if (values.length === 0) return emptyStream();
344
+ return { _tag: "FromArray", values };
336
345
  }
337
346
  function collectStream(stream) {
347
+ const syncResult = drainStreamSyncFull(stream);
348
+ if (syncResult !== null) {
349
+ return asyncSucceed(syncResult);
350
+ }
338
351
  const loop = (cur, acc) => asyncFold(
339
352
  uncons(cur),
340
353
  (opt) => {
341
354
  if (opt._tag === "None") return succeed(acc);
342
355
  return fail(opt);
343
356
  },
344
- ([a, tail]) => loop(tail, [...acc, a])
357
+ ([a, tail]) => {
358
+ acc.push(a);
359
+ return loop(tail, acc);
360
+ }
345
361
  );
346
362
  return mapError(loop(stream, []), (opt) => {
347
363
  if (opt._tag === "Some") return opt.value;
348
364
  throw new Error("unreachable: stream end handled as success");
349
365
  });
350
366
  }
351
- function readerStream(reader, normalizeError) {
352
- const pull = async((_, cb) => {
353
- reader.read().then(({ done, value }) => {
354
- if (done) {
355
- cb({ _tag: "Failure", cause: { _tag: "Fail", error: none } });
367
+ function drainStreamSyncFull(stream) {
368
+ const result = [];
369
+ let cur = stream;
370
+ while (true) {
371
+ switch (cur._tag) {
372
+ case "Empty":
373
+ return result;
374
+ case "FromArray": {
375
+ const arr = cur.values;
376
+ for (let i = 0; i < arr.length; i++) {
377
+ result.push(arr[i]);
378
+ }
379
+ return result;
380
+ }
381
+ case "Emit": {
382
+ const zio = cur.value;
383
+ if (zio._tag === "Succeed") {
384
+ result.push(zio.value);
385
+ return result;
386
+ }
387
+ return null;
388
+ }
389
+ case "Concat": {
390
+ const leftItems = drainStreamSyncFull(cur.left);
391
+ if (leftItems === null) return null;
392
+ for (let i = 0; i < leftItems.length; i++) {
393
+ result.push(leftItems[i]);
394
+ }
395
+ cur = cur.right;
396
+ break;
397
+ }
398
+ default:
399
+ return null;
400
+ }
401
+ }
402
+ }
403
+ function readerStream(reader, normalizeError, signal) {
404
+ const pull = asyncEffect((_, cb) => {
405
+ let done = false;
406
+ const cleanup = () => signal?.removeEventListener("abort", abort);
407
+ const finish = (exit) => {
408
+ if (done) return;
409
+ done = true;
410
+ cleanup();
411
+ cb(exit);
412
+ };
413
+ const abort = () => {
414
+ try {
415
+ reader.cancel();
416
+ } catch {
417
+ }
418
+ const error = typeof DOMException === "function" ? new DOMException("aborted", "AbortError") : new Error("aborted");
419
+ finish({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(error)) } });
420
+ };
421
+ if (signal?.aborted) {
422
+ abort();
423
+ return;
424
+ }
425
+ signal?.addEventListener("abort", abort, { once: true });
426
+ reader.read().then(({ done: done2, value }) => {
427
+ if (done2) {
428
+ finish({ _tag: "Failure", cause: { _tag: "Fail", error: none } });
356
429
  return;
357
430
  }
358
- cb({
431
+ finish({
359
432
  _tag: "Success",
360
433
  value: [value, fromPull(pull)]
361
434
  });
362
435
  }).catch((e) => {
363
- cb({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(e)) } });
436
+ finish({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(e)) } });
364
437
  });
438
+ return () => {
439
+ cleanup();
440
+ try {
441
+ reader.cancel();
442
+ } catch {
443
+ }
444
+ };
365
445
  });
366
446
  return fromPull(pull);
367
447
  }
368
- function streamFromReadableStream(body, normalizeError) {
448
+ function streamFromReadableStream(body, normalizeError, options = {}) {
369
449
  if (!body) return emptyStream();
370
450
  let reader;
371
451
  return unwrapScoped(
372
452
  // acquire: produce un ZStream
373
453
  sync(() => {
374
454
  reader = body.getReader();
375
- return readerStream(reader, normalizeError);
455
+ return readerStream(reader, normalizeError, options.signal);
376
456
  }),
377
457
  // release: se corre en fin / error / interrupción
378
458
  () => asyncSync(() => {
379
459
  try {
380
460
  reader?.cancel();
381
461
  } catch {
462
+ } finally {
463
+ options.onRelease?.();
382
464
  }
383
465
  })
384
466
  );
@@ -0,0 +1,131 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkTGIFUAK4cjs = require('./chunk-TGIFUAK4.cjs');
4
+
5
+ // src/core/stream/structuredConcurrency.ts
6
+ function race(left, right, parentScope) {
7
+ return _chunkTGIFUAK4cjs.asyncEffect.call(void 0, (env, cb) => {
8
+ const scope = parentScope.subScope();
9
+ let done = false;
10
+ const onResult = (exit) => {
11
+ if (done) return;
12
+ done = true;
13
+ scope.close(exit);
14
+ cb(exit);
15
+ };
16
+ const fiberLeft = scope.fork(left);
17
+ const fiberRight = scope.fork(right);
18
+ fiberLeft.join(onResult);
19
+ fiberRight.join(onResult);
20
+ });
21
+ }
22
+ function zipPar(left, right, parentScope) {
23
+ return _chunkTGIFUAK4cjs.asyncEffect.call(void 0, (env, cb) => {
24
+ const scope = parentScope.subScope();
25
+ let leftExit = null;
26
+ let rightExit = null;
27
+ let done = false;
28
+ const checkDone = () => {
29
+ if (!leftExit || !rightExit || done) return;
30
+ done = true;
31
+ if (leftExit._tag === "Success" && rightExit._tag === "Success") {
32
+ scope.close({ _tag: "Success", value: void 0 });
33
+ cb({
34
+ _tag: "Success",
35
+ value: [leftExit.value, rightExit.value]
36
+ });
37
+ return;
38
+ }
39
+ let cause;
40
+ if (leftExit._tag === "Failure") {
41
+ cause = leftExit.cause;
42
+ } else if (rightExit._tag === "Failure") {
43
+ cause = rightExit.cause;
44
+ } else {
45
+ throw new Error("zipPar: unreachable state (no Failure exit)");
46
+ }
47
+ const errExit = {
48
+ _tag: "Failure",
49
+ cause
50
+ };
51
+ scope.close(errExit);
52
+ cb(errExit);
53
+ };
54
+ const f1 = scope.fork(left);
55
+ const f2 = scope.fork(right);
56
+ f1.join((exit) => {
57
+ leftExit = exit;
58
+ checkDone();
59
+ });
60
+ f2.join((exit) => {
61
+ rightExit = exit;
62
+ checkDone();
63
+ });
64
+ });
65
+ }
66
+ function collectAllPar(effects, parentScope) {
67
+ return _chunkTGIFUAK4cjs.asyncEffect.call(void 0, (env, cb) => {
68
+ const scope = parentScope.subScope();
69
+ const results = new Array(effects.length);
70
+ let completed = 0;
71
+ let done = false;
72
+ effects.forEach((eff, i) => {
73
+ const f = scope.fork(eff);
74
+ f.join((exit) => {
75
+ if (done) return;
76
+ if (exit._tag === "Failure") {
77
+ done = true;
78
+ const errExit = {
79
+ _tag: "Failure",
80
+ cause: exit.cause
81
+ };
82
+ scope.close(errExit);
83
+ cb(errExit);
84
+ return;
85
+ }
86
+ results[i] = exit.value;
87
+ completed++;
88
+ if (completed === effects.length) {
89
+ done = true;
90
+ const successExit = {
91
+ _tag: "Success",
92
+ value: results
93
+ };
94
+ scope.close({ _tag: "Success", value: void 0 });
95
+ cb(successExit);
96
+ }
97
+ });
98
+ });
99
+ });
100
+ }
101
+ function raceWith(left, right, parentScope, onLeft, onRight) {
102
+ return _chunkTGIFUAK4cjs.asyncEffect.call(void 0, (env, cb) => {
103
+ const scope = parentScope.subScope();
104
+ let done = false;
105
+ const fiberLeft = scope.fork(left);
106
+ const fiberRight = scope.fork(right);
107
+ const finish = (next) => {
108
+ scope.fork(next).join((exitNext) => {
109
+ scope.close(exitNext);
110
+ cb(exitNext);
111
+ });
112
+ };
113
+ fiberLeft.join((exitL) => {
114
+ if (done) return;
115
+ done = true;
116
+ finish(onLeft(exitL, fiberRight, scope));
117
+ });
118
+ fiberRight.join((exitR) => {
119
+ if (done) return;
120
+ done = true;
121
+ finish(onRight(exitR, fiberLeft, scope));
122
+ });
123
+ });
124
+ }
125
+
126
+
127
+
128
+
129
+
130
+
131
+ exports.race = race; exports.zipPar = zipPar; exports.collectAllPar = collectAllPar; exports.raceWith = raceWith;