@metrxbot/sdk 0.1.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,207 @@
1
+ # Metrx SDK
2
+
3
+ TypeScript SDK for integrating with the Metrx gateway. The gateway is a Cloudflare Worker that proxies LLM API calls with cost tracking, rate limiting, and request metadata.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @metrx/sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### Initialize the Client
14
+
15
+ ```typescript
16
+ import { MetrxbotClient } from '@metrx/sdk';
17
+
18
+ const client = new MetrxbotClient({
19
+ apiKey: process.env.METRX_API_KEY,
20
+ gatewayUrl: 'https://gateway.metrxbot.com', // optional, defaults to this
21
+ defaultAgentId: 'my-agent', // optional
22
+ timeout: 30000, // optional, in milliseconds
23
+ });
24
+ ```
25
+
26
+ ### Chat Completions (OpenAI-compatible)
27
+
28
+ ```typescript
29
+ const response = await client.chat({
30
+ model: 'gpt-4',
31
+ messages: [
32
+ { role: 'user', content: 'What is 2+2?' }
33
+ ],
34
+ customerId: 'user-123', // optional, for tracking
35
+ sessionId: 'session-456', // optional, for tracking
36
+ });
37
+
38
+ console.log(response.choices[0].message.content);
39
+ console.log(`Cost: ${response._meta.costMicrocents} microcents`);
40
+ console.log(`Latency: ${response._meta.latencyMs}ms`);
41
+ ```
42
+
43
+ ### Streaming Chat Completions
44
+
45
+ ```typescript
46
+ const stream = client.chatStream({
47
+ model: 'gpt-4',
48
+ messages: [
49
+ { role: 'user', content: 'Write a haiku' }
50
+ ]
51
+ });
52
+
53
+ for await (const chunk of stream) {
54
+ if (chunk.choices?.[0]?.delta?.content) {
55
+ process.stdout.write(chunk.choices[0].delta.content);
56
+ }
57
+ }
58
+ ```
59
+
60
+ ### Anthropic Messages API
61
+
62
+ ```typescript
63
+ const response = await client.messages({
64
+ model: 'claude-3-sonnet',
65
+ max_tokens: 1024,
66
+ messages: [
67
+ { role: 'user', content: 'Hello, Claude!' }
68
+ ]
69
+ });
70
+
71
+ console.log(response.content[0].text);
72
+ ```
73
+
74
+ ### Embeddings
75
+
76
+ ```typescript
77
+ const response = await client.embeddings({
78
+ model: 'text-embedding-3-small',
79
+ input: 'Hello world'
80
+ });
81
+
82
+ console.log(response.data[0].embedding);
83
+ ```
84
+
85
+ ### Health Check
86
+
87
+ ```typescript
88
+ const health = await client.health();
89
+ console.log(health.status); // 'ok', 'degraded', or 'error'
90
+ console.log(health.version);
91
+ ```
92
+
93
+ ### List Available Models
94
+
95
+ ```typescript
96
+ const models = await client.models();
97
+ console.log(models.data.map(m => m.id));
98
+ ```
99
+
100
+ ## Configuration
101
+
102
+ ### Client Options
103
+
104
+ ```typescript
105
+ interface MetrxbotConfig {
106
+ // Required: Your Metrx API key
107
+ apiKey: string;
108
+
109
+ // Optional: Gateway URL (defaults to https://gateway.metrxbot.com)
110
+ gatewayUrl?: string;
111
+
112
+ // Optional: Default agent ID for all requests
113
+ defaultAgentId?: string;
114
+
115
+ // Optional: Default LLM provider (openai, anthropic, etc.)
116
+ defaultProvider?: string;
117
+
118
+ // Optional: Request timeout in milliseconds (defaults to 30000)
119
+ timeout?: number;
120
+ }
121
+ ```
122
+
123
+ ### Request Options
124
+
125
+ All API methods accept these additional optional parameters:
126
+
127
+ ```typescript
128
+ interface RequestOptions {
129
+ // Override the default agent ID for this request
130
+ agentId?: string;
131
+
132
+ // Customer/end-user ID for tracking
133
+ customerId?: string;
134
+
135
+ // Session ID for tracking
136
+ sessionId?: string;
137
+
138
+ // Provider API key (if required by provider)
139
+ providerKey?: string;
140
+
141
+ // Force a specific provider for this request
142
+ provider?: string;
143
+ }
144
+ ```
145
+
146
+ ## Error Handling
147
+
148
+ The SDK provides specific error classes for different failure scenarios:
149
+
150
+ ```typescript
151
+ import {
152
+ MetrxbotError,
153
+ AuthenticationError,
154
+ RateLimitError,
155
+ GatewayError,
156
+ ValidationError,
157
+ TimeoutError,
158
+ } from '@metrxbot/sdk';
159
+
160
+ try {
161
+ const response = await client.chat({
162
+ model: 'gpt-4',
163
+ messages: [{ role: 'user', content: 'Hello' }]
164
+ });
165
+ } catch (error) {
166
+ if (error instanceof AuthenticationError) {
167
+ console.error('API key is invalid');
168
+ } else if (error instanceof RateLimitError) {
169
+ console.error(`Rate limited. Retry after ${error.retryAfter}s`);
170
+ } else if (error instanceof GatewayError) {
171
+ console.error('Gateway is experiencing issues');
172
+ } else if (error instanceof ValidationError) {
173
+ console.error('Invalid request parameters');
174
+ } else if (error instanceof TimeoutError) {
175
+ console.error('Request timed out');
176
+ } else {
177
+ console.error('Unknown error:', error);
178
+ }
179
+ }
180
+ ```
181
+
182
+ ## Response Metadata
183
+
184
+ All responses include a `_meta` field with gateway metadata:
185
+
186
+ ```typescript
187
+ interface MetrxbotMeta {
188
+ // Gateway response latency in milliseconds
189
+ latencyMs: number;
190
+
191
+ // Cost of the request in microcents
192
+ costMicrocents: number;
193
+
194
+ // X-Request-ID header from gateway
195
+ requestId?: string;
196
+ }
197
+ ```
198
+
199
+ ## Supported Environments
200
+
201
+ - Node.js 18+
202
+ - Deno
203
+ - Modern browsers (with native fetch support)
204
+
205
+ ## License
206
+
207
+ MIT
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Metrx Client
3
+ * Main SDK client for interacting with the Metrx gateway
4
+ */
5
+ import { MetrxbotConfig, ChatCompletionParams, ChatCompletionResponse, EmbeddingsParams, EmbeddingsResponse, HealthResponse, MessagesParams, MessagesResponse, ModelsResponse, StreamChunk } from './types';
6
+ export declare class MetrxbotClient {
7
+ private apiKey;
8
+ private gatewayUrl;
9
+ private defaultAgentId?;
10
+ private defaultProvider?;
11
+ private timeout;
12
+ constructor(config: MetrxbotConfig);
13
+ /**
14
+ * Perform a health check on the gateway
15
+ */
16
+ health(): Promise<HealthResponse>;
17
+ /**
18
+ * List available models
19
+ */
20
+ models(): Promise<ModelsResponse>;
21
+ /**
22
+ * OpenAI-compatible chat completion
23
+ */
24
+ chat(params: ChatCompletionParams): Promise<ChatCompletionResponse>;
25
+ /**
26
+ * OpenAI-compatible chat completion with streaming
27
+ */
28
+ chatStream(params: ChatCompletionParams): AsyncIterable<StreamChunk>;
29
+ /**
30
+ * Anthropic-compatible messages endpoint
31
+ */
32
+ messages(params: MessagesParams): Promise<MessagesResponse>;
33
+ /**
34
+ * OpenAI-compatible embeddings
35
+ */
36
+ embeddings(params: EmbeddingsParams): Promise<EmbeddingsResponse>;
37
+ /**
38
+ * Internal: Make a JSON request and return parsed response
39
+ */
40
+ private request;
41
+ /**
42
+ * Internal: Raw fetch with headers and timeout
43
+ */
44
+ private fetchRaw;
45
+ /**
46
+ * Internal: Build request headers
47
+ */
48
+ private buildHeaders;
49
+ /**
50
+ * Internal: Extract metadata from response headers
51
+ */
52
+ private extractMetadata;
53
+ /**
54
+ * Internal: Handle error responses
55
+ */
56
+ private handleErrorResponse;
57
+ }
58
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,cAAc,EAEd,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,cAAc,EAEd,WAAW,EACZ,MAAM,SAAS,CAAC;AAajB,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,cAAc;IAYlC;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAIvC;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAIvC;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IASzE;;OAEG;IACI,UAAU,CACf,MAAM,EAAE,oBAAoB,GAC3B,aAAa,CAAC,WAAW,CAAC;IAyD7B;;OAEG;IACG,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC;IASjE;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IASvE;;OAEG;YACW,OAAO;IAsBrB;;OAEG;YACW,QAAQ;IAsCtB;;OAEG;IACH,OAAO,CAAC,YAAY;IA+BpB;;OAEG;IACH,OAAO,CAAC,eAAe;IAkBvB;;OAEG;YACW,mBAAmB;CAgClC"}
package/dist/client.js ADDED
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Metrx Client
3
+ * Main SDK client for interacting with the Metrx gateway
4
+ */
5
+ import { MetrxbotError, AuthenticationError, GatewayError, RateLimitError, TimeoutError, ValidationError, } from './errors';
6
+ const DEFAULT_GATEWAY_URL = 'https://gateway.metrxbot.com';
7
+ const DEFAULT_TIMEOUT = 30000; // 30 seconds
8
+ export class MetrxbotClient {
9
+ apiKey;
10
+ gatewayUrl;
11
+ defaultAgentId;
12
+ defaultProvider;
13
+ timeout;
14
+ constructor(config) {
15
+ if (!config.apiKey) {
16
+ throw new ValidationError('apiKey is required');
17
+ }
18
+ this.apiKey = config.apiKey;
19
+ this.gatewayUrl = config.gatewayUrl || DEFAULT_GATEWAY_URL;
20
+ this.defaultAgentId = config.defaultAgentId;
21
+ this.defaultProvider = config.defaultProvider;
22
+ this.timeout = config.timeout || DEFAULT_TIMEOUT;
23
+ }
24
+ /**
25
+ * Perform a health check on the gateway
26
+ */
27
+ async health() {
28
+ return this.request('GET', '/health');
29
+ }
30
+ /**
31
+ * List available models
32
+ */
33
+ async models() {
34
+ return this.request('GET', '/v1/models');
35
+ }
36
+ /**
37
+ * OpenAI-compatible chat completion
38
+ */
39
+ async chat(params) {
40
+ return this.request('POST', '/v1/chat/completions', { ...params, stream: false }, params);
41
+ }
42
+ /**
43
+ * OpenAI-compatible chat completion with streaming
44
+ */
45
+ async *chatStream(params) {
46
+ const response = await this.fetchRaw('POST', '/v1/chat/completions', { ...params, stream: true }, params);
47
+ if (!response.ok) {
48
+ await this.handleErrorResponse(response);
49
+ }
50
+ if (!response.body) {
51
+ throw new MetrxbotError('No response body for streaming request');
52
+ }
53
+ const reader = response.body.getReader();
54
+ const decoder = new TextDecoder();
55
+ try {
56
+ let buffer = '';
57
+ while (true) {
58
+ const { done, value } = await reader.read();
59
+ if (done)
60
+ break;
61
+ buffer += decoder.decode(value, { stream: true });
62
+ const lines = buffer.split('\n');
63
+ buffer = lines.pop() || '';
64
+ for (const line of lines) {
65
+ if (!line.trim())
66
+ continue;
67
+ if (!line.startsWith('data: '))
68
+ continue;
69
+ const data = line.slice(6).trim();
70
+ if (data === '[DONE]') {
71
+ break;
72
+ }
73
+ try {
74
+ const chunk = JSON.parse(data);
75
+ // Attach metadata from response headers
76
+ chunk._meta = this.extractMetadata(response);
77
+ yield chunk;
78
+ }
79
+ catch {
80
+ // Skip malformed JSON
81
+ }
82
+ }
83
+ }
84
+ }
85
+ finally {
86
+ reader.releaseLock();
87
+ }
88
+ }
89
+ /**
90
+ * Anthropic-compatible messages endpoint
91
+ */
92
+ async messages(params) {
93
+ return this.request('POST', '/v1/messages', params, params);
94
+ }
95
+ /**
96
+ * OpenAI-compatible embeddings
97
+ */
98
+ async embeddings(params) {
99
+ return this.request('POST', '/v1/embeddings', params, params);
100
+ }
101
+ /**
102
+ * Internal: Make a JSON request and return parsed response
103
+ */
104
+ async request(method, path, body, options) {
105
+ const response = await this.fetchRaw(method, path, body, options);
106
+ if (!response.ok) {
107
+ await this.handleErrorResponse(response);
108
+ }
109
+ const data = (await response.json());
110
+ // Attach metadata from response headers
111
+ if (data && typeof data === 'object') {
112
+ data._meta = this.extractMetadata(response);
113
+ }
114
+ return data;
115
+ }
116
+ /**
117
+ * Internal: Raw fetch with headers and timeout
118
+ */
119
+ async fetchRaw(method, path, body, options) {
120
+ const url = `${this.gatewayUrl}${path}`;
121
+ const headers = this.buildHeaders(options);
122
+ const init = {
123
+ method,
124
+ headers,
125
+ };
126
+ if (body) {
127
+ init.body = JSON.stringify(body);
128
+ }
129
+ const controller = new AbortController();
130
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
131
+ try {
132
+ const response = await fetch(url, {
133
+ ...init,
134
+ signal: controller.signal,
135
+ });
136
+ return response;
137
+ }
138
+ catch (error) {
139
+ if (error instanceof Error && error.name === 'AbortError') {
140
+ throw new TimeoutError(`Request timeout after ${this.timeout}ms`);
141
+ }
142
+ throw error;
143
+ }
144
+ finally {
145
+ clearTimeout(timeoutId);
146
+ }
147
+ }
148
+ /**
149
+ * Internal: Build request headers
150
+ */
151
+ buildHeaders(options) {
152
+ const headers = {
153
+ 'Content-Type': 'application/json',
154
+ Authorization: `Bearer ${this.apiKey}`,
155
+ };
156
+ const agentId = options?.agentId || this.defaultAgentId;
157
+ if (agentId) {
158
+ headers['X-Agent-ID'] = agentId;
159
+ }
160
+ if (options?.customerId) {
161
+ headers['X-Customer-ID'] = options.customerId;
162
+ }
163
+ if (options?.sessionId) {
164
+ headers['X-Session-ID'] = options.sessionId;
165
+ }
166
+ if (options?.providerKey) {
167
+ headers['X-Provider-Key'] = options.providerKey;
168
+ }
169
+ const provider = options?.provider || this.defaultProvider;
170
+ if (provider) {
171
+ headers['X-Provider'] = provider;
172
+ }
173
+ return headers;
174
+ }
175
+ /**
176
+ * Internal: Extract metadata from response headers
177
+ */
178
+ extractMetadata(response) {
179
+ const latencyMs = parseInt(response.headers.get('X-Gateway-Latency') || '0', 10);
180
+ const costMicrocents = parseInt(response.headers.get('X-Gateway-Cost') || '0', 10);
181
+ const requestId = response.headers.get('X-Request-ID') || undefined;
182
+ return {
183
+ latencyMs,
184
+ costMicrocents,
185
+ requestId: requestId || undefined,
186
+ };
187
+ }
188
+ /**
189
+ * Internal: Handle error responses
190
+ */
191
+ async handleErrorResponse(response) {
192
+ const requestId = response.headers.get('X-Request-ID') || undefined;
193
+ let errorMessage = `HTTP ${response.status}`;
194
+ try {
195
+ const errorData = (await response.json());
196
+ if (errorData.error?.message) {
197
+ errorMessage = errorData.error.message;
198
+ }
199
+ }
200
+ catch {
201
+ // Response is not JSON, use default message
202
+ }
203
+ switch (response.status) {
204
+ case 400:
205
+ throw new ValidationError(errorMessage, requestId);
206
+ case 401:
207
+ throw new AuthenticationError(errorMessage, requestId);
208
+ case 429:
209
+ const retryAfter = response.headers.get('Retry-After');
210
+ throw new RateLimitError(errorMessage, retryAfter || undefined, requestId);
211
+ case 502:
212
+ case 504:
213
+ throw new GatewayError(errorMessage, response.status, requestId);
214
+ default:
215
+ throw new MetrxbotError(errorMessage, response.status, requestId);
216
+ }
217
+ }
218
+ }
219
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Metrx Error Classes
3
+ */
4
+ export declare class MetrxbotError extends Error {
5
+ statusCode?: number;
6
+ retryAfter?: number;
7
+ requestId?: string;
8
+ constructor(message: string, statusCode?: number, requestId?: string);
9
+ }
10
+ export declare class AuthenticationError extends MetrxbotError {
11
+ constructor(message?: string, requestId?: string);
12
+ }
13
+ export declare class RateLimitError extends MetrxbotError {
14
+ constructor(message?: string, retryAfter?: number | string, requestId?: string);
15
+ }
16
+ export declare class GatewayError extends MetrxbotError {
17
+ constructor(message: string, statusCode: number, requestId?: string);
18
+ }
19
+ export declare class ValidationError extends MetrxbotError {
20
+ constructor(message?: string, requestId?: string);
21
+ }
22
+ export declare class TimeoutError extends MetrxbotError {
23
+ constructor(message?: string, requestId?: string);
24
+ }
25
+ export declare function isMetrxbotError(error: unknown): error is MetrxbotError;
26
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,aAAc,SAAQ,KAAK;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAMrE;AAED,qBAAa,mBAAoB,SAAQ,aAAa;gBACxC,OAAO,GAAE,MAAgC,EAAE,SAAS,CAAC,EAAE,MAAM;CAI1E;AAED,qBAAa,cAAe,SAAQ,aAAa;gBAE7C,OAAO,GAAE,MAA8B,EACvC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAC5B,SAAS,CAAC,EAAE,MAAM;CAOrB;AAED,qBAAa,YAAa,SAAQ,aAAa;gBACjC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAIpE;AAED,qBAAa,eAAgB,SAAQ,aAAa;gBACpC,OAAO,GAAE,MAA4B,EAAE,SAAS,CAAC,EAAE,MAAM;CAItE;AAED,qBAAa,YAAa,SAAQ,aAAa;gBACjC,OAAO,GAAE,MAA0B,EAAE,SAAS,CAAC,EAAE,MAAM;CAIpE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEtE"}
package/dist/errors.js ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Metrx Error Classes
3
+ */
4
+ export class MetrxbotError extends Error {
5
+ statusCode;
6
+ retryAfter;
7
+ requestId;
8
+ constructor(message, statusCode, requestId) {
9
+ super(message);
10
+ this.name = 'MetrxbotError';
11
+ this.statusCode = statusCode;
12
+ this.requestId = requestId;
13
+ }
14
+ }
15
+ export class AuthenticationError extends MetrxbotError {
16
+ constructor(message = 'Authentication failed', requestId) {
17
+ super(message, 401, requestId);
18
+ this.name = 'AuthenticationError';
19
+ }
20
+ }
21
+ export class RateLimitError extends MetrxbotError {
22
+ constructor(message = 'Rate limit exceeded', retryAfter, requestId) {
23
+ super(message, 429, requestId);
24
+ this.name = 'RateLimitError';
25
+ this.retryAfter =
26
+ typeof retryAfter === 'string' ? parseInt(retryAfter, 10) : retryAfter;
27
+ }
28
+ }
29
+ export class GatewayError extends MetrxbotError {
30
+ constructor(message, statusCode, requestId) {
31
+ super(message, statusCode, requestId);
32
+ this.name = 'GatewayError';
33
+ }
34
+ }
35
+ export class ValidationError extends MetrxbotError {
36
+ constructor(message = 'Validation failed', requestId) {
37
+ super(message, 400, requestId);
38
+ this.name = 'ValidationError';
39
+ }
40
+ }
41
+ export class TimeoutError extends MetrxbotError {
42
+ constructor(message = 'Request timeout', requestId) {
43
+ super(message, 0, requestId);
44
+ this.name = 'TimeoutError';
45
+ }
46
+ }
47
+ export function isMetrxbotError(error) {
48
+ return error instanceof MetrxbotError;
49
+ }
50
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC/B,UAAU,CAAU;IACpB,UAAU,CAAU;IACpB,SAAS,CAAU;IAE1B,YAAY,OAAe,EAAE,UAAmB,EAAE,SAAkB;QAClE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,aAAa;IACpD,YAAY,UAAkB,uBAAuB,EAAE,SAAkB;QACvE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,aAAa;IAC/C,YACE,UAAkB,qBAAqB,EACvC,UAA4B,EAC5B,SAAkB;QAElB,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,UAAU;YACb,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAC3E,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,aAAa;IAC7C,YAAY,OAAe,EAAE,UAAkB,EAAE,SAAkB;QACjE,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,aAAa;IAChD,YAAY,UAAkB,mBAAmB,EAAE,SAAkB;QACnE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,aAAa;IAC7C,YAAY,UAAkB,iBAAiB,EAAE,SAAkB;QACjE,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,KAAK,YAAY,aAAa,CAAC;AACxC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Metrx SDK
3
+ * TypeScript SDK for integrating with Metrx gateway
4
+ */
5
+ export { MetrxbotClient } from './client';
6
+ export { MetrxbotSpanExporter } from './otel';
7
+ export type { MetrxbotConfig, MetrxbotMeta, RequestOptions, ChatCompletionParams, ChatCompletionResponse, ChatMessage, ChatChoice, StreamChunk, StreamChoice, MessagesParams, MessagesResponse, AnthropicMessage, AnthropicContent, MessageContent, EmbeddingsParams, EmbeddingsResponse, Embedding, HealthResponse, ModelsResponse, Model, APIError, OtelExporterConfig, } from './types';
8
+ export { MetrxbotError, AuthenticationError, RateLimitError, GatewayError, ValidationError, TimeoutError, isMetrxbotError, } from './errors';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAG9C,YAAY,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,WAAW,EACX,UAAU,EACV,WAAW,EACX,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,cAAc,EACd,KAAK,EACL,QAAQ,EACR,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Metrx SDK
3
+ * TypeScript SDK for integrating with Metrx gateway
4
+ */
5
+ export { MetrxbotClient } from './client';
6
+ // OpenTelemetry Exporter
7
+ export { MetrxbotSpanExporter } from './otel';
8
+ // Errors
9
+ export { MetrxbotError, AuthenticationError, RateLimitError, GatewayError, ValidationError, TimeoutError, isMetrxbotError, } from './errors';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,yBAAyB;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AA4B9C,SAAS;AACT,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAC"}
package/dist/otel.d.ts ADDED
@@ -0,0 +1,115 @@
1
+ /**
2
+ * OpenTelemetry Span Exporter for Metrx
3
+ *
4
+ * Exports LLM-related spans to Metrx's event ingestion API.
5
+ * Uses duck typing to avoid @opentelemetry dependencies (zero-dependency SDK).
6
+ */
7
+ import type { OtelExporterConfig } from './types';
8
+ /**
9
+ * Minimal SpanExporter interface (duck-typed from OpenTelemetry)
10
+ */
11
+ interface SpanExporter {
12
+ export(spans: ReadableSpan[], resultCallback: ExportResultCallback): void;
13
+ shutdown(): Promise<void>;
14
+ forceFlush(timeoutMs?: number): Promise<void>;
15
+ }
16
+ /**
17
+ * Minimal ReadableSpan interface (duck-typed from OpenTelemetry)
18
+ */
19
+ interface ReadableSpan {
20
+ name: string;
21
+ spanContext(): {
22
+ traceId: string;
23
+ spanId: string;
24
+ };
25
+ parentSpanId?: string;
26
+ startTime: [number, number];
27
+ endTime: [number, number];
28
+ duration: [number, number];
29
+ status?: {
30
+ code: number;
31
+ message?: string;
32
+ };
33
+ attributes?: Record<string, any>;
34
+ links?: Array<any>;
35
+ events?: Array<any>;
36
+ resource?: {
37
+ attributes?: Record<string, any>;
38
+ };
39
+ }
40
+ /**
41
+ * Result callback for span export
42
+ */
43
+ type ExportResultCallback = (result: ExportResult) => void;
44
+ /**
45
+ * Export result status codes
46
+ */
47
+ declare enum ExportResultCode {
48
+ SUCCESS = 0,
49
+ FAILED = 1
50
+ }
51
+ /**
52
+ * Export result passed to callback
53
+ */
54
+ interface ExportResult {
55
+ code: ExportResultCode;
56
+ }
57
+ /**
58
+ * OpenTelemetry Span Exporter for Metrx
59
+ *
60
+ * Filters LLM-related spans from OpenTelemetry SDK and exports them
61
+ * to Metrx's event ingestion API.
62
+ */
63
+ export declare class MetrxbotSpanExporter implements SpanExporter {
64
+ private apiKey;
65
+ private gatewayUrl;
66
+ private agentId?;
67
+ private batchSize;
68
+ private flushIntervalMs;
69
+ private buffer;
70
+ private flushTimer?;
71
+ private isShuttingDown;
72
+ constructor(config: OtelExporterConfig);
73
+ /**
74
+ * Export spans from OpenTelemetry SDK
75
+ */
76
+ export(spans: ReadableSpan[], resultCallback: ExportResultCallback): void;
77
+ /**
78
+ * Shutdown exporter and flush remaining spans
79
+ */
80
+ shutdown(): Promise<void>;
81
+ /**
82
+ * Force flush buffered spans immediately
83
+ */
84
+ forceFlush(_timeoutMs?: number): Promise<void>;
85
+ /**
86
+ * Convert an OpenTelemetry span to an LLM event
87
+ */
88
+ private spanToLLMEvent;
89
+ /**
90
+ * Check if a span is LLM-related
91
+ */
92
+ private isLLMSpan;
93
+ /**
94
+ * Calculate latency in milliseconds from span timing
95
+ */
96
+ private calculateLatencyMs;
97
+ /**
98
+ * Start periodic flush timer
99
+ */
100
+ private startFlushTimer;
101
+ /**
102
+ * Flush buffered spans synchronously (best effort)
103
+ */
104
+ private flush;
105
+ /**
106
+ * Flush buffered spans asynchronously
107
+ */
108
+ private flushAsync;
109
+ /**
110
+ * Send events to Metrx API
111
+ */
112
+ private sendEvents;
113
+ }
114
+ export {};
115
+ //# sourceMappingURL=otel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel.d.ts","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;GAEG;AACH,UAAU,YAAY;IACpB,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,cAAc,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED;;GAEG;AACH,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACpB,QAAQ,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,CAAC;CACjD;AAED;;GAEG;AACH,KAAK,oBAAoB,GAAG,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;AAE3D;;GAEG;AACH,aAAK,gBAAgB;IACnB,OAAO,IAAI;IACX,MAAM,IAAI;CACX;AAED;;GAEG;AACH,UAAU,YAAY;IACpB,IAAI,EAAE,gBAAgB,CAAC;CACxB;AAoBD;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,cAAc,CAAS;gBAEnB,MAAM,EAAE,kBAAkB;IActC;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,cAAc,EAAE,oBAAoB,GAAG,IAAI;IA0BzE;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAc/B;;OAEG;IACG,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpD;;OAEG;IACH,OAAO,CAAC,cAAc;IA8DtB;;OAEG;IACH,OAAO,CAAC,SAAS;IA2BjB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;OAEG;IACH,OAAO,CAAC,KAAK;IAeb;;OAEG;YACW,UAAU;IAiBxB;;OAEG;YACW,UAAU;CA8BzB"}
package/dist/otel.js ADDED
@@ -0,0 +1,249 @@
1
+ /**
2
+ * OpenTelemetry Span Exporter for Metrx
3
+ *
4
+ * Exports LLM-related spans to Metrx's event ingestion API.
5
+ * Uses duck typing to avoid @opentelemetry dependencies (zero-dependency SDK).
6
+ */
7
+ /**
8
+ * Export result status codes
9
+ */
10
+ var ExportResultCode;
11
+ (function (ExportResultCode) {
12
+ ExportResultCode[ExportResultCode["SUCCESS"] = 0] = "SUCCESS";
13
+ ExportResultCode[ExportResultCode["FAILED"] = 1] = "FAILED";
14
+ })(ExportResultCode || (ExportResultCode = {}));
15
+ /**
16
+ * OpenTelemetry Span Exporter for Metrx
17
+ *
18
+ * Filters LLM-related spans from OpenTelemetry SDK and exports them
19
+ * to Metrx's event ingestion API.
20
+ */
21
+ export class MetrxbotSpanExporter {
22
+ apiKey;
23
+ gatewayUrl;
24
+ agentId;
25
+ batchSize;
26
+ flushIntervalMs;
27
+ buffer = [];
28
+ flushTimer;
29
+ isShuttingDown = false;
30
+ constructor(config) {
31
+ if (!config.apiKey) {
32
+ throw new Error('apiKey is required');
33
+ }
34
+ this.apiKey = config.apiKey;
35
+ this.gatewayUrl = config.gatewayUrl || 'https://gateway.metrxbot.com';
36
+ this.agentId = config.agentId;
37
+ this.batchSize = config.batchSize ?? 50;
38
+ this.flushIntervalMs = config.flushIntervalMs ?? 5000;
39
+ this.startFlushTimer();
40
+ }
41
+ /**
42
+ * Export spans from OpenTelemetry SDK
43
+ */
44
+ export(spans, resultCallback) {
45
+ if (this.isShuttingDown) {
46
+ resultCallback({ code: ExportResultCode.FAILED });
47
+ return;
48
+ }
49
+ try {
50
+ for (const span of spans) {
51
+ const event = this.spanToLLMEvent(span);
52
+ if (event) {
53
+ this.buffer.push(event);
54
+ // Flush if batch size reached
55
+ if (this.buffer.length >= this.batchSize) {
56
+ this.flush();
57
+ }
58
+ }
59
+ }
60
+ resultCallback({ code: ExportResultCode.SUCCESS });
61
+ }
62
+ catch (error) {
63
+ console.error('Error exporting spans to Metrx:', error);
64
+ resultCallback({ code: ExportResultCode.FAILED });
65
+ }
66
+ }
67
+ /**
68
+ * Shutdown exporter and flush remaining spans
69
+ */
70
+ async shutdown() {
71
+ this.isShuttingDown = true;
72
+ // Clear flush timer
73
+ if (this.flushTimer) {
74
+ clearInterval(this.flushTimer);
75
+ }
76
+ // Flush remaining spans
77
+ if (this.buffer.length > 0) {
78
+ await this.flushAsync();
79
+ }
80
+ }
81
+ /**
82
+ * Force flush buffered spans immediately
83
+ */
84
+ async forceFlush(_timeoutMs) {
85
+ if (this.buffer.length > 0) {
86
+ await this.flushAsync();
87
+ }
88
+ }
89
+ /**
90
+ * Convert an OpenTelemetry span to an LLM event
91
+ */
92
+ spanToLLMEvent(span) {
93
+ // Check if this is an LLM-related span
94
+ if (!this.isLLMSpan(span)) {
95
+ return null;
96
+ }
97
+ const attributes = span.attributes || {};
98
+ const spanContext = span.spanContext();
99
+ // Extract model - check multiple conventions
100
+ const model = attributes['llm.model'] || attributes['gen_ai.request.model'] || 'unknown';
101
+ // Extract provider - check multiple conventions
102
+ const provider = attributes['llm.provider'] || attributes['gen_ai.system'];
103
+ // Extract token counts - check multiple conventions
104
+ const inputTokens = attributes['llm.usage.prompt_tokens'] || attributes['gen_ai.usage.input_tokens'];
105
+ const outputTokens = attributes['llm.usage.completion_tokens'] || attributes['gen_ai.usage.output_tokens'];
106
+ // Extract cost if available
107
+ const costMicrocents = attributes['llm.cost'];
108
+ // Calculate latency in milliseconds
109
+ const latencyMs = this.calculateLatencyMs(span);
110
+ // Build event
111
+ const event = {
112
+ model,
113
+ latency_ms: latencyMs,
114
+ timestamp: new Date().toISOString(),
115
+ span_name: span.name,
116
+ trace_id: spanContext.traceId,
117
+ span_id: spanContext.spanId,
118
+ };
119
+ // Add optional fields
120
+ if (this.agentId) {
121
+ event.agent_id = this.agentId;
122
+ }
123
+ if (provider) {
124
+ event.provider = provider;
125
+ }
126
+ if (typeof inputTokens === 'number') {
127
+ event.input_tokens = inputTokens;
128
+ }
129
+ if (typeof outputTokens === 'number') {
130
+ event.output_tokens = outputTokens;
131
+ }
132
+ if (typeof costMicrocents === 'number') {
133
+ event.cost_microcents = costMicrocents;
134
+ }
135
+ return event;
136
+ }
137
+ /**
138
+ * Check if a span is LLM-related
139
+ */
140
+ isLLMSpan(span) {
141
+ const spanName = span.name.toLowerCase();
142
+ const attributes = span.attributes || {};
143
+ // Check span name for LLM keywords
144
+ const llmKeywords = ['chat', 'completion', 'embedding', 'llm'];
145
+ if (llmKeywords.some((keyword) => spanName.includes(keyword))) {
146
+ return true;
147
+ }
148
+ // Check for OpenTelemetry semantic conventions
149
+ if (attributes['gen_ai.system']) {
150
+ return true;
151
+ }
152
+ // Check for other LLM-related attributes
153
+ if (attributes['llm.model'] ||
154
+ attributes['llm.provider'] ||
155
+ attributes['gen_ai.request.model']) {
156
+ return true;
157
+ }
158
+ return false;
159
+ }
160
+ /**
161
+ * Calculate latency in milliseconds from span timing
162
+ */
163
+ calculateLatencyMs(span) {
164
+ const startTime = span.startTime;
165
+ const endTime = span.endTime;
166
+ // Convert [seconds, nanoseconds] to milliseconds
167
+ const startMs = startTime[0] * 1000 + startTime[1] / 1000000;
168
+ const endMs = endTime[0] * 1000 + endTime[1] / 1000000;
169
+ return Math.round(endMs - startMs);
170
+ }
171
+ /**
172
+ * Start periodic flush timer
173
+ */
174
+ startFlushTimer() {
175
+ this.flushTimer = setInterval(() => {
176
+ if (this.buffer.length > 0) {
177
+ this.flush();
178
+ }
179
+ }, this.flushIntervalMs);
180
+ // Allow timer to not block process exit
181
+ if (this.flushTimer.unref) {
182
+ this.flushTimer.unref();
183
+ }
184
+ }
185
+ /**
186
+ * Flush buffered spans synchronously (best effort)
187
+ */
188
+ flush() {
189
+ if (this.buffer.length === 0) {
190
+ return;
191
+ }
192
+ const events = this.buffer.splice(0, this.batchSize);
193
+ // Fire and forget - don't block on network
194
+ this.sendEvents(events).catch((error) => {
195
+ console.error('Failed to send events to Metrx:', error);
196
+ // Re-add failed events to buffer for retry
197
+ this.buffer.unshift(...events);
198
+ });
199
+ }
200
+ /**
201
+ * Flush buffered spans asynchronously
202
+ */
203
+ async flushAsync() {
204
+ if (this.buffer.length === 0) {
205
+ return;
206
+ }
207
+ const events = this.buffer.splice(0, this.batchSize);
208
+ try {
209
+ await this.sendEvents(events);
210
+ }
211
+ catch (error) {
212
+ console.error('Failed to send events to Metrx:', error);
213
+ // Re-add failed events to buffer for retry
214
+ this.buffer.unshift(...events);
215
+ throw error;
216
+ }
217
+ }
218
+ /**
219
+ * Send events to Metrx API
220
+ */
221
+ async sendEvents(events) {
222
+ if (events.length === 0) {
223
+ return;
224
+ }
225
+ const url = `${this.gatewayUrl}/api/events/ingest`;
226
+ const response = await fetch(url, {
227
+ method: 'POST',
228
+ headers: {
229
+ 'Content-Type': 'application/json',
230
+ Authorization: `Bearer ${this.apiKey}`,
231
+ },
232
+ body: JSON.stringify({ events }),
233
+ });
234
+ if (!response.ok) {
235
+ let errorMessage = `HTTP ${response.status}`;
236
+ try {
237
+ const errorData = (await response.json());
238
+ if (errorData.error?.message) {
239
+ errorMessage = errorData.error.message;
240
+ }
241
+ }
242
+ catch {
243
+ // Ignore JSON parse errors
244
+ }
245
+ throw new Error(`Failed to send events to Metrx: ${errorMessage}`);
246
+ }
247
+ }
248
+ }
249
+ //# sourceMappingURL=otel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel.js","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Metrx SDK Type Definitions
3
+ */
4
+ export interface MetrxbotConfig {
5
+ /** Metrx API key for authentication */
6
+ apiKey: string;
7
+ /** Gateway URL (default: https://gateway.metrxbot.com) */
8
+ gatewayUrl?: string;
9
+ /** Default agent ID for all requests */
10
+ defaultAgentId?: string;
11
+ /** Default LLM provider (openai, anthropic, etc.) */
12
+ defaultProvider?: string;
13
+ /** Request timeout in milliseconds (default: 30000) */
14
+ timeout?: number;
15
+ }
16
+ export interface MetrxbotMeta {
17
+ /** Gateway response latency in milliseconds */
18
+ latencyMs: number;
19
+ /** Cost of the request in microcents */
20
+ costMicrocents: number;
21
+ /** X-Request-ID header from gateway */
22
+ requestId?: string;
23
+ }
24
+ export interface RequestOptions {
25
+ /** Override agent ID for this request */
26
+ agentId?: string;
27
+ /** Customer/end-user ID for tracking */
28
+ customerId?: string;
29
+ /** Session ID for tracking */
30
+ sessionId?: string;
31
+ /** Provider API key override */
32
+ providerKey?: string;
33
+ /** Force specific provider */
34
+ provider?: string;
35
+ }
36
+ export interface ChatCompletionParams extends RequestOptions {
37
+ model: string;
38
+ messages: ChatMessage[];
39
+ temperature?: number;
40
+ top_p?: number;
41
+ max_tokens?: number;
42
+ stop?: string | string[];
43
+ stream?: boolean;
44
+ [key: string]: unknown;
45
+ }
46
+ export interface ChatMessage {
47
+ role: 'system' | 'user' | 'assistant';
48
+ content: string;
49
+ }
50
+ export interface ChatCompletionResponse {
51
+ id: string;
52
+ object: string;
53
+ created: number;
54
+ model: string;
55
+ choices: ChatChoice[];
56
+ usage?: {
57
+ prompt_tokens: number;
58
+ completion_tokens: number;
59
+ total_tokens: number;
60
+ };
61
+ _meta: MetrxbotMeta;
62
+ }
63
+ export interface ChatChoice {
64
+ index: number;
65
+ message: ChatMessage;
66
+ finish_reason: string;
67
+ logprobs?: unknown;
68
+ }
69
+ export interface StreamChunk {
70
+ id?: string;
71
+ object?: string;
72
+ created?: number;
73
+ model?: string;
74
+ choices?: StreamChoice[];
75
+ _meta?: MetrxbotMeta;
76
+ }
77
+ export interface StreamChoice {
78
+ index: number;
79
+ delta: {
80
+ role?: string;
81
+ content?: string;
82
+ };
83
+ finish_reason?: string;
84
+ }
85
+ export interface MessagesParams extends RequestOptions {
86
+ model: string;
87
+ messages: AnthropicMessage[];
88
+ max_tokens: number;
89
+ system?: string;
90
+ temperature?: number;
91
+ top_p?: number;
92
+ [key: string]: unknown;
93
+ }
94
+ export interface AnthropicMessage {
95
+ role: 'user' | 'assistant';
96
+ content: string | AnthropicContent[];
97
+ }
98
+ export interface AnthropicContent {
99
+ type: 'text' | 'image';
100
+ text?: string;
101
+ source?: {
102
+ type: 'base64' | 'url';
103
+ media_type?: string;
104
+ data?: string;
105
+ url?: string;
106
+ };
107
+ }
108
+ export interface MessagesResponse {
109
+ id: string;
110
+ type: string;
111
+ role: string;
112
+ content: MessageContent[];
113
+ model: string;
114
+ stop_reason: string;
115
+ stop_sequence?: string;
116
+ usage?: {
117
+ input_tokens: number;
118
+ output_tokens: number;
119
+ };
120
+ _meta: MetrxbotMeta;
121
+ }
122
+ export interface MessageContent {
123
+ type: 'text';
124
+ text: string;
125
+ }
126
+ export interface EmbeddingsParams extends RequestOptions {
127
+ model: string;
128
+ input: string | string[];
129
+ encoding_format?: 'float' | 'base64';
130
+ }
131
+ export interface EmbeddingsResponse {
132
+ object: string;
133
+ data: Embedding[];
134
+ model: string;
135
+ usage: {
136
+ prompt_tokens: number;
137
+ total_tokens: number;
138
+ };
139
+ _meta: MetrxbotMeta;
140
+ }
141
+ export interface Embedding {
142
+ object: string;
143
+ embedding: number[];
144
+ index: number;
145
+ }
146
+ export interface HealthResponse {
147
+ status: 'ok' | 'degraded' | 'error';
148
+ timestamp: string;
149
+ version: string;
150
+ }
151
+ export interface ModelsResponse {
152
+ object: 'list';
153
+ data: Model[];
154
+ }
155
+ export interface Model {
156
+ id: string;
157
+ object: 'model';
158
+ owned_by: string;
159
+ permission?: unknown[];
160
+ }
161
+ export interface APIError {
162
+ message: string;
163
+ type: string;
164
+ param?: string;
165
+ code?: string;
166
+ }
167
+ export interface OtelExporterConfig {
168
+ /** Metrx API key for authentication */
169
+ apiKey: string;
170
+ /** Gateway URL (default: https://gateway.metrxbot.com) */
171
+ gatewayUrl?: string;
172
+ /** Agent ID for tracking LLM calls */
173
+ agentId?: string;
174
+ /** Batch size before forcing export (default: 50) */
175
+ batchSize?: number;
176
+ /** Flush interval in milliseconds (default: 5000) */
177
+ flushIntervalMs?: number;
178
+ }
179
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IAEf,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,wCAAwC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAElB,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;IAEvB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAID,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,IAAI,GAAG,UAAU,GAAG,OAAO,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,EAAE,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;CACxB;AAID,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IAEf,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Metrx SDK Type Definitions
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@metrxbot/sdk",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for integrating with Metrx gateway",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest",
15
+ "clean": "rm -rf dist"
16
+ },
17
+ "keywords": [
18
+ "metrx",
19
+ "llm",
20
+ "sdk",
21
+ "openai",
22
+ "anthropic"
23
+ ],
24
+ "author": "Metrx",
25
+ "license": "MIT",
26
+ "devDependencies": {
27
+ "typescript": "^5.0.0",
28
+ "vitest": "^1.0.0"
29
+ },
30
+ "engines": {
31
+ "node": ">=18.0.0"
32
+ }
33
+ }