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.
Files changed (39) hide show
  1. package/dist/client.cjs +1 -1
  2. package/dist/client.js +1 -1
  3. package/dist/experimental/vercel/index.cjs +18 -637
  4. package/dist/experimental/vercel/index.d.ts +3 -257
  5. package/dist/experimental/vercel/index.js +2 -635
  6. package/dist/experimental/vercel/middleware.cjs +2 -78
  7. package/dist/experimental/vercel/middleware.js +1 -77
  8. package/dist/experimental/vercel/telemetry.cjs +462 -0
  9. package/dist/experimental/vercel/telemetry.d.ts +89 -0
  10. package/dist/experimental/vercel/telemetry.js +459 -0
  11. package/dist/experimental/vercel/utils.cjs +142 -35
  12. package/dist/experimental/vercel/utils.d.ts +28 -3
  13. package/dist/experimental/vercel/utils.js +140 -34
  14. package/dist/experimental/vercel/wrap.cjs +639 -0
  15. package/dist/experimental/vercel/wrap.d.ts +257 -0
  16. package/dist/experimental/vercel/wrap.js +635 -0
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/sandbox/client.cjs +21 -0
  21. package/dist/sandbox/client.d.ts +1 -0
  22. package/dist/sandbox/client.js +21 -0
  23. package/dist/sandbox/sandbox.cjs +12 -1
  24. package/dist/sandbox/sandbox.js +12 -1
  25. package/dist/sandbox/types.d.ts +12 -0
  26. package/dist/sandbox/ws_execute.cjs +11 -7
  27. package/dist/sandbox/ws_execute.d.ts +2 -1
  28. package/dist/sandbox/ws_execute.js +11 -7
  29. package/dist/utils/types.cjs +13 -0
  30. package/dist/utils/types.d.ts +2 -0
  31. package/dist/utils/types.js +8 -0
  32. package/dist/utils/vercel.cjs +68 -10
  33. package/dist/utils/vercel.d.ts +17 -2
  34. package/dist/utils/vercel.js +68 -10
  35. package/experimental/sandbox.cjs +1 -0
  36. package/experimental/sandbox.d.cts +1 -0
  37. package/experimental/sandbox.d.ts +1 -0
  38. package/experimental/sandbox.js +1 -0
  39. package/package.json +22 -7
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertMessageToTracedFormat = exports.normalizeFileDataAsDataURL = void 0;
3
+ exports.setUsageMetadataOnRunTree = exports.convertMessageToTracedFormat = exports.normalizeFileDataAsDataURL = void 0;
4
+ const types_js_1 = require("../../utils/types.cjs");
5
+ const vercel_js_1 = require("../../utils/vercel.cjs");
4
6
  const guessMimetypeFromBase64 = (data) => {
5
7
  // Check magic bytes from base64 data
6
8
  const bytes = atob(data.substring(0, 20)); // Decode first few bytes
@@ -42,62 +44,89 @@ const guessMimetypeFromBase64 = (data) => {
42
44
  }
43
45
  return undefined;
44
46
  };
47
+ function _isAISDKFileData(input) {
48
+ if (!(0, types_js_1.isRecord)(input))
49
+ return false;
50
+ if (input.type === "data" && "data" in input)
51
+ return true;
52
+ if (input.type === "url" && "url" in input)
53
+ return true;
54
+ if (input.type === "reference" && "reference" in input)
55
+ return true;
56
+ if (input.type === "text" && "text" in input)
57
+ return true;
58
+ return false;
59
+ }
60
+ function _toUint8Array(fileData) {
61
+ // Covers `fileData: ArrayBuffer | Buffer | Uint8Array`
62
+ if (fileData instanceof Uint8Array) {
63
+ return fileData;
64
+ }
65
+ if (fileData != null &&
66
+ typeof fileData === "object" &&
67
+ "type" in fileData &&
68
+ "data" in fileData &&
69
+ typeof fileData.data === "object" &&
70
+ // eslint-disable-next-line no-instanceof/no-instanceof
71
+ fileData.data instanceof Uint8Array) {
72
+ return fileData.data;
73
+ // eslint-disable-next-line no-instanceof/no-instanceof
74
+ }
75
+ if (fileData instanceof ArrayBuffer) {
76
+ return new Uint8Array(fileData);
77
+ }
78
+ return undefined;
79
+ }
45
80
  const normalizeFileDataAsDataURL = (fileData, mimeType) => {
46
- // eslint-disable-next-line no-instanceof/no-instanceof
81
+ if (_isAISDKFileData(fileData)) {
82
+ if (fileData.type === "data") {
83
+ return (0, exports.normalizeFileDataAsDataURL)(fileData.data, mimeType);
84
+ }
85
+ if (fileData.type === "url") {
86
+ return fileData.url.toString();
87
+ }
88
+ if (fileData.type === "reference") {
89
+ // TODO: figure out if we can store the reference in a more reasonable format
90
+ return `data:application/octet-stream;base64,${btoa(JSON.stringify(fileData.reference))}`;
91
+ }
92
+ if (fileData.type === "text") {
93
+ return `data:text/plain;base64,${btoa(fileData.text)}`;
94
+ }
95
+ throw new Error("AISDKFileData is not supported");
96
+ }
47
97
  if (fileData instanceof URL) {
48
98
  return fileData.toString();
49
99
  }
50
- let normalizedFileData;
51
100
  if (typeof fileData !== "string") {
52
- let uint8Array;
53
- // eslint-disable-next-line no-instanceof/no-instanceof
54
- if (fileData instanceof Uint8Array) {
55
- uint8Array = fileData;
56
- }
57
- else if (fileData != null &&
58
- typeof fileData === "object" &&
59
- "type" in fileData &&
60
- "data" in fileData &&
61
- typeof fileData.data === "object" &&
62
- // eslint-disable-next-line no-instanceof/no-instanceof
63
- fileData.data instanceof Uint8Array) {
64
- uint8Array = fileData.data;
65
- // eslint-disable-next-line no-instanceof/no-instanceof
66
- }
67
- else if (fileData instanceof ArrayBuffer) {
68
- uint8Array = new Uint8Array(fileData);
69
- }
101
+ const uint8Array = _toUint8Array(fileData);
70
102
  if (uint8Array) {
71
103
  let binary = "";
72
104
  for (let i = 0; i < uint8Array.length; i++) {
73
105
  binary += String.fromCharCode(uint8Array[i]);
74
106
  }
75
107
  const base64 = btoa(binary);
76
- normalizedFileData = `data:${mimeType ??
108
+ const dataType = mimeType ??
77
109
  guessMimetypeFromBase64(base64) ??
78
- "application/octet-stream"};base64,${base64}`;
79
- }
80
- else {
81
- normalizedFileData = "";
110
+ "application/octet-stream";
111
+ return `data:${dataType};base64,${base64}`;
82
112
  }
83
113
  }
84
- else {
114
+ if (typeof fileData === "string") {
85
115
  if (fileData.startsWith("http://") || fileData.startsWith("https://")) {
86
- normalizedFileData = fileData;
116
+ return fileData;
87
117
  }
88
- else if (!fileData.startsWith("data:")) {
89
- normalizedFileData = `data:${mimeType ??
118
+ if (!fileData.startsWith("data:")) {
119
+ return `data:${mimeType ??
90
120
  guessMimetypeFromBase64(fileData) ??
91
121
  "application/octet-stream"};base64,${fileData}`;
92
122
  }
93
- else {
94
- normalizedFileData = fileData;
95
- }
123
+ return fileData;
96
124
  }
97
- return normalizedFileData;
125
+ return "";
98
126
  };
99
127
  exports.normalizeFileDataAsDataURL = normalizeFileDataAsDataURL;
100
- const convertMessageToTracedFormat = (message, responseMetadata) => {
128
+ const convertMessageToTracedFormat = (rawMessage, responseMetadata) => {
129
+ const message = rawMessage;
101
130
  const formattedMessage = {
102
131
  ...message,
103
132
  };
@@ -179,3 +208,81 @@ const convertMessageToTracedFormat = (message, responseMetadata) => {
179
208
  return formattedMessage;
180
209
  };
181
210
  exports.convertMessageToTracedFormat = convertMessageToTracedFormat;
211
+ const setUsageMetadataOnRunTree = (result, runTree) => {
212
+ if (result.usage == null || typeof result.usage !== "object") {
213
+ return;
214
+ }
215
+ const usage = result.usage;
216
+ let inputTokens;
217
+ let outputTokens;
218
+ let totalTokens;
219
+ // AI SDK 6: Check for object-based token structures first
220
+ if ((0, types_js_1.isRecord)(usage.inputTokens) &&
221
+ usage.inputTokens?.total != null &&
222
+ typeof usage.inputTokens.total === "number") {
223
+ // AI SDK 6 detected
224
+ inputTokens = usage.inputTokens.total;
225
+ if ((0, types_js_1.isRecord)(usage.outputTokens) &&
226
+ usage.outputTokens?.total != null &&
227
+ typeof usage.outputTokens.total === "number") {
228
+ outputTokens = usage.outputTokens.total;
229
+ }
230
+ totalTokens = result.usage?.totalTokens;
231
+ if (typeof totalTokens !== "number" &&
232
+ typeof inputTokens === "number" &&
233
+ typeof outputTokens === "number") {
234
+ totalTokens = inputTokens + outputTokens;
235
+ }
236
+ }
237
+ else if (typeof usage.inputTokens === "number") {
238
+ // AI SDK 5 detected
239
+ inputTokens = usage.inputTokens;
240
+ if (typeof usage.outputTokens === "number") {
241
+ outputTokens = usage.outputTokens;
242
+ }
243
+ totalTokens = result.usage?.totalTokens;
244
+ if (typeof totalTokens !== "number" &&
245
+ typeof inputTokens === "number" &&
246
+ typeof outputTokens === "number") {
247
+ totalTokens = inputTokens + outputTokens;
248
+ }
249
+ }
250
+ else {
251
+ // AI SDK 4 fallback
252
+ if (typeof usage.promptTokens === "number") {
253
+ inputTokens = usage.promptTokens;
254
+ }
255
+ if (typeof usage.completionTokens === "number") {
256
+ outputTokens = usage.completionTokens;
257
+ }
258
+ totalTokens = result.usage?.totalTokens;
259
+ if (typeof totalTokens !== "number" &&
260
+ typeof inputTokens === "number" &&
261
+ typeof outputTokens === "number") {
262
+ totalTokens = inputTokens + outputTokens;
263
+ }
264
+ }
265
+ const langsmithUsage = {
266
+ input_tokens: inputTokens,
267
+ output_tokens: outputTokens,
268
+ total_tokens: totalTokens,
269
+ };
270
+ const inputTokenDetails = (0, vercel_js_1.extractInputTokenDetails)(result.usage, result.providerMetadata);
271
+ const outputTokenDetails = (0, vercel_js_1.extractOutputTokenDetails)(result.usage, result.providerMetadata);
272
+ runTree.extra = {
273
+ ...runTree.extra,
274
+ metadata: {
275
+ ...runTree.extra?.metadata,
276
+ usage_metadata: {
277
+ ...langsmithUsage,
278
+ input_token_details: {
279
+ ...inputTokenDetails,
280
+ },
281
+ output_token_details: {
282
+ ...outputTokenDetails,
283
+ },
284
+ },
285
+ },
286
+ };
287
+ };
288
+ exports.setUsageMetadataOnRunTree = setUsageMetadataOnRunTree;
@@ -1,3 +1,28 @@
1
- import type { LanguageModelV2DataContent } from "@ai-sdk/provider";
2
- export declare const normalizeFileDataAsDataURL: (fileData: LanguageModelV2DataContent | ArrayBuffer, mimeType?: string) => string;
3
- export declare const convertMessageToTracedFormat: (message: Record<string, unknown>, responseMetadata?: Record<string, unknown>) => Record<string, unknown>;
1
+ import type { LanguageModelV2DataContent, LanguageModelV2Usage, SharedV2ProviderMetadata } from "@ai-sdk/provider";
2
+ import { RunTree } from "../../run_trees.js";
3
+ type AISDKDataContent = string | Uint8Array | ArrayBuffer | Buffer;
4
+ type AISDKProviderReference = {
5
+ [provider: string]: string;
6
+ } & {
7
+ type?: never;
8
+ };
9
+ type AISDKFileData = {
10
+ type: "data";
11
+ data: AISDKDataContent;
12
+ } | {
13
+ type: "url";
14
+ url: URL;
15
+ } | {
16
+ type: "reference";
17
+ reference: AISDKProviderReference;
18
+ } | {
19
+ type: "text";
20
+ text: string;
21
+ };
22
+ export declare const normalizeFileDataAsDataURL: (fileData: AISDKFileData | AISDKDataContent | LanguageModelV2DataContent | AISDKProviderReference | URL, mimeType: string | undefined) => string;
23
+ export declare const convertMessageToTracedFormat: (rawMessage: Record<string, unknown>, responseMetadata?: Record<string, unknown>) => Record<string, unknown>;
24
+ export declare const setUsageMetadataOnRunTree: (result: {
25
+ usage?: LanguageModelV2Usage;
26
+ providerMetadata?: SharedV2ProviderMetadata;
27
+ }, runTree: RunTree) => void;
28
+ export {};
@@ -1,3 +1,5 @@
1
+ import { isRecord } from "../../utils/types.js";
2
+ import { extractInputTokenDetails, extractOutputTokenDetails, } from "../../utils/vercel.js";
1
3
  const guessMimetypeFromBase64 = (data) => {
2
4
  // Check magic bytes from base64 data
3
5
  const bytes = atob(data.substring(0, 20)); // Decode first few bytes
@@ -39,61 +41,88 @@ const guessMimetypeFromBase64 = (data) => {
39
41
  }
40
42
  return undefined;
41
43
  };
44
+ function _isAISDKFileData(input) {
45
+ if (!isRecord(input))
46
+ return false;
47
+ if (input.type === "data" && "data" in input)
48
+ return true;
49
+ if (input.type === "url" && "url" in input)
50
+ return true;
51
+ if (input.type === "reference" && "reference" in input)
52
+ return true;
53
+ if (input.type === "text" && "text" in input)
54
+ return true;
55
+ return false;
56
+ }
57
+ function _toUint8Array(fileData) {
58
+ // Covers `fileData: ArrayBuffer | Buffer | Uint8Array`
59
+ if (fileData instanceof Uint8Array) {
60
+ return fileData;
61
+ }
62
+ if (fileData != null &&
63
+ typeof fileData === "object" &&
64
+ "type" in fileData &&
65
+ "data" in fileData &&
66
+ typeof fileData.data === "object" &&
67
+ // eslint-disable-next-line no-instanceof/no-instanceof
68
+ fileData.data instanceof Uint8Array) {
69
+ return fileData.data;
70
+ // eslint-disable-next-line no-instanceof/no-instanceof
71
+ }
72
+ if (fileData instanceof ArrayBuffer) {
73
+ return new Uint8Array(fileData);
74
+ }
75
+ return undefined;
76
+ }
42
77
  export const normalizeFileDataAsDataURL = (fileData, mimeType) => {
43
- // eslint-disable-next-line no-instanceof/no-instanceof
78
+ if (_isAISDKFileData(fileData)) {
79
+ if (fileData.type === "data") {
80
+ return normalizeFileDataAsDataURL(fileData.data, mimeType);
81
+ }
82
+ if (fileData.type === "url") {
83
+ return fileData.url.toString();
84
+ }
85
+ if (fileData.type === "reference") {
86
+ // TODO: figure out if we can store the reference in a more reasonable format
87
+ return `data:application/octet-stream;base64,${btoa(JSON.stringify(fileData.reference))}`;
88
+ }
89
+ if (fileData.type === "text") {
90
+ return `data:text/plain;base64,${btoa(fileData.text)}`;
91
+ }
92
+ throw new Error("AISDKFileData is not supported");
93
+ }
44
94
  if (fileData instanceof URL) {
45
95
  return fileData.toString();
46
96
  }
47
- let normalizedFileData;
48
97
  if (typeof fileData !== "string") {
49
- let uint8Array;
50
- // eslint-disable-next-line no-instanceof/no-instanceof
51
- if (fileData instanceof Uint8Array) {
52
- uint8Array = fileData;
53
- }
54
- else if (fileData != null &&
55
- typeof fileData === "object" &&
56
- "type" in fileData &&
57
- "data" in fileData &&
58
- typeof fileData.data === "object" &&
59
- // eslint-disable-next-line no-instanceof/no-instanceof
60
- fileData.data instanceof Uint8Array) {
61
- uint8Array = fileData.data;
62
- // eslint-disable-next-line no-instanceof/no-instanceof
63
- }
64
- else if (fileData instanceof ArrayBuffer) {
65
- uint8Array = new Uint8Array(fileData);
66
- }
98
+ const uint8Array = _toUint8Array(fileData);
67
99
  if (uint8Array) {
68
100
  let binary = "";
69
101
  for (let i = 0; i < uint8Array.length; i++) {
70
102
  binary += String.fromCharCode(uint8Array[i]);
71
103
  }
72
104
  const base64 = btoa(binary);
73
- normalizedFileData = `data:${mimeType ??
105
+ const dataType = mimeType ??
74
106
  guessMimetypeFromBase64(base64) ??
75
- "application/octet-stream"};base64,${base64}`;
76
- }
77
- else {
78
- normalizedFileData = "";
107
+ "application/octet-stream";
108
+ return `data:${dataType};base64,${base64}`;
79
109
  }
80
110
  }
81
- else {
111
+ if (typeof fileData === "string") {
82
112
  if (fileData.startsWith("http://") || fileData.startsWith("https://")) {
83
- normalizedFileData = fileData;
113
+ return fileData;
84
114
  }
85
- else if (!fileData.startsWith("data:")) {
86
- normalizedFileData = `data:${mimeType ??
115
+ if (!fileData.startsWith("data:")) {
116
+ return `data:${mimeType ??
87
117
  guessMimetypeFromBase64(fileData) ??
88
118
  "application/octet-stream"};base64,${fileData}`;
89
119
  }
90
- else {
91
- normalizedFileData = fileData;
92
- }
120
+ return fileData;
93
121
  }
94
- return normalizedFileData;
122
+ return "";
95
123
  };
96
- export const convertMessageToTracedFormat = (message, responseMetadata) => {
124
+ export const convertMessageToTracedFormat = (rawMessage, responseMetadata) => {
125
+ const message = rawMessage;
97
126
  const formattedMessage = {
98
127
  ...message,
99
128
  };
@@ -174,3 +203,80 @@ export const convertMessageToTracedFormat = (message, responseMetadata) => {
174
203
  }
175
204
  return formattedMessage;
176
205
  };
206
+ export const setUsageMetadataOnRunTree = (result, runTree) => {
207
+ if (result.usage == null || typeof result.usage !== "object") {
208
+ return;
209
+ }
210
+ const usage = result.usage;
211
+ let inputTokens;
212
+ let outputTokens;
213
+ let totalTokens;
214
+ // AI SDK 6: Check for object-based token structures first
215
+ if (isRecord(usage.inputTokens) &&
216
+ usage.inputTokens?.total != null &&
217
+ typeof usage.inputTokens.total === "number") {
218
+ // AI SDK 6 detected
219
+ inputTokens = usage.inputTokens.total;
220
+ if (isRecord(usage.outputTokens) &&
221
+ usage.outputTokens?.total != null &&
222
+ typeof usage.outputTokens.total === "number") {
223
+ outputTokens = usage.outputTokens.total;
224
+ }
225
+ totalTokens = result.usage?.totalTokens;
226
+ if (typeof totalTokens !== "number" &&
227
+ typeof inputTokens === "number" &&
228
+ typeof outputTokens === "number") {
229
+ totalTokens = inputTokens + outputTokens;
230
+ }
231
+ }
232
+ else if (typeof usage.inputTokens === "number") {
233
+ // AI SDK 5 detected
234
+ inputTokens = usage.inputTokens;
235
+ if (typeof usage.outputTokens === "number") {
236
+ outputTokens = usage.outputTokens;
237
+ }
238
+ totalTokens = result.usage?.totalTokens;
239
+ if (typeof totalTokens !== "number" &&
240
+ typeof inputTokens === "number" &&
241
+ typeof outputTokens === "number") {
242
+ totalTokens = inputTokens + outputTokens;
243
+ }
244
+ }
245
+ else {
246
+ // AI SDK 4 fallback
247
+ if (typeof usage.promptTokens === "number") {
248
+ inputTokens = usage.promptTokens;
249
+ }
250
+ if (typeof usage.completionTokens === "number") {
251
+ outputTokens = usage.completionTokens;
252
+ }
253
+ totalTokens = result.usage?.totalTokens;
254
+ if (typeof totalTokens !== "number" &&
255
+ typeof inputTokens === "number" &&
256
+ typeof outputTokens === "number") {
257
+ totalTokens = inputTokens + outputTokens;
258
+ }
259
+ }
260
+ const langsmithUsage = {
261
+ input_tokens: inputTokens,
262
+ output_tokens: outputTokens,
263
+ total_tokens: totalTokens,
264
+ };
265
+ const inputTokenDetails = extractInputTokenDetails(result.usage, result.providerMetadata);
266
+ const outputTokenDetails = extractOutputTokenDetails(result.usage, result.providerMetadata);
267
+ runTree.extra = {
268
+ ...runTree.extra,
269
+ metadata: {
270
+ ...runTree.extra?.metadata,
271
+ usage_metadata: {
272
+ ...langsmithUsage,
273
+ input_token_details: {
274
+ ...inputTokenDetails,
275
+ },
276
+ output_token_details: {
277
+ ...outputTokenDetails,
278
+ },
279
+ },
280
+ },
281
+ };
282
+ };