langsmith 0.8.4 → 0.8.6

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.
@@ -300,6 +300,7 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
300
300
  },
301
301
  enableTestTracking: experimentConfig?.enableTestTracking,
302
302
  setupPromise,
303
+ syncExamplePromises: new Map(),
303
304
  };
304
305
  beforeAll(async () => {
305
306
  const storageValue = await runDatasetSetup(context);
@@ -307,15 +308,14 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
307
308
  setupPromiseResolver();
308
309
  });
309
310
  afterAll(async () => {
311
+ const examples = await Promise.all(context.syncExamplePromises.values());
310
312
  await Promise.all([
311
313
  client.awaitPendingTraceBatches(),
312
- ...globals_js_1.syncExamplePromises.values(),
313
314
  ...globals_js_1.evaluatorLogFeedbackPromises.values(),
314
315
  ]);
315
316
  if (!(0, globals_js_1.trackingEnabled)(context)) {
316
317
  return;
317
318
  }
318
- const examples = [...globals_js_1.syncExamplePromises.values()];
319
319
  if (examples.length === 0) {
320
320
  return;
321
321
  }
@@ -364,6 +364,7 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
364
364
  await client.updateProject(datasetInfo.project.id, {
365
365
  metadata: {
366
366
  ...suiteMetadata,
367
+ dataset_version: finalModifiedAt,
367
368
  commit,
368
369
  branch,
369
370
  dirty,
@@ -546,8 +547,11 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
546
547
  // Currently run end time has to be after example modified time
547
548
  // for examples to render properly, so we must modify the example
548
549
  // first before running the test.
549
- if (globals_js_1.syncExamplePromises.get(exampleId) === undefined) {
550
- globals_js_1.syncExamplePromises.set(exampleId, await syncExample({
550
+ if (context.syncExamplePromises === undefined) {
551
+ throw new Error("Internal error: syncExamplePromises not initialized. This is a bug in the LangSmith SDK — please open an issue at https://github.com/langchain-ai/langsmith-sdk/issues.");
552
+ }
553
+ if (!context.syncExamplePromises.has(exampleId)) {
554
+ const syncPromise = syncExample({
551
555
  client,
552
556
  exampleId,
553
557
  datasetId: dataset.id,
@@ -556,8 +560,10 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
556
560
  metadata,
557
561
  split,
558
562
  createdAt,
559
- }));
563
+ });
564
+ context.syncExamplePromises.set(exampleId, syncPromise);
560
565
  }
566
+ await context.syncExamplePromises.get(exampleId);
561
567
  const traceableOptions = {
562
568
  reference_example_id: exampleId,
563
569
  project_name: project.name,
@@ -573,6 +579,9 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
573
579
  const tracedFunction = (0, traceable_js_1.traceable)(async () => {
574
580
  return globals_js_1.testWrapperAsyncLocalStorageInstance.run({
575
581
  ...context,
582
+ dataset,
583
+ project,
584
+ client,
576
585
  currentExample: {
577
586
  inputs,
578
587
  outputs: referenceOutputs,
@@ -9,7 +9,7 @@ import { execSync } from "child_process";
9
9
  import { getCurrentRunTree, traceable } from "../../traceable.js";
10
10
  import { randomName } from "../../evaluation/_random_name.js";
11
11
  import { toBeRelativeCloseTo, toBeAbsoluteCloseTo, toBeSemanticCloseTo, } from "./matchers.js";
12
- import { evaluatorLogFeedbackPromises, testWrapperAsyncLocalStorageInstance, _logTestFeedback, syncExamplePromises, trackingEnabled, DEFAULT_TEST_CLIENT, } from "./globals.js";
12
+ import { evaluatorLogFeedbackPromises, testWrapperAsyncLocalStorageInstance, _logTestFeedback, trackingEnabled, DEFAULT_TEST_CLIENT, } from "./globals.js";
13
13
  import { wrapExpect } from "./vendor/chain.js";
14
14
  import { getEnvironmentVariable, isJsDom } from "../env.js";
15
15
  import { STRIP_ANSI_REGEX, TEST_ID_DELIMITER, UUID5_NAMESPACE, } from "./constants.js";
@@ -253,6 +253,7 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
253
253
  },
254
254
  enableTestTracking: experimentConfig?.enableTestTracking,
255
255
  setupPromise,
256
+ syncExamplePromises: new Map(),
256
257
  };
257
258
  beforeAll(async () => {
258
259
  const storageValue = await runDatasetSetup(context);
@@ -260,15 +261,14 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
260
261
  setupPromiseResolver();
261
262
  });
262
263
  afterAll(async () => {
264
+ const examples = await Promise.all(context.syncExamplePromises.values());
263
265
  await Promise.all([
264
266
  client.awaitPendingTraceBatches(),
265
- ...syncExamplePromises.values(),
266
267
  ...evaluatorLogFeedbackPromises.values(),
267
268
  ]);
268
269
  if (!trackingEnabled(context)) {
269
270
  return;
270
271
  }
271
- const examples = [...syncExamplePromises.values()];
272
272
  if (examples.length === 0) {
273
273
  return;
274
274
  }
@@ -317,6 +317,7 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
317
317
  await client.updateProject(datasetInfo.project.id, {
318
318
  metadata: {
319
319
  ...suiteMetadata,
320
+ dataset_version: finalModifiedAt,
320
321
  commit,
321
322
  branch,
322
323
  dirty,
@@ -499,8 +500,11 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
499
500
  // Currently run end time has to be after example modified time
500
501
  // for examples to render properly, so we must modify the example
501
502
  // first before running the test.
502
- if (syncExamplePromises.get(exampleId) === undefined) {
503
- syncExamplePromises.set(exampleId, await syncExample({
503
+ if (context.syncExamplePromises === undefined) {
504
+ throw new Error("Internal error: syncExamplePromises not initialized. This is a bug in the LangSmith SDK — please open an issue at https://github.com/langchain-ai/langsmith-sdk/issues.");
505
+ }
506
+ if (!context.syncExamplePromises.has(exampleId)) {
507
+ const syncPromise = syncExample({
504
508
  client,
505
509
  exampleId,
506
510
  datasetId: dataset.id,
@@ -509,8 +513,10 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
509
513
  metadata,
510
514
  split,
511
515
  createdAt,
512
- }));
516
+ });
517
+ context.syncExamplePromises.set(exampleId, syncPromise);
513
518
  }
519
+ await context.syncExamplePromises.get(exampleId);
514
520
  const traceableOptions = {
515
521
  reference_example_id: exampleId,
516
522
  project_name: project.name,
@@ -526,6 +532,9 @@ export function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
526
532
  const tracedFunction = traceable(async () => {
527
533
  return testWrapperAsyncLocalStorageInstance.run({
528
534
  ...context,
535
+ dataset,
536
+ project,
537
+ client,
529
538
  currentExample: {
530
539
  inputs,
531
540
  outputs: referenceOutputs,
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.v2RunToRun = v2RunToRun;
4
+ exports.loadTracesV2 = loadTracesV2;
5
+ // Omitting selects from `/v2/runs/query` returns only the run ID.
6
+ const V2_RUN_SELECTS = [
7
+ "ID",
8
+ "NAME",
9
+ "RUN_TYPE",
10
+ "STATUS",
11
+ "START_TIME",
12
+ "END_TIME",
13
+ "INPUTS",
14
+ "OUTPUTS",
15
+ "PARENT_RUN_IDS",
16
+ "PROJECT_ID",
17
+ "TRACE_ID",
18
+ "DOTTED_ORDER",
19
+ "REFERENCE_EXAMPLE_ID",
20
+ "ERROR",
21
+ ];
22
+ function v2RunToRun(run) {
23
+ if (run.id == null || run.name == null || run.run_type == null) {
24
+ throw new Error("V2 run response is missing required fields.");
25
+ }
26
+ return {
27
+ id: run.id,
28
+ name: run.name,
29
+ run_type: run.run_type.toLowerCase(),
30
+ start_time: run.start_time,
31
+ end_time: run.end_time,
32
+ trace_id: run.trace_id,
33
+ session_id: run.project_id,
34
+ parent_run_id: run.parent_run_ids?.at(-1),
35
+ dotted_order: run.dotted_order,
36
+ reference_example_id: run.reference_example_id,
37
+ inputs: run.inputs ?? {},
38
+ outputs: run.outputs,
39
+ error: run.error ?? undefined,
40
+ status: run.status?.toLowerCase(),
41
+ };
42
+ }
43
+ async function loadTracesV2(client, project, options) {
44
+ const runs = [];
45
+ const pager = client.runs.queryV2({
46
+ project_ids: [project.id],
47
+ min_start_time: new Date(project.start_time).toISOString(),
48
+ max_start_time: new Date(project.end_time ?? Date.now()).toISOString(),
49
+ is_root: options.isRoot,
50
+ selects: V2_RUN_SELECTS,
51
+ });
52
+ for await (const run of pager) {
53
+ runs.push(v2RunToRun(run));
54
+ }
55
+ return runs;
56
+ }
@@ -0,0 +1,7 @@
1
+ import type { Run as V2Run } from "../_openapi_client/resources/runs/runs.js";
2
+ import type { Client } from "../client.js";
3
+ import type { Run, TracerSession } from "../schemas.js";
4
+ export declare function v2RunToRun(run: V2Run): Run;
5
+ export declare function loadTracesV2(client: Client, project: TracerSession, options: {
6
+ isRoot?: boolean;
7
+ }): Promise<Run[]>;
@@ -0,0 +1,52 @@
1
+ // Omitting selects from `/v2/runs/query` returns only the run ID.
2
+ const V2_RUN_SELECTS = [
3
+ "ID",
4
+ "NAME",
5
+ "RUN_TYPE",
6
+ "STATUS",
7
+ "START_TIME",
8
+ "END_TIME",
9
+ "INPUTS",
10
+ "OUTPUTS",
11
+ "PARENT_RUN_IDS",
12
+ "PROJECT_ID",
13
+ "TRACE_ID",
14
+ "DOTTED_ORDER",
15
+ "REFERENCE_EXAMPLE_ID",
16
+ "ERROR",
17
+ ];
18
+ export function v2RunToRun(run) {
19
+ if (run.id == null || run.name == null || run.run_type == null) {
20
+ throw new Error("V2 run response is missing required fields.");
21
+ }
22
+ return {
23
+ id: run.id,
24
+ name: run.name,
25
+ run_type: run.run_type.toLowerCase(),
26
+ start_time: run.start_time,
27
+ end_time: run.end_time,
28
+ trace_id: run.trace_id,
29
+ session_id: run.project_id,
30
+ parent_run_id: run.parent_run_ids?.at(-1),
31
+ dotted_order: run.dotted_order,
32
+ reference_example_id: run.reference_example_id,
33
+ inputs: run.inputs ?? {},
34
+ outputs: run.outputs,
35
+ error: run.error ?? undefined,
36
+ status: run.status?.toLowerCase(),
37
+ };
38
+ }
39
+ export async function loadTracesV2(client, project, options) {
40
+ const runs = [];
41
+ const pager = client.runs.queryV2({
42
+ project_ids: [project.id],
43
+ min_start_time: new Date(project.start_time).toISOString(),
44
+ max_start_time: new Date(project.end_time ?? Date.now()).toISOString(),
45
+ is_root: options.isRoot,
46
+ selects: V2_RUN_SELECTS,
47
+ });
48
+ for await (const run of pager) {
49
+ runs.push(v2RunToRun(run));
50
+ }
51
+ return runs;
52
+ }
package/dist/uuid.cjs CHANGED
@@ -2,12 +2,32 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.uuid7FromTime = void 0;
4
4
  exports.uuid7 = uuid7;
5
+ exports.computeRunIdForSecondaryReplica = computeRunIdForSecondaryReplica;
5
6
  const index_js_1 = require("./utils/uuid/src/index.cjs");
6
- var _uuid_js_1 = require("./utils/_uuid.cjs");
7
- Object.defineProperty(exports, "uuid7FromTime", { enumerable: true, get: function () { return _uuid_js_1.uuid7FromTime; } });
7
+ const _uuid_js_1 = require("./utils/_uuid.cjs");
8
+ var _uuid_js_2 = require("./utils/_uuid.cjs");
9
+ Object.defineProperty(exports, "uuid7FromTime", { enumerable: true, get: function () { return _uuid_js_2.uuid7FromTime; } });
8
10
  /**
9
11
  * Generate a random UUID v7 string.
10
12
  */
11
13
  function uuid7() {
12
14
  return (0, index_js_1.v7)();
13
15
  }
16
+ /**
17
+ * Compute the run ID used for a secondary tracing replica.
18
+ *
19
+ * @param runId - The original UUID v7 run ID.
20
+ * @param projectName - The secondary replica's destination project name.
21
+ * @returns The run ID used in the secondary replica destination.
22
+ */
23
+ function computeRunIdForSecondaryReplica(runId, projectName) {
24
+ if (typeof projectName !== "string" || projectName.length === 0) {
25
+ throw new Error("projectName must be a non-empty string");
26
+ }
27
+ (0, _uuid_js_1.assertUuid)(runId, "runId");
28
+ const normalizedRunId = runId.toLowerCase();
29
+ if ((0, _uuid_js_1.getUuidVersion)(normalizedRunId) !== 7) {
30
+ throw new Error("runId must be a UUID v7");
31
+ }
32
+ return (0, _uuid_js_1.nonCryptographicUuid7Deterministic)(normalizedRunId, projectName);
33
+ }
package/dist/uuid.d.ts CHANGED
@@ -3,3 +3,11 @@ export { uuid7FromTime } from "./utils/_uuid.js";
3
3
  * Generate a random UUID v7 string.
4
4
  */
5
5
  export declare function uuid7(): string;
6
+ /**
7
+ * Compute the run ID used for a secondary tracing replica.
8
+ *
9
+ * @param runId - The original UUID v7 run ID.
10
+ * @param projectName - The secondary replica's destination project name.
11
+ * @returns The run ID used in the secondary replica destination.
12
+ */
13
+ export declare function computeRunIdForSecondaryReplica(runId: string, projectName: string): string;
package/dist/uuid.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { v7 as uuidv7 } from "./utils/uuid/src/index.js";
2
+ import { assertUuid, getUuidVersion, nonCryptographicUuid7Deterministic, } from "./utils/_uuid.js";
2
3
  export { uuid7FromTime } from "./utils/_uuid.js";
3
4
  /**
4
5
  * Generate a random UUID v7 string.
@@ -6,3 +7,21 @@ export { uuid7FromTime } from "./utils/_uuid.js";
6
7
  export function uuid7() {
7
8
  return uuidv7();
8
9
  }
10
+ /**
11
+ * Compute the run ID used for a secondary tracing replica.
12
+ *
13
+ * @param runId - The original UUID v7 run ID.
14
+ * @param projectName - The secondary replica's destination project name.
15
+ * @returns The run ID used in the secondary replica destination.
16
+ */
17
+ export function computeRunIdForSecondaryReplica(runId, projectName) {
18
+ if (typeof projectName !== "string" || projectName.length === 0) {
19
+ throw new Error("projectName must be a non-empty string");
20
+ }
21
+ assertUuid(runId, "runId");
22
+ const normalizedRunId = runId.toLowerCase();
23
+ if (getUuidVersion(normalizedRunId) !== 7) {
24
+ throw new Error("runId must be a UUID v7");
25
+ }
26
+ return nonCryptographicUuid7Deterministic(normalizedRunId, projectName);
27
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
5
5
  "packageManager": "pnpm@10.33.0",
6
6
  "files": [
@@ -156,12 +156,18 @@
156
156
  "p-queue": "6.6.2"
157
157
  },
158
158
  "devDependencies": {
159
+ "@ai-sdk/anthropic": "4.0.18",
160
+ "@ai-sdk/harness": "1.0.41",
161
+ "@ai-sdk/harness-claude-code": "1.0.42",
162
+ "@ai-sdk/harness-pi": "1.0.41",
159
163
  "@ai-sdk/openai": "4.0.4",
160
164
  "@ai-sdk/provider": "4.0.1",
161
- "@ai-sdk/anthropic": "4.0.0-beta.67",
165
+ "@ai-sdk/sandbox-just-bash": "1.0.40",
166
+ "@ai-sdk/sandbox-vercel": "1.0.41",
162
167
  "@anthropic-ai/claude-agent-sdk": "^0.3.150",
163
168
  "@anthropic-ai/sdk": "^0.98.0",
164
169
  "@babel/preset-env": "^8.0.2",
170
+ "@earendil-works/pi-coding-agent": "0.80.10",
165
171
  "@faker-js/faker": "^8.4.1",
166
172
  "@google/genai": "^2.0.1",
167
173
  "@jest/globals": "^30.4.1",
@@ -184,7 +190,7 @@
184
190
  "@types/ws": "^8.18.1",
185
191
  "@typescript-eslint/eslint-plugin": "^8.62.1",
186
192
  "@typescript-eslint/parser": "^8.62.1",
187
- "ai": "7.0.0-beta.178",
193
+ "ai": "7.0.36",
188
194
  "babel-jest": "^30.2.0",
189
195
  "cross-env": "^10.1.0",
190
196
  "dotenv": "^17.3.1",