brass-runtime 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +287 -23
  3. package/dist/agent/cli/main.cjs +38 -38
  4. package/dist/agent/cli/main.js +6 -6
  5. package/dist/agent/cli/main.mjs +6 -6
  6. package/dist/agent/index.cjs +7 -7
  7. package/dist/agent/index.d.ts +1 -1
  8. package/dist/agent/index.js +6 -6
  9. package/dist/agent/index.mjs +6 -6
  10. package/dist/chunk-2HQTDLHF.mjs +683 -0
  11. package/dist/chunk-36I3M4UC.mjs +370 -0
  12. package/dist/{chunk-QY5FKYEQ.js → chunk-3AYM6WPJ.js} +570 -51
  13. package/dist/chunk-3LOYJFRR.cjs +300 -0
  14. package/dist/chunk-3Y2RIUMM.js +300 -0
  15. package/dist/{chunk-7XOPAB5Q.js → chunk-4P2HHGAX.mjs} +83 -5
  16. package/dist/{chunk-N6VHMOWB.cjs → chunk-4ROBZFL6.cjs} +128 -128
  17. package/dist/{chunk-NC5SDRYE.js → chunk-52OB2ROS.js} +4 -4
  18. package/dist/{chunk-JX3LZQJH.cjs → chunk-52PPNNI4.cjs} +82 -20
  19. package/dist/{chunk-5YOQOXEQ.cjs → chunk-5EC274J5.cjs} +676 -293
  20. package/dist/chunk-5QC7LRZ3.js +229 -0
  21. package/dist/{chunk-7TL2LHQJ.js → chunk-5VRJNBLZ.mjs} +524 -141
  22. package/dist/chunk-62AZW6UT.cjs +313 -0
  23. package/dist/chunk-6IXXWIUM.js +683 -0
  24. package/dist/chunk-6RY2FFN4.mjs +2024 -0
  25. package/dist/chunk-74ZTY6CP.js +2871 -0
  26. package/dist/chunk-7CMJS3QE.mjs +2871 -0
  27. package/dist/{chunk-2WC63LJK.mjs → chunk-7JIJOVCT.js} +20 -10
  28. package/dist/chunk-7X3K5RMS.js +2024 -0
  29. package/dist/chunk-7ZPEZ57L.cjs +2024 -0
  30. package/dist/{chunk-FM4W4QPL.js → chunk-A2OM6NEH.mjs} +5 -4
  31. package/dist/chunk-AGR5B2BC.cjs +683 -0
  32. package/dist/chunk-B33ICAKP.js +313 -0
  33. package/dist/{chunk-J3H54ZRV.mjs → chunk-B5JD23U7.mjs} +1 -1
  34. package/dist/{chunk-F5EUMJL7.mjs → chunk-BKK77SBA.js} +83 -5
  35. package/dist/{chunk-U5KWK3PX.mjs → chunk-C3MDXTRZ.js} +11 -0
  36. package/dist/{chunk-SPUEME2B.cjs → chunk-CZIVE6NT.cjs} +12 -1
  37. package/dist/{chunk-TDVMADDN.js → chunk-DNFJLJMW.mjs} +11 -0
  38. package/dist/{chunk-XDZOO4L5.js → chunk-EJ6BPYVR.mjs} +79 -17
  39. package/dist/chunk-EOC4UHBS.mjs +229 -0
  40. package/dist/chunk-F6XWZQY4.cjs +777 -0
  41. package/dist/{chunk-7LVI2GIN.js → chunk-FH2X7BVP.js} +507 -72
  42. package/dist/{chunk-OOGJ73B6.js → chunk-FHQGHPMO.mjs} +20 -10
  43. package/dist/{chunk-WQ5QNU5R.cjs → chunk-GLE2WY7Z.cjs} +652 -217
  44. package/dist/{chunk-G6IQOE4P.mjs → chunk-GYM3LLGS.mjs} +507 -72
  45. package/dist/{chunk-TVN5I4U6.cjs → chunk-JF5WGYJJ.cjs} +25 -24
  46. package/dist/{chunk-CY33PGEX.mjs → chunk-KH4SYAOS.mjs} +570 -51
  47. package/dist/chunk-KN32XNTH.mjs +313 -0
  48. package/dist/chunk-KQLYONSE.cjs +2871 -0
  49. package/dist/{chunk-7HUOJA4W.cjs → chunk-KZJQ723N.cjs} +90 -80
  50. package/dist/{chunk-CCKHV5BT.mjs → chunk-L2SYFEBS.js} +5 -4
  51. package/dist/{chunk-IJT6RRQ5.cjs → chunk-L6VB5N7Q.cjs} +20 -9
  52. package/dist/{chunk-ZGLD4TVZ.mjs → chunk-MBEJI5HF.mjs} +4 -4
  53. package/dist/{chunk-PRWCB3QL.mjs → chunk-MIIYDLGM.js} +524 -141
  54. package/dist/{chunk-H55LI6WY.js → chunk-MOO4L7F4.mjs} +15 -4
  55. package/dist/chunk-MVGUEJ5Z.cjs +370 -0
  56. package/dist/chunk-PD4EJTQC.cjs +229 -0
  57. package/dist/chunk-PWC3RBQE.mjs +300 -0
  58. package/dist/{chunk-MWXMNYJS.cjs → chunk-Q2I37RP3.cjs} +643 -124
  59. package/dist/{chunk-VFIUZG7J.mjs → chunk-RKGKFN2A.js} +79 -17
  60. package/dist/{chunk-NYL4D7SK.cjs → chunk-SA6HUJVI.cjs} +5 -5
  61. package/dist/chunk-SK7UZRNI.mjs +777 -0
  62. package/dist/{chunk-K2T3DV26.mjs → chunk-TRM4JUZQ.js} +15 -4
  63. package/dist/chunk-UB4B6OFY.js +370 -0
  64. package/dist/{chunk-G3XGCZDQ.js → chunk-UCUBNWM2.js} +1 -1
  65. package/dist/chunk-VWIPB6I5.js +777 -0
  66. package/dist/{chunk-JNFRRJYH.cjs → chunk-WBGRHGBP.cjs} +270 -192
  67. package/dist/{client-CtFmoDvM.d.ts → client-CZHU674n.d.ts} +211 -36
  68. package/dist/core/index.cjs +135 -9
  69. package/dist/core/index.d.ts +238 -33
  70. package/dist/core/index.js +155 -29
  71. package/dist/core/index.mjs +155 -29
  72. package/dist/{effect-CGNl5Rqp.d.ts → effect-DIUHZ9IN.d.ts} +89 -1
  73. package/dist/effectRunner-CFLC32IK.cjs +8 -0
  74. package/dist/{effectRunner-A4CHJXJI.js → effectRunner-L4S7IPT3.js} +2 -2
  75. package/dist/{effectRunner-OPUF6QRN.mjs → effectRunner-NNGG75QA.mjs} +2 -2
  76. package/dist/http/index.cjs +324 -2986
  77. package/dist/http/index.d.ts +54 -68
  78. package/dist/http/index.js +238 -2900
  79. package/dist/http/index.mjs +238 -2900
  80. package/dist/http/testing.cjs +14 -12
  81. package/dist/http/testing.d.ts +5 -4
  82. package/dist/http/testing.js +10 -8
  83. package/dist/http/testing.mjs +10 -8
  84. package/dist/index.cjs +423 -255
  85. package/dist/index.d.ts +87 -69
  86. package/dist/index.js +301 -133
  87. package/dist/index.mjs +301 -133
  88. package/dist/observability/index.cjs +18 -531
  89. package/dist/observability/index.d.ts +81 -8
  90. package/dist/observability/index.js +25 -538
  91. package/dist/observability/index.mjs +25 -538
  92. package/dist/perf/cli.cjs +401 -0
  93. package/dist/perf/cli.d.ts +1 -0
  94. package/dist/perf/cli.js +401 -0
  95. package/dist/perf/cli.mjs +401 -0
  96. package/dist/perf/index.cjs +141 -0
  97. package/dist/perf/index.d.ts +483 -0
  98. package/dist/perf/index.js +141 -0
  99. package/dist/perf/index.mjs +141 -0
  100. package/dist/schedule-CK3Ml_7p.d.ts +259 -0
  101. package/dist/schema/index.cjs +6 -2
  102. package/dist/schema/index.d.ts +3 -1
  103. package/dist/schema/index.js +5 -1
  104. package/dist/schema/index.mjs +5 -1
  105. package/dist/{server-C8hDXA74.d.ts → server-D6JZ15_e.d.ts} +16 -4
  106. package/dist/{stream-dvSs0QS5.d.ts → stream-B4oK9JFP.d.ts} +1 -1
  107. package/dist/{tracer-B5tRH9H7.d.ts → tracer-Hwt1cl7h.d.ts} +13 -54
  108. package/dist/{tracing-Dt9S_6V8.d.ts → tracing-DqbTKGcf.d.ts} +1 -1
  109. package/docs/ARCHITECTURE.md +292 -0
  110. package/docs/README.md +65 -0
  111. package/docs/adr/0001-ai-context-pack.md +32 -0
  112. package/docs/agent-apply-mode.md +104 -0
  113. package/docs/agent-approvals.md +110 -0
  114. package/docs/agent-batch.md +185 -0
  115. package/docs/agent-boundaries.md +112 -0
  116. package/docs/agent-chat-sessions.md +160 -0
  117. package/docs/agent-ci.md +17 -0
  118. package/docs/agent-cli.md +405 -0
  119. package/docs/agent-config.md +480 -0
  120. package/docs/agent-context-discovery.md +159 -0
  121. package/docs/agent-copilot-like-dx.md +126 -0
  122. package/docs/agent-declarative-optimized-planning.md +138 -0
  123. package/docs/agent-dx.md +224 -0
  124. package/docs/agent-env-files.md +126 -0
  125. package/docs/agent-follow-up-context.md +43 -0
  126. package/docs/agent-global-usage.md +180 -0
  127. package/docs/agent-init.md +109 -0
  128. package/docs/agent-install-and-configure.md +516 -0
  129. package/docs/agent-language-workspace-ux.md +99 -0
  130. package/docs/agent-llm-adapters.md +123 -0
  131. package/docs/agent-local-install.md +190 -0
  132. package/docs/agent-local-tests.md +51 -0
  133. package/docs/agent-observability.md +155 -0
  134. package/docs/agent-patch-quality-loop.md +162 -0
  135. package/docs/agent-presets.md +22 -0
  136. package/docs/agent-project-commands.md +237 -0
  137. package/docs/agent-project-intelligence.md +156 -0
  138. package/docs/agent-redaction.md +18 -0
  139. package/docs/agent-release-readiness.md +76 -0
  140. package/docs/agent-rollback-safety.md +162 -0
  141. package/docs/agent-rollback.md +23 -0
  142. package/docs/agent-run-artifacts.md +16 -0
  143. package/docs/agent-vscode-auto-discovery.md +137 -0
  144. package/docs/agent-vscode-batch-runner.md +100 -0
  145. package/docs/agent-vscode-chat-layout.md +90 -0
  146. package/docs/agent-vscode-clean-install.md +147 -0
  147. package/docs/agent-vscode-code-actions.md +70 -0
  148. package/docs/agent-vscode-diff-preview.md +45 -0
  149. package/docs/agent-vscode-inline-assist.md +56 -0
  150. package/docs/agent-vscode-install.md +186 -0
  151. package/docs/agent-vscode-model-setup.md +97 -0
  152. package/docs/agent-vscode-patch-preview.md +92 -0
  153. package/docs/agent-vscode-problems.md +79 -0
  154. package/docs/agent-vscode-project-dashboard.md +106 -0
  155. package/docs/agent-vscode-run-history.md +92 -0
  156. package/docs/agent-vscode-ux.md +73 -0
  157. package/docs/ai/INVARIANTS.md +84 -0
  158. package/docs/ai/PROJECT_MAP.md +338 -0
  159. package/docs/ai/PUBLIC_API.md +339 -0
  160. package/docs/ai/VALIDATION_MATRIX.md +67 -0
  161. package/docs/api-polish.md +37 -0
  162. package/docs/cancellation.md +162 -0
  163. package/docs/coverage.md +46 -0
  164. package/docs/framework-integrations.md +38 -0
  165. package/docs/frameworks/angular.md +153 -0
  166. package/docs/frameworks/express.md +125 -0
  167. package/docs/frameworks/fastify.md +124 -0
  168. package/docs/frameworks/nestjs.md +282 -0
  169. package/docs/frameworks/nextjs.md +147 -0
  170. package/docs/frameworks/react.md +139 -0
  171. package/docs/frameworks/vanilla.md +224 -0
  172. package/docs/getting-started.md +159 -0
  173. package/docs/guides/README.md +40 -0
  174. package/docs/guides/circuit-breaker.md +89 -0
  175. package/docs/guides/error-handling.md +91 -0
  176. package/docs/guides/getting-started.md +107 -0
  177. package/docs/guides/layers.md +189 -0
  178. package/docs/guides/metrics.md +101 -0
  179. package/docs/guides/resource-management.md +141 -0
  180. package/docs/guides/retry.md +215 -0
  181. package/docs/guides/semaphore.md +66 -0
  182. package/docs/guides/streams.md +117 -0
  183. package/docs/guides/supervisors.md +98 -0
  184. package/docs/guides/testing.md +162 -0
  185. package/docs/guides/tracing.md +71 -0
  186. package/docs/http-recipes.md +399 -0
  187. package/docs/http.md +749 -0
  188. package/docs/modules.md +285 -0
  189. package/docs/nestjs.md +6 -0
  190. package/docs/observability-collector-smoke.md +31 -0
  191. package/docs/observability-framework-examples.md +110 -0
  192. package/docs/observability.md +649 -0
  193. package/docs/otel-collector-smoke.yaml +27 -0
  194. package/docs/performance-profiler.md +199 -0
  195. package/docs/production-readiness.md +73 -0
  196. package/docs/recipes/README.md +12 -0
  197. package/docs/recipes/http-server.md +45 -0
  198. package/docs/recipes/layers.md +44 -0
  199. package/docs/recipes/performance.md +47 -0
  200. package/docs/recipes/runtime.md +41 -0
  201. package/docs/recipes/testing.md +41 -0
  202. package/docs/release.md +53 -0
  203. package/docs/wasm-bounded-queues.md +44 -0
  204. package/docs/wasm-engine-observability-benchmarks.md +85 -0
  205. package/docs/wasm-fiber-engine.md +117 -0
  206. package/docs/wasm-scheduler-state-machine.md +122 -0
  207. package/docs/wasm-stream-chunks.md +54 -0
  208. package/package.json +22 -2
  209. package/dist/chunk-45F7OKGT.cjs +0 -104
  210. package/dist/chunk-7V4KY4RL.mjs +0 -104
  211. package/dist/chunk-DJQ7OMMB.cjs +0 -144
  212. package/dist/chunk-GOV47PPB.mjs +0 -552
  213. package/dist/chunk-JF4XXPZ5.cjs +0 -552
  214. package/dist/chunk-KCPT2D6G.js +0 -552
  215. package/dist/chunk-NOYZIMUJ.mjs +0 -144
  216. package/dist/chunk-PNVFW245.js +0 -144
  217. package/dist/chunk-ROJC3NBJ.js +0 -104
  218. package/dist/effectRunner-3ZHAD3LE.cjs +0 -8
  219. package/dist/schedule-Fque9Abz.d.ts +0 -70
@@ -0,0 +1,313 @@
1
+ import {
2
+ Scope
3
+ } from "./chunk-L2SYFEBS.js";
4
+ import {
5
+ unsafeGetCurrentRuntime
6
+ } from "./chunk-FH2X7BVP.js";
7
+ import {
8
+ Cause,
9
+ Exit,
10
+ asyncEffect,
11
+ asyncFail,
12
+ asyncFold,
13
+ asyncSucceed,
14
+ unit
15
+ } from "./chunk-UB4B6OFY.js";
16
+
17
+ // src/core/runtime/resource.ts
18
+ function bracket(acquire, use, release) {
19
+ return asyncEffect((env, cb) => {
20
+ const runtime = unsafeGetCurrentRuntime();
21
+ const scope = new Scope(runtime);
22
+ const acquireFiber = scope.fork(acquire);
23
+ acquireFiber.join((acquireExit) => {
24
+ if (acquireExit._tag === "Failure") {
25
+ scope.close(acquireExit);
26
+ cb(acquireExit);
27
+ return;
28
+ }
29
+ const resource2 = acquireExit.value;
30
+ const useFiber = scope.fork(use(resource2));
31
+ useFiber.join((useExit) => {
32
+ const releaseEffect = safeRelease(release, resource2, useExit);
33
+ const releaseFiber = runtime.fork(releaseEffect);
34
+ releaseFiber.join(() => {
35
+ scope.close(useExit);
36
+ cb(useExit);
37
+ });
38
+ });
39
+ });
40
+ return () => {
41
+ scope.close(Exit.failCause(Cause.interrupt()));
42
+ };
43
+ });
44
+ }
45
+ function safeRelease(release, resource2, exit) {
46
+ return asyncFold(
47
+ (() => {
48
+ try {
49
+ return release(resource2, exit);
50
+ } catch {
51
+ return unit();
52
+ }
53
+ })(),
54
+ () => unit(),
55
+ () => unit()
56
+ );
57
+ }
58
+ function ensuring(effect, finalizer) {
59
+ return asyncEffect((env, cb) => {
60
+ const runtime = unsafeGetCurrentRuntime();
61
+ const fiber = runtime.fork(effect);
62
+ fiber.join((exit) => {
63
+ const fin = asyncFold(
64
+ (() => {
65
+ try {
66
+ return finalizer(exit);
67
+ } catch {
68
+ return unit();
69
+ }
70
+ })(),
71
+ () => unit(),
72
+ () => unit()
73
+ );
74
+ runtime.fork(fin).join(() => {
75
+ cb(exit);
76
+ });
77
+ });
78
+ return () => {
79
+ fiber.interrupt();
80
+ };
81
+ });
82
+ }
83
+ function resource(acquire, release) {
84
+ return makeResourceFromUse((body) => bracket(acquire, body, release));
85
+ }
86
+ var makeResource = resource;
87
+ function resourceSucceed(value) {
88
+ return makeResourceFromUse((body) => body(value));
89
+ }
90
+ function resourceFromManaged(m) {
91
+ return makeResourceFromUse((body) => useManaged(m, body));
92
+ }
93
+ function useResource(res, body) {
94
+ return res.use(body);
95
+ }
96
+ function resourceAll(resources) {
97
+ const build = (index) => {
98
+ if (index >= resources.length) return resourceSucceed([]);
99
+ return resources[index].flatMap(
100
+ (head) => build(index + 1).map((tail) => [head, ...tail])
101
+ );
102
+ };
103
+ return build(0).map((values) => values);
104
+ }
105
+ var Resource = Object.freeze({
106
+ make: resource,
107
+ succeed: resourceSucceed,
108
+ fromManaged: resourceFromManaged,
109
+ all: resourceAll,
110
+ use: useResource
111
+ });
112
+ function makeResourceFromUse(use) {
113
+ const self = {
114
+ _tag: "Resource",
115
+ use,
116
+ map: (f) => makeResourceFromUse((body) => self.use((a) => body(f(a)))),
117
+ flatMap: (f) => makeResourceFromUse((body) => self.use((a) => f(a).use(body))),
118
+ zip: (that) => self.flatMap((a) => that.map((b) => [a, b]))
119
+ };
120
+ return self;
121
+ }
122
+ function managed(acquire, release) {
123
+ return {
124
+ _tag: "Managed",
125
+ acquire,
126
+ release: (resource2, exit) => release(resource2, exit)
127
+ };
128
+ }
129
+ function useManaged(m, body) {
130
+ return bracket(m.acquire, body, m.release);
131
+ }
132
+ function managedAll(manageds) {
133
+ const acquire = asyncEffect((env, cb) => {
134
+ const runtime = unsafeGetCurrentRuntime();
135
+ const resources = [];
136
+ let i = 0;
137
+ const acquireNext = () => {
138
+ if (i >= manageds.length) {
139
+ cb({ _tag: "Success", value: resources });
140
+ return;
141
+ }
142
+ const m = manageds[i];
143
+ const fiber = runtime.fork(m.acquire);
144
+ fiber.join((exit) => {
145
+ if (exit._tag === "Failure") {
146
+ releaseAcquired(runtime, manageds, resources, exit).then(() => {
147
+ cb(exit);
148
+ });
149
+ return;
150
+ }
151
+ resources.push(exit.value);
152
+ i++;
153
+ acquireNext();
154
+ });
155
+ };
156
+ acquireNext();
157
+ });
158
+ const release = (resources, exit) => {
159
+ return asyncEffect((_env, cb) => {
160
+ const runtime = unsafeGetCurrentRuntime();
161
+ releaseAcquired(runtime, manageds, resources, exit).then(() => {
162
+ cb({ _tag: "Success", value: void 0 });
163
+ });
164
+ });
165
+ };
166
+ return { _tag: "Managed", acquire, release };
167
+ }
168
+ async function releaseAcquired(runtime, manageds, resources, exit) {
169
+ for (let i = resources.length - 1; i >= 0; i--) {
170
+ try {
171
+ const m = manageds[i];
172
+ await new Promise((resolve) => {
173
+ const releaseEff = asyncFold(
174
+ m.release(resources[i], exit),
175
+ () => unit(),
176
+ () => unit()
177
+ );
178
+ runtime.fork(releaseEff).join(() => resolve());
179
+ });
180
+ } catch {
181
+ }
182
+ }
183
+ }
184
+
185
+ // src/core/runtime/circuitBreaker.ts
186
+ function makeCircuitBreaker(config = {}) {
187
+ const failureThreshold = config.failureThreshold ?? 5;
188
+ const resetTimeoutMs = config.resetTimeoutMs ?? 3e4;
189
+ const successThreshold = config.successThreshold ?? 1;
190
+ const isFailure = config.isFailure ?? (() => true);
191
+ const onStateChange = config.onStateChange;
192
+ let currentState = "closed";
193
+ let consecutiveFailures = 0;
194
+ let consecutiveSuccesses = 0;
195
+ let openedAt = 0;
196
+ let totalRequests = 0;
197
+ let totalFailures = 0;
198
+ let totalSuccesses = 0;
199
+ let totalRejected = 0;
200
+ let lastFailureTime = null;
201
+ let lastSuccessTime = null;
202
+ const transition = (to) => {
203
+ if (currentState === to) return;
204
+ const from = currentState;
205
+ currentState = to;
206
+ onStateChange?.(from, to);
207
+ };
208
+ const onSuccess = () => {
209
+ totalSuccesses++;
210
+ lastSuccessTime = Date.now();
211
+ consecutiveFailures = 0;
212
+ if (currentState === "half-open") {
213
+ consecutiveSuccesses++;
214
+ if (consecutiveSuccesses >= successThreshold) {
215
+ consecutiveSuccesses = 0;
216
+ transition("closed");
217
+ }
218
+ }
219
+ };
220
+ const onFailure = (error) => {
221
+ if (!isFailure(error)) {
222
+ onSuccess();
223
+ return;
224
+ }
225
+ totalFailures++;
226
+ lastFailureTime = Date.now();
227
+ consecutiveSuccesses = 0;
228
+ consecutiveFailures++;
229
+ if (currentState === "half-open") {
230
+ openedAt = Date.now();
231
+ transition("open");
232
+ } else if (currentState === "closed" && consecutiveFailures >= failureThreshold) {
233
+ openedAt = Date.now();
234
+ transition("open");
235
+ }
236
+ };
237
+ const shouldAllow = () => {
238
+ switch (currentState) {
239
+ case "closed":
240
+ return true;
241
+ case "open": {
242
+ const elapsed = Date.now() - openedAt;
243
+ if (elapsed >= resetTimeoutMs) {
244
+ transition("half-open");
245
+ return true;
246
+ }
247
+ return false;
248
+ }
249
+ case "half-open":
250
+ return true;
251
+ }
252
+ };
253
+ const protect = (effect) => {
254
+ totalRequests++;
255
+ if (!shouldAllow()) {
256
+ totalRejected++;
257
+ return asyncFail({
258
+ _tag: "CircuitBreakerOpen",
259
+ openSince: openedAt,
260
+ failures: consecutiveFailures
261
+ });
262
+ }
263
+ return asyncFold(
264
+ effect,
265
+ (error) => {
266
+ onFailure(error);
267
+ return asyncFail(error);
268
+ },
269
+ (value) => {
270
+ onSuccess();
271
+ return asyncSucceed(value);
272
+ }
273
+ );
274
+ };
275
+ const stats = () => ({
276
+ state: currentState,
277
+ failures: consecutiveFailures,
278
+ successes: consecutiveSuccesses,
279
+ totalRequests,
280
+ totalFailures,
281
+ totalSuccesses,
282
+ totalRejected,
283
+ lastFailureTime,
284
+ lastSuccessTime
285
+ });
286
+ const reset = () => {
287
+ consecutiveFailures = 0;
288
+ consecutiveSuccesses = 0;
289
+ transition("closed");
290
+ };
291
+ return {
292
+ state: () => currentState,
293
+ protect,
294
+ stats,
295
+ reset
296
+ };
297
+ }
298
+
299
+ export {
300
+ bracket,
301
+ ensuring,
302
+ resource,
303
+ makeResource,
304
+ resourceSucceed,
305
+ resourceFromManaged,
306
+ useResource,
307
+ resourceAll,
308
+ Resource,
309
+ managed,
310
+ useManaged,
311
+ managedAll,
312
+ makeCircuitBreaker
313
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  asyncEffect
3
- } from "./chunk-NOYZIMUJ.mjs";
3
+ } from "./chunk-36I3M4UC.mjs";
4
4
 
5
5
  // src/core/stream/structuredConcurrency.ts
6
6
  function race(left, right, parentScope) {
@@ -2,25 +2,25 @@ import {
2
2
  EventBus,
3
3
  InMemoryTracer,
4
4
  makeMetrics
5
- } from "./chunk-VFIUZG7J.mjs";
5
+ } from "./chunk-RKGKFN2A.js";
6
6
  import {
7
7
  Runtime,
8
8
  ctxExtend,
9
9
  ctxToObject,
10
10
  emptyContext,
11
11
  getCurrentFiber
12
- } from "./chunk-G6IQOE4P.mjs";
12
+ } from "./chunk-FH2X7BVP.js";
13
13
  import {
14
14
  asyncFail,
15
15
  asyncFlatMap,
16
16
  asyncFold,
17
17
  asyncSucceed,
18
18
  asyncSync
19
- } from "./chunk-NOYZIMUJ.mjs";
19
+ } from "./chunk-UB4B6OFY.js";
20
20
  import {
21
21
  Schema,
22
22
  parseConfig
23
- } from "./chunk-U5KWK3PX.mjs";
23
+ } from "./chunk-C3MDXTRZ.js";
24
24
 
25
25
  // src/observability/health.ts
26
26
  function snapshotRuntimeHealth(options = {}) {
@@ -1462,6 +1462,7 @@ var object = Schema.custom(
1462
1462
  );
1463
1463
  var falseOrObject = Schema.union([Schema.literal(false), object]);
1464
1464
  var ratio = Schema.number({ min: 0, max: 1 });
1465
+ var logLevel = Schema.enum(["debug", "info", "warn", "error"]);
1465
1466
  var retryOptions = Schema.object({
1466
1467
  attempts: Schema.number({ min: 0, int: true }).optional(),
1467
1468
  initialDelayMs: Schema.number({ min: 0, int: true }).optional(),
@@ -1523,11 +1524,78 @@ var observabilityOptions = Schema.object({
1523
1524
  childName: fn.optional(),
1524
1525
  onFlushError: fn.optional()
1525
1526
  }, { unknownKeys: "passthrough" });
1527
+ var httpObservabilityOptions = Schema.object({
1528
+ metrics: falseOrObject.optional(),
1529
+ logs: Schema.union([
1530
+ Schema.literal(false),
1531
+ Schema.object({
1532
+ requestLevel: Schema.union([logLevel, Schema.literal(false)]).optional(),
1533
+ responseLevel: Schema.union([logLevel, Schema.literal(false)]).optional(),
1534
+ errorLevel: Schema.union([logLevel, Schema.literal(false)]).optional()
1535
+ }, { unknownKeys: "passthrough" })
1536
+ ]).optional(),
1537
+ spans: Schema.union([
1538
+ Schema.literal(false),
1539
+ Schema.object({
1540
+ name: Schema.union([Schema.string({ minLength: 1 }), fn]).optional(),
1541
+ attributes: Schema.union([object, fn]).optional()
1542
+ }, { unknownKeys: "passthrough" })
1543
+ ]).optional(),
1544
+ adaptiveLimiter: Schema.union([
1545
+ Schema.boolean(),
1546
+ Schema.object({
1547
+ enabled: Schema.boolean().optional(),
1548
+ includeKeyLabel: Schema.boolean().optional()
1549
+ }, { unknownKeys: "passthrough" })
1550
+ ]).optional(),
1551
+ policy: Schema.union([
1552
+ Schema.boolean(),
1553
+ Schema.object({
1554
+ enabled: Schema.boolean().optional(),
1555
+ labelKeys: Schema.array(Schema.enum(["preset", "lane", "poolKey", "dedupKey", "priority", "retry"])).optional()
1556
+ }, { unknownKeys: "passthrough" })
1557
+ ]).optional(),
1558
+ injectTraceHeaders: Schema.boolean().optional(),
1559
+ includeHostLabel: Schema.boolean().optional(),
1560
+ route: Schema.union([Schema.string({ minLength: 1 }), fn]).optional(),
1561
+ clock: fn.optional(),
1562
+ durationBuckets: Schema.array(Schema.number({ min: 0 }).refine((n) => n > 0, "duration bucket must be > 0")).optional()
1563
+ }, { unknownKeys: "passthrough" });
1526
1564
  function validateObservabilityOptions(options) {
1527
1565
  parseConfig("ObservabilityOptions", observabilityOptions, options);
1528
1566
  }
1567
+ function validateHttpObservabilityOptions(options) {
1568
+ parseConfig("HttpObservabilityOptions", httpObservabilityOptions, options);
1569
+ }
1529
1570
 
1530
1571
  // src/observability/setup.ts
1572
+ var DEFAULT_OTLP_SIGNALS = ["metrics", "traces", "logs"];
1573
+ function makeOtlpOptions(input) {
1574
+ const endpoint = normalizeOtlpEndpoint(input.endpoint);
1575
+ const signals = input.signals ?? DEFAULT_OTLP_SIGNALS;
1576
+ return {
1577
+ ...signals.includes("metrics") ? { metricsUrl: `${endpoint}/v1/metrics` } : {},
1578
+ ...signals.includes("traces") ? { tracesUrl: `${endpoint}/v1/traces` } : {},
1579
+ ...signals.includes("logs") ? { logsUrl: `${endpoint}/v1/logs` } : {},
1580
+ ...input.headers ? { headers: input.headers } : {},
1581
+ ...input.fetch ? { fetch: input.fetch } : {},
1582
+ ...input.timeoutMs !== void 0 ? { timeoutMs: input.timeoutMs } : {},
1583
+ ...input.retry ? { retry: input.retry } : {},
1584
+ ...input.pipeline ? { pipeline: input.pipeline } : {}
1585
+ };
1586
+ }
1587
+ function normalizeOtlpEndpoint(endpoint) {
1588
+ const trimmed = endpoint.trim();
1589
+ let end = trimmed.length;
1590
+ while (end > 0 && trimmed.charCodeAt(end - 1) === 47) {
1591
+ end -= 1;
1592
+ }
1593
+ const normalized = trimmed.slice(0, end);
1594
+ if (!normalized) {
1595
+ throw new Error("makeOtlpOptions endpoint must not be empty");
1596
+ }
1597
+ return normalized;
1598
+ }
1531
1599
  function makeObservability(options = {}) {
1532
1600
  validateObservabilityOptions(options);
1533
1601
  const serviceName = options.serviceName ?? "brass-runtime";
@@ -1861,12 +1929,13 @@ function makeRuntimeTraceIdGenerator() {
1861
1929
  newSpanId: () => randomHexId(16)
1862
1930
  };
1863
1931
  }
1932
+ var HEX_BYTE = Array.from({ length: 256 }, (_, byte) => byte.toString(16).padStart(2, "0"));
1864
1933
  function randomHexId(length) {
1865
1934
  const cryptoLike = globalThis.crypto;
1866
1935
  if (typeof cryptoLike?.getRandomValues === "function") {
1867
1936
  const bytes = new Uint8Array(Math.ceil(length / 2));
1868
1937
  cryptoLike.getRandomValues(bytes);
1869
- return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, length);
1938
+ return bytesToHex(bytes, length);
1870
1939
  }
1871
1940
  if (typeof cryptoLike?.randomUUID === "function") {
1872
1941
  const hex = cryptoLike.randomUUID().replace(/-/g, "");
@@ -1878,6 +1947,13 @@ function randomHexId(length) {
1878
1947
  }
1879
1948
  return out.slice(0, length);
1880
1949
  }
1950
+ function bytesToHex(bytes, length) {
1951
+ let out = "";
1952
+ for (let i = 0; i < bytes.length; i++) {
1953
+ out += HEX_BYTE[bytes[i]];
1954
+ }
1955
+ return out.length === length ? out : out.slice(0, length);
1956
+ }
1881
1957
 
1882
1958
  // src/observability/request.ts
1883
1959
  function makeRequestObservabilityContext(observability, input = {}) {
@@ -2134,6 +2210,8 @@ export {
2134
2210
  makeCardinalityLimitedMetrics,
2135
2211
  normalizeHttpRoute,
2136
2212
  sanitizeHttpTarget,
2213
+ validateHttpObservabilityOptions,
2214
+ makeOtlpOptions,
2137
2215
  makeObservability,
2138
2216
  resolveRequestTraceSeed,
2139
2217
  resolveRequestBaggage,
@@ -18,6 +18,15 @@ var ConfigValidationError = class extends Error {
18
18
  this.issues = issues;
19
19
  }
20
20
  };
21
+ function isConfigValidationError(error) {
22
+ return error instanceof ConfigValidationError || typeof error === "object" && error !== null && error._tag === "ConfigValidationError" && typeof error.configName === "string" && Array.isArray(error.issues);
23
+ }
24
+ function formatConfigError(error) {
25
+ if (!isConfigValidationError(error)) {
26
+ return error instanceof Error ? error.message : String(error);
27
+ }
28
+ return `${error.configName} failed validation: ${formatIssues(error.issues)}`;
29
+ }
21
30
  var ok = (data) => ({ success: true, data });
22
31
  var fail = (issues) => ({ success: false, issues });
23
32
  var receivedKind = (value) => {
@@ -332,6 +341,8 @@ function parseConfig(configName, validator, value) {
332
341
  export {
333
342
  SchemaValidationException,
334
343
  ConfigValidationError,
344
+ isConfigValidationError,
345
+ formatConfigError,
335
346
  makeSchemaIssue,
336
347
  formatIssues,
337
348
  schema,
@@ -18,6 +18,15 @@ var ConfigValidationError = (_class = class extends Error {
18
18
  this.issues = issues;
19
19
  }
20
20
  }, _class);
21
+ function isConfigValidationError(error) {
22
+ return error instanceof ConfigValidationError || typeof error === "object" && error !== null && error._tag === "ConfigValidationError" && typeof error.configName === "string" && Array.isArray(error.issues);
23
+ }
24
+ function formatConfigError(error) {
25
+ if (!isConfigValidationError(error)) {
26
+ return error instanceof Error ? error.message : String(error);
27
+ }
28
+ return `${error.configName} failed validation: ${formatIssues(error.issues)}`;
29
+ }
21
30
  var ok = (data) => ({ success: true, data });
22
31
  var fail = (issues) => ({ success: false, issues });
23
32
  var receivedKind = (value) => {
@@ -340,4 +349,6 @@ function parseConfig(configName, validator, value) {
340
349
 
341
350
 
342
351
 
343
- exports.SchemaValidationException = SchemaValidationException; exports.ConfigValidationError = ConfigValidationError; exports.makeSchemaIssue = makeSchemaIssue; exports.formatIssues = formatIssues; exports.schema = schema; exports.s = s; exports.Schema = Schema; exports.isSchema = isSchema; exports.validateValue = validateValue; exports.parseConfig = parseConfig;
352
+
353
+
354
+ exports.SchemaValidationException = SchemaValidationException; exports.ConfigValidationError = ConfigValidationError; exports.isConfigValidationError = isConfigValidationError; exports.formatConfigError = formatConfigError; exports.makeSchemaIssue = makeSchemaIssue; exports.formatIssues = formatIssues; exports.schema = schema; exports.s = s; exports.Schema = Schema; exports.isSchema = isSchema; exports.validateValue = validateValue; exports.parseConfig = parseConfig;
@@ -18,6 +18,15 @@ var ConfigValidationError = class extends Error {
18
18
  this.issues = issues;
19
19
  }
20
20
  };
21
+ function isConfigValidationError(error) {
22
+ return error instanceof ConfigValidationError || typeof error === "object" && error !== null && error._tag === "ConfigValidationError" && typeof error.configName === "string" && Array.isArray(error.issues);
23
+ }
24
+ function formatConfigError(error) {
25
+ if (!isConfigValidationError(error)) {
26
+ return error instanceof Error ? error.message : String(error);
27
+ }
28
+ return `${error.configName} failed validation: ${formatIssues(error.issues)}`;
29
+ }
21
30
  var ok = (data) => ({ success: true, data });
22
31
  var fail = (issues) => ({ success: false, issues });
23
32
  var receivedKind = (value) => {
@@ -332,6 +341,8 @@ function parseConfig(configName, validator, value) {
332
341
  export {
333
342
  SchemaValidationException,
334
343
  ConfigValidationError,
344
+ isConfigValidationError,
345
+ formatConfigError,
335
346
  makeSchemaIssue,
336
347
  formatIssues,
337
348
  schema,