langsmith 0.7.0 → 0.7.2
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/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/dist/experimental/vercel/index.cjs +18 -637
- package/dist/experimental/vercel/index.d.ts +3 -257
- package/dist/experimental/vercel/index.js +2 -635
- package/dist/experimental/vercel/middleware.cjs +2 -78
- package/dist/experimental/vercel/middleware.js +1 -77
- package/dist/experimental/vercel/telemetry.cjs +462 -0
- package/dist/experimental/vercel/telemetry.d.ts +89 -0
- package/dist/experimental/vercel/telemetry.js +459 -0
- package/dist/experimental/vercel/utils.cjs +142 -35
- package/dist/experimental/vercel/utils.d.ts +28 -3
- package/dist/experimental/vercel/utils.js +140 -34
- package/dist/experimental/vercel/wrap.cjs +639 -0
- package/dist/experimental/vercel/wrap.d.ts +257 -0
- package/dist/experimental/vercel/wrap.js +635 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/sandbox/client.cjs +21 -0
- package/dist/sandbox/client.d.ts +1 -0
- package/dist/sandbox/client.js +21 -0
- package/dist/sandbox/sandbox.cjs +12 -1
- package/dist/sandbox/sandbox.js +12 -1
- package/dist/sandbox/types.d.ts +12 -0
- package/dist/sandbox/ws_execute.cjs +11 -7
- package/dist/sandbox/ws_execute.d.ts +2 -1
- package/dist/sandbox/ws_execute.js +11 -7
- package/dist/utils/types.cjs +13 -0
- package/dist/utils/types.d.ts +2 -0
- package/dist/utils/types.js +8 -0
- package/dist/utils/vercel.cjs +68 -10
- package/dist/utils/vercel.d.ts +17 -2
- package/dist/utils/vercel.js +68 -10
- package/experimental/sandbox.cjs +1 -0
- package/experimental/sandbox.d.cts +1 -0
- package/experimental/sandbox.d.ts +1 -0
- package/experimental/sandbox.js +1 -0
- package/package.json +22 -7
package/dist/sandbox/client.cjs
CHANGED
|
@@ -89,6 +89,12 @@ class SandboxClient {
|
|
|
89
89
|
writable: true,
|
|
90
90
|
value: void 0
|
|
91
91
|
});
|
|
92
|
+
Object.defineProperty(this, "_defaultHeaders", {
|
|
93
|
+
enumerable: true,
|
|
94
|
+
configurable: true,
|
|
95
|
+
writable: true,
|
|
96
|
+
value: void 0
|
|
97
|
+
});
|
|
92
98
|
Object.defineProperty(this, "_fetchImpl", {
|
|
93
99
|
enumerable: true,
|
|
94
100
|
configurable: true,
|
|
@@ -103,6 +109,7 @@ class SandboxClient {
|
|
|
103
109
|
});
|
|
104
110
|
this._baseUrl = (config.apiEndpoint ?? getDefaultApiEndpoint()).replace(/\/$/, "");
|
|
105
111
|
this._apiKey = config.apiKey ?? getDefaultApiKey();
|
|
112
|
+
this._defaultHeaders = { ...(config.headers ?? {}) };
|
|
106
113
|
this._fetchImpl = (0, fetch_js_1._getFetchImplementation)();
|
|
107
114
|
this._caller = new async_caller_js_1.AsyncCaller({
|
|
108
115
|
maxRetries: config.maxRetries ?? 3,
|
|
@@ -122,6 +129,11 @@ class SandboxClient {
|
|
|
122
129
|
if (this._apiKey) {
|
|
123
130
|
headers.set("X-Api-Key", this._apiKey);
|
|
124
131
|
}
|
|
132
|
+
for (const [name, value] of Object.entries(this._defaultHeaders)) {
|
|
133
|
+
if (!headers.has(name)) {
|
|
134
|
+
headers.set(name, value);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
125
137
|
return this._caller.call(() => this._fetchImpl(url, {
|
|
126
138
|
...init,
|
|
127
139
|
headers,
|
|
@@ -134,6 +146,15 @@ class SandboxClient {
|
|
|
134
146
|
getApiKey() {
|
|
135
147
|
return this._apiKey;
|
|
136
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Get the constructor-supplied default headers. Used by the WebSocket exec
|
|
151
|
+
* path so headers like `X-Service-Key` set on the client are attached to
|
|
152
|
+
* the WS upgrade request.
|
|
153
|
+
* @internal
|
|
154
|
+
*/
|
|
155
|
+
getDefaultHeaders() {
|
|
156
|
+
return { ...this._defaultHeaders };
|
|
157
|
+
}
|
|
137
158
|
/**
|
|
138
159
|
* JSON POST helper. Sends JSON body, checks response status,
|
|
139
160
|
* and returns the Response for further processing.
|
package/dist/sandbox/client.d.ts
CHANGED
package/dist/sandbox/client.js
CHANGED
|
@@ -86,6 +86,12 @@ export class SandboxClient {
|
|
|
86
86
|
writable: true,
|
|
87
87
|
value: void 0
|
|
88
88
|
});
|
|
89
|
+
Object.defineProperty(this, "_defaultHeaders", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
configurable: true,
|
|
92
|
+
writable: true,
|
|
93
|
+
value: void 0
|
|
94
|
+
});
|
|
89
95
|
Object.defineProperty(this, "_fetchImpl", {
|
|
90
96
|
enumerable: true,
|
|
91
97
|
configurable: true,
|
|
@@ -100,6 +106,7 @@ export class SandboxClient {
|
|
|
100
106
|
});
|
|
101
107
|
this._baseUrl = (config.apiEndpoint ?? getDefaultApiEndpoint()).replace(/\/$/, "");
|
|
102
108
|
this._apiKey = config.apiKey ?? getDefaultApiKey();
|
|
109
|
+
this._defaultHeaders = { ...(config.headers ?? {}) };
|
|
103
110
|
this._fetchImpl = _getFetchImplementation();
|
|
104
111
|
this._caller = new AsyncCaller({
|
|
105
112
|
maxRetries: config.maxRetries ?? 3,
|
|
@@ -119,6 +126,11 @@ export class SandboxClient {
|
|
|
119
126
|
if (this._apiKey) {
|
|
120
127
|
headers.set("X-Api-Key", this._apiKey);
|
|
121
128
|
}
|
|
129
|
+
for (const [name, value] of Object.entries(this._defaultHeaders)) {
|
|
130
|
+
if (!headers.has(name)) {
|
|
131
|
+
headers.set(name, value);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
122
134
|
return this._caller.call(() => this._fetchImpl(url, {
|
|
123
135
|
...init,
|
|
124
136
|
headers,
|
|
@@ -131,6 +143,15 @@ export class SandboxClient {
|
|
|
131
143
|
getApiKey() {
|
|
132
144
|
return this._apiKey;
|
|
133
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Get the constructor-supplied default headers. Used by the WebSocket exec
|
|
148
|
+
* path so headers like `X-Service-Key` set on the client are attached to
|
|
149
|
+
* the WS upgrade request.
|
|
150
|
+
* @internal
|
|
151
|
+
*/
|
|
152
|
+
getDefaultHeaders() {
|
|
153
|
+
return { ...this._defaultHeaders };
|
|
154
|
+
}
|
|
134
155
|
/**
|
|
135
156
|
* JSON POST helper. Sends JSON body, checks response status,
|
|
136
157
|
* and returns the Response for further processing.
|
package/dist/sandbox/sandbox.cjs
CHANGED
|
@@ -227,6 +227,7 @@ class Sandbox {
|
|
|
227
227
|
async _runWs(command, options = {}) {
|
|
228
228
|
const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, idleTimeout, killOnDisconnect, ttlSeconds, pty, } = options;
|
|
229
229
|
const dataplaneUrl = this.requireDataplaneUrl();
|
|
230
|
+
const clientHeaders = this._client.getDefaultHeaders();
|
|
230
231
|
const [stream, control] = await (0, ws_execute_js_1.runWsStream)(dataplaneUrl, this._client.getApiKey(), command, {
|
|
231
232
|
timeout,
|
|
232
233
|
env,
|
|
@@ -238,6 +239,9 @@ class Sandbox {
|
|
|
238
239
|
killOnDisconnect,
|
|
239
240
|
ttlSeconds,
|
|
240
241
|
pty,
|
|
242
|
+
...(Object.keys(clientHeaders).length > 0
|
|
243
|
+
? { headers: clientHeaders }
|
|
244
|
+
: {}),
|
|
241
245
|
});
|
|
242
246
|
const handle = new command_handle_js_1.CommandHandle(stream, control, this);
|
|
243
247
|
await handle._ensureStarted();
|
|
@@ -292,7 +296,14 @@ class Sandbox {
|
|
|
292
296
|
async reconnect(commandId, options = {}) {
|
|
293
297
|
const { stdoutOffset = 0, stderrOffset = 0 } = options;
|
|
294
298
|
const dataplaneUrl = this.requireDataplaneUrl();
|
|
295
|
-
const
|
|
299
|
+
const clientHeaders = this._client.getDefaultHeaders();
|
|
300
|
+
const [stream, control] = await (0, ws_execute_js_1.reconnectWsStream)(dataplaneUrl, this._client.getApiKey(), commandId, {
|
|
301
|
+
stdoutOffset,
|
|
302
|
+
stderrOffset,
|
|
303
|
+
...(Object.keys(clientHeaders).length > 0
|
|
304
|
+
? { headers: clientHeaders }
|
|
305
|
+
: {}),
|
|
306
|
+
});
|
|
296
307
|
return new command_handle_js_1.CommandHandle(stream, control, this, {
|
|
297
308
|
commandId,
|
|
298
309
|
stdoutOffset,
|
package/dist/sandbox/sandbox.js
CHANGED
|
@@ -224,6 +224,7 @@ export class Sandbox {
|
|
|
224
224
|
async _runWs(command, options = {}) {
|
|
225
225
|
const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, idleTimeout, killOnDisconnect, ttlSeconds, pty, } = options;
|
|
226
226
|
const dataplaneUrl = this.requireDataplaneUrl();
|
|
227
|
+
const clientHeaders = this._client.getDefaultHeaders();
|
|
227
228
|
const [stream, control] = await runWsStream(dataplaneUrl, this._client.getApiKey(), command, {
|
|
228
229
|
timeout,
|
|
229
230
|
env,
|
|
@@ -235,6 +236,9 @@ export class Sandbox {
|
|
|
235
236
|
killOnDisconnect,
|
|
236
237
|
ttlSeconds,
|
|
237
238
|
pty,
|
|
239
|
+
...(Object.keys(clientHeaders).length > 0
|
|
240
|
+
? { headers: clientHeaders }
|
|
241
|
+
: {}),
|
|
238
242
|
});
|
|
239
243
|
const handle = new CommandHandle(stream, control, this);
|
|
240
244
|
await handle._ensureStarted();
|
|
@@ -289,7 +293,14 @@ export class Sandbox {
|
|
|
289
293
|
async reconnect(commandId, options = {}) {
|
|
290
294
|
const { stdoutOffset = 0, stderrOffset = 0 } = options;
|
|
291
295
|
const dataplaneUrl = this.requireDataplaneUrl();
|
|
292
|
-
const
|
|
296
|
+
const clientHeaders = this._client.getDefaultHeaders();
|
|
297
|
+
const [stream, control] = await reconnectWsStream(dataplaneUrl, this._client.getApiKey(), commandId, {
|
|
298
|
+
stdoutOffset,
|
|
299
|
+
stderrOffset,
|
|
300
|
+
...(Object.keys(clientHeaders).length > 0
|
|
301
|
+
? { headers: clientHeaders }
|
|
302
|
+
: {}),
|
|
303
|
+
});
|
|
293
304
|
return new CommandHandle(stream, control, this, {
|
|
294
305
|
commandId,
|
|
295
306
|
stdoutOffset,
|
package/dist/sandbox/types.d.ts
CHANGED
|
@@ -108,6 +108,13 @@ export interface SandboxClientConfig {
|
|
|
108
108
|
* Defaults to Infinity (no limit).
|
|
109
109
|
*/
|
|
110
110
|
maxConcurrency?: number;
|
|
111
|
+
/**
|
|
112
|
+
* Optional default headers attached to every request on this client,
|
|
113
|
+
* including the data-plane `/execute` HTTP endpoint and the `/execute/ws`
|
|
114
|
+
* WebSocket upgrade. Use this to pass additional auth headers
|
|
115
|
+
* (e.g. `X-Service-Key`).
|
|
116
|
+
*/
|
|
117
|
+
headers?: Record<string, string>;
|
|
111
118
|
}
|
|
112
119
|
/**
|
|
113
120
|
* A single chunk of streaming output from command execution.
|
|
@@ -163,6 +170,11 @@ export interface WsRunOptions {
|
|
|
163
170
|
ttlSeconds?: number;
|
|
164
171
|
/** Whether to allocate a PTY. */
|
|
165
172
|
pty?: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Additional headers attached to the WebSocket upgrade request. Merged on
|
|
175
|
+
* top of any default headers the SandboxClient was constructed with.
|
|
176
|
+
*/
|
|
177
|
+
headers?: Record<string, string>;
|
|
166
178
|
}
|
|
167
179
|
/**
|
|
168
180
|
* Options for running a command in a sandbox.
|
|
@@ -38,11 +38,15 @@ function buildWsUrl(dataplaneUrl) {
|
|
|
38
38
|
/**
|
|
39
39
|
* Build auth headers for the WebSocket upgrade request.
|
|
40
40
|
*/
|
|
41
|
-
function buildAuthHeaders(apiKey) {
|
|
41
|
+
function buildAuthHeaders(apiKey, extraHeaders) {
|
|
42
|
+
const headers = {};
|
|
42
43
|
if (apiKey) {
|
|
43
|
-
|
|
44
|
+
headers["X-Api-Key"] = apiKey;
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
+
if (extraHeaders) {
|
|
47
|
+
Object.assign(headers, extraHeaders);
|
|
48
|
+
}
|
|
49
|
+
return headers;
|
|
46
50
|
}
|
|
47
51
|
// =============================================================================
|
|
48
52
|
// Stream Control
|
|
@@ -238,9 +242,9 @@ async function* readWsMessages(ws) {
|
|
|
238
242
|
* data arrives in addition to yielding the messages.
|
|
239
243
|
*/
|
|
240
244
|
async function runWsStream(dataplaneUrl, apiKey, command, options = {}) {
|
|
241
|
-
const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, commandId, idleTimeout = 300, killOnDisconnect = false, ttlSeconds = 600, pty, } = options;
|
|
245
|
+
const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, commandId, idleTimeout = 300, killOnDisconnect = false, ttlSeconds = 600, pty, headers: extraHeaders, } = options;
|
|
242
246
|
const wsUrl = buildWsUrl(dataplaneUrl);
|
|
243
|
-
const headers = buildAuthHeaders(apiKey);
|
|
247
|
+
const headers = buildAuthHeaders(apiKey, extraHeaders);
|
|
244
248
|
const control = new WSStreamControl();
|
|
245
249
|
async function* stream() {
|
|
246
250
|
let ws;
|
|
@@ -308,9 +312,9 @@ async function runWsStream(dataplaneUrl, apiKey, command, options = {}) {
|
|
|
308
312
|
* No 'started' message is sent on reconnection.
|
|
309
313
|
*/
|
|
310
314
|
async function reconnectWsStream(dataplaneUrl, apiKey, commandId, options = {}) {
|
|
311
|
-
const { stdoutOffset = 0, stderrOffset = 0 } = options;
|
|
315
|
+
const { stdoutOffset = 0, stderrOffset = 0, headers: extraHeaders } = options;
|
|
312
316
|
const wsUrl = buildWsUrl(dataplaneUrl);
|
|
313
|
-
const headers = buildAuthHeaders(apiKey);
|
|
317
|
+
const headers = buildAuthHeaders(apiKey, extraHeaders);
|
|
314
318
|
const control = new WSStreamControl();
|
|
315
319
|
async function* stream() {
|
|
316
320
|
let ws;
|
|
@@ -13,7 +13,7 @@ export declare function buildWsUrl(dataplaneUrl: string): string;
|
|
|
13
13
|
/**
|
|
14
14
|
* Build auth headers for the WebSocket upgrade request.
|
|
15
15
|
*/
|
|
16
|
-
export declare function buildAuthHeaders(apiKey: string | undefined): Record<string, string>;
|
|
16
|
+
export declare function buildAuthHeaders(apiKey: string | undefined, extraHeaders?: Record<string, string>): Record<string, string>;
|
|
17
17
|
/**
|
|
18
18
|
* Control interface for an active WebSocket stream.
|
|
19
19
|
*
|
|
@@ -66,5 +66,6 @@ export declare function runWsStream(dataplaneUrl: string, apiKey: string | undef
|
|
|
66
66
|
export declare function reconnectWsStream(dataplaneUrl: string, apiKey: string | undefined, commandId: string, options?: {
|
|
67
67
|
stdoutOffset?: number;
|
|
68
68
|
stderrOffset?: number;
|
|
69
|
+
headers?: Record<string, string>;
|
|
69
70
|
}): Promise<[AsyncIterableIterator<WsMessage>, WSStreamControl]>;
|
|
70
71
|
export {};
|
|
@@ -30,11 +30,15 @@ export function buildWsUrl(dataplaneUrl) {
|
|
|
30
30
|
/**
|
|
31
31
|
* Build auth headers for the WebSocket upgrade request.
|
|
32
32
|
*/
|
|
33
|
-
export function buildAuthHeaders(apiKey) {
|
|
33
|
+
export function buildAuthHeaders(apiKey, extraHeaders) {
|
|
34
|
+
const headers = {};
|
|
34
35
|
if (apiKey) {
|
|
35
|
-
|
|
36
|
+
headers["X-Api-Key"] = apiKey;
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
if (extraHeaders) {
|
|
39
|
+
Object.assign(headers, extraHeaders);
|
|
40
|
+
}
|
|
41
|
+
return headers;
|
|
38
42
|
}
|
|
39
43
|
// =============================================================================
|
|
40
44
|
// Stream Control
|
|
@@ -229,9 +233,9 @@ async function* readWsMessages(ws) {
|
|
|
229
233
|
* data arrives in addition to yielding the messages.
|
|
230
234
|
*/
|
|
231
235
|
export async function runWsStream(dataplaneUrl, apiKey, command, options = {}) {
|
|
232
|
-
const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, commandId, idleTimeout = 300, killOnDisconnect = false, ttlSeconds = 600, pty, } = options;
|
|
236
|
+
const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, commandId, idleTimeout = 300, killOnDisconnect = false, ttlSeconds = 600, pty, headers: extraHeaders, } = options;
|
|
233
237
|
const wsUrl = buildWsUrl(dataplaneUrl);
|
|
234
|
-
const headers = buildAuthHeaders(apiKey);
|
|
238
|
+
const headers = buildAuthHeaders(apiKey, extraHeaders);
|
|
235
239
|
const control = new WSStreamControl();
|
|
236
240
|
async function* stream() {
|
|
237
241
|
let ws;
|
|
@@ -299,9 +303,9 @@ export async function runWsStream(dataplaneUrl, apiKey, command, options = {}) {
|
|
|
299
303
|
* No 'started' message is sent on reconnection.
|
|
300
304
|
*/
|
|
301
305
|
export async function reconnectWsStream(dataplaneUrl, apiKey, commandId, options = {}) {
|
|
302
|
-
const { stdoutOffset = 0, stderrOffset = 0 } = options;
|
|
306
|
+
const { stdoutOffset = 0, stderrOffset = 0, headers: extraHeaders } = options;
|
|
303
307
|
const wsUrl = buildWsUrl(dataplaneUrl);
|
|
304
|
-
const headers = buildAuthHeaders(apiKey);
|
|
308
|
+
const headers = buildAuthHeaders(apiKey, extraHeaders);
|
|
305
309
|
const control = new WSStreamControl();
|
|
306
310
|
async function* stream() {
|
|
307
311
|
let ws;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPrimitive = exports.isRecord = void 0;
|
|
4
|
+
const isRecord = (value) => {
|
|
5
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
+
};
|
|
7
|
+
exports.isRecord = isRecord;
|
|
8
|
+
const isPrimitive = (value) => {
|
|
9
|
+
return (typeof value === "string" ||
|
|
10
|
+
typeof value === "number" ||
|
|
11
|
+
typeof value === "boolean");
|
|
12
|
+
};
|
|
13
|
+
exports.isPrimitive = isPrimitive;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const isRecord = (value) => {
|
|
2
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
+
};
|
|
4
|
+
export const isPrimitive = (value) => {
|
|
5
|
+
return (typeof value === "string" ||
|
|
6
|
+
typeof value === "number" ||
|
|
7
|
+
typeof value === "boolean");
|
|
8
|
+
};
|
package/dist/utils/vercel.cjs
CHANGED
|
@@ -4,6 +4,7 @@ exports.extractOutputTokenDetails = extractOutputTokenDetails;
|
|
|
4
4
|
exports.extractInputTokenDetails = extractInputTokenDetails;
|
|
5
5
|
exports.extractUsageMetadata = extractUsageMetadata;
|
|
6
6
|
const usage_js_1 = require("./usage.cjs");
|
|
7
|
+
const types_js_1 = require("./types.cjs");
|
|
7
8
|
function extractTraceableServiceTier(providerMetadata) {
|
|
8
9
|
if (providerMetadata?.openai != null &&
|
|
9
10
|
typeof providerMetadata.openai === "object") {
|
|
@@ -19,6 +20,14 @@ function extractTraceableServiceTier(providerMetadata) {
|
|
|
19
20
|
function isLanguageModelV3Usage(usage) {
|
|
20
21
|
return usage.inputTokens != null && typeof usage.inputTokens === "object";
|
|
21
22
|
}
|
|
23
|
+
function isTelemetryLanguageModelUsage(usage) {
|
|
24
|
+
if (!(0, types_js_1.isRecord)(usage))
|
|
25
|
+
return false;
|
|
26
|
+
return ((usage.inputTokens == null || typeof usage.inputTokens === "number") &&
|
|
27
|
+
(0, types_js_1.isRecord)(usage.inputTokenDetails) &&
|
|
28
|
+
(usage.outputTokens == null || typeof usage.outputTokens === "number") &&
|
|
29
|
+
(0, types_js_1.isRecord)(usage.outputTokenDetails));
|
|
30
|
+
}
|
|
22
31
|
function extractAISDK6OutputTokenDetails(usage, providerMetadata) {
|
|
23
32
|
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
24
33
|
const outputTokenDetailsKeyPrefix = openAIServiceTier
|
|
@@ -42,32 +51,51 @@ function extractAISDK6OutputTokenDetails(usage, providerMetadata) {
|
|
|
42
51
|
}
|
|
43
52
|
return outputTokenDetails;
|
|
44
53
|
}
|
|
54
|
+
// TODO: verify service tier token counting
|
|
55
|
+
function extractTelemetryOutputTokenDetails(usage, providerMetadata) {
|
|
56
|
+
const result = {};
|
|
57
|
+
const serviceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
58
|
+
const prefix = serviceTier ? `${serviceTier}_` : "";
|
|
59
|
+
const reasoning = usage.outputTokenDetails?.reasoningTokens ?? undefined;
|
|
60
|
+
if (typeof reasoning === "number" && reasoning > 0) {
|
|
61
|
+
const key = `${prefix}reasoning`;
|
|
62
|
+
result[key] = reasoning;
|
|
63
|
+
}
|
|
64
|
+
// Apply service tier logic
|
|
65
|
+
if (serviceTier != null) {
|
|
66
|
+
// Avoid counting reasoning tokens towards the output token count
|
|
67
|
+
// since service tier tokens are already priced differently
|
|
68
|
+
result[serviceTier] = (usage.outputTokens ?? 0) - (reasoning ?? 0);
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
45
72
|
function extractOutputTokenDetails(usage, providerMetadata) {
|
|
46
73
|
if (usage == null) {
|
|
47
74
|
return {};
|
|
48
75
|
}
|
|
76
|
+
// AI SDK 7: Use Telemetry Language Model Usage
|
|
77
|
+
if (isTelemetryLanguageModelUsage(usage)) {
|
|
78
|
+
return extractTelemetryOutputTokenDetails(usage, providerMetadata);
|
|
79
|
+
}
|
|
49
80
|
// AI SDK 6: Check for built-in outputTokens breakdown first
|
|
50
81
|
if (isLanguageModelV3Usage(usage)) {
|
|
51
82
|
// Return AI SDK 6 results (even if empty, to prevent falling through to SDK 5 logic)
|
|
52
83
|
return extractAISDK6OutputTokenDetails(usage, providerMetadata);
|
|
53
84
|
}
|
|
85
|
+
// AI SDK <= 5
|
|
54
86
|
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
: "";
|
|
58
|
-
const outputTokenDetails = {};
|
|
87
|
+
const prefix = openAIServiceTier ? `${openAIServiceTier}_` : "";
|
|
88
|
+
const result = {};
|
|
59
89
|
if (typeof usage?.reasoningTokens === "number") {
|
|
60
|
-
|
|
61
|
-
usage.reasoningTokens;
|
|
90
|
+
result[`${prefix}reasoning`] = usage.reasoningTokens;
|
|
62
91
|
}
|
|
63
92
|
if (openAIServiceTier && typeof usage?.outputTokens === "number") {
|
|
64
93
|
// Avoid counting reasoning tokens towards the output token count
|
|
65
94
|
// since service tier tokens are already priced differently
|
|
66
|
-
|
|
67
|
-
usage.outputTokens -
|
|
68
|
-
(outputTokenDetails[`${outputTokenDetailsKeyPrefix}reasoning`] ?? 0);
|
|
95
|
+
result[openAIServiceTier] =
|
|
96
|
+
usage.outputTokens - (result[`${prefix}reasoning`] ?? 0);
|
|
69
97
|
}
|
|
70
|
-
return
|
|
98
|
+
return result;
|
|
71
99
|
}
|
|
72
100
|
function extractAISDK6InputTokenDetails(usage, providerMetadata) {
|
|
73
101
|
let inputTokenDetails = {};
|
|
@@ -116,10 +144,40 @@ function extractAISDK6InputTokenDetails(usage, providerMetadata) {
|
|
|
116
144
|
}
|
|
117
145
|
return inputTokenDetails;
|
|
118
146
|
}
|
|
147
|
+
function extractTelemetryInputTokenDetails(usage, providerMetadata) {
|
|
148
|
+
const result = {};
|
|
149
|
+
const cacheRead = usage.inputTokenDetails?.cacheReadTokens ?? undefined;
|
|
150
|
+
const cacheWrite = usage.inputTokenDetails?.cacheWriteTokens ?? undefined;
|
|
151
|
+
if (typeof cacheRead === "number" && cacheRead > 0) {
|
|
152
|
+
result.cache_read = cacheRead;
|
|
153
|
+
}
|
|
154
|
+
if (typeof cacheWrite === "number" && cacheWrite > 0) {
|
|
155
|
+
result.cache_creation = cacheWrite;
|
|
156
|
+
}
|
|
157
|
+
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
158
|
+
const prefix = openAIServiceTier
|
|
159
|
+
? `${openAIServiceTier}_`
|
|
160
|
+
: "";
|
|
161
|
+
if (openAIServiceTier && typeof usage.inputTokens === "number") {
|
|
162
|
+
if (result.cache_read != null) {
|
|
163
|
+
result[`${prefix}cache_read`] = result.cache_read;
|
|
164
|
+
delete result.cache_read;
|
|
165
|
+
}
|
|
166
|
+
if (typeof usage?.inputTokens === "number") {
|
|
167
|
+
result[openAIServiceTier] =
|
|
168
|
+
usage.inputTokens - (result[`${prefix}cache_read`] ?? 0);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
119
173
|
function extractInputTokenDetails(usage, providerMetadata) {
|
|
120
174
|
if (usage == null) {
|
|
121
175
|
return {};
|
|
122
176
|
}
|
|
177
|
+
// AI SDK 7: Use Telemetry Language Model Usage
|
|
178
|
+
if (isTelemetryLanguageModelUsage(usage)) {
|
|
179
|
+
return extractTelemetryInputTokenDetails(usage, providerMetadata);
|
|
180
|
+
}
|
|
123
181
|
// AI SDK 6: Check for built-in inputTokens breakdown first
|
|
124
182
|
if (isLanguageModelV3Usage(usage)) {
|
|
125
183
|
// Return AI SDK 6 results (even if empty, to prevent falling through to SDK 5 logic)
|
package/dist/utils/vercel.d.ts
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import type { LanguageModelV2Usage, LanguageModelV3Usage } from "@ai-sdk/provider";
|
|
2
2
|
import { KVMap } from "../schemas.js";
|
|
3
|
-
export declare function extractOutputTokenDetails(usage?: Partial<LanguageModelV2Usage> | Partial<LanguageModelV3Usage>, providerMetadata?: Record<string, unknown>): Record<string, number
|
|
4
|
-
|
|
3
|
+
export declare function extractOutputTokenDetails(usage?: Partial<LanguageModelV2Usage> | Partial<LanguageModelV3Usage>, providerMetadata?: Record<string, unknown>): Record<string, number> | {
|
|
4
|
+
reasoning?: number;
|
|
5
|
+
flex?: number;
|
|
6
|
+
flex_reasoning?: number;
|
|
7
|
+
priority?: number;
|
|
8
|
+
priority_reasoning?: number;
|
|
9
|
+
};
|
|
10
|
+
export declare function extractInputTokenDetails(usage?: Partial<LanguageModelV2Usage> | Partial<LanguageModelV3Usage>, providerMetadata?: Record<string, unknown>): Record<string, number> | {
|
|
11
|
+
cache_read?: number;
|
|
12
|
+
cache_creation?: number;
|
|
13
|
+
flex?: number;
|
|
14
|
+
flex_cache_read?: number;
|
|
15
|
+
flex_cache_creation?: number;
|
|
16
|
+
priority?: number;
|
|
17
|
+
priority_cache_read?: number;
|
|
18
|
+
priority_cache_creation?: number;
|
|
19
|
+
};
|
|
5
20
|
export declare function extractUsageMetadata(span?: {
|
|
6
21
|
status?: {
|
|
7
22
|
code: number;
|
package/dist/utils/vercel.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { convertAnthropicUsageToInputTokenDetails } from "./usage.js";
|
|
2
|
+
import { isRecord } from "./types.js";
|
|
2
3
|
function extractTraceableServiceTier(providerMetadata) {
|
|
3
4
|
if (providerMetadata?.openai != null &&
|
|
4
5
|
typeof providerMetadata.openai === "object") {
|
|
@@ -14,6 +15,14 @@ function extractTraceableServiceTier(providerMetadata) {
|
|
|
14
15
|
function isLanguageModelV3Usage(usage) {
|
|
15
16
|
return usage.inputTokens != null && typeof usage.inputTokens === "object";
|
|
16
17
|
}
|
|
18
|
+
function isTelemetryLanguageModelUsage(usage) {
|
|
19
|
+
if (!isRecord(usage))
|
|
20
|
+
return false;
|
|
21
|
+
return ((usage.inputTokens == null || typeof usage.inputTokens === "number") &&
|
|
22
|
+
isRecord(usage.inputTokenDetails) &&
|
|
23
|
+
(usage.outputTokens == null || typeof usage.outputTokens === "number") &&
|
|
24
|
+
isRecord(usage.outputTokenDetails));
|
|
25
|
+
}
|
|
17
26
|
function extractAISDK6OutputTokenDetails(usage, providerMetadata) {
|
|
18
27
|
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
19
28
|
const outputTokenDetailsKeyPrefix = openAIServiceTier
|
|
@@ -37,32 +46,51 @@ function extractAISDK6OutputTokenDetails(usage, providerMetadata) {
|
|
|
37
46
|
}
|
|
38
47
|
return outputTokenDetails;
|
|
39
48
|
}
|
|
49
|
+
// TODO: verify service tier token counting
|
|
50
|
+
function extractTelemetryOutputTokenDetails(usage, providerMetadata) {
|
|
51
|
+
const result = {};
|
|
52
|
+
const serviceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
53
|
+
const prefix = serviceTier ? `${serviceTier}_` : "";
|
|
54
|
+
const reasoning = usage.outputTokenDetails?.reasoningTokens ?? undefined;
|
|
55
|
+
if (typeof reasoning === "number" && reasoning > 0) {
|
|
56
|
+
const key = `${prefix}reasoning`;
|
|
57
|
+
result[key] = reasoning;
|
|
58
|
+
}
|
|
59
|
+
// Apply service tier logic
|
|
60
|
+
if (serviceTier != null) {
|
|
61
|
+
// Avoid counting reasoning tokens towards the output token count
|
|
62
|
+
// since service tier tokens are already priced differently
|
|
63
|
+
result[serviceTier] = (usage.outputTokens ?? 0) - (reasoning ?? 0);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
40
67
|
export function extractOutputTokenDetails(usage, providerMetadata) {
|
|
41
68
|
if (usage == null) {
|
|
42
69
|
return {};
|
|
43
70
|
}
|
|
71
|
+
// AI SDK 7: Use Telemetry Language Model Usage
|
|
72
|
+
if (isTelemetryLanguageModelUsage(usage)) {
|
|
73
|
+
return extractTelemetryOutputTokenDetails(usage, providerMetadata);
|
|
74
|
+
}
|
|
44
75
|
// AI SDK 6: Check for built-in outputTokens breakdown first
|
|
45
76
|
if (isLanguageModelV3Usage(usage)) {
|
|
46
77
|
// Return AI SDK 6 results (even if empty, to prevent falling through to SDK 5 logic)
|
|
47
78
|
return extractAISDK6OutputTokenDetails(usage, providerMetadata);
|
|
48
79
|
}
|
|
80
|
+
// AI SDK <= 5
|
|
49
81
|
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
: "";
|
|
53
|
-
const outputTokenDetails = {};
|
|
82
|
+
const prefix = openAIServiceTier ? `${openAIServiceTier}_` : "";
|
|
83
|
+
const result = {};
|
|
54
84
|
if (typeof usage?.reasoningTokens === "number") {
|
|
55
|
-
|
|
56
|
-
usage.reasoningTokens;
|
|
85
|
+
result[`${prefix}reasoning`] = usage.reasoningTokens;
|
|
57
86
|
}
|
|
58
87
|
if (openAIServiceTier && typeof usage?.outputTokens === "number") {
|
|
59
88
|
// Avoid counting reasoning tokens towards the output token count
|
|
60
89
|
// since service tier tokens are already priced differently
|
|
61
|
-
|
|
62
|
-
usage.outputTokens -
|
|
63
|
-
(outputTokenDetails[`${outputTokenDetailsKeyPrefix}reasoning`] ?? 0);
|
|
90
|
+
result[openAIServiceTier] =
|
|
91
|
+
usage.outputTokens - (result[`${prefix}reasoning`] ?? 0);
|
|
64
92
|
}
|
|
65
|
-
return
|
|
93
|
+
return result;
|
|
66
94
|
}
|
|
67
95
|
function extractAISDK6InputTokenDetails(usage, providerMetadata) {
|
|
68
96
|
let inputTokenDetails = {};
|
|
@@ -111,10 +139,40 @@ function extractAISDK6InputTokenDetails(usage, providerMetadata) {
|
|
|
111
139
|
}
|
|
112
140
|
return inputTokenDetails;
|
|
113
141
|
}
|
|
142
|
+
function extractTelemetryInputTokenDetails(usage, providerMetadata) {
|
|
143
|
+
const result = {};
|
|
144
|
+
const cacheRead = usage.inputTokenDetails?.cacheReadTokens ?? undefined;
|
|
145
|
+
const cacheWrite = usage.inputTokenDetails?.cacheWriteTokens ?? undefined;
|
|
146
|
+
if (typeof cacheRead === "number" && cacheRead > 0) {
|
|
147
|
+
result.cache_read = cacheRead;
|
|
148
|
+
}
|
|
149
|
+
if (typeof cacheWrite === "number" && cacheWrite > 0) {
|
|
150
|
+
result.cache_creation = cacheWrite;
|
|
151
|
+
}
|
|
152
|
+
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
153
|
+
const prefix = openAIServiceTier
|
|
154
|
+
? `${openAIServiceTier}_`
|
|
155
|
+
: "";
|
|
156
|
+
if (openAIServiceTier && typeof usage.inputTokens === "number") {
|
|
157
|
+
if (result.cache_read != null) {
|
|
158
|
+
result[`${prefix}cache_read`] = result.cache_read;
|
|
159
|
+
delete result.cache_read;
|
|
160
|
+
}
|
|
161
|
+
if (typeof usage?.inputTokens === "number") {
|
|
162
|
+
result[openAIServiceTier] =
|
|
163
|
+
usage.inputTokens - (result[`${prefix}cache_read`] ?? 0);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
114
168
|
export function extractInputTokenDetails(usage, providerMetadata) {
|
|
115
169
|
if (usage == null) {
|
|
116
170
|
return {};
|
|
117
171
|
}
|
|
172
|
+
// AI SDK 7: Use Telemetry Language Model Usage
|
|
173
|
+
if (isTelemetryLanguageModelUsage(usage)) {
|
|
174
|
+
return extractTelemetryInputTokenDetails(usage, providerMetadata);
|
|
175
|
+
}
|
|
118
176
|
// AI SDK 6: Check for built-in inputTokens breakdown first
|
|
119
177
|
if (isLanguageModelV3Usage(usage)) {
|
|
120
178
|
// Return AI SDK 6 results (even if empty, to prevent falling through to SDK 5 logic)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('../dist/sandbox/index.cjs');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../dist/sandbox/index.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../dist/sandbox/index.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../dist/sandbox/index.js'
|