langsmith 0.5.21 → 0.5.23

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 (42) hide show
  1. package/dist/client.cjs +327 -10
  2. package/dist/client.d.ts +90 -1
  3. package/dist/client.js +330 -13
  4. package/dist/evaluation/_runner.cjs +1 -4
  5. package/dist/evaluation/_runner.js +1 -4
  6. package/dist/experimental/sandbox/client.cjs +102 -427
  7. package/dist/experimental/sandbox/client.d.ts +68 -159
  8. package/dist/experimental/sandbox/client.js +104 -429
  9. package/dist/experimental/sandbox/errors.cjs +1 -2
  10. package/dist/experimental/sandbox/errors.d.ts +1 -2
  11. package/dist/experimental/sandbox/errors.js +1 -2
  12. package/dist/experimental/sandbox/helpers.cjs +8 -98
  13. package/dist/experimental/sandbox/helpers.d.ts +0 -29
  14. package/dist/experimental/sandbox/helpers.js +9 -95
  15. package/dist/experimental/sandbox/index.cjs +6 -1
  16. package/dist/experimental/sandbox/index.d.ts +7 -2
  17. package/dist/experimental/sandbox/index.js +6 -1
  18. package/dist/experimental/sandbox/sandbox.cjs +3 -11
  19. package/dist/experimental/sandbox/sandbox.d.ts +3 -5
  20. package/dist/experimental/sandbox/sandbox.js +3 -11
  21. package/dist/experimental/sandbox/types.d.ts +32 -149
  22. package/dist/index.cjs +1 -1
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/schemas.d.ts +54 -0
  26. package/dist/utils/error.cjs +7 -0
  27. package/dist/utils/error.d.ts +1 -0
  28. package/dist/utils/error.js +6 -0
  29. package/dist/utils/fast-safe-stringify/index.cjs +228 -0
  30. package/dist/utils/fast-safe-stringify/index.d.ts +33 -0
  31. package/dist/utils/fast-safe-stringify/index.js +227 -0
  32. package/dist/utils/prompts.cjs +7 -2
  33. package/dist/utils/prompts.d.ts +6 -1
  34. package/dist/utils/prompts.js +6 -1
  35. package/dist/wrappers/openai_agents.cjs +849 -0
  36. package/dist/wrappers/openai_agents.d.ts +92 -0
  37. package/dist/wrappers/openai_agents.js +845 -0
  38. package/package.json +22 -6
  39. package/wrappers/openai_agents.cjs +1 -0
  40. package/wrappers/openai_agents.d.cts +1 -0
  41. package/wrappers/openai_agents.d.ts +1 -0
  42. package/wrappers/openai_agents.js +1 -0
package/dist/client.js CHANGED
@@ -7,12 +7,12 @@ import { getEnvironmentVariable, getLangSmithEnvVarsMetadata, getLangSmithEnviro
7
7
  import { __version__ } from "./index.js";
8
8
  import { assertUuid } from "./utils/_uuid.js";
9
9
  import { warnOnce } from "./utils/warn.js";
10
- import { parsePromptIdentifier } from "./utils/prompts.js";
11
- import { raiseForStatus, isLangSmithNotFoundError } from "./utils/error.js";
10
+ import { parseHubIdentifier } from "./utils/prompts.js";
11
+ import { raiseForStatus, isLangSmithNotFoundError, isLangSmithConflictError, } from "./utils/error.js";
12
12
  import { promptCacheSingleton, } from "./utils/prompt_cache/index.js";
13
13
  import * as fsUtils from "./utils/fs.js";
14
14
  import { _shouldStreamForGlobalFetchImplementation, _getFetchImplementation, } from "./singletons/fetch.js";
15
- import { serialize as serializePayloadForTracing } from "./utils/fast-safe-stringify/index.js";
15
+ import { serialize as serializePayloadForTracing, estimateSerializedSize, } from "./utils/fast-safe-stringify/index.js";
16
16
  /**
17
17
  * Catches timestamps without a timezone suffix.
18
18
  */
@@ -152,7 +152,19 @@ export class AutoBatchQueue {
152
152
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise
153
153
  itemPromiseResolve = resolve;
154
154
  });
155
- const size = serializePayloadForTracing(item.item, `Serializing run with id: ${item.item.id}`).length;
155
+ // By default we compute the exact serialized size here by stringifying
156
+ // the payload. This is expensive: JSON.stringify on large payloads
157
+ // blocks the event loop on the user's hot path.
158
+ //
159
+ // Opting into LANGSMITH_PERF_OPTIMIZATION=true switches to a cheap
160
+ // structural estimate instead. The estimate is only used for soft
161
+ // memory accounting (queue size limit and downstream async caller
162
+ // memory tracking), never for anything correctness-critical -- the
163
+ // real serialization still happens later, off the hot path, when the
164
+ // batch is assembled for sending.
165
+ const size = getLangSmithEnvironmentVariable("PERF_OPTIMIZATION") === "true"
166
+ ? estimateSerializedSize(item.item)
167
+ : serializePayloadForTracing(item.item, `Serializing run with id: ${item.item.id}`).length;
156
168
  // Check if adding this item would exceed the size limit
157
169
  // Allow the run if the queue is empty (to support large single traces)
158
170
  if (this.sizeBytes + size > this.maxSizeBytes && this.items.length > 0) {
@@ -279,6 +291,12 @@ export class Client {
279
291
  writable: true,
280
292
  value: void 0
281
293
  });
294
+ Object.defineProperty(this, "hideMetadata", {
295
+ enumerable: true,
296
+ configurable: true,
297
+ writable: true,
298
+ value: void 0
299
+ });
282
300
  Object.defineProperty(this, "omitTracedRuntimeInfo", {
283
301
  enumerable: true,
284
302
  configurable: true,
@@ -491,6 +509,7 @@ export class Client {
491
509
  config.hideInputs ?? config.anonymizer ?? defaultConfig.hideInputs;
492
510
  this.hideOutputs =
493
511
  config.hideOutputs ?? config.anonymizer ?? defaultConfig.hideOutputs;
512
+ this.hideMetadata = config.hideMetadata ?? defaultConfig.hideMetadata;
494
513
  this.omitTracedRuntimeInfo = config.omitTracedRuntimeInfo ?? false;
495
514
  this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
496
515
  this.autoBatchQueue = new AutoBatchQueue(maxMemory);
@@ -540,12 +559,14 @@ export class Client {
540
559
  const apiUrl = getLangSmithEnvironmentVariable("ENDPOINT") ?? DEFAULT_API_URL;
541
560
  const hideInputs = getLangSmithEnvironmentVariable("HIDE_INPUTS") === "true";
542
561
  const hideOutputs = getLangSmithEnvironmentVariable("HIDE_OUTPUTS") === "true";
562
+ const hideMetadata = getLangSmithEnvironmentVariable("HIDE_METADATA") === "true";
543
563
  return {
544
564
  apiUrl: apiUrl,
545
565
  apiKey: apiKey,
546
566
  webUrl: undefined,
547
567
  hideInputs: hideInputs,
548
568
  hideOutputs: hideOutputs,
569
+ hideMetadata: hideMetadata,
549
570
  };
550
571
  }
551
572
  getHostUrl() {
@@ -641,6 +662,18 @@ export class Client {
641
662
  }
642
663
  return outputs;
643
664
  }
665
+ async processMetadata(metadata) {
666
+ if (this.hideMetadata === false) {
667
+ return metadata;
668
+ }
669
+ if (this.hideMetadata === true) {
670
+ return {};
671
+ }
672
+ if (typeof this.hideMetadata === "function") {
673
+ return this.hideMetadata(metadata);
674
+ }
675
+ return metadata;
676
+ }
644
677
  /**
645
678
  * Filter content from new_token events to prevent streaming LLM output
646
679
  * from being uploaded via events.
@@ -667,6 +700,12 @@ export class Client {
667
700
  if (runParams.outputs !== undefined) {
668
701
  runParams.outputs = await this.processOutputs(runParams.outputs);
669
702
  }
703
+ if (runParams.extra != null && "metadata" in runParams.extra) {
704
+ runParams.extra = {
705
+ ...runParams.extra,
706
+ metadata: await this.processMetadata(runParams.extra.metadata),
707
+ };
708
+ }
670
709
  if (runParams.events !== undefined) {
671
710
  runParams.events = this._filterNewTokenEvents(runParams.events);
672
711
  }
@@ -1514,6 +1553,12 @@ export class Client {
1514
1553
  if (run.outputs) {
1515
1554
  run.outputs = await this.processOutputs(run.outputs);
1516
1555
  }
1556
+ if (run.extra != null && "metadata" in run.extra) {
1557
+ run.extra = {
1558
+ ...run.extra,
1559
+ metadata: await this.processMetadata(run.extra.metadata),
1560
+ };
1561
+ }
1517
1562
  if (run.events) {
1518
1563
  run.events = this._filterNewTokenEvents(run.events);
1519
1564
  }
@@ -3750,7 +3795,7 @@ export class Client {
3750
3795
  return json.commits[0].commit_hash;
3751
3796
  }
3752
3797
  async _likeOrUnlikePrompt(promptIdentifier, like) {
3753
- const [owner, promptName, _] = parsePromptIdentifier(promptIdentifier);
3798
+ const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
3754
3799
  const body = JSON.stringify({ like: like });
3755
3800
  const response = await this.caller.call(async () => {
3756
3801
  const res = await this._fetch(`${this.apiUrl}/likes/${owner}/${promptName}`, {
@@ -3769,7 +3814,7 @@ export class Client {
3769
3814
  return response.json();
3770
3815
  }
3771
3816
  async _getPromptUrl(promptIdentifier) {
3772
- const [owner, promptName, commitHash] = parsePromptIdentifier(promptIdentifier);
3817
+ const [owner, promptName, commitHash] = parseHubIdentifier(promptIdentifier);
3773
3818
  if (!(await this._currentTenantIsOwner(owner))) {
3774
3819
  if (commitHash !== "latest") {
3775
3820
  return `${this.getHostUrl()}/hub/${owner}/${promptName}/${commitHash.substring(0, 8)}`;
@@ -3861,7 +3906,7 @@ export class Client {
3861
3906
  * ```
3862
3907
  */
3863
3908
  async *listCommits(promptIdentifier) {
3864
- const [owner, promptName, _] = parsePromptIdentifier(promptIdentifier);
3909
+ const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
3865
3910
  for await (const commits of this._getPaginated(`/commits/${owner}/${promptName}/`, new URLSearchParams(), (res) => res.commits)) {
3866
3911
  yield* commits;
3867
3912
  }
@@ -3924,7 +3969,7 @@ export class Client {
3924
3969
  * ```
3925
3970
  */
3926
3971
  async getPrompt(promptIdentifier) {
3927
- const [owner, promptName, _] = parsePromptIdentifier(promptIdentifier);
3972
+ const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
3928
3973
  const response = await this.caller.call(async () => {
3929
3974
  const res = await this._fetch(`${this.apiUrl}/repos/${owner}/${promptName}`, {
3930
3975
  method: "GET",
@@ -3981,7 +4026,7 @@ export class Client {
3981
4026
  You can add a handle by creating a public prompt at:\n
3982
4027
  https://smith.langchain.com/prompts`);
3983
4028
  }
3984
- const [owner, promptName, _] = parsePromptIdentifier(promptIdentifier);
4029
+ const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
3985
4030
  if (!(await this._currentTenantIsOwner(owner))) {
3986
4031
  throw await this._ownerConflictError("create a prompt", owner);
3987
4032
  }
@@ -4040,7 +4085,7 @@ export class Client {
4040
4085
  if (!(await this.promptExists(promptIdentifier))) {
4041
4086
  throw new Error("Prompt does not exist, you must create it first.");
4042
4087
  }
4043
- const [owner, promptName, _] = parsePromptIdentifier(promptIdentifier);
4088
+ const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
4044
4089
  const resolvedParentCommitHash = options?.parentCommitHash === "latest" || !options?.parentCommitHash
4045
4090
  ? await this._getLatestCommitHash(`${owner}/${promptName}`)
4046
4091
  : options?.parentCommitHash;
@@ -4238,7 +4283,7 @@ export class Client {
4238
4283
  if (!(await this.promptExists(promptIdentifier))) {
4239
4284
  throw new Error("Prompt does not exist, you must create it first.");
4240
4285
  }
4241
- const [owner, promptName] = parsePromptIdentifier(promptIdentifier);
4286
+ const [owner, promptName] = parseHubIdentifier(promptIdentifier);
4242
4287
  if (!(await this._currentTenantIsOwner(owner))) {
4243
4288
  throw await this._ownerConflictError("update a prompt", owner);
4244
4289
  }
@@ -4278,7 +4323,7 @@ export class Client {
4278
4323
  if (!(await this.promptExists(promptIdentifier))) {
4279
4324
  throw new Error("Prompt does not exist, you must create it first.");
4280
4325
  }
4281
- const [owner, promptName, _] = parsePromptIdentifier(promptIdentifier);
4326
+ const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
4282
4327
  if (!(await this._currentTenantIsOwner(owner))) {
4283
4328
  throw await this._ownerConflictError("delete a prompt", owner);
4284
4329
  }
@@ -4306,7 +4351,7 @@ export class Client {
4306
4351
  * Fetch a prompt commit directly from the API (bypassing cache).
4307
4352
  */
4308
4353
  async _fetchPromptFromApi(promptIdentifier, options) {
4309
- const [owner, promptName, commitHash] = parsePromptIdentifier(promptIdentifier);
4354
+ const [owner, promptName, commitHash] = parseHubIdentifier(promptIdentifier);
4310
4355
  const response = await this.caller.call(async () => {
4311
4356
  const res = await this._fetch(`${this.apiUrl}/commits/${owner}/${promptName}/${commitHash}${options?.includeModel ? "?include_model=true" : ""}`, {
4312
4357
  method: "GET",
@@ -4386,6 +4431,251 @@ export class Client {
4386
4431
  });
4387
4432
  return url;
4388
4433
  }
4434
+ /**
4435
+ * Check if an agent repo exists.
4436
+ */
4437
+ async agentExists(identifier) {
4438
+ const [owner, name] = parseHubIdentifier(identifier);
4439
+ return this._repoExists(owner, name);
4440
+ }
4441
+ /**
4442
+ * Check if a skill repo exists.
4443
+ */
4444
+ async skillExists(identifier) {
4445
+ const [owner, name] = parseHubIdentifier(identifier);
4446
+ return this._repoExists(owner, name);
4447
+ }
4448
+ /**
4449
+ * Pull an agent directory from Hub.
4450
+ * @param identifier The identifier (owner/name[:version]).
4451
+ * @param options.version Commit hash or tag; overrides identifier's version.
4452
+ */
4453
+ async pullAgent(identifier, options) {
4454
+ return (await this._pullDirectory(identifier, "agent", options?.version));
4455
+ }
4456
+ /**
4457
+ * Pull a skill directory from Hub.
4458
+ */
4459
+ async pullSkill(identifier, options) {
4460
+ return (await this._pullDirectory(identifier, "skill", options?.version));
4461
+ }
4462
+ /**
4463
+ * Push an agent to Hub. Creates the repo if missing, patches metadata if
4464
+ * provided, then commits the given files.
4465
+ * @returns The URL of the resulting commit.
4466
+ */
4467
+ async pushAgent(identifier, options) {
4468
+ return this._pushDirectory(identifier, "agent", options);
4469
+ }
4470
+ /**
4471
+ * Push a skill to Hub.
4472
+ */
4473
+ async pushSkill(identifier, options) {
4474
+ return this._pushDirectory(identifier, "skill", options);
4475
+ }
4476
+ /**
4477
+ * Delete an agent and all its owned child file repos.
4478
+ */
4479
+ async deleteAgent(identifier) {
4480
+ return this._deleteDirectory(identifier);
4481
+ }
4482
+ /**
4483
+ * Delete a skill and all its owned child file repos.
4484
+ */
4485
+ async deleteSkill(identifier) {
4486
+ return this._deleteDirectory(identifier);
4487
+ }
4488
+ /**
4489
+ * List agent repos. Yields one at a time, auto-paginating.
4490
+ */
4491
+ async *listAgents(options) {
4492
+ yield* this._listReposByType("agent", options);
4493
+ }
4494
+ /**
4495
+ * List skill repos. Yields one at a time, auto-paginating.
4496
+ */
4497
+ async *listSkills(options) {
4498
+ yield* this._listReposByType("skill", options);
4499
+ }
4500
+ async *_listReposByType(repoType, options) {
4501
+ const params = new URLSearchParams();
4502
+ params.append("repo_type", repoType);
4503
+ params.append("is_archived", (!!options?.isArchived).toString());
4504
+ if (options?.isPublic !== undefined) {
4505
+ params.append("is_public", options.isPublic.toString());
4506
+ }
4507
+ if (options?.query) {
4508
+ params.append("query", options.query);
4509
+ }
4510
+ for await (const repos of this._getPaginated("/repos", params, (res) => res.repos)) {
4511
+ yield* repos;
4512
+ }
4513
+ }
4514
+ async _pullDirectory(identifier, repoType, version) {
4515
+ const [owner, name, parsedVersion] = parseHubIdentifier(identifier);
4516
+ const resolvedVersion = version ?? (parsedVersion !== "latest" ? parsedVersion : undefined);
4517
+ const url = new URL(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories`);
4518
+ url.searchParams.set("repo_type", repoType);
4519
+ if (resolvedVersion) {
4520
+ url.searchParams.set("commit", resolvedVersion);
4521
+ }
4522
+ const response = await this.caller.call(async () => {
4523
+ const res = await this._fetch(url.toString(), {
4524
+ method: "GET",
4525
+ headers: this._mergedHeaders,
4526
+ signal: AbortSignal.timeout(this.timeout_ms),
4527
+ ...this.fetchOptions,
4528
+ });
4529
+ await raiseForStatus(res, "pull directory");
4530
+ return res;
4531
+ });
4532
+ return (await response.json());
4533
+ }
4534
+ async _pushDirectory(identifier, repoType, options) {
4535
+ if (options.parentCommit !== undefined &&
4536
+ (options.parentCommit.length < 8 || options.parentCommit.length > 64)) {
4537
+ throw new Error("parent_commit must be 8-64 characters");
4538
+ }
4539
+ const [owner, name] = parseHubIdentifier(identifier);
4540
+ if (!(await this._currentTenantIsOwner(owner))) {
4541
+ throw await this._ownerConflictError(`push ${repoType}`, owner);
4542
+ }
4543
+ if (await this._repoExists(owner, name)) {
4544
+ if (options.description !== undefined ||
4545
+ options.readme !== undefined ||
4546
+ options.tags !== undefined ||
4547
+ options.isPublic !== undefined) {
4548
+ await this._updateRepoMetadata(owner, name, options);
4549
+ }
4550
+ }
4551
+ else {
4552
+ const REPO_HANDLE_PATTERN = /^[a-z][a-z0-9-_]*$/;
4553
+ if (!REPO_HANDLE_PATTERN.test(name)) {
4554
+ throw new Error(`Invalid repo_handle ${JSON.stringify(name)}: must match ${REPO_HANDLE_PATTERN}`);
4555
+ }
4556
+ await this._createRepo(name, repoType, options);
4557
+ }
4558
+ const body = { files: options.files };
4559
+ if (options.parentCommit) {
4560
+ body.parent_commit = options.parentCommit;
4561
+ }
4562
+ const response = await this.caller.call(async () => {
4563
+ const res = await this._fetch(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories/commits`, {
4564
+ method: "POST",
4565
+ headers: {
4566
+ ...this._mergedHeaders,
4567
+ "Content-Type": "application/json",
4568
+ },
4569
+ signal: AbortSignal.timeout(this.timeout_ms),
4570
+ ...this.fetchOptions,
4571
+ body: JSON.stringify(body),
4572
+ });
4573
+ await raiseForStatus(res, `push ${repoType}`);
4574
+ return res;
4575
+ });
4576
+ const data = (await response.json());
4577
+ const commitHash = data.commit.commit_hash;
4578
+ return `${this.getHostUrl()}/hub/${owner}/${name}:${commitHash.slice(0, 8)}`;
4579
+ }
4580
+ async _deleteDirectory(identifier) {
4581
+ const [owner, name] = parseHubIdentifier(identifier);
4582
+ if (!(await this._currentTenantIsOwner(owner))) {
4583
+ throw await this._ownerConflictError("delete", owner);
4584
+ }
4585
+ await this.caller.call(async () => {
4586
+ const res = await this._fetch(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories`, {
4587
+ method: "DELETE",
4588
+ headers: this._mergedHeaders,
4589
+ signal: AbortSignal.timeout(this.timeout_ms),
4590
+ ...this.fetchOptions,
4591
+ });
4592
+ await raiseForStatus(res, "delete directory");
4593
+ return res;
4594
+ });
4595
+ }
4596
+ async _repoExists(owner, name) {
4597
+ try {
4598
+ await this.caller.call(async () => {
4599
+ const res = await this._fetch(`${this.apiUrl}/repos/${owner}/${name}`, {
4600
+ method: "GET",
4601
+ headers: this._mergedHeaders,
4602
+ signal: AbortSignal.timeout(this.timeout_ms),
4603
+ ...this.fetchOptions,
4604
+ });
4605
+ await raiseForStatus(res, "check repo exists");
4606
+ return res;
4607
+ });
4608
+ return true;
4609
+ }
4610
+ catch (e) {
4611
+ if (isLangSmithNotFoundError(e)) {
4612
+ return false;
4613
+ }
4614
+ throw e;
4615
+ }
4616
+ }
4617
+ async _createRepo(name, repoType, options) {
4618
+ const body = {
4619
+ repo_handle: name,
4620
+ repo_type: repoType,
4621
+ is_public: !!options.isPublic,
4622
+ };
4623
+ if (options.description !== undefined)
4624
+ body.description = options.description;
4625
+ if (options.readme !== undefined)
4626
+ body.readme = options.readme;
4627
+ if (options.tags !== undefined)
4628
+ body.tags = options.tags;
4629
+ try {
4630
+ await this.caller.call(async () => {
4631
+ const res = await this._fetch(`${this.apiUrl}/repos/`, {
4632
+ method: "POST",
4633
+ headers: {
4634
+ ...this._mergedHeaders,
4635
+ "Content-Type": "application/json",
4636
+ },
4637
+ signal: AbortSignal.timeout(this.timeout_ms),
4638
+ ...this.fetchOptions,
4639
+ body: JSON.stringify(body),
4640
+ });
4641
+ await raiseForStatus(res, `create ${repoType}`);
4642
+ return res;
4643
+ });
4644
+ }
4645
+ catch (e) {
4646
+ if (isLangSmithConflictError(e)) {
4647
+ return;
4648
+ }
4649
+ throw e;
4650
+ }
4651
+ }
4652
+ async _updateRepoMetadata(owner, name, options) {
4653
+ const body = {};
4654
+ if (options.description !== undefined)
4655
+ body.description = options.description;
4656
+ if (options.readme !== undefined)
4657
+ body.readme = options.readme;
4658
+ if (options.tags !== undefined)
4659
+ body.tags = options.tags;
4660
+ if (options.isPublic !== undefined)
4661
+ body.is_public = options.isPublic;
4662
+ if (Object.keys(body).length === 0)
4663
+ return;
4664
+ await this.caller.call(async () => {
4665
+ const res = await this._fetch(`${this.apiUrl}/repos/${owner}/${name}`, {
4666
+ method: "PATCH",
4667
+ headers: {
4668
+ ...this._mergedHeaders,
4669
+ "Content-Type": "application/json",
4670
+ },
4671
+ signal: AbortSignal.timeout(this.timeout_ms),
4672
+ ...this.fetchOptions,
4673
+ body: JSON.stringify(body),
4674
+ });
4675
+ await raiseForStatus(res, "update repo metadata");
4676
+ return res;
4677
+ });
4678
+ }
4389
4679
  /**
4390
4680
  * Clone a public dataset to your own langsmith tenant.
4391
4681
  * This operation is idempotent. If you already have a dataset with the given name,
@@ -4525,6 +4815,33 @@ export class Client {
4525
4815
  await getDefaultOTLPTracerComponents()?.DEFAULT_LANGSMITH_SPAN_PROCESSOR?.forceFlush();
4526
4816
  }
4527
4817
  }
4818
+ /**
4819
+ * Returns a string representation of the Client instance.
4820
+ * This method is called when the object is converted to a string
4821
+ * or logged, ensuring sensitive information like API keys is not exposed.
4822
+ *
4823
+ * @returns A string representation of the Client.
4824
+ */
4825
+ toString() {
4826
+ const params = [`apiUrl=${JSON.stringify(this.apiUrl)}`];
4827
+ if (this.webUrl !== undefined) {
4828
+ params.push(`webUrl=${JSON.stringify(this.webUrl)}`);
4829
+ }
4830
+ if (this.workspaceId !== undefined) {
4831
+ params.push(`workspaceId=${JSON.stringify(this.workspaceId)}`);
4832
+ }
4833
+ return `[LangSmithClient ${params.join(" ")}]`;
4834
+ }
4835
+ /**
4836
+ * Custom inspect method for Node.js.
4837
+ * This method is called when the object is inspected in the Node.js REPL
4838
+ * or with console.log, ensuring sensitive information like API keys is not exposed.
4839
+ *
4840
+ * @returns A string representation of the Client for inspection.
4841
+ */
4842
+ [Symbol.for("nodejs.util.inspect.custom")]() {
4843
+ return this.toString();
4844
+ }
4528
4845
  }
4529
4846
  Object.defineProperty(Client, "_fallbackDirsCreated", {
4530
4847
  enumerable: true,
@@ -726,10 +726,7 @@ async function _evaluate(target, fields) {
726
726
  const standardFields = fields;
727
727
  const [experiment_, newRuns] = await _resolveExperiment(fields.experiment ?? null, runs, client);
728
728
  let manager = await new _ExperimentManager({
729
- data: Array.isArray(standardFields.data) ? undefined : standardFields.data,
730
- examples: Array.isArray(standardFields.data)
731
- ? standardFields.data
732
- : undefined,
729
+ data: standardFields.data,
733
730
  client,
734
731
  metadata: fields.metadata,
735
732
  experiment: experiment_ ?? fields.experimentPrefix,
@@ -719,10 +719,7 @@ async function _evaluate(target, fields) {
719
719
  const standardFields = fields;
720
720
  const [experiment_, newRuns] = await _resolveExperiment(fields.experiment ?? null, runs, client);
721
721
  let manager = await new _ExperimentManager({
722
- data: Array.isArray(standardFields.data) ? undefined : standardFields.data,
723
- examples: Array.isArray(standardFields.data)
724
- ? standardFields.data
725
- : undefined,
722
+ data: standardFields.data,
726
723
  client,
727
724
  metadata: fields.metadata,
728
725
  experiment: experiment_ ?? fields.experimentPrefix,