atabey 0.1.1-beta → 0.1.2
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/README.md +144 -78
- package/dist/atabey/src/cli/commands/coverage.js +17 -12
- package/dist/atabey/src/cli/commands/coverage.js.map +1 -1
- package/dist/atabey/src/cli/commands/lint.d.ts +2 -1
- package/dist/atabey/src/cli/commands/lint.js +20 -1
- package/dist/atabey/src/cli/commands/lint.js.map +1 -1
- package/dist/atabey/src/cli/commands/mcp.js +56 -23
- package/dist/atabey/src/cli/commands/mcp.js.map +1 -1
- package/dist/atabey/src/cli/commands/orchestrate.d.ts +6 -6
- package/dist/shared/src/agent-identity.d.ts +1 -34
- package/dist/shared/src/agent-identity.js +1 -76
- package/dist/shared/src/agent-identity.js.map +1 -1
- package/dist/shared/src/api-catalog.d.ts +1 -57
- package/dist/shared/src/api-catalog.js +1 -253
- package/dist/shared/src/api-catalog.js.map +1 -1
- package/dist/shared/src/audit-chain.d.ts +1 -80
- package/dist/shared/src/audit-chain.js +1 -261
- package/dist/shared/src/audit-chain.js.map +1 -1
- package/dist/shared/src/audit.d.ts +1 -121
- package/dist/shared/src/audit.js +1 -321
- package/dist/shared/src/audit.js.map +1 -1
- package/dist/shared/src/constants.d.ts +1 -150
- package/dist/shared/src/constants.js +1 -211
- package/dist/shared/src/constants.js.map +1 -1
- package/dist/shared/src/database.d.ts +1 -6
- package/dist/shared/src/database.js +1 -15
- package/dist/shared/src/database.js.map +1 -1
- package/dist/shared/src/errors.d.ts +1 -46
- package/dist/shared/src/errors.js +1 -68
- package/dist/shared/src/errors.js.map +1 -1
- package/dist/shared/src/file-lock.d.ts +1 -93
- package/dist/shared/src/file-lock.js +1 -239
- package/dist/shared/src/file-lock.js.map +1 -1
- package/dist/shared/src/fs.d.ts +1 -9
- package/dist/shared/src/fs.js +1 -53
- package/dist/shared/src/fs.js.map +1 -1
- package/dist/shared/src/index.d.ts +2 -31
- package/dist/shared/src/index.js +2 -31
- package/dist/shared/src/index.js.map +1 -1
- package/dist/shared/src/job-queue.d.ts +1 -76
- package/dist/shared/src/job-queue.js +1 -199
- package/dist/shared/src/job-queue.js.map +1 -1
- package/dist/shared/src/lock.d.ts +1 -82
- package/dist/shared/src/lock.js +1 -158
- package/dist/shared/src/lock.js.map +1 -1
- package/dist/shared/src/logger.d.ts +1 -31
- package/dist/shared/src/logger.js +1 -152
- package/dist/shared/src/logger.js.map +1 -1
- package/dist/shared/src/memory-prune.d.ts +1 -18
- package/dist/shared/src/memory-prune.js +1 -47
- package/dist/shared/src/memory-prune.js.map +1 -1
- package/dist/shared/src/migrations.d.ts +1 -69
- package/dist/shared/src/migrations.js +1 -393
- package/dist/shared/src/migrations.js.map +1 -1
- package/dist/shared/src/modules/agent/agent-identity.d.ts +34 -0
- package/dist/shared/src/modules/agent/agent-identity.js +77 -0
- package/dist/shared/src/modules/agent/agent-identity.js.map +1 -0
- package/dist/shared/src/modules/agent/api-catalog.d.ts +57 -0
- package/dist/shared/src/modules/agent/api-catalog.js +254 -0
- package/dist/shared/src/modules/agent/api-catalog.js.map +1 -0
- package/dist/shared/src/modules/agent/index.d.ts +3 -0
- package/dist/shared/src/modules/agent/index.js +4 -0
- package/dist/shared/src/modules/agent/index.js.map +1 -0
- package/dist/shared/src/modules/agent/tokenizer.d.ts +54 -0
- package/dist/shared/src/modules/agent/tokenizer.js +272 -0
- package/dist/shared/src/modules/agent/tokenizer.js.map +1 -0
- package/dist/shared/src/modules/concurrency/file-lock.d.ts +93 -0
- package/dist/shared/src/modules/concurrency/file-lock.js +240 -0
- package/dist/shared/src/modules/concurrency/file-lock.js.map +1 -0
- package/dist/shared/src/modules/concurrency/index.d.ts +6 -0
- package/dist/shared/src/modules/concurrency/index.js +7 -0
- package/dist/shared/src/modules/concurrency/index.js.map +1 -0
- package/dist/shared/src/modules/concurrency/job-queue.d.ts +76 -0
- package/dist/shared/src/modules/concurrency/job-queue.js +200 -0
- package/dist/shared/src/modules/concurrency/job-queue.js.map +1 -0
- package/dist/shared/src/modules/concurrency/lock.d.ts +82 -0
- package/dist/shared/src/modules/concurrency/lock.js +159 -0
- package/dist/shared/src/modules/concurrency/lock.js.map +1 -0
- package/dist/shared/src/modules/concurrency/resilience.d.ts +84 -0
- package/dist/shared/src/modules/concurrency/resilience.js +217 -0
- package/dist/shared/src/modules/concurrency/resilience.js.map +1 -0
- package/dist/shared/src/modules/concurrency/worker-pool.d.ts +52 -0
- package/dist/shared/src/modules/concurrency/worker-pool.js +229 -0
- package/dist/shared/src/modules/concurrency/worker-pool.js.map +1 -0
- package/dist/shared/src/modules/concurrency/worker-thread.d.ts +21 -0
- package/dist/shared/src/modules/concurrency/worker-thread.js +67 -0
- package/dist/shared/src/modules/concurrency/worker-thread.js.map +1 -0
- package/dist/shared/src/modules/index.d.ts +14 -0
- package/dist/shared/src/modules/index.js +15 -0
- package/dist/shared/src/modules/index.js.map +1 -0
- package/dist/shared/src/modules/observability/audit-chain.d.ts +80 -0
- package/dist/shared/src/modules/observability/audit-chain.js +262 -0
- package/dist/shared/src/modules/observability/audit-chain.js.map +1 -0
- package/dist/shared/src/modules/observability/audit.d.ts +121 -0
- package/dist/shared/src/modules/observability/audit.js +322 -0
- package/dist/shared/src/modules/observability/audit.js.map +1 -0
- package/dist/shared/src/modules/observability/index.d.ts +4 -0
- package/dist/shared/src/modules/observability/index.js +5 -0
- package/dist/shared/src/modules/observability/index.js.map +1 -0
- package/dist/shared/src/modules/observability/logger.d.ts +31 -0
- package/dist/shared/src/modules/observability/logger.js +153 -0
- package/dist/shared/src/modules/observability/logger.js.map +1 -0
- package/dist/shared/src/modules/observability/otel.d.ts +39 -0
- package/dist/shared/src/modules/observability/otel.js +93 -0
- package/dist/shared/src/modules/observability/otel.js.map +1 -0
- package/dist/shared/src/modules/primitives/constants.d.ts +150 -0
- package/dist/shared/src/modules/primitives/constants.js +212 -0
- package/dist/shared/src/modules/primitives/constants.js.map +1 -0
- package/dist/shared/src/modules/primitives/errors.d.ts +46 -0
- package/dist/shared/src/modules/primitives/errors.js +69 -0
- package/dist/shared/src/modules/primitives/errors.js.map +1 -0
- package/dist/shared/src/modules/primitives/fs.d.ts +9 -0
- package/dist/shared/src/modules/primitives/fs.js +54 -0
- package/dist/shared/src/modules/primitives/fs.js.map +1 -0
- package/dist/shared/src/modules/primitives/index.d.ts +7 -0
- package/dist/shared/src/modules/primitives/index.js +8 -0
- package/dist/shared/src/modules/primitives/index.js.map +1 -0
- package/dist/shared/src/modules/primitives/outbound-http.d.ts +32 -0
- package/dist/shared/src/modules/primitives/outbound-http.js +88 -0
- package/dist/shared/src/modules/primitives/outbound-http.js.map +1 -0
- package/dist/shared/src/modules/primitives/string.d.ts +1 -0
- package/dist/shared/src/modules/primitives/string.js +30 -0
- package/dist/shared/src/modules/primitives/string.js.map +1 -0
- package/dist/shared/src/modules/primitives/time.d.ts +5 -0
- package/dist/shared/src/modules/primitives/time.js +35 -0
- package/dist/shared/src/modules/primitives/time.js.map +1 -0
- package/dist/shared/src/modules/primitives/types.d.ts +27 -0
- package/dist/shared/src/modules/primitives/types.js +17 -0
- package/dist/shared/src/modules/primitives/types.js.map +1 -0
- package/dist/shared/src/modules/sandbox/index.d.ts +3 -0
- package/dist/shared/src/modules/sandbox/index.js +4 -0
- package/dist/shared/src/modules/sandbox/index.js.map +1 -0
- package/dist/shared/src/modules/sandbox/sandbox-fs.d.ts +28 -0
- package/dist/shared/src/modules/sandbox/sandbox-fs.js +143 -0
- package/dist/shared/src/modules/sandbox/sandbox-fs.js.map +1 -0
- package/dist/shared/src/modules/sandbox/sandbox-runtime.d.ts +78 -0
- package/dist/shared/src/modules/sandbox/sandbox-runtime.js +282 -0
- package/dist/shared/src/modules/sandbox/sandbox-runtime.js.map +1 -0
- package/dist/shared/src/modules/sandbox/sandbox.d.ts +54 -0
- package/dist/shared/src/modules/sandbox/sandbox.js +179 -0
- package/dist/shared/src/modules/sandbox/sandbox.js.map +1 -0
- package/dist/shared/src/modules/security/index.d.ts +5 -0
- package/dist/shared/src/modules/security/index.js +6 -0
- package/dist/shared/src/modules/security/index.js.map +1 -0
- package/dist/shared/src/modules/security/pii.d.ts +70 -0
- package/dist/shared/src/modules/security/pii.js +276 -0
- package/dist/shared/src/modules/security/pii.js.map +1 -0
- package/dist/shared/src/modules/security/policy-gate.d.ts +42 -0
- package/dist/shared/src/modules/security/policy-gate.js +172 -0
- package/dist/shared/src/modules/security/policy-gate.js.map +1 -0
- package/dist/shared/src/modules/security/retention.d.ts +68 -0
- package/dist/shared/src/modules/security/retention.js +218 -0
- package/dist/shared/src/modules/security/retention.js.map +1 -0
- package/dist/shared/src/modules/security/secrets.d.ts +99 -0
- package/dist/shared/src/modules/security/secrets.js +371 -0
- package/dist/shared/src/modules/security/secrets.js.map +1 -0
- package/dist/shared/src/modules/security/tls.d.ts +87 -0
- package/dist/shared/src/modules/security/tls.js +154 -0
- package/dist/shared/src/modules/security/tls.js.map +1 -0
- package/dist/shared/src/modules/storage/database.d.ts +6 -0
- package/dist/shared/src/modules/storage/database.js +16 -0
- package/dist/shared/src/modules/storage/database.js.map +1 -0
- package/dist/shared/src/modules/storage/index.d.ts +4 -0
- package/dist/shared/src/modules/storage/index.js +5 -0
- package/dist/shared/src/modules/storage/index.js.map +1 -0
- package/dist/shared/src/modules/storage/memory-prune.d.ts +18 -0
- package/dist/shared/src/modules/storage/memory-prune.js +48 -0
- package/dist/shared/src/modules/storage/memory-prune.js.map +1 -0
- package/dist/shared/src/modules/storage/migrations.d.ts +69 -0
- package/dist/shared/src/modules/storage/migrations.js +394 -0
- package/dist/shared/src/modules/storage/migrations.js.map +1 -0
- package/dist/shared/src/modules/storage/storage.d.ts +341 -0
- package/dist/shared/src/modules/storage/storage.js +1004 -0
- package/dist/shared/src/modules/storage/storage.js.map +1 -0
- package/dist/shared/src/otel.d.ts +1 -39
- package/dist/shared/src/otel.js +1 -92
- package/dist/shared/src/otel.js.map +1 -1
- package/dist/shared/src/outbound-http.d.ts +1 -32
- package/dist/shared/src/outbound-http.js +1 -87
- package/dist/shared/src/outbound-http.js.map +1 -1
- package/dist/shared/src/pii.d.ts +1 -70
- package/dist/shared/src/pii.js +1 -275
- package/dist/shared/src/pii.js.map +1 -1
- package/dist/shared/src/policy-gate.d.ts +1 -42
- package/dist/shared/src/policy-gate.js +1 -171
- package/dist/shared/src/policy-gate.js.map +1 -1
- package/dist/shared/src/resilience.d.ts +1 -84
- package/dist/shared/src/resilience.js +1 -216
- package/dist/shared/src/resilience.js.map +1 -1
- package/dist/shared/src/retention.d.ts +1 -68
- package/dist/shared/src/retention.js +1 -217
- package/dist/shared/src/retention.js.map +1 -1
- package/dist/shared/src/sandbox-fs.d.ts +1 -28
- package/dist/shared/src/sandbox-fs.js +1 -142
- package/dist/shared/src/sandbox-fs.js.map +1 -1
- package/dist/shared/src/sandbox-runtime.d.ts +1 -78
- package/dist/shared/src/sandbox-runtime.js +1 -281
- package/dist/shared/src/sandbox-runtime.js.map +1 -1
- package/dist/shared/src/sandbox.d.ts +1 -54
- package/dist/shared/src/sandbox.js +1 -178
- package/dist/shared/src/sandbox.js.map +1 -1
- package/dist/shared/src/secrets.d.ts +1 -99
- package/dist/shared/src/secrets.js +1 -370
- package/dist/shared/src/secrets.js.map +1 -1
- package/dist/shared/src/storage.d.ts +1 -341
- package/dist/shared/src/storage.js +1 -1003
- package/dist/shared/src/storage.js.map +1 -1
- package/dist/shared/src/string.d.ts +1 -1
- package/dist/shared/src/string.js +1 -29
- package/dist/shared/src/string.js.map +1 -1
- package/dist/shared/src/time.d.ts +1 -5
- package/dist/shared/src/time.js +1 -34
- package/dist/shared/src/time.js.map +1 -1
- package/dist/shared/src/tls.d.ts +1 -87
- package/dist/shared/src/tls.js +1 -153
- package/dist/shared/src/tls.js.map +1 -1
- package/dist/shared/src/tokenizer.d.ts +1 -54
- package/dist/shared/src/tokenizer.js +1 -271
- package/dist/shared/src/tokenizer.js.map +1 -1
- package/dist/shared/src/types.d.ts +1 -27
- package/dist/shared/src/types.js +1 -16
- package/dist/shared/src/types.js.map +1 -1
- package/dist/shared/src/worker-pool.d.ts +1 -52
- package/dist/shared/src/worker-pool.js +1 -228
- package/dist/shared/src/worker-pool.js.map +1 -1
- package/dist/shared/src/worker-thread.d.ts +1 -21
- package/dist/shared/src/worker-thread.js +1 -66
- package/dist/shared/src/worker-thread.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polly-style resilience primitives — no external deps.
|
|
3
|
+
*
|
|
4
|
+
* - withRetry: exponential backoff + jitter for transient failures
|
|
5
|
+
* - CircuitBreaker: closed → open → half-open state machine
|
|
6
|
+
* - withResilience: compose retry + circuit breaker
|
|
7
|
+
*
|
|
8
|
+
* Typical use: LLM provider rate limits, timeouts, 5xx, network blips.
|
|
9
|
+
*/
|
|
10
|
+
export class CircuitOpenError extends Error {
|
|
11
|
+
circuit;
|
|
12
|
+
retryAfterMs;
|
|
13
|
+
constructor(circuit, retryAfterMs) {
|
|
14
|
+
super(`[CircuitBreaker:${circuit}] Circuit is OPEN — rejecting call. Retry after ~${retryAfterMs}ms`);
|
|
15
|
+
this.name = "CircuitOpenError";
|
|
16
|
+
this.circuit = circuit;
|
|
17
|
+
this.retryAfterMs = retryAfterMs;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class CircuitBreaker {
|
|
21
|
+
state = "closed";
|
|
22
|
+
failures = 0;
|
|
23
|
+
successes = 0;
|
|
24
|
+
openedAt = 0;
|
|
25
|
+
failureThreshold;
|
|
26
|
+
successThreshold;
|
|
27
|
+
openMs;
|
|
28
|
+
name;
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.failureThreshold = options.failureThreshold ?? 5;
|
|
31
|
+
this.successThreshold = options.successThreshold ?? 2;
|
|
32
|
+
this.openMs = options.openMs ?? 30_000;
|
|
33
|
+
this.name = options.name ?? "default";
|
|
34
|
+
}
|
|
35
|
+
getState() {
|
|
36
|
+
this.maybeTransitionToHalfOpen();
|
|
37
|
+
return this.state;
|
|
38
|
+
}
|
|
39
|
+
getStats() {
|
|
40
|
+
return {
|
|
41
|
+
state: this.getState(),
|
|
42
|
+
failures: this.failures,
|
|
43
|
+
successes: this.successes,
|
|
44
|
+
name: this.name,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Manual reset (e.g. after operator intervention). */
|
|
48
|
+
reset() {
|
|
49
|
+
this.state = "closed";
|
|
50
|
+
this.failures = 0;
|
|
51
|
+
this.successes = 0;
|
|
52
|
+
this.openedAt = 0;
|
|
53
|
+
}
|
|
54
|
+
async exec(fn) {
|
|
55
|
+
this.maybeTransitionToHalfOpen();
|
|
56
|
+
if (this.state === "open") {
|
|
57
|
+
const retryAfterMs = Math.max(0, this.openMs - (Date.now() - this.openedAt));
|
|
58
|
+
throw new CircuitOpenError(this.name, retryAfterMs);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const result = await fn();
|
|
62
|
+
this.onSuccess();
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
this.onFailure();
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
maybeTransitionToHalfOpen() {
|
|
71
|
+
if (this.state === "open" && Date.now() - this.openedAt >= this.openMs) {
|
|
72
|
+
this.state = "half-open";
|
|
73
|
+
this.successes = 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
onSuccess() {
|
|
77
|
+
if (this.state === "half-open") {
|
|
78
|
+
this.successes++;
|
|
79
|
+
if (this.successes >= this.successThreshold) {
|
|
80
|
+
this.state = "closed";
|
|
81
|
+
this.failures = 0;
|
|
82
|
+
this.successes = 0;
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// closed: decay failure count on success
|
|
87
|
+
this.failures = 0;
|
|
88
|
+
}
|
|
89
|
+
onFailure() {
|
|
90
|
+
this.failures++;
|
|
91
|
+
this.successes = 0;
|
|
92
|
+
if (this.state === "half-open") {
|
|
93
|
+
this.trip();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (this.failures >= this.failureThreshold) {
|
|
97
|
+
this.trip();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
trip() {
|
|
101
|
+
this.state = "open";
|
|
102
|
+
this.openedAt = Date.now();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function computeBackoffDelay(attempt, options = {}) {
|
|
106
|
+
const base = options.baseDelayMs ?? 100;
|
|
107
|
+
const max = options.maxDelayMs ?? 10_000;
|
|
108
|
+
const factor = options.factor ?? 2;
|
|
109
|
+
const jitter = options.jitter !== false;
|
|
110
|
+
// attempt is 1-based for first retry after failure → attempt 1 => base * factor^0
|
|
111
|
+
const exp = Math.max(0, attempt - 1);
|
|
112
|
+
let delay = Math.min(max, base * Math.pow(factor, exp));
|
|
113
|
+
if (jitter) {
|
|
114
|
+
delay = Math.floor(Math.random() * delay);
|
|
115
|
+
}
|
|
116
|
+
return delay;
|
|
117
|
+
}
|
|
118
|
+
export async function withRetry(fn, options = {}) {
|
|
119
|
+
const maxAttempts = Math.max(1, options.maxAttempts ?? 3);
|
|
120
|
+
const retryIf = options.retryIf ?? (() => true);
|
|
121
|
+
let lastError;
|
|
122
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
123
|
+
if (options.signal?.aborted) {
|
|
124
|
+
throw options.signal.reason ?? new Error("Aborted");
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
return await fn(attempt);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
lastError = err;
|
|
131
|
+
const isLast = attempt >= maxAttempts;
|
|
132
|
+
if (isLast || !retryIf(err, attempt)) {
|
|
133
|
+
throw err;
|
|
134
|
+
}
|
|
135
|
+
const delay = computeBackoffDelay(attempt, options);
|
|
136
|
+
options.onRetry?.(err, attempt, delay);
|
|
137
|
+
await sleep(delay, options.signal);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
throw lastError;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Execute `fn` through optional circuit breaker + retry with exponential backoff.
|
|
144
|
+
*/
|
|
145
|
+
export async function withResilience(fn, options = {}) {
|
|
146
|
+
const breaker = options.circuitBreaker;
|
|
147
|
+
const skipOpen = options.skipRetryOnOpenCircuit !== false;
|
|
148
|
+
const retryOpts = {
|
|
149
|
+
...options.retry,
|
|
150
|
+
retryIf: (err, attempt) => {
|
|
151
|
+
if (skipOpen && err instanceof CircuitOpenError)
|
|
152
|
+
return false;
|
|
153
|
+
return options.retry?.retryIf ? options.retry.retryIf(err, attempt) : true;
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
return withRetry(async (attempt) => {
|
|
157
|
+
if (breaker) {
|
|
158
|
+
return breaker.exec(() => fn(attempt));
|
|
159
|
+
}
|
|
160
|
+
return fn(attempt);
|
|
161
|
+
}, retryOpts);
|
|
162
|
+
}
|
|
163
|
+
/** Heuristic: retry rate limits, timeouts, and common transient network errors. */
|
|
164
|
+
export function isTransientError(error) {
|
|
165
|
+
if (error instanceof CircuitOpenError)
|
|
166
|
+
return false;
|
|
167
|
+
if (!error)
|
|
168
|
+
return false;
|
|
169
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
170
|
+
const lower = msg.toLowerCase();
|
|
171
|
+
const code = error.code;
|
|
172
|
+
const status = error.status;
|
|
173
|
+
if (status === 429 || status === 502 || status === 503 || status === 504)
|
|
174
|
+
return true;
|
|
175
|
+
if (code === "ETIMEDOUT" || code === "ECONNRESET" || code === "EAI_AGAIN" || code === "ENOTFOUND") {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
if (lower.includes("rate limit") ||
|
|
179
|
+
lower.includes("too many requests") ||
|
|
180
|
+
lower.includes("timeout") ||
|
|
181
|
+
lower.includes("temporar") ||
|
|
182
|
+
lower.includes("econnreset") ||
|
|
183
|
+
lower.includes("socket hang up")) {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
/** Shared breakers for common services (lazy). */
|
|
189
|
+
const breakers = new Map();
|
|
190
|
+
export function getCircuitBreaker(name, options) {
|
|
191
|
+
let b = breakers.get(name);
|
|
192
|
+
if (!b) {
|
|
193
|
+
b = new CircuitBreaker({ name, ...options });
|
|
194
|
+
breakers.set(name, b);
|
|
195
|
+
}
|
|
196
|
+
return b;
|
|
197
|
+
}
|
|
198
|
+
export function resetAllCircuitBreakers() {
|
|
199
|
+
for (const b of breakers.values())
|
|
200
|
+
b.reset();
|
|
201
|
+
breakers.clear();
|
|
202
|
+
}
|
|
203
|
+
function sleep(ms, signal) {
|
|
204
|
+
return new Promise((resolve, reject) => {
|
|
205
|
+
if (signal?.aborted) {
|
|
206
|
+
reject(signal.reason ?? new Error("Aborted"));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const timer = setTimeout(resolve, ms);
|
|
210
|
+
const onAbort = () => {
|
|
211
|
+
clearTimeout(timer);
|
|
212
|
+
reject(signal?.reason ?? new Error("Aborted"));
|
|
213
|
+
};
|
|
214
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=resilience.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resilience.js","sourceRoot":"","sources":["../../../../../../shared/src/modules/concurrency/resilience.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory Worker Pool — worker_threads based, no Redis/BullMQ.
|
|
3
|
+
*
|
|
4
|
+
* Heavy / isolable work runs off the main thread. Concurrency is capped
|
|
5
|
+
* (default os.cpus().length) via an internal queue so RAM/CPU stay bounded.
|
|
6
|
+
*
|
|
7
|
+
* Thread-safety note: SQLite (better-sqlite3) bindings are NOT thread-safe.
|
|
8
|
+
* Worker threads MUST NOT access AtabeyStorage or any SQLite connection.
|
|
9
|
+
* Only CPU-bound isolable work (hash, tokenize, etc.) should be dispatched
|
|
10
|
+
* to the worker pool.
|
|
11
|
+
*/
|
|
12
|
+
export interface WorkerPoolOptions {
|
|
13
|
+
/** Max concurrent worker jobs. Default: os.cpus().length (clamped 1–16). */
|
|
14
|
+
maxConcurrency?: number;
|
|
15
|
+
/** Idle workers retained in the pool. Default: min(2, maxConcurrency). */
|
|
16
|
+
minWorkers?: number;
|
|
17
|
+
/** Per-job timeout in ms. Default: 30_000. */
|
|
18
|
+
jobTimeoutMs?: number;
|
|
19
|
+
/** Optional absolute path to worker script (tests / monorepo layouts). */
|
|
20
|
+
workerScript?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class WorkerPool {
|
|
23
|
+
private readonly maxConcurrency;
|
|
24
|
+
private readonly minWorkers;
|
|
25
|
+
private readonly jobTimeoutMs;
|
|
26
|
+
private readonly workerScript;
|
|
27
|
+
private readonly workers;
|
|
28
|
+
private readonly queue;
|
|
29
|
+
private readonly inflight;
|
|
30
|
+
private jobSeq;
|
|
31
|
+
private closed;
|
|
32
|
+
constructor(options?: WorkerPoolOptions);
|
|
33
|
+
/**
|
|
34
|
+
* Run a named job type on a worker thread.
|
|
35
|
+
* Returns when the worker posts a result (or on timeout/error).
|
|
36
|
+
*/
|
|
37
|
+
run<T = unknown>(type: string, payload?: unknown): Promise<T>;
|
|
38
|
+
getStats(): {
|
|
39
|
+
maxConcurrency: number;
|
|
40
|
+
workers: number;
|
|
41
|
+
busy: number;
|
|
42
|
+
pending: number;
|
|
43
|
+
inflight: number;
|
|
44
|
+
};
|
|
45
|
+
close(): Promise<void>;
|
|
46
|
+
private failWorkerJob;
|
|
47
|
+
private spawnWorker;
|
|
48
|
+
private removeWorker;
|
|
49
|
+
private dispatch;
|
|
50
|
+
}
|
|
51
|
+
export declare function getDefaultWorkerPool(options?: WorkerPoolOptions): WorkerPool;
|
|
52
|
+
export declare function resetDefaultWorkerPool(): Promise<void>;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Memory Worker Pool — worker_threads based, no Redis/BullMQ.
|
|
3
|
+
*
|
|
4
|
+
* Heavy / isolable work runs off the main thread. Concurrency is capped
|
|
5
|
+
* (default os.cpus().length) via an internal queue so RAM/CPU stay bounded.
|
|
6
|
+
*
|
|
7
|
+
* Thread-safety note: SQLite (better-sqlite3) bindings are NOT thread-safe.
|
|
8
|
+
* Worker threads MUST NOT access AtabeyStorage or any SQLite connection.
|
|
9
|
+
* Only CPU-bound isolable work (hash, tokenize, etc.) should be dispatched
|
|
10
|
+
* to the worker pool.
|
|
11
|
+
*/
|
|
12
|
+
import fs from "fs";
|
|
13
|
+
import os from "os";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { fileURLToPath } from "url";
|
|
16
|
+
import { Worker } from "worker_threads";
|
|
17
|
+
function defaultWorkerScript() {
|
|
18
|
+
// Compiled ESM layout: dist/worker-thread.js next to this module
|
|
19
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const jsScript = path.join(here, "worker-thread.js");
|
|
21
|
+
const tsScript = path.join(here, "worker-thread.ts");
|
|
22
|
+
// Prefer compiled JS; fall back to TS for dev (tsx/ts-node)
|
|
23
|
+
if (fs.existsSync(jsScript))
|
|
24
|
+
return jsScript;
|
|
25
|
+
if (fs.existsSync(tsScript))
|
|
26
|
+
return tsScript;
|
|
27
|
+
// Fallback: try resolving via import.meta.resolve for monorepo layouts
|
|
28
|
+
try {
|
|
29
|
+
const resolved = import.meta.resolve("./worker-thread.js");
|
|
30
|
+
if (resolved)
|
|
31
|
+
return new URL(resolved).pathname;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// ignore
|
|
35
|
+
}
|
|
36
|
+
return jsScript;
|
|
37
|
+
}
|
|
38
|
+
export class WorkerPool {
|
|
39
|
+
maxConcurrency;
|
|
40
|
+
minWorkers;
|
|
41
|
+
jobTimeoutMs;
|
|
42
|
+
workerScript;
|
|
43
|
+
workers = [];
|
|
44
|
+
queue = [];
|
|
45
|
+
inflight = new Map();
|
|
46
|
+
jobSeq = 0;
|
|
47
|
+
closed = false;
|
|
48
|
+
constructor(options = {}) {
|
|
49
|
+
const cpus = Math.max(1, os.cpus()?.length || 1);
|
|
50
|
+
const requested = options.maxConcurrency ?? cpus;
|
|
51
|
+
this.maxConcurrency = Math.max(1, Math.min(requested, 16));
|
|
52
|
+
this.minWorkers = Math.max(0, Math.min(options.minWorkers ?? Math.min(2, this.maxConcurrency), this.maxConcurrency));
|
|
53
|
+
this.jobTimeoutMs = options.jobTimeoutMs ?? 30_000;
|
|
54
|
+
this.workerScript = options.workerScript ?? defaultWorkerScript();
|
|
55
|
+
for (let i = 0; i < this.minWorkers; i++) {
|
|
56
|
+
this.spawnWorker();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Run a named job type on a worker thread.
|
|
61
|
+
* Returns when the worker posts a result (or on timeout/error).
|
|
62
|
+
*/
|
|
63
|
+
run(type, payload) {
|
|
64
|
+
if (this.closed) {
|
|
65
|
+
return Promise.reject(new Error("[WorkerPool] Pool is closed."));
|
|
66
|
+
}
|
|
67
|
+
const id = `wjob-${++this.jobSeq}-${Date.now()}`;
|
|
68
|
+
const job = { id, type, payload };
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
const timer = setTimeout(() => {
|
|
71
|
+
this.inflight.delete(id);
|
|
72
|
+
// Free (and recycle) the worker stuck on this job so a hung job
|
|
73
|
+
// cannot permanently occupy the pool and deadlock every caller.
|
|
74
|
+
const stuck = this.workers.find((w) => w.currentJobId === id);
|
|
75
|
+
if (stuck) {
|
|
76
|
+
stuck.busy = false;
|
|
77
|
+
stuck.currentJobId = null;
|
|
78
|
+
this.removeWorker(stuck);
|
|
79
|
+
void stuck.worker.terminate().catch(() => { });
|
|
80
|
+
}
|
|
81
|
+
reject(new Error(`[WorkerPool] Job ${id} timed out after ${this.jobTimeoutMs}ms`));
|
|
82
|
+
this.dispatch();
|
|
83
|
+
if (!this.closed && this.workers.length < this.minWorkers) {
|
|
84
|
+
this.spawnWorker();
|
|
85
|
+
}
|
|
86
|
+
}, this.jobTimeoutMs);
|
|
87
|
+
const pending = {
|
|
88
|
+
job,
|
|
89
|
+
resolve: (v) => resolve(v),
|
|
90
|
+
reject,
|
|
91
|
+
timer,
|
|
92
|
+
};
|
|
93
|
+
this.queue.push(pending);
|
|
94
|
+
this.dispatch();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
getStats() {
|
|
98
|
+
return {
|
|
99
|
+
maxConcurrency: this.maxConcurrency,
|
|
100
|
+
workers: this.workers.length,
|
|
101
|
+
busy: this.workers.filter((w) => w.busy).length,
|
|
102
|
+
pending: this.queue.length,
|
|
103
|
+
inflight: this.inflight.size,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async close() {
|
|
107
|
+
this.closed = true;
|
|
108
|
+
while (this.queue.length > 0) {
|
|
109
|
+
const p = this.queue.shift();
|
|
110
|
+
if (p) {
|
|
111
|
+
clearTimeout(p.timer);
|
|
112
|
+
p.reject(new Error("[WorkerPool] Pool closed while job was queued."));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Settle any in-flight jobs so their awaiters don't hang forever.
|
|
116
|
+
for (const pending of this.inflight.values()) {
|
|
117
|
+
clearTimeout(pending.timer);
|
|
118
|
+
pending.reject(new Error("[WorkerPool] Pool closed while the job was in flight."));
|
|
119
|
+
}
|
|
120
|
+
this.inflight.clear();
|
|
121
|
+
await Promise.all(this.workers.map((pw) => new Promise((resolve) => {
|
|
122
|
+
pw.worker.once("exit", () => resolve());
|
|
123
|
+
void pw.worker.terminate();
|
|
124
|
+
})));
|
|
125
|
+
this.workers.length = 0;
|
|
126
|
+
}
|
|
127
|
+
failWorkerJob(pw, error) {
|
|
128
|
+
const jobId = pw.currentJobId;
|
|
129
|
+
pw.busy = false;
|
|
130
|
+
pw.currentJobId = null;
|
|
131
|
+
if (!jobId)
|
|
132
|
+
return;
|
|
133
|
+
const pending = this.inflight.get(jobId);
|
|
134
|
+
if (!pending)
|
|
135
|
+
return;
|
|
136
|
+
clearTimeout(pending.timer);
|
|
137
|
+
this.inflight.delete(jobId);
|
|
138
|
+
pending.reject(error);
|
|
139
|
+
}
|
|
140
|
+
spawnWorker() {
|
|
141
|
+
const worker = new Worker(this.workerScript);
|
|
142
|
+
const pw = { worker, busy: false, currentJobId: null };
|
|
143
|
+
worker.on("message", (msg) => {
|
|
144
|
+
const pending = this.inflight.get(msg.id);
|
|
145
|
+
pw.busy = false;
|
|
146
|
+
pw.currentJobId = null;
|
|
147
|
+
if (!pending) {
|
|
148
|
+
this.dispatch();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
clearTimeout(pending.timer);
|
|
152
|
+
this.inflight.delete(msg.id);
|
|
153
|
+
if (msg.ok) {
|
|
154
|
+
pending.resolve(msg.result);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
pending.reject(new Error(msg.error || "Worker job failed"));
|
|
158
|
+
}
|
|
159
|
+
this.dispatch();
|
|
160
|
+
});
|
|
161
|
+
worker.on("error", (err) => {
|
|
162
|
+
this.failWorkerJob(pw, err instanceof Error ? err : new Error(String(err)));
|
|
163
|
+
this.removeWorker(pw);
|
|
164
|
+
if (!this.closed) {
|
|
165
|
+
this.spawnWorker();
|
|
166
|
+
}
|
|
167
|
+
this.dispatch();
|
|
168
|
+
});
|
|
169
|
+
worker.on("exit", (code) => {
|
|
170
|
+
if (pw.busy && pw.currentJobId) {
|
|
171
|
+
this.failWorkerJob(pw, new Error(`[WorkerPool] Worker exited with code ${code} while running job ${pw.currentJobId}`));
|
|
172
|
+
}
|
|
173
|
+
this.removeWorker(pw);
|
|
174
|
+
if (!this.closed && code !== 0) {
|
|
175
|
+
// Replace crashed worker so pool size recovers
|
|
176
|
+
if (this.workers.length < this.minWorkers) {
|
|
177
|
+
this.spawnWorker();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
this.dispatch();
|
|
181
|
+
});
|
|
182
|
+
this.workers.push(pw);
|
|
183
|
+
return pw;
|
|
184
|
+
}
|
|
185
|
+
removeWorker(pw) {
|
|
186
|
+
const idx = this.workers.indexOf(pw);
|
|
187
|
+
if (idx >= 0)
|
|
188
|
+
this.workers.splice(idx, 1);
|
|
189
|
+
}
|
|
190
|
+
dispatch() {
|
|
191
|
+
if (this.closed)
|
|
192
|
+
return;
|
|
193
|
+
while (this.queue.length > 0) {
|
|
194
|
+
let free = this.workers.find((w) => !w.busy);
|
|
195
|
+
if (!free && this.workers.length < this.maxConcurrency) {
|
|
196
|
+
free = this.spawnWorker();
|
|
197
|
+
}
|
|
198
|
+
if (!free)
|
|
199
|
+
break;
|
|
200
|
+
const pending = this.queue.shift();
|
|
201
|
+
if (!pending)
|
|
202
|
+
break;
|
|
203
|
+
free.busy = true;
|
|
204
|
+
free.currentJobId = pending.job.id;
|
|
205
|
+
this.inflight.set(pending.job.id, pending);
|
|
206
|
+
free.worker.postMessage(pending.job);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
let defaultPool = null;
|
|
211
|
+
export function getDefaultWorkerPool(options) {
|
|
212
|
+
if (!defaultPool) {
|
|
213
|
+
const fromEnv = process.env.ATABEY_WORKER_CONCURRENCY
|
|
214
|
+
? parseInt(process.env.ATABEY_WORKER_CONCURRENCY, 10)
|
|
215
|
+
: undefined;
|
|
216
|
+
defaultPool = new WorkerPool({
|
|
217
|
+
maxConcurrency: options?.maxConcurrency ?? (Number.isFinite(fromEnv) ? fromEnv : undefined),
|
|
218
|
+
...options,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return defaultPool;
|
|
222
|
+
}
|
|
223
|
+
export async function resetDefaultWorkerPool() {
|
|
224
|
+
if (defaultPool) {
|
|
225
|
+
await defaultPool.close();
|
|
226
|
+
defaultPool = null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=worker-pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-pool.js","sourceRoot":"","sources":["../../../../../../shared/src/modules/concurrency/worker-pool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic worker_threads entrypoint for Atabey WorkerPool.
|
|
3
|
+
* Receives serializable jobs and returns serializable results.
|
|
4
|
+
*
|
|
5
|
+
* Supported job types (extensible):
|
|
6
|
+
* - "ping" — health check
|
|
7
|
+
* - "hash" — simple string hash (CPU sample)
|
|
8
|
+
* - "tokenize" — tokenization for TF-IDF style work
|
|
9
|
+
* - "sleep" — test helper
|
|
10
|
+
*/
|
|
11
|
+
export interface WorkerJob {
|
|
12
|
+
id: string;
|
|
13
|
+
type: string;
|
|
14
|
+
payload?: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface WorkerResult {
|
|
17
|
+
id: string;
|
|
18
|
+
ok: boolean;
|
|
19
|
+
result?: unknown;
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic worker_threads entrypoint for Atabey WorkerPool.
|
|
3
|
+
* Receives serializable jobs and returns serializable results.
|
|
4
|
+
*
|
|
5
|
+
* Supported job types (extensible):
|
|
6
|
+
* - "ping" — health check
|
|
7
|
+
* - "hash" — simple string hash (CPU sample)
|
|
8
|
+
* - "tokenize" — tokenization for TF-IDF style work
|
|
9
|
+
* - "sleep" — test helper
|
|
10
|
+
*/
|
|
11
|
+
import { parentPort } from "worker_threads";
|
|
12
|
+
function tokenize(text) {
|
|
13
|
+
return text
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.replace(/[^\w\s-]/g, " ")
|
|
16
|
+
.split(/\s+/)
|
|
17
|
+
.filter((t) => t.length > 1);
|
|
18
|
+
}
|
|
19
|
+
function simpleHash(input) {
|
|
20
|
+
let h = 0;
|
|
21
|
+
for (let i = 0; i < input.length; i++) {
|
|
22
|
+
h = (Math.imul(31, h) + input.charCodeAt(i)) | 0;
|
|
23
|
+
}
|
|
24
|
+
return h >>> 0;
|
|
25
|
+
}
|
|
26
|
+
async function handleJob(job) {
|
|
27
|
+
switch (job.type) {
|
|
28
|
+
case "ping":
|
|
29
|
+
return { pong: true, pid: process.pid, ts: Date.now() };
|
|
30
|
+
case "hash": {
|
|
31
|
+
const text = String(job.payload?.text ?? "");
|
|
32
|
+
return { hash: simpleHash(text), length: text.length };
|
|
33
|
+
}
|
|
34
|
+
case "tokenize": {
|
|
35
|
+
const text = String(job.payload?.text ?? "");
|
|
36
|
+
const tokens = tokenize(text);
|
|
37
|
+
return { tokens, count: tokens.length };
|
|
38
|
+
}
|
|
39
|
+
case "sleep": {
|
|
40
|
+
const ms = Math.min(10_000, Math.max(0, Number(job.payload?.ms ?? 0)));
|
|
41
|
+
await new Promise((r) => setTimeout(r, ms));
|
|
42
|
+
return { slept: ms };
|
|
43
|
+
}
|
|
44
|
+
default:
|
|
45
|
+
throw new Error(`Unknown worker job type: ${job.type}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (parentPort) {
|
|
49
|
+
parentPort.on("message", (job) => {
|
|
50
|
+
void (async () => {
|
|
51
|
+
try {
|
|
52
|
+
const result = await handleJob(job);
|
|
53
|
+
const msg = { id: job.id, ok: true, result };
|
|
54
|
+
parentPort.postMessage(msg);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
const msg = {
|
|
58
|
+
id: job.id,
|
|
59
|
+
ok: false,
|
|
60
|
+
error: err instanceof Error ? err.message : String(err),
|
|
61
|
+
};
|
|
62
|
+
parentPort.postMessage(msg);
|
|
63
|
+
}
|
|
64
|
+
})();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=worker-thread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-thread.js","sourceRoot":"","sources":["../../../../../../shared/src/modules/concurrency/worker-thread.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./storage/index.js";
|
|
2
|
+
export * from "./security/index.js";
|
|
3
|
+
export * from "./concurrency/index.js";
|
|
4
|
+
export * from "./sandbox/index.js";
|
|
5
|
+
export * from "./observability/index.js";
|
|
6
|
+
export * from "./agent/index.js";
|
|
7
|
+
export * from "./primitives/index.js";
|
|
8
|
+
export * as Storage from "./storage/index.js";
|
|
9
|
+
export * as Security from "./security/index.js";
|
|
10
|
+
export * as Concurrency from "./concurrency/index.js";
|
|
11
|
+
export * as Sandbox from "./sandbox/index.js";
|
|
12
|
+
export * as Observability from "./observability/index.js";
|
|
13
|
+
export * as Agent from "./agent/index.js";
|
|
14
|
+
export * as Primitives from "./primitives/index.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./storage/index.js";
|
|
2
|
+
export * from "./security/index.js";
|
|
3
|
+
export * from "./concurrency/index.js";
|
|
4
|
+
export * from "./sandbox/index.js";
|
|
5
|
+
export * from "./observability/index.js";
|
|
6
|
+
export * from "./agent/index.js";
|
|
7
|
+
export * from "./primitives/index.js";
|
|
8
|
+
export * as Storage from "./storage/index.js";
|
|
9
|
+
export * as Security from "./security/index.js";
|
|
10
|
+
export * as Concurrency from "./concurrency/index.js";
|
|
11
|
+
export * as Sandbox from "./sandbox/index.js";
|
|
12
|
+
export * as Observability from "./observability/index.js";
|
|
13
|
+
export * as Agent from "./agent/index.js";
|
|
14
|
+
export * as Primitives from "./primitives/index.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../shared/src/modules/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AAEtC,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,WAAW,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,aAAa,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAC1C,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC"}
|