langsmith 0.3.67 → 0.3.69

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 CHANGED
@@ -533,7 +533,7 @@ class Client {
533
533
  signal: AbortSignal.timeout(this.timeout_ms),
534
534
  ...this.fetchOptions,
535
535
  });
536
- await (0, error_js_1.raiseForStatus)(res, `Failed to fetch ${path}`);
536
+ await (0, error_js_1.raiseForStatus)(res, `fetch ${path}`);
537
537
  return res;
538
538
  });
539
539
  return response;
@@ -556,7 +556,7 @@ class Client {
556
556
  signal: AbortSignal.timeout(this.timeout_ms),
557
557
  ...this.fetchOptions,
558
558
  });
559
- await (0, error_js_1.raiseForStatus)(res, `Failed to fetch ${path}`);
559
+ await (0, error_js_1.raiseForStatus)(res, `fetch ${path}`);
560
560
  return res;
561
561
  });
562
562
  const items = transform
@@ -584,7 +584,7 @@ class Client {
584
584
  ...this.fetchOptions,
585
585
  body,
586
586
  });
587
- await (0, error_js_1.raiseForStatus)(res, `Failed to fetch ${path}`);
587
+ await (0, error_js_1.raiseForStatus)(res, `fetch ${path}`);
588
588
  return res;
589
589
  });
590
590
  const responseBody = await response.json();
package/dist/client.js CHANGED
@@ -495,7 +495,7 @@ export class Client {
495
495
  signal: AbortSignal.timeout(this.timeout_ms),
496
496
  ...this.fetchOptions,
497
497
  });
498
- await raiseForStatus(res, `Failed to fetch ${path}`);
498
+ await raiseForStatus(res, `fetch ${path}`);
499
499
  return res;
500
500
  });
501
501
  return response;
@@ -518,7 +518,7 @@ export class Client {
518
518
  signal: AbortSignal.timeout(this.timeout_ms),
519
519
  ...this.fetchOptions,
520
520
  });
521
- await raiseForStatus(res, `Failed to fetch ${path}`);
521
+ await raiseForStatus(res, `fetch ${path}`);
522
522
  return res;
523
523
  });
524
524
  const items = transform
@@ -546,7 +546,7 @@ export class Client {
546
546
  ...this.fetchOptions,
547
547
  body,
548
548
  });
549
- await raiseForStatus(res, `Failed to fetch ${path}`);
549
+ await raiseForStatus(res, `fetch ${path}`);
550
550
  return res;
551
551
  });
552
552
  const responseBody = await response.json();
@@ -203,7 +203,7 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
203
203
  }
204
204
  const { content } = lastStep;
205
205
  return (0, utils_js_1.convertMessageToTracedFormat)({
206
- content,
206
+ content: content ?? outputs.outputs.text,
207
207
  role: "assistant",
208
208
  });
209
209
  }
@@ -325,20 +325,34 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
325
325
  return inputFormatter(inputs);
326
326
  },
327
327
  processOutputs: async (outputs) => {
328
- if (resolvedLsConfig?.processOutputs) {
329
- return resolvedLsConfig.processOutputs(outputs);
330
- }
331
- if (outputs.outputs == null || typeof outputs.outputs !== "object") {
332
- return outputs;
328
+ try {
329
+ if (resolvedLsConfig?.processOutputs) {
330
+ return resolvedLsConfig.processOutputs(outputs);
331
+ }
332
+ if (outputs.outputs == null ||
333
+ typeof outputs.outputs !== "object") {
334
+ return outputs;
335
+ }
336
+ // Important: Even accessing this property creates a promise.
337
+ // This must be awaited.
338
+ let content = await outputs.outputs.content;
339
+ if (content == null) {
340
+ // AI SDK 4 shim
341
+ content = await outputs.outputs.text;
342
+ }
343
+ if (content == null ||
344
+ !["object", "string"].includes(typeof content)) {
345
+ return outputs;
346
+ }
347
+ return (0, utils_js_1.convertMessageToTracedFormat)({
348
+ content,
349
+ role: "assistant",
350
+ });
333
351
  }
334
- const content = await outputs.outputs.content;
335
- if (content == null || typeof content !== "object") {
352
+ catch (e) {
353
+ // Handle parsing failures without a log
336
354
  return outputs;
337
355
  }
338
- return (0, utils_js_1.convertMessageToTracedFormat)({
339
- content,
340
- role: "assistant",
341
- });
342
356
  },
343
357
  });
344
358
  return traceableFunc(...args);
@@ -393,17 +407,24 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
393
407
  return inputFormatter(inputs);
394
408
  },
395
409
  processOutputs: async (outputs) => {
396
- if (resolvedLsConfig?.processOutputs) {
397
- return resolvedLsConfig.processOutputs(outputs);
398
- }
399
- if (outputs.outputs == null || typeof outputs.outputs !== "object") {
400
- return outputs;
410
+ try {
411
+ if (resolvedLsConfig?.processOutputs) {
412
+ return resolvedLsConfig.processOutputs(outputs);
413
+ }
414
+ if (outputs.outputs == null ||
415
+ typeof outputs.outputs !== "object") {
416
+ return outputs;
417
+ }
418
+ const object = await outputs.outputs.object;
419
+ if (object == null || typeof object !== "object") {
420
+ return outputs;
421
+ }
422
+ return object;
401
423
  }
402
- const object = await outputs.outputs.object;
403
- if (object == null || typeof object !== "object") {
424
+ catch (e) {
425
+ // Handle parsing failures without a log
404
426
  return outputs;
405
427
  }
406
- return object;
407
428
  },
408
429
  });
409
430
  return traceableFunc(...args);
@@ -199,7 +199,7 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
199
199
  }
200
200
  const { content } = lastStep;
201
201
  return convertMessageToTracedFormat({
202
- content,
202
+ content: content ?? outputs.outputs.text,
203
203
  role: "assistant",
204
204
  });
205
205
  }
@@ -321,20 +321,34 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
321
321
  return inputFormatter(inputs);
322
322
  },
323
323
  processOutputs: async (outputs) => {
324
- if (resolvedLsConfig?.processOutputs) {
325
- return resolvedLsConfig.processOutputs(outputs);
326
- }
327
- if (outputs.outputs == null || typeof outputs.outputs !== "object") {
328
- return outputs;
324
+ try {
325
+ if (resolvedLsConfig?.processOutputs) {
326
+ return resolvedLsConfig.processOutputs(outputs);
327
+ }
328
+ if (outputs.outputs == null ||
329
+ typeof outputs.outputs !== "object") {
330
+ return outputs;
331
+ }
332
+ // Important: Even accessing this property creates a promise.
333
+ // This must be awaited.
334
+ let content = await outputs.outputs.content;
335
+ if (content == null) {
336
+ // AI SDK 4 shim
337
+ content = await outputs.outputs.text;
338
+ }
339
+ if (content == null ||
340
+ !["object", "string"].includes(typeof content)) {
341
+ return outputs;
342
+ }
343
+ return convertMessageToTracedFormat({
344
+ content,
345
+ role: "assistant",
346
+ });
329
347
  }
330
- const content = await outputs.outputs.content;
331
- if (content == null || typeof content !== "object") {
348
+ catch (e) {
349
+ // Handle parsing failures without a log
332
350
  return outputs;
333
351
  }
334
- return convertMessageToTracedFormat({
335
- content,
336
- role: "assistant",
337
- });
338
352
  },
339
353
  });
340
354
  return traceableFunc(...args);
@@ -389,17 +403,24 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
389
403
  return inputFormatter(inputs);
390
404
  },
391
405
  processOutputs: async (outputs) => {
392
- if (resolvedLsConfig?.processOutputs) {
393
- return resolvedLsConfig.processOutputs(outputs);
394
- }
395
- if (outputs.outputs == null || typeof outputs.outputs !== "object") {
396
- return outputs;
406
+ try {
407
+ if (resolvedLsConfig?.processOutputs) {
408
+ return resolvedLsConfig.processOutputs(outputs);
409
+ }
410
+ if (outputs.outputs == null ||
411
+ typeof outputs.outputs !== "object") {
412
+ return outputs;
413
+ }
414
+ const object = await outputs.outputs.object;
415
+ if (object == null || typeof object !== "object") {
416
+ return outputs;
417
+ }
418
+ return object;
397
419
  }
398
- const object = await outputs.outputs.object;
399
- if (object == null || typeof object !== "object") {
420
+ catch (e) {
421
+ // Handle parsing failures without a log
400
422
  return outputs;
401
423
  }
402
- return object;
403
424
  },
404
425
  });
405
426
  return traceableFunc(...args);
@@ -26,10 +26,21 @@ const setUsageMetadataOnRunTree = (result, runTree) => {
26
26
  if (result.usage == null || typeof result.usage !== "object") {
27
27
  return;
28
28
  }
29
+ // Shim for AI SDK 4
30
+ const inputTokens = result.usage?.inputTokens ??
31
+ result.usage?.promptTokens;
32
+ const outputTokens = result.usage?.outputTokens ??
33
+ result.usage?.completionTokens;
34
+ let totalTokens = result.usage?.totalTokens;
35
+ if (typeof totalTokens !== "number" &&
36
+ typeof inputTokens === "number" &&
37
+ typeof outputTokens === "number") {
38
+ totalTokens = inputTokens + outputTokens;
39
+ }
29
40
  const langsmithUsage = {
30
- input_tokens: result.usage?.inputTokens,
31
- output_tokens: result.usage?.outputTokens,
32
- total_tokens: result.usage?.totalTokens,
41
+ input_tokens: inputTokens,
42
+ output_tokens: outputTokens,
43
+ total_tokens: totalTokens,
33
44
  };
34
45
  const inputTokenDetails = (0, vercel_js_1.extractInputTokenDetails)(result.usage, result.providerMetadata);
35
46
  const outputTokenDetails = (0, vercel_js_1.extractOutputTokenDetails)(result.usage, result.providerMetadata);
@@ -130,19 +141,35 @@ function LangSmithMiddleware(config) {
130
141
  try {
131
142
  const output = chunks.reduce((aggregated, chunk) => {
132
143
  if (chunk.type === "text-delta") {
133
- if (chunk.delta == null) {
144
+ if (chunk.delta != null) {
145
+ return {
146
+ ...aggregated,
147
+ content: aggregated.content + chunk.delta,
148
+ };
149
+ }
150
+ else if ("textDelta" in chunk &&
151
+ chunk.textDelta != null) {
152
+ // AI SDK 4 shim
153
+ return {
154
+ ...aggregated,
155
+ content: aggregated.content + chunk.textDelta,
156
+ };
157
+ }
158
+ else {
134
159
  return aggregated;
135
160
  }
136
- return {
137
- ...aggregated,
138
- content: aggregated.content + chunk.delta,
139
- };
140
161
  }
141
162
  else if (chunk.type === "tool-call") {
142
163
  const matchingToolCall = aggregated.tool_calls.find((call) => call.id === chunk.toolCallId);
143
164
  if (matchingToolCall != null) {
144
165
  return aggregated;
145
166
  }
167
+ let chunkArgs = chunk.input;
168
+ if (chunkArgs == null &&
169
+ "args" in chunk &&
170
+ typeof chunk.args === "string") {
171
+ chunkArgs = chunk.args;
172
+ }
146
173
  return {
147
174
  ...aggregated,
148
175
  tool_calls: [
@@ -152,7 +179,7 @@ function LangSmithMiddleware(config) {
152
179
  type: "function",
153
180
  function: {
154
181
  name: chunk.toolName,
155
- arguments: chunk.input,
182
+ arguments: chunkArgs,
156
183
  },
157
184
  },
158
185
  ],
@@ -177,7 +204,7 @@ function LangSmithMiddleware(config) {
177
204
  tool_calls: [],
178
205
  });
179
206
  const outputFormatter = lsConfig?.processOutputs ?? utils_js_1.convertMessageToTracedFormat;
180
- const formattedOutputs = outputFormatter(output);
207
+ const formattedOutputs = await outputFormatter(output);
181
208
  await runTree?.end(formattedOutputs);
182
209
  }
183
210
  catch (error) {
@@ -22,6 +22,6 @@ export declare function LangSmithMiddleware(config?: {
22
22
  modelId?: string;
23
23
  lsConfig?: Partial<Omit<RunTreeConfig, "inputs" | "outputs" | "run_type">> & {
24
24
  processInputs?: (inputs: Record<string, unknown>) => Record<string, unknown>;
25
- processOutputs?: (outputs: Record<string, unknown>) => Record<string, unknown>;
25
+ processOutputs?: (outputs: Record<string, unknown>) => Record<string, unknown> | Promise<Record<string, unknown>>;
26
26
  };
27
27
  }): LanguageModelV2Middleware;
@@ -23,10 +23,21 @@ const setUsageMetadataOnRunTree = (result, runTree) => {
23
23
  if (result.usage == null || typeof result.usage !== "object") {
24
24
  return;
25
25
  }
26
+ // Shim for AI SDK 4
27
+ const inputTokens = result.usage?.inputTokens ??
28
+ result.usage?.promptTokens;
29
+ const outputTokens = result.usage?.outputTokens ??
30
+ result.usage?.completionTokens;
31
+ let totalTokens = result.usage?.totalTokens;
32
+ if (typeof totalTokens !== "number" &&
33
+ typeof inputTokens === "number" &&
34
+ typeof outputTokens === "number") {
35
+ totalTokens = inputTokens + outputTokens;
36
+ }
26
37
  const langsmithUsage = {
27
- input_tokens: result.usage?.inputTokens,
28
- output_tokens: result.usage?.outputTokens,
29
- total_tokens: result.usage?.totalTokens,
38
+ input_tokens: inputTokens,
39
+ output_tokens: outputTokens,
40
+ total_tokens: totalTokens,
30
41
  };
31
42
  const inputTokenDetails = extractInputTokenDetails(result.usage, result.providerMetadata);
32
43
  const outputTokenDetails = extractOutputTokenDetails(result.usage, result.providerMetadata);
@@ -127,19 +138,35 @@ export function LangSmithMiddleware(config) {
127
138
  try {
128
139
  const output = chunks.reduce((aggregated, chunk) => {
129
140
  if (chunk.type === "text-delta") {
130
- if (chunk.delta == null) {
141
+ if (chunk.delta != null) {
142
+ return {
143
+ ...aggregated,
144
+ content: aggregated.content + chunk.delta,
145
+ };
146
+ }
147
+ else if ("textDelta" in chunk &&
148
+ chunk.textDelta != null) {
149
+ // AI SDK 4 shim
150
+ return {
151
+ ...aggregated,
152
+ content: aggregated.content + chunk.textDelta,
153
+ };
154
+ }
155
+ else {
131
156
  return aggregated;
132
157
  }
133
- return {
134
- ...aggregated,
135
- content: aggregated.content + chunk.delta,
136
- };
137
158
  }
138
159
  else if (chunk.type === "tool-call") {
139
160
  const matchingToolCall = aggregated.tool_calls.find((call) => call.id === chunk.toolCallId);
140
161
  if (matchingToolCall != null) {
141
162
  return aggregated;
142
163
  }
164
+ let chunkArgs = chunk.input;
165
+ if (chunkArgs == null &&
166
+ "args" in chunk &&
167
+ typeof chunk.args === "string") {
168
+ chunkArgs = chunk.args;
169
+ }
143
170
  return {
144
171
  ...aggregated,
145
172
  tool_calls: [
@@ -149,7 +176,7 @@ export function LangSmithMiddleware(config) {
149
176
  type: "function",
150
177
  function: {
151
178
  name: chunk.toolName,
152
- arguments: chunk.input,
179
+ arguments: chunkArgs,
153
180
  },
154
181
  },
155
182
  ],
@@ -174,7 +201,7 @@ export function LangSmithMiddleware(config) {
174
201
  tool_calls: [],
175
202
  });
176
203
  const outputFormatter = lsConfig?.processOutputs ?? convertMessageToTracedFormat;
177
- const formattedOutputs = outputFormatter(output);
204
+ const formattedOutputs = await outputFormatter(output);
178
205
  await runTree?.end(formattedOutputs);
179
206
  }
180
207
  catch (error) {
@@ -109,14 +109,17 @@ const convertMessageToTracedFormat = (message) => {
109
109
  block.type === "tool-call");
110
110
  });
111
111
  const toolCalls = toolCallBlocks.map((block) => {
112
+ // AI SDK 4 shim
113
+ let toolArgs = block.input ?? (("args" in block && block.args) || undefined);
114
+ if (typeof toolArgs !== "string") {
115
+ toolArgs = JSON.stringify(toolArgs);
116
+ }
112
117
  return {
113
118
  id: block.toolCallId,
114
119
  type: "function",
115
120
  function: {
116
121
  name: block.toolName,
117
- arguments: typeof block.input !== "string"
118
- ? JSON.stringify(block.input)
119
- : block.input,
122
+ arguments: toolArgs,
120
123
  },
121
124
  };
122
125
  });
@@ -147,6 +150,21 @@ const convertMessageToTracedFormat = (message) => {
147
150
  });
148
151
  formattedMessage.content = newContent;
149
152
  }
153
+ else if (message.content == null && "text" in message) {
154
+ // AI SDK 4 shim
155
+ formattedMessage.content = message.text ?? "";
156
+ if ("toolCalls" in message &&
157
+ Array.isArray(message.toolCalls) &&
158
+ !("tool_calls" in formattedMessage)) {
159
+ formattedMessage.tool_calls = message.toolCalls.map((toolCall) => {
160
+ return {
161
+ id: toolCall.toolCallId,
162
+ type: "function",
163
+ function: { name: toolCall.toolName, arguments: toolCall.args },
164
+ };
165
+ });
166
+ }
167
+ }
150
168
  return formattedMessage;
151
169
  };
152
170
  exports.convertMessageToTracedFormat = convertMessageToTracedFormat;
@@ -105,14 +105,17 @@ export const convertMessageToTracedFormat = (message) => {
105
105
  block.type === "tool-call");
106
106
  });
107
107
  const toolCalls = toolCallBlocks.map((block) => {
108
+ // AI SDK 4 shim
109
+ let toolArgs = block.input ?? (("args" in block && block.args) || undefined);
110
+ if (typeof toolArgs !== "string") {
111
+ toolArgs = JSON.stringify(toolArgs);
112
+ }
108
113
  return {
109
114
  id: block.toolCallId,
110
115
  type: "function",
111
116
  function: {
112
117
  name: block.toolName,
113
- arguments: typeof block.input !== "string"
114
- ? JSON.stringify(block.input)
115
- : block.input,
118
+ arguments: toolArgs,
116
119
  },
117
120
  };
118
121
  });
@@ -143,5 +146,20 @@ export const convertMessageToTracedFormat = (message) => {
143
146
  });
144
147
  formattedMessage.content = newContent;
145
148
  }
149
+ else if (message.content == null && "text" in message) {
150
+ // AI SDK 4 shim
151
+ formattedMessage.content = message.text ?? "";
152
+ if ("toolCalls" in message &&
153
+ Array.isArray(message.toolCalls) &&
154
+ !("tool_calls" in formattedMessage)) {
155
+ formattedMessage.tool_calls = message.toolCalls.map((toolCall) => {
156
+ return {
157
+ id: toolCall.toolCallId,
158
+ type: "function",
159
+ function: { name: toolCall.toolName, arguments: toolCall.args },
160
+ };
161
+ });
162
+ }
163
+ }
146
164
  return formattedMessage;
147
165
  };
package/dist/index.cjs CHANGED
@@ -10,4 +10,4 @@ Object.defineProperty(exports, "overrideFetchImplementation", { enumerable: true
10
10
  var project_js_1 = require("./utils/project.cjs");
11
11
  Object.defineProperty(exports, "getDefaultProjectName", { enumerable: true, get: function () { return project_js_1.getDefaultProjectName; } });
12
12
  // Update using yarn bump-version
13
- exports.__version__ = "0.3.67";
13
+ exports.__version__ = "0.3.69";
package/dist/index.d.ts CHANGED
@@ -3,4 +3,4 @@ export type { Dataset, Example, TracerSession, Run, Feedback, RetrieverOutput, }
3
3
  export { RunTree, type RunTreeConfig } from "./run_trees.js";
4
4
  export { overrideFetchImplementation } from "./singletons/fetch.js";
5
5
  export { getDefaultProjectName } from "./utils/project.js";
6
- export declare const __version__ = "0.3.67";
6
+ export declare const __version__ = "0.3.69";
package/dist/index.js CHANGED
@@ -3,4 +3,4 @@ export { RunTree } from "./run_trees.js";
3
3
  export { overrideFetchImplementation } from "./singletons/fetch.js";
4
4
  export { getDefaultProjectName } from "./utils/project.js";
5
5
  // Update using yarn bump-version
6
- export const __version__ = "0.3.67";
6
+ export const __version__ = "0.3.69";
@@ -166,10 +166,20 @@ async function handleRunOutputs(params) {
166
166
  })
167
167
  .catch(async (e) => {
168
168
  console.error("Error occurred during processOutputs. Sending unprocessed outputs:", e);
169
- await runTree?.end(outputs);
169
+ try {
170
+ await runTree?.end(outputs);
171
+ }
172
+ catch (e) {
173
+ console.error("Error occurred during runTree?.end.", e);
174
+ }
170
175
  })
171
176
  .finally(async () => {
172
- await handleEnd({ runTree, postRunPromise, on_end, excludeInputs });
177
+ try {
178
+ await handleEnd({ runTree, postRunPromise, on_end, excludeInputs });
179
+ }
180
+ catch (e) {
181
+ console.error("Error occurred during handleEnd.", e);
182
+ }
173
183
  });
174
184
  return;
175
185
  }
package/dist/traceable.js CHANGED
@@ -162,10 +162,20 @@ async function handleRunOutputs(params) {
162
162
  })
163
163
  .catch(async (e) => {
164
164
  console.error("Error occurred during processOutputs. Sending unprocessed outputs:", e);
165
- await runTree?.end(outputs);
165
+ try {
166
+ await runTree?.end(outputs);
167
+ }
168
+ catch (e) {
169
+ console.error("Error occurred during runTree?.end.", e);
170
+ }
166
171
  })
167
172
  .finally(async () => {
168
- await handleEnd({ runTree, postRunPromise, on_end, excludeInputs });
173
+ try {
174
+ await handleEnd({ runTree, postRunPromise, on_end, excludeInputs });
175
+ }
176
+ catch (e) {
177
+ console.error("Error occurred during handleEnd.", e);
178
+ }
169
179
  });
170
180
  return;
171
181
  }
@@ -93,21 +93,35 @@ async function raiseForStatus(response, context, consumeOnSuccess) {
93
93
  const errorData = await response.json();
94
94
  const errorCode = errorData?.error;
95
95
  if (errorCode === "org_scoped_key_requires_workspace") {
96
- throw new Error("This API key is org-scoped and requires workspace specification. " +
97
- "Please provide 'workspaceId' parameter, " +
98
- "or set LANGSMITH_WORKSPACE_ID environment variable.");
96
+ errorBody =
97
+ "This API key is org-scoped and requires workspace specification. " +
98
+ "Please provide 'workspaceId' parameter, " +
99
+ "or set LANGSMITH_WORKSPACE_ID environment variable.";
99
100
  }
101
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
102
  }
101
103
  catch (e) {
102
- throw new Error(`${response.status} ${response.statusText}`);
104
+ const errorWithStatus = new Error(`${response.status} ${response.statusText}`);
105
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
+ errorWithStatus.status = response?.status;
107
+ throw errorWithStatus;
103
108
  }
104
109
  }
105
- errorBody = await response.text();
106
- const fullMessage = `Failed to ${context}. Received status [${response.status}]: ${response.statusText}. Server response: ${errorBody}`;
110
+ if (errorBody === undefined) {
111
+ try {
112
+ errorBody = await response.text();
113
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
114
+ }
115
+ catch (e) {
116
+ errorBody = "";
117
+ }
118
+ }
119
+ const fullMessage = `Failed to ${context}. Received status [${response.status}]: ${response.statusText}. Message: ${errorBody}`;
107
120
  if (response.status === 409) {
108
121
  throw new LangSmithConflictError(fullMessage);
109
122
  }
110
123
  const err = new Error(fullMessage);
124
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
125
  err.status = response.status;
112
126
  throw err;
113
127
  }
@@ -86,21 +86,35 @@ export async function raiseForStatus(response, context, consumeOnSuccess) {
86
86
  const errorData = await response.json();
87
87
  const errorCode = errorData?.error;
88
88
  if (errorCode === "org_scoped_key_requires_workspace") {
89
- throw new Error("This API key is org-scoped and requires workspace specification. " +
90
- "Please provide 'workspaceId' parameter, " +
91
- "or set LANGSMITH_WORKSPACE_ID environment variable.");
89
+ errorBody =
90
+ "This API key is org-scoped and requires workspace specification. " +
91
+ "Please provide 'workspaceId' parameter, " +
92
+ "or set LANGSMITH_WORKSPACE_ID environment variable.";
92
93
  }
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
95
  }
94
96
  catch (e) {
95
- throw new Error(`${response.status} ${response.statusText}`);
97
+ const errorWithStatus = new Error(`${response.status} ${response.statusText}`);
98
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
+ errorWithStatus.status = response?.status;
100
+ throw errorWithStatus;
96
101
  }
97
102
  }
98
- errorBody = await response.text();
99
- const fullMessage = `Failed to ${context}. Received status [${response.status}]: ${response.statusText}. Server response: ${errorBody}`;
103
+ if (errorBody === undefined) {
104
+ try {
105
+ errorBody = await response.text();
106
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
107
+ }
108
+ catch (e) {
109
+ errorBody = "";
110
+ }
111
+ }
112
+ const fullMessage = `Failed to ${context}. Received status [${response.status}]: ${response.statusText}. Message: ${errorBody}`;
100
113
  if (response.status === 409) {
101
114
  throw new LangSmithConflictError(fullMessage);
102
115
  }
103
116
  const err = new Error(fullMessage);
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
104
118
  err.status = response.status;
105
119
  throw err;
106
120
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.3.67",
3
+ "version": "0.3.69",
4
4
  "description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.",
5
5
  "packageManager": "yarn@1.22.19",
6
6
  "files": [
@@ -114,6 +114,7 @@
114
114
  "test:integration": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000",
115
115
  "test:single": "NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
116
116
  "watch:single": "NODE_OPTIONS=--experimental-vm-modules yarn run jest --watch --config jest.config.cjs --testTimeout 100000",
117
+ "test:vitest": "vitest run --config vitest.config.ts",
117
118
  "test:eval:vitest": "vitest run --config ls.vitest.config.ts",
118
119
  "lint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
119
120
  "lint:fix": "yarn lint --fix",
@@ -148,7 +149,7 @@
148
149
  "uuid": "^10.0.0"
149
150
  },
150
151
  "devDependencies": {
151
- "@ai-sdk/anthropic": "^2.0.1",
152
+ "@ai-sdk/anthropic": "^2.0.17",
152
153
  "@ai-sdk/openai": "^2.0.23",
153
154
  "@babel/preset-env": "^7.22.4",
154
155
  "@faker-js/faker": "^8.4.1",
@@ -167,7 +168,7 @@
167
168
  "@types/node-fetch": "^2.6.12",
168
169
  "@typescript-eslint/eslint-plugin": "^5.59.8",
169
170
  "@typescript-eslint/parser": "^5.59.8",
170
- "ai": "^5.0.10",
171
+ "ai": "^5.0.44",
171
172
  "babel-jest": "^29.5.0",
172
173
  "cross-env": "^7.0.3",
173
174
  "dotenv": "^16.1.3",
@@ -178,6 +179,7 @@
178
179
  "eslint-plugin-prettier": "^4.2.1",
179
180
  "jest": "^29.5.0",
180
181
  "langchain": "^0.3.29",
182
+ "msw": "^2.11.2",
181
183
  "node-fetch": "^2.7.0",
182
184
  "openai": "^5.8.2",
183
185
  "prettier": "^2.8.8",