@paid-ai/paid-node 0.0.8-alpha3 → 0.0.8-alpha5
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 +31 -5
- package/dist/cjs/Client.d.ts +20 -1
- package/dist/cjs/Client.js +16 -4
- package/dist/cjs/tracing/signal.d.ts +1 -1
- package/dist/cjs/tracing/signal.js +12 -3
- package/dist/cjs/tracing/tracing.js +3 -2
- package/dist/cjs/tracing/wrappers/openAiWrapper.js +4 -5
- package/dist/cjs/tracing/wrappers/vercelAIWrapper.d.ts +22 -0
- package/dist/cjs/tracing/wrappers/vercelAIWrapper.js +327 -0
- package/dist/cjs/vercel/index.d.ts +1 -0
- package/dist/cjs/vercel/index.js +10 -0
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Client.d.mts +20 -1
- package/dist/esm/Client.mjs +16 -4
- package/dist/esm/tracing/signal.d.mts +1 -1
- package/dist/esm/tracing/signal.mjs +12 -3
- package/dist/esm/tracing/tracing.mjs +3 -2
- package/dist/esm/tracing/wrappers/openAiWrapper.mjs +4 -5
- package/dist/esm/tracing/wrappers/vercelAIWrapper.d.mts +22 -0
- package/dist/esm/tracing/wrappers/vercelAIWrapper.mjs +319 -0
- package/dist/esm/vercel/index.d.mts +1 -0
- package/dist/esm/vercel/index.mjs +1 -0
- package/dist/esm/version.d.mts +1 -1
- package/dist/esm/version.mjs +1 -1
- package/package.json +15 -1
package/README.md
CHANGED
|
@@ -136,16 +136,42 @@ const additionalData = {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
};
|
|
139
|
-
await client.usage.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
await client.usage.recordBulk({
|
|
140
|
+
signals: [{
|
|
141
|
+
agent_id: "<your_agent_id>",
|
|
142
|
+
event_name: "<your_signal_name>",
|
|
143
|
+
customer_id: "<your_customer_id>",
|
|
144
|
+
data: additionalData,
|
|
145
|
+
}]
|
|
144
146
|
})
|
|
145
147
|
|
|
146
148
|
await client.usage.flush(); // need to flush to send usage immediately
|
|
147
149
|
```
|
|
148
150
|
|
|
151
|
+
## Send signals over OTLP
|
|
152
|
+
|
|
153
|
+
Besides sending signals over REST, it's also possible to send signals as part or tracing
|
|
154
|
+
context, just like with cost tracking.
|
|
155
|
+
|
|
156
|
+
Example usage:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { PaidClient } from "@paid-ai/paid-node";
|
|
160
|
+
|
|
161
|
+
async function main() {
|
|
162
|
+
const client = new PaidClient({ token: "<your_paid_api_key>" });
|
|
163
|
+
|
|
164
|
+
// initialize cost tracking
|
|
165
|
+
await client.initializeTracing()
|
|
166
|
+
|
|
167
|
+
// trace the call
|
|
168
|
+
await client.trace("<your_external_customer_id>", async () => {
|
|
169
|
+
// ... your app logic, cost tracking LLM wrapper calls
|
|
170
|
+
client.signal("signal_name", { "data": { // ... additional data, e.g. costs } });
|
|
171
|
+
}, "<optional_external_agent_id>");
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
149
175
|
## Advanced
|
|
150
176
|
|
|
151
177
|
### Additional Headers
|
package/dist/cjs/Client.d.ts
CHANGED
|
@@ -43,5 +43,24 @@ export declare class PaidClient {
|
|
|
43
43
|
get usage(): Usage;
|
|
44
44
|
initializeTracing(collectorEndpoint?: string): Promise<void>;
|
|
45
45
|
trace<T extends (...args: any[]) => any>(externalCustomerId: string, fn: T, externalAgentId?: string, ...args: Parameters<T>): Promise<ReturnType<T>>;
|
|
46
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Sends Paid signal. Needs to be called as part of callback to Paid.trace().
|
|
48
|
+
* When enableCostTracing flag is on, signal is associated
|
|
49
|
+
* with cost traces from the same Paid.trace() context.
|
|
50
|
+
*
|
|
51
|
+
* @param eventName - The name of the signal.
|
|
52
|
+
* @param enableCostTracing - Whether to associate this signal with cost traces
|
|
53
|
+
* from the current Paid.trace() context (default: false)
|
|
54
|
+
* @param data - Optional additional data to include with the signal
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* When enableCostTracing is on, the signal will be associated with cost
|
|
58
|
+
* traces within the same Paid.trace() context.
|
|
59
|
+
* It is advised to only make one call to this function
|
|
60
|
+
* with enableCostTracing per Paid.trace() context.
|
|
61
|
+
* Otherwise, there will be multiple signals that refer to the same costs.
|
|
62
|
+
*/
|
|
63
|
+
signal(eventName: string): void;
|
|
64
|
+
signal(eventName: string, data: Record<string, any>): void;
|
|
65
|
+
signal(eventName: string, enableCostTracing: boolean, data?: Record<string, any>): void;
|
|
47
66
|
}
|
package/dist/cjs/Client.js
CHANGED
|
@@ -95,16 +95,28 @@ class PaidClient {
|
|
|
95
95
|
(0, tracing_js_1._initializeTracing)(resolvedToken, collectorEndpoint);
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
|
-
// Use this method to track actions like LLM
|
|
98
|
+
// Use this method to track actions like LLM costs and sending signals.
|
|
99
99
|
// The callback to this function is the work that you want to trace.
|
|
100
100
|
trace(externalCustomerId, fn, externalAgentId, ...args) {
|
|
101
101
|
return __awaiter(this, void 0, void 0, function* () {
|
|
102
102
|
return yield (0, tracing_js_1._trace)(externalCustomerId, fn, externalAgentId, ...args);
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
signal(eventName, enableCostTracingOrData, data) {
|
|
106
|
+
let enableCostTracing = false;
|
|
107
|
+
let finalData;
|
|
108
|
+
if (typeof enableCostTracingOrData === 'boolean') {
|
|
109
|
+
// Case: signal(eventName, boolean, data?)
|
|
110
|
+
enableCostTracing = enableCostTracingOrData;
|
|
111
|
+
finalData = data;
|
|
112
|
+
}
|
|
113
|
+
else if (typeof enableCostTracingOrData === 'object') {
|
|
114
|
+
// Case: signal(eventName, data)
|
|
115
|
+
enableCostTracing = false;
|
|
116
|
+
finalData = enableCostTracingOrData;
|
|
117
|
+
}
|
|
118
|
+
// Case: signal(eventName) - both remain default/undefined
|
|
119
|
+
return (0, signal_js_1._signal)(eventName, enableCostTracing, finalData);
|
|
108
120
|
}
|
|
109
121
|
}
|
|
110
122
|
exports.PaidClient = PaidClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function _signal(eventName: string, data?: Record<string, any>): void;
|
|
1
|
+
export declare function _signal(eventName: string, enableCostTracing: boolean, data?: Record<string, any>): void;
|
|
@@ -4,7 +4,7 @@ exports._signal = _signal;
|
|
|
4
4
|
const api_1 = require("@opentelemetry/api");
|
|
5
5
|
const tracing_js_1 = require("./tracing.js");
|
|
6
6
|
const tracing_js_2 = require("./tracing.js");
|
|
7
|
-
function _signal(eventName, data) {
|
|
7
|
+
function _signal(eventName, enableCostTracing, data) {
|
|
8
8
|
if (!eventName) {
|
|
9
9
|
throw new Error("Event name is required for signal.");
|
|
10
10
|
}
|
|
@@ -14,8 +14,7 @@ function _signal(eventName, data) {
|
|
|
14
14
|
if (!externalCustomerId || !externalAgentId || !token) {
|
|
15
15
|
throw new Error(`Missing some of: external_customer_id: ${externalCustomerId}, external_agent_id: ${externalAgentId}, or token. Make sure to call signal() within trace()`);
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
tracer.startActiveSpan("trace.signal", (span) => {
|
|
17
|
+
tracing_js_2.paidTracer.startActiveSpan("trace.signal", (span) => {
|
|
19
18
|
try {
|
|
20
19
|
const attributes = {
|
|
21
20
|
external_customer_id: externalCustomerId,
|
|
@@ -23,6 +22,16 @@ function _signal(eventName, data) {
|
|
|
23
22
|
event_name: eventName,
|
|
24
23
|
token: token,
|
|
25
24
|
};
|
|
25
|
+
if (enableCostTracing) {
|
|
26
|
+
// let the app know to associate this signal with cost traces
|
|
27
|
+
attributes["enable_cost_tracing"] = true;
|
|
28
|
+
if (data === undefined) {
|
|
29
|
+
data = { paid: { enable_cost_tracing: true } };
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
data["paid"] = { enable_cost_tracing: true };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
26
35
|
// Optional data (ex. manual cost tracking)
|
|
27
36
|
if (data) {
|
|
28
37
|
attributes["data"] = JSON.stringify(data);
|
|
@@ -35,6 +35,7 @@ const COLLECTOR_ENDPOINT = process.env.PAID_COLLECTOR_ENDPOINT || "https://colle
|
|
|
35
35
|
let paidExporter = new exporter_trace_otlp_http_1.OTLPTraceExporter({ url: COLLECTOR_ENDPOINT });
|
|
36
36
|
let spanProcessor = new sdk_trace_base_1.BatchSpanProcessor(paidExporter);
|
|
37
37
|
let paidTracerProvider = new sdk_trace_node_1.NodeTracerProvider({ spanProcessors: [spanProcessor] });
|
|
38
|
+
paidTracerProvider.register();
|
|
38
39
|
exports.paidTracer = paidTracerProvider.getTracer("paid.node");
|
|
39
40
|
// storage for passing info to child spans
|
|
40
41
|
const customerIdStorage = new async_hooks_1.AsyncLocalStorage();
|
|
@@ -79,6 +80,7 @@ function _initializeTracing(apiKey, collectorEndpoint) {
|
|
|
79
80
|
paidExporter = new exporter_trace_otlp_http_1.OTLPTraceExporter({ url: collectorEndpoint });
|
|
80
81
|
spanProcessor = new sdk_trace_base_1.BatchSpanProcessor(paidExporter);
|
|
81
82
|
paidTracerProvider = new sdk_trace_node_1.NodeTracerProvider({ spanProcessors: [spanProcessor] });
|
|
83
|
+
paidTracerProvider.register();
|
|
82
84
|
exports.paidTracer = paidTracerProvider.getTracer("paid.node");
|
|
83
85
|
}
|
|
84
86
|
setupGracefulShutdown(spanProcessor);
|
|
@@ -88,12 +90,11 @@ function _initializeTracing(apiKey, collectorEndpoint) {
|
|
|
88
90
|
}
|
|
89
91
|
function _trace(externalCustomerId, fn, externalAgentId, ...args) {
|
|
90
92
|
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
-
const tracer = exports.paidTracer;
|
|
92
93
|
const token = getToken();
|
|
93
94
|
if (!token || !externalCustomerId) {
|
|
94
95
|
throw new Error(`Paid tracing is not initialized. Make sure to call initializeTracing() first.`);
|
|
95
96
|
}
|
|
96
|
-
return
|
|
97
|
+
return exports.paidTracer.startActiveSpan("paid.node", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
97
98
|
span.setAttribute("external_customer_id", externalCustomerId);
|
|
98
99
|
span.setAttribute("token", token);
|
|
99
100
|
if (externalAgentId) {
|
|
@@ -197,16 +197,15 @@ class ImagesWrapper {
|
|
|
197
197
|
}
|
|
198
198
|
generate(params) {
|
|
199
199
|
return __awaiter(this, void 0, void 0, function* () {
|
|
200
|
-
var _a;
|
|
201
200
|
const externalCustomerId = (0, tracing_js_1.getCustomerIdStorage)();
|
|
202
201
|
const externalAgentId = (0, tracing_js_1.getAgentIdStorage)();
|
|
203
202
|
const token = (0, tracing_js_1.getTokenStorage)();
|
|
204
|
-
const model =
|
|
203
|
+
const model = params.model || "";
|
|
205
204
|
if (!token || !externalCustomerId) {
|
|
206
205
|
throw new Error("No token or externalCustomerId: This wrapper should be used inside a callback to paid.trace().");
|
|
207
206
|
}
|
|
208
207
|
return this.tracer.startActiveSpan("trace.openai.images", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
209
|
-
var _a
|
|
208
|
+
var _a;
|
|
210
209
|
const attributes = {
|
|
211
210
|
"gen_ai.request.model": model,
|
|
212
211
|
"gen_ai.system": "openai",
|
|
@@ -222,8 +221,8 @@ class ImagesWrapper {
|
|
|
222
221
|
const response = yield this.openai.images.generate(params);
|
|
223
222
|
span.setAttributes({
|
|
224
223
|
"gen_ai.image.count": (_a = params.n) !== null && _a !== void 0 ? _a : 1,
|
|
225
|
-
"gen_ai.image.size":
|
|
226
|
-
"gen_ai.image.quality":
|
|
224
|
+
"gen_ai.image.size": params.size || "",
|
|
225
|
+
"gen_ai.image.quality": params.quality || "",
|
|
227
226
|
});
|
|
228
227
|
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
229
228
|
return response;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { generateText as originalGenerateText, streamText as originalStreamText, generateObject as originalGenerateObject, streamObject as originalStreamObject, embed as originalEmbed, embedMany as originalEmbedMany } from "ai";
|
|
2
|
+
type GenerateTextParams = Parameters<typeof originalGenerateText>[0];
|
|
3
|
+
type StreamTextParams = Parameters<typeof originalStreamText>[0];
|
|
4
|
+
type GenerateObjectParams = Parameters<typeof originalGenerateObject>[0];
|
|
5
|
+
type StreamObjectParams = Parameters<typeof originalStreamObject>[0];
|
|
6
|
+
type EmbedParams = Parameters<typeof originalEmbed>[0];
|
|
7
|
+
type EmbedManyParams = Parameters<typeof originalEmbedMany>[0];
|
|
8
|
+
export declare function generateText(params: GenerateTextParams): Promise<ReturnType<typeof originalGenerateText>>;
|
|
9
|
+
export declare function streamText(params: StreamTextParams): Promise<ReturnType<typeof originalStreamText>>;
|
|
10
|
+
export declare function generateObject(params: GenerateObjectParams): Promise<ReturnType<typeof originalGenerateObject>>;
|
|
11
|
+
export declare function streamObject(params: StreamObjectParams): Promise<ReturnType<typeof originalStreamObject>>;
|
|
12
|
+
export declare function embed(params: EmbedParams): Promise<ReturnType<typeof originalEmbed>>;
|
|
13
|
+
export declare function embedMany(params: EmbedManyParams): Promise<ReturnType<typeof originalEmbedMany>>;
|
|
14
|
+
declare const _default: {
|
|
15
|
+
generateText: typeof generateText;
|
|
16
|
+
streamText: typeof streamText;
|
|
17
|
+
generateObject: typeof generateObject;
|
|
18
|
+
streamObject: typeof streamObject;
|
|
19
|
+
embed: typeof embed;
|
|
20
|
+
embedMany: typeof embedMany;
|
|
21
|
+
};
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.generateText = generateText;
|
|
13
|
+
exports.streamText = streamText;
|
|
14
|
+
exports.generateObject = generateObject;
|
|
15
|
+
exports.streamObject = streamObject;
|
|
16
|
+
exports.embed = embed;
|
|
17
|
+
exports.embedMany = embedMany;
|
|
18
|
+
const api_1 = require("@opentelemetry/api");
|
|
19
|
+
const tracing_js_1 = require("../tracing.js");
|
|
20
|
+
const ai_1 = require("ai");
|
|
21
|
+
function getModelInfo(model) {
|
|
22
|
+
if (model === null || model === void 0 ? void 0 : model.modelId) {
|
|
23
|
+
const modelId = model.modelId;
|
|
24
|
+
if (modelId.startsWith('gpt-') || modelId.startsWith('text-embedding-') || modelId.startsWith('dall-e-')) {
|
|
25
|
+
return { system: 'openai', modelName: modelId };
|
|
26
|
+
}
|
|
27
|
+
if (modelId.startsWith('claude-')) {
|
|
28
|
+
return { system: 'anthropic', modelName: modelId };
|
|
29
|
+
}
|
|
30
|
+
if (modelId.startsWith('mistral-') || modelId.startsWith('codestral-')) {
|
|
31
|
+
return { system: 'mistral', modelName: modelId };
|
|
32
|
+
}
|
|
33
|
+
if (modelId.includes('gemini')) {
|
|
34
|
+
return { system: 'google', modelName: modelId };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (model === null || model === void 0 ? void 0 : model.provider) {
|
|
38
|
+
return { system: model.provider, modelName: model.modelId };
|
|
39
|
+
}
|
|
40
|
+
return { system: 'unknown' };
|
|
41
|
+
}
|
|
42
|
+
function extractUsageMetrics(usage) {
|
|
43
|
+
const usageAttrs = {};
|
|
44
|
+
const inputTokens = usage.promptTokens || usage.prompt_tokens || usage.inputTokens;
|
|
45
|
+
const outputTokens = usage.completionTokens || usage.completion_tokens || usage.outputTokens;
|
|
46
|
+
const cachedTokens = usage.cachedPromptTokens || usage.cached_prompt_tokens || usage.cachedInputTokens;
|
|
47
|
+
if (inputTokens !== undefined) {
|
|
48
|
+
usageAttrs["gen_ai.usage.input_tokens"] = inputTokens;
|
|
49
|
+
}
|
|
50
|
+
if (outputTokens !== undefined) {
|
|
51
|
+
usageAttrs["gen_ai.usage.output_tokens"] = outputTokens;
|
|
52
|
+
}
|
|
53
|
+
if (cachedTokens !== undefined) {
|
|
54
|
+
usageAttrs["gen_ai.usage.cached_input_tokens"] = cachedTokens;
|
|
55
|
+
}
|
|
56
|
+
if (usage.tokens !== undefined && inputTokens === undefined) {
|
|
57
|
+
usageAttrs["gen_ai.usage.input_tokens"] = usage.tokens;
|
|
58
|
+
}
|
|
59
|
+
return usageAttrs;
|
|
60
|
+
}
|
|
61
|
+
function validateContext() {
|
|
62
|
+
const externalCustomerId = (0, tracing_js_1.getCustomerIdStorage)();
|
|
63
|
+
const token = (0, tracing_js_1.getTokenStorage)();
|
|
64
|
+
if (!token || !externalCustomerId) {
|
|
65
|
+
throw new Error("No token or externalCustomerId: This wrapper should be used inside a callback to paid.trace().");
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
externalCustomerId,
|
|
69
|
+
externalAgentId: (0, tracing_js_1.getAgentIdStorage)(),
|
|
70
|
+
token,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function generateText(params) {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
const context = validateContext();
|
|
76
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
77
|
+
return tracing_js_1.paidTracer.startActiveSpan("trace.ai-sdk.generateText", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
var _a;
|
|
79
|
+
const attributes = {
|
|
80
|
+
"gen_ai.system": aiSystem,
|
|
81
|
+
"gen_ai.operation.name": "chat",
|
|
82
|
+
"external_customer_id": context.externalCustomerId,
|
|
83
|
+
"token": context.token,
|
|
84
|
+
};
|
|
85
|
+
if (context.externalAgentId) {
|
|
86
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
87
|
+
}
|
|
88
|
+
if (modelName) {
|
|
89
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
90
|
+
}
|
|
91
|
+
span.setAttributes(attributes);
|
|
92
|
+
try {
|
|
93
|
+
const result = yield (0, ai_1.generateText)(params);
|
|
94
|
+
if (result.usage) {
|
|
95
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
96
|
+
span.setAttributes(usageAttrs);
|
|
97
|
+
}
|
|
98
|
+
if ((_a = result.response) === null || _a === void 0 ? void 0 : _a.modelId) {
|
|
99
|
+
span.setAttribute("gen_ai.response.model", result.response.modelId);
|
|
100
|
+
}
|
|
101
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
|
|
106
|
+
span.recordException(error);
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
span.end();
|
|
111
|
+
}
|
|
112
|
+
}));
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function streamText(params) {
|
|
116
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
117
|
+
const context = validateContext();
|
|
118
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
119
|
+
return tracing_js_1.paidTracer.startActiveSpan("trace.ai-sdk.streamText", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const attributes = {
|
|
121
|
+
"gen_ai.system": aiSystem,
|
|
122
|
+
"gen_ai.operation.name": "chat",
|
|
123
|
+
"external_customer_id": context.externalCustomerId,
|
|
124
|
+
"token": context.token,
|
|
125
|
+
};
|
|
126
|
+
if (context.externalAgentId) {
|
|
127
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
128
|
+
}
|
|
129
|
+
if (modelName) {
|
|
130
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
131
|
+
}
|
|
132
|
+
span.setAttributes(attributes);
|
|
133
|
+
try {
|
|
134
|
+
const originalOnFinish = params.onFinish;
|
|
135
|
+
const wrappedParams = Object.assign(Object.assign({}, params), { onFinish: (result) => {
|
|
136
|
+
if (result.usage) {
|
|
137
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
138
|
+
span.setAttributes(usageAttrs);
|
|
139
|
+
}
|
|
140
|
+
if (originalOnFinish) {
|
|
141
|
+
originalOnFinish(result);
|
|
142
|
+
}
|
|
143
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
144
|
+
span.end();
|
|
145
|
+
} });
|
|
146
|
+
const result = (0, ai_1.streamText)(wrappedParams);
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
|
|
151
|
+
span.recordException(error);
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
span.end();
|
|
156
|
+
}
|
|
157
|
+
}));
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function generateObject(params) {
|
|
161
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
162
|
+
const context = validateContext();
|
|
163
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
164
|
+
return tracing_js_1.paidTracer.startActiveSpan("trace.ai-sdk.generateObject", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
var _a;
|
|
166
|
+
const attributes = {
|
|
167
|
+
"gen_ai.system": aiSystem,
|
|
168
|
+
"gen_ai.operation.name": "chat",
|
|
169
|
+
"external_customer_id": context.externalCustomerId,
|
|
170
|
+
"token": context.token,
|
|
171
|
+
};
|
|
172
|
+
if (context.externalAgentId) {
|
|
173
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
174
|
+
}
|
|
175
|
+
if (modelName) {
|
|
176
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
177
|
+
}
|
|
178
|
+
span.setAttributes(attributes);
|
|
179
|
+
try {
|
|
180
|
+
const result = yield (0, ai_1.generateObject)(params);
|
|
181
|
+
if (result.usage) {
|
|
182
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
183
|
+
span.setAttributes(usageAttrs);
|
|
184
|
+
}
|
|
185
|
+
if ((_a = result.response) === null || _a === void 0 ? void 0 : _a.modelId) {
|
|
186
|
+
span.setAttribute("gen_ai.response.model", result.response.modelId);
|
|
187
|
+
}
|
|
188
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
|
|
193
|
+
span.recordException(error);
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
span.end();
|
|
198
|
+
}
|
|
199
|
+
}));
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function streamObject(params) {
|
|
203
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
204
|
+
const context = validateContext();
|
|
205
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
206
|
+
return tracing_js_1.paidTracer.startActiveSpan("trace.ai-sdk.streamObject", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
const attributes = {
|
|
208
|
+
"gen_ai.system": aiSystem,
|
|
209
|
+
"gen_ai.operation.name": "chat",
|
|
210
|
+
"external_customer_id": context.externalCustomerId,
|
|
211
|
+
"token": context.token,
|
|
212
|
+
};
|
|
213
|
+
if (context.externalAgentId) {
|
|
214
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
215
|
+
}
|
|
216
|
+
if (modelName) {
|
|
217
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
218
|
+
}
|
|
219
|
+
span.setAttributes(attributes);
|
|
220
|
+
try {
|
|
221
|
+
const originalOnFinish = params.onFinish;
|
|
222
|
+
const wrappedParams = Object.assign(Object.assign({}, params), { onFinish: (result) => {
|
|
223
|
+
if (result.usage) {
|
|
224
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
225
|
+
span.setAttributes(usageAttrs);
|
|
226
|
+
}
|
|
227
|
+
if (originalOnFinish) {
|
|
228
|
+
originalOnFinish(result);
|
|
229
|
+
}
|
|
230
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
231
|
+
span.end();
|
|
232
|
+
} });
|
|
233
|
+
const result = (0, ai_1.streamObject)(wrappedParams);
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
|
|
238
|
+
span.recordException(error);
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
}));
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
function embed(params) {
|
|
245
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
246
|
+
const context = validateContext();
|
|
247
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
248
|
+
return tracing_js_1.paidTracer.startActiveSpan("trace.ai-sdk.embed", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
249
|
+
const attributes = {
|
|
250
|
+
"gen_ai.system": aiSystem,
|
|
251
|
+
"gen_ai.operation.name": "embeddings",
|
|
252
|
+
"external_customer_id": context.externalCustomerId,
|
|
253
|
+
"token": context.token,
|
|
254
|
+
};
|
|
255
|
+
if (context.externalAgentId) {
|
|
256
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
257
|
+
}
|
|
258
|
+
if (modelName) {
|
|
259
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
260
|
+
}
|
|
261
|
+
span.setAttributes(attributes);
|
|
262
|
+
try {
|
|
263
|
+
const result = yield (0, ai_1.embed)(params);
|
|
264
|
+
if (result.usage) {
|
|
265
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
266
|
+
span.setAttributes(usageAttrs);
|
|
267
|
+
}
|
|
268
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
|
|
273
|
+
span.recordException(error);
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
finally {
|
|
277
|
+
span.end();
|
|
278
|
+
}
|
|
279
|
+
}));
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
function embedMany(params) {
|
|
283
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
284
|
+
const context = validateContext();
|
|
285
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
286
|
+
return tracing_js_1.paidTracer.startActiveSpan("trace.ai-sdk.embedMany", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
287
|
+
const attributes = {
|
|
288
|
+
"gen_ai.system": aiSystem,
|
|
289
|
+
"gen_ai.operation.name": "embeddings",
|
|
290
|
+
"external_customer_id": context.externalCustomerId,
|
|
291
|
+
"token": context.token,
|
|
292
|
+
};
|
|
293
|
+
if (context.externalAgentId) {
|
|
294
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
295
|
+
}
|
|
296
|
+
if (modelName) {
|
|
297
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
298
|
+
}
|
|
299
|
+
span.setAttributes(attributes);
|
|
300
|
+
try {
|
|
301
|
+
const result = yield (0, ai_1.embedMany)(params);
|
|
302
|
+
if (result.usage) {
|
|
303
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
304
|
+
span.setAttributes(usageAttrs);
|
|
305
|
+
}
|
|
306
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
307
|
+
return result;
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
|
|
311
|
+
span.recordException(error);
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
314
|
+
finally {
|
|
315
|
+
span.end();
|
|
316
|
+
}
|
|
317
|
+
}));
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
exports.default = {
|
|
321
|
+
generateText,
|
|
322
|
+
streamText,
|
|
323
|
+
generateObject,
|
|
324
|
+
streamObject,
|
|
325
|
+
embed,
|
|
326
|
+
embedMany,
|
|
327
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generateText as paidGenerateText, streamText as paidStreamText, generateObject as paidGenerateObject, streamObject as paidStreamObject, embed as paidEmbed, embedMany as paidEmbedMany, } from "../tracing/wrappers/vercelAIWrapper.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.paidEmbedMany = exports.paidEmbed = exports.paidStreamObject = exports.paidGenerateObject = exports.paidStreamText = exports.paidGenerateText = void 0;
|
|
4
|
+
var vercelAIWrapper_js_1 = require("../tracing/wrappers/vercelAIWrapper.js");
|
|
5
|
+
Object.defineProperty(exports, "paidGenerateText", { enumerable: true, get: function () { return vercelAIWrapper_js_1.generateText; } });
|
|
6
|
+
Object.defineProperty(exports, "paidStreamText", { enumerable: true, get: function () { return vercelAIWrapper_js_1.streamText; } });
|
|
7
|
+
Object.defineProperty(exports, "paidGenerateObject", { enumerable: true, get: function () { return vercelAIWrapper_js_1.generateObject; } });
|
|
8
|
+
Object.defineProperty(exports, "paidStreamObject", { enumerable: true, get: function () { return vercelAIWrapper_js_1.streamObject; } });
|
|
9
|
+
Object.defineProperty(exports, "paidEmbed", { enumerable: true, get: function () { return vercelAIWrapper_js_1.embed; } });
|
|
10
|
+
Object.defineProperty(exports, "paidEmbedMany", { enumerable: true, get: function () { return vercelAIWrapper_js_1.embedMany; } });
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.0.8-
|
|
1
|
+
export declare const SDK_VERSION = "0.0.8-alpha5";
|
package/dist/cjs/version.js
CHANGED
package/dist/esm/Client.d.mts
CHANGED
|
@@ -43,5 +43,24 @@ export declare class PaidClient {
|
|
|
43
43
|
get usage(): Usage;
|
|
44
44
|
initializeTracing(collectorEndpoint?: string): Promise<void>;
|
|
45
45
|
trace<T extends (...args: any[]) => any>(externalCustomerId: string, fn: T, externalAgentId?: string, ...args: Parameters<T>): Promise<ReturnType<T>>;
|
|
46
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Sends Paid signal. Needs to be called as part of callback to Paid.trace().
|
|
48
|
+
* When enableCostTracing flag is on, signal is associated
|
|
49
|
+
* with cost traces from the same Paid.trace() context.
|
|
50
|
+
*
|
|
51
|
+
* @param eventName - The name of the signal.
|
|
52
|
+
* @param enableCostTracing - Whether to associate this signal with cost traces
|
|
53
|
+
* from the current Paid.trace() context (default: false)
|
|
54
|
+
* @param data - Optional additional data to include with the signal
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* When enableCostTracing is on, the signal will be associated with cost
|
|
58
|
+
* traces within the same Paid.trace() context.
|
|
59
|
+
* It is advised to only make one call to this function
|
|
60
|
+
* with enableCostTracing per Paid.trace() context.
|
|
61
|
+
* Otherwise, there will be multiple signals that refer to the same costs.
|
|
62
|
+
*/
|
|
63
|
+
signal(eventName: string): void;
|
|
64
|
+
signal(eventName: string, data: Record<string, any>): void;
|
|
65
|
+
signal(eventName: string, enableCostTracing: boolean, data?: Record<string, any>): void;
|
|
47
66
|
}
|
package/dist/esm/Client.mjs
CHANGED
|
@@ -59,15 +59,27 @@ export class PaidClient {
|
|
|
59
59
|
_initializeTracing(resolvedToken, collectorEndpoint);
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
|
-
// Use this method to track actions like LLM
|
|
62
|
+
// Use this method to track actions like LLM costs and sending signals.
|
|
63
63
|
// The callback to this function is the work that you want to trace.
|
|
64
64
|
trace(externalCustomerId, fn, externalAgentId, ...args) {
|
|
65
65
|
return __awaiter(this, void 0, void 0, function* () {
|
|
66
66
|
return yield _trace(externalCustomerId, fn, externalAgentId, ...args);
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
signal(eventName, enableCostTracingOrData, data) {
|
|
70
|
+
let enableCostTracing = false;
|
|
71
|
+
let finalData;
|
|
72
|
+
if (typeof enableCostTracingOrData === 'boolean') {
|
|
73
|
+
// Case: signal(eventName, boolean, data?)
|
|
74
|
+
enableCostTracing = enableCostTracingOrData;
|
|
75
|
+
finalData = data;
|
|
76
|
+
}
|
|
77
|
+
else if (typeof enableCostTracingOrData === 'object') {
|
|
78
|
+
// Case: signal(eventName, data)
|
|
79
|
+
enableCostTracing = false;
|
|
80
|
+
finalData = enableCostTracingOrData;
|
|
81
|
+
}
|
|
82
|
+
// Case: signal(eventName) - both remain default/undefined
|
|
83
|
+
return _signal(eventName, enableCostTracing, finalData);
|
|
72
84
|
}
|
|
73
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function _signal(eventName: string, data?: Record<string, any>): void;
|
|
1
|
+
export declare function _signal(eventName: string, enableCostTracing: boolean, data?: Record<string, any>): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SpanStatusCode } from "@opentelemetry/api";
|
|
2
2
|
import { getCustomerIdStorage, getAgentIdStorage, getTokenStorage } from "./tracing.mjs";
|
|
3
3
|
import { paidTracer } from "./tracing.mjs";
|
|
4
|
-
export function _signal(eventName, data) {
|
|
4
|
+
export function _signal(eventName, enableCostTracing, data) {
|
|
5
5
|
if (!eventName) {
|
|
6
6
|
throw new Error("Event name is required for signal.");
|
|
7
7
|
}
|
|
@@ -11,8 +11,7 @@ export function _signal(eventName, data) {
|
|
|
11
11
|
if (!externalCustomerId || !externalAgentId || !token) {
|
|
12
12
|
throw new Error(`Missing some of: external_customer_id: ${externalCustomerId}, external_agent_id: ${externalAgentId}, or token. Make sure to call signal() within trace()`);
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
tracer.startActiveSpan("trace.signal", (span) => {
|
|
14
|
+
paidTracer.startActiveSpan("trace.signal", (span) => {
|
|
16
15
|
try {
|
|
17
16
|
const attributes = {
|
|
18
17
|
external_customer_id: externalCustomerId,
|
|
@@ -20,6 +19,16 @@ export function _signal(eventName, data) {
|
|
|
20
19
|
event_name: eventName,
|
|
21
20
|
token: token,
|
|
22
21
|
};
|
|
22
|
+
if (enableCostTracing) {
|
|
23
|
+
// let the app know to associate this signal with cost traces
|
|
24
|
+
attributes["enable_cost_tracing"] = true;
|
|
25
|
+
if (data === undefined) {
|
|
26
|
+
data = { paid: { enable_cost_tracing: true } };
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
data["paid"] = { enable_cost_tracing: true };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
// Optional data (ex. manual cost tracking)
|
|
24
33
|
if (data) {
|
|
25
34
|
attributes["data"] = JSON.stringify(data);
|
|
@@ -27,6 +27,7 @@ const COLLECTOR_ENDPOINT = process.env.PAID_COLLECTOR_ENDPOINT || "https://colle
|
|
|
27
27
|
let paidExporter = new OTLPTraceExporter({ url: COLLECTOR_ENDPOINT });
|
|
28
28
|
let spanProcessor = new BatchSpanProcessor(paidExporter);
|
|
29
29
|
let paidTracerProvider = new NodeTracerProvider({ spanProcessors: [spanProcessor] });
|
|
30
|
+
paidTracerProvider.register();
|
|
30
31
|
export let paidTracer = paidTracerProvider.getTracer("paid.node");
|
|
31
32
|
// storage for passing info to child spans
|
|
32
33
|
const customerIdStorage = new AsyncLocalStorage();
|
|
@@ -68,6 +69,7 @@ export function _initializeTracing(apiKey, collectorEndpoint) {
|
|
|
68
69
|
paidExporter = new OTLPTraceExporter({ url: collectorEndpoint });
|
|
69
70
|
spanProcessor = new BatchSpanProcessor(paidExporter);
|
|
70
71
|
paidTracerProvider = new NodeTracerProvider({ spanProcessors: [spanProcessor] });
|
|
72
|
+
paidTracerProvider.register();
|
|
71
73
|
paidTracer = paidTracerProvider.getTracer("paid.node");
|
|
72
74
|
}
|
|
73
75
|
setupGracefulShutdown(spanProcessor);
|
|
@@ -77,12 +79,11 @@ export function _initializeTracing(apiKey, collectorEndpoint) {
|
|
|
77
79
|
}
|
|
78
80
|
export function _trace(externalCustomerId, fn, externalAgentId, ...args) {
|
|
79
81
|
return __awaiter(this, void 0, void 0, function* () {
|
|
80
|
-
const tracer = paidTracer;
|
|
81
82
|
const token = getToken();
|
|
82
83
|
if (!token || !externalCustomerId) {
|
|
83
84
|
throw new Error(`Paid tracing is not initialized. Make sure to call initializeTracing() first.`);
|
|
84
85
|
}
|
|
85
|
-
return
|
|
86
|
+
return paidTracer.startActiveSpan("paid.node", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
86
87
|
span.setAttribute("external_customer_id", externalCustomerId);
|
|
87
88
|
span.setAttribute("token", token);
|
|
88
89
|
if (externalAgentId) {
|
|
@@ -193,16 +193,15 @@ class ImagesWrapper {
|
|
|
193
193
|
}
|
|
194
194
|
generate(params) {
|
|
195
195
|
return __awaiter(this, void 0, void 0, function* () {
|
|
196
|
-
var _a;
|
|
197
196
|
const externalCustomerId = getCustomerIdStorage();
|
|
198
197
|
const externalAgentId = getAgentIdStorage();
|
|
199
198
|
const token = getTokenStorage();
|
|
200
|
-
const model =
|
|
199
|
+
const model = params.model || "";
|
|
201
200
|
if (!token || !externalCustomerId) {
|
|
202
201
|
throw new Error("No token or externalCustomerId: This wrapper should be used inside a callback to paid.trace().");
|
|
203
202
|
}
|
|
204
203
|
return this.tracer.startActiveSpan("trace.openai.images", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
205
|
-
var _a
|
|
204
|
+
var _a;
|
|
206
205
|
const attributes = {
|
|
207
206
|
"gen_ai.request.model": model,
|
|
208
207
|
"gen_ai.system": "openai",
|
|
@@ -218,8 +217,8 @@ class ImagesWrapper {
|
|
|
218
217
|
const response = yield this.openai.images.generate(params);
|
|
219
218
|
span.setAttributes({
|
|
220
219
|
"gen_ai.image.count": (_a = params.n) !== null && _a !== void 0 ? _a : 1,
|
|
221
|
-
"gen_ai.image.size":
|
|
222
|
-
"gen_ai.image.quality":
|
|
220
|
+
"gen_ai.image.size": params.size || "",
|
|
221
|
+
"gen_ai.image.quality": params.quality || "",
|
|
223
222
|
});
|
|
224
223
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
225
224
|
return response;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { generateText as originalGenerateText, streamText as originalStreamText, generateObject as originalGenerateObject, streamObject as originalStreamObject, embed as originalEmbed, embedMany as originalEmbedMany } from "ai";
|
|
2
|
+
type GenerateTextParams = Parameters<typeof originalGenerateText>[0];
|
|
3
|
+
type StreamTextParams = Parameters<typeof originalStreamText>[0];
|
|
4
|
+
type GenerateObjectParams = Parameters<typeof originalGenerateObject>[0];
|
|
5
|
+
type StreamObjectParams = Parameters<typeof originalStreamObject>[0];
|
|
6
|
+
type EmbedParams = Parameters<typeof originalEmbed>[0];
|
|
7
|
+
type EmbedManyParams = Parameters<typeof originalEmbedMany>[0];
|
|
8
|
+
export declare function generateText(params: GenerateTextParams): Promise<ReturnType<typeof originalGenerateText>>;
|
|
9
|
+
export declare function streamText(params: StreamTextParams): Promise<ReturnType<typeof originalStreamText>>;
|
|
10
|
+
export declare function generateObject(params: GenerateObjectParams): Promise<ReturnType<typeof originalGenerateObject>>;
|
|
11
|
+
export declare function streamObject(params: StreamObjectParams): Promise<ReturnType<typeof originalStreamObject>>;
|
|
12
|
+
export declare function embed(params: EmbedParams): Promise<ReturnType<typeof originalEmbed>>;
|
|
13
|
+
export declare function embedMany(params: EmbedManyParams): Promise<ReturnType<typeof originalEmbedMany>>;
|
|
14
|
+
declare const _default: {
|
|
15
|
+
generateText: typeof generateText;
|
|
16
|
+
streamText: typeof streamText;
|
|
17
|
+
generateObject: typeof generateObject;
|
|
18
|
+
streamObject: typeof streamObject;
|
|
19
|
+
embed: typeof embed;
|
|
20
|
+
embedMany: typeof embedMany;
|
|
21
|
+
};
|
|
22
|
+
export default _default;
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
11
|
+
import { getCustomerIdStorage, getAgentIdStorage, getTokenStorage, paidTracer } from "../tracing.mjs";
|
|
12
|
+
import { generateText as originalGenerateText, streamText as originalStreamText, generateObject as originalGenerateObject, streamObject as originalStreamObject, embed as originalEmbed, embedMany as originalEmbedMany, } from "ai";
|
|
13
|
+
function getModelInfo(model) {
|
|
14
|
+
if (model === null || model === void 0 ? void 0 : model.modelId) {
|
|
15
|
+
const modelId = model.modelId;
|
|
16
|
+
if (modelId.startsWith('gpt-') || modelId.startsWith('text-embedding-') || modelId.startsWith('dall-e-')) {
|
|
17
|
+
return { system: 'openai', modelName: modelId };
|
|
18
|
+
}
|
|
19
|
+
if (modelId.startsWith('claude-')) {
|
|
20
|
+
return { system: 'anthropic', modelName: modelId };
|
|
21
|
+
}
|
|
22
|
+
if (modelId.startsWith('mistral-') || modelId.startsWith('codestral-')) {
|
|
23
|
+
return { system: 'mistral', modelName: modelId };
|
|
24
|
+
}
|
|
25
|
+
if (modelId.includes('gemini')) {
|
|
26
|
+
return { system: 'google', modelName: modelId };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (model === null || model === void 0 ? void 0 : model.provider) {
|
|
30
|
+
return { system: model.provider, modelName: model.modelId };
|
|
31
|
+
}
|
|
32
|
+
return { system: 'unknown' };
|
|
33
|
+
}
|
|
34
|
+
function extractUsageMetrics(usage) {
|
|
35
|
+
const usageAttrs = {};
|
|
36
|
+
const inputTokens = usage.promptTokens || usage.prompt_tokens || usage.inputTokens;
|
|
37
|
+
const outputTokens = usage.completionTokens || usage.completion_tokens || usage.outputTokens;
|
|
38
|
+
const cachedTokens = usage.cachedPromptTokens || usage.cached_prompt_tokens || usage.cachedInputTokens;
|
|
39
|
+
if (inputTokens !== undefined) {
|
|
40
|
+
usageAttrs["gen_ai.usage.input_tokens"] = inputTokens;
|
|
41
|
+
}
|
|
42
|
+
if (outputTokens !== undefined) {
|
|
43
|
+
usageAttrs["gen_ai.usage.output_tokens"] = outputTokens;
|
|
44
|
+
}
|
|
45
|
+
if (cachedTokens !== undefined) {
|
|
46
|
+
usageAttrs["gen_ai.usage.cached_input_tokens"] = cachedTokens;
|
|
47
|
+
}
|
|
48
|
+
if (usage.tokens !== undefined && inputTokens === undefined) {
|
|
49
|
+
usageAttrs["gen_ai.usage.input_tokens"] = usage.tokens;
|
|
50
|
+
}
|
|
51
|
+
return usageAttrs;
|
|
52
|
+
}
|
|
53
|
+
function validateContext() {
|
|
54
|
+
const externalCustomerId = getCustomerIdStorage();
|
|
55
|
+
const token = getTokenStorage();
|
|
56
|
+
if (!token || !externalCustomerId) {
|
|
57
|
+
throw new Error("No token or externalCustomerId: This wrapper should be used inside a callback to paid.trace().");
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
externalCustomerId,
|
|
61
|
+
externalAgentId: getAgentIdStorage(),
|
|
62
|
+
token,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function generateText(params) {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
const context = validateContext();
|
|
68
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
69
|
+
return paidTracer.startActiveSpan("trace.ai-sdk.generateText", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
var _a;
|
|
71
|
+
const attributes = {
|
|
72
|
+
"gen_ai.system": aiSystem,
|
|
73
|
+
"gen_ai.operation.name": "chat",
|
|
74
|
+
"external_customer_id": context.externalCustomerId,
|
|
75
|
+
"token": context.token,
|
|
76
|
+
};
|
|
77
|
+
if (context.externalAgentId) {
|
|
78
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
79
|
+
}
|
|
80
|
+
if (modelName) {
|
|
81
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
82
|
+
}
|
|
83
|
+
span.setAttributes(attributes);
|
|
84
|
+
try {
|
|
85
|
+
const result = yield originalGenerateText(params);
|
|
86
|
+
if (result.usage) {
|
|
87
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
88
|
+
span.setAttributes(usageAttrs);
|
|
89
|
+
}
|
|
90
|
+
if ((_a = result.response) === null || _a === void 0 ? void 0 : _a.modelId) {
|
|
91
|
+
span.setAttribute("gen_ai.response.model", result.response.modelId);
|
|
92
|
+
}
|
|
93
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
98
|
+
span.recordException(error);
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
span.end();
|
|
103
|
+
}
|
|
104
|
+
}));
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
export function streamText(params) {
|
|
108
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
109
|
+
const context = validateContext();
|
|
110
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
111
|
+
return paidTracer.startActiveSpan("trace.ai-sdk.streamText", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
112
|
+
const attributes = {
|
|
113
|
+
"gen_ai.system": aiSystem,
|
|
114
|
+
"gen_ai.operation.name": "chat",
|
|
115
|
+
"external_customer_id": context.externalCustomerId,
|
|
116
|
+
"token": context.token,
|
|
117
|
+
};
|
|
118
|
+
if (context.externalAgentId) {
|
|
119
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
120
|
+
}
|
|
121
|
+
if (modelName) {
|
|
122
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
123
|
+
}
|
|
124
|
+
span.setAttributes(attributes);
|
|
125
|
+
try {
|
|
126
|
+
const originalOnFinish = params.onFinish;
|
|
127
|
+
const wrappedParams = Object.assign(Object.assign({}, params), { onFinish: (result) => {
|
|
128
|
+
if (result.usage) {
|
|
129
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
130
|
+
span.setAttributes(usageAttrs);
|
|
131
|
+
}
|
|
132
|
+
if (originalOnFinish) {
|
|
133
|
+
originalOnFinish(result);
|
|
134
|
+
}
|
|
135
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
136
|
+
span.end();
|
|
137
|
+
} });
|
|
138
|
+
const result = originalStreamText(wrappedParams);
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
143
|
+
span.recordException(error);
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
span.end();
|
|
148
|
+
}
|
|
149
|
+
}));
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
export function generateObject(params) {
|
|
153
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
const context = validateContext();
|
|
155
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
156
|
+
return paidTracer.startActiveSpan("trace.ai-sdk.generateObject", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
157
|
+
var _a;
|
|
158
|
+
const attributes = {
|
|
159
|
+
"gen_ai.system": aiSystem,
|
|
160
|
+
"gen_ai.operation.name": "chat",
|
|
161
|
+
"external_customer_id": context.externalCustomerId,
|
|
162
|
+
"token": context.token,
|
|
163
|
+
};
|
|
164
|
+
if (context.externalAgentId) {
|
|
165
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
166
|
+
}
|
|
167
|
+
if (modelName) {
|
|
168
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
169
|
+
}
|
|
170
|
+
span.setAttributes(attributes);
|
|
171
|
+
try {
|
|
172
|
+
const result = yield originalGenerateObject(params);
|
|
173
|
+
if (result.usage) {
|
|
174
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
175
|
+
span.setAttributes(usageAttrs);
|
|
176
|
+
}
|
|
177
|
+
if ((_a = result.response) === null || _a === void 0 ? void 0 : _a.modelId) {
|
|
178
|
+
span.setAttribute("gen_ai.response.model", result.response.modelId);
|
|
179
|
+
}
|
|
180
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
185
|
+
span.recordException(error);
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
span.end();
|
|
190
|
+
}
|
|
191
|
+
}));
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
export function streamObject(params) {
|
|
195
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
196
|
+
const context = validateContext();
|
|
197
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
198
|
+
return paidTracer.startActiveSpan("trace.ai-sdk.streamObject", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
const attributes = {
|
|
200
|
+
"gen_ai.system": aiSystem,
|
|
201
|
+
"gen_ai.operation.name": "chat",
|
|
202
|
+
"external_customer_id": context.externalCustomerId,
|
|
203
|
+
"token": context.token,
|
|
204
|
+
};
|
|
205
|
+
if (context.externalAgentId) {
|
|
206
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
207
|
+
}
|
|
208
|
+
if (modelName) {
|
|
209
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
210
|
+
}
|
|
211
|
+
span.setAttributes(attributes);
|
|
212
|
+
try {
|
|
213
|
+
const originalOnFinish = params.onFinish;
|
|
214
|
+
const wrappedParams = Object.assign(Object.assign({}, params), { onFinish: (result) => {
|
|
215
|
+
if (result.usage) {
|
|
216
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
217
|
+
span.setAttributes(usageAttrs);
|
|
218
|
+
}
|
|
219
|
+
if (originalOnFinish) {
|
|
220
|
+
originalOnFinish(result);
|
|
221
|
+
}
|
|
222
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
223
|
+
span.end();
|
|
224
|
+
} });
|
|
225
|
+
const result = originalStreamObject(wrappedParams);
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
230
|
+
span.recordException(error);
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
}));
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
export function embed(params) {
|
|
237
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
238
|
+
const context = validateContext();
|
|
239
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
240
|
+
return paidTracer.startActiveSpan("trace.ai-sdk.embed", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
241
|
+
const attributes = {
|
|
242
|
+
"gen_ai.system": aiSystem,
|
|
243
|
+
"gen_ai.operation.name": "embeddings",
|
|
244
|
+
"external_customer_id": context.externalCustomerId,
|
|
245
|
+
"token": context.token,
|
|
246
|
+
};
|
|
247
|
+
if (context.externalAgentId) {
|
|
248
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
249
|
+
}
|
|
250
|
+
if (modelName) {
|
|
251
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
252
|
+
}
|
|
253
|
+
span.setAttributes(attributes);
|
|
254
|
+
try {
|
|
255
|
+
const result = yield originalEmbed(params);
|
|
256
|
+
if (result.usage) {
|
|
257
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
258
|
+
span.setAttributes(usageAttrs);
|
|
259
|
+
}
|
|
260
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
265
|
+
span.recordException(error);
|
|
266
|
+
throw error;
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
span.end();
|
|
270
|
+
}
|
|
271
|
+
}));
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
export function embedMany(params) {
|
|
275
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
+
const context = validateContext();
|
|
277
|
+
const { system: aiSystem, modelName } = getModelInfo(params.model);
|
|
278
|
+
return paidTracer.startActiveSpan("trace.ai-sdk.embedMany", (span) => __awaiter(this, void 0, void 0, function* () {
|
|
279
|
+
const attributes = {
|
|
280
|
+
"gen_ai.system": aiSystem,
|
|
281
|
+
"gen_ai.operation.name": "embeddings",
|
|
282
|
+
"external_customer_id": context.externalCustomerId,
|
|
283
|
+
"token": context.token,
|
|
284
|
+
};
|
|
285
|
+
if (context.externalAgentId) {
|
|
286
|
+
attributes["external_agent_id"] = context.externalAgentId;
|
|
287
|
+
}
|
|
288
|
+
if (modelName) {
|
|
289
|
+
attributes["gen_ai.request.model"] = modelName;
|
|
290
|
+
}
|
|
291
|
+
span.setAttributes(attributes);
|
|
292
|
+
try {
|
|
293
|
+
const result = yield originalEmbedMany(params);
|
|
294
|
+
if (result.usage) {
|
|
295
|
+
const usageAttrs = extractUsageMetrics(result.usage);
|
|
296
|
+
span.setAttributes(usageAttrs);
|
|
297
|
+
}
|
|
298
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
303
|
+
span.recordException(error);
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
span.end();
|
|
308
|
+
}
|
|
309
|
+
}));
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
export default {
|
|
313
|
+
generateText,
|
|
314
|
+
streamText,
|
|
315
|
+
generateObject,
|
|
316
|
+
streamObject,
|
|
317
|
+
embed,
|
|
318
|
+
embedMany,
|
|
319
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generateText as paidGenerateText, streamText as paidStreamText, generateObject as paidGenerateObject, streamObject as paidStreamObject, embed as paidEmbed, embedMany as paidEmbedMany, } from "../tracing/wrappers/vercelAIWrapper.mjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generateText as paidGenerateText, streamText as paidStreamText, generateObject as paidGenerateObject, streamObject as paidStreamObject, embed as paidEmbed, embedMany as paidEmbedMany, } from "../tracing/wrappers/vercelAIWrapper.mjs";
|
package/dist/esm/version.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.0.8-
|
|
1
|
+
export declare const SDK_VERSION = "0.0.8-alpha5";
|
package/dist/esm/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.0.8-
|
|
1
|
+
export const SDK_VERSION = "0.0.8-alpha5";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paid-ai/paid-node",
|
|
3
|
-
"version": "0.0.8-
|
|
3
|
+
"version": "0.0.8-alpha5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": "https://github.com/AgentPaid/paid-node",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -20,6 +20,18 @@
|
|
|
20
20
|
},
|
|
21
21
|
"default": "./dist/cjs/index.js"
|
|
22
22
|
},
|
|
23
|
+
"./vercel": {
|
|
24
|
+
"types": "./dist/cjs/vercel/index.d.ts",
|
|
25
|
+
"import": {
|
|
26
|
+
"types": "./dist/esm/vercel/index.d.mts",
|
|
27
|
+
"default": "./dist/esm/vercel/index.mjs"
|
|
28
|
+
},
|
|
29
|
+
"require": {
|
|
30
|
+
"types": "./dist/cjs/vercel/index.d.ts",
|
|
31
|
+
"default": "./dist/cjs/vercel/index.js"
|
|
32
|
+
},
|
|
33
|
+
"default": "./dist/cjs/vercel/index.js"
|
|
34
|
+
},
|
|
23
35
|
"./package.json": "./package.json"
|
|
24
36
|
},
|
|
25
37
|
"files": [
|
|
@@ -36,12 +48,14 @@
|
|
|
36
48
|
"wire:test": "yarn test:wire"
|
|
37
49
|
},
|
|
38
50
|
"dependencies": {
|
|
51
|
+
"@ai-sdk/openai": "^1.3.23",
|
|
39
52
|
"@anthropic-ai/sdk": "^0.56.0",
|
|
40
53
|
"@langchain/core": "^0.3.64",
|
|
41
54
|
"@mistralai/mistralai": "^1.7.4",
|
|
42
55
|
"@opentelemetry/api": "^1.9.0",
|
|
43
56
|
"@opentelemetry/exporter-trace-otlp-http": "^0.202.0",
|
|
44
57
|
"@opentelemetry/sdk-node": "^0.202.0",
|
|
58
|
+
"ai": "^5.0.2",
|
|
45
59
|
"form-data": "^4.0.0",
|
|
46
60
|
"formdata-node": "^6.0.3",
|
|
47
61
|
"js-base64": "3.7.7",
|