langsmith 0.4.11 → 0.4.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.
@@ -197,6 +197,16 @@ const wrapAnthropic = (anthropic, options) => {
197
197
  throw new Error("This instance of Anthropic client has been already wrapped once.");
198
198
  }
199
199
  const tracedAnthropicClient = { ...anthropic };
200
+ // Extract ls_invocation_params from metadata
201
+ const prepopulatedInvocationParams = typeof options?.metadata?.ls_invocation_params === "object"
202
+ ? options.metadata.ls_invocation_params
203
+ : {};
204
+ // Remove ls_invocation_params from metadata to avoid duplication
205
+ const { ls_invocation_params, ...restMetadata } = options?.metadata ?? {};
206
+ const cleanedOptions = {
207
+ ...options,
208
+ metadata: restMetadata,
209
+ };
200
210
  // Common configuration for messages.create
201
211
  const messagesCreateConfig = {
202
212
  name: "ChatAnthropic",
@@ -223,11 +233,14 @@ const wrapAnthropic = (anthropic, options) => {
223
233
  ls_max_tokens: params.max_tokens ?? undefined,
224
234
  ls_temperature: params.temperature ?? undefined,
225
235
  ls_stop,
226
- ls_invocation_params,
236
+ ls_invocation_params: {
237
+ ...prepopulatedInvocationParams,
238
+ ...ls_invocation_params,
239
+ },
227
240
  };
228
241
  },
229
242
  processOutputs: processMessageOutput,
230
- ...options,
243
+ ...cleanedOptions,
231
244
  };
232
245
  // Create a new messages object preserving the prototype
233
246
  tracedAnthropicClient.messages = Object.create(Object.getPrototypeOf(anthropic.messages));
@@ -268,7 +281,7 @@ const wrapAnthropic = (anthropic, options) => {
268
281
  argsConfigPath: [1, "langsmithExtra"],
269
282
  getInvocationParams: messagesCreateConfig.getInvocationParams,
270
283
  processOutputs: processMessageOutput,
271
- ...options,
284
+ ...cleanedOptions,
272
285
  });
273
286
  // Wrap beta.messages if it exists
274
287
  if (anthropic.beta &&
@@ -289,7 +302,7 @@ const wrapAnthropic = (anthropic, options) => {
289
302
  argsConfigPath: [1, "langsmithExtra"],
290
303
  getInvocationParams: messagesCreateConfig.getInvocationParams,
291
304
  processOutputs: processMessageOutput,
292
- ...options,
305
+ ...cleanedOptions,
293
306
  });
294
307
  }
295
308
  tracedAnthropicClient.beta = tracedBeta;
@@ -194,6 +194,16 @@ export const wrapAnthropic = (anthropic, options) => {
194
194
  throw new Error("This instance of Anthropic client has been already wrapped once.");
195
195
  }
196
196
  const tracedAnthropicClient = { ...anthropic };
197
+ // Extract ls_invocation_params from metadata
198
+ const prepopulatedInvocationParams = typeof options?.metadata?.ls_invocation_params === "object"
199
+ ? options.metadata.ls_invocation_params
200
+ : {};
201
+ // Remove ls_invocation_params from metadata to avoid duplication
202
+ const { ls_invocation_params, ...restMetadata } = options?.metadata ?? {};
203
+ const cleanedOptions = {
204
+ ...options,
205
+ metadata: restMetadata,
206
+ };
197
207
  // Common configuration for messages.create
198
208
  const messagesCreateConfig = {
199
209
  name: "ChatAnthropic",
@@ -220,11 +230,14 @@ export const wrapAnthropic = (anthropic, options) => {
220
230
  ls_max_tokens: params.max_tokens ?? undefined,
221
231
  ls_temperature: params.temperature ?? undefined,
222
232
  ls_stop,
223
- ls_invocation_params,
233
+ ls_invocation_params: {
234
+ ...prepopulatedInvocationParams,
235
+ ...ls_invocation_params,
236
+ },
224
237
  };
225
238
  },
226
239
  processOutputs: processMessageOutput,
227
- ...options,
240
+ ...cleanedOptions,
228
241
  };
229
242
  // Create a new messages object preserving the prototype
230
243
  tracedAnthropicClient.messages = Object.create(Object.getPrototypeOf(anthropic.messages));
@@ -265,7 +278,7 @@ export const wrapAnthropic = (anthropic, options) => {
265
278
  argsConfigPath: [1, "langsmithExtra"],
266
279
  getInvocationParams: messagesCreateConfig.getInvocationParams,
267
280
  processOutputs: processMessageOutput,
268
- ...options,
281
+ ...cleanedOptions,
269
282
  });
270
283
  // Wrap beta.messages if it exists
271
284
  if (anthropic.beta &&
@@ -286,7 +299,7 @@ export const wrapAnthropic = (anthropic, options) => {
286
299
  argsConfigPath: [1, "langsmithExtra"],
287
300
  getInvocationParams: messagesCreateConfig.getInvocationParams,
288
301
  processOutputs: processMessageOutput,
289
- ...options,
302
+ ...cleanedOptions,
290
303
  });
291
304
  }
292
305
  tracedAnthropicClient.beta = tracedBeta;
@@ -358,7 +358,7 @@ function processGeminiOutputs(outputs) {
358
358
  }
359
359
  return result;
360
360
  }
361
- function getInvocationParams(payload) {
361
+ function _getGeminiInvocationParams(prepopulatedInvocationParams, payload) {
362
362
  const config = (payload?.[0] || payload);
363
363
  return {
364
364
  ls_provider: "google",
@@ -366,6 +366,7 @@ function getInvocationParams(payload) {
366
366
  ls_model_name: config?.model || "unknown",
367
367
  ls_temperature: config?.config?.temperature,
368
368
  ls_max_tokens: config?.config?.maxOutputTokens,
369
+ ls_invocation_params: prepopulatedInvocationParams,
369
370
  };
370
371
  }
371
372
  /**
@@ -407,22 +408,32 @@ function wrapGemini(gemini, options) {
407
408
  "Wrapping a client multiple times is not supported.");
408
409
  }
409
410
  const tracedGeminiClient = { ...gemini };
411
+ // Extract ls_invocation_params from metadata
412
+ const prepopulatedInvocationParams = typeof options?.metadata?.ls_invocation_params === "object"
413
+ ? options.metadata.ls_invocation_params
414
+ : {};
415
+ // Remove ls_invocation_params from metadata to avoid duplication
416
+ const { ls_invocation_params, ...restMetadata } = options?.metadata ?? {};
417
+ const cleanedOptions = {
418
+ ...options,
419
+ metadata: restMetadata,
420
+ };
410
421
  const geminiTraceConfig = {
411
422
  name: "ChatGoogleGenerativeAI",
412
423
  run_type: "llm",
413
- getInvocationParams,
424
+ getInvocationParams: (payload) => _getGeminiInvocationParams(prepopulatedInvocationParams ?? {}, payload),
414
425
  processInputs: processGeminiInputs,
415
426
  processOutputs: processGeminiOutputs,
416
- ...options,
427
+ ...cleanedOptions,
417
428
  };
418
429
  const geminiStreamTraceConfig = {
419
430
  name: "ChatGoogleGenerativeAI",
420
431
  run_type: "llm",
421
432
  aggregator: chatAggregator,
422
- getInvocationParams,
433
+ getInvocationParams: (payload) => _getGeminiInvocationParams(prepopulatedInvocationParams ?? {}, payload),
423
434
  processInputs: processGeminiInputs,
424
435
  processOutputs: processGeminiOutputs,
425
- ...options,
436
+ ...cleanedOptions,
426
437
  };
427
438
  tracedGeminiClient.models = {
428
439
  ...gemini.models,
@@ -355,7 +355,7 @@ function processGeminiOutputs(outputs) {
355
355
  }
356
356
  return result;
357
357
  }
358
- function getInvocationParams(payload) {
358
+ function _getGeminiInvocationParams(prepopulatedInvocationParams, payload) {
359
359
  const config = (payload?.[0] || payload);
360
360
  return {
361
361
  ls_provider: "google",
@@ -363,6 +363,7 @@ function getInvocationParams(payload) {
363
363
  ls_model_name: config?.model || "unknown",
364
364
  ls_temperature: config?.config?.temperature,
365
365
  ls_max_tokens: config?.config?.maxOutputTokens,
366
+ ls_invocation_params: prepopulatedInvocationParams,
366
367
  };
367
368
  }
368
369
  /**
@@ -404,22 +405,32 @@ export function wrapGemini(gemini, options) {
404
405
  "Wrapping a client multiple times is not supported.");
405
406
  }
406
407
  const tracedGeminiClient = { ...gemini };
408
+ // Extract ls_invocation_params from metadata
409
+ const prepopulatedInvocationParams = typeof options?.metadata?.ls_invocation_params === "object"
410
+ ? options.metadata.ls_invocation_params
411
+ : {};
412
+ // Remove ls_invocation_params from metadata to avoid duplication
413
+ const { ls_invocation_params, ...restMetadata } = options?.metadata ?? {};
414
+ const cleanedOptions = {
415
+ ...options,
416
+ metadata: restMetadata,
417
+ };
407
418
  const geminiTraceConfig = {
408
419
  name: "ChatGoogleGenerativeAI",
409
420
  run_type: "llm",
410
- getInvocationParams,
421
+ getInvocationParams: (payload) => _getGeminiInvocationParams(prepopulatedInvocationParams ?? {}, payload),
411
422
  processInputs: processGeminiInputs,
412
423
  processOutputs: processGeminiOutputs,
413
- ...options,
424
+ ...cleanedOptions,
414
425
  };
415
426
  const geminiStreamTraceConfig = {
416
427
  name: "ChatGoogleGenerativeAI",
417
428
  run_type: "llm",
418
429
  aggregator: chatAggregator,
419
- getInvocationParams,
430
+ getInvocationParams: (payload) => _getGeminiInvocationParams(prepopulatedInvocationParams ?? {}, payload),
420
431
  processInputs: processGeminiInputs,
421
432
  processOutputs: processGeminiOutputs,
422
- ...options,
433
+ ...cleanedOptions,
423
434
  };
424
435
  tracedGeminiClient.models = {
425
436
  ...gemini.models,
@@ -232,7 +232,7 @@ function processChatCompletion(outputs) {
232
232
  delete result.usage;
233
233
  return result;
234
234
  }
235
- const getChatModelInvocationParamsFn = (provider, useResponsesApi) => {
235
+ const getChatModelInvocationParamsFn = (provider, prepopulatedInvocationParams, useResponsesApi) => {
236
236
  return (payload) => {
237
237
  if (typeof payload !== "object" || payload == null)
238
238
  return undefined;
@@ -255,7 +255,10 @@ const getChatModelInvocationParamsFn = (provider, useResponsesApi) => {
255
255
  ls_max_tokens: params.max_completion_tokens ?? params.max_tokens ?? undefined,
256
256
  ls_temperature: params.temperature ?? undefined,
257
257
  ls_stop,
258
- ls_invocation_params,
258
+ ls_invocation_params: {
259
+ ...prepopulatedInvocationParams,
260
+ ...ls_invocation_params,
261
+ },
259
262
  };
260
263
  };
261
264
  };
@@ -301,14 +304,23 @@ const wrapOpenAI = (openai, options) => {
301
304
  // Some internal OpenAI methods call each other, so we need to preserve original
302
305
  // OpenAI methods.
303
306
  const tracedOpenAIClient = { ...openai };
307
+ const prepopulatedInvocationParams = typeof options?.metadata?.ls_invocation_params === "object"
308
+ ? options.metadata.ls_invocation_params
309
+ : {};
310
+ // Remove ls_invocation_params from metadata to avoid duplication
311
+ const { ls_invocation_params, ...restMetadata } = options?.metadata ?? {};
312
+ const cleanedOptions = {
313
+ ...options,
314
+ metadata: restMetadata,
315
+ };
304
316
  const chatCompletionParseMetadata = {
305
317
  name: chatName,
306
318
  run_type: "llm",
307
319
  aggregator: chatAggregator,
308
320
  argsConfigPath: [1, "langsmithExtra"],
309
- getInvocationParams: getChatModelInvocationParamsFn(provider, false),
321
+ getInvocationParams: getChatModelInvocationParamsFn(provider, prepopulatedInvocationParams, false),
310
322
  processOutputs: processChatCompletion,
311
- ...options,
323
+ ...cleanedOptions,
312
324
  };
313
325
  if (openai.beta) {
314
326
  tracedOpenAIClient.beta = openai.beta;
@@ -398,10 +410,13 @@ const wrapOpenAI = (openai, options) => {
398
410
  ls_max_tokens: params.max_tokens ?? undefined,
399
411
  ls_temperature: params.temperature ?? undefined,
400
412
  ls_stop,
401
- ls_invocation_params,
413
+ ls_invocation_params: {
414
+ ...prepopulatedInvocationParams,
415
+ ...ls_invocation_params,
416
+ },
402
417
  };
403
418
  },
404
- ...options,
419
+ ...cleanedOptions,
405
420
  }),
406
421
  };
407
422
  // Add responses API support if it exists
@@ -420,9 +435,9 @@ const wrapOpenAI = (openai, options) => {
420
435
  run_type: "llm",
421
436
  aggregator: responsesAggregator,
422
437
  argsConfigPath: [1, "langsmithExtra"],
423
- getInvocationParams: getChatModelInvocationParamsFn(provider, true),
438
+ getInvocationParams: getChatModelInvocationParamsFn(provider, prepopulatedInvocationParams, true),
424
439
  processOutputs: processChatCompletion,
425
- ...options,
440
+ ...cleanedOptions,
426
441
  });
427
442
  }
428
443
  if (tracedOpenAIClient.responses &&
@@ -432,9 +447,9 @@ const wrapOpenAI = (openai, options) => {
432
447
  run_type: "llm",
433
448
  aggregator: responsesAggregator,
434
449
  argsConfigPath: [1, "langsmithExtra"],
435
- getInvocationParams: getChatModelInvocationParamsFn(provider, true),
450
+ getInvocationParams: getChatModelInvocationParamsFn(provider, prepopulatedInvocationParams, true),
436
451
  processOutputs: processChatCompletion,
437
- ...options,
452
+ ...cleanedOptions,
438
453
  });
439
454
  }
440
455
  if (tracedOpenAIClient.responses &&
@@ -444,9 +459,9 @@ const wrapOpenAI = (openai, options) => {
444
459
  run_type: "llm",
445
460
  aggregator: responsesAggregator,
446
461
  argsConfigPath: [1, "langsmithExtra"],
447
- getInvocationParams: getChatModelInvocationParamsFn(provider, true),
462
+ getInvocationParams: getChatModelInvocationParamsFn(provider, prepopulatedInvocationParams, true),
448
463
  processOutputs: processChatCompletion,
449
- ...options,
464
+ ...cleanedOptions,
450
465
  });
451
466
  }
452
467
  }
@@ -229,7 +229,7 @@ function processChatCompletion(outputs) {
229
229
  delete result.usage;
230
230
  return result;
231
231
  }
232
- const getChatModelInvocationParamsFn = (provider, useResponsesApi) => {
232
+ const getChatModelInvocationParamsFn = (provider, prepopulatedInvocationParams, useResponsesApi) => {
233
233
  return (payload) => {
234
234
  if (typeof payload !== "object" || payload == null)
235
235
  return undefined;
@@ -252,7 +252,10 @@ const getChatModelInvocationParamsFn = (provider, useResponsesApi) => {
252
252
  ls_max_tokens: params.max_completion_tokens ?? params.max_tokens ?? undefined,
253
253
  ls_temperature: params.temperature ?? undefined,
254
254
  ls_stop,
255
- ls_invocation_params,
255
+ ls_invocation_params: {
256
+ ...prepopulatedInvocationParams,
257
+ ...ls_invocation_params,
258
+ },
256
259
  };
257
260
  };
258
261
  };
@@ -298,14 +301,23 @@ export const wrapOpenAI = (openai, options) => {
298
301
  // Some internal OpenAI methods call each other, so we need to preserve original
299
302
  // OpenAI methods.
300
303
  const tracedOpenAIClient = { ...openai };
304
+ const prepopulatedInvocationParams = typeof options?.metadata?.ls_invocation_params === "object"
305
+ ? options.metadata.ls_invocation_params
306
+ : {};
307
+ // Remove ls_invocation_params from metadata to avoid duplication
308
+ const { ls_invocation_params, ...restMetadata } = options?.metadata ?? {};
309
+ const cleanedOptions = {
310
+ ...options,
311
+ metadata: restMetadata,
312
+ };
301
313
  const chatCompletionParseMetadata = {
302
314
  name: chatName,
303
315
  run_type: "llm",
304
316
  aggregator: chatAggregator,
305
317
  argsConfigPath: [1, "langsmithExtra"],
306
- getInvocationParams: getChatModelInvocationParamsFn(provider, false),
318
+ getInvocationParams: getChatModelInvocationParamsFn(provider, prepopulatedInvocationParams, false),
307
319
  processOutputs: processChatCompletion,
308
- ...options,
320
+ ...cleanedOptions,
309
321
  };
310
322
  if (openai.beta) {
311
323
  tracedOpenAIClient.beta = openai.beta;
@@ -395,10 +407,13 @@ export const wrapOpenAI = (openai, options) => {
395
407
  ls_max_tokens: params.max_tokens ?? undefined,
396
408
  ls_temperature: params.temperature ?? undefined,
397
409
  ls_stop,
398
- ls_invocation_params,
410
+ ls_invocation_params: {
411
+ ...prepopulatedInvocationParams,
412
+ ...ls_invocation_params,
413
+ },
399
414
  };
400
415
  },
401
- ...options,
416
+ ...cleanedOptions,
402
417
  }),
403
418
  };
404
419
  // Add responses API support if it exists
@@ -417,9 +432,9 @@ export const wrapOpenAI = (openai, options) => {
417
432
  run_type: "llm",
418
433
  aggregator: responsesAggregator,
419
434
  argsConfigPath: [1, "langsmithExtra"],
420
- getInvocationParams: getChatModelInvocationParamsFn(provider, true),
435
+ getInvocationParams: getChatModelInvocationParamsFn(provider, prepopulatedInvocationParams, true),
421
436
  processOutputs: processChatCompletion,
422
- ...options,
437
+ ...cleanedOptions,
423
438
  });
424
439
  }
425
440
  if (tracedOpenAIClient.responses &&
@@ -429,9 +444,9 @@ export const wrapOpenAI = (openai, options) => {
429
444
  run_type: "llm",
430
445
  aggregator: responsesAggregator,
431
446
  argsConfigPath: [1, "langsmithExtra"],
432
- getInvocationParams: getChatModelInvocationParamsFn(provider, true),
447
+ getInvocationParams: getChatModelInvocationParamsFn(provider, prepopulatedInvocationParams, true),
433
448
  processOutputs: processChatCompletion,
434
- ...options,
449
+ ...cleanedOptions,
435
450
  });
436
451
  }
437
452
  if (tracedOpenAIClient.responses &&
@@ -441,9 +456,9 @@ export const wrapOpenAI = (openai, options) => {
441
456
  run_type: "llm",
442
457
  aggregator: responsesAggregator,
443
458
  argsConfigPath: [1, "langsmithExtra"],
444
- getInvocationParams: getChatModelInvocationParamsFn(provider, true),
459
+ getInvocationParams: getChatModelInvocationParamsFn(provider, prepopulatedInvocationParams, true),
445
460
  processOutputs: processChatCompletion,
446
- ...options,
461
+ ...cleanedOptions,
447
462
  });
448
463
  }
449
464
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.4.11",
3
+ "version": "0.4.12",
4
4
  "description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
5
5
  "packageManager": "yarn@1.22.19",
6
6
  "files": [