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.
- package/dist/client.cjs +47 -7
- package/dist/client.d.ts +17 -2
- package/dist/client.js +47 -7
- package/dist/evaluation/_runner.cjs +13 -2
- package/dist/evaluation/_runner.js +13 -2
- package/dist/evaluation/evaluate_comparative.cjs +14 -6
- package/dist/evaluation/evaluate_comparative.d.ts +4 -1
- package/dist/evaluation/evaluate_comparative.js +13 -6
- package/dist/experimental/vercel/telemetry.cjs +158 -29
- package/dist/experimental/vercel/telemetry.js +158 -29
- package/dist/index.cjs +3 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/run_trees.cjs +30 -10
- package/dist/run_trees.d.ts +3 -1
- package/dist/run_trees.js +30 -10
- package/dist/sandbox/command_handle.cjs +1 -1
- package/dist/sandbox/command_handle.js +2 -2
- package/dist/sandbox/errors.cjs +16 -1
- package/dist/sandbox/errors.d.ts +11 -0
- package/dist/sandbox/errors.js +14 -0
- package/dist/sandbox/sandbox.cjs +44 -20
- package/dist/sandbox/sandbox.js +45 -21
- package/dist/utils/jestlike/globals.cjs +13 -6
- package/dist/utils/jestlike/globals.d.ts +1 -1
- package/dist/utils/jestlike/globals.js +12 -5
- package/dist/utils/jestlike/index.cjs +14 -5
- package/dist/utils/jestlike/index.js +15 -6
- package/dist/utils/v2_migration.cjs +56 -0
- package/dist/utils/v2_migration.d.ts +7 -0
- package/dist/utils/v2_migration.js +52 -0
- package/dist/uuid.cjs +22 -2
- package/dist/uuid.d.ts +8 -0
- package/dist/uuid.js +19 -0
- package/package.json +9 -3
|
@@ -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 (
|
|
550
|
-
|
|
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,
|
|
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
|
|
503
|
-
syncExamplePromises.
|
|
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
|
-
|
|
7
|
-
|
|
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.
|
|
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/
|
|
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.
|
|
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",
|