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,189 @@
1
+ import { R as RuntimeHooks, b as RingBufferOptions, c as RuntimeEvent, a as RuntimeEmitContext, d as RuntimeEventRecord, e as RuntimeSpanLink, T as TraceContext, B as Baggage } from './effect-DIUHZ9IN.js';
2
+ import { R as RuntimeClock } from './schedule-CK3Ml_7p.js';
3
+
4
+ type MetricType = "counter" | "gauge" | "histogram";
5
+ type MetricValue = {
6
+ readonly name: string;
7
+ readonly type: MetricType;
8
+ readonly value: number;
9
+ readonly labels: Record<string, string>;
10
+ readonly timestamp: number;
11
+ };
12
+ type HistogramBuckets = {
13
+ readonly boundaries: readonly number[];
14
+ counts: number[];
15
+ sum: number;
16
+ count: number;
17
+ min: number;
18
+ max: number;
19
+ exemplars?: Array<MetricExemplar | undefined>;
20
+ };
21
+ type MetricExemplar = {
22
+ readonly value: number;
23
+ readonly timestamp: number;
24
+ readonly traceId?: string;
25
+ readonly spanId?: string;
26
+ readonly labels?: Record<string, string>;
27
+ };
28
+ type MetricsRegistry = {
29
+ /** Create or get a counter. */
30
+ readonly counter: (name: string, labels?: Record<string, string>) => Counter;
31
+ /** Create or get a gauge. */
32
+ readonly gauge: (name: string, labels?: Record<string, string>) => Gauge;
33
+ /** Create or get a histogram. */
34
+ readonly histogram: (name: string, boundaries?: number[], labels?: Record<string, string>) => Histogram;
35
+ /** Get all current metric values. */
36
+ readonly snapshot: () => MetricSnapshot;
37
+ /** Reset all metrics. */
38
+ readonly reset: () => void;
39
+ };
40
+ type Counter = {
41
+ readonly increment: (n?: number) => void;
42
+ readonly value: () => number;
43
+ };
44
+ type Gauge = {
45
+ readonly set: (value: number) => void;
46
+ readonly increment: (n?: number) => void;
47
+ readonly decrement: (n?: number) => void;
48
+ readonly value: () => number;
49
+ };
50
+ type Histogram = {
51
+ readonly observe: (value: number, exemplar?: Omit<MetricExemplar, "value"> | MetricExemplar) => void;
52
+ readonly buckets: () => HistogramBuckets;
53
+ readonly percentile: (p: number) => number;
54
+ };
55
+ type MetricSnapshot = {
56
+ readonly counters: Array<{
57
+ name: string;
58
+ labels: Record<string, string>;
59
+ value: number;
60
+ }>;
61
+ readonly gauges: Array<{
62
+ name: string;
63
+ labels: Record<string, string>;
64
+ value: number;
65
+ }>;
66
+ readonly histograms: Array<{
67
+ name: string;
68
+ labels: Record<string, string>;
69
+ buckets: HistogramBuckets;
70
+ }>;
71
+ };
72
+ /**
73
+ * Creates a metrics registry.
74
+ *
75
+ * ```ts
76
+ * const metrics = makeMetrics();
77
+ *
78
+ * const requestCount = metrics.counter("http_requests_total", { method: "GET" });
79
+ * requestCount.increment();
80
+ *
81
+ * const latency = metrics.histogram("http_request_duration_ms");
82
+ * latency.observe(42.5);
83
+ *
84
+ * const activeConns = metrics.gauge("active_connections");
85
+ * activeConns.set(10);
86
+ *
87
+ * console.log(metrics.snapshot());
88
+ * ```
89
+ */
90
+ declare function makeMetrics(): MetricsRegistry;
91
+
92
+ type EventHandler = (ev: RuntimeEventRecord) => void;
93
+ declare function runtimeHooksToEventHandler(hooks: RuntimeHooks): EventHandler;
94
+ type EventBusOptions = RingBufferOptions;
95
+ declare class EventBus implements RuntimeHooks {
96
+ private readonly options;
97
+ private seq;
98
+ private subs;
99
+ private flushScheduled;
100
+ private readonly boundFlush;
101
+ constructor(options?: EventBusOptions);
102
+ emit(ev: RuntimeEvent, ctx: RuntimeEmitContext): void;
103
+ subscribe(handler: EventHandler, perSubscriberCapacity?: number): () => void;
104
+ subscribeHooks(hooks: RuntimeHooks, perSubscriberCapacity?: number): () => void;
105
+ flush(budget?: number): void;
106
+ }
107
+
108
+ type RuntimeSpanEvent = {
109
+ wallTs: number;
110
+ name: string;
111
+ attrs?: unknown;
112
+ };
113
+ type RuntimeSpan = {
114
+ traceId: string;
115
+ spanId: string;
116
+ parentSpanId?: string;
117
+ traceState?: string;
118
+ name: string;
119
+ startWallTs: number;
120
+ endWallTs?: number;
121
+ attrs: Record<string, unknown>;
122
+ links: RuntimeSpanLink[];
123
+ events: RuntimeSpanEvent[];
124
+ };
125
+ type InMemoryTracerOptions = {
126
+ readonly sanitizeAttributes?: (attrs: Record<string, unknown>) => Record<string, unknown>;
127
+ readonly sanitizeError?: (error: unknown) => unknown;
128
+ readonly maxFinishedSpans?: number;
129
+ readonly maxSpanAgeMs?: number;
130
+ readonly clock?: () => number;
131
+ };
132
+ type InMemoryTracerStats = {
133
+ readonly storedSpans: number;
134
+ readonly finishedSpans: number;
135
+ readonly prunedFinishedSpans: number;
136
+ };
137
+ declare class InMemoryTracer implements RuntimeHooks {
138
+ private readonly options;
139
+ spans: Map<string, RuntimeSpan>;
140
+ private readonly finishedSpanIds;
141
+ private readonly finishedSpanSet;
142
+ private finishedSpanOffset;
143
+ private finishedSpanCount;
144
+ private prunedFinishedSpans;
145
+ constructor(options?: InMemoryTracerOptions);
146
+ emit(ev: RuntimeEvent, ctx: RuntimeEmitContext): void;
147
+ exportFinished(): RuntimeSpan[];
148
+ pruneFinished(spanIds?: Iterable<string>): number;
149
+ stats(): InMemoryTracerStats;
150
+ private attrs;
151
+ private error;
152
+ private now;
153
+ private pruneExpiredFinished;
154
+ private pruneFinishedOverLimit;
155
+ private markFinished;
156
+ private deleteFinished;
157
+ private peekOldestFinished;
158
+ private deleteOldestFinished;
159
+ private compactFinishedIds;
160
+ }
161
+
162
+ type TraceSamplingInput = {
163
+ readonly traceId: string;
164
+ readonly spanName?: string;
165
+ readonly parentSampled?: boolean;
166
+ readonly attributes?: Record<string, unknown>;
167
+ };
168
+ type TraceSampler = ((input: TraceSamplingInput) => boolean) | {
169
+ shouldSample(input: TraceSamplingInput): boolean;
170
+ };
171
+ interface Tracer {
172
+ newTraceId(): string;
173
+ newSpanId(): string;
174
+ }
175
+ declare const defaultTracer: Tracer;
176
+ type BrassEnv = {
177
+ brass?: {
178
+ tracer?: Tracer;
179
+ traceSeed?: TraceContext;
180
+ baggage?: Baggage;
181
+ sampler?: TraceSampler;
182
+ respectRemoteSampled?: boolean;
183
+ forceSampleOnError?: boolean;
184
+ childName?: (parentName?: string) => string | undefined;
185
+ clock?: RuntimeClock;
186
+ };
187
+ };
188
+
189
+ export { type BrassEnv as B, type Counter as C, EventBus as E, type Gauge as G, type Histogram as H, InMemoryTracer as I, type MetricsRegistry as M, type RuntimeSpan as R, type TraceSampler as T, type MetricExemplar as a, type MetricSnapshot as b, type TraceSamplingInput as c, type Tracer as d, type InMemoryTracerOptions as e, type EventBusOptions as f, type EventHandler as g, type HistogramBuckets as h, type InMemoryTracerStats as i, type MetricType as j, type MetricValue as k, type RuntimeSpanEvent as l, defaultTracer as m, makeMetrics as n, runtimeHooksToEventHandler as r };
@@ -0,0 +1,148 @@
1
+ import { A as Async, E as Exit } from './effect-DIUHZ9IN.js';
2
+
3
+ /**
4
+ * Acquires a resource, uses it, and guarantees release regardless of outcome.
5
+ *
6
+ * - `acquire` runs uninterruptibly (once started, it completes)
7
+ * - `use` runs with the acquired resource
8
+ * - `release` runs after `use` completes (success, failure, or interruption)
9
+ *
10
+ * ```ts
11
+ * const result = bracket(
12
+ * openConnection(), // acquire
13
+ * (conn) => queryDatabase(conn), // use
14
+ * (conn, exit) => conn.close() // release (always runs)
15
+ * );
16
+ * ```
17
+ */
18
+ declare function bracket<R, E, A, B>(acquire: Async<R, E, A>, use: (resource: A) => Async<R, E, B>, release: (resource: A, exit: Exit<E, B>) => Async<R, any, void>): Async<R, E, B>;
19
+ /**
20
+ * Runs `effect` and then runs `finalizer` regardless of the outcome.
21
+ * The finalizer receives the exit value for inspection.
22
+ *
23
+ * ```ts
24
+ * const result = ensuring(
25
+ * doWork(),
26
+ * (exit) => logCompletion(exit)
27
+ * );
28
+ * ```
29
+ */
30
+ declare function ensuring<R, E, A>(effect: Async<R, E, A>, finalizer: (exit: Exit<E, A>) => Async<R, any, void>): Async<R, E, A>;
31
+ declare function resource<R, E, A>(acquire: Async<R, E, A>, release: (resource: A, exit: Exit<any, any>) => Async<R, any, void>): Resource<R, E, A>;
32
+ declare const makeResource: typeof resource;
33
+ declare function resourceSucceed<A>(value: A): Resource<unknown, never, A>;
34
+ declare function resourceFromManaged<R, E, A>(m: Managed<R, E, A>): Resource<R, E, A>;
35
+ declare function useResource<R, E, A, R2, E2, B>(res: Resource<R, E, A>, body: (resource: A) => Async<R2, E2, B>): Async<R & R2, E | E2, B>;
36
+ declare function resourceAll<R, E, Resources extends readonly any[]>(resources: {
37
+ [K in keyof Resources]: Resource<R, E, Resources[K]>;
38
+ }): Resource<R, E, Resources>;
39
+ /**
40
+ * A Resource describes a scoped value. It is acquired for each `use`, released
41
+ * in LIFO order, and can be composed with `map`, `flatMap`, and `zip`.
42
+ */
43
+ type Resource<R, E, A> = {
44
+ readonly _tag: "Resource";
45
+ readonly use: <R2, E2, B>(body: (resource: A) => Async<R2, E2, B>) => Async<R & R2, E | E2, B>;
46
+ readonly map: <B>(f: (resource: A) => B) => Resource<R, E, B>;
47
+ readonly flatMap: <R2, E2, B>(f: (resource: A) => Resource<R2, E2, B>) => Resource<R & R2, E | E2, B>;
48
+ readonly zip: <R2, E2, B>(that: Resource<R2, E2, B>) => Resource<R & R2, E | E2, [A, B]>;
49
+ };
50
+ declare const Resource: Readonly<{
51
+ make: typeof resource;
52
+ succeed: typeof resourceSucceed;
53
+ fromManaged: typeof resourceFromManaged;
54
+ all: typeof resourceAll;
55
+ use: typeof useResource;
56
+ }>;
57
+ /**
58
+ * A Managed resource describes how to acquire and release a resource.
59
+ * It can be used multiple times — each `use` call acquires a fresh instance.
60
+ *
61
+ * ```ts
62
+ * const dbPool = managed(
63
+ * createPool({ max: 10 }),
64
+ * (pool) => pool.close()
65
+ * );
66
+ *
67
+ * // Use it:
68
+ * const result = useManaged(dbPool, (pool) => pool.query("SELECT 1"));
69
+ * ```
70
+ */
71
+ type Managed<R, E, A> = {
72
+ readonly _tag: "Managed";
73
+ readonly acquire: Async<R, E, A>;
74
+ readonly release: (resource: A, exit: Exit<any, any>) => Async<R, any, void>;
75
+ };
76
+ /**
77
+ * Creates a Managed resource descriptor.
78
+ */
79
+ declare function managed<R, E, A>(acquire: Async<R, E, A>, release: (resource: A, exit?: Exit<any, any>) => Async<R, any, void>): Managed<R, E, A>;
80
+ /**
81
+ * Uses a Managed resource: acquires, runs the body, and releases.
82
+ */
83
+ declare function useManaged<R, E, A, B>(m: Managed<R, E, A>, body: (resource: A) => Async<R, E, B>): Async<R, E, B>;
84
+ /**
85
+ * Combines multiple Managed resources. All are acquired in order,
86
+ * and released in reverse order (LIFO).
87
+ *
88
+ * ```ts
89
+ * const resources = managedAll([dbPool, cacheConn, fileHandle]);
90
+ * const result = useManaged(resources, ([db, cache, file]) => ...);
91
+ * ```
92
+ */
93
+ declare function managedAll<R, E, Resources extends readonly any[]>(manageds: {
94
+ [K in keyof Resources]: Managed<R, E, Resources[K]>;
95
+ }): Managed<R, E, Resources>;
96
+
97
+ type SpanContext = {
98
+ readonly traceId: string;
99
+ readonly spanId: string;
100
+ readonly parentSpanId?: string;
101
+ };
102
+ type SpanStatus = "ok" | "error" | "unset";
103
+ type Span = {
104
+ readonly name: string;
105
+ readonly context: SpanContext;
106
+ readonly startTime: number;
107
+ endTime?: number;
108
+ status: SpanStatus;
109
+ readonly attributes: Record<string, string | number | boolean>;
110
+ readonly events: SpanEvent[];
111
+ };
112
+ type SpanEvent = {
113
+ readonly name: string;
114
+ readonly time: number;
115
+ readonly attributes?: Record<string, string | number | boolean>;
116
+ };
117
+ type TracerConfig = {
118
+ /** Service name for span metadata. */
119
+ readonly serviceName: string;
120
+ /** Called when a span ends (for export). */
121
+ readonly onSpanEnd?: (span: Span) => void;
122
+ /** Sampling rate (0.0 to 1.0). Default: 1.0 (sample everything). */
123
+ readonly sampleRate?: number;
124
+ };
125
+ type Tracer = {
126
+ /** Wrap an effect in a span. */
127
+ readonly span: <R, E, A>(name: string, effect: Async<R, E, A>, attributes?: Record<string, string | number | boolean>) => Async<R, E, A>;
128
+ /** Get all completed spans (for testing). */
129
+ readonly spans: () => readonly Span[];
130
+ /** Clear collected spans. */
131
+ readonly clear: () => void;
132
+ };
133
+ /**
134
+ * Creates a tracer that wraps effects in spans.
135
+ *
136
+ * ```ts
137
+ * const tracer = makeTracer({ serviceName: "my-app" });
138
+ *
139
+ * const result = await run(
140
+ * tracer.span("fetchUser", fetchUser(id), { userId: id })
141
+ * );
142
+ *
143
+ * console.log(tracer.spans()); // all completed spans
144
+ * ```
145
+ */
146
+ declare function makeTracer(config: TracerConfig): Tracer;
147
+
148
+ export { type Managed as M, Resource as R, type Span as S, type Tracer as T, type SpanContext as a, type SpanEvent as b, type SpanStatus as c, type TracerConfig as d, bracket as e, ensuring as f, makeTracer as g, managed as h, managedAll as i, resourceAll as j, resourceFromManaged as k, resourceSucceed as l, makeResource as m, useResource as n, resource as r, useManaged as u };
@@ -0,0 +1,292 @@
1
+ # 🧱 ARCHITECTURE — brass-runtime
2
+
3
+ This document explains the **architectural structure** of `brass-runtime`, how the layers relate to each other, and the design principles behind them.
4
+
5
+ The architecture is intentionally inspired by **ZIO 2**, but implemented from scratch in **TypeScript**, without relying on `Promise` as the semantic runtime primitive.
6
+
7
+ ---
8
+
9
+ ## High-level overview
10
+
11
+ ```
12
+ ┌────────────────────────────────────────────┐
13
+ │ User Programs │
14
+ │ (examples, apps, libraries, tests) │
15
+ └────────────────────────────────────────────┘
16
+
17
+
18
+ ┌────────────────────────────────────────────┐
19
+ │ High-level Modules │
20
+ │ (HTTP, Streams, Resources, etc.) │
21
+ └────────────────────────────────────────────┘
22
+
23
+
24
+ ┌────────────────────────────────────────────┐
25
+ │ Core Effect Runtime │
26
+ │ Async / Effect / Fiber / Scope / Scheduler │
27
+ └────────────────────────────────────────────┘
28
+
29
+
30
+ ┌────────────────────────────────────────────┐
31
+ │ JavaScript Host Environment │
32
+ │ (event loop, timers, fetch, callbacks) │
33
+ └────────────────────────────────────────────┘
34
+ ```
35
+
36
+ Key idea:
37
+ > **Only the core runtime knows about execution.**
38
+ > Everything else is *pure descriptions* interpreted by the runtime.
39
+
40
+ ---
41
+
42
+ ## Core principles
43
+
44
+ ### 1. No Promise-based semantics
45
+ - `Promise` is never the semantic primitive.
46
+ - Async work is represented explicitly as data (`Async`).
47
+ - The runtime *interprets* async effects using callbacks and schedulers.
48
+
49
+ This ensures:
50
+ - Deterministic scheduling
51
+ - Cooperative cancellation
52
+ - Structured concurrency
53
+ - Testability
54
+
55
+ ---
56
+
57
+ ### 2. Lazy by default
58
+ All effects are **lazy**:
59
+ - Nothing runs until interpreted by a `Fiber`
60
+ - Creating an effect is pure and side-effect free
61
+
62
+ ```ts
63
+ const eff = http.getJson<Post>("/posts/1")
64
+ // nothing has happened yet
65
+ ```
66
+
67
+ Execution only begins when:
68
+ - Forked into a fiber
69
+ - Or awaited via `toPromise` (interop helper)
70
+
71
+ ---
72
+
73
+ ### 3. Structured concurrency
74
+ Fibers always belong to a **Scope**.
75
+
76
+ Rules:
77
+ - Child fibers cannot outlive their parent scope
78
+ - Closing a scope interrupts all children
79
+ - Finalizers run in LIFO order
80
+
81
+ This prevents:
82
+ - Leaked async tasks
83
+ - Forgotten cleanups
84
+ - Detached background work
85
+
86
+ ---
87
+
88
+ ## Core Runtime Layer
89
+
90
+ ### Main components
91
+
92
+ ```
93
+ Async
94
+
95
+
96
+ Fiber ── Scheduler
97
+
98
+
99
+ Scope ── Finalizers
100
+ ```
101
+
102
+ #### `Async<R, E, A>`
103
+ - Algebraic data type representing effectful computation
104
+ - Variants: `Succeed | Fail | Sync | Async | FlatMap`
105
+ - Pure data, no execution
106
+
107
+ #### `Fiber<E, A>`
108
+ - Interpreter of `Async`
109
+ - Owns:
110
+ - Stack
111
+ - RunState
112
+ - Interrupt status
113
+ - Finalizers
114
+ - Can be:
115
+ - Joined
116
+ - Interrupted
117
+ - Forked
118
+
119
+ #### `Scheduler`
120
+ - Cooperative task queue
121
+ - Ensures fairness
122
+ - No preemption
123
+ - Explicit scheduling boundaries
124
+
125
+ #### `Scope`
126
+ - Lifetime manager
127
+ - Owns:
128
+ - Child fibers
129
+ - Sub-scopes
130
+ - Finalizers
131
+ - Deterministic cleanup
132
+
133
+ ---
134
+
135
+ ## Streams Architecture
136
+
137
+ Streams are **pull-based**, inspired by ZIO Streams.
138
+
139
+ ```
140
+ ZStream
141
+
142
+
143
+ Pull<R, Option<E>, A>
144
+ ```
145
+
146
+ ### Characteristics
147
+ - Backpressure-aware
148
+ - Resource-safe
149
+ - Scope-bound
150
+ - Deterministic cleanup
151
+
152
+ ### Why pull-based?
153
+ - Simpler cancellation semantics
154
+ - Natural backpressure
155
+ - Easier reasoning about lifetimes
156
+
157
+ ---
158
+
159
+ ## HTTP Module Architecture (brass-http)
160
+
161
+ HTTP is **not part of the core runtime**.
162
+
163
+ It is implemented as a **high-level module** built entirely on `Async`.
164
+
165
+ ```
166
+ HttpRequest
167
+
168
+
169
+ HttpClient (Request => Async)
170
+
171
+
172
+ Middlewares
173
+ (withMeta, logging, retries)
174
+
175
+
176
+ Content helpers
177
+ (getJson, getText)
178
+ ```
179
+
180
+ ### Important properties
181
+ - Fully lazy
182
+ - Cancelable via fiber interruption
183
+ - Composable via middleware functions
184
+ - Environment-aware (baseUrl, headers, auth)
185
+
186
+ HTTP execution only happens when:
187
+ - The returned `Async` is run by a fiber
188
+
189
+ ---
190
+
191
+ ## Middleware model
192
+
193
+ Middlewares are pure functions:
194
+
195
+ ```ts
196
+ type Middleware = (client: HttpClient) => HttpClient
197
+ ```
198
+
199
+ They:
200
+ - Do not execute effects
201
+ - Only transform descriptions
202
+ - Compose left-to-right
203
+
204
+ Examples:
205
+ - `withMeta`
206
+ - logging
207
+ - retries
208
+ - tracing
209
+ - auth injection
210
+
211
+ ---
212
+
213
+ ## Interop Layer
214
+
215
+ ### `toPromise`
216
+ - Thin boundary for examples and DX
217
+ - Not part of core semantics
218
+ - Converts fiber execution into a `Promise`
219
+
220
+ ### `fromPromiseAbortable`
221
+ - Adapts Promise APIs that support `AbortSignal`
222
+ - Preserves cooperative cancellation
223
+ - Integrates cleanly with fibers
224
+
225
+ Interop is **explicit and contained**.
226
+
227
+ ---
228
+
229
+ ## What is NOT allowed
230
+
231
+ By design:
232
+ - ❌ Hidden Promises inside effects
233
+ - ❌ Detached async work
234
+ - ❌ Implicit background execution
235
+ - ❌ Fire-and-forget APIs
236
+
237
+ If something runs:
238
+ > It must be owned by a fiber and a scope.
239
+
240
+ ---
241
+
242
+ ## Extension points
243
+
244
+ Designed to grow horizontally:
245
+
246
+ - New modules (HTTP, FS, DB, etc.)
247
+ - New stream combinators
248
+ - New schedulers (priority, test)
249
+ - New runtimes (browser, workers)
250
+
251
+ Without changing the core semantics.
252
+
253
+ ---
254
+
255
+ ## Mental model (TL;DR)
256
+
257
+ - **Core** = execution + rules
258
+ - **Async** = description
259
+ - **Fiber** = interpreter
260
+ - **Scope** = lifetime
261
+ - **Modules** = pure libraries on top
262
+ - **Interop** = explicit escape hatch
263
+
264
+ If you understand this:
265
+ 👉 you understand the entire system.
266
+
267
+ ---
268
+
269
+ ## Status
270
+
271
+ This architecture is:
272
+ - Experimental
273
+ - Intentionally minimal
274
+ - Designed for learning, exploration, and correctness
275
+
276
+ But:
277
+ > It already enforces stronger guarantees than most Promise-based codebases.
278
+
279
+ ---
280
+
281
+ MIT License © 2025
282
+
283
+
284
+ ---
285
+
286
+ ## Further reading
287
+
288
+ - [Getting started](./getting-started.md)
289
+ - [Modules overview](./modules.md)
290
+ - [Cancellation & interruption](./cancellation.md)
291
+ - [Observability (hooks & events)](./observability.md)
292
+ - [HTTP client](./http.md)
package/docs/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # Documentation
2
+
3
+ Start here:
4
+
5
+ - **[Getting started](./getting-started.md)** — installation, first effects, and running examples
6
+ - **[Architecture](./ARCHITECTURE.md)** — how the runtime is structured
7
+ - **[Cancellation & interruption](./cancellation.md)** — interruption semantics, scopes, and cancellable `Async`
8
+ - **[Observability](./observability.md)** — hooks, events, sinks, tracing, and HTTP policy context
9
+ - **[HTTP client](./http.md)** — ZIO-style HTTP built on brass-runtime
10
+ - **[HTTP recipes](./http-recipes.md)** — typed clients, custom transports, production adoption, observability, and config validation
11
+ - **[Recipes](./recipes/README.md)** — copyable runtime, layer, HTTP server, testing, and performance paths
12
+ - **[API polish notes](./api-polish.md)** — first-release DX audit and compatibility posture
13
+ - **[First release checklist](./release.md)** — local release gate and perf evidence workflow
14
+ - **[Modules overview](./modules.md)** — map of core modules and where things live
15
+ - **[AI context pack](./ai/PROJECT_MAP.md)** — compact project map, invariants, validation matrix, and public API notes
16
+ - **[Agent module boundaries](./agent-boundaries.md)** — rules for keeping `brass-agent` isolated from the core runtime
17
+ - **[Brass Agent install and configure](./agent-install-and-configure.md)** — end-to-end local setup for CLI, config, providers, and VS Code
18
+
19
+ - [Agent LLM adapters](./agent-llm-adapters.md)
20
+ - [Agent env files](./agent-env-files.md)
21
+ - [Agent global usage and workspace discovery](./agent-global-usage.md)
22
+ - [Agent apply mode](./agent-apply-mode.md)
23
+ - [Brass Agent CLI](./agent-cli.md)
24
+ - [Agent init](./agent-init.md)
25
+ - [Agent observability](./agent-observability.md)
26
+ - [Agent approvals](./agent-approvals.md)
27
+ - [Agent config and policy files](./agent-config.md)
28
+ - [Agent project command discovery](./agent-project-commands.md)
29
+ - [Agent project intelligence](./agent-project-intelligence.md)
30
+ - [Declarative optimized planning roadmap](./agent-declarative-optimized-planning.md)
31
+ - [Agent context discovery](./agent-context-discovery.md)
32
+ - [Agent patch quality loop](./agent-patch-quality-loop.md)
33
+ - [Agent automatic rollback safety](./agent-rollback-safety.md)
34
+ - [Agent DX surfaces](./agent-dx.md)
35
+
36
+ - [VS Code patch preview](./agent-vscode-patch-preview.md)
37
+ - [VS Code enhanced diff preview](./agent-vscode-diff-preview.md)
38
+ - [VS Code run history](./agent-vscode-run-history.md)
39
+ - [VS Code batch runner](./agent-vscode-batch-runner.md)
40
+ - [VS Code UX](./agent-vscode-ux.md)
41
+ - [VS Code Project dashboard](./agent-vscode-project-dashboard.md)
42
+ - [VS Code Chat layout / focus mode](./agent-vscode-chat-layout.md)
43
+ - [Copilot-like VS Code DX](./agent-copilot-like-dx.md)
44
+ - [Chat sessions and slash commands](./agent-chat-sessions.md)
45
+ - [Agent follow-up context](./agent-follow-up-context.md)
46
+ - [VS Code code actions](./agent-vscode-code-actions.md)
47
+ - [VS Code problems-aware chat](./agent-vscode-problems.md)
48
+ - [VS Code inline assist](./agent-vscode-inline-assist.md)
49
+ - [Agent release readiness](./agent-release-readiness.md)
50
+ - [VS Code local install](./agent-vscode-install.md)
51
+ - [VS Code auto-discovery](./agent-vscode-auto-discovery.md)
52
+ - [VS Code model setup](./agent-vscode-model-setup.md)
53
+ - [Agent local install and doctor](./agent-local-install.md)
54
+ - [Agent local tests](./agent-local-tests.md)
55
+
56
+ - [Agent rollback patches](./agent-rollback.md)
57
+ - [Agent redaction](./agent-redaction.md)
58
+ - [Agent run artifacts](./agent-run-artifacts.md)
59
+ - [Agent CI mode](./agent-ci.md)
60
+ - [Agent presets](./agent-presets.md)
61
+ - [Agent batch runs](./agent-batch.md)
62
+ - [VS Code full clean and reinstall](./agent-vscode-clean-install.md)
63
+ - [Agent language and workspace setup UX](agent-language-workspace-ux.md)