brass-runtime 1.13.8 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +6 -3
  2. package/dist/agent/cli/main.cjs +44 -43
  3. package/dist/agent/cli/main.js +5 -4
  4. package/dist/agent/cli/main.mjs +5 -4
  5. package/dist/agent/index.cjs +4 -3
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +3 -2
  8. package/dist/agent/index.mjs +3 -2
  9. package/dist/{chunk-3R7ZYRK2.mjs → chunk-3QMOKAS5.js} +9 -7
  10. package/dist/{chunk-ATHSSDUF.js → chunk-4NHES7VK.mjs} +113 -31
  11. package/dist/chunk-AR22SXML.js +1043 -0
  12. package/dist/chunk-BDF4AMWX.mjs +3773 -0
  13. package/dist/chunk-BDYEENHT.js +224 -0
  14. package/dist/chunk-BMH5AV44.js +3773 -0
  15. package/dist/chunk-ELOOF35R.mjs +131 -0
  16. package/dist/chunk-JFPU5GQI.mjs +1043 -0
  17. package/dist/{chunk-INZBKOHY.js → chunk-K6M7MDZ4.mjs} +9 -7
  18. package/dist/chunk-MS34J5LY.cjs +224 -0
  19. package/dist/{chunk-XNOTJSMZ.mjs → chunk-PPUXIH5R.js} +113 -31
  20. package/dist/chunk-R3R2FVLG.cjs +131 -0
  21. package/dist/{chunk-ZTDK2DLG.cjs → chunk-STVLQ3XD.cjs} +169 -87
  22. package/dist/chunk-TGIFUAK4.cjs +3773 -0
  23. package/dist/chunk-TO7IKXYT.js +131 -0
  24. package/dist/chunk-UMAZLXAB.mjs +224 -0
  25. package/dist/{chunk-XDINDYNA.cjs → chunk-VEZNF5GZ.cjs} +136 -134
  26. package/dist/chunk-XPZNXSVN.cjs +1043 -0
  27. package/dist/core/index.cjs +216 -0
  28. package/dist/core/index.d.ts +673 -0
  29. package/dist/core/index.js +216 -0
  30. package/dist/core/index.mjs +216 -0
  31. package/dist/{effect-ISvXPLgc.d.ts → effect-CMOQKX8y.d.ts} +202 -31
  32. package/dist/http/index.cjs +3177 -187
  33. package/dist/http/index.d.ts +1692 -9
  34. package/dist/http/index.js +3164 -174
  35. package/dist/http/index.mjs +3164 -174
  36. package/dist/index.cjs +936 -219
  37. package/dist/index.d.ts +313 -36
  38. package/dist/index.js +830 -113
  39. package/dist/index.mjs +830 -113
  40. package/dist/{stream-BvukHxCv.d.ts → stream-FQm9h4Mg.d.ts} +12 -4
  41. package/dist/tracing-DNT9jEbr.d.ts +106 -0
  42. package/package.json +11 -3
  43. package/wasm/pkg/brass_runtime_wasm_engine.d.ts +95 -16
  44. package/wasm/pkg/brass_runtime_wasm_engine.js +715 -15
  45. package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm +0 -0
  46. package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm.d.ts +78 -7
  47. package/dist/chunk-2P4PD6D7.cjs +0 -2557
  48. package/dist/chunk-7F2R7A2V.mjs +0 -2557
  49. package/dist/chunk-L6KKKM66.js +0 -2557
@@ -1,4 +1,4 @@
1
- import { Z as ZIO, O as Option, E as Exit, A as Async } from './effect-ISvXPLgc.js';
1
+ import { Z as ZIO, O as Option, E as Exit, A as Async } from './effect-CMOQKX8y.js';
2
2
 
3
3
  type Empty<R, E, A> = {
4
4
  readonly _tag: "Empty";
@@ -38,7 +38,11 @@ type Managed<R, E, A> = {
38
38
  release: (exit: Exit<any, any>) => Async<R, any, void>;
39
39
  }>;
40
40
  };
41
- type ZStream<R, E, A> = Empty<R, E, A> | Emit<R, E, A> | Concat<R, E, A> | FromPull<R, E, A> | Flatten<R, E, A> | Merge<R, E, A> | Scoped<R, E, A> | Managed<R, E, A>;
41
+ type FromArray<R, E, A> = {
42
+ readonly _tag: "FromArray";
43
+ readonly values: readonly A[];
44
+ };
45
+ type ZStream<R, E, A> = Empty<R, E, A> | Emit<R, E, A> | Concat<R, E, A> | FromPull<R, E, A> | FromArray<R, E, A> | Flatten<R, E, A> | Merge<R, E, A> | Scoped<R, E, A> | Managed<R, E, A>;
42
46
  type Normalize<E> = (u: unknown) => E;
43
47
  declare const widenOpt: <E1, E2>(opt: Option<E1>) => Option<E1 | E2>;
44
48
  declare const fromPull: <R, E, A>(pull: ZIO<R, Option<E>, [A, ZStream<R, E, A>]>) => ZStream<R, E, A>;
@@ -61,6 +65,10 @@ declare function zip<R, E1, A, E2, B>(left: ZStream<R, E1, A>, right: ZStream<R,
61
65
  declare function foreachStream<R, E, A, R2, E2>(stream: ZStream<R, E, A>, f: (a: A) => Async<R2, E2, void>): Async<R & R2, E | E2, void>;
62
66
  declare function fromArray<A>(values: readonly A[]): ZStream<unknown, never, A>;
63
67
  declare function collectStream<R, E, A>(stream: ZStream<R, E, A>): ZIO<R, E, A[]>;
64
- declare function streamFromReadableStream<E>(body: ReadableStream<Uint8Array> | null | undefined, normalizeError: Normalize<E>): ZStream<unknown, E, Uint8Array>;
68
+ type ReadableStreamOptions = {
69
+ signal?: AbortSignal;
70
+ onRelease?: () => void;
71
+ };
72
+ declare function streamFromReadableStream<E>(body: ReadableStream<Uint8Array> | null | undefined, normalizeError: Normalize<E>, options?: ReadableStreamOptions): ZStream<unknown, E, Uint8Array>;
65
73
 
66
- export { type Concat as C, type Emit as E, type Flatten as F, type Managed as M, type Normalize as N, type Scoped as S, type ZStream as Z, type Empty as a, type FromPull as b, type Merge as c, assertNever as d, collectStream as e, concatStream as f, emitStream as g, emptyStream as h, flattenStream as i, foreachStream as j, fromArray as k, fromPull as l, managedStream as m, mapStream as n, merge as o, mergeStream as p, unwrapScoped as q, rangeStream as r, streamFromReadableStream as s, uncons as u, widenOpt as w, zip as z };
74
+ export { type Concat as C, type Emit as E, type Flatten as F, type Managed as M, type Normalize as N, type ReadableStreamOptions as R, type Scoped as S, type ZStream as Z, type Empty as a, type FromArray as b, type FromPull as c, type Merge as d, assertNever as e, collectStream as f, concatStream as g, emitStream as h, emptyStream as i, flattenStream as j, foreachStream as k, fromArray as l, fromPull as m, managedStream as n, mapStream as o, merge as p, mergeStream as q, rangeStream as r, streamFromReadableStream as s, unwrapScoped as t, uncons as u, widenOpt as w, zip as z };
@@ -0,0 +1,106 @@
1
+ import { A as Async } from './effect-CMOQKX8y.js';
2
+
3
+ type CircuitBreakerState = "closed" | "open" | "half-open";
4
+ type CircuitBreakerError = {
5
+ readonly _tag: "CircuitBreakerOpen";
6
+ readonly openSince: number;
7
+ readonly failures: number;
8
+ };
9
+ type CircuitBreakerConfig = {
10
+ /** Number of consecutive failures before opening the circuit. Default: 5 */
11
+ readonly failureThreshold?: number;
12
+ /** Time in ms to wait before transitioning from OPEN to HALF_OPEN. Default: 30000 */
13
+ readonly resetTimeoutMs?: number;
14
+ /** Number of successes in HALF_OPEN needed to close the circuit. Default: 1 */
15
+ readonly successThreshold?: number;
16
+ /** Custom predicate: should this error count as a failure? Default: all errors count. */
17
+ readonly isFailure?: (error: unknown) => boolean;
18
+ /** Called on state transitions (for observability). */
19
+ readonly onStateChange?: (from: CircuitBreakerState, to: CircuitBreakerState) => void;
20
+ };
21
+ type CircuitBreakerStats = {
22
+ readonly state: CircuitBreakerState;
23
+ readonly failures: number;
24
+ readonly successes: number;
25
+ readonly totalRequests: number;
26
+ readonly totalFailures: number;
27
+ readonly totalSuccesses: number;
28
+ readonly totalRejected: number;
29
+ readonly lastFailureTime: number | null;
30
+ readonly lastSuccessTime: number | null;
31
+ };
32
+ type CircuitBreaker = {
33
+ /** Current state of the circuit breaker. */
34
+ readonly state: () => CircuitBreakerState;
35
+ /** Run an effect through the circuit breaker. */
36
+ readonly protect: <R, E, A>(effect: Async<R, E, A>) => Async<R, E | CircuitBreakerError, A>;
37
+ /** Get current stats. */
38
+ readonly stats: () => CircuitBreakerStats;
39
+ /** Manually reset to closed state. */
40
+ readonly reset: () => void;
41
+ };
42
+ /**
43
+ * Creates a circuit breaker.
44
+ *
45
+ * ```ts
46
+ * const breaker = makeCircuitBreaker({ failureThreshold: 3, resetTimeoutMs: 10000 });
47
+ *
48
+ * // Protect an effect:
49
+ * const result = await run(breaker.protect(callExternalService()));
50
+ * // Throws CircuitBreakerOpen if circuit is open
51
+ * ```
52
+ */
53
+ declare function makeCircuitBreaker(config?: CircuitBreakerConfig): CircuitBreaker;
54
+
55
+ type SpanContext = {
56
+ readonly traceId: string;
57
+ readonly spanId: string;
58
+ readonly parentSpanId?: string;
59
+ };
60
+ type SpanStatus = "ok" | "error" | "unset";
61
+ type Span = {
62
+ readonly name: string;
63
+ readonly context: SpanContext;
64
+ readonly startTime: number;
65
+ endTime?: number;
66
+ status: SpanStatus;
67
+ readonly attributes: Record<string, string | number | boolean>;
68
+ readonly events: SpanEvent[];
69
+ };
70
+ type SpanEvent = {
71
+ readonly name: string;
72
+ readonly time: number;
73
+ readonly attributes?: Record<string, string | number | boolean>;
74
+ };
75
+ type TracerConfig = {
76
+ /** Service name for span metadata. */
77
+ readonly serviceName: string;
78
+ /** Called when a span ends (for export). */
79
+ readonly onSpanEnd?: (span: Span) => void;
80
+ /** Sampling rate (0.0 to 1.0). Default: 1.0 (sample everything). */
81
+ readonly sampleRate?: number;
82
+ };
83
+ type Tracer = {
84
+ /** Wrap an effect in a span. */
85
+ readonly span: <R, E, A>(name: string, effect: Async<R, E, A>, attributes?: Record<string, string | number | boolean>) => Async<R, E, A>;
86
+ /** Get all completed spans (for testing). */
87
+ readonly spans: () => readonly Span[];
88
+ /** Clear collected spans. */
89
+ readonly clear: () => void;
90
+ };
91
+ /**
92
+ * Creates a tracer that wraps effects in spans.
93
+ *
94
+ * ```ts
95
+ * const tracer = makeTracer({ serviceName: "my-app" });
96
+ *
97
+ * const result = await run(
98
+ * tracer.span("fetchUser", fetchUser(id), { userId: id })
99
+ * );
100
+ *
101
+ * console.log(tracer.spans()); // all completed spans
102
+ * ```
103
+ */
104
+ declare function makeTracer(config: TracerConfig): Tracer;
105
+
106
+ export { type CircuitBreaker as C, type Span as S, type Tracer as T, type CircuitBreakerConfig as a, type CircuitBreakerError as b, type CircuitBreakerState as c, type CircuitBreakerStats as d, type SpanContext as e, type SpanEvent as f, type SpanStatus as g, type TracerConfig as h, makeTracer as i, makeCircuitBreaker as m };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brass-runtime",
3
- "version": "1.13.8",
3
+ "version": "1.15.0",
4
4
  "description": "Effect runtime utilities for TypeScript",
5
5
  "license": "MIT",
6
6
  "author": "Augusto Vivaldelli",
@@ -18,6 +18,11 @@
18
18
  "import": "./dist/http/index.mjs",
19
19
  "require": "./dist/http/index.cjs"
20
20
  },
21
+ "./core": {
22
+ "types": "./dist/core/index.d.ts",
23
+ "import": "./dist/core/index.mjs",
24
+ "require": "./dist/core/index.cjs"
25
+ },
21
26
  "./agent": {
22
27
  "types": "./dist/agent/index.d.ts",
23
28
  "import": "./dist/agent/index.mjs",
@@ -55,7 +60,9 @@
55
60
  "clean": "rimraf dist wasm/pkg",
56
61
  "test": "vitest run",
57
62
  "test:watch": "vitest",
58
- "test:coverage": "vitest run --coverage",
63
+ "test:coverage": "COVERAGE_GATE=baseline vitest run --coverage",
64
+ "test:coverage:report": "COVERAGE_GATE=off vitest run --coverage",
65
+ "test:coverage:100": "COVERAGE_GATE=100 vitest run --coverage",
59
66
  "test:types": "tsc -p tsconfig.json --noEmit",
60
67
  "check": "npm run test:types && npm run test && npm run test:coverage",
61
68
  "check:full": "npm run clean && npm run build && npm run test",
@@ -84,7 +91,8 @@
84
91
  "agent:vscode:reinstall:global": "npm run agent:vscode:uninstall:global && npm run agent:vscode:install:global",
85
92
  "benchmark": "tsx src/benchmarks/runner.ts",
86
93
  "benchmark:json": "tsx src/benchmarks/runner.ts --json",
87
- "test:coverage:html": "vitest run --coverage --reporter=default",
94
+ "context": "node scripts/context-pack.mjs",
95
+ "test:coverage:html": "COVERAGE_GATE=off vitest run --coverage --reporter=default",
88
96
  "build:wasm": "cd crates/brass-runtime-wasm-engine && wasm-pack build --target nodejs --out-dir ../../wasm/pkg",
89
97
  "build:ts": "tsup",
90
98
  "validate:cjs": "node scripts/validate-cjs.mjs"
@@ -15,6 +15,22 @@ export class BrassWasmChunkBuffer {
15
15
  take_chunk(): Array<any>;
16
16
  }
17
17
 
18
+ export class BrassWasmFiberReadyQueue {
19
+ free(): void;
20
+ [Symbol.dispose](): void;
21
+ begin_flush(): number;
22
+ clear(): void;
23
+ end_flush(ran: number): number;
24
+ enqueue_fiber(fiber_id: number, tag: string): number;
25
+ enqueue_fiber_lane(fiber_id: number, lane_id: number): number;
26
+ intern_lane(key: string): number;
27
+ len(): number;
28
+ metric_u64(id: number): number;
29
+ constructor(flush_budget: number, micro_threshold: number, lane_capacity: number, lane_budget: number, max_lanes: number);
30
+ shift_fiber(): number;
31
+ stats_json(): string;
32
+ }
33
+
18
34
  export class BrassWasmFiberRegistry {
19
35
  free(): void;
20
36
  [Symbol.dispose](): void;
@@ -33,6 +49,37 @@ export class BrassWasmFiberRegistry {
33
49
  wake_queue_len(): number;
34
50
  }
35
51
 
52
+ export class BrassWasmHttpPermitPool {
53
+ free(): void;
54
+ [Symbol.dispose](): void;
55
+ acquire(subject_id: number, key_id: number, now_ms: bigint): number;
56
+ advance_time(now_ms: bigint): number;
57
+ cancel(permit_id: number): boolean;
58
+ intern_key(key: string): number;
59
+ last_permit_id(): number;
60
+ memory(): any;
61
+ metric_u64(id: number): number;
62
+ metrics_snapshot_len(): number;
63
+ metrics_snapshot_ptr(): number;
64
+ constructor(concurrency: number, max_queue: number, queue_timeout_ms: bigint);
65
+ next_deadline_ms(): number;
66
+ permit_events_len(): number;
67
+ release(key_id: number, now_ms: bigint): number;
68
+ }
69
+
70
+ export class BrassWasmRetryPlanner {
71
+ free(): void;
72
+ [Symbol.dispose](): void;
73
+ drop_state(retry_id: number): boolean;
74
+ memory(): any;
75
+ metric_u64(id: number): number;
76
+ metrics_snapshot_len(): number;
77
+ metrics_snapshot_ptr(): number;
78
+ constructor();
79
+ next_delay_ms(retry_id: number, now_ms: number, retryable: boolean, retry_after_ms: number): number;
80
+ start(now_ms: number, max_retries: number, base_delay_ms: number, max_delay_ms: number, max_elapsed_ms: number, seed: bigint): number;
81
+ }
82
+
36
83
  export class BrassWasmRingBuffer {
37
84
  free(): void;
38
85
  [Symbol.dispose](): void;
@@ -48,45 +95,77 @@ export class BrassWasmRingBuffer {
48
95
  export class BrassWasmSchedulerStateMachine {
49
96
  free(): void;
50
97
  [Symbol.dispose](): void;
51
- /**
52
- * Enter flushing. Returns the number of tasks this flush may run.
53
- */
54
98
  begin_flush(): number;
55
99
  capacity(): number;
56
100
  clear(): void;
57
- /**
58
- * Finish a flush. Returns the scheduling policy for the next flush:
59
- * - 0 => schedule a micro flush
60
- * - 1 => schedule a macro flush
61
- * - 2 => no more work
62
- */
63
101
  end_flush(ran: number): number;
102
+ enqueue(task_ref: number, tag: string): number;
64
103
  /**
65
- * Enqueue a task ref and return the scheduling policy:
66
- * - 0 => schedule a micro flush
67
- * - 1 => schedule a macro flush
68
- * - 2 => no new flush needed
69
- * - 3 => queue full / task dropped
104
+ * Enqueue multiple tasks in a single boundary crossing.
105
+ * Returns a Uint32Array of policies (one per task):
106
+ * - 0 = SCHEDULER_POLICY_MICRO
107
+ * - 1 = SCHEDULER_POLICY_MACRO
108
+ * - 2 = SCHEDULER_POLICY_NONE (already scheduled)
109
+ * - 3 = SCHEDULER_POLICY_DROPPED
70
110
  */
71
- enqueue(task_ref: number): number;
111
+ enqueue_batch(task_refs: Uint32Array, tags: Array<any>): Uint32Array;
112
+ enqueue_lane(task_ref: number, lane_id: number): number;
113
+ intern_lane(key: string): number;
72
114
  is_flushing(): boolean;
73
115
  is_scheduled(): boolean;
116
+ lane_len(lane_id: number): number;
74
117
  len(): number;
75
- constructor(initial_capacity: number, max_capacity: number, flush_budget: number, micro_threshold: number);
118
+ metric_u64(id: number): number;
119
+ constructor(_initial_capacity: number, max_capacity: number, flush_budget: number, micro_threshold: number, lane_capacity: number, lane_budget: number, max_lanes: number);
76
120
  shift(): number;
77
121
  stats_json(): string;
78
122
  }
79
123
 
124
+ export class BrassWasmTimerWheel {
125
+ free(): void;
126
+ [Symbol.dispose](): void;
127
+ advance_time(now_ms: bigint): number;
128
+ cancel(timer_id: number): boolean;
129
+ expired_len(): number;
130
+ memory(): any;
131
+ metric_u64(id: number): number;
132
+ metrics_snapshot_len(): number;
133
+ metrics_snapshot_ptr(): number;
134
+ constructor(tick_ms: bigint, bucket_count: number);
135
+ next_deadline_ms(): number;
136
+ schedule_deadline(subject_id: number, kind: number, deadline_ms: bigint): number;
137
+ }
138
+
80
139
  export class BrassWasmVm {
81
140
  free(): void;
82
141
  [Symbol.dispose](): void;
83
142
  create_fiber(program_json: string): number;
143
+ create_fiber_bin(program_words: Uint32Array): number;
144
+ create_fiber_from_program_words(word_len: number): number;
145
+ drive_batch_bin(fiber_id: number, budget: number): Uint32Array;
146
+ drive_batch_ptr(fiber_id: number, budget: number): number;
84
147
  drop_fiber(fiber_id: number): void;
148
+ event_batch_len(): number;
85
149
  interrupt(fiber_id: number, reason_ref: number): string;
150
+ interrupt_bin(fiber_id: number, reason_ref: number, budget: number): Uint32Array;
151
+ interrupt_ptr(fiber_id: number, reason_ref: number, budget: number): number;
152
+ memory(): any;
153
+ metric_u64(id: number): number;
154
+ metrics_snapshot_len(): number;
155
+ metrics_snapshot_ptr(): number;
86
156
  constructor();
87
157
  poll(fiber_id: number): string;
158
+ poll_bin(fiber_id: number): Uint32Array;
159
+ prepare_patch_words(word_len: number): number;
160
+ prepare_program_words(word_len: number): number;
88
161
  provide_effect(fiber_id: number, root: number, nodes_json: string): string;
162
+ provide_effect_bin(fiber_id: number, root: number, nodes_words: Uint32Array, budget: number): Uint32Array;
163
+ provide_effect_from_words(fiber_id: number, root: number, word_len: number, budget: number): number;
89
164
  provide_error(fiber_id: number, error_ref: number): string;
165
+ provide_error_bin(fiber_id: number, error_ref: number, budget: number): Uint32Array;
166
+ provide_error_ptr(fiber_id: number, error_ref: number, budget: number): number;
90
167
  provide_value(fiber_id: number, value_ref: number): string;
168
+ provide_value_bin(fiber_id: number, value_ref: number, budget: number): Uint32Array;
169
+ provide_value_ptr(fiber_id: number, value_ref: number, budget: number): number;
91
170
  stats_json(): string;
92
171
  }