@coalex-ai/sdk 0.4.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Coalex.ai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,263 @@
1
+ # Coalex SDK for TypeScript
2
+
3
+ A TypeScript package for OpenTelemetry integration with Coalex.ai observability platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @coalex-ai/sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { register, coalexContext } from '@coalex-ai/sdk';
15
+
16
+ // Register Coalex tracing
17
+ const tracerProvider = register({
18
+ agentId: 'YOUR_AGENT_ID'
19
+ });
20
+
21
+ // Use coalexContext for proper span management and attribute propagation
22
+ await coalexContext(
23
+ {
24
+ requestId: 'req_001',
25
+ promptVersion: 'v1.0.0'
26
+ },
27
+ async () => {
28
+ // Your instrumented code here
29
+ // Any OpenTelemetry instrumented calls will be traced with proper context
30
+ const result = await someApiCall();
31
+ return result;
32
+ }
33
+ );
34
+ ```
35
+
36
+ ## Features
37
+
38
+ - **Simple Setup**: One-line registration with `register()`
39
+ - **Coalex Integration**: Default endpoint for Coalex observability platform
40
+ - **Context Management**: Use `coalexContext()` for proper span hierarchy and attribute propagation
41
+ - **OpenTelemetry Compatible**: Works with all OpenTelemetry instrumentations
42
+ - **Authentication**: Automatic authentication using agent_id
43
+ - **Human-in-the-Loop**: Approval workflow for human review
44
+ - **Metrics Tracking**: Submit and track performance metrics
45
+
46
+ ## Configuration
47
+
48
+ ### Register
49
+
50
+ ```typescript
51
+ import { register } from '@coalex/sdk';
52
+
53
+ const tracerProvider = register({
54
+ agentId: 'YOUR_AGENT_ID', // Required: Your unique agent identifier
55
+ endpoint: 'https://custom-endpoint', // Optional: Custom OTLP endpoint
56
+ serviceName: 'my-service', // Optional: Service name (default: 'coalex-service')
57
+ serviceVersion: '1.0.0', // Optional: Service version
58
+ additionalAttributes: { // Optional: Additional resource attributes
59
+ environment: 'production'
60
+ }
61
+ });
62
+ ```
63
+
64
+ ## API Reference
65
+
66
+ ### Tracing
67
+
68
+ #### `register(options: RegisterOptions)`
69
+
70
+ Register Coalex OpenTelemetry tracing with the Coalex platform.
71
+
72
+ **Parameters:**
73
+ - `agentId` (required): Your unique agent identifier for authentication
74
+ - `endpoint` (optional): OTLP endpoint URL (defaults to `https://traces.coalex.ai/v1/traces`)
75
+ - `serviceName` (optional): Name of your service (defaults to `'coalex-service'`)
76
+ - `serviceVersion` (optional): Version of your service (defaults to `'0.1.0'`)
77
+ - `additionalAttributes` (optional): Additional resource attributes to include
78
+
79
+ **Returns:** `NodeTracerProvider` - The configured tracer provider
80
+
81
+ #### `coalexContext(options, fn)`
82
+
83
+ Execute a function within a Coalex context that ensures attributes are propagated to child spans.
84
+
85
+ **Parameters:**
86
+ - `options.requestId` (required): Unique request identifier
87
+ - `options.promptVersion` (required): Version of the prompt being used
88
+ - `options.spanName` (optional): Name for the context span (defaults to `'coalex_operation'`)
89
+ - `fn`: The async function to execute within the context
90
+
91
+ **Returns:** `Promise<T>` - Promise that resolves with the function result
92
+
93
+ **Example:**
94
+ ```typescript
95
+ await coalexContext(
96
+ {
97
+ requestId: 'req_12345',
98
+ promptVersion: 'v2.0.0'
99
+ },
100
+ async () => {
101
+ // Your code here
102
+ return await someOperation();
103
+ }
104
+ );
105
+ ```
106
+
107
+ #### `coalexContextSync(options, fn)`
108
+
109
+ Synchronous version of `coalexContext` for non-async operations.
110
+
111
+ **Example:**
112
+ ```typescript
113
+ const result = coalexContextSync(
114
+ {
115
+ requestId: 'req_12345',
116
+ promptVersion: 'v2.0.0'
117
+ },
118
+ () => {
119
+ // Your synchronous code here
120
+ return someValue;
121
+ }
122
+ );
123
+ ```
124
+
125
+ #### `addRequestContext(requestId, promptVersion)`
126
+
127
+ Add request context to the current active span. For better attribute propagation, consider using `coalexContext()` instead.
128
+
129
+ ### Approval
130
+
131
+ #### `approve(options: ApproveOptions)`
132
+
133
+ Submit an approval request for human-in-the-loop review.
134
+
135
+ **Parameters:**
136
+ - `requestId` (required): Unique identifier for this approval request
137
+ - `inputData` (optional): Input data provided to your AI system
138
+ - `outputData` (optional): Output data generated by your AI system
139
+ - `version` (optional): Version of your prompt/model (defaults to `'1.0.0'`)
140
+ - `slaSeconds` (optional): SLA in seconds for human review (defaults to 3600)
141
+ - `agentId` (optional): Agent ID for authentication (auto-detected if not provided)
142
+ - `urlParams` (optional): Additional URL parameters for the review interface
143
+ - `eval` (optional): Evaluation control - string (use provided eval_id), true (generate eval_id), false/null (skip eval)
144
+ - `endpoint` (optional): Creator service endpoint
145
+
146
+ **Returns:** `Promise<ApprovalResponse>` - The approval response
147
+
148
+ **Example:**
149
+ ```typescript
150
+ import { approve } from '@coalex/sdk';
151
+
152
+ const response = await approve({
153
+ requestId: 'req_12345',
154
+ inputData: { userQuery: 'What is the weather?' },
155
+ outputData: { response: "It's sunny today" },
156
+ version: 'v1.2.0'
157
+ });
158
+
159
+ console.log(`Approval task created: ${response.taskId}`);
160
+ console.log(`Status: ${response.status}`);
161
+
162
+ if (response.isAutoApproved) {
163
+ console.log('Request was auto-approved');
164
+ } else if (response.needsHumanReview) {
165
+ console.log('Request needs human review');
166
+ }
167
+ ```
168
+
169
+ ### Metrics
170
+
171
+ #### `submitMetric(options: SubmitMetricOptions)`
172
+
173
+ Submit a metric for performance tracking and monitoring.
174
+
175
+ **Parameters:**
176
+ - `requestId` (required): Unique identifier for the request that generated this metric
177
+ - `metricId` (required): Identifier for the type/name of metric
178
+ - `value` (required): Numeric value for the metric
179
+ - `metricType` (optional): Type category of the metric (e.g., "precision", "recall")
180
+ - `metadata` (optional): Additional contextual data for the metric
181
+ - `agentId` (optional): Agent ID for authentication (auto-detected if not provided)
182
+ - `reviewingAgentId` (optional): ID of agent that reviewed/validated this metric
183
+ - `taskId` (optional): Associated task identifier if applicable
184
+ - `endpoint` (optional): Creator service endpoint
185
+
186
+ **Returns:** `Promise<MetricResponse>` - The metric response
187
+
188
+ **Example:**
189
+ ```typescript
190
+ import { submitMetric } from '@coalex/sdk';
191
+
192
+ const response = await submitMetric({
193
+ requestId: 'req_12345',
194
+ metricId: 'model_precision',
195
+ value: 0.92,
196
+ metricType: 'precision',
197
+ metadata: {
198
+ modelVersion: 'v2.1.0',
199
+ dataset: 'test_set_v1'
200
+ }
201
+ });
202
+
203
+ console.log(`Metric stored with ID: ${response.id}`);
204
+ ```
205
+
206
+ ## Complete Example
207
+
208
+ ```typescript
209
+ import { register, coalexContext, approve, submitMetric } from '@coalex-ai/sdk';
210
+
211
+ // 1. Register tracing
212
+ register({
213
+ agentId: 'YOUR_AGENT_ID',
214
+ serviceName: 'my-ai-service'
215
+ });
216
+
217
+ // 2. Use context for traced operations
218
+ await coalexContext(
219
+ {
220
+ requestId: 'req_001',
221
+ promptVersion: 'v1.0.0'
222
+ },
223
+ async () => {
224
+ // Your AI/LLM operations here
225
+ const result = await generateResponse('What is AI?');
226
+
227
+ // 3. Submit for approval
228
+ const approval = await approve({
229
+ requestId: 'req_001',
230
+ inputData: { query: 'What is AI?' },
231
+ outputData: { response: result },
232
+ version: 'v1.0.0'
233
+ });
234
+
235
+ // 4. Submit metrics
236
+ if (approval.isAutoApproved) {
237
+ await submitMetric({
238
+ requestId: 'req_001',
239
+ metricId: 'auto_approval_rate',
240
+ value: 1.0,
241
+ metricType: 'rate'
242
+ });
243
+ }
244
+
245
+ return result;
246
+ }
247
+ );
248
+ ```
249
+
250
+ ## TypeScript Support
251
+
252
+ This package is written in TypeScript and includes full type definitions. All functions and classes are fully typed for an excellent development experience.
253
+
254
+ ## License
255
+
256
+ MIT
257
+
258
+ ## Links
259
+
260
+ - [Homepage](https://coalex.ai)
261
+ - [Documentation](https://docs.coalex.ai)
262
+ - [GitHub](https://github.com/coalex-ai/coalex-ts)
263
+ - [PyPI (Python version)](https://pypi.org/project/coalex/)
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Coalex approval functionality for human-in-the-loop workflows.
3
+ */
4
+ export interface ApprovalRequestData {
5
+ requestId: string;
6
+ inputData?: Record<string, any>;
7
+ outputData?: Record<string, any>;
8
+ version?: string;
9
+ slaSeconds?: number;
10
+ agentId?: string;
11
+ urlParams?: Record<string, any>;
12
+ eval?: string | boolean;
13
+ }
14
+ export interface ApprovalResponseData {
15
+ taskId: string;
16
+ requestId: string;
17
+ status: string;
18
+ slaTimestamp: Date;
19
+ evalId?: string;
20
+ tunedOutputData?: Record<string, any>;
21
+ }
22
+ /**
23
+ * Request object for approval tasks.
24
+ */
25
+ export declare class ApprovalRequest {
26
+ requestId: string;
27
+ inputData: Record<string, any>;
28
+ outputData: Record<string, any>;
29
+ version: string;
30
+ slaSeconds: number;
31
+ agentId?: string;
32
+ urlParams: Record<string, any>;
33
+ eval?: string | boolean;
34
+ constructor(data: ApprovalRequestData);
35
+ }
36
+ /**
37
+ * Response object for approval requests.
38
+ */
39
+ export declare class ApprovalResponse {
40
+ taskId: string;
41
+ requestId: string;
42
+ status: string;
43
+ slaTimestamp: Date;
44
+ evalId?: string;
45
+ tunedOutputData?: Record<string, any>;
46
+ constructor(data: ApprovalResponseData);
47
+ /**
48
+ * Check if this request was auto-approved.
49
+ */
50
+ get isAutoApproved(): boolean;
51
+ /**
52
+ * Check if this request needs human review.
53
+ */
54
+ get needsHumanReview(): boolean;
55
+ }
56
+ export interface ApproveOptions {
57
+ requestId: string;
58
+ inputData?: Record<string, any>;
59
+ outputData?: Record<string, any>;
60
+ version?: string;
61
+ slaSeconds?: number;
62
+ agentId?: string;
63
+ urlParams?: Record<string, any>;
64
+ eval?: string | boolean;
65
+ endpoint?: string;
66
+ }
67
+ /**
68
+ * Submit an approval request for human-in-the-loop review.
69
+ *
70
+ * This function sends a request to the coalex-ai-creator service to create
71
+ * an approval task that will be handled by a human reviewer.
72
+ *
73
+ * @param options - Approval request options
74
+ * @returns Promise that resolves to ApprovalResponse
75
+ * @throws Error if required parameters are missing or the request fails
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * import { register, approve } from '@coalex/sdk';
80
+ *
81
+ * // Register coalex first
82
+ * register({ agentId: 'your-agent-id' });
83
+ *
84
+ * // Submit approval request
85
+ * const response = await approve({
86
+ * requestId: 'req_12345',
87
+ * inputData: { userQuery: 'What is the weather?' },
88
+ * outputData: { response: "It's sunny today" },
89
+ * version: 'v1.2.0'
90
+ * });
91
+ *
92
+ * console.log(`Approval task created: ${response.taskId}`);
93
+ * ```
94
+ */
95
+ export declare function approve(options: ApproveOptions): Promise<ApprovalResponse>;
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ /**
3
+ * Coalex approval functionality for human-in-the-loop workflows.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ApprovalResponse = exports.ApprovalRequest = void 0;
7
+ exports.approve = approve;
8
+ const api_1 = require("@opentelemetry/api");
9
+ const DEFAULT_CREATOR_ENDPOINT = 'https://creator.coalex.ai';
10
+ /**
11
+ * Request object for approval tasks.
12
+ */
13
+ class ApprovalRequest {
14
+ constructor(data) {
15
+ this.requestId = data.requestId;
16
+ this.inputData = data.inputData || {};
17
+ this.outputData = data.outputData || {};
18
+ this.version = data.version || '1.0.0';
19
+ this.slaSeconds = data.slaSeconds || 3600;
20
+ this.agentId = data.agentId;
21
+ this.urlParams = data.urlParams || {};
22
+ this.eval = data.eval;
23
+ }
24
+ }
25
+ exports.ApprovalRequest = ApprovalRequest;
26
+ /**
27
+ * Response object for approval requests.
28
+ */
29
+ class ApprovalResponse {
30
+ constructor(data) {
31
+ this.taskId = data.taskId;
32
+ this.requestId = data.requestId;
33
+ this.status = data.status;
34
+ this.slaTimestamp = data.slaTimestamp;
35
+ this.evalId = data.evalId;
36
+ this.tunedOutputData = data.tunedOutputData;
37
+ }
38
+ /**
39
+ * Check if this request was auto-approved.
40
+ */
41
+ get isAutoApproved() {
42
+ return this.status === 'auto_approved';
43
+ }
44
+ /**
45
+ * Check if this request needs human review.
46
+ */
47
+ get needsHumanReview() {
48
+ return this.status === 'pending';
49
+ }
50
+ }
51
+ exports.ApprovalResponse = ApprovalResponse;
52
+ /**
53
+ * Extract agent_id from the current tracer provider's resource.
54
+ */
55
+ function getAgentIdFromTracer() {
56
+ try {
57
+ const tracerProvider = api_1.trace.getTracerProvider();
58
+ if (tracerProvider && tracerProvider.resource) {
59
+ const attributes = tracerProvider.resource.attributes;
60
+ return attributes['coalex.agent_id'];
61
+ }
62
+ }
63
+ catch (error) {
64
+ console.warn('Failed to get agent_id from tracer:', error);
65
+ }
66
+ return undefined;
67
+ }
68
+ /**
69
+ * Submit an approval request for human-in-the-loop review.
70
+ *
71
+ * This function sends a request to the coalex-ai-creator service to create
72
+ * an approval task that will be handled by a human reviewer.
73
+ *
74
+ * @param options - Approval request options
75
+ * @returns Promise that resolves to ApprovalResponse
76
+ * @throws Error if required parameters are missing or the request fails
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * import { register, approve } from '@coalex/sdk';
81
+ *
82
+ * // Register coalex first
83
+ * register({ agentId: 'your-agent-id' });
84
+ *
85
+ * // Submit approval request
86
+ * const response = await approve({
87
+ * requestId: 'req_12345',
88
+ * inputData: { userQuery: 'What is the weather?' },
89
+ * outputData: { response: "It's sunny today" },
90
+ * version: 'v1.2.0'
91
+ * });
92
+ *
93
+ * console.log(`Approval task created: ${response.taskId}`);
94
+ * ```
95
+ */
96
+ async function approve(options) {
97
+ const { requestId, inputData, outputData, version = '1.0.0', slaSeconds = 3600, urlParams, eval: evalOption, endpoint = DEFAULT_CREATOR_ENDPOINT } = options;
98
+ if (!requestId) {
99
+ throw new Error('requestId is required');
100
+ }
101
+ // Auto-detect agent_id from tracer if not provided
102
+ let agentId = options.agentId;
103
+ if (!agentId) {
104
+ agentId = getAgentIdFromTracer();
105
+ if (!agentId) {
106
+ throw new Error('agentId is required. Either pass it explicitly or ensure register() was called first.');
107
+ }
108
+ }
109
+ // Create approval request
110
+ const approvalRequest = new ApprovalRequest({
111
+ requestId,
112
+ inputData,
113
+ outputData,
114
+ version,
115
+ slaSeconds,
116
+ agentId,
117
+ urlParams,
118
+ eval: evalOption
119
+ });
120
+ // Prepare request payload
121
+ const payload = {
122
+ request_id: approvalRequest.requestId,
123
+ input_data: approvalRequest.inputData,
124
+ output_data: approvalRequest.outputData,
125
+ version: approvalRequest.version,
126
+ sla_seconds: approvalRequest.slaSeconds,
127
+ agent_id: approvalRequest.agentId,
128
+ url_params: approvalRequest.urlParams,
129
+ eval: approvalRequest.eval
130
+ };
131
+ // Prepare headers for authentication
132
+ const headers = {
133
+ 'Authorization': `Bearer ${agentId}`,
134
+ 'Content-Type': 'application/json'
135
+ };
136
+ // Build URL
137
+ const url = `${endpoint}/approve`;
138
+ console.log(`Submitting approval request ${requestId} for agent ${agentId}`);
139
+ try {
140
+ // Make HTTP request
141
+ const response = await fetch(url, {
142
+ method: 'POST',
143
+ headers,
144
+ body: JSON.stringify(payload)
145
+ });
146
+ // Check response status
147
+ if (!response.ok) {
148
+ const errorText = await response.text();
149
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
150
+ }
151
+ // Parse response
152
+ const responseData = await response.json();
153
+ // Convert sla_timestamp string to Date
154
+ const slaTimestamp = new Date(responseData.sla_timestamp);
155
+ const approvalResponse = new ApprovalResponse({
156
+ taskId: responseData.task_id,
157
+ requestId: responseData.request_id,
158
+ status: responseData.status,
159
+ slaTimestamp,
160
+ evalId: responseData.eval_id,
161
+ tunedOutputData: responseData.tuned_output_data
162
+ });
163
+ console.log(`Approval request ${requestId} submitted successfully. Task ID: ${approvalResponse.taskId}`);
164
+ return approvalResponse;
165
+ }
166
+ catch (error) {
167
+ console.error(`Failed to submit approval request ${requestId}:`, error);
168
+ throw error;
169
+ }
170
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Coalex SDK for observability and monitoring.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { register, addRequestContext, coalexContext, coalexContextSync, RegisterOptions, CoalexContextOptions } from './otel/register';
7
+ export { approve, ApprovalRequest, ApprovalResponse, ApprovalRequestData, ApprovalResponseData, ApproveOptions } from './approve';
8
+ export { submitMetric, MetricRequest, MetricResponse, MetricRequestData, MetricResponseData, SubmitMetricOptions } from './metrics';
9
+ export declare const VERSION = "0.4.1";
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ /**
3
+ * Coalex SDK for observability and monitoring.
4
+ *
5
+ * @packageDocumentation
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.VERSION = exports.MetricResponse = exports.MetricRequest = exports.submitMetric = exports.ApprovalResponse = exports.ApprovalRequest = exports.approve = exports.coalexContextSync = exports.coalexContext = exports.addRequestContext = exports.register = void 0;
9
+ // OpenTelemetry registration and context
10
+ var register_1 = require("./otel/register");
11
+ Object.defineProperty(exports, "register", { enumerable: true, get: function () { return register_1.register; } });
12
+ Object.defineProperty(exports, "addRequestContext", { enumerable: true, get: function () { return register_1.addRequestContext; } });
13
+ Object.defineProperty(exports, "coalexContext", { enumerable: true, get: function () { return register_1.coalexContext; } });
14
+ Object.defineProperty(exports, "coalexContextSync", { enumerable: true, get: function () { return register_1.coalexContextSync; } });
15
+ // Approval functionality
16
+ var approve_1 = require("./approve");
17
+ Object.defineProperty(exports, "approve", { enumerable: true, get: function () { return approve_1.approve; } });
18
+ Object.defineProperty(exports, "ApprovalRequest", { enumerable: true, get: function () { return approve_1.ApprovalRequest; } });
19
+ Object.defineProperty(exports, "ApprovalResponse", { enumerable: true, get: function () { return approve_1.ApprovalResponse; } });
20
+ // Metrics functionality
21
+ var metrics_1 = require("./metrics");
22
+ Object.defineProperty(exports, "submitMetric", { enumerable: true, get: function () { return metrics_1.submitMetric; } });
23
+ Object.defineProperty(exports, "MetricRequest", { enumerable: true, get: function () { return metrics_1.MetricRequest; } });
24
+ Object.defineProperty(exports, "MetricResponse", { enumerable: true, get: function () { return metrics_1.MetricResponse; } });
25
+ // Version
26
+ exports.VERSION = '0.4.1';
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Coalex metrics functionality for performance tracking and monitoring.
3
+ */
4
+ export interface MetricRequestData {
5
+ requestId: string;
6
+ metricId: string;
7
+ value: number;
8
+ metricType?: string;
9
+ metadata?: Record<string, any>;
10
+ agentId?: string;
11
+ reviewingAgentId?: string;
12
+ taskId?: string;
13
+ }
14
+ export interface MetricResponseData {
15
+ id: number;
16
+ agentId: string;
17
+ accountId: string;
18
+ requestId: string;
19
+ metricId: string;
20
+ metricType?: string;
21
+ value: number;
22
+ metadata: Record<string, any>;
23
+ reviewingAgentId?: string;
24
+ taskId?: string;
25
+ createdAt: Date;
26
+ }
27
+ /**
28
+ * Request object for metric submission.
29
+ */
30
+ export declare class MetricRequest {
31
+ requestId: string;
32
+ metricId: string;
33
+ value: number;
34
+ metricType?: string;
35
+ metadata: Record<string, any>;
36
+ agentId?: string;
37
+ reviewingAgentId?: string;
38
+ taskId?: string;
39
+ constructor(data: MetricRequestData);
40
+ }
41
+ /**
42
+ * Response object for metric submissions.
43
+ */
44
+ export declare class MetricResponse {
45
+ id: number;
46
+ agentId: string;
47
+ accountId: string;
48
+ requestId: string;
49
+ metricId: string;
50
+ metricType?: string;
51
+ value: number;
52
+ metadata: Record<string, any>;
53
+ reviewingAgentId?: string;
54
+ taskId?: string;
55
+ createdAt: Date;
56
+ constructor(data: MetricResponseData);
57
+ }
58
+ export interface SubmitMetricOptions {
59
+ requestId: string;
60
+ metricId: string;
61
+ value: number;
62
+ metricType?: string;
63
+ metadata?: Record<string, any>;
64
+ agentId?: string;
65
+ reviewingAgentId?: string;
66
+ taskId?: string;
67
+ endpoint?: string;
68
+ }
69
+ /**
70
+ * Submit a metric for performance tracking and monitoring.
71
+ *
72
+ * This function sends a metric to the coalex-ai-creator service to be stored
73
+ * and made available for analysis and reporting.
74
+ *
75
+ * @param options - Metric submission options
76
+ * @returns Promise that resolves to MetricResponse
77
+ * @throws Error if required parameters are missing or the request fails
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * import { register, submitMetric } from '@coalex/sdk';
82
+ *
83
+ * // Register coalex first
84
+ * register({ agentId: 'your-agent-id' });
85
+ *
86
+ * // Submit a precision metric
87
+ * const response = await submitMetric({
88
+ * requestId: 'req_12345',
89
+ * metricId: 'model_precision',
90
+ * value: 0.92,
91
+ * metricType: 'precision',
92
+ * metadata: {
93
+ * modelVersion: 'v2.1.0',
94
+ * dataset: 'test_set_v1'
95
+ * }
96
+ * });
97
+ *
98
+ * console.log(`Metric stored with ID: ${response.id}`);
99
+ * ```
100
+ */
101
+ export declare function submitMetric(options: SubmitMetricOptions): Promise<MetricResponse>;
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ /**
3
+ * Coalex metrics functionality for performance tracking and monitoring.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MetricResponse = exports.MetricRequest = void 0;
7
+ exports.submitMetric = submitMetric;
8
+ const api_1 = require("@opentelemetry/api");
9
+ const DEFAULT_CREATOR_ENDPOINT = 'https://creator.coalex.ai';
10
+ /**
11
+ * Request object for metric submission.
12
+ */
13
+ class MetricRequest {
14
+ constructor(data) {
15
+ this.requestId = data.requestId;
16
+ this.metricId = data.metricId;
17
+ this.value = data.value;
18
+ this.metricType = data.metricType;
19
+ this.metadata = data.metadata || {};
20
+ this.agentId = data.agentId;
21
+ this.reviewingAgentId = data.reviewingAgentId;
22
+ this.taskId = data.taskId;
23
+ }
24
+ }
25
+ exports.MetricRequest = MetricRequest;
26
+ /**
27
+ * Response object for metric submissions.
28
+ */
29
+ class MetricResponse {
30
+ constructor(data) {
31
+ this.id = data.id;
32
+ this.agentId = data.agentId;
33
+ this.accountId = data.accountId;
34
+ this.requestId = data.requestId;
35
+ this.metricId = data.metricId;
36
+ this.metricType = data.metricType;
37
+ this.value = data.value;
38
+ this.metadata = data.metadata;
39
+ this.reviewingAgentId = data.reviewingAgentId;
40
+ this.taskId = data.taskId;
41
+ this.createdAt = data.createdAt;
42
+ }
43
+ }
44
+ exports.MetricResponse = MetricResponse;
45
+ /**
46
+ * Extract agent_id from the current tracer provider's resource.
47
+ */
48
+ function getAgentIdFromTracer() {
49
+ try {
50
+ const tracerProvider = api_1.trace.getTracerProvider();
51
+ if (tracerProvider && tracerProvider.resource) {
52
+ const attributes = tracerProvider.resource.attributes;
53
+ return attributes['coalex.agent_id'];
54
+ }
55
+ }
56
+ catch (error) {
57
+ console.warn('Failed to get agent_id from tracer:', error);
58
+ }
59
+ return undefined;
60
+ }
61
+ /**
62
+ * Submit a metric for performance tracking and monitoring.
63
+ *
64
+ * This function sends a metric to the coalex-ai-creator service to be stored
65
+ * and made available for analysis and reporting.
66
+ *
67
+ * @param options - Metric submission options
68
+ * @returns Promise that resolves to MetricResponse
69
+ * @throws Error if required parameters are missing or the request fails
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * import { register, submitMetric } from '@coalex/sdk';
74
+ *
75
+ * // Register coalex first
76
+ * register({ agentId: 'your-agent-id' });
77
+ *
78
+ * // Submit a precision metric
79
+ * const response = await submitMetric({
80
+ * requestId: 'req_12345',
81
+ * metricId: 'model_precision',
82
+ * value: 0.92,
83
+ * metricType: 'precision',
84
+ * metadata: {
85
+ * modelVersion: 'v2.1.0',
86
+ * dataset: 'test_set_v1'
87
+ * }
88
+ * });
89
+ *
90
+ * console.log(`Metric stored with ID: ${response.id}`);
91
+ * ```
92
+ */
93
+ async function submitMetric(options) {
94
+ const { requestId, metricId, value, metricType, metadata, reviewingAgentId, taskId, endpoint = DEFAULT_CREATOR_ENDPOINT } = options;
95
+ if (!requestId) {
96
+ throw new Error('requestId is required');
97
+ }
98
+ if (!metricId) {
99
+ throw new Error('metricId is required');
100
+ }
101
+ if (value === null || value === undefined) {
102
+ throw new Error('value is required');
103
+ }
104
+ // Ensure value is a number
105
+ const numericValue = Number(value);
106
+ if (isNaN(numericValue)) {
107
+ throw new Error('value must be a numeric type');
108
+ }
109
+ // Auto-detect agent_id from tracer if not provided
110
+ let agentId = options.agentId;
111
+ if (!agentId) {
112
+ agentId = getAgentIdFromTracer();
113
+ if (!agentId) {
114
+ throw new Error('agentId is required. Either pass it explicitly or ensure register() was called first.');
115
+ }
116
+ }
117
+ // Create metric request
118
+ const metricRequest = new MetricRequest({
119
+ requestId,
120
+ metricId,
121
+ value: numericValue,
122
+ metricType,
123
+ metadata,
124
+ agentId,
125
+ reviewingAgentId,
126
+ taskId
127
+ });
128
+ // Prepare request payload
129
+ const payload = {
130
+ request_id: metricRequest.requestId,
131
+ metric_id: metricRequest.metricId,
132
+ value: metricRequest.value,
133
+ agent_id: metricRequest.agentId
134
+ };
135
+ // Add optional fields if provided
136
+ if (metricRequest.metricType) {
137
+ payload.metric_type = metricRequest.metricType;
138
+ }
139
+ if (metricRequest.metadata && Object.keys(metricRequest.metadata).length > 0) {
140
+ payload.metadata = metricRequest.metadata;
141
+ }
142
+ if (metricRequest.reviewingAgentId) {
143
+ payload.reviewing_agent_id = metricRequest.reviewingAgentId;
144
+ }
145
+ if (metricRequest.taskId) {
146
+ payload.task_id = metricRequest.taskId;
147
+ }
148
+ // Prepare headers for authentication
149
+ const headers = {
150
+ 'Authorization': `Bearer ${agentId}`,
151
+ 'Content-Type': 'application/json'
152
+ };
153
+ // Build URL
154
+ const url = `${endpoint}/metrics`;
155
+ console.log(`Submitting metric ${metricId} for request ${requestId} (agent: ${agentId})`);
156
+ try {
157
+ // Make HTTP request
158
+ const response = await fetch(url, {
159
+ method: 'POST',
160
+ headers,
161
+ body: JSON.stringify(payload)
162
+ });
163
+ // Check response status
164
+ if (!response.ok) {
165
+ const errorText = await response.text();
166
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
167
+ }
168
+ // Parse response
169
+ const responseData = await response.json();
170
+ // Parse created_at timestamp
171
+ const createdAt = new Date(responseData.created_at);
172
+ const metricResponse = new MetricResponse({
173
+ id: responseData.id,
174
+ agentId: responseData.agent_id,
175
+ accountId: responseData.account_id,
176
+ requestId: responseData.request_id,
177
+ metricId: responseData.metric_id,
178
+ metricType: responseData.metric_type,
179
+ value: responseData.value,
180
+ metadata: responseData.metadata || {},
181
+ reviewingAgentId: responseData.reviewing_agent_id,
182
+ taskId: responseData.task_id,
183
+ createdAt
184
+ });
185
+ console.log(`Metric ${metricId} submitted successfully. ID: ${metricResponse.id}`);
186
+ return metricResponse;
187
+ }
188
+ catch (error) {
189
+ console.error(`Failed to submit metric ${metricId} for request ${requestId}:`, error);
190
+ throw error;
191
+ }
192
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Coalex OpenTelemetry registration and setup.
3
+ */
4
+ import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
5
+ export interface RegisterOptions {
6
+ agentId: string;
7
+ endpoint?: string;
8
+ serviceName?: string;
9
+ serviceVersion?: string;
10
+ additionalAttributes?: Record<string, string | number | boolean>;
11
+ }
12
+ export interface CoalexContextOptions {
13
+ requestId: string;
14
+ promptVersion: string;
15
+ spanName?: string;
16
+ }
17
+ /**
18
+ * Register Coalex OpenTelemetry tracing with Coalex OTLP endpoint.
19
+ *
20
+ * @param options - Configuration options for tracing
21
+ * @returns Configured TracerProvider instance
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { register } from '@coalex/sdk';
26
+ *
27
+ * const tracerProvider = register({
28
+ * agentId: 'YOUR_AGENT_ID'
29
+ * });
30
+ * ```
31
+ */
32
+ export declare function register(options: RegisterOptions): NodeTracerProvider;
33
+ /**
34
+ * Add request context to the current span.
35
+ *
36
+ * This function adds attributes to the current active span if one exists.
37
+ * For better attribute propagation, consider using coalexContext() instead.
38
+ *
39
+ * @param requestId - Unique request identifier
40
+ * @param promptVersion - Version of the prompt being used
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * import { addRequestContext } from '@coalex/sdk';
45
+ *
46
+ * addRequestContext('req_001', 'v1.0.0');
47
+ * ```
48
+ */
49
+ export declare function addRequestContext(requestId: string, promptVersion: string): void;
50
+ /**
51
+ * Execute a function within a Coalex context that ensures attributes are propagated to child spans.
52
+ *
53
+ * @param options - Context options including requestId and promptVersion
54
+ * @param fn - The function to execute within the context
55
+ * @returns Promise that resolves with the function result
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * import { coalexContext } from '@coalex/sdk';
60
+ *
61
+ * await coalexContext(
62
+ * {
63
+ * requestId: 'req_001',
64
+ * promptVersion: 'v1.0.0'
65
+ * },
66
+ * async () => {
67
+ * // Any OpenTelemetry instrumented calls here will inherit the attributes
68
+ * const response = await someApiCall();
69
+ * return response;
70
+ * }
71
+ * );
72
+ * ```
73
+ */
74
+ export declare function coalexContext<T>(options: CoalexContextOptions, fn: () => Promise<T> | T): Promise<T>;
75
+ /**
76
+ * Synchronous version of coalexContext for non-async operations.
77
+ *
78
+ * @param options - Context options including requestId and promptVersion
79
+ * @param fn - The function to execute within the context
80
+ * @returns The function result
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * import { coalexContextSync } from '@coalex/sdk';
85
+ *
86
+ * const result = coalexContextSync(
87
+ * {
88
+ * requestId: 'req_001',
89
+ * promptVersion: 'v1.0.0'
90
+ * },
91
+ * () => {
92
+ * // Synchronous operations here
93
+ * return someValue;
94
+ * }
95
+ * );
96
+ * ```
97
+ */
98
+ export declare function coalexContextSync<T>(options: CoalexContextOptions, fn: () => T): T;
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ /**
3
+ * Coalex OpenTelemetry registration and setup.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.register = register;
7
+ exports.addRequestContext = addRequestContext;
8
+ exports.coalexContext = coalexContext;
9
+ exports.coalexContextSync = coalexContextSync;
10
+ const api_1 = require("@opentelemetry/api");
11
+ const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
12
+ const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
13
+ const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
14
+ const resources_1 = require("@opentelemetry/resources");
15
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
16
+ const DEFAULT_COALEX_ENDPOINT = 'https://traces.coalex.ai/v1/traces';
17
+ /**
18
+ * Register Coalex OpenTelemetry tracing with Coalex OTLP endpoint.
19
+ *
20
+ * @param options - Configuration options for tracing
21
+ * @returns Configured TracerProvider instance
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { register } from '@coalex/sdk';
26
+ *
27
+ * const tracerProvider = register({
28
+ * agentId: 'YOUR_AGENT_ID'
29
+ * });
30
+ * ```
31
+ */
32
+ function register(options) {
33
+ const { agentId, endpoint = DEFAULT_COALEX_ENDPOINT, serviceName = 'coalex-service', serviceVersion = '0.1.0', additionalAttributes = {} } = options;
34
+ if (!agentId) {
35
+ throw new Error('agentId is required');
36
+ }
37
+ // Create resource with service information
38
+ const resourceAttributes = {
39
+ [semantic_conventions_1.ATTR_SERVICE_NAME]: serviceName,
40
+ [semantic_conventions_1.ATTR_SERVICE_VERSION]: serviceVersion,
41
+ 'coalex.agent_id': agentId,
42
+ ...additionalAttributes
43
+ };
44
+ const resource = new resources_1.Resource(resourceAttributes);
45
+ // Create tracer provider
46
+ const tracerProvider = new sdk_trace_node_1.NodeTracerProvider({
47
+ resource
48
+ });
49
+ // Create OTLP exporter with agent_id in headers for auth
50
+ const exporter = new exporter_trace_otlp_http_1.OTLPTraceExporter({
51
+ url: endpoint,
52
+ headers: {
53
+ 'Authorization': `Bearer ${agentId}`,
54
+ 'X-Agent-ID': agentId
55
+ }
56
+ });
57
+ // Create batch span processor
58
+ const spanProcessor = new sdk_trace_base_1.BatchSpanProcessor(exporter);
59
+ tracerProvider.addSpanProcessor(spanProcessor);
60
+ // Set as global tracer provider
61
+ tracerProvider.register();
62
+ console.log(`Coalex tracing registered for agent ${agentId} -> ${endpoint}`);
63
+ return tracerProvider;
64
+ }
65
+ /**
66
+ * Add request context to the current span.
67
+ *
68
+ * This function adds attributes to the current active span if one exists.
69
+ * For better attribute propagation, consider using coalexContext() instead.
70
+ *
71
+ * @param requestId - Unique request identifier
72
+ * @param promptVersion - Version of the prompt being used
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * import { addRequestContext } from '@coalex/sdk';
77
+ *
78
+ * addRequestContext('req_001', 'v1.0.0');
79
+ * ```
80
+ */
81
+ function addRequestContext(requestId, promptVersion) {
82
+ const span = api_1.trace.getActiveSpan();
83
+ if (span && span.isRecording()) {
84
+ span.setAttribute('session.id', requestId);
85
+ span.setAttribute('prompt.version', promptVersion);
86
+ }
87
+ else {
88
+ console.warn('addRequestContext called without an active span. ' +
89
+ 'Consider using coalexContext() for better attribute propagation.');
90
+ }
91
+ }
92
+ /**
93
+ * Execute a function within a Coalex context that ensures attributes are propagated to child spans.
94
+ *
95
+ * @param options - Context options including requestId and promptVersion
96
+ * @param fn - The function to execute within the context
97
+ * @returns Promise that resolves with the function result
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * import { coalexContext } from '@coalex/sdk';
102
+ *
103
+ * await coalexContext(
104
+ * {
105
+ * requestId: 'req_001',
106
+ * promptVersion: 'v1.0.0'
107
+ * },
108
+ * async () => {
109
+ * // Any OpenTelemetry instrumented calls here will inherit the attributes
110
+ * const response = await someApiCall();
111
+ * return response;
112
+ * }
113
+ * );
114
+ * ```
115
+ */
116
+ async function coalexContext(options, fn) {
117
+ const { requestId, promptVersion, spanName = 'coalex_operation' } = options;
118
+ const tracer = api_1.trace.getTracer('coalex');
119
+ // Get agent_id from the current tracer provider's resource
120
+ let agentId;
121
+ const tracerProvider = api_1.trace.getTracerProvider();
122
+ if (tracerProvider && tracerProvider.resource) {
123
+ const attributes = tracerProvider.resource.attributes;
124
+ agentId = attributes['coalex.agent_id'];
125
+ }
126
+ return tracer.startActiveSpan(spanName, async (span) => {
127
+ try {
128
+ // Set Coalex attributes
129
+ if (agentId) {
130
+ span.setAttribute('account_id', agentId);
131
+ }
132
+ span.setAttribute('session.id', requestId);
133
+ span.setAttribute('prompt.version', promptVersion);
134
+ // Execute the function
135
+ const result = await fn();
136
+ span.end();
137
+ return result;
138
+ }
139
+ catch (error) {
140
+ // Record the error and re-throw
141
+ span.recordException(error);
142
+ span.end();
143
+ throw error;
144
+ }
145
+ });
146
+ }
147
+ /**
148
+ * Synchronous version of coalexContext for non-async operations.
149
+ *
150
+ * @param options - Context options including requestId and promptVersion
151
+ * @param fn - The function to execute within the context
152
+ * @returns The function result
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * import { coalexContextSync } from '@coalex/sdk';
157
+ *
158
+ * const result = coalexContextSync(
159
+ * {
160
+ * requestId: 'req_001',
161
+ * promptVersion: 'v1.0.0'
162
+ * },
163
+ * () => {
164
+ * // Synchronous operations here
165
+ * return someValue;
166
+ * }
167
+ * );
168
+ * ```
169
+ */
170
+ function coalexContextSync(options, fn) {
171
+ const { requestId, promptVersion, spanName = 'coalex_operation' } = options;
172
+ const tracer = api_1.trace.getTracer('coalex');
173
+ // Get agent_id from the current tracer provider's resource
174
+ let agentId;
175
+ const tracerProvider = api_1.trace.getTracerProvider();
176
+ if (tracerProvider && tracerProvider.resource) {
177
+ const attributes = tracerProvider.resource.attributes;
178
+ agentId = attributes['coalex.agent_id'];
179
+ }
180
+ return tracer.startActiveSpan(spanName, (span) => {
181
+ try {
182
+ // Set Coalex attributes
183
+ if (agentId) {
184
+ span.setAttribute('account_id', agentId);
185
+ }
186
+ span.setAttribute('session.id', requestId);
187
+ span.setAttribute('prompt.version', promptVersion);
188
+ // Execute the function
189
+ const result = fn();
190
+ span.end();
191
+ return result;
192
+ }
193
+ catch (error) {
194
+ // Record the error and re-throw
195
+ span.recordException(error);
196
+ span.end();
197
+ throw error;
198
+ }
199
+ });
200
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@coalex-ai/sdk",
3
+ "version": "0.4.1",
4
+ "description": "TypeScript SDK for Coalex.ai observability platform with OpenTelemetry integration",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch",
10
+ "prepublishOnly": "npm run build",
11
+ "test": "jest"
12
+ },
13
+ "keywords": [
14
+ "coalex",
15
+ "opentelemetry",
16
+ "tracing",
17
+ "observability",
18
+ "monitoring",
19
+ "metrics"
20
+ ],
21
+ "author": "Coalex.ai <support@coalex.ai>",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/coalex-ai/coalex-ts"
26
+ },
27
+ "dependencies": {
28
+ "@opentelemetry/api": "^1.9.0",
29
+ "@opentelemetry/sdk-trace-base": "^1.28.0",
30
+ "@opentelemetry/sdk-trace-node": "^1.28.0",
31
+ "@opentelemetry/exporter-trace-otlp-http": "^0.55.0",
32
+ "@opentelemetry/resources": "^1.28.0",
33
+ "@opentelemetry/semantic-conventions": "^1.28.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^22.10.1",
37
+ "typescript": "^5.7.2",
38
+ "jest": "^29.7.0",
39
+ "@types/jest": "^29.5.14",
40
+ "ts-jest": "^29.2.5"
41
+ },
42
+ "files": [
43
+ "dist",
44
+ "README.md",
45
+ "LICENSE"
46
+ ]
47
+ }