@rheonic/sdk 0.1.0-beta.10 → 0.1.0-beta.12
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/CHANGELOG.md +4 -0
- package/README.md +20 -7
- package/dist/eventBuilder.d.ts +5 -2
- package/dist/eventBuilder.js +2 -1
- package/dist/protectEngine.d.ts +1 -1
- package/dist/protectEngine.js +17 -7
- package/dist/providers/anthropicAdapter.js +5 -3
- package/dist/providers/googleAdapter.js +86 -20
- package/dist/providers/openaiAdapter.js +5 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,13 @@ All notable changes to `@rheonic/sdk` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
### Changed
|
|
8
|
+
- Google provider instrumentation and examples now align with the current official Google Gen AI JavaScript SDK shape: `@google/genai` with `ai.models.generateContent({...})`.
|
|
9
|
+
|
|
7
10
|
### Fixed
|
|
8
11
|
- SDK debug logs now always emit non-empty `trace_id` and `span_id`, including warmup, token-estimation, and protect preflight paths.
|
|
9
12
|
- Provider instrumentation now keeps the full protected call lifecycle under one trace so SDK debug logs correlate cleanly with backend requests.
|
|
13
|
+
- Quickstart and README examples now use the published `@rheonic/sdk` package name consistently and show the current Anthropic and Google instrumentation patterns.
|
|
10
14
|
|
|
11
15
|
## 0.1.0-beta.7
|
|
12
16
|
|
package/README.md
CHANGED
|
@@ -69,14 +69,18 @@ Anthropic:
|
|
|
69
69
|
|
|
70
70
|
```ts
|
|
71
71
|
import Anthropic from "@anthropic-ai/sdk";
|
|
72
|
-
import { createClient, RHEONICBlockedError } from "@rheonic/sdk";
|
|
72
|
+
import { createClient, instrumentAnthropic, RHEONICBlockedError } from "@rheonic/sdk";
|
|
73
73
|
|
|
74
74
|
const rheonic = createClient({
|
|
75
75
|
baseUrl: process.env.RHEONIC_BASE_URL!,
|
|
76
76
|
ingestKey: process.env.RHEONIC_INGEST_KEY!,
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
const anthropic =
|
|
79
|
+
const anthropic = instrumentAnthropic(new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY! }), {
|
|
80
|
+
client: rheonic,
|
|
81
|
+
endpoint: "/v1/messages",
|
|
82
|
+
feature: "assistant",
|
|
83
|
+
});
|
|
80
84
|
|
|
81
85
|
try {
|
|
82
86
|
await anthropic.messages.create({
|
|
@@ -100,19 +104,28 @@ try {
|
|
|
100
104
|
Google:
|
|
101
105
|
|
|
102
106
|
```ts
|
|
103
|
-
import {
|
|
104
|
-
import { createClient, RHEONICBlockedError } from "@rheonic/sdk";
|
|
107
|
+
import { GoogleGenAI } from "@google/genai";
|
|
108
|
+
import { createClient, instrumentGoogle, RHEONICBlockedError } from "@rheonic/sdk";
|
|
105
109
|
|
|
106
110
|
const rheonic = createClient({
|
|
107
111
|
baseUrl: process.env.RHEONIC_BASE_URL!,
|
|
108
112
|
ingestKey: process.env.RHEONIC_INGEST_KEY!,
|
|
109
113
|
});
|
|
110
114
|
|
|
111
|
-
const
|
|
112
|
-
|
|
115
|
+
const ai = instrumentGoogle(new GoogleGenAI({ apiKey: process.env.GOOGLE_API_KEY! }), {
|
|
116
|
+
client: rheonic,
|
|
117
|
+
endpoint: "/v1beta/models/generateContent",
|
|
118
|
+
feature: "assistant",
|
|
119
|
+
});
|
|
113
120
|
|
|
114
121
|
try {
|
|
115
|
-
await
|
|
122
|
+
await ai.models.generateContent({
|
|
123
|
+
model: "gemini-1.5-pro",
|
|
124
|
+
contents: "hello",
|
|
125
|
+
config: {
|
|
126
|
+
maxOutputTokens: 256,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
116
129
|
} catch (error) {
|
|
117
130
|
if (error instanceof RHEONICBlockedError) {
|
|
118
131
|
console.log(JSON.stringify({
|
package/dist/eventBuilder.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface EventRequest {
|
|
2
2
|
endpoint?: string;
|
|
3
3
|
feature?: string;
|
|
4
|
+
request_fingerprint?: string;
|
|
4
5
|
input_tokens?: number;
|
|
5
6
|
input_tokens_estimate?: number;
|
|
6
7
|
token_explosion_tokens?: number;
|
|
@@ -17,14 +18,16 @@ export interface EventResponse {
|
|
|
17
18
|
export interface EventPayload {
|
|
18
19
|
ts: string;
|
|
19
20
|
provider: string;
|
|
20
|
-
|
|
21
|
+
requested_model: string | null;
|
|
22
|
+
resolved_model: string | null;
|
|
21
23
|
environment: string;
|
|
22
24
|
request: EventRequest;
|
|
23
25
|
response: EventResponse;
|
|
24
26
|
}
|
|
25
27
|
export interface BuildEventInput {
|
|
26
28
|
provider: string;
|
|
27
|
-
|
|
29
|
+
requested_model?: string | null;
|
|
30
|
+
resolved_model?: string | null;
|
|
28
31
|
environment?: string;
|
|
29
32
|
ts?: string;
|
|
30
33
|
request?: EventRequest;
|
package/dist/eventBuilder.js
CHANGED
|
@@ -2,7 +2,8 @@ export function buildEvent(input) {
|
|
|
2
2
|
return {
|
|
3
3
|
ts: input.ts ?? new Date().toISOString(),
|
|
4
4
|
provider: input.provider,
|
|
5
|
-
|
|
5
|
+
requested_model: input.requested_model ?? null,
|
|
6
|
+
resolved_model: input.resolved_model ?? null,
|
|
6
7
|
environment: input.environment ?? "dev",
|
|
7
8
|
request: input.request ?? {},
|
|
8
9
|
response: input.response ?? {},
|
package/dist/protectEngine.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export type ProtectDecision = "allow" | "clamp" | "block";
|
|
|
2
2
|
export type ProtectFailMode = "open" | "closed";
|
|
3
3
|
export interface ProtectContext {
|
|
4
4
|
provider: string;
|
|
5
|
-
|
|
5
|
+
requested_model?: string | null;
|
|
6
6
|
feature?: string;
|
|
7
7
|
max_output_tokens?: number;
|
|
8
8
|
input_tokens_estimate?: number;
|
package/dist/protectEngine.js
CHANGED
|
@@ -90,7 +90,7 @@ export class ProtectEngine {
|
|
|
90
90
|
status_code: response.status,
|
|
91
91
|
latency_ms: Date.now() - startedAt,
|
|
92
92
|
});
|
|
93
|
-
void this.reportDecisionUnavailable(context.provider, typeof context.
|
|
93
|
+
void this.reportDecisionUnavailable(context.provider, typeof context.requested_model === "string" ? context.requested_model : undefined, requestId, traceId);
|
|
94
94
|
return this.fallbackEvaluation(traceId, requestId);
|
|
95
95
|
}
|
|
96
96
|
const parsed = (await response.json());
|
|
@@ -140,7 +140,7 @@ export class ProtectEngine {
|
|
|
140
140
|
latency_ms: Date.now() - startedAt,
|
|
141
141
|
timeout_ms: timeoutMs,
|
|
142
142
|
});
|
|
143
|
-
void this.reportDecisionTimeout(context.provider, typeof context.
|
|
143
|
+
void this.reportDecisionTimeout(context.provider, typeof context.requested_model === "string" ? context.requested_model : undefined, requestId, traceId);
|
|
144
144
|
}
|
|
145
145
|
else {
|
|
146
146
|
this.debugLog?.("Protect preflight failed", {
|
|
@@ -148,7 +148,7 @@ export class ProtectEngine {
|
|
|
148
148
|
latency_ms: Date.now() - startedAt,
|
|
149
149
|
error_type: extractErrorType(error),
|
|
150
150
|
});
|
|
151
|
-
void this.reportDecisionUnavailable(context.provider, typeof context.
|
|
151
|
+
void this.reportDecisionUnavailable(context.provider, typeof context.requested_model === "string" ? context.requested_model : undefined, requestId, traceId);
|
|
152
152
|
}
|
|
153
153
|
return this.fallbackEvaluation(traceId, requestId);
|
|
154
154
|
}
|
|
@@ -189,7 +189,7 @@ export class ProtectEngine {
|
|
|
189
189
|
// Best effort only; keep local defaults if bootstrap fails.
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
-
async reportDecisionTimeout(provider,
|
|
192
|
+
async reportDecisionTimeout(provider, requestedModel, requestId, traceId) {
|
|
193
193
|
try {
|
|
194
194
|
await requestJson(`${this.baseUrl}/api/v1/protect/decision-timeout`, {
|
|
195
195
|
method: "POST",
|
|
@@ -200,14 +200,19 @@ export class ProtectEngine {
|
|
|
200
200
|
"X-Span-ID": generateSpanId(),
|
|
201
201
|
"X-Rheonic-Protect-Request-Id": requestId,
|
|
202
202
|
},
|
|
203
|
-
body: JSON.stringify({
|
|
203
|
+
body: JSON.stringify({
|
|
204
|
+
environment: this.environment,
|
|
205
|
+
provider,
|
|
206
|
+
requested_model: requestedModel,
|
|
207
|
+
request_id: requestId,
|
|
208
|
+
}),
|
|
204
209
|
});
|
|
205
210
|
}
|
|
206
211
|
catch {
|
|
207
212
|
// Swallow timeout reporting errors; protect evaluation must never throw here.
|
|
208
213
|
}
|
|
209
214
|
}
|
|
210
|
-
async reportDecisionUnavailable(provider,
|
|
215
|
+
async reportDecisionUnavailable(provider, requestedModel, requestId, traceId) {
|
|
211
216
|
try {
|
|
212
217
|
await requestJson(`${this.baseUrl}/api/v1/protect/decision-unavailable`, {
|
|
213
218
|
method: "POST",
|
|
@@ -218,7 +223,12 @@ export class ProtectEngine {
|
|
|
218
223
|
"X-Span-ID": generateSpanId(),
|
|
219
224
|
"X-Rheonic-Protect-Request-Id": requestId,
|
|
220
225
|
},
|
|
221
|
-
body: JSON.stringify({
|
|
226
|
+
body: JSON.stringify({
|
|
227
|
+
environment: this.environment,
|
|
228
|
+
provider,
|
|
229
|
+
requested_model: requestedModel,
|
|
230
|
+
request_id: requestId,
|
|
231
|
+
}),
|
|
222
232
|
});
|
|
223
233
|
}
|
|
224
234
|
catch {
|
|
@@ -36,7 +36,7 @@ export function instrumentAnthropic(anthropicClient, options) {
|
|
|
36
36
|
});
|
|
37
37
|
const protectPayload = {
|
|
38
38
|
provider: "anthropic",
|
|
39
|
-
|
|
39
|
+
requested_model: requestedModel,
|
|
40
40
|
environment: options.environment ?? options.client.environment,
|
|
41
41
|
feature: options.feature,
|
|
42
42
|
max_output_tokens: extractMaxOutputTokens(args),
|
|
@@ -56,7 +56,8 @@ export function instrumentAnthropic(anthropicClient, options) {
|
|
|
56
56
|
const response = await originalCreate(...callArgs);
|
|
57
57
|
await options.client.captureEventAndFlush(buildEvent({
|
|
58
58
|
provider: "anthropic",
|
|
59
|
-
|
|
59
|
+
requested_model: requestedModel,
|
|
60
|
+
resolved_model: extractResponseModel(response),
|
|
60
61
|
environment: options.environment ?? options.client.environment,
|
|
61
62
|
request: {
|
|
62
63
|
endpoint: options.endpoint,
|
|
@@ -77,7 +78,8 @@ export function instrumentAnthropic(anthropicClient, options) {
|
|
|
77
78
|
catch (error) {
|
|
78
79
|
await options.client.captureEventAndFlush(buildEvent({
|
|
79
80
|
provider: "anthropic",
|
|
80
|
-
|
|
81
|
+
requested_model: requestedModel,
|
|
82
|
+
resolved_model: null,
|
|
81
83
|
environment: options.environment ?? options.client.environment,
|
|
82
84
|
request: {
|
|
83
85
|
endpoint: options.endpoint,
|
|
@@ -8,17 +8,17 @@ export function __setInputTokenEstimatorForTests(estimator) {
|
|
|
8
8
|
estimatorOverrideForTests = estimator;
|
|
9
9
|
}
|
|
10
10
|
export function instrumentGoogle(googleModel, options) {
|
|
11
|
-
const targetGenerate = googleModel
|
|
12
|
-
if (
|
|
11
|
+
const targetGenerate = resolveGenerateTarget(googleModel);
|
|
12
|
+
if (!targetGenerate) {
|
|
13
13
|
return googleModel;
|
|
14
14
|
}
|
|
15
|
-
const originalGenerate = targetGenerate.bind(
|
|
16
|
-
|
|
15
|
+
const originalGenerate = targetGenerate.fn.bind(targetGenerate.owner);
|
|
16
|
+
targetGenerate.owner[targetGenerate.key] = async (...args) => {
|
|
17
17
|
const traceId = generateTraceId();
|
|
18
18
|
const spanId = generateSpanId();
|
|
19
19
|
return bindTraceContext(traceId, spanId, async () => {
|
|
20
20
|
const startedAt = Date.now();
|
|
21
|
-
const requestedModel = extractRequestedModel(googleModel);
|
|
21
|
+
const requestedModel = extractRequestedModel(googleModel, args);
|
|
22
22
|
validateProviderModel("google", requestedModel);
|
|
23
23
|
const requestPayload = extractRequestPayload(args, requestedModel);
|
|
24
24
|
let estimatedInputTokens = null;
|
|
@@ -36,7 +36,7 @@ export function instrumentGoogle(googleModel, options) {
|
|
|
36
36
|
});
|
|
37
37
|
const protectPayload = {
|
|
38
38
|
provider: "google",
|
|
39
|
-
|
|
39
|
+
requested_model: requestedModel,
|
|
40
40
|
environment: options.environment ?? options.client.environment,
|
|
41
41
|
feature: options.feature,
|
|
42
42
|
max_output_tokens: extractMaxOutputTokens(args),
|
|
@@ -56,7 +56,8 @@ export function instrumentGoogle(googleModel, options) {
|
|
|
56
56
|
const response = await originalGenerate(...callArgs);
|
|
57
57
|
await options.client.captureEventAndFlush(buildEvent({
|
|
58
58
|
provider: "google",
|
|
59
|
-
|
|
59
|
+
requested_model: requestedModel,
|
|
60
|
+
resolved_model: extractResponseModel(response),
|
|
60
61
|
environment: options.environment ?? options.client.environment,
|
|
61
62
|
request: {
|
|
62
63
|
endpoint: options.endpoint,
|
|
@@ -77,7 +78,8 @@ export function instrumentGoogle(googleModel, options) {
|
|
|
77
78
|
catch (error) {
|
|
78
79
|
await options.client.captureEventAndFlush(buildEvent({
|
|
79
80
|
provider: "google",
|
|
80
|
-
|
|
81
|
+
requested_model: requestedModel,
|
|
82
|
+
resolved_model: null,
|
|
81
83
|
environment: options.environment ?? options.client.environment,
|
|
82
84
|
request: {
|
|
83
85
|
endpoint: options.endpoint,
|
|
@@ -99,6 +101,26 @@ export function instrumentGoogle(googleModel, options) {
|
|
|
99
101
|
};
|
|
100
102
|
return googleModel;
|
|
101
103
|
}
|
|
104
|
+
function resolveGenerateTarget(googleModel) {
|
|
105
|
+
const directGenerate = googleModel?.generateContent;
|
|
106
|
+
if (typeof directGenerate === "function") {
|
|
107
|
+
return {
|
|
108
|
+
owner: googleModel,
|
|
109
|
+
fn: directGenerate,
|
|
110
|
+
key: "generateContent",
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const models = googleModel?.models;
|
|
114
|
+
const nestedGenerate = models?.generateContent;
|
|
115
|
+
if (models && typeof nestedGenerate === "function") {
|
|
116
|
+
return {
|
|
117
|
+
owner: models,
|
|
118
|
+
fn: nestedGenerate,
|
|
119
|
+
key: "generateContent",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
102
124
|
function extractRequestPayload(args, model) {
|
|
103
125
|
const firstArg = args[0];
|
|
104
126
|
if (typeof firstArg === "string") {
|
|
@@ -109,8 +131,13 @@ function extractRequestPayload(args, model) {
|
|
|
109
131
|
}
|
|
110
132
|
return null;
|
|
111
133
|
}
|
|
112
|
-
function extractRequestedModel(googleModel) {
|
|
134
|
+
function extractRequestedModel(googleModel, args) {
|
|
113
135
|
if (!googleModel || typeof googleModel !== "object") {
|
|
136
|
+
const firstArg = args[0];
|
|
137
|
+
if (firstArg && typeof firstArg === "object" && "model" in firstArg) {
|
|
138
|
+
const payloadModel = firstArg.model;
|
|
139
|
+
return typeof payloadModel === "string" ? payloadModel : null;
|
|
140
|
+
}
|
|
114
141
|
return null;
|
|
115
142
|
}
|
|
116
143
|
const withModel = googleModel;
|
|
@@ -120,16 +147,35 @@ function extractRequestedModel(googleModel) {
|
|
|
120
147
|
if (typeof withModel.modelName === "string") {
|
|
121
148
|
return withModel.modelName;
|
|
122
149
|
}
|
|
150
|
+
const firstArg = args[0];
|
|
151
|
+
if (firstArg && typeof firstArg === "object" && "model" in firstArg) {
|
|
152
|
+
const payloadModel = firstArg.model;
|
|
153
|
+
return typeof payloadModel === "string" ? payloadModel : null;
|
|
154
|
+
}
|
|
123
155
|
return null;
|
|
124
156
|
}
|
|
125
157
|
function extractMaxOutputTokens(args) {
|
|
126
158
|
const firstArg = args[0];
|
|
127
159
|
if (!firstArg || typeof firstArg !== "object") {
|
|
128
|
-
|
|
160
|
+
const secondArg = args[1];
|
|
161
|
+
if (!secondArg || typeof secondArg !== "object") {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
const options = secondArg;
|
|
165
|
+
const optionsGenerationMax = options.generationConfig?.maxOutputTokens;
|
|
166
|
+
if (typeof optionsGenerationMax === "number") {
|
|
167
|
+
return optionsGenerationMax;
|
|
168
|
+
}
|
|
169
|
+
const optionsConfigMax = options.config?.maxOutputTokens;
|
|
170
|
+
return typeof optionsConfigMax === "number" ? optionsConfigMax : undefined;
|
|
129
171
|
}
|
|
130
172
|
const payload = firstArg;
|
|
131
|
-
const
|
|
132
|
-
|
|
173
|
+
const generationMax = payload.generationConfig?.maxOutputTokens;
|
|
174
|
+
if (typeof generationMax === "number") {
|
|
175
|
+
return generationMax;
|
|
176
|
+
}
|
|
177
|
+
const configMax = payload.config?.maxOutputTokens;
|
|
178
|
+
return typeof configMax === "number" ? configMax : undefined;
|
|
133
179
|
}
|
|
134
180
|
function extractTotalTokens(response) {
|
|
135
181
|
if (!response || typeof response !== "object") {
|
|
@@ -149,6 +195,23 @@ function extractTotalTokens(response) {
|
|
|
149
195
|
const total = prompt + candidates;
|
|
150
196
|
return total > 0 ? total : undefined;
|
|
151
197
|
}
|
|
198
|
+
function extractResponseModel(response) {
|
|
199
|
+
if (!response || typeof response !== "object") {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const topLevelModel = response.model;
|
|
203
|
+
if (typeof topLevelModel === "string" && topLevelModel.trim()) {
|
|
204
|
+
return topLevelModel;
|
|
205
|
+
}
|
|
206
|
+
const nestedResponse = response.response;
|
|
207
|
+
if (typeof nestedResponse?.modelVersion === "string" && nestedResponse.modelVersion.trim()) {
|
|
208
|
+
return nestedResponse.modelVersion;
|
|
209
|
+
}
|
|
210
|
+
if (typeof nestedResponse?.model === "string" && nestedResponse.model.trim()) {
|
|
211
|
+
return nestedResponse.model;
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
152
215
|
function extractErrorType(error) {
|
|
153
216
|
if (error && typeof error === "object" && "name" in error) {
|
|
154
217
|
const name = error.name;
|
|
@@ -189,11 +252,13 @@ function maybeApplyGoogleClamp(args, decision) {
|
|
|
189
252
|
const firstArg = nextArgs[0];
|
|
190
253
|
if (firstArg && typeof firstArg === "object") {
|
|
191
254
|
const payload = { ...firstArg };
|
|
192
|
-
const
|
|
193
|
-
|
|
255
|
+
const useModernConfig = "config" in payload || "contents" in payload || "model" in payload;
|
|
256
|
+
const configKey = useModernConfig ? "config" : "generationConfig";
|
|
257
|
+
const existingConfig = payload[configKey] && typeof payload[configKey] === "object"
|
|
258
|
+
? payload[configKey]
|
|
194
259
|
: {};
|
|
195
260
|
const existingMax = existingConfig.maxOutputTokens;
|
|
196
|
-
payload
|
|
261
|
+
payload[configKey] = {
|
|
197
262
|
...existingConfig,
|
|
198
263
|
maxOutputTokens: typeof existingMax === "number" ? Math.min(existingMax, recommended) : recommended,
|
|
199
264
|
};
|
|
@@ -201,14 +266,15 @@ function maybeApplyGoogleClamp(args, decision) {
|
|
|
201
266
|
return nextArgs;
|
|
202
267
|
}
|
|
203
268
|
const secondArg = nextArgs[1];
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
|
|
269
|
+
const existingOptions = secondArg && typeof secondArg === "object" ? { ...secondArg } : {};
|
|
270
|
+
const configKey = existingOptions.config && typeof existingOptions.config === "object" ? "config" : "generationConfig";
|
|
271
|
+
const generationConfig = existingOptions[configKey] && typeof existingOptions[configKey] === "object"
|
|
272
|
+
? { ...existingOptions[configKey] }
|
|
207
273
|
: {};
|
|
208
274
|
const existingMax = generationConfig.maxOutputTokens;
|
|
209
275
|
generationConfig.maxOutputTokens = typeof existingMax === "number" ? Math.min(existingMax, recommended) : recommended;
|
|
210
|
-
|
|
211
|
-
nextArgs[1] =
|
|
276
|
+
existingOptions[configKey] = generationConfig;
|
|
277
|
+
nextArgs[1] = existingOptions;
|
|
212
278
|
return nextArgs;
|
|
213
279
|
}
|
|
214
280
|
function markClampAppliedIfChanged(decision, originalMaxTokens, appliedMaxTokens) {
|
|
@@ -35,7 +35,7 @@ export function instrumentOpenAI(openaiClient, options) {
|
|
|
35
35
|
});
|
|
36
36
|
const protectPayload = {
|
|
37
37
|
provider: "openai",
|
|
38
|
-
model,
|
|
38
|
+
requested_model: model,
|
|
39
39
|
environment: options.environment ?? options.client.environment,
|
|
40
40
|
feature: options.feature,
|
|
41
41
|
max_output_tokens: extractMaxOutputTokens(args),
|
|
@@ -57,7 +57,8 @@ export function instrumentOpenAI(openaiClient, options) {
|
|
|
57
57
|
const response = await originalCreate(...callArgs);
|
|
58
58
|
await options.client.captureEventAndFlush(buildEvent({
|
|
59
59
|
provider: "openai",
|
|
60
|
-
|
|
60
|
+
requested_model: model,
|
|
61
|
+
resolved_model: extractResponseModel(response),
|
|
61
62
|
environment: options.environment ?? options.client.environment,
|
|
62
63
|
request: {
|
|
63
64
|
endpoint: options.endpoint,
|
|
@@ -77,7 +78,8 @@ export function instrumentOpenAI(openaiClient, options) {
|
|
|
77
78
|
catch (error) {
|
|
78
79
|
await options.client.captureEventAndFlush(buildEvent({
|
|
79
80
|
provider: "openai",
|
|
80
|
-
model,
|
|
81
|
+
requested_model: model,
|
|
82
|
+
resolved_model: null,
|
|
81
83
|
environment: options.environment ?? options.client.environment,
|
|
82
84
|
request: {
|
|
83
85
|
endpoint: options.endpoint,
|
package/package.json
CHANGED