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