brass-runtime 1.15.0 → 1.16.1

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 (209) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +673 -136
  3. package/dist/agent/cli/main.cjs +40 -35
  4. package/dist/agent/cli/main.js +9 -4
  5. package/dist/agent/cli/main.mjs +9 -4
  6. package/dist/agent/index.cjs +8 -4
  7. package/dist/agent/index.d.ts +1 -1
  8. package/dist/agent/index.js +7 -3
  9. package/dist/agent/index.mjs +7 -3
  10. package/dist/chunk-2HQTDLHF.mjs +683 -0
  11. package/dist/chunk-36I3M4UC.mjs +370 -0
  12. package/dist/chunk-3AYM6WPJ.js +1629 -0
  13. package/dist/chunk-3LOYJFRR.cjs +300 -0
  14. package/dist/chunk-3RG5ZIWI.js +10 -0
  15. package/dist/chunk-3Y2RIUMM.js +300 -0
  16. package/dist/{chunk-VEZNF5GZ.cjs → chunk-4ROBZFL6.cjs} +130 -126
  17. package/dist/{chunk-3QMOKAS5.js → chunk-52OB2ROS.js} +9 -5
  18. package/dist/chunk-52PPNNI4.cjs +416 -0
  19. package/dist/chunk-5EC274J5.cjs +2874 -0
  20. package/dist/chunk-5QC7LRZ3.js +229 -0
  21. package/dist/chunk-5VRJNBLZ.mjs +2874 -0
  22. package/dist/chunk-62AZW6UT.cjs +313 -0
  23. package/dist/chunk-6IXXWIUM.js +683 -0
  24. package/dist/chunk-74ZTY6CP.js +2871 -0
  25. package/dist/chunk-76YMRMH2.cjs +777 -0
  26. package/dist/chunk-7CMJS3QE.mjs +2871 -0
  27. package/dist/{chunk-4NHES7VK.mjs → chunk-7JIJOVCT.js} +27 -13
  28. package/dist/chunk-A2OM6NEH.mjs +194 -0
  29. package/dist/chunk-AGR5B2BC.cjs +683 -0
  30. package/dist/chunk-AVNQLJ5V.js +777 -0
  31. package/dist/chunk-B33ICAKP.js +313 -0
  32. package/dist/{chunk-ELOOF35R.mjs → chunk-B5JD23U7.mjs} +1 -1
  33. package/dist/chunk-BABBZK4Y.js +2024 -0
  34. package/dist/chunk-C3MDXTRZ.js +354 -0
  35. package/dist/chunk-CIZFIMK5.js +2193 -0
  36. package/dist/chunk-CZIVE6NT.cjs +354 -0
  37. package/dist/chunk-DNFJLJMW.mjs +354 -0
  38. package/dist/chunk-DNFO2EIZ.mjs +777 -0
  39. package/dist/chunk-EJ6BPYVR.mjs +416 -0
  40. package/dist/chunk-ENKODRU3.cjs +2193 -0
  41. package/dist/chunk-EOC4UHBS.mjs +229 -0
  42. package/dist/{chunk-BMH5AV44.js → chunk-FH2X7BVP.js} +756 -440
  43. package/dist/{chunk-PPUXIH5R.js → chunk-FHQGHPMO.mjs} +27 -13
  44. package/dist/{chunk-TGIFUAK4.cjs → chunk-GLE2WY7Z.cjs} +951 -635
  45. package/dist/{chunk-BDF4AMWX.mjs → chunk-GYM3LLGS.mjs} +756 -440
  46. package/dist/chunk-HLWLMW2F.mjs +2024 -0
  47. package/dist/chunk-JF5WGYJJ.cjs +194 -0
  48. package/dist/chunk-KH4SYAOS.mjs +1629 -0
  49. package/dist/chunk-KN32XNTH.mjs +313 -0
  50. package/dist/chunk-KQLYONSE.cjs +2871 -0
  51. package/dist/{chunk-STVLQ3XD.cjs → chunk-KZJQ723N.cjs} +92 -78
  52. package/dist/chunk-L2SYFEBS.js +194 -0
  53. package/dist/chunk-L6VB5N7Q.cjs +104 -0
  54. package/dist/{chunk-K6M7MDZ4.mjs → chunk-MBEJI5HF.mjs} +9 -5
  55. package/dist/chunk-MIIYDLGM.js +2874 -0
  56. package/dist/chunk-MOO4L7F4.mjs +104 -0
  57. package/dist/chunk-MT3OWDPC.mjs +2193 -0
  58. package/dist/chunk-MVGUEJ5Z.cjs +370 -0
  59. package/dist/chunk-OBGZSXTJ.cjs +10 -0
  60. package/dist/chunk-PD4EJTQC.cjs +229 -0
  61. package/dist/chunk-PWC3RBQE.mjs +300 -0
  62. package/dist/chunk-Q2I37RP3.cjs +1629 -0
  63. package/dist/chunk-RKGKFN2A.js +416 -0
  64. package/dist/{chunk-R3R2FVLG.cjs → chunk-SA6HUJVI.cjs} +5 -5
  65. package/dist/chunk-TRM4JUZQ.js +104 -0
  66. package/dist/chunk-UB4B6OFY.js +370 -0
  67. package/dist/{chunk-TO7IKXYT.js → chunk-UCUBNWM2.js} +1 -1
  68. package/dist/chunk-VN44DYYT.cjs +2024 -0
  69. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  70. package/dist/client-CZHU674n.d.ts +820 -0
  71. package/dist/core/index.cjs +198 -4
  72. package/dist/core/index.d.ts +311 -212
  73. package/dist/core/index.js +237 -43
  74. package/dist/core/index.mjs +237 -43
  75. package/dist/{effect-CMOQKX8y.d.ts → effect-DIUHZ9IN.d.ts} +195 -1
  76. package/dist/effectRunner-CFLC32IK.cjs +8 -0
  77. package/dist/effectRunner-L4S7IPT3.js +8 -0
  78. package/dist/effectRunner-NNGG75QA.mjs +8 -0
  79. package/dist/http/index.cjs +1227 -2971
  80. package/dist/http/index.d.ts +826 -280
  81. package/dist/http/index.js +1089 -2833
  82. package/dist/http/index.mjs +1089 -2833
  83. package/dist/http/testing.cjs +161 -0
  84. package/dist/http/testing.d.ts +43 -0
  85. package/dist/http/testing.js +161 -0
  86. package/dist/http/testing.mjs +161 -0
  87. package/dist/index.cjs +486 -250
  88. package/dist/index.d.ts +87 -95
  89. package/dist/index.js +391 -155
  90. package/dist/index.mjs +391 -155
  91. package/dist/observability/index.cjs +162 -0
  92. package/dist/observability/index.d.ts +152 -0
  93. package/dist/observability/index.js +162 -0
  94. package/dist/observability/index.mjs +162 -0
  95. package/dist/perf/cli.cjs +401 -0
  96. package/dist/perf/cli.d.ts +1 -0
  97. package/dist/perf/cli.js +401 -0
  98. package/dist/perf/cli.mjs +401 -0
  99. package/dist/perf/index.cjs +141 -0
  100. package/dist/perf/index.d.ts +483 -0
  101. package/dist/perf/index.js +141 -0
  102. package/dist/perf/index.mjs +141 -0
  103. package/dist/schedule-CK3Ml_7p.d.ts +259 -0
  104. package/dist/schema/index.cjs +29 -0
  105. package/dist/schema/index.d.ts +179 -0
  106. package/dist/schema/index.js +29 -0
  107. package/dist/schema/index.mjs +29 -0
  108. package/dist/server-GJPg8ZSG.d.ts +675 -0
  109. package/dist/{stream-FQm9h4Mg.d.ts → stream-B4oK9JFP.d.ts} +1 -1
  110. package/dist/tracer-Hwt1cl7h.d.ts +189 -0
  111. package/dist/tracing-DqbTKGcf.d.ts +148 -0
  112. package/docs/ARCHITECTURE.md +292 -0
  113. package/docs/README.md +63 -0
  114. package/docs/adr/0001-ai-context-pack.md +32 -0
  115. package/docs/agent-apply-mode.md +104 -0
  116. package/docs/agent-approvals.md +110 -0
  117. package/docs/agent-batch.md +185 -0
  118. package/docs/agent-boundaries.md +112 -0
  119. package/docs/agent-chat-sessions.md +160 -0
  120. package/docs/agent-ci.md +17 -0
  121. package/docs/agent-cli.md +405 -0
  122. package/docs/agent-config.md +480 -0
  123. package/docs/agent-context-discovery.md +159 -0
  124. package/docs/agent-copilot-like-dx.md +126 -0
  125. package/docs/agent-declarative-optimized-planning.md +138 -0
  126. package/docs/agent-dx.md +224 -0
  127. package/docs/agent-env-files.md +126 -0
  128. package/docs/agent-follow-up-context.md +43 -0
  129. package/docs/agent-global-usage.md +180 -0
  130. package/docs/agent-init.md +109 -0
  131. package/docs/agent-install-and-configure.md +516 -0
  132. package/docs/agent-language-workspace-ux.md +99 -0
  133. package/docs/agent-llm-adapters.md +123 -0
  134. package/docs/agent-local-install.md +190 -0
  135. package/docs/agent-local-tests.md +51 -0
  136. package/docs/agent-observability.md +155 -0
  137. package/docs/agent-patch-quality-loop.md +162 -0
  138. package/docs/agent-presets.md +22 -0
  139. package/docs/agent-project-commands.md +237 -0
  140. package/docs/agent-project-intelligence.md +156 -0
  141. package/docs/agent-redaction.md +18 -0
  142. package/docs/agent-release-readiness.md +76 -0
  143. package/docs/agent-rollback-safety.md +162 -0
  144. package/docs/agent-rollback.md +23 -0
  145. package/docs/agent-run-artifacts.md +16 -0
  146. package/docs/agent-vscode-auto-discovery.md +137 -0
  147. package/docs/agent-vscode-batch-runner.md +100 -0
  148. package/docs/agent-vscode-chat-layout.md +90 -0
  149. package/docs/agent-vscode-clean-install.md +147 -0
  150. package/docs/agent-vscode-code-actions.md +70 -0
  151. package/docs/agent-vscode-diff-preview.md +45 -0
  152. package/docs/agent-vscode-inline-assist.md +56 -0
  153. package/docs/agent-vscode-install.md +186 -0
  154. package/docs/agent-vscode-model-setup.md +97 -0
  155. package/docs/agent-vscode-patch-preview.md +92 -0
  156. package/docs/agent-vscode-problems.md +79 -0
  157. package/docs/agent-vscode-project-dashboard.md +106 -0
  158. package/docs/agent-vscode-run-history.md +92 -0
  159. package/docs/agent-vscode-ux.md +73 -0
  160. package/docs/ai/INVARIANTS.md +84 -0
  161. package/docs/ai/PROJECT_MAP.md +338 -0
  162. package/docs/ai/PUBLIC_API.md +336 -0
  163. package/docs/ai/VALIDATION_MATRIX.md +67 -0
  164. package/docs/api-polish.md +37 -0
  165. package/docs/cancellation.md +162 -0
  166. package/docs/coverage.md +46 -0
  167. package/docs/getting-started.md +159 -0
  168. package/docs/guides/README.md +40 -0
  169. package/docs/guides/circuit-breaker.md +89 -0
  170. package/docs/guides/error-handling.md +91 -0
  171. package/docs/guides/getting-started.md +107 -0
  172. package/docs/guides/layers.md +189 -0
  173. package/docs/guides/metrics.md +101 -0
  174. package/docs/guides/resource-management.md +141 -0
  175. package/docs/guides/retry.md +215 -0
  176. package/docs/guides/semaphore.md +66 -0
  177. package/docs/guides/streams.md +117 -0
  178. package/docs/guides/supervisors.md +98 -0
  179. package/docs/guides/testing.md +162 -0
  180. package/docs/guides/tracing.md +71 -0
  181. package/docs/http-recipes.md +399 -0
  182. package/docs/http.md +749 -0
  183. package/docs/modules.md +285 -0
  184. package/docs/observability-collector-smoke.md +31 -0
  185. package/docs/observability-framework-examples.md +98 -0
  186. package/docs/observability.md +542 -0
  187. package/docs/otel-collector-smoke.yaml +27 -0
  188. package/docs/performance-profiler.md +199 -0
  189. package/docs/production-readiness.md +73 -0
  190. package/docs/recipes/README.md +12 -0
  191. package/docs/recipes/http-server.md +45 -0
  192. package/docs/recipes/layers.md +44 -0
  193. package/docs/recipes/performance.md +47 -0
  194. package/docs/recipes/runtime.md +41 -0
  195. package/docs/recipes/testing.md +41 -0
  196. package/docs/release.md +53 -0
  197. package/docs/wasm-bounded-queues.md +44 -0
  198. package/docs/wasm-engine-observability-benchmarks.md +85 -0
  199. package/docs/wasm-fiber-engine.md +117 -0
  200. package/docs/wasm-scheduler-state-machine.md +122 -0
  201. package/docs/wasm-stream-chunks.md +54 -0
  202. package/package.json +48 -2
  203. package/dist/chunk-AR22SXML.js +0 -1043
  204. package/dist/chunk-BDYEENHT.js +0 -224
  205. package/dist/chunk-JFPU5GQI.mjs +0 -1043
  206. package/dist/chunk-MS34J5LY.cjs +0 -224
  207. package/dist/chunk-UMAZLXAB.mjs +0 -224
  208. package/dist/chunk-XPZNXSVN.cjs +0 -1043
  209. package/dist/tracing-DNT9jEbr.d.ts +0 -106
@@ -0,0 +1,683 @@
1
+ import {
2
+ liveClock,
3
+ runtimeClockFromEnv,
4
+ unsafeGetCurrentRuntime
5
+ } from "./chunk-FH2X7BVP.js";
6
+ import {
7
+ Async,
8
+ asyncEffect,
9
+ asyncFail,
10
+ asyncFlatMap,
11
+ asyncFold,
12
+ asyncSucceed
13
+ } from "./chunk-UB4B6OFY.js";
14
+
15
+ // src/core/runtime/combinators.ts
16
+ function sleep(ms) {
17
+ return asyncEffect((env, cb) => {
18
+ const clock = runtimeClockFromEnv(env);
19
+ const id = clock.setTimeout(() => cb({ _tag: "Success", value: void 0 }), ms);
20
+ return () => clock.clearTimeout(id);
21
+ });
22
+ }
23
+ function timeout(effect, ms) {
24
+ return asyncEffect((env, cb) => {
25
+ const clock = runtimeClockFromEnv(env);
26
+ let done = false;
27
+ let timerId;
28
+ let fiber;
29
+ timerId = clock.setTimeout(() => {
30
+ if (done) return;
31
+ done = true;
32
+ fiber?.interrupt();
33
+ cb({
34
+ _tag: "Failure",
35
+ cause: { _tag: "Fail", error: { _tag: "TimeoutError", ms } }
36
+ });
37
+ }, ms);
38
+ const runtime = unsafeGetCurrentRuntime();
39
+ fiber = runtime.fork(effect);
40
+ fiber.join((exit) => {
41
+ if (done) return;
42
+ done = true;
43
+ clock.clearTimeout(timerId);
44
+ cb(exit);
45
+ });
46
+ return () => {
47
+ if (done) return;
48
+ done = true;
49
+ clock.clearTimeout(timerId);
50
+ fiber.interrupt();
51
+ };
52
+ });
53
+ }
54
+ function retry(effect, policy) {
55
+ const shouldRetry = policy.shouldRetry ?? (() => true);
56
+ const jitter2 = policy.jitter ?? "full";
57
+ const maxElapsedMs = policy.maxElapsedMs;
58
+ const computeDelay = (attempt) => {
59
+ const exp = policy.baseDelayMs * Math.pow(2, attempt);
60
+ const capped = Math.min(exp, policy.maxDelayMs);
61
+ if (jitter2 === "none") return capped;
62
+ return Math.floor(Math.random() * capped);
63
+ };
64
+ const loop = (attempt, startedAt, clock) => asyncFold(
65
+ effect,
66
+ (error) => {
67
+ if (attempt >= policy.maxRetries) return asyncFail(error);
68
+ if (!shouldRetry(error, attempt)) return asyncFail(error);
69
+ if (maxElapsedMs !== void 0) {
70
+ const elapsed2 = clock.now() - startedAt;
71
+ if (elapsed2 >= maxElapsedMs) return asyncFail(error);
72
+ }
73
+ const delay = computeDelay(attempt);
74
+ return asyncFlatMap(sleep(delay), () => loop(attempt + 1, startedAt, clock));
75
+ },
76
+ (value) => asyncSucceed(value)
77
+ );
78
+ return asyncFlatMap(
79
+ { _tag: "Sync", thunk: (env) => {
80
+ const clock = runtimeClockFromEnv(env);
81
+ return { clock, startedAt: clock.now() };
82
+ } },
83
+ ({ clock, startedAt }) => loop(0, startedAt, clock)
84
+ );
85
+ }
86
+ function retryN(effect, n) {
87
+ return retry(effect, {
88
+ maxRetries: n,
89
+ baseDelayMs: 0,
90
+ maxDelayMs: 0,
91
+ jitter: "none"
92
+ });
93
+ }
94
+ function retryWithBackoff(effect, opts = {}) {
95
+ return retry(effect, {
96
+ maxRetries: opts.maxRetries ?? 3,
97
+ baseDelayMs: opts.baseDelayMs ?? 100,
98
+ maxDelayMs: opts.maxDelayMs ?? 1e4,
99
+ maxElapsedMs: opts.maxElapsedMs,
100
+ shouldRetry: opts.shouldRetry,
101
+ jitter: "full"
102
+ });
103
+ }
104
+
105
+ // src/core/runtime/schedule.ts
106
+ function recurs(n) {
107
+ return {
108
+ _tag: "Schedule",
109
+ initial: () => 0,
110
+ step: (count, _input) => {
111
+ const next = count + 1;
112
+ return [{ continue: next < n, delayMs: 0 }, next, next];
113
+ }
114
+ };
115
+ }
116
+ function forever() {
117
+ return {
118
+ _tag: "Schedule",
119
+ initial: () => 0,
120
+ step: (count) => {
121
+ const next = count + 1;
122
+ return [{ continue: true, delayMs: 0 }, next, next];
123
+ }
124
+ };
125
+ }
126
+ function never() {
127
+ return {
128
+ _tag: "Schedule",
129
+ initial: () => 0,
130
+ step: (count) => {
131
+ const next = count + 1;
132
+ return [{ continue: false, delayMs: 0 }, next, next];
133
+ }
134
+ };
135
+ }
136
+ function once() {
137
+ return {
138
+ _tag: "Schedule",
139
+ initial: () => 0,
140
+ step: (count) => {
141
+ const next = count + 1;
142
+ return [{ continue: count === 0, delayMs: 0 }, next, next];
143
+ }
144
+ };
145
+ }
146
+ function fixed(delayMs) {
147
+ const delay = normalizeDelay(delayMs);
148
+ return {
149
+ _tag: "Schedule",
150
+ initial: () => 0,
151
+ step: (count, _input) => {
152
+ return [{ continue: true, delayMs: delay }, count + 1, count + 1];
153
+ }
154
+ };
155
+ }
156
+ var spaced = fixed;
157
+ function exponential(baseMs, maxMs = Infinity) {
158
+ const base = Math.max(0, baseMs);
159
+ const cap = normalizeCap(maxMs);
160
+ return {
161
+ _tag: "Schedule",
162
+ initial: () => 0,
163
+ step: (count, _input) => {
164
+ const delay = Math.min(base * Math.pow(2, count), cap);
165
+ return [{ continue: true, delayMs: delay }, count + 1, count + 1];
166
+ }
167
+ };
168
+ }
169
+ function linear(baseMs, maxMs = Infinity) {
170
+ const base = Math.max(0, baseMs);
171
+ const cap = normalizeCap(maxMs);
172
+ return {
173
+ _tag: "Schedule",
174
+ initial: () => 0,
175
+ step: (count, _input) => {
176
+ const next = count + 1;
177
+ return [{ continue: true, delayMs: Math.min(base * next, cap) }, next, next];
178
+ }
179
+ };
180
+ }
181
+ function fibonacci(baseMs, maxMs = Infinity) {
182
+ const base = Math.max(0, baseMs);
183
+ const cap = normalizeCap(maxMs);
184
+ return {
185
+ _tag: "Schedule",
186
+ initial: () => ({ prev: 0, curr: 1, count: 0 }),
187
+ step: (state, _input) => {
188
+ const delay = Math.min(base * state.curr, cap);
189
+ const next = {
190
+ prev: state.curr,
191
+ curr: state.prev + state.curr,
192
+ count: state.count + 1
193
+ };
194
+ return [{ continue: true, delayMs: delay }, next, state.count + 1];
195
+ }
196
+ };
197
+ }
198
+ function jittered(baseMs, maxMs = Infinity) {
199
+ return jitteredSchedule(exponential(baseMs, maxMs), { factor: 1 });
200
+ }
201
+ function elapsed(maxMs) {
202
+ const max = Math.max(0, maxMs);
203
+ return {
204
+ _tag: "Schedule",
205
+ initial: (context) => nowFromContext(context),
206
+ step: (startedAt, _input, context) => {
207
+ const el = nowFromContext(context) - startedAt;
208
+ return [{ continue: el < max, delayMs: 0 }, startedAt, el];
209
+ }
210
+ };
211
+ }
212
+ function whileInput(pred) {
213
+ return {
214
+ _tag: "Schedule",
215
+ initial: () => void 0,
216
+ step: (_state, input) => {
217
+ return [{ continue: pred(input), delayMs: 0 }, void 0, input];
218
+ }
219
+ };
220
+ }
221
+ function untilInput(pred) {
222
+ return {
223
+ _tag: "Schedule",
224
+ initial: () => void 0,
225
+ step: (_state, input) => {
226
+ return [{ continue: !pred(input), delayMs: 0 }, void 0, input];
227
+ }
228
+ };
229
+ }
230
+ function take(schedule, n) {
231
+ const limit = Math.max(0, Math.floor(n));
232
+ return {
233
+ _tag: "Schedule",
234
+ name: schedule.name,
235
+ initial: (context) => ({ inner: schedule.initial(context), count: 0 }),
236
+ step: (state, input, context) => {
237
+ if (state.count >= limit) return [{ continue: false, delayMs: 0 }, state, void 0];
238
+ const [decision, nextInner, output] = schedule.step(state.inner, input, context);
239
+ const nextState = { inner: nextInner, count: state.count + 1 };
240
+ return [{ continue: decision.continue && state.count + 1 < limit, delayMs: decision.delayMs }, nextState, output];
241
+ }
242
+ };
243
+ }
244
+ function map(schedule, f) {
245
+ return {
246
+ _tag: "Schedule",
247
+ name: schedule.name,
248
+ initial: schedule.initial,
249
+ step: (state, input, context) => {
250
+ const [decision, nextState, output] = schedule.step(state, input, context);
251
+ return [decision, nextState, f(output)];
252
+ }
253
+ };
254
+ }
255
+ function contramap(schedule, f) {
256
+ return {
257
+ _tag: "Schedule",
258
+ name: schedule.name,
259
+ initial: schedule.initial,
260
+ step: (state, input, context) => schedule.step(state, f(input), context)
261
+ };
262
+ }
263
+ function jitteredSchedule(schedule, options = {}) {
264
+ const factor = typeof options === "number" ? options : options.factor ?? 1;
265
+ const random = typeof options === "number" ? Math.random : options.random ?? Math.random;
266
+ const spread = Math.max(0, factor);
267
+ return {
268
+ _tag: "Schedule",
269
+ name: schedule.name,
270
+ initial: schedule.initial,
271
+ step: (state, input, context) => {
272
+ const [decision, nextState, output] = schedule.step(state, input, context);
273
+ if (!decision.continue || decision.delayMs <= 0 || spread === 0) {
274
+ return [decision, nextState, output];
275
+ }
276
+ const delay = spread >= 1 ? Math.floor(random() * decision.delayMs) : Math.floor(decision.delayMs * (1 - spread + random() * spread * 2));
277
+ return [{ ...decision, delayMs: Math.max(0, delay) }, nextState, output];
278
+ }
279
+ };
280
+ }
281
+ var jitter = jitteredSchedule;
282
+ function windowed(schedule, windowMs, clock) {
283
+ const window = Math.max(0, windowMs);
284
+ return {
285
+ _tag: "Schedule",
286
+ name: schedule.name,
287
+ initial: (context) => ({ inner: schedule.initial(context), windowStartedAt: clockNow(clock, context) }),
288
+ step: (state, input, context) => {
289
+ const now = clockNow(clock, context);
290
+ const shouldReset = window > 0 && now - state.windowStartedAt > window;
291
+ const inner = shouldReset ? schedule.initial(context) : state.inner;
292
+ const windowStartedAt = shouldReset ? now : state.windowStartedAt;
293
+ const [decision, nextInner, output] = schedule.step(inner, input, context);
294
+ return [decision, { inner: nextInner, windowStartedAt }, output];
295
+ }
296
+ };
297
+ }
298
+ function maxDelay(schedule, maxMs) {
299
+ const cap = Math.max(0, maxMs);
300
+ return {
301
+ _tag: "Schedule",
302
+ name: schedule.name,
303
+ initial: schedule.initial,
304
+ step: (state, input, context) => {
305
+ const [decision, nextState, output] = schedule.step(state, input, context);
306
+ return [{ ...decision, delayMs: Math.min(decision.delayMs, cap) }, nextState, output];
307
+ }
308
+ };
309
+ }
310
+ function maxElapsed(schedule, maxMs) {
311
+ const max = Math.max(0, maxMs);
312
+ return {
313
+ _tag: "Schedule",
314
+ name: schedule.name,
315
+ initial: (context) => ({ inner: schedule.initial(context), startedAt: nowFromContext(context) }),
316
+ step: (state, input, context) => {
317
+ const now = nowFromContext(context);
318
+ const elapsedMs = Math.max(0, now - state.startedAt);
319
+ if (elapsedMs >= max) return [{ continue: false, delayMs: 0 }, state, void 0];
320
+ const [decision, nextInner, output] = schedule.step(state.inner, input, context);
321
+ const remaining = Math.max(0, max - elapsedMs);
322
+ return [
323
+ { ...decision, continue: decision.continue && remaining > 0, delayMs: Math.min(decision.delayMs, remaining) },
324
+ { inner: nextInner, startedAt: state.startedAt },
325
+ output
326
+ ];
327
+ }
328
+ };
329
+ }
330
+ var upTo = maxElapsed;
331
+ function whileOutput(schedule, pred) {
332
+ return {
333
+ _tag: "Schedule",
334
+ name: schedule.name,
335
+ initial: schedule.initial,
336
+ step: (state, input, context) => {
337
+ const [decision, nextState, output] = schedule.step(state, input, context);
338
+ return [{ ...decision, continue: decision.continue && pred(output) }, nextState, output];
339
+ }
340
+ };
341
+ }
342
+ function untilOutput(schedule, pred) {
343
+ return whileOutput(schedule, (output) => !pred(output));
344
+ }
345
+ function named(name, schedule) {
346
+ return {
347
+ _tag: "Schedule",
348
+ name,
349
+ initial: schedule.initial,
350
+ step: schedule.step
351
+ };
352
+ }
353
+ function tapDecision(schedule, tap) {
354
+ return {
355
+ _tag: "Schedule",
356
+ name: schedule.name,
357
+ initial: schedule.initial,
358
+ step: (state, input, context) => {
359
+ const [decision, nextState, output] = schedule.step(state, input, context);
360
+ const enriched = enrichDecision(decision, context, schedule.name);
361
+ safeObserve(tap, {
362
+ name: enriched.name,
363
+ input,
364
+ output,
365
+ decision: enriched,
366
+ attempt: enriched.attempt ?? context?.attempt ?? 0,
367
+ elapsedMs: enriched.elapsedMs ?? elapsedFromContext(context),
368
+ state,
369
+ nextState,
370
+ timestamp: wallClockNow()
371
+ });
372
+ return [decision, nextState, output];
373
+ }
374
+ };
375
+ }
376
+ function andThen(first, second) {
377
+ return {
378
+ _tag: "Schedule",
379
+ name: first.name ?? second.name,
380
+ initial: (context) => ({ phase: "first", inner: first.initial(context) }),
381
+ step: (state, input, context) => {
382
+ if (state.phase === "first") {
383
+ const [decision2, nextInner2, output2] = first.step(state.inner, input, context);
384
+ if (decision2.continue) {
385
+ return [decision2, { phase: "first", inner: nextInner2 }, output2];
386
+ }
387
+ return [{ continue: true, delayMs: decision2.delayMs }, { phase: "second", inner: second.initial(context) }, output2];
388
+ }
389
+ const [decision, nextInner, output] = second.step(state.inner, input, context);
390
+ return [decision, { phase: "second", inner: nextInner }, output];
391
+ }
392
+ };
393
+ }
394
+ function intersect(left, right) {
395
+ return {
396
+ _tag: "Schedule",
397
+ name: left.name ?? right.name,
398
+ initial: (context) => ({ left: left.initial(context), right: right.initial(context) }),
399
+ step: (state, input, context) => {
400
+ const [ld, ls, lo] = left.step(state.left, input, context);
401
+ const [rd, rs, ro] = right.step(state.right, input, context);
402
+ const cont = ld.continue && rd.continue;
403
+ const delay = Math.max(ld.delayMs, rd.delayMs);
404
+ return [{ continue: cont, delayMs: delay }, { left: ls, right: rs }, [lo, ro]];
405
+ }
406
+ };
407
+ }
408
+ function union(left, right) {
409
+ return {
410
+ _tag: "Schedule",
411
+ name: left.name ?? right.name,
412
+ initial: (context) => ({ left: left.initial(context), right: right.initial(context) }),
413
+ step: (state, input, context) => {
414
+ const [ld, ls, lo] = left.step(state.left, input, context);
415
+ const [rd, rs, ro] = right.step(state.right, input, context);
416
+ const cont = ld.continue || rd.continue;
417
+ const delay = Math.min(ld.delayMs, rd.delayMs);
418
+ return [{ continue: cont, delayMs: delay }, { left: ls, right: rs }, [lo, ro]];
419
+ }
420
+ };
421
+ }
422
+ function makeScheduleDriver(schedule, options = {}) {
423
+ const clock = options.clock ?? liveClock;
424
+ let startedAtMs = options.startedAtMs ?? clock.now();
425
+ let attempt = 0;
426
+ let lastDecision;
427
+ let state = schedule.initial(makeContext(clock, startedAtMs, attempt, options.name ?? schedule.name));
428
+ return {
429
+ next: (input) => {
430
+ const currentState = state;
431
+ const context = makeContext(clock, startedAtMs, attempt, options.name ?? schedule.name);
432
+ const [decision, nextState, output] = schedule.step(currentState, input, context);
433
+ const enriched = enrichDecision(decision, context, schedule.name);
434
+ state = nextState;
435
+ const result = {
436
+ continue: enriched.continue,
437
+ delayMs: enriched.delayMs,
438
+ output,
439
+ decision: enriched,
440
+ attempt: enriched.attempt ?? attempt,
441
+ elapsedMs: enriched.elapsedMs ?? elapsedFromContext(context),
442
+ state: nextState
443
+ };
444
+ lastDecision = result;
445
+ const event = {
446
+ name: enriched.name,
447
+ input,
448
+ output,
449
+ decision: enriched,
450
+ attempt: result.attempt,
451
+ elapsedMs: result.elapsedMs,
452
+ state: currentState,
453
+ nextState,
454
+ timestamp: wallClockNow()
455
+ };
456
+ observeDriverDecision(event, options);
457
+ attempt++;
458
+ return result;
459
+ },
460
+ reset: () => {
461
+ startedAtMs = clock.now();
462
+ attempt = 0;
463
+ lastDecision = void 0;
464
+ state = schedule.initial(makeContext(clock, startedAtMs, attempt, options.name ?? schedule.name));
465
+ },
466
+ snapshot: () => ({
467
+ name: options.name ?? schedule.name,
468
+ attempt,
469
+ elapsedMs: Math.max(0, clock.now() - startedAtMs),
470
+ state,
471
+ last: lastDecision
472
+ }),
473
+ state: () => state,
474
+ last: () => lastDecision
475
+ };
476
+ }
477
+ var scheduleDriver = makeScheduleDriver;
478
+ function runSchedule(schedule, inputs, options = {}) {
479
+ const driver = makeScheduleDriver(schedule, options);
480
+ const decisions = [];
481
+ for (const input of inputs) {
482
+ const next = driver.next(input);
483
+ decisions.push(next);
484
+ if (!next.continue) break;
485
+ }
486
+ return decisions;
487
+ }
488
+ function driverFromRuntime(schedule, options = {}) {
489
+ return Async.sync((env) => makeScheduleDriver(schedule, {
490
+ ...options,
491
+ clock: options.clock ?? runtimeClockFromEnv(env)
492
+ }));
493
+ }
494
+ function retryWithSchedule(effect, schedule, options = {}) {
495
+ return asyncFlatMap(driverFromRuntime(schedule, options), (driver) => {
496
+ const loop = () => asyncFold(
497
+ effect,
498
+ (error) => {
499
+ const next = driver.next(error);
500
+ if (!next.continue) return asyncFail(error);
501
+ if (next.delayMs <= 0) return loop();
502
+ return asyncFlatMap(sleep(next.delayMs), () => loop());
503
+ },
504
+ (value) => asyncSucceed(value)
505
+ );
506
+ return loop();
507
+ });
508
+ }
509
+ var retry2 = retryWithSchedule;
510
+ function repeatWithSchedule(effect, schedule, options = {}) {
511
+ return asyncFlatMap(driverFromRuntime(schedule, options), (driver) => {
512
+ const loop = (lastValue) => {
513
+ const next = driver.next(lastValue);
514
+ if (!next.continue) return asyncSucceed(lastValue);
515
+ if (next.delayMs <= 0) {
516
+ return asyncFold(
517
+ effect,
518
+ (error) => asyncFail(error),
519
+ (value) => loop(value)
520
+ );
521
+ }
522
+ return asyncFlatMap(
523
+ sleep(next.delayMs),
524
+ () => asyncFold(
525
+ effect,
526
+ (error) => asyncFail(error),
527
+ (value) => loop(value)
528
+ )
529
+ );
530
+ };
531
+ return asyncFold(
532
+ effect,
533
+ (error) => asyncFail(error),
534
+ (value) => loop(value)
535
+ );
536
+ });
537
+ }
538
+ var repeat = repeatWithSchedule;
539
+ var poll = repeatWithSchedule;
540
+ function normalizeDelay(ms) {
541
+ if (!Number.isFinite(ms)) return 0;
542
+ return Math.max(0, Math.floor(ms));
543
+ }
544
+ function normalizeCap(ms) {
545
+ if (ms === Infinity) return Infinity;
546
+ return normalizeDelay(ms);
547
+ }
548
+ function defaultClock() {
549
+ return liveClock.now();
550
+ }
551
+ function nowFromContext(context) {
552
+ return context?.clock.now() ?? defaultClock();
553
+ }
554
+ function clockNow(clock, context) {
555
+ return clock ? clock() : nowFromContext(context);
556
+ }
557
+ function elapsedFromContext(context) {
558
+ if (!context) return 0;
559
+ return Math.max(0, context.clock.now() - context.startedAtMs);
560
+ }
561
+ function makeContext(clock, startedAtMs, attempt, name) {
562
+ return { clock, startedAtMs, attempt, name };
563
+ }
564
+ function enrichDecision(decision, context, fallbackName) {
565
+ const delayMs = normalizeDelay(decision.delayMs);
566
+ return {
567
+ ...decision,
568
+ continue: decision.continue,
569
+ delayMs,
570
+ attempt: decision.attempt ?? context?.attempt,
571
+ elapsedMs: decision.elapsedMs ?? elapsedFromContext(context),
572
+ name: decision.name ?? context?.name ?? fallbackName
573
+ };
574
+ }
575
+ function wallClockNow() {
576
+ return Date.now();
577
+ }
578
+ function safeObserve(observer, event) {
579
+ try {
580
+ observer(event);
581
+ } catch {
582
+ }
583
+ }
584
+ function observeDriverDecision(event, options) {
585
+ if (options.onDecision) safeObserve(options.onDecision, event);
586
+ if (!options.hooks) return;
587
+ try {
588
+ options.hooks.emit({
589
+ type: "schedule.decision",
590
+ name: event.name,
591
+ attempt: event.attempt,
592
+ elapsedMs: event.elapsedMs,
593
+ delayMs: event.decision.delayMs,
594
+ continue: event.decision.continue,
595
+ reason: event.decision.reason,
596
+ ...options.captureInput ? { input: event.input } : {},
597
+ ...options.captureOutput ? { output: event.output } : {}
598
+ }, options.emitContext ?? {});
599
+ } catch {
600
+ }
601
+ }
602
+ var Schedule = Object.freeze({
603
+ driver: makeScheduleDriver,
604
+ run: runSchedule,
605
+ recurs,
606
+ forever,
607
+ never,
608
+ once,
609
+ fixed,
610
+ spaced,
611
+ linear,
612
+ exponential,
613
+ fibonacci,
614
+ jittered,
615
+ jitteredSchedule,
616
+ jitter,
617
+ elapsed,
618
+ whileInput,
619
+ untilInput,
620
+ whileOutput,
621
+ untilOutput,
622
+ take,
623
+ map,
624
+ contramap,
625
+ maxDelay,
626
+ maxElapsed,
627
+ upTo,
628
+ windowed,
629
+ named,
630
+ tapDecision,
631
+ andThen,
632
+ intersect,
633
+ union,
634
+ retry: retryWithSchedule,
635
+ repeat: repeatWithSchedule,
636
+ poll: repeatWithSchedule
637
+ });
638
+
639
+ export {
640
+ sleep,
641
+ timeout,
642
+ retry,
643
+ retryN,
644
+ retryWithBackoff,
645
+ recurs,
646
+ forever,
647
+ never,
648
+ once,
649
+ fixed,
650
+ spaced,
651
+ exponential,
652
+ linear,
653
+ fibonacci,
654
+ jittered,
655
+ elapsed,
656
+ whileInput,
657
+ untilInput,
658
+ take,
659
+ map,
660
+ contramap,
661
+ jitteredSchedule,
662
+ jitter,
663
+ windowed,
664
+ maxDelay,
665
+ maxElapsed,
666
+ upTo,
667
+ whileOutput,
668
+ untilOutput,
669
+ named,
670
+ tapDecision,
671
+ andThen,
672
+ intersect,
673
+ union,
674
+ makeScheduleDriver,
675
+ scheduleDriver,
676
+ runSchedule,
677
+ retryWithSchedule,
678
+ retry2,
679
+ repeatWithSchedule,
680
+ repeat,
681
+ poll,
682
+ Schedule
683
+ };