langsmith 0.7.10 → 0.7.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -15
- package/dist/_openapi_client/client.cjs +0 -80
- package/dist/_openapi_client/client.d.ts +2 -32
- package/dist/_openapi_client/client.js +0 -80
- package/dist/_openapi_client/core/pagination.cjs +2 -2
- package/dist/_openapi_client/core/pagination.js +2 -2
- package/dist/_openapi_client/internal/utils/query.cjs +1 -1
- package/dist/_openapi_client/internal/utils/query.js +1 -1
- package/dist/_openapi_client/resources/datasets/datasets.d.ts +52 -4
- package/dist/_openapi_client/resources/index.cjs +1 -21
- package/dist/_openapi_client/resources/index.d.ts +1 -11
- package/dist/_openapi_client/resources/index.js +0 -10
- package/dist/_openapi_client/resources/runs/index.cjs +9 -0
- package/dist/_openapi_client/resources/runs/index.d.ts +2 -0
- package/dist/_openapi_client/resources/runs/index.js +4 -0
- package/dist/_openapi_client/resources/runs/runs.cjs +54 -41
- package/dist/_openapi_client/resources/runs/runs.d.ts +571 -313
- package/dist/_openapi_client/resources/runs/runs.js +54 -41
- package/dist/_openapi_client/resources/runs.cjs +19 -0
- package/dist/_openapi_client/resources/runs.d.ts +1 -0
- package/dist/_openapi_client/resources/runs.js +3 -0
- package/dist/anonymizer/index.cjs +142 -0
- package/dist/anonymizer/index.d.ts +45 -0
- package/dist/anonymizer/index.js +140 -0
- package/dist/client.cjs +29 -1
- package/dist/client.d.ts +6 -1
- package/dist/client.js +28 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/sandbox/client.cjs +5 -8
- package/dist/sandbox/client.js +5 -8
- package/dist/sandbox/index.cjs +2 -1
- package/dist/sandbox/index.d.ts +2 -2
- package/dist/sandbox/index.js +1 -1
- package/dist/sandbox/mounts.cjs +157 -18
- package/dist/sandbox/mounts.d.ts +10 -2
- package/dist/sandbox/mounts.js +155 -18
- package/dist/sandbox/proxy_config.cjs +19 -44
- package/dist/sandbox/proxy_config.d.ts +2 -4
- package/dist/sandbox/proxy_config.js +19 -43
- package/dist/sandbox/types.d.ts +56 -15
- package/dist/utils/constants.cjs +4 -0
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.js +1 -0
- package/package.json +5 -5
- package/dist/_openapi_client/resources/annotation-queues/annotation-queues.cjs +0 -138
- package/dist/_openapi_client/resources/annotation-queues/annotation-queues.d.ts +0 -367
- package/dist/_openapi_client/resources/annotation-queues/annotation-queues.js +0 -101
- package/dist/_openapi_client/resources/annotation-queues/runs.cjs +0 -46
- package/dist/_openapi_client/resources/annotation-queues/runs.d.ts +0 -128
- package/dist/_openapi_client/resources/annotation-queues/runs.js +0 -42
- package/dist/_openapi_client/resources/commits.cjs +0 -44
- package/dist/_openapi_client/resources/commits.d.ts +0 -204
- package/dist/_openapi_client/resources/commits.js +0 -40
- package/dist/_openapi_client/resources/evaluators.cjs +0 -15
- package/dist/_openapi_client/resources/evaluators.d.ts +0 -125
- package/dist/_openapi_client/resources/evaluators.js +0 -11
- package/dist/_openapi_client/resources/examples/bulk.cjs +0 -24
- package/dist/_openapi_client/resources/examples/bulk.d.ts +0 -78
- package/dist/_openapi_client/resources/examples/bulk.js +0 -20
- package/dist/_openapi_client/resources/examples/examples.cjs +0 -124
- package/dist/_openapi_client/resources/examples/examples.d.ts +0 -182
- package/dist/_openapi_client/resources/examples/examples.js +0 -87
- package/dist/_openapi_client/resources/examples/validate.cjs +0 -21
- package/dist/_openapi_client/resources/examples/validate.d.ts +0 -38
- package/dist/_openapi_client/resources/examples/validate.js +0 -17
- package/dist/_openapi_client/resources/feedback/configs.cjs +0 -24
- package/dist/_openapi_client/resources/feedback/configs.d.ts +0 -18
- package/dist/_openapi_client/resources/feedback/configs.js +0 -20
- package/dist/_openapi_client/resources/feedback/feedback.cjs +0 -98
- package/dist/_openapi_client/resources/feedback/feedback.d.ts +0 -275
- package/dist/_openapi_client/resources/feedback/feedback.js +0 -61
- package/dist/_openapi_client/resources/feedback/tokens.cjs +0 -35
- package/dist/_openapi_client/resources/feedback/tokens.d.ts +0 -130
- package/dist/_openapi_client/resources/feedback/tokens.js +0 -31
- package/dist/_openapi_client/resources/public/datasets.cjs +0 -47
- package/dist/_openapi_client/resources/public/datasets.d.ts +0 -152
- package/dist/_openapi_client/resources/public/datasets.js +0 -43
- package/dist/_openapi_client/resources/public/public.cjs +0 -62
- package/dist/_openapi_client/resources/public/public.d.ts +0 -32
- package/dist/_openapi_client/resources/public/public.js +0 -25
- package/dist/_openapi_client/resources/repos/directories.cjs +0 -40
- package/dist/_openapi_client/resources/repos/directories.d.ts +0 -72
- package/dist/_openapi_client/resources/repos/directories.js +0 -36
- package/dist/_openapi_client/resources/repos/repos.cjs +0 -93
- package/dist/_openapi_client/resources/repos/repos.d.ts +0 -188
- package/dist/_openapi_client/resources/repos/repos.js +0 -56
- package/dist/_openapi_client/resources/sandboxes/boxes.cjs +0 -86
- package/dist/_openapi_client/resources/sandboxes/boxes.d.ts +0 -1121
- package/dist/_openapi_client/resources/sandboxes/boxes.js +0 -82
- package/dist/_openapi_client/resources/sandboxes/sandboxes.cjs +0 -63
- package/dist/_openapi_client/resources/sandboxes/sandboxes.d.ts +0 -13
- package/dist/_openapi_client/resources/sandboxes/sandboxes.js +0 -26
- package/dist/_openapi_client/resources/sandboxes/snapshots.cjs +0 -39
- package/dist/_openapi_client/resources/sandboxes/snapshots.d.ts +0 -130
- package/dist/_openapi_client/resources/sandboxes/snapshots.js +0 -35
- package/dist/_openapi_client/resources/settings.cjs +0 -15
- package/dist/_openapi_client/resources/settings.d.ts +0 -18
- package/dist/_openapi_client/resources/settings.js +0 -11
- package/dist/_openapi_client/resources/workspaces.cjs +0 -35
- package/dist/_openapi_client/resources/workspaces.d.ts +0 -84
- package/dist/_openapi_client/resources/workspaces.js +0 -31
package/dist/sandbox/mounts.js
CHANGED
|
@@ -1,10 +1,67 @@
|
|
|
1
|
-
import { proxyConfig } from "./proxy_config.js";
|
|
2
1
|
function requireNonEmptyString(value, field) {
|
|
3
2
|
if (typeof value !== "string" || value.trim() === "") {
|
|
4
3
|
throw new Error(`${field} must be a non-empty string`);
|
|
5
4
|
}
|
|
6
5
|
return value.trim();
|
|
7
6
|
}
|
|
7
|
+
function copyMountSecret(secret, field) {
|
|
8
|
+
if (secret === null || typeof secret !== "object" || Array.isArray(secret)) {
|
|
9
|
+
throw new Error(`${field} must be a sandbox secret`);
|
|
10
|
+
}
|
|
11
|
+
const candidate = secret;
|
|
12
|
+
if (candidate.type !== "workspace_secret" && candidate.type !== "opaque") {
|
|
13
|
+
throw new Error(`${field} must use workspace_secret or opaque`);
|
|
14
|
+
}
|
|
15
|
+
if (typeof candidate.value !== "string" || candidate.value.trim() === "") {
|
|
16
|
+
throw new Error(`${field}.value must be a non-empty string`);
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
type: candidate.type,
|
|
20
|
+
value: candidate.value,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function requireGitRemoteUrl(remoteUrl) {
|
|
24
|
+
if (typeof remoteUrl !== "string" || remoteUrl === "") {
|
|
25
|
+
throw new Error("remoteUrl must be a non-empty string");
|
|
26
|
+
}
|
|
27
|
+
if (remoteUrl.trim() !== remoteUrl ||
|
|
28
|
+
/\s/u.test(remoteUrl) ||
|
|
29
|
+
remoteUrl.includes(String.fromCharCode(0))) {
|
|
30
|
+
throw new Error("remoteUrl must not contain whitespace or NUL bytes");
|
|
31
|
+
}
|
|
32
|
+
let parsed;
|
|
33
|
+
try {
|
|
34
|
+
parsed = new URL(remoteUrl);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw new Error("remoteUrl must be an absolute HTTPS URL");
|
|
38
|
+
}
|
|
39
|
+
if (parsed.protocol !== "https:" || parsed.host === "") {
|
|
40
|
+
throw new Error("remoteUrl must be an absolute HTTPS URL");
|
|
41
|
+
}
|
|
42
|
+
if (parsed.username !== "" || parsed.password !== "") {
|
|
43
|
+
throw new Error("remoteUrl must not include embedded credentials");
|
|
44
|
+
}
|
|
45
|
+
if (parsed.pathname === "" || parsed.pathname === "/") {
|
|
46
|
+
throw new Error("remoteUrl must include a repository path");
|
|
47
|
+
}
|
|
48
|
+
if (parsed.search !== "" || parsed.hash !== "") {
|
|
49
|
+
throw new Error("remoteUrl must not include query or fragment");
|
|
50
|
+
}
|
|
51
|
+
return remoteUrl;
|
|
52
|
+
}
|
|
53
|
+
function copyGitRef(ref) {
|
|
54
|
+
if (ref === null || typeof ref !== "object" || Array.isArray(ref)) {
|
|
55
|
+
throw new Error("ref must be an object");
|
|
56
|
+
}
|
|
57
|
+
if (ref.type !== "branch" && ref.type !== "tag") {
|
|
58
|
+
throw new Error("ref.type must be branch or tag");
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
type: ref.type,
|
|
62
|
+
name: requireNonEmptyString(ref.name, "ref.name"),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
8
65
|
export function s3Mount({ id, mountPath, bucket, region = "us-east-1", prefix, endpointUrl = "https://s3.amazonaws.com", pathStyle = false, readOnly, cache, }) {
|
|
9
66
|
const mount = {
|
|
10
67
|
id: requireNonEmptyString(id, "id"),
|
|
@@ -28,6 +85,26 @@ export function s3Mount({ id, mountPath, bucket, region = "us-east-1", prefix, e
|
|
|
28
85
|
}
|
|
29
86
|
return mount;
|
|
30
87
|
}
|
|
88
|
+
export function gitMount({ id, mountPath, remoteUrl, ref, refreshIntervalSeconds, }) {
|
|
89
|
+
const mount = {
|
|
90
|
+
id: requireNonEmptyString(id, "id"),
|
|
91
|
+
type: "git",
|
|
92
|
+
mount_path: requireNonEmptyString(mountPath, "mountPath"),
|
|
93
|
+
git: {
|
|
94
|
+
remote_url: requireGitRemoteUrl(remoteUrl),
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
if (ref !== undefined) {
|
|
98
|
+
mount.git.ref = copyGitRef(ref);
|
|
99
|
+
}
|
|
100
|
+
if (refreshIntervalSeconds !== undefined) {
|
|
101
|
+
if (refreshIntervalSeconds < 1) {
|
|
102
|
+
throw new Error("refreshIntervalSeconds must be at least 1");
|
|
103
|
+
}
|
|
104
|
+
mount.git.refresh_interval_seconds = refreshIntervalSeconds;
|
|
105
|
+
}
|
|
106
|
+
return mount;
|
|
107
|
+
}
|
|
31
108
|
export function gcsMount({ id, mountPath, bucket, prefix, readOnly, cache, }) {
|
|
32
109
|
const mount = {
|
|
33
110
|
id: requireNonEmptyString(id, "id"),
|
|
@@ -56,35 +133,80 @@ function normalizeMounts(mounts) {
|
|
|
56
133
|
if (mount === null || typeof mount !== "object" || Array.isArray(mount)) {
|
|
57
134
|
throw new Error("mounts must be a non-empty array of mount objects");
|
|
58
135
|
}
|
|
59
|
-
if (mount.type !== "s3" && mount.type !== "gcs") {
|
|
60
|
-
throw new Error("mountConfig only supports s3 and
|
|
136
|
+
if (mount.type !== "s3" && mount.type !== "gcs" && mount.type !== "git") {
|
|
137
|
+
throw new Error("mountConfig only supports s3, gcs, and git mounts");
|
|
61
138
|
}
|
|
139
|
+
rejectProviderCredentialsInMount(mount);
|
|
62
140
|
return mount;
|
|
63
141
|
});
|
|
64
142
|
}
|
|
65
|
-
|
|
143
|
+
const FORBIDDEN_MOUNT_CREDENTIAL_FIELDS = new Set([
|
|
144
|
+
"access_key_id",
|
|
145
|
+
"secret_access_key",
|
|
146
|
+
"session_token",
|
|
147
|
+
"service_account_json",
|
|
148
|
+
"access_token",
|
|
149
|
+
"refresh_token",
|
|
150
|
+
"credentials",
|
|
151
|
+
"credential",
|
|
152
|
+
]);
|
|
153
|
+
function rejectProviderCredentialsInMount(value) {
|
|
154
|
+
if (Array.isArray(value)) {
|
|
155
|
+
for (const child of value) {
|
|
156
|
+
rejectProviderCredentialsInMount(child);
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (value !== null && typeof value === "object") {
|
|
161
|
+
for (const [key, child] of Object.entries(value)) {
|
|
162
|
+
if (FORBIDDEN_MOUNT_CREDENTIAL_FIELDS.has(key)) {
|
|
163
|
+
throw new Error("provider credentials must be supplied in mountConfig.auth, not individual mount specs");
|
|
164
|
+
}
|
|
165
|
+
rejectProviderCredentialsInMount(child);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function normalizeMountAuth(auth) {
|
|
66
170
|
if (!Array.isArray(auth)) {
|
|
67
|
-
throw new Error("auth must be an array of provider auth
|
|
171
|
+
throw new Error("auth must be an array of provider auth blocks");
|
|
68
172
|
}
|
|
69
173
|
const byProvider = {};
|
|
70
|
-
for (const
|
|
71
|
-
if (
|
|
72
|
-
throw new Error("auth must be an array of provider auth
|
|
174
|
+
for (const block of auth) {
|
|
175
|
+
if (block === null || typeof block !== "object" || Array.isArray(block)) {
|
|
176
|
+
throw new Error("auth must be an array of provider auth blocks");
|
|
73
177
|
}
|
|
74
|
-
const provider =
|
|
178
|
+
const provider = block.type;
|
|
75
179
|
if (provider !== "aws" && provider !== "gcp") {
|
|
76
|
-
throw new Error("mountConfig auth only supports aws and gcp
|
|
180
|
+
throw new Error("mountConfig auth only supports aws and gcp blocks");
|
|
77
181
|
}
|
|
78
182
|
if (byProvider[provider] !== undefined) {
|
|
79
183
|
throw new Error(`duplicate ${provider} auth rule in mountConfig`);
|
|
80
184
|
}
|
|
81
|
-
|
|
185
|
+
if (provider === "aws") {
|
|
186
|
+
const aws = block.aws;
|
|
187
|
+
if (aws === undefined) {
|
|
188
|
+
throw new Error("aws mount auth must include an aws block");
|
|
189
|
+
}
|
|
190
|
+
byProvider.aws = {
|
|
191
|
+
access_key_id: copyMountSecret(aws.access_key_id, "accessKeyId"),
|
|
192
|
+
secret_access_key: copyMountSecret(aws.secret_access_key, "secretAccessKey"),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
const gcp = block.gcp;
|
|
197
|
+
if (gcp === undefined) {
|
|
198
|
+
throw new Error("gcp mount auth must include a gcp block");
|
|
199
|
+
}
|
|
200
|
+
byProvider.gcp = {
|
|
201
|
+
service_account_json: copyMountSecret(gcp.service_account_json, "serviceAccountJson"),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
82
204
|
}
|
|
83
205
|
return byProvider;
|
|
84
206
|
}
|
|
85
|
-
export function mountConfig({ auth, mounts, }) {
|
|
207
|
+
export function mountConfig({ auth = [], mounts, }) {
|
|
86
208
|
const normalizedMounts = normalizeMounts(mounts);
|
|
87
|
-
const authByProvider =
|
|
209
|
+
const authByProvider = normalizeMountAuth(auth);
|
|
88
210
|
const mountProviders = new Set(normalizedMounts.map((mount) => mount.type));
|
|
89
211
|
if (mountProviders.has("s3") && authByProvider.aws === undefined) {
|
|
90
212
|
throw new Error("s3 mounts require aws auth in mountConfig");
|
|
@@ -99,11 +221,26 @@ export function mountConfig({ auth, mounts, }) {
|
|
|
99
221
|
throw new Error("gcp auth requires at least one gcs mount in mountConfig");
|
|
100
222
|
}
|
|
101
223
|
return {
|
|
224
|
+
auth: authByProvider,
|
|
102
225
|
mounts: normalizedMounts,
|
|
103
|
-
proxyConfig: proxyConfig({
|
|
104
|
-
rules: ["aws", "gcp"]
|
|
105
|
-
.map((provider) => authByProvider[provider])
|
|
106
|
-
.filter((rule) => rule !== undefined),
|
|
107
|
-
}),
|
|
108
226
|
};
|
|
109
227
|
}
|
|
228
|
+
export function validateMountConfigProxyConfig(mountConfig, proxyConfig) {
|
|
229
|
+
if (proxyConfig === undefined) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const rules = proxyConfig.rules ?? [];
|
|
233
|
+
if (!Array.isArray(rules)) {
|
|
234
|
+
throw new Error("proxyConfig rules must be an array");
|
|
235
|
+
}
|
|
236
|
+
for (const rule of rules) {
|
|
237
|
+
if (rule === null || typeof rule !== "object" || Array.isArray(rule)) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const ruleType = rule.type;
|
|
241
|
+
if ((ruleType === "aws" || ruleType === "gcp") &&
|
|
242
|
+
mountConfig.auth[ruleType] !== undefined) {
|
|
243
|
+
throw new Error(`${ruleType} auth cannot be provided in both mountConfig and proxyConfig`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
@@ -3,14 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.workspaceSecret = workspaceSecret;
|
|
4
4
|
exports.opaqueSecret = opaqueSecret;
|
|
5
5
|
exports.proxyConfig = proxyConfig;
|
|
6
|
-
exports.mergeProxyConfigs = mergeProxyConfigs;
|
|
7
6
|
exports.awsAuth = awsAuth;
|
|
8
7
|
exports.gcpAuth = gcpAuth;
|
|
9
|
-
const DEFAULT_GCP_AUTH_MATCH_HOSTS = [
|
|
10
|
-
"storage.googleapis.com",
|
|
11
|
-
"www.googleapis.com",
|
|
12
|
-
];
|
|
13
|
-
const PROVIDER_RULE_TYPES = new Set(["aws", "gcp"]);
|
|
14
8
|
function requireNonEmptyString(value, field) {
|
|
15
9
|
if (typeof value !== "string" || value.trim() === "") {
|
|
16
10
|
throw new Error(`${field} must be a non-empty string`);
|
|
@@ -34,9 +28,20 @@ function requireProxyRules(rules) {
|
|
|
34
28
|
if (rule === null || typeof rule !== "object" || Array.isArray(rule)) {
|
|
35
29
|
throw new Error("rules must be an array of proxy rule objects");
|
|
36
30
|
}
|
|
31
|
+
validateProxyProviderRule(rule);
|
|
37
32
|
return rule;
|
|
38
33
|
});
|
|
39
34
|
}
|
|
35
|
+
function validateProxyProviderRule(rule) {
|
|
36
|
+
if (rule.type !== "gcp") {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const gcp = rule.gcp;
|
|
40
|
+
if (gcp === undefined || gcp.scopes === undefined) {
|
|
41
|
+
throw new Error("gcp proxy auth rules require scopes");
|
|
42
|
+
}
|
|
43
|
+
requireNonEmptyStringArray(gcp.scopes, "scopes");
|
|
44
|
+
}
|
|
40
45
|
/** Reference a LangSmith workspace secret in a sandbox proxy configuration. */
|
|
41
46
|
function workspaceSecret(name) {
|
|
42
47
|
const normalized = requireNonEmptyString(name, "name");
|
|
@@ -73,38 +78,6 @@ function proxyConfig({ rules, noProxy, accessControl, } = {}) {
|
|
|
73
78
|
}
|
|
74
79
|
return config;
|
|
75
80
|
}
|
|
76
|
-
function providerRuleTypes(config) {
|
|
77
|
-
const providers = new Set();
|
|
78
|
-
for (const rule of config.rules ?? []) {
|
|
79
|
-
if (rule === null || typeof rule !== "object" || Array.isArray(rule)) {
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
const ruleType = rule.type;
|
|
83
|
-
if (typeof ruleType === "string" && PROVIDER_RULE_TYPES.has(ruleType)) {
|
|
84
|
-
providers.add(ruleType);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return providers;
|
|
88
|
-
}
|
|
89
|
-
function mergeProxyConfigs(generatedConfig, explicitConfig) {
|
|
90
|
-
if (generatedConfig === undefined) {
|
|
91
|
-
return explicitConfig;
|
|
92
|
-
}
|
|
93
|
-
if (explicitConfig === undefined) {
|
|
94
|
-
return generatedConfig;
|
|
95
|
-
}
|
|
96
|
-
const generatedProviders = providerRuleTypes(generatedConfig);
|
|
97
|
-
for (const provider of providerRuleTypes(explicitConfig)) {
|
|
98
|
-
if (generatedProviders.has(provider)) {
|
|
99
|
-
throw new Error(`${provider} auth cannot be provided in both mountConfig and proxyConfig`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
...generatedConfig,
|
|
104
|
-
...explicitConfig,
|
|
105
|
-
rules: [...(generatedConfig.rules ?? []), ...(explicitConfig.rules ?? [])],
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
81
|
/** Build a sandbox proxy rule that signs AWS HTTPS requests with SigV4. */
|
|
109
82
|
function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled = true, }) {
|
|
110
83
|
return {
|
|
@@ -118,15 +91,17 @@ function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled = true, }
|
|
|
118
91
|
};
|
|
119
92
|
}
|
|
120
93
|
/** Build a sandbox proxy rule that injects GCP OAuth bearer auth. */
|
|
121
|
-
function gcpAuth({ serviceAccountJson, scopes,
|
|
94
|
+
function gcpAuth({ serviceAccountJson, scopes, name = "gcp", enabled = true, }) {
|
|
95
|
+
const gcp = {
|
|
96
|
+
service_account_json: serviceAccountJson,
|
|
97
|
+
};
|
|
98
|
+
if (scopes !== undefined) {
|
|
99
|
+
gcp.scopes = requireNonEmptyStringArray(scopes, "scopes");
|
|
100
|
+
}
|
|
122
101
|
return {
|
|
123
102
|
name: requireNonEmptyString(name, "name"),
|
|
124
103
|
type: "gcp",
|
|
125
104
|
enabled,
|
|
126
|
-
|
|
127
|
-
gcp: {
|
|
128
|
-
service_account_json: serviceAccountJson,
|
|
129
|
-
scopes: requireNonEmptyStringArray(scopes, "scopes"),
|
|
130
|
-
},
|
|
105
|
+
gcp,
|
|
131
106
|
};
|
|
132
107
|
}
|
|
@@ -9,7 +9,6 @@ export declare function proxyConfig({ rules, noProxy, accessControl, }?: {
|
|
|
9
9
|
noProxy?: string[];
|
|
10
10
|
accessControl?: SandboxAccessControl;
|
|
11
11
|
}): SandboxProxyConfig;
|
|
12
|
-
export declare function mergeProxyConfigs(generatedConfig: SandboxProxyConfig | undefined, explicitConfig: SandboxProxyConfig | undefined): SandboxProxyConfig | undefined;
|
|
13
12
|
/** Build a sandbox proxy rule that signs AWS HTTPS requests with SigV4. */
|
|
14
13
|
export declare function awsAuth({ accessKeyId, secretAccessKey, name, enabled, }: {
|
|
15
14
|
accessKeyId: SandboxProxySecret;
|
|
@@ -18,10 +17,9 @@ export declare function awsAuth({ accessKeyId, secretAccessKey, name, enabled, }
|
|
|
18
17
|
enabled?: boolean;
|
|
19
18
|
}): SandboxAwsAuthRule;
|
|
20
19
|
/** Build a sandbox proxy rule that injects GCP OAuth bearer auth. */
|
|
21
|
-
export declare function gcpAuth({ serviceAccountJson, scopes,
|
|
20
|
+
export declare function gcpAuth({ serviceAccountJson, scopes, name, enabled, }: {
|
|
22
21
|
serviceAccountJson: SandboxProxySecret;
|
|
23
|
-
scopes
|
|
24
|
-
matchHosts?: string[];
|
|
22
|
+
scopes?: string[];
|
|
25
23
|
name?: string;
|
|
26
24
|
enabled?: boolean;
|
|
27
25
|
}): SandboxGcpAuthRule;
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
const DEFAULT_GCP_AUTH_MATCH_HOSTS = [
|
|
2
|
-
"storage.googleapis.com",
|
|
3
|
-
"www.googleapis.com",
|
|
4
|
-
];
|
|
5
|
-
const PROVIDER_RULE_TYPES = new Set(["aws", "gcp"]);
|
|
6
1
|
function requireNonEmptyString(value, field) {
|
|
7
2
|
if (typeof value !== "string" || value.trim() === "") {
|
|
8
3
|
throw new Error(`${field} must be a non-empty string`);
|
|
@@ -26,9 +21,20 @@ function requireProxyRules(rules) {
|
|
|
26
21
|
if (rule === null || typeof rule !== "object" || Array.isArray(rule)) {
|
|
27
22
|
throw new Error("rules must be an array of proxy rule objects");
|
|
28
23
|
}
|
|
24
|
+
validateProxyProviderRule(rule);
|
|
29
25
|
return rule;
|
|
30
26
|
});
|
|
31
27
|
}
|
|
28
|
+
function validateProxyProviderRule(rule) {
|
|
29
|
+
if (rule.type !== "gcp") {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const gcp = rule.gcp;
|
|
33
|
+
if (gcp === undefined || gcp.scopes === undefined) {
|
|
34
|
+
throw new Error("gcp proxy auth rules require scopes");
|
|
35
|
+
}
|
|
36
|
+
requireNonEmptyStringArray(gcp.scopes, "scopes");
|
|
37
|
+
}
|
|
32
38
|
/** Reference a LangSmith workspace secret in a sandbox proxy configuration. */
|
|
33
39
|
export function workspaceSecret(name) {
|
|
34
40
|
const normalized = requireNonEmptyString(name, "name");
|
|
@@ -65,38 +71,6 @@ export function proxyConfig({ rules, noProxy, accessControl, } = {}) {
|
|
|
65
71
|
}
|
|
66
72
|
return config;
|
|
67
73
|
}
|
|
68
|
-
function providerRuleTypes(config) {
|
|
69
|
-
const providers = new Set();
|
|
70
|
-
for (const rule of config.rules ?? []) {
|
|
71
|
-
if (rule === null || typeof rule !== "object" || Array.isArray(rule)) {
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
const ruleType = rule.type;
|
|
75
|
-
if (typeof ruleType === "string" && PROVIDER_RULE_TYPES.has(ruleType)) {
|
|
76
|
-
providers.add(ruleType);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return providers;
|
|
80
|
-
}
|
|
81
|
-
export function mergeProxyConfigs(generatedConfig, explicitConfig) {
|
|
82
|
-
if (generatedConfig === undefined) {
|
|
83
|
-
return explicitConfig;
|
|
84
|
-
}
|
|
85
|
-
if (explicitConfig === undefined) {
|
|
86
|
-
return generatedConfig;
|
|
87
|
-
}
|
|
88
|
-
const generatedProviders = providerRuleTypes(generatedConfig);
|
|
89
|
-
for (const provider of providerRuleTypes(explicitConfig)) {
|
|
90
|
-
if (generatedProviders.has(provider)) {
|
|
91
|
-
throw new Error(`${provider} auth cannot be provided in both mountConfig and proxyConfig`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
...generatedConfig,
|
|
96
|
-
...explicitConfig,
|
|
97
|
-
rules: [...(generatedConfig.rules ?? []), ...(explicitConfig.rules ?? [])],
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
74
|
/** Build a sandbox proxy rule that signs AWS HTTPS requests with SigV4. */
|
|
101
75
|
export function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled = true, }) {
|
|
102
76
|
return {
|
|
@@ -110,15 +84,17 @@ export function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled =
|
|
|
110
84
|
};
|
|
111
85
|
}
|
|
112
86
|
/** Build a sandbox proxy rule that injects GCP OAuth bearer auth. */
|
|
113
|
-
export function gcpAuth({ serviceAccountJson, scopes,
|
|
87
|
+
export function gcpAuth({ serviceAccountJson, scopes, name = "gcp", enabled = true, }) {
|
|
88
|
+
const gcp = {
|
|
89
|
+
service_account_json: serviceAccountJson,
|
|
90
|
+
};
|
|
91
|
+
if (scopes !== undefined) {
|
|
92
|
+
gcp.scopes = requireNonEmptyStringArray(scopes, "scopes");
|
|
93
|
+
}
|
|
114
94
|
return {
|
|
115
95
|
name: requireNonEmptyString(name, "name"),
|
|
116
96
|
type: "gcp",
|
|
117
97
|
enabled,
|
|
118
|
-
|
|
119
|
-
gcp: {
|
|
120
|
-
service_account_json: serviceAccountJson,
|
|
121
|
-
scopes: requireNonEmptyStringArray(scopes, "scopes"),
|
|
122
|
-
},
|
|
98
|
+
gcp,
|
|
123
99
|
};
|
|
124
100
|
}
|
package/dist/sandbox/types.d.ts
CHANGED
|
@@ -280,16 +280,14 @@ export interface SandboxAwsAuthRule {
|
|
|
280
280
|
export interface SandboxGcpAuthRule {
|
|
281
281
|
/** Rule name. */
|
|
282
282
|
name: string;
|
|
283
|
-
/** GCP auth rules
|
|
283
|
+
/** GCP auth rules use the sandbox proxy's built-in Google API host matcher. */
|
|
284
284
|
type: "gcp";
|
|
285
285
|
/** Whether the rule is enabled. */
|
|
286
286
|
enabled?: boolean;
|
|
287
|
-
/** Google API hosts covered by this rule, such as storage.googleapis.com. */
|
|
288
|
-
match_hosts: string[];
|
|
289
287
|
/** GCP service-account credential and OAuth scopes. */
|
|
290
288
|
gcp: {
|
|
291
289
|
service_account_json: SandboxProxySecret;
|
|
292
|
-
scopes
|
|
290
|
+
scopes?: string[];
|
|
293
291
|
};
|
|
294
292
|
}
|
|
295
293
|
/** Proxy rule accepted by the sandbox proxy config. */
|
|
@@ -307,14 +305,14 @@ export interface SandboxProxyConfig {
|
|
|
307
305
|
/** Allow/deny list enforced at the proxy sidecar. */
|
|
308
306
|
access_control?: SandboxAccessControl;
|
|
309
307
|
}
|
|
310
|
-
/** Optional per-mount cache configuration supported by
|
|
308
|
+
/** Optional per-mount cache configuration supported by bucket mounts. */
|
|
311
309
|
export interface MountCacheConfig {
|
|
312
310
|
/** Maximum VFS cache size in bytes. */
|
|
313
311
|
max_size_bytes?: number;
|
|
314
312
|
/** Seconds rclone waits before writing cached changes back. */
|
|
315
313
|
writeback_seconds?: number;
|
|
316
314
|
}
|
|
317
|
-
interface
|
|
315
|
+
interface SandboxBucketMountBase {
|
|
318
316
|
/** Stable mount identifier. */
|
|
319
317
|
id: string;
|
|
320
318
|
/** Absolute path inside the sandbox where the mount appears. */
|
|
@@ -341,7 +339,7 @@ export interface S3MountConfig {
|
|
|
341
339
|
path_style?: boolean;
|
|
342
340
|
}
|
|
343
341
|
/** S3-backed sandbox mount specification. */
|
|
344
|
-
export interface S3MountSpec extends
|
|
342
|
+
export interface S3MountSpec extends SandboxBucketMountBase {
|
|
345
343
|
/** Mount type. */
|
|
346
344
|
type: "s3";
|
|
347
345
|
/** S3 mount configuration. */
|
|
@@ -355,20 +353,63 @@ export interface GCSMountConfig {
|
|
|
355
353
|
prefix?: string;
|
|
356
354
|
}
|
|
357
355
|
/** GCS-backed sandbox mount specification. */
|
|
358
|
-
export interface GCSMountSpec extends
|
|
356
|
+
export interface GCSMountSpec extends SandboxBucketMountBase {
|
|
359
357
|
/** Mount type. */
|
|
360
358
|
type: "gcs";
|
|
361
359
|
/** GCS mount configuration. */
|
|
362
360
|
gcs: GCSMountConfig;
|
|
363
361
|
}
|
|
362
|
+
/** Git ref selected for a sandbox mount. */
|
|
363
|
+
export interface GitMountRefSpec {
|
|
364
|
+
/** Git ref type. */
|
|
365
|
+
type: "branch" | "tag";
|
|
366
|
+
/** Branch or tag name. */
|
|
367
|
+
name: string;
|
|
368
|
+
}
|
|
369
|
+
/** Git configuration for a sandbox mount. */
|
|
370
|
+
export interface GitMountConfig {
|
|
371
|
+
/** Public HTTPS Git remote URL. */
|
|
372
|
+
remote_url: string;
|
|
373
|
+
/** Optional branch or tag to mount. */
|
|
374
|
+
ref?: GitMountRefSpec;
|
|
375
|
+
/** Optional refresh interval for polling the remote. */
|
|
376
|
+
refresh_interval_seconds?: number;
|
|
377
|
+
}
|
|
378
|
+
/** Git-backed sandbox mount specification. */
|
|
379
|
+
export interface GitMountSpec {
|
|
380
|
+
/** Stable mount identifier. */
|
|
381
|
+
id: string;
|
|
382
|
+
/** Mount type. */
|
|
383
|
+
type: "git";
|
|
384
|
+
/** Absolute path inside the sandbox where the mount appears. */
|
|
385
|
+
mount_path: string;
|
|
386
|
+
/** Git mount configuration. */
|
|
387
|
+
git: GitMountConfig;
|
|
388
|
+
}
|
|
364
389
|
/** Sandbox mount specification. */
|
|
365
|
-
export type SandboxMount = S3MountSpec | GCSMountSpec;
|
|
366
|
-
/**
|
|
390
|
+
export type SandboxMount = S3MountSpec | GCSMountSpec | GitMountSpec;
|
|
391
|
+
/** AWS credentials used by the backend to authenticate S3 mounts. */
|
|
392
|
+
export interface SandboxAwsMountAuthConfig {
|
|
393
|
+
access_key_id: SandboxProxySecret;
|
|
394
|
+
secret_access_key: SandboxProxySecret;
|
|
395
|
+
}
|
|
396
|
+
/** GCP credentials used by the backend to authenticate GCS mounts. */
|
|
397
|
+
export interface SandboxGcpMountAuthConfig {
|
|
398
|
+
service_account_json: SandboxProxySecret;
|
|
399
|
+
}
|
|
400
|
+
/** Provider auth blocks for sandbox mounts. */
|
|
401
|
+
export interface SandboxMountAuthConfig {
|
|
402
|
+
aws?: SandboxAwsMountAuthConfig;
|
|
403
|
+
gcp?: SandboxGcpMountAuthConfig;
|
|
404
|
+
}
|
|
405
|
+
/** Provider auth helper output accepted by mountConfig. */
|
|
406
|
+
export type SandboxMountAuth = SandboxAwsAuthRule | SandboxGcpAuthRule;
|
|
407
|
+
/** Public mount config sent to the sandbox API. */
|
|
367
408
|
export interface SandboxMountConfig {
|
|
409
|
+
/** Provider auth blocks for bucket-backed mounts. */
|
|
410
|
+
auth: SandboxMountAuthConfig;
|
|
368
411
|
/** Mounts attached to the sandbox. */
|
|
369
412
|
mounts: SandboxMount[];
|
|
370
|
-
/** Proxy auth config required by the mounts. */
|
|
371
|
-
proxyConfig: SandboxProxyConfig;
|
|
372
413
|
}
|
|
373
414
|
/**
|
|
374
415
|
* Options for creating a sandbox.
|
|
@@ -417,9 +458,9 @@ export interface CreateSandboxOptions {
|
|
|
417
458
|
/** Root filesystem capacity in bytes. */
|
|
418
459
|
fsCapacityBytes?: number;
|
|
419
460
|
/**
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
461
|
+
* Mount configuration forwarded to the server as `mount_config`. The backend
|
|
462
|
+
* expands mount auth into runtime proxy rules. Explicit AWS/GCP proxy rules
|
|
463
|
+
* in `proxyConfig` conflict with mount auth for the same provider.
|
|
423
464
|
*/
|
|
424
465
|
mountConfig?: SandboxMountConfig;
|
|
425
466
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const _MIN_BACKEND_VERSION = "0.16.6rc1";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const _MIN_BACKEND_VERSION = "0.16.6rc1";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.12",
|
|
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,9 +156,9 @@
|
|
|
156
156
|
"p-queue": "6.6.2"
|
|
157
157
|
},
|
|
158
158
|
"devDependencies": {
|
|
159
|
-
"@ai-sdk/openai": "4.0.0-
|
|
160
|
-
"@ai-sdk/provider": "4.0.0-
|
|
161
|
-
"@ai-sdk/anthropic": "4.0.0-
|
|
159
|
+
"@ai-sdk/openai": "4.0.0-beta.74",
|
|
160
|
+
"@ai-sdk/provider": "4.0.0-beta.19",
|
|
161
|
+
"@ai-sdk/anthropic": "4.0.0-beta.67",
|
|
162
162
|
"@anthropic-ai/claude-agent-sdk": "^0.3.150",
|
|
163
163
|
"@anthropic-ai/sdk": "^0.98.0",
|
|
164
164
|
"@babel/preset-env": "^7.22.4",
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
"@types/ws": "^8.18.1",
|
|
185
185
|
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
|
186
186
|
"@typescript-eslint/parser": "^5.59.8",
|
|
187
|
-
"ai": "7.0.0-
|
|
187
|
+
"ai": "7.0.0-beta.178",
|
|
188
188
|
"babel-jest": "^30.2.0",
|
|
189
189
|
"cross-env": "^10.1.0",
|
|
190
190
|
"dotenv": "^17.3.1",
|