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
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LS_MESSAGE_VIEW_EXCLUDE = exports.__version__ = exports.InternalServerError = exports.RateLimitError = exports.UnprocessableEntityError = exports.ConflictError = exports.NotFoundError = exports.PermissionDeniedError = exports.AuthenticationError = exports.BadRequestError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIUserAbortError = exports.APIError = exports.LangsmithError = exports.promptCacheSingleton = exports.configureGlobalPromptCache = exports.PromptCache = exports.Cache = exports.isTracingEnabled = exports.uuid7FromTime = exports.uuid7 = exports.getDefaultProjectName = exports.overrideFetchImplementation = exports.RunTree = exports.Client = void 0;
|
|
3
|
+
exports.LS_MESSAGE_VIEW_EXCLUDE = exports.__version__ = exports.InternalServerError = exports.RateLimitError = exports.UnprocessableEntityError = exports.ConflictError = exports.NotFoundError = exports.PermissionDeniedError = exports.AuthenticationError = exports.BadRequestError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIUserAbortError = exports.APIError = exports.LangsmithError = exports.promptCacheSingleton = exports.configureGlobalPromptCache = exports.PromptCache = exports.Cache = exports.isTracingEnabled = exports.uuid7FromTime = exports.uuid7 = exports.computeRunIdForSecondaryReplica = exports.getDefaultProjectName = exports.overrideFetchImplementation = exports.RunTree = exports.Client = void 0;
|
|
4
4
|
var client_js_1 = require("./client.cjs");
|
|
5
5
|
Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return client_js_1.Client; } });
|
|
6
6
|
var run_trees_js_1 = require("./run_trees.cjs");
|
|
@@ -10,6 +10,7 @@ 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
|
var uuid_js_1 = require("./uuid.cjs");
|
|
13
|
+
Object.defineProperty(exports, "computeRunIdForSecondaryReplica", { enumerable: true, get: function () { return uuid_js_1.computeRunIdForSecondaryReplica; } });
|
|
13
14
|
Object.defineProperty(exports, "uuid7", { enumerable: true, get: function () { return uuid_js_1.uuid7; } });
|
|
14
15
|
Object.defineProperty(exports, "uuid7FromTime", { enumerable: true, get: function () { return uuid_js_1.uuid7FromTime; } });
|
|
15
16
|
var guard_js_1 = require("./utils/guard.cjs");
|
|
@@ -34,6 +35,6 @@ Object.defineProperty(exports, "UnprocessableEntityError", { enumerable: true, g
|
|
|
34
35
|
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return error_js_1.RateLimitError; } });
|
|
35
36
|
Object.defineProperty(exports, "InternalServerError", { enumerable: true, get: function () { return error_js_1.InternalServerError; } });
|
|
36
37
|
// Update using pnpm bump-version
|
|
37
|
-
exports.__version__ = "0.8.
|
|
38
|
+
exports.__version__ = "0.8.6";
|
|
38
39
|
// Metadata key to hide a traced run from LangSmith's Messages View.
|
|
39
40
|
exports.LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { Client, type ClientConfig, type LangSmithTracingClientInterface, } from "./client.js";
|
|
2
2
|
export type { Dataset, Example, TracerSession, Run, Feedback, FeedbackConfigSchema, RetrieverOutput, } from "./schemas.js";
|
|
3
|
-
export { RunTree, type RunTreeConfig } from "./run_trees.js";
|
|
3
|
+
export { RunTree, type RunTreeConfig, type WriteReplica } from "./run_trees.js";
|
|
4
4
|
export { overrideFetchImplementation } from "./singletons/fetch.js";
|
|
5
5
|
export { getDefaultProjectName } from "./utils/project.js";
|
|
6
|
-
export { uuid7, uuid7FromTime } from "./uuid.js";
|
|
6
|
+
export { computeRunIdForSecondaryReplica, uuid7, uuid7FromTime, } from "./uuid.js";
|
|
7
7
|
export { isTracingEnabled } from "./utils/guard.js";
|
|
8
8
|
export { Cache, PromptCache, type CacheConfig, type CacheMetrics, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
9
9
|
export { LangsmithError, APIError, APIUserAbortError, APIConnectionError, APIConnectionTimeoutError, BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, } from "./_openapi_client/core/error.js";
|
|
10
|
-
export declare const __version__ = "0.8.
|
|
10
|
+
export declare const __version__ = "0.8.6";
|
|
11
11
|
export declare const LS_MESSAGE_VIEW_EXCLUDE: "ls_message_view_exclude";
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,11 @@ export { Client, } from "./client.js";
|
|
|
2
2
|
export { RunTree } from "./run_trees.js";
|
|
3
3
|
export { overrideFetchImplementation } from "./singletons/fetch.js";
|
|
4
4
|
export { getDefaultProjectName } from "./utils/project.js";
|
|
5
|
-
export { uuid7, uuid7FromTime } from "./uuid.js";
|
|
5
|
+
export { computeRunIdForSecondaryReplica, uuid7, uuid7FromTime, } from "./uuid.js";
|
|
6
6
|
export { isTracingEnabled } from "./utils/guard.js";
|
|
7
7
|
export { Cache, PromptCache, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
|
|
8
8
|
export { LangsmithError, APIError, APIUserAbortError, APIConnectionError, APIConnectionTimeoutError, BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, } from "./_openapi_client/core/error.js";
|
|
9
9
|
// Update using pnpm bump-version
|
|
10
|
-
export const __version__ = "0.8.
|
|
10
|
+
export const __version__ = "0.8.6";
|
|
11
11
|
// Metadata key to hide a traced run from LangSmith's Messages View.
|
|
12
12
|
export const LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
|
package/dist/run_trees.cjs
CHANGED
|
@@ -46,12 +46,16 @@ function convertToDottedOrderFormat(epoch, runId, executionOrder = 1) {
|
|
|
46
46
|
}
|
|
47
47
|
const HEADER_SAFE_REPLICA_FIELDS = new Set([
|
|
48
48
|
"projectName",
|
|
49
|
+
"primary",
|
|
49
50
|
"updates",
|
|
50
51
|
"reroot",
|
|
51
52
|
]);
|
|
52
53
|
function filterReplicaForHeaders(replica) {
|
|
53
54
|
const filtered = {};
|
|
54
55
|
for (const key of Object.keys(replica)) {
|
|
56
|
+
if (key === "primary" && typeof replica[key] !== "boolean") {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
55
59
|
if (HEADER_SAFE_REPLICA_FIELDS.has(key)) {
|
|
56
60
|
filtered[key] = replica[key];
|
|
57
61
|
}
|
|
@@ -567,10 +571,10 @@ class RunTree {
|
|
|
567
571
|
}
|
|
568
572
|
}
|
|
569
573
|
_remapForProject(params) {
|
|
570
|
-
const { projectName, runtimeEnv, excludeChildRuns = true, reroot = false, distributedParentId, apiUrl, apiKey, workspaceId, } = params;
|
|
574
|
+
const { projectName, primary, runtimeEnv, excludeChildRuns = true, reroot = false, distributedParentId, apiUrl, apiKey, workspaceId, } = params;
|
|
571
575
|
const baseRun = this._convertToCreate(this, runtimeEnv, excludeChildRuns);
|
|
572
|
-
//
|
|
573
|
-
if (projectName === this.project_name) {
|
|
576
|
+
// Preserve legacy behavior when `primary` is omitted.
|
|
577
|
+
if (primary === undefined && projectName === this.project_name) {
|
|
574
578
|
return {
|
|
575
579
|
...baseRun,
|
|
576
580
|
session_name: projectName,
|
|
@@ -643,6 +647,12 @@ class RunTree {
|
|
|
643
647
|
}
|
|
644
648
|
}
|
|
645
649
|
}
|
|
650
|
+
if (primary) {
|
|
651
|
+
return {
|
|
652
|
+
...baseRun,
|
|
653
|
+
session_name: projectName,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
646
656
|
// Remap IDs for the replica using nonCryptographicUuid7Deterministic
|
|
647
657
|
// This ensures consistency across runs in the same replica while
|
|
648
658
|
// preserving UUID7 properties (time-ordering, monotonicity)
|
|
@@ -691,9 +701,10 @@ class RunTree {
|
|
|
691
701
|
try {
|
|
692
702
|
const runtimeEnv = (0, env_js_2.getRuntimeEnvironment)();
|
|
693
703
|
if (this.replicas && this.replicas.length > 0) {
|
|
694
|
-
for (const { projectName, apiKey, apiUrl, workspaceId, reroot, client: replicaClient, } of this.replicas) {
|
|
704
|
+
for (const { projectName, primary, apiKey, apiUrl, workspaceId, reroot, client: replicaClient, } of this.replicas) {
|
|
695
705
|
const runCreate = this._remapForProject({
|
|
696
706
|
projectName: projectName ?? this.project_name,
|
|
707
|
+
primary,
|
|
697
708
|
runtimeEnv,
|
|
698
709
|
excludeChildRuns: true,
|
|
699
710
|
reroot,
|
|
@@ -728,9 +739,10 @@ class RunTree {
|
|
|
728
739
|
}
|
|
729
740
|
async patchRun(options) {
|
|
730
741
|
if (this.replicas && this.replicas.length > 0) {
|
|
731
|
-
for (const { projectName, apiKey, apiUrl, workspaceId, updates, reroot, client: replicaClient, } of this.replicas) {
|
|
742
|
+
for (const { projectName, primary, apiKey, apiUrl, workspaceId, updates, reroot, client: replicaClient, } of this.replicas) {
|
|
732
743
|
const runData = this._remapForProject({
|
|
733
744
|
projectName: projectName ?? this.project_name,
|
|
745
|
+
primary,
|
|
734
746
|
runtimeEnv: undefined,
|
|
735
747
|
excludeChildRuns: true,
|
|
736
748
|
reroot,
|
|
@@ -996,10 +1008,16 @@ function _getWriteReplicasFromEnv() {
|
|
|
996
1008
|
`expected string, got ${typeof item.project_name}`);
|
|
997
1009
|
continue;
|
|
998
1010
|
}
|
|
1011
|
+
if (item.primary !== undefined && typeof item.primary !== "boolean") {
|
|
1012
|
+
console.warn(`Invalid primary type in LANGSMITH_RUNS_ENDPOINTS: ` +
|
|
1013
|
+
`expected boolean, got ${typeof item.primary}`);
|
|
1014
|
+
continue;
|
|
1015
|
+
}
|
|
999
1016
|
replicas.push({
|
|
1000
1017
|
apiUrl: item.api_url.replace(/\/$/, ""),
|
|
1001
1018
|
apiKey: item.api_key,
|
|
1002
1019
|
projectName: item.project_name ?? undefined,
|
|
1020
|
+
primary: item.primary ?? undefined,
|
|
1003
1021
|
});
|
|
1004
1022
|
}
|
|
1005
1023
|
return replicas;
|
|
@@ -1039,9 +1057,8 @@ function _getWriteReplicasFromEnv() {
|
|
|
1039
1057
|
}
|
|
1040
1058
|
}
|
|
1041
1059
|
function _ensureWriteReplicas(replicas) {
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
return replicas.map((replica) => {
|
|
1060
|
+
const ensured = replicas
|
|
1061
|
+
? replicas.map((replica) => {
|
|
1045
1062
|
if (Array.isArray(replica)) {
|
|
1046
1063
|
return {
|
|
1047
1064
|
projectName: replica[0],
|
|
@@ -1049,9 +1066,12 @@ function _ensureWriteReplicas(replicas) {
|
|
|
1049
1066
|
};
|
|
1050
1067
|
}
|
|
1051
1068
|
return replica;
|
|
1052
|
-
})
|
|
1069
|
+
})
|
|
1070
|
+
: _getWriteReplicasFromEnv();
|
|
1071
|
+
if (ensured.filter((replica) => replica.primary === true).length > 1) {
|
|
1072
|
+
throw new Error("Only one replica can be marked as primary.");
|
|
1053
1073
|
}
|
|
1054
|
-
return
|
|
1074
|
+
return ensured;
|
|
1055
1075
|
}
|
|
1056
1076
|
function _checkEndpointEnvUnset(parsed) {
|
|
1057
1077
|
if (Object.keys(parsed).length > 0 &&
|
package/dist/run_trees.d.ts
CHANGED
|
@@ -55,11 +55,13 @@ interface HeadersLike {
|
|
|
55
55
|
set(name: string, value: string): void;
|
|
56
56
|
}
|
|
57
57
|
type ProjectReplica = [string, KVMap | undefined];
|
|
58
|
-
type WriteReplica = {
|
|
58
|
+
export type WriteReplica = {
|
|
59
59
|
apiUrl?: string;
|
|
60
60
|
apiKey?: string;
|
|
61
61
|
workspaceId?: string;
|
|
62
62
|
projectName?: string;
|
|
63
|
+
/** Whether this replica keeps the original run IDs. */
|
|
64
|
+
primary?: boolean;
|
|
63
65
|
updates?: KVMap | undefined;
|
|
64
66
|
fromEnv?: boolean;
|
|
65
67
|
reroot?: boolean;
|
package/dist/run_trees.js
CHANGED
|
@@ -40,12 +40,16 @@ export function convertToDottedOrderFormat(epoch, runId, executionOrder = 1) {
|
|
|
40
40
|
}
|
|
41
41
|
const HEADER_SAFE_REPLICA_FIELDS = new Set([
|
|
42
42
|
"projectName",
|
|
43
|
+
"primary",
|
|
43
44
|
"updates",
|
|
44
45
|
"reroot",
|
|
45
46
|
]);
|
|
46
47
|
function filterReplicaForHeaders(replica) {
|
|
47
48
|
const filtered = {};
|
|
48
49
|
for (const key of Object.keys(replica)) {
|
|
50
|
+
if (key === "primary" && typeof replica[key] !== "boolean") {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
49
53
|
if (HEADER_SAFE_REPLICA_FIELDS.has(key)) {
|
|
50
54
|
filtered[key] = replica[key];
|
|
51
55
|
}
|
|
@@ -561,10 +565,10 @@ export class RunTree {
|
|
|
561
565
|
}
|
|
562
566
|
}
|
|
563
567
|
_remapForProject(params) {
|
|
564
|
-
const { projectName, runtimeEnv, excludeChildRuns = true, reroot = false, distributedParentId, apiUrl, apiKey, workspaceId, } = params;
|
|
568
|
+
const { projectName, primary, runtimeEnv, excludeChildRuns = true, reroot = false, distributedParentId, apiUrl, apiKey, workspaceId, } = params;
|
|
565
569
|
const baseRun = this._convertToCreate(this, runtimeEnv, excludeChildRuns);
|
|
566
|
-
//
|
|
567
|
-
if (projectName === this.project_name) {
|
|
570
|
+
// Preserve legacy behavior when `primary` is omitted.
|
|
571
|
+
if (primary === undefined && projectName === this.project_name) {
|
|
568
572
|
return {
|
|
569
573
|
...baseRun,
|
|
570
574
|
session_name: projectName,
|
|
@@ -637,6 +641,12 @@ export class RunTree {
|
|
|
637
641
|
}
|
|
638
642
|
}
|
|
639
643
|
}
|
|
644
|
+
if (primary) {
|
|
645
|
+
return {
|
|
646
|
+
...baseRun,
|
|
647
|
+
session_name: projectName,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
640
650
|
// Remap IDs for the replica using nonCryptographicUuid7Deterministic
|
|
641
651
|
// This ensures consistency across runs in the same replica while
|
|
642
652
|
// preserving UUID7 properties (time-ordering, monotonicity)
|
|
@@ -685,9 +695,10 @@ export class RunTree {
|
|
|
685
695
|
try {
|
|
686
696
|
const runtimeEnv = getRuntimeEnvironment();
|
|
687
697
|
if (this.replicas && this.replicas.length > 0) {
|
|
688
|
-
for (const { projectName, apiKey, apiUrl, workspaceId, reroot, client: replicaClient, } of this.replicas) {
|
|
698
|
+
for (const { projectName, primary, apiKey, apiUrl, workspaceId, reroot, client: replicaClient, } of this.replicas) {
|
|
689
699
|
const runCreate = this._remapForProject({
|
|
690
700
|
projectName: projectName ?? this.project_name,
|
|
701
|
+
primary,
|
|
691
702
|
runtimeEnv,
|
|
692
703
|
excludeChildRuns: true,
|
|
693
704
|
reroot,
|
|
@@ -722,9 +733,10 @@ export class RunTree {
|
|
|
722
733
|
}
|
|
723
734
|
async patchRun(options) {
|
|
724
735
|
if (this.replicas && this.replicas.length > 0) {
|
|
725
|
-
for (const { projectName, apiKey, apiUrl, workspaceId, updates, reroot, client: replicaClient, } of this.replicas) {
|
|
736
|
+
for (const { projectName, primary, apiKey, apiUrl, workspaceId, updates, reroot, client: replicaClient, } of this.replicas) {
|
|
726
737
|
const runData = this._remapForProject({
|
|
727
738
|
projectName: projectName ?? this.project_name,
|
|
739
|
+
primary,
|
|
728
740
|
runtimeEnv: undefined,
|
|
729
741
|
excludeChildRuns: true,
|
|
730
742
|
reroot,
|
|
@@ -989,10 +1001,16 @@ function _getWriteReplicasFromEnv() {
|
|
|
989
1001
|
`expected string, got ${typeof item.project_name}`);
|
|
990
1002
|
continue;
|
|
991
1003
|
}
|
|
1004
|
+
if (item.primary !== undefined && typeof item.primary !== "boolean") {
|
|
1005
|
+
console.warn(`Invalid primary type in LANGSMITH_RUNS_ENDPOINTS: ` +
|
|
1006
|
+
`expected boolean, got ${typeof item.primary}`);
|
|
1007
|
+
continue;
|
|
1008
|
+
}
|
|
992
1009
|
replicas.push({
|
|
993
1010
|
apiUrl: item.api_url.replace(/\/$/, ""),
|
|
994
1011
|
apiKey: item.api_key,
|
|
995
1012
|
projectName: item.project_name ?? undefined,
|
|
1013
|
+
primary: item.primary ?? undefined,
|
|
996
1014
|
});
|
|
997
1015
|
}
|
|
998
1016
|
return replicas;
|
|
@@ -1032,9 +1050,8 @@ function _getWriteReplicasFromEnv() {
|
|
|
1032
1050
|
}
|
|
1033
1051
|
}
|
|
1034
1052
|
function _ensureWriteReplicas(replicas) {
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
return replicas.map((replica) => {
|
|
1053
|
+
const ensured = replicas
|
|
1054
|
+
? replicas.map((replica) => {
|
|
1038
1055
|
if (Array.isArray(replica)) {
|
|
1039
1056
|
return {
|
|
1040
1057
|
projectName: replica[0],
|
|
@@ -1042,9 +1059,12 @@ function _ensureWriteReplicas(replicas) {
|
|
|
1042
1059
|
};
|
|
1043
1060
|
}
|
|
1044
1061
|
return replica;
|
|
1045
|
-
})
|
|
1062
|
+
})
|
|
1063
|
+
: _getWriteReplicasFromEnv();
|
|
1064
|
+
if (ensured.filter((replica) => replica.primary === true).length > 1) {
|
|
1065
|
+
throw new Error("Only one replica can be marked as primary.");
|
|
1046
1066
|
}
|
|
1047
|
-
return
|
|
1067
|
+
return ensured;
|
|
1048
1068
|
}
|
|
1049
1069
|
function _checkEndpointEnvUnset(parsed) {
|
|
1050
1070
|
if (Object.keys(parsed).length > 0 &&
|
|
@@ -147,7 +147,7 @@ class CommandHandle {
|
|
|
147
147
|
return;
|
|
148
148
|
const firstResult = await this._stream.next();
|
|
149
149
|
if (firstResult.done) {
|
|
150
|
-
throw new errors_js_1.
|
|
150
|
+
throw new errors_js_1.LangSmithStreamEndedBeforeStartedError("Command stream ended before 'started' message");
|
|
151
151
|
}
|
|
152
152
|
const firstMsg = firstResult.value;
|
|
153
153
|
if (firstMsg.type !== "started") {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Port of Python's AsyncCommandHandle to TypeScript.
|
|
6
6
|
*/
|
|
7
|
-
import { LangSmithSandboxConnectionError, LangSmithSandboxOperationError, } from "./errors.js";
|
|
7
|
+
import { LangSmithSandboxConnectionError, LangSmithSandboxOperationError, LangSmithStreamEndedBeforeStartedError, } from "./errors.js";
|
|
8
8
|
/**
|
|
9
9
|
* Async handle to a running command with streaming output and auto-reconnect.
|
|
10
10
|
*
|
|
@@ -144,7 +144,7 @@ export class CommandHandle {
|
|
|
144
144
|
return;
|
|
145
145
|
const firstResult = await this._stream.next();
|
|
146
146
|
if (firstResult.done) {
|
|
147
|
-
throw new
|
|
147
|
+
throw new LangSmithStreamEndedBeforeStartedError("Command stream ended before 'started' message");
|
|
148
148
|
}
|
|
149
149
|
const firstMsg = firstResult.value;
|
|
150
150
|
if (firstMsg.type !== "started") {
|
package/dist/sandbox/errors.cjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* properties for specific handling when needed.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.LangSmithSandboxServerReloadError = exports.LangSmithCommandTimeoutError = exports.LangSmithSandboxOperationError = exports.LangSmithSandboxNotReadyError = exports.LangSmithDataplaneNotConfiguredError = exports.LangSmithSandboxCreationError = exports.LangSmithResourceCreationError = exports.LangSmithQuotaExceededError = exports.LangSmithValidationError = exports.LangSmithResourceNameConflictError = exports.LangSmithResourceAlreadyExistsError = exports.LangSmithResourceInUseError = exports.LangSmithResourceTimeoutError = exports.LangSmithResourceNotFoundError = exports.LangSmithSandboxConnectionError = exports.LangSmithSandboxAuthenticationError = exports.LangSmithSandboxAPIError = exports.LangSmithSandboxError = void 0;
|
|
10
|
+
exports.LangSmithSandboxServerReloadError = exports.LangSmithStreamEndedBeforeStartedError = exports.LangSmithCommandTimeoutError = exports.LangSmithSandboxOperationError = exports.LangSmithSandboxNotReadyError = exports.LangSmithDataplaneNotConfiguredError = exports.LangSmithSandboxCreationError = exports.LangSmithResourceCreationError = exports.LangSmithQuotaExceededError = exports.LangSmithValidationError = exports.LangSmithResourceNameConflictError = exports.LangSmithResourceAlreadyExistsError = exports.LangSmithResourceInUseError = exports.LangSmithResourceTimeoutError = exports.LangSmithResourceNotFoundError = exports.LangSmithSandboxConnectionError = exports.LangSmithSandboxAuthenticationError = exports.LangSmithSandboxAPIError = exports.LangSmithSandboxError = void 0;
|
|
11
11
|
/**
|
|
12
12
|
* Base exception for sandbox client errors.
|
|
13
13
|
*/
|
|
@@ -357,6 +357,21 @@ class LangSmithCommandTimeoutError extends LangSmithSandboxOperationError {
|
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
359
|
exports.LangSmithCommandTimeoutError = LangSmithCommandTimeoutError;
|
|
360
|
+
/**
|
|
361
|
+
* Internal: a command WebSocket closed before the guest sent its 'started'
|
|
362
|
+
* frame (the proxied tunnel was torn down gracefully mid-handshake).
|
|
363
|
+
*
|
|
364
|
+
* Marks the idempotently-retryable early close, as distinct from a
|
|
365
|
+
* command-level failure. Subclasses the operation error so callers that catch
|
|
366
|
+
* the public type are unaffected.
|
|
367
|
+
*/
|
|
368
|
+
class LangSmithStreamEndedBeforeStartedError extends LangSmithSandboxOperationError {
|
|
369
|
+
constructor(message) {
|
|
370
|
+
super(message, "command");
|
|
371
|
+
this.name = "LangSmithStreamEndedBeforeStartedError";
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
exports.LangSmithStreamEndedBeforeStartedError = LangSmithStreamEndedBeforeStartedError;
|
|
360
375
|
/**
|
|
361
376
|
* Raised when the sandbox server is reloading (close code 1001).
|
|
362
377
|
*
|
package/dist/sandbox/errors.d.ts
CHANGED
|
@@ -154,6 +154,17 @@ export declare class LangSmithCommandTimeoutError extends LangSmithSandboxOperat
|
|
|
154
154
|
timeout?: number;
|
|
155
155
|
constructor(message: string, timeout?: number);
|
|
156
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Internal: a command WebSocket closed before the guest sent its 'started'
|
|
159
|
+
* frame (the proxied tunnel was torn down gracefully mid-handshake).
|
|
160
|
+
*
|
|
161
|
+
* Marks the idempotently-retryable early close, as distinct from a
|
|
162
|
+
* command-level failure. Subclasses the operation error so callers that catch
|
|
163
|
+
* the public type are unaffected.
|
|
164
|
+
*/
|
|
165
|
+
export declare class LangSmithStreamEndedBeforeStartedError extends LangSmithSandboxOperationError {
|
|
166
|
+
constructor(message: string);
|
|
167
|
+
}
|
|
157
168
|
/**
|
|
158
169
|
* Raised when the sandbox server is reloading (close code 1001).
|
|
159
170
|
*
|
package/dist/sandbox/errors.js
CHANGED
|
@@ -337,6 +337,20 @@ export class LangSmithCommandTimeoutError extends LangSmithSandboxOperationError
|
|
|
337
337
|
this.timeout = timeout;
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Internal: a command WebSocket closed before the guest sent its 'started'
|
|
342
|
+
* frame (the proxied tunnel was torn down gracefully mid-handshake).
|
|
343
|
+
*
|
|
344
|
+
* Marks the idempotently-retryable early close, as distinct from a
|
|
345
|
+
* command-level failure. Subclasses the operation error so callers that catch
|
|
346
|
+
* the public type are unaffected.
|
|
347
|
+
*/
|
|
348
|
+
export class LangSmithStreamEndedBeforeStartedError extends LangSmithSandboxOperationError {
|
|
349
|
+
constructor(message) {
|
|
350
|
+
super(message, "command");
|
|
351
|
+
this.name = "LangSmithStreamEndedBeforeStartedError";
|
|
352
|
+
}
|
|
353
|
+
}
|
|
340
354
|
/**
|
|
341
355
|
* Raised when the sandbox server is reloading (close code 1001).
|
|
342
356
|
*
|
package/dist/sandbox/sandbox.cjs
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.Sandbox = void 0;
|
|
7
|
+
const uuid_js_1 = require("../uuid.cjs");
|
|
7
8
|
const errors_js_1 = require("./errors.cjs");
|
|
8
9
|
const helpers_js_1 = require("./helpers.cjs");
|
|
9
10
|
const command_handle_js_1 = require("./command_handle.cjs");
|
|
@@ -229,26 +230,49 @@ class Sandbox {
|
|
|
229
230
|
const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, commandId, idleTimeout, killOnDisconnect, ttlSeconds, pty, } = options;
|
|
230
231
|
const dataplaneUrl = this.requireDataplaneUrl();
|
|
231
232
|
const clientHeaders = this._client.getDefaultHeaders();
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
233
|
+
// A client-supplied command_id makes execute idempotent: the daemon does
|
|
234
|
+
// get-or-create keyed on it, so if the tunnel closes before "started" we
|
|
235
|
+
// can re-issue the same id and reattach to the existing command instead of
|
|
236
|
+
// spawning a second one.
|
|
237
|
+
const execCommandId = commandId ?? (0, uuid_js_1.uuid7)();
|
|
238
|
+
let attempt = 0;
|
|
239
|
+
// eslint-disable-next-line no-constant-condition
|
|
240
|
+
while (true) {
|
|
241
|
+
const [stream, control] = await (0, ws_execute_js_1.runWsStream)(dataplaneUrl, this._client.getApiKey(), command, {
|
|
242
|
+
timeout,
|
|
243
|
+
env,
|
|
244
|
+
cwd,
|
|
245
|
+
shell,
|
|
246
|
+
commandId: execCommandId,
|
|
247
|
+
idleTimeout,
|
|
248
|
+
killOnDisconnect,
|
|
249
|
+
ttlSeconds,
|
|
250
|
+
pty,
|
|
251
|
+
...(Object.keys(clientHeaders).length > 0
|
|
252
|
+
? { headers: clientHeaders }
|
|
253
|
+
: {}),
|
|
254
|
+
});
|
|
255
|
+
const handle = new command_handle_js_1.CommandHandle(stream, control, this, {
|
|
256
|
+
onStdout,
|
|
257
|
+
onStderr,
|
|
258
|
+
});
|
|
259
|
+
try {
|
|
260
|
+
await handle._ensureStarted();
|
|
261
|
+
return handle;
|
|
262
|
+
}
|
|
263
|
+
catch (e) {
|
|
264
|
+
// Idempotent re-issue (same command_id) after an early close.
|
|
265
|
+
if (!(e instanceof errors_js_1.LangSmithStreamEndedBeforeStartedError)) {
|
|
266
|
+
throw e;
|
|
267
|
+
}
|
|
268
|
+
attempt++;
|
|
269
|
+
if (attempt > command_handle_js_1.CommandHandle.MAX_AUTO_RECONNECTS) {
|
|
270
|
+
throw e;
|
|
271
|
+
}
|
|
272
|
+
const delay = Math.min(command_handle_js_1.CommandHandle.BACKOFF_BASE * 2 ** (attempt - 1), command_handle_js_1.CommandHandle.BACKOFF_MAX);
|
|
273
|
+
await new Promise((r) => setTimeout(r, delay * 1000));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
252
276
|
}
|
|
253
277
|
/**
|
|
254
278
|
* Execute a command via HTTP POST (blocking).
|
package/dist/sandbox/sandbox.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sandbox class for interacting with a specific sandbox instance.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { uuid7 } from "../uuid.js";
|
|
5
|
+
import { LangSmithDataplaneNotConfiguredError, LangSmithStreamEndedBeforeStartedError, } from "./errors.js";
|
|
5
6
|
import { handleSandboxHttpError } from "./helpers.js";
|
|
6
7
|
import { CommandHandle } from "./command_handle.js";
|
|
7
8
|
import { reconnectWsStream, runWsStream } from "./ws_execute.js";
|
|
@@ -226,26 +227,49 @@ export class Sandbox {
|
|
|
226
227
|
const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, commandId, idleTimeout, killOnDisconnect, ttlSeconds, pty, } = options;
|
|
227
228
|
const dataplaneUrl = this.requireDataplaneUrl();
|
|
228
229
|
const clientHeaders = this._client.getDefaultHeaders();
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
230
|
+
// A client-supplied command_id makes execute idempotent: the daemon does
|
|
231
|
+
// get-or-create keyed on it, so if the tunnel closes before "started" we
|
|
232
|
+
// can re-issue the same id and reattach to the existing command instead of
|
|
233
|
+
// spawning a second one.
|
|
234
|
+
const execCommandId = commandId ?? uuid7();
|
|
235
|
+
let attempt = 0;
|
|
236
|
+
// eslint-disable-next-line no-constant-condition
|
|
237
|
+
while (true) {
|
|
238
|
+
const [stream, control] = await runWsStream(dataplaneUrl, this._client.getApiKey(), command, {
|
|
239
|
+
timeout,
|
|
240
|
+
env,
|
|
241
|
+
cwd,
|
|
242
|
+
shell,
|
|
243
|
+
commandId: execCommandId,
|
|
244
|
+
idleTimeout,
|
|
245
|
+
killOnDisconnect,
|
|
246
|
+
ttlSeconds,
|
|
247
|
+
pty,
|
|
248
|
+
...(Object.keys(clientHeaders).length > 0
|
|
249
|
+
? { headers: clientHeaders }
|
|
250
|
+
: {}),
|
|
251
|
+
});
|
|
252
|
+
const handle = new CommandHandle(stream, control, this, {
|
|
253
|
+
onStdout,
|
|
254
|
+
onStderr,
|
|
255
|
+
});
|
|
256
|
+
try {
|
|
257
|
+
await handle._ensureStarted();
|
|
258
|
+
return handle;
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
// Idempotent re-issue (same command_id) after an early close.
|
|
262
|
+
if (!(e instanceof LangSmithStreamEndedBeforeStartedError)) {
|
|
263
|
+
throw e;
|
|
264
|
+
}
|
|
265
|
+
attempt++;
|
|
266
|
+
if (attempt > CommandHandle.MAX_AUTO_RECONNECTS) {
|
|
267
|
+
throw e;
|
|
268
|
+
}
|
|
269
|
+
const delay = Math.min(CommandHandle.BACKOFF_BASE * 2 ** (attempt - 1), CommandHandle.BACKOFF_MAX);
|
|
270
|
+
await new Promise((r) => setTimeout(r, delay * 1000));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
249
273
|
}
|
|
250
274
|
/**
|
|
251
275
|
* Execute a command via HTTP POST (blocking).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.evaluatorLogFeedbackPromises = exports.testWrapperAsyncLocalStorageInstance = exports.DEFAULT_TEST_CLIENT = void 0;
|
|
4
4
|
exports.trackingEnabled = trackingEnabled;
|
|
5
5
|
exports._logTestFeedback = _logTestFeedback;
|
|
6
6
|
const node_async_hooks_1 = require("node:async_hooks");
|
|
@@ -19,7 +19,6 @@ function trackingEnabled(context) {
|
|
|
19
19
|
return (0, env_js_2.isEnvTracingEnabled)();
|
|
20
20
|
}
|
|
21
21
|
exports.evaluatorLogFeedbackPromises = new Set();
|
|
22
|
-
exports.syncExamplePromises = new Map();
|
|
23
22
|
function _logTestFeedback(params) {
|
|
24
23
|
const { exampleId, feedback, context, runTree, client, sourceRunId } = params;
|
|
25
24
|
if (trackingEnabled(context)) {
|
|
@@ -30,10 +29,18 @@ function _logTestFeedback(params) {
|
|
|
30
29
|
throw new Error("Could not log feedback to LangSmith: missing run information. Please contact us for help.");
|
|
31
30
|
}
|
|
32
31
|
exports.evaluatorLogFeedbackPromises.add((async () => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
if (context.project == null) {
|
|
33
|
+
throw new Error("Could not log feedback to LangSmith: missing project information. Please contact us for help.");
|
|
34
|
+
}
|
|
35
|
+
await context.syncExamplePromises?.get(exampleId);
|
|
36
|
+
await client?.logEvaluationFeedback({
|
|
37
|
+
evaluatorResponse: feedback,
|
|
38
|
+
run: runTree,
|
|
39
|
+
projectId: context.project.id,
|
|
40
|
+
sourceInfo: sourceRunId !== undefined
|
|
41
|
+
? { __run: { run_id: sourceRunId } }
|
|
42
|
+
: undefined,
|
|
43
|
+
});
|
|
37
44
|
})());
|
|
38
45
|
}
|
|
39
46
|
context.onFeedbackLogged?.(feedback);
|
|
@@ -20,11 +20,11 @@ export type TestWrapperAsyncLocalStorageData = {
|
|
|
20
20
|
suiteName: string;
|
|
21
21
|
testRootRunTree?: RunTree;
|
|
22
22
|
setupPromise?: Promise<void>;
|
|
23
|
+
syncExamplePromises?: Map<string, Promise<Example>>;
|
|
23
24
|
};
|
|
24
25
|
export declare const testWrapperAsyncLocalStorageInstance: AsyncLocalStorage<TestWrapperAsyncLocalStorageData>;
|
|
25
26
|
export declare function trackingEnabled(context: TestWrapperAsyncLocalStorageData): boolean;
|
|
26
27
|
export declare const evaluatorLogFeedbackPromises: Set<unknown>;
|
|
27
|
-
export declare const syncExamplePromises: Map<any, any>;
|
|
28
28
|
export declare function _logTestFeedback(params: {
|
|
29
29
|
exampleId?: string;
|
|
30
30
|
feedback: SimpleEvaluationResult;
|
|
@@ -14,7 +14,6 @@ export function trackingEnabled(context) {
|
|
|
14
14
|
return isEnvTracingEnabled();
|
|
15
15
|
}
|
|
16
16
|
export const evaluatorLogFeedbackPromises = new Set();
|
|
17
|
-
export const syncExamplePromises = new Map();
|
|
18
17
|
export function _logTestFeedback(params) {
|
|
19
18
|
const { exampleId, feedback, context, runTree, client, sourceRunId } = params;
|
|
20
19
|
if (trackingEnabled(context)) {
|
|
@@ -25,10 +24,18 @@ export function _logTestFeedback(params) {
|
|
|
25
24
|
throw new Error("Could not log feedback to LangSmith: missing run information. Please contact us for help.");
|
|
26
25
|
}
|
|
27
26
|
evaluatorLogFeedbackPromises.add((async () => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
if (context.project == null) {
|
|
28
|
+
throw new Error("Could not log feedback to LangSmith: missing project information. Please contact us for help.");
|
|
29
|
+
}
|
|
30
|
+
await context.syncExamplePromises?.get(exampleId);
|
|
31
|
+
await client?.logEvaluationFeedback({
|
|
32
|
+
evaluatorResponse: feedback,
|
|
33
|
+
run: runTree,
|
|
34
|
+
projectId: context.project.id,
|
|
35
|
+
sourceInfo: sourceRunId !== undefined
|
|
36
|
+
? { __run: { run_id: sourceRunId } }
|
|
37
|
+
: undefined,
|
|
38
|
+
});
|
|
32
39
|
})());
|
|
33
40
|
}
|
|
34
41
|
context.onFeedbackLogged?.(feedback);
|