@elsium-ai/client 0.3.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 ADDED
@@ -0,0 +1,153 @@
1
+ # @elsium-ai/client
2
+
3
+ TypeScript HTTP client for consuming ElsiumAI servers, with full SSE streaming support.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@elsium-ai/client.svg)](https://www.npmjs.com/package/@elsium-ai/client)
6
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/elsium-ai/elsium-ai/blob/main/LICENSE)
7
+
8
+ ---
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @elsium-ai/client
14
+ ```
15
+
16
+ ---
17
+
18
+ ## What's Inside
19
+
20
+ | Category | Exports |
21
+ |----------|---------|
22
+ | **Client** | `createClient` |
23
+ | **Types** | `ElsiumClient`, `ClientConfig`, `ChatRequest`, `ChatResponse`, `CompleteRequest`, `CompleteResponse`, `HealthResponse`, `MetricsResponse`, `AgentInfo` |
24
+ | **SSE** | `parseSSEStream` |
25
+
26
+ ---
27
+
28
+ ## Usage
29
+
30
+ ### Creating a client
31
+
32
+ ```typescript
33
+ import { createClient } from '@elsium-ai/client'
34
+
35
+ const client = createClient({
36
+ baseUrl: 'http://localhost:3000',
37
+ apiKey: 'my-api-token', // Optional — sent as Authorization: Bearer header
38
+ timeout: 30_000, // Optional — request timeout in ms
39
+ })
40
+ ```
41
+
42
+ ### Chat with an agent
43
+
44
+ ```typescript
45
+ const response = await client.chat({
46
+ agent: 'support-agent',
47
+ message: 'How do I return my order?',
48
+ })
49
+
50
+ console.log(response.message) // Agent's response text
51
+ ```
52
+
53
+ ### Raw LLM completion
54
+
55
+ ```typescript
56
+ const response = await client.complete({
57
+ messages: [{ role: 'user', content: 'Explain TypeScript generics.' }],
58
+ model: 'claude-sonnet-4-6',
59
+ })
60
+
61
+ console.log(response.message)
62
+ console.log(response.usage) // { inputTokens, outputTokens, totalTokens }
63
+ ```
64
+
65
+ ### Streaming (SSE)
66
+
67
+ ```typescript
68
+ // Stream chat responses
69
+ for await (const event of client.chatStream({
70
+ agent: 'support-agent',
71
+ message: 'Write a poem about coding',
72
+ })) {
73
+ if (event.type === 'text_delta') {
74
+ process.stdout.write(event.text)
75
+ } else if (event.type === 'message_end') {
76
+ console.log('\nDone:', event.usage)
77
+ }
78
+ }
79
+
80
+ // Stream completions
81
+ for await (const event of client.completeStream({
82
+ messages: [{ role: 'user', content: 'Count to 10 slowly' }],
83
+ })) {
84
+ if (event.type === 'text_delta') {
85
+ process.stdout.write(event.text)
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### Health check
91
+
92
+ ```typescript
93
+ const health = await client.health()
94
+ console.log(health.status) // 'ok'
95
+ ```
96
+
97
+ ### List agents
98
+
99
+ ```typescript
100
+ const agents = await client.agents()
101
+ for (const agent of agents) {
102
+ console.log(`${agent.name}: ${agent.description}`)
103
+ }
104
+ ```
105
+
106
+ ### Metrics
107
+
108
+ ```typescript
109
+ const metrics = await client.metrics()
110
+ console.log(metrics)
111
+ ```
112
+
113
+ ---
114
+
115
+ ## SSE Parser
116
+
117
+ Use the SSE parser standalone to parse any Server-Sent Events response:
118
+
119
+ ```typescript
120
+ import { parseSSEStream } from '@elsium-ai/client'
121
+
122
+ const response = await fetch('http://localhost:3000/chat', {
123
+ method: 'POST',
124
+ headers: { 'Content-Type': 'application/json' },
125
+ body: JSON.stringify({ agent: 'assistant', message: 'Hello', stream: true }),
126
+ })
127
+
128
+ for await (const event of parseSSEStream(response)) {
129
+ console.log(event.type, event)
130
+ }
131
+ ```
132
+
133
+ ---
134
+
135
+ ## ElsiumClient Interface
136
+
137
+ ```typescript
138
+ interface ElsiumClient {
139
+ chat(req: ChatRequest): Promise<ChatResponse>
140
+ chatStream(req: ChatRequest): AsyncIterable<StreamEvent>
141
+ complete(req: CompleteRequest): Promise<CompleteResponse>
142
+ completeStream(req: CompleteRequest): AsyncIterable<StreamEvent>
143
+ health(): Promise<HealthResponse>
144
+ metrics(): Promise<MetricsResponse>
145
+ agents(): Promise<AgentInfo[]>
146
+ }
147
+ ```
148
+
149
+ ---
150
+
151
+ ## License
152
+
153
+ [MIT](https://github.com/elsium-ai/elsium-ai/blob/main/LICENSE) - Copyright (c) 2026 Eric Utrera
@@ -0,0 +1,85 @@
1
+ import type { StreamEvent } from '@elsium-ai/core';
2
+ export interface ClientConfig {
3
+ baseUrl: string;
4
+ apiKey?: string;
5
+ timeout?: number;
6
+ }
7
+ export interface ChatRequest {
8
+ message: string;
9
+ agent?: string;
10
+ stream?: boolean;
11
+ }
12
+ export interface ChatResponse {
13
+ message: string;
14
+ usage: {
15
+ inputTokens: number;
16
+ outputTokens: number;
17
+ totalTokens: number;
18
+ cost: number;
19
+ };
20
+ model: string;
21
+ traceId: string;
22
+ }
23
+ export interface CompleteRequest {
24
+ messages: Array<{
25
+ role: string;
26
+ content: string;
27
+ }>;
28
+ model?: string;
29
+ system?: string;
30
+ maxTokens?: number;
31
+ temperature?: number;
32
+ stream?: boolean;
33
+ }
34
+ export interface CompleteResponse {
35
+ id: string;
36
+ message: string;
37
+ model: string;
38
+ usage: {
39
+ inputTokens: number;
40
+ outputTokens: number;
41
+ totalTokens: number;
42
+ };
43
+ cost: {
44
+ inputCost: number;
45
+ outputCost: number;
46
+ totalCost: number;
47
+ currency: string;
48
+ };
49
+ traceId: string;
50
+ }
51
+ export interface HealthResponse {
52
+ status: 'ok' | 'degraded';
53
+ version: string;
54
+ uptime: number;
55
+ providers: string[];
56
+ }
57
+ export interface MetricsResponse {
58
+ uptime: number;
59
+ totalRequests: number;
60
+ totalTokens: number;
61
+ totalCost: number;
62
+ byModel: Record<string, {
63
+ requests: number;
64
+ tokens: number;
65
+ cost: number;
66
+ }>;
67
+ }
68
+ export interface AgentInfo {
69
+ name: string;
70
+ model: string;
71
+ tools: string[];
72
+ }
73
+ export interface ElsiumClient {
74
+ chat(req: ChatRequest): Promise<ChatResponse>;
75
+ chatStream(req: ChatRequest): AsyncIterable<StreamEvent>;
76
+ complete(req: CompleteRequest): Promise<CompleteResponse>;
77
+ completeStream(req: CompleteRequest): AsyncIterable<StreamEvent>;
78
+ health(): Promise<HealthResponse>;
79
+ metrics(): Promise<MetricsResponse>;
80
+ agents(): Promise<{
81
+ agents: AgentInfo[];
82
+ }>;
83
+ }
84
+ export declare function createClient(config: ClientConfig): ElsiumClient;
85
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { createClient } from './client';
2
+ export type { ElsiumClient, ClientConfig, ChatRequest, ChatResponse, CompleteRequest, CompleteResponse, HealthResponse, MetricsResponse, AgentInfo, } from './client';
3
+ export { parseSSEStream } from './sse-parser';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,YAAY,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,SAAS,GACT,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,119 @@
1
+ // src/sse-parser.ts
2
+ async function* parseSSEStream(response) {
3
+ if (!response.body) {
4
+ throw new Error("Response body is null");
5
+ }
6
+ const reader = response.body.getReader();
7
+ const decoder = new TextDecoder;
8
+ let buffer = "";
9
+ try {
10
+ while (true) {
11
+ const { done, value } = await reader.read();
12
+ if (done)
13
+ break;
14
+ buffer += decoder.decode(value, { stream: true });
15
+ const lines = buffer.split(`
16
+ `);
17
+ buffer = lines.pop() ?? "";
18
+ for (const line of lines) {
19
+ if (line.startsWith("event: error")) {
20
+ continue;
21
+ }
22
+ if (!line.startsWith("data: "))
23
+ continue;
24
+ const data = line.slice(6).trim();
25
+ if (!data || data === "[DONE]")
26
+ continue;
27
+ try {
28
+ const event = JSON.parse(data);
29
+ yield event;
30
+ } catch {}
31
+ }
32
+ }
33
+ } finally {
34
+ reader.releaseLock();
35
+ }
36
+ }
37
+
38
+ // src/client.ts
39
+ function createClient(config) {
40
+ const { baseUrl, apiKey, timeout = 30000 } = config;
41
+ function headers() {
42
+ const h = {
43
+ "Content-Type": "application/json"
44
+ };
45
+ if (apiKey) {
46
+ h.Authorization = `Bearer ${apiKey}`;
47
+ }
48
+ return h;
49
+ }
50
+ async function request(method, path, body) {
51
+ const controller = new AbortController;
52
+ const timer = setTimeout(() => controller.abort(), timeout);
53
+ try {
54
+ const response = await fetch(`${baseUrl}${path}`, {
55
+ method,
56
+ headers: headers(),
57
+ body: body ? JSON.stringify(body) : undefined,
58
+ signal: controller.signal
59
+ });
60
+ if (!response.ok) {
61
+ const errorBody = await response.text().catch(() => "Unknown error");
62
+ throw new Error(`HTTP ${response.status}: ${errorBody}`);
63
+ }
64
+ return await response.json();
65
+ } finally {
66
+ clearTimeout(timer);
67
+ }
68
+ }
69
+ async function streamRequest(path, body) {
70
+ const controller = new AbortController;
71
+ const timer = setTimeout(() => controller.abort(), timeout);
72
+ try {
73
+ const response = await fetch(`${baseUrl}${path}`, {
74
+ method: "POST",
75
+ headers: headers(),
76
+ body: JSON.stringify(body),
77
+ signal: controller.signal
78
+ });
79
+ if (!response.ok) {
80
+ const errorBody = await response.text().catch(() => "Unknown error");
81
+ clearTimeout(timer);
82
+ throw new Error(`HTTP ${response.status}: ${errorBody}`);
83
+ }
84
+ return response;
85
+ } catch (err) {
86
+ clearTimeout(timer);
87
+ throw err;
88
+ }
89
+ }
90
+ return {
91
+ async chat(req) {
92
+ return request("POST", "/chat", { ...req, stream: false });
93
+ },
94
+ async* chatStream(req) {
95
+ const response = await streamRequest("/chat", { ...req, stream: true });
96
+ yield* parseSSEStream(response);
97
+ },
98
+ async complete(req) {
99
+ return request("POST", "/complete", { ...req, stream: false });
100
+ },
101
+ async* completeStream(req) {
102
+ const response = await streamRequest("/complete", { ...req, stream: true });
103
+ yield* parseSSEStream(response);
104
+ },
105
+ async health() {
106
+ return request("GET", "/health");
107
+ },
108
+ async metrics() {
109
+ return request("GET", "/metrics");
110
+ },
111
+ async agents() {
112
+ return request("GET", "/agents");
113
+ }
114
+ };
115
+ }
116
+ export {
117
+ parseSSEStream,
118
+ createClient
119
+ };
@@ -0,0 +1,3 @@
1
+ import type { StreamEvent } from '@elsium-ai/core';
2
+ export declare function parseSSEStream(response: Response): AsyncIterable<StreamEvent>;
3
+ //# sourceMappingURL=sse-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-parser.d.ts","sourceRoot":"","sources":["../src/sse-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,wBAAuB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,aAAa,CAAC,WAAW,CAAC,CAsCpF"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@elsium-ai/client",
3
+ "version": "0.3.0",
4
+ "description": "HTTP client SDK for ElsiumAI server",
5
+ "license": "MIT",
6
+ "author": "Eric Utrera <ebutrera9103@gmail.com>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/elsium-ai/elsium-ai.git",
10
+ "directory": "packages/client"
11
+ },
12
+ "type": "module",
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/index.js",
18
+ "types": "./dist/index.d.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "bun build ./src/index.ts --outdir ./dist --target node && bun x tsc -p tsconfig.build.json --emitDeclarationOnly",
26
+ "dev": "bun --watch src/index.ts"
27
+ },
28
+ "dependencies": {
29
+ "@elsium-ai/core": "^0.3.0"
30
+ },
31
+ "devDependencies": {
32
+ "typescript": "^5.7.0"
33
+ },
34
+ "publishConfig": {
35
+ "registry": "https://registry.npmjs.org",
36
+ "access": "public"
37
+ }
38
+ }