@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 +21 -0
- package/README.md +263 -0
- package/dist/approve.d.ts +95 -0
- package/dist/approve.js +170 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +26 -0
- package/dist/metrics.d.ts +101 -0
- package/dist/metrics.js +192 -0
- package/dist/otel/register.d.ts +98 -0
- package/dist/otel/register.js +200 -0
- package/package.json +47 -0
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>;
|
package/dist/approve.js
ADDED
|
@@ -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
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -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>;
|
package/dist/metrics.js
ADDED
|
@@ -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
|
+
}
|