elsium-ai 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -0
- package/dist/index.js +559 -26
- package/package.json +3 -4
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://github.com/elsium-ai/elsium-ai" target="blank"><img src="https://raw.githubusercontent.com/elsium-ai/elsium-ai/main/assets/logo.png" width="320" alt="ElsiumAI Logo" /></a>
|
|
3
|
+
</p>
|
|
4
|
+
<h3 align="center">Reliability. Governance. Reproducible AI.</h3>
|
|
5
|
+
<p align="center">The TypeScript framework for AI systems you can trust in production.</p>
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://github.com/elsium-ai/elsium-ai/actions"><img src="https://github.com/elsium-ai/elsium-ai/workflows/CI/badge.svg" alt="CI"></a>
|
|
8
|
+
<a href="https://github.com/elsium-ai/elsium-ai/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/elsium-ai"><img src="https://img.shields.io/npm/v/elsium-ai.svg" alt="npm"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
> **AI systems must fail predictably.**
|
|
15
|
+
> **AI systems must be auditable.**
|
|
16
|
+
> **AI systems must be reproducible.**
|
|
17
|
+
> **AI systems must be governed by policy, not hope.**
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install elsium-ai
|
|
25
|
+
# or
|
|
26
|
+
bun add elsium-ai
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This umbrella package re-exports all ElsiumAI modules. You can also install individual packages for smaller bundles.
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { gateway } from 'elsium-ai'
|
|
35
|
+
import { defineAgent } from 'elsium-ai'
|
|
36
|
+
import { env } from 'elsium-ai'
|
|
37
|
+
|
|
38
|
+
const llm = gateway({
|
|
39
|
+
provider: 'anthropic',
|
|
40
|
+
model: 'claude-sonnet-4-6',
|
|
41
|
+
apiKey: env('ANTHROPIC_API_KEY'),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const agent = defineAgent(
|
|
45
|
+
{ name: 'assistant', system: 'You are a helpful assistant.' },
|
|
46
|
+
{ complete: (req) => llm.complete(req) },
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
const result = await agent.run('What is TypeScript?')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Three Pillars
|
|
53
|
+
|
|
54
|
+
| Pillar | The guarantee |
|
|
55
|
+
|--------|--------------|
|
|
56
|
+
| **Reliability** | Your system stays up when providers break — circuit breakers, bulkhead isolation, request dedup, graceful shutdown |
|
|
57
|
+
| **Governance** | You control who does what, and you can prove it — policy engine, RBAC, approval gates, hash-chained audit trail |
|
|
58
|
+
| **Reproducible AI** | Tools to measure, pin, and reproduce AI outputs — seed propagation, output pinning, provenance tracking, determinism assertions |
|
|
59
|
+
|
|
60
|
+
## Packages
|
|
61
|
+
|
|
62
|
+
| Package | Description |
|
|
63
|
+
|---------|-------------|
|
|
64
|
+
| [`@elsium-ai/core`](https://www.npmjs.com/package/@elsium-ai/core) | Types, errors, streaming, circuit breaker, dedup, policy engine, shutdown |
|
|
65
|
+
| [`@elsium-ai/gateway`](https://www.npmjs.com/package/@elsium-ai/gateway) | Multi-provider gateway, X-Ray, provider mesh, bulkhead, PII detection |
|
|
66
|
+
| [`@elsium-ai/agents`](https://www.npmjs.com/package/@elsium-ai/agents) | Agents, memory, guardrails, approval gates, multi-agent |
|
|
67
|
+
| [`@elsium-ai/tools`](https://www.npmjs.com/package/@elsium-ai/tools) | Tool definitions with Zod validation |
|
|
68
|
+
| [`@elsium-ai/rag`](https://www.npmjs.com/package/@elsium-ai/rag) | Document loading, chunking, embeddings, vector search |
|
|
69
|
+
| [`@elsium-ai/workflows`](https://www.npmjs.com/package/@elsium-ai/workflows) | Sequential, parallel, and branching workflows |
|
|
70
|
+
| [`@elsium-ai/observe`](https://www.npmjs.com/package/@elsium-ai/observe) | Tracing, cost intelligence, audit trail, provenance tracking |
|
|
71
|
+
| [`@elsium-ai/mcp`](https://www.npmjs.com/package/@elsium-ai/mcp) | Bidirectional MCP client and server |
|
|
72
|
+
| [`@elsium-ai/app`](https://www.npmjs.com/package/@elsium-ai/app) | HTTP server, CORS, auth, rate limiting, RBAC |
|
|
73
|
+
| [`@elsium-ai/testing`](https://www.npmjs.com/package/@elsium-ai/testing) | Mocks, evals, pinning, determinism assertions, prompt versioning |
|
|
74
|
+
| [`@elsium-ai/cli`](https://www.npmjs.com/package/@elsium-ai/cli) | Scaffolding, dev server, X-Ray inspection |
|
|
75
|
+
|
|
76
|
+
## Performance
|
|
77
|
+
|
|
78
|
+
Measured with zero-latency mock provider to isolate framework cost.
|
|
79
|
+
|
|
80
|
+
| Metric | P50 | P95 | Conditions |
|
|
81
|
+
|---|:---:|:---:|---|
|
|
82
|
+
| Core completion path | 2.3us | 5.5us | Agent, no middleware |
|
|
83
|
+
| Full governance stack | 6.2us | 9.5us | Security + audit + policy + cost + xray + logging |
|
|
84
|
+
| Under concurrency | 5.0us | 6.4us | 100 parallel requests, full stack |
|
|
85
|
+
|
|
86
|
+
Framework cost contribution: <0.01% of total request time.
|
|
87
|
+
|
|
88
|
+
## Documentation
|
|
89
|
+
|
|
90
|
+
Full documentation, architecture diagrams, and examples at [github.com/elsium-ai/elsium-ai](https://github.com/elsium-ai/elsium-ai).
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
[MIT](https://github.com/elsium-ai/elsium-ai/blob/main/LICENSE) - Copyright (c) 2026 Eric Utrera
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @bun
|
|
2
1
|
var __defProp = Object.defineProperty;
|
|
3
2
|
var __returnValue = (v) => v;
|
|
4
3
|
function __exportSetter(name, newValue) {
|
|
@@ -139,7 +138,7 @@ function tryCatchSync(fn) {
|
|
|
139
138
|
}
|
|
140
139
|
}
|
|
141
140
|
// ../core/src/utils.ts
|
|
142
|
-
import { randomBytes } from "crypto";
|
|
141
|
+
import { randomBytes } from "node:crypto";
|
|
143
142
|
function cryptoHex(bytes) {
|
|
144
143
|
return randomBytes(bytes).toString("hex");
|
|
145
144
|
}
|
|
@@ -843,7 +842,7 @@ function resolveModelName(model) {
|
|
|
843
842
|
function calculateCost(model, usage) {
|
|
844
843
|
const pricing = PRICING[resolveModelName(model)];
|
|
845
844
|
if (!pricing) {
|
|
846
|
-
log.warn(`Unknown model "${model}"
|
|
845
|
+
log.warn(`Unknown model "${model}" — cost will be reported as $0. Register pricing with registerPricing().`);
|
|
847
846
|
return {
|
|
848
847
|
inputCost: 0,
|
|
849
848
|
outputCost: 0,
|
|
@@ -2375,7 +2374,7 @@ function createProviderMesh(config) {
|
|
|
2375
2374
|
retryable: false
|
|
2376
2375
|
});
|
|
2377
2376
|
}
|
|
2378
|
-
const sortedProviders = [...config.providers]
|
|
2377
|
+
const sortedProviders = [...config.providers];
|
|
2379
2378
|
const gateways = new Map;
|
|
2380
2379
|
const circuitBreakers = new Map;
|
|
2381
2380
|
for (const entry of sortedProviders) {
|
|
@@ -7173,7 +7172,7 @@ function computeHallucinationRisk(input, output) {
|
|
|
7173
7172
|
const risk = 1 - Math.min(overlapRatio * 2, 1);
|
|
7174
7173
|
return {
|
|
7175
7174
|
score: risk,
|
|
7176
|
-
reason: risk > 0.5 ? "Output has low overlap with input
|
|
7175
|
+
reason: risk > 0.5 ? "Output has low overlap with input — potential hallucination" : "Output appears grounded in input context"
|
|
7177
7176
|
};
|
|
7178
7177
|
}
|
|
7179
7178
|
function computeRelevance(input, output) {
|
|
@@ -7447,7 +7446,7 @@ Only respond with JSON, nothing else.`
|
|
|
7447
7446
|
return {
|
|
7448
7447
|
passed: score >= threshold,
|
|
7449
7448
|
score,
|
|
7450
|
-
reason: score >= threshold ? "Output appears grounded in context (heuristic)" : `Only ${(score * 100).toFixed(0)}% of claims supported by context (heuristic
|
|
7449
|
+
reason: score >= threshold ? "Output appears grounded in context (heuristic)" : `Only ${(score * 100).toFixed(0)}% of claims supported by context (heuristic — provide llmComplete for production-grade checks)`
|
|
7451
7450
|
};
|
|
7452
7451
|
}
|
|
7453
7452
|
async function checkHallucination(output, context) {
|
|
@@ -7504,7 +7503,7 @@ Only respond with JSON, nothing else.`
|
|
|
7504
7503
|
return {
|
|
7505
7504
|
passed: score >= threshold,
|
|
7506
7505
|
score,
|
|
7507
|
-
reason: score >= threshold ? "Output is relevant to input (heuristic)" : "Output may not be relevant to the input (heuristic
|
|
7506
|
+
reason: score >= threshold ? "Output is relevant to input (heuristic)" : "Output may not be relevant to the input (heuristic — provide llmComplete for production-grade checks)"
|
|
7508
7507
|
};
|
|
7509
7508
|
}
|
|
7510
7509
|
async function checkRelevance(input, output) {
|
|
@@ -7560,7 +7559,7 @@ Only respond with JSON, nothing else.`
|
|
|
7560
7559
|
return {
|
|
7561
7560
|
passed: score >= 0.7,
|
|
7562
7561
|
score,
|
|
7563
|
-
reason: score >= 0.7 ? "Output appears grounded in sources (heuristic)" : "Output contains claims not found in sources (heuristic
|
|
7562
|
+
reason: score >= 0.7 ? "Output appears grounded in sources (heuristic)" : "Output contains claims not found in sources (heuristic — provide llmComplete for production-grade checks)"
|
|
7564
7563
|
};
|
|
7565
7564
|
}
|
|
7566
7565
|
async function checkGrounding(output, sources) {
|
|
@@ -7641,7 +7640,7 @@ function evaluateTransition(currentState, currentStateName, result, stateConfig,
|
|
|
7641
7640
|
});
|
|
7642
7641
|
conversationMessages.push({
|
|
7643
7642
|
role: "user",
|
|
7644
|
-
content: `[State transition: ${currentStateName}
|
|
7643
|
+
content: `[State transition: ${currentStateName} → ${nextStateName}] Continue based on the previous response.`
|
|
7645
7644
|
});
|
|
7646
7645
|
return { nextStateName, nextState };
|
|
7647
7646
|
}
|
|
@@ -9621,6 +9620,540 @@ function createOTLPExporter(config) {
|
|
|
9621
9620
|
}
|
|
9622
9621
|
};
|
|
9623
9622
|
}
|
|
9623
|
+
// ../../node_modules/.bun/@hono+node-server@1.19.9/node_modules/@hono/node-server/dist/index.mjs
|
|
9624
|
+
import { createServer as createServerHTTP } from "http";
|
|
9625
|
+
import { Http2ServerRequest as Http2ServerRequest2 } from "http2";
|
|
9626
|
+
import { Http2ServerRequest } from "http2";
|
|
9627
|
+
import { Readable } from "stream";
|
|
9628
|
+
import crypto from "crypto";
|
|
9629
|
+
var RequestError = class extends Error {
|
|
9630
|
+
constructor(message, options) {
|
|
9631
|
+
super(message, options);
|
|
9632
|
+
this.name = "RequestError";
|
|
9633
|
+
}
|
|
9634
|
+
};
|
|
9635
|
+
var toRequestError = (e) => {
|
|
9636
|
+
if (e instanceof RequestError) {
|
|
9637
|
+
return e;
|
|
9638
|
+
}
|
|
9639
|
+
return new RequestError(e.message, { cause: e });
|
|
9640
|
+
};
|
|
9641
|
+
var GlobalRequest = global.Request;
|
|
9642
|
+
var Request2 = class extends GlobalRequest {
|
|
9643
|
+
constructor(input, options) {
|
|
9644
|
+
if (typeof input === "object" && getRequestCache in input) {
|
|
9645
|
+
input = input[getRequestCache]();
|
|
9646
|
+
}
|
|
9647
|
+
if (typeof options?.body?.getReader !== "undefined") {
|
|
9648
|
+
options.duplex ??= "half";
|
|
9649
|
+
}
|
|
9650
|
+
super(input, options);
|
|
9651
|
+
}
|
|
9652
|
+
};
|
|
9653
|
+
var newHeadersFromIncoming = (incoming) => {
|
|
9654
|
+
const headerRecord = [];
|
|
9655
|
+
const rawHeaders = incoming.rawHeaders;
|
|
9656
|
+
for (let i = 0;i < rawHeaders.length; i += 2) {
|
|
9657
|
+
const { [i]: key, [i + 1]: value } = rawHeaders;
|
|
9658
|
+
if (key.charCodeAt(0) !== 58) {
|
|
9659
|
+
headerRecord.push([key, value]);
|
|
9660
|
+
}
|
|
9661
|
+
}
|
|
9662
|
+
return new Headers(headerRecord);
|
|
9663
|
+
};
|
|
9664
|
+
var wrapBodyStream = Symbol("wrapBodyStream");
|
|
9665
|
+
var newRequestFromIncoming = (method, url, headers, incoming, abortController) => {
|
|
9666
|
+
const init = {
|
|
9667
|
+
method,
|
|
9668
|
+
headers,
|
|
9669
|
+
signal: abortController.signal
|
|
9670
|
+
};
|
|
9671
|
+
if (method === "TRACE") {
|
|
9672
|
+
init.method = "GET";
|
|
9673
|
+
const req = new Request2(url, init);
|
|
9674
|
+
Object.defineProperty(req, "method", {
|
|
9675
|
+
get() {
|
|
9676
|
+
return "TRACE";
|
|
9677
|
+
}
|
|
9678
|
+
});
|
|
9679
|
+
return req;
|
|
9680
|
+
}
|
|
9681
|
+
if (!(method === "GET" || method === "HEAD")) {
|
|
9682
|
+
if ("rawBody" in incoming && incoming.rawBody instanceof Buffer) {
|
|
9683
|
+
init.body = new ReadableStream({
|
|
9684
|
+
start(controller) {
|
|
9685
|
+
controller.enqueue(incoming.rawBody);
|
|
9686
|
+
controller.close();
|
|
9687
|
+
}
|
|
9688
|
+
});
|
|
9689
|
+
} else if (incoming[wrapBodyStream]) {
|
|
9690
|
+
let reader;
|
|
9691
|
+
init.body = new ReadableStream({
|
|
9692
|
+
async pull(controller) {
|
|
9693
|
+
try {
|
|
9694
|
+
reader ||= Readable.toWeb(incoming).getReader();
|
|
9695
|
+
const { done, value } = await reader.read();
|
|
9696
|
+
if (done) {
|
|
9697
|
+
controller.close();
|
|
9698
|
+
} else {
|
|
9699
|
+
controller.enqueue(value);
|
|
9700
|
+
}
|
|
9701
|
+
} catch (error) {
|
|
9702
|
+
controller.error(error);
|
|
9703
|
+
}
|
|
9704
|
+
}
|
|
9705
|
+
});
|
|
9706
|
+
} else {
|
|
9707
|
+
init.body = Readable.toWeb(incoming);
|
|
9708
|
+
}
|
|
9709
|
+
}
|
|
9710
|
+
return new Request2(url, init);
|
|
9711
|
+
};
|
|
9712
|
+
var getRequestCache = Symbol("getRequestCache");
|
|
9713
|
+
var requestCache = Symbol("requestCache");
|
|
9714
|
+
var incomingKey = Symbol("incomingKey");
|
|
9715
|
+
var urlKey = Symbol("urlKey");
|
|
9716
|
+
var headersKey = Symbol("headersKey");
|
|
9717
|
+
var abortControllerKey = Symbol("abortControllerKey");
|
|
9718
|
+
var getAbortController = Symbol("getAbortController");
|
|
9719
|
+
var requestPrototype = {
|
|
9720
|
+
get method() {
|
|
9721
|
+
return this[incomingKey].method || "GET";
|
|
9722
|
+
},
|
|
9723
|
+
get url() {
|
|
9724
|
+
return this[urlKey];
|
|
9725
|
+
},
|
|
9726
|
+
get headers() {
|
|
9727
|
+
return this[headersKey] ||= newHeadersFromIncoming(this[incomingKey]);
|
|
9728
|
+
},
|
|
9729
|
+
[getAbortController]() {
|
|
9730
|
+
this[getRequestCache]();
|
|
9731
|
+
return this[abortControllerKey];
|
|
9732
|
+
},
|
|
9733
|
+
[getRequestCache]() {
|
|
9734
|
+
this[abortControllerKey] ||= new AbortController;
|
|
9735
|
+
return this[requestCache] ||= newRequestFromIncoming(this.method, this[urlKey], this.headers, this[incomingKey], this[abortControllerKey]);
|
|
9736
|
+
}
|
|
9737
|
+
};
|
|
9738
|
+
[
|
|
9739
|
+
"body",
|
|
9740
|
+
"bodyUsed",
|
|
9741
|
+
"cache",
|
|
9742
|
+
"credentials",
|
|
9743
|
+
"destination",
|
|
9744
|
+
"integrity",
|
|
9745
|
+
"mode",
|
|
9746
|
+
"redirect",
|
|
9747
|
+
"referrer",
|
|
9748
|
+
"referrerPolicy",
|
|
9749
|
+
"signal",
|
|
9750
|
+
"keepalive"
|
|
9751
|
+
].forEach((k) => {
|
|
9752
|
+
Object.defineProperty(requestPrototype, k, {
|
|
9753
|
+
get() {
|
|
9754
|
+
return this[getRequestCache]()[k];
|
|
9755
|
+
}
|
|
9756
|
+
});
|
|
9757
|
+
});
|
|
9758
|
+
["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
|
|
9759
|
+
Object.defineProperty(requestPrototype, k, {
|
|
9760
|
+
value: function() {
|
|
9761
|
+
return this[getRequestCache]()[k]();
|
|
9762
|
+
}
|
|
9763
|
+
});
|
|
9764
|
+
});
|
|
9765
|
+
Object.setPrototypeOf(requestPrototype, Request2.prototype);
|
|
9766
|
+
var newRequest = (incoming, defaultHostname) => {
|
|
9767
|
+
const req = Object.create(requestPrototype);
|
|
9768
|
+
req[incomingKey] = incoming;
|
|
9769
|
+
const incomingUrl = incoming.url || "";
|
|
9770
|
+
if (incomingUrl[0] !== "/" && (incomingUrl.startsWith("http://") || incomingUrl.startsWith("https://"))) {
|
|
9771
|
+
if (incoming instanceof Http2ServerRequest) {
|
|
9772
|
+
throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
|
|
9773
|
+
}
|
|
9774
|
+
try {
|
|
9775
|
+
const url2 = new URL(incomingUrl);
|
|
9776
|
+
req[urlKey] = url2.href;
|
|
9777
|
+
} catch (e) {
|
|
9778
|
+
throw new RequestError("Invalid absolute URL", { cause: e });
|
|
9779
|
+
}
|
|
9780
|
+
return req;
|
|
9781
|
+
}
|
|
9782
|
+
const host = (incoming instanceof Http2ServerRequest ? incoming.authority : incoming.headers.host) || defaultHostname;
|
|
9783
|
+
if (!host) {
|
|
9784
|
+
throw new RequestError("Missing host header");
|
|
9785
|
+
}
|
|
9786
|
+
let scheme;
|
|
9787
|
+
if (incoming instanceof Http2ServerRequest) {
|
|
9788
|
+
scheme = incoming.scheme;
|
|
9789
|
+
if (!(scheme === "http" || scheme === "https")) {
|
|
9790
|
+
throw new RequestError("Unsupported scheme");
|
|
9791
|
+
}
|
|
9792
|
+
} else {
|
|
9793
|
+
scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
|
|
9794
|
+
}
|
|
9795
|
+
const url = new URL(`${scheme}://${host}${incomingUrl}`);
|
|
9796
|
+
if (url.hostname.length !== host.length && url.hostname !== host.replace(/:\d+$/, "")) {
|
|
9797
|
+
throw new RequestError("Invalid host header");
|
|
9798
|
+
}
|
|
9799
|
+
req[urlKey] = url.href;
|
|
9800
|
+
return req;
|
|
9801
|
+
};
|
|
9802
|
+
var responseCache = Symbol("responseCache");
|
|
9803
|
+
var getResponseCache = Symbol("getResponseCache");
|
|
9804
|
+
var cacheKey = Symbol("cache");
|
|
9805
|
+
var GlobalResponse = global.Response;
|
|
9806
|
+
var Response2 = class _Response {
|
|
9807
|
+
#body;
|
|
9808
|
+
#init;
|
|
9809
|
+
[getResponseCache]() {
|
|
9810
|
+
delete this[cacheKey];
|
|
9811
|
+
return this[responseCache] ||= new GlobalResponse(this.#body, this.#init);
|
|
9812
|
+
}
|
|
9813
|
+
constructor(body, init) {
|
|
9814
|
+
let headers;
|
|
9815
|
+
this.#body = body;
|
|
9816
|
+
if (init instanceof _Response) {
|
|
9817
|
+
const cachedGlobalResponse = init[responseCache];
|
|
9818
|
+
if (cachedGlobalResponse) {
|
|
9819
|
+
this.#init = cachedGlobalResponse;
|
|
9820
|
+
this[getResponseCache]();
|
|
9821
|
+
return;
|
|
9822
|
+
} else {
|
|
9823
|
+
this.#init = init.#init;
|
|
9824
|
+
headers = new Headers(init.#init.headers);
|
|
9825
|
+
}
|
|
9826
|
+
} else {
|
|
9827
|
+
this.#init = init;
|
|
9828
|
+
}
|
|
9829
|
+
if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) {
|
|
9830
|
+
headers ||= init?.headers || { "content-type": "text/plain; charset=UTF-8" };
|
|
9831
|
+
this[cacheKey] = [init?.status || 200, body, headers];
|
|
9832
|
+
}
|
|
9833
|
+
}
|
|
9834
|
+
get headers() {
|
|
9835
|
+
const cache = this[cacheKey];
|
|
9836
|
+
if (cache) {
|
|
9837
|
+
if (!(cache[2] instanceof Headers)) {
|
|
9838
|
+
cache[2] = new Headers(cache[2]);
|
|
9839
|
+
}
|
|
9840
|
+
return cache[2];
|
|
9841
|
+
}
|
|
9842
|
+
return this[getResponseCache]().headers;
|
|
9843
|
+
}
|
|
9844
|
+
get status() {
|
|
9845
|
+
return this[cacheKey]?.[0] ?? this[getResponseCache]().status;
|
|
9846
|
+
}
|
|
9847
|
+
get ok() {
|
|
9848
|
+
const status = this.status;
|
|
9849
|
+
return status >= 200 && status < 300;
|
|
9850
|
+
}
|
|
9851
|
+
};
|
|
9852
|
+
["body", "bodyUsed", "redirected", "statusText", "trailers", "type", "url"].forEach((k) => {
|
|
9853
|
+
Object.defineProperty(Response2.prototype, k, {
|
|
9854
|
+
get() {
|
|
9855
|
+
return this[getResponseCache]()[k];
|
|
9856
|
+
}
|
|
9857
|
+
});
|
|
9858
|
+
});
|
|
9859
|
+
["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => {
|
|
9860
|
+
Object.defineProperty(Response2.prototype, k, {
|
|
9861
|
+
value: function() {
|
|
9862
|
+
return this[getResponseCache]()[k]();
|
|
9863
|
+
}
|
|
9864
|
+
});
|
|
9865
|
+
});
|
|
9866
|
+
Object.setPrototypeOf(Response2, GlobalResponse);
|
|
9867
|
+
Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
|
|
9868
|
+
async function readWithoutBlocking(readPromise) {
|
|
9869
|
+
return Promise.race([readPromise, Promise.resolve().then(() => Promise.resolve(undefined))]);
|
|
9870
|
+
}
|
|
9871
|
+
function writeFromReadableStreamDefaultReader(reader, writable, currentReadPromise) {
|
|
9872
|
+
const cancel = (error) => {
|
|
9873
|
+
reader.cancel(error).catch(() => {});
|
|
9874
|
+
};
|
|
9875
|
+
writable.on("close", cancel);
|
|
9876
|
+
writable.on("error", cancel);
|
|
9877
|
+
(currentReadPromise ?? reader.read()).then(flow, handleStreamError);
|
|
9878
|
+
return reader.closed.finally(() => {
|
|
9879
|
+
writable.off("close", cancel);
|
|
9880
|
+
writable.off("error", cancel);
|
|
9881
|
+
});
|
|
9882
|
+
function handleStreamError(error) {
|
|
9883
|
+
if (error) {
|
|
9884
|
+
writable.destroy(error);
|
|
9885
|
+
}
|
|
9886
|
+
}
|
|
9887
|
+
function onDrain() {
|
|
9888
|
+
reader.read().then(flow, handleStreamError);
|
|
9889
|
+
}
|
|
9890
|
+
function flow({ done, value }) {
|
|
9891
|
+
try {
|
|
9892
|
+
if (done) {
|
|
9893
|
+
writable.end();
|
|
9894
|
+
} else if (!writable.write(value)) {
|
|
9895
|
+
writable.once("drain", onDrain);
|
|
9896
|
+
} else {
|
|
9897
|
+
return reader.read().then(flow, handleStreamError);
|
|
9898
|
+
}
|
|
9899
|
+
} catch (e) {
|
|
9900
|
+
handleStreamError(e);
|
|
9901
|
+
}
|
|
9902
|
+
}
|
|
9903
|
+
}
|
|
9904
|
+
function writeFromReadableStream(stream, writable) {
|
|
9905
|
+
if (stream.locked) {
|
|
9906
|
+
throw new TypeError("ReadableStream is locked.");
|
|
9907
|
+
} else if (writable.destroyed) {
|
|
9908
|
+
return;
|
|
9909
|
+
}
|
|
9910
|
+
return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
|
|
9911
|
+
}
|
|
9912
|
+
var buildOutgoingHttpHeaders = (headers) => {
|
|
9913
|
+
const res = {};
|
|
9914
|
+
if (!(headers instanceof Headers)) {
|
|
9915
|
+
headers = new Headers(headers ?? undefined);
|
|
9916
|
+
}
|
|
9917
|
+
const cookies = [];
|
|
9918
|
+
for (const [k, v] of headers) {
|
|
9919
|
+
if (k === "set-cookie") {
|
|
9920
|
+
cookies.push(v);
|
|
9921
|
+
} else {
|
|
9922
|
+
res[k] = v;
|
|
9923
|
+
}
|
|
9924
|
+
}
|
|
9925
|
+
if (cookies.length > 0) {
|
|
9926
|
+
res["set-cookie"] = cookies;
|
|
9927
|
+
}
|
|
9928
|
+
res["content-type"] ??= "text/plain; charset=UTF-8";
|
|
9929
|
+
return res;
|
|
9930
|
+
};
|
|
9931
|
+
var X_ALREADY_SENT = "x-hono-already-sent";
|
|
9932
|
+
if (typeof global.crypto === "undefined") {
|
|
9933
|
+
global.crypto = crypto;
|
|
9934
|
+
}
|
|
9935
|
+
var outgoingEnded = Symbol("outgoingEnded");
|
|
9936
|
+
var handleRequestError = () => new Response(null, {
|
|
9937
|
+
status: 400
|
|
9938
|
+
});
|
|
9939
|
+
var handleFetchError = (e) => new Response(null, {
|
|
9940
|
+
status: e instanceof Error && (e.name === "TimeoutError" || e.constructor.name === "TimeoutError") ? 504 : 500
|
|
9941
|
+
});
|
|
9942
|
+
var handleResponseError = (e, outgoing) => {
|
|
9943
|
+
const err2 = e instanceof Error ? e : new Error("unknown error", { cause: e });
|
|
9944
|
+
if (err2.code === "ERR_STREAM_PREMATURE_CLOSE") {
|
|
9945
|
+
console.info("The user aborted a request.");
|
|
9946
|
+
} else {
|
|
9947
|
+
console.error(e);
|
|
9948
|
+
if (!outgoing.headersSent) {
|
|
9949
|
+
outgoing.writeHead(500, { "Content-Type": "text/plain" });
|
|
9950
|
+
}
|
|
9951
|
+
outgoing.end(`Error: ${err2.message}`);
|
|
9952
|
+
outgoing.destroy(err2);
|
|
9953
|
+
}
|
|
9954
|
+
};
|
|
9955
|
+
var flushHeaders = (outgoing) => {
|
|
9956
|
+
if ("flushHeaders" in outgoing && outgoing.writable) {
|
|
9957
|
+
outgoing.flushHeaders();
|
|
9958
|
+
}
|
|
9959
|
+
};
|
|
9960
|
+
var responseViaCache = async (res, outgoing) => {
|
|
9961
|
+
let [status, body, header] = res[cacheKey];
|
|
9962
|
+
if (header instanceof Headers) {
|
|
9963
|
+
header = buildOutgoingHttpHeaders(header);
|
|
9964
|
+
}
|
|
9965
|
+
if (typeof body === "string") {
|
|
9966
|
+
header["Content-Length"] = Buffer.byteLength(body);
|
|
9967
|
+
} else if (body instanceof Uint8Array) {
|
|
9968
|
+
header["Content-Length"] = body.byteLength;
|
|
9969
|
+
} else if (body instanceof Blob) {
|
|
9970
|
+
header["Content-Length"] = body.size;
|
|
9971
|
+
}
|
|
9972
|
+
outgoing.writeHead(status, header);
|
|
9973
|
+
if (typeof body === "string" || body instanceof Uint8Array) {
|
|
9974
|
+
outgoing.end(body);
|
|
9975
|
+
} else if (body instanceof Blob) {
|
|
9976
|
+
outgoing.end(new Uint8Array(await body.arrayBuffer()));
|
|
9977
|
+
} else {
|
|
9978
|
+
flushHeaders(outgoing);
|
|
9979
|
+
await writeFromReadableStream(body, outgoing)?.catch((e) => handleResponseError(e, outgoing));
|
|
9980
|
+
}
|
|
9981
|
+
outgoing[outgoingEnded]?.();
|
|
9982
|
+
};
|
|
9983
|
+
var isPromise = (res) => typeof res.then === "function";
|
|
9984
|
+
var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
9985
|
+
if (isPromise(res)) {
|
|
9986
|
+
if (options.errorHandler) {
|
|
9987
|
+
try {
|
|
9988
|
+
res = await res;
|
|
9989
|
+
} catch (err2) {
|
|
9990
|
+
const errRes = await options.errorHandler(err2);
|
|
9991
|
+
if (!errRes) {
|
|
9992
|
+
return;
|
|
9993
|
+
}
|
|
9994
|
+
res = errRes;
|
|
9995
|
+
}
|
|
9996
|
+
} else {
|
|
9997
|
+
res = await res.catch(handleFetchError);
|
|
9998
|
+
}
|
|
9999
|
+
}
|
|
10000
|
+
if (cacheKey in res) {
|
|
10001
|
+
return responseViaCache(res, outgoing);
|
|
10002
|
+
}
|
|
10003
|
+
const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
|
|
10004
|
+
if (res.body) {
|
|
10005
|
+
const reader = res.body.getReader();
|
|
10006
|
+
const values = [];
|
|
10007
|
+
let done = false;
|
|
10008
|
+
let currentReadPromise = undefined;
|
|
10009
|
+
if (resHeaderRecord["transfer-encoding"] !== "chunked") {
|
|
10010
|
+
let maxReadCount = 2;
|
|
10011
|
+
for (let i = 0;i < maxReadCount; i++) {
|
|
10012
|
+
currentReadPromise ||= reader.read();
|
|
10013
|
+
const chunk = await readWithoutBlocking(currentReadPromise).catch((e) => {
|
|
10014
|
+
console.error(e);
|
|
10015
|
+
done = true;
|
|
10016
|
+
});
|
|
10017
|
+
if (!chunk) {
|
|
10018
|
+
if (i === 1) {
|
|
10019
|
+
await new Promise((resolve) => setTimeout(resolve));
|
|
10020
|
+
maxReadCount = 3;
|
|
10021
|
+
continue;
|
|
10022
|
+
}
|
|
10023
|
+
break;
|
|
10024
|
+
}
|
|
10025
|
+
currentReadPromise = undefined;
|
|
10026
|
+
if (chunk.value) {
|
|
10027
|
+
values.push(chunk.value);
|
|
10028
|
+
}
|
|
10029
|
+
if (chunk.done) {
|
|
10030
|
+
done = true;
|
|
10031
|
+
break;
|
|
10032
|
+
}
|
|
10033
|
+
}
|
|
10034
|
+
if (done && !("content-length" in resHeaderRecord)) {
|
|
10035
|
+
resHeaderRecord["content-length"] = values.reduce((acc, value) => acc + value.length, 0);
|
|
10036
|
+
}
|
|
10037
|
+
}
|
|
10038
|
+
outgoing.writeHead(res.status, resHeaderRecord);
|
|
10039
|
+
values.forEach((value) => {
|
|
10040
|
+
outgoing.write(value);
|
|
10041
|
+
});
|
|
10042
|
+
if (done) {
|
|
10043
|
+
outgoing.end();
|
|
10044
|
+
} else {
|
|
10045
|
+
if (values.length === 0) {
|
|
10046
|
+
flushHeaders(outgoing);
|
|
10047
|
+
}
|
|
10048
|
+
await writeFromReadableStreamDefaultReader(reader, outgoing, currentReadPromise);
|
|
10049
|
+
}
|
|
10050
|
+
} else if (resHeaderRecord[X_ALREADY_SENT]) {} else {
|
|
10051
|
+
outgoing.writeHead(res.status, resHeaderRecord);
|
|
10052
|
+
outgoing.end();
|
|
10053
|
+
}
|
|
10054
|
+
outgoing[outgoingEnded]?.();
|
|
10055
|
+
};
|
|
10056
|
+
var getRequestListener = (fetchCallback, options = {}) => {
|
|
10057
|
+
const autoCleanupIncoming = options.autoCleanupIncoming ?? true;
|
|
10058
|
+
if (options.overrideGlobalObjects !== false && global.Request !== Request2) {
|
|
10059
|
+
Object.defineProperty(global, "Request", {
|
|
10060
|
+
value: Request2
|
|
10061
|
+
});
|
|
10062
|
+
Object.defineProperty(global, "Response", {
|
|
10063
|
+
value: Response2
|
|
10064
|
+
});
|
|
10065
|
+
}
|
|
10066
|
+
return async (incoming, outgoing) => {
|
|
10067
|
+
let res, req;
|
|
10068
|
+
try {
|
|
10069
|
+
req = newRequest(incoming, options.hostname);
|
|
10070
|
+
let incomingEnded = !autoCleanupIncoming || incoming.method === "GET" || incoming.method === "HEAD";
|
|
10071
|
+
if (!incomingEnded) {
|
|
10072
|
+
incoming[wrapBodyStream] = true;
|
|
10073
|
+
incoming.on("end", () => {
|
|
10074
|
+
incomingEnded = true;
|
|
10075
|
+
});
|
|
10076
|
+
if (incoming instanceof Http2ServerRequest2) {
|
|
10077
|
+
outgoing[outgoingEnded] = () => {
|
|
10078
|
+
if (!incomingEnded) {
|
|
10079
|
+
setTimeout(() => {
|
|
10080
|
+
if (!incomingEnded) {
|
|
10081
|
+
setTimeout(() => {
|
|
10082
|
+
incoming.destroy();
|
|
10083
|
+
outgoing.destroy();
|
|
10084
|
+
});
|
|
10085
|
+
}
|
|
10086
|
+
});
|
|
10087
|
+
}
|
|
10088
|
+
};
|
|
10089
|
+
}
|
|
10090
|
+
}
|
|
10091
|
+
outgoing.on("close", () => {
|
|
10092
|
+
const abortController = req[abortControllerKey];
|
|
10093
|
+
if (abortController) {
|
|
10094
|
+
if (incoming.errored) {
|
|
10095
|
+
req[abortControllerKey].abort(incoming.errored.toString());
|
|
10096
|
+
} else if (!outgoing.writableFinished) {
|
|
10097
|
+
req[abortControllerKey].abort("Client connection prematurely closed.");
|
|
10098
|
+
}
|
|
10099
|
+
}
|
|
10100
|
+
if (!incomingEnded) {
|
|
10101
|
+
setTimeout(() => {
|
|
10102
|
+
if (!incomingEnded) {
|
|
10103
|
+
setTimeout(() => {
|
|
10104
|
+
incoming.destroy();
|
|
10105
|
+
});
|
|
10106
|
+
}
|
|
10107
|
+
});
|
|
10108
|
+
}
|
|
10109
|
+
});
|
|
10110
|
+
res = fetchCallback(req, { incoming, outgoing });
|
|
10111
|
+
if (cacheKey in res) {
|
|
10112
|
+
return responseViaCache(res, outgoing);
|
|
10113
|
+
}
|
|
10114
|
+
} catch (e) {
|
|
10115
|
+
if (!res) {
|
|
10116
|
+
if (options.errorHandler) {
|
|
10117
|
+
res = await options.errorHandler(req ? e : toRequestError(e));
|
|
10118
|
+
if (!res) {
|
|
10119
|
+
return;
|
|
10120
|
+
}
|
|
10121
|
+
} else if (!req) {
|
|
10122
|
+
res = handleRequestError();
|
|
10123
|
+
} else {
|
|
10124
|
+
res = handleFetchError(e);
|
|
10125
|
+
}
|
|
10126
|
+
} else {
|
|
10127
|
+
return handleResponseError(e, outgoing);
|
|
10128
|
+
}
|
|
10129
|
+
}
|
|
10130
|
+
try {
|
|
10131
|
+
return await responseViaResponseObject(res, outgoing, options);
|
|
10132
|
+
} catch (e) {
|
|
10133
|
+
return handleResponseError(e, outgoing);
|
|
10134
|
+
}
|
|
10135
|
+
};
|
|
10136
|
+
};
|
|
10137
|
+
var createAdaptorServer = (options) => {
|
|
10138
|
+
const fetchCallback = options.fetch;
|
|
10139
|
+
const requestListener = getRequestListener(fetchCallback, {
|
|
10140
|
+
hostname: options.hostname,
|
|
10141
|
+
overrideGlobalObjects: options.overrideGlobalObjects,
|
|
10142
|
+
autoCleanupIncoming: options.autoCleanupIncoming
|
|
10143
|
+
});
|
|
10144
|
+
const createServer = options.createServer || createServerHTTP;
|
|
10145
|
+
const server = createServer(options.serverOptions || {}, requestListener);
|
|
10146
|
+
return server;
|
|
10147
|
+
};
|
|
10148
|
+
var serve = (options, listeningListener) => {
|
|
10149
|
+
const server = createAdaptorServer(options);
|
|
10150
|
+
server.listen(options?.port ?? 3000, options.hostname, () => {
|
|
10151
|
+
const serverInfo = server.address();
|
|
10152
|
+
listeningListener && listeningListener(serverInfo);
|
|
10153
|
+
});
|
|
10154
|
+
return server;
|
|
10155
|
+
};
|
|
10156
|
+
|
|
9624
10157
|
// ../../node_modules/.bun/hono@4.12.3/node_modules/hono/dist/compose.js
|
|
9625
10158
|
var compose = (middleware, onError, onNotFound) => {
|
|
9626
10159
|
return (context, next) => {
|
|
@@ -9777,15 +10310,15 @@ var getPattern = (label, next) => {
|
|
|
9777
10310
|
}
|
|
9778
10311
|
const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
|
|
9779
10312
|
if (match) {
|
|
9780
|
-
const
|
|
9781
|
-
if (!patternCache[
|
|
10313
|
+
const cacheKey2 = `${label}#${next}`;
|
|
10314
|
+
if (!patternCache[cacheKey2]) {
|
|
9782
10315
|
if (match[2]) {
|
|
9783
|
-
patternCache[
|
|
10316
|
+
patternCache[cacheKey2] = next && next[0] !== ":" && next[0] !== "*" ? [cacheKey2, match[1], new RegExp(`^${match[2]}(?=/${next})`)] : [label, match[1], new RegExp(`^${match[2]}$`)];
|
|
9784
10317
|
} else {
|
|
9785
|
-
patternCache[
|
|
10318
|
+
patternCache[cacheKey2] = [label, match[1], true];
|
|
9786
10319
|
}
|
|
9787
10320
|
}
|
|
9788
|
-
return patternCache[
|
|
10321
|
+
return patternCache[cacheKey2];
|
|
9789
10322
|
}
|
|
9790
10323
|
return null;
|
|
9791
10324
|
};
|
|
@@ -11157,7 +11690,7 @@ var Hono2 = class extends Hono {
|
|
|
11157
11690
|
};
|
|
11158
11691
|
|
|
11159
11692
|
// ../app/src/middleware.ts
|
|
11160
|
-
import { timingSafeEqual } from "crypto";
|
|
11693
|
+
import { timingSafeEqual } from "node:crypto";
|
|
11161
11694
|
function corsMiddleware(config = true) {
|
|
11162
11695
|
const opts = typeof config === "boolean" ? { origin: [], methods: ["GET", "POST", "OPTIONS"] } : config;
|
|
11163
11696
|
return async (c, next) => {
|
|
@@ -11410,19 +11943,19 @@ function createApp(config) {
|
|
|
11410
11943
|
listen(port) {
|
|
11411
11944
|
const listenPort = port ?? serverConfig.port ?? 3000;
|
|
11412
11945
|
const hostname = serverConfig.hostname ?? "0.0.0.0";
|
|
11413
|
-
const server =
|
|
11946
|
+
const server = serve({
|
|
11947
|
+
fetch: app.fetch,
|
|
11414
11948
|
port: listenPort,
|
|
11415
|
-
hostname
|
|
11416
|
-
fetch: app.fetch
|
|
11949
|
+
hostname
|
|
11417
11950
|
});
|
|
11418
11951
|
log5.info("ElsiumAI server started", {
|
|
11419
11952
|
url: `http://${hostname}:${listenPort}`,
|
|
11420
11953
|
routes: ["POST /chat", "POST /complete", "GET /health", "GET /metrics", "GET /agents"]
|
|
11421
11954
|
});
|
|
11422
11955
|
return {
|
|
11423
|
-
port:
|
|
11956
|
+
port: listenPort,
|
|
11424
11957
|
stop: () => {
|
|
11425
|
-
server.
|
|
11958
|
+
server.close();
|
|
11426
11959
|
}
|
|
11427
11960
|
};
|
|
11428
11961
|
}
|
|
@@ -11431,7 +11964,7 @@ function createApp(config) {
|
|
|
11431
11964
|
// ../app/src/rbac.ts
|
|
11432
11965
|
var log6 = createLogger();
|
|
11433
11966
|
// ../mcp/src/client.ts
|
|
11434
|
-
import { spawn } from "child_process";
|
|
11967
|
+
import { spawn } from "node:child_process";
|
|
11435
11968
|
function createMCPClient(config) {
|
|
11436
11969
|
let process2 = null;
|
|
11437
11970
|
let connected = false;
|
|
@@ -11919,7 +12452,7 @@ function mockProvider(options = {}) {
|
|
|
11919
12452
|
};
|
|
11920
12453
|
}
|
|
11921
12454
|
// ../testing/src/fixtures.ts
|
|
11922
|
-
import { createHash } from "crypto";
|
|
12455
|
+
import { createHash } from "node:crypto";
|
|
11923
12456
|
function hashMessages(messages) {
|
|
11924
12457
|
const content = messages.map((m) => `${m.role}:${m.content}`).join("|");
|
|
11925
12458
|
return createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
@@ -12281,7 +12814,7 @@ function formatEvalReport(result) {
|
|
|
12281
12814
|
const lines = [];
|
|
12282
12815
|
lines.push(`
|
|
12283
12816
|
Eval Suite: ${result.name}`);
|
|
12284
|
-
lines.push(` ${"
|
|
12817
|
+
lines.push(` ${"─".repeat(50)}`);
|
|
12285
12818
|
for (const r of result.results) {
|
|
12286
12819
|
const icon = r.passed ? "PASS" : "FAIL";
|
|
12287
12820
|
lines.push(` [${icon}] ${r.name} (${r.durationMs}ms)`);
|
|
@@ -12293,7 +12826,7 @@ function formatEvalReport(result) {
|
|
|
12293
12826
|
}
|
|
12294
12827
|
}
|
|
12295
12828
|
}
|
|
12296
|
-
lines.push(` ${"
|
|
12829
|
+
lines.push(` ${"─".repeat(50)}`);
|
|
12297
12830
|
lines.push(` Score: ${(result.score * 100).toFixed(1)}% | ${result.passed}/${result.total} passed | ${result.durationMs}ms`);
|
|
12298
12831
|
lines.push("");
|
|
12299
12832
|
return lines.join(`
|
|
@@ -12432,8 +12965,8 @@ function createPromptRegistry() {
|
|
|
12432
12965
|
};
|
|
12433
12966
|
}
|
|
12434
12967
|
// ../testing/src/regression.ts
|
|
12435
|
-
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
12436
|
-
import { dirname } from "path";
|
|
12968
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
12969
|
+
import { dirname } from "node:path";
|
|
12437
12970
|
function makeEmptyResult(name) {
|
|
12438
12971
|
return {
|
|
12439
12972
|
name,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elsium-ai",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "ElsiumAI — A high-performance, TypeScript-first AI framework
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "ElsiumAI — A high-performance, TypeScript-first AI framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Eric Utrera <ebutrera9103@gmail.com>",
|
|
7
7
|
"repository": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
|
-
"build": "bun build ./src/index.ts --outdir ./dist --target
|
|
25
|
+
"build": "bun build ./src/index.ts --outdir ./dist --target node && bun x tsc -p tsconfig.build.json --emitDeclarationOnly"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@elsium-ai/core": "workspace:*",
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
"@elsium-ai/mcp": "workspace:*"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"bun-types": "^1.3.0",
|
|
41
40
|
"typescript": "^5.7.0"
|
|
42
41
|
}
|
|
43
42
|
}
|