langsmith 0.8.10 → 0.8.11

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/index.cjs CHANGED
@@ -35,6 +35,6 @@ Object.defineProperty(exports, "UnprocessableEntityError", { enumerable: true, g
35
35
  Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return error_js_1.RateLimitError; } });
36
36
  Object.defineProperty(exports, "InternalServerError", { enumerable: true, get: function () { return error_js_1.InternalServerError; } });
37
37
  // Update using pnpm bump-version
38
- exports.__version__ = "0.8.10";
38
+ exports.__version__ = "0.8.11";
39
39
  // Metadata key to hide a traced run from LangSmith's Messages View.
40
40
  exports.LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
package/dist/index.d.ts CHANGED
@@ -7,5 +7,5 @@ export { computeRunIdForSecondaryReplica, uuid7, uuid7FromTime, } from "./uuid.j
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";
10
+ export declare const __version__ = "0.8.11";
11
11
  export declare const LS_MESSAGE_VIEW_EXCLUDE: "ls_message_view_exclude";
package/dist/index.js CHANGED
@@ -7,6 +7,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";
10
+ export const __version__ = "0.8.11";
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";
@@ -698,13 +698,19 @@ class SandboxClient {
698
698
  *
699
699
  * @param name - Snapshot name.
700
700
  * @param dockerfile - Local Dockerfile path, relative to context by default.
701
- * @param fsCapacityBytes - Filesystem capacity in bytes.
702
- * @param options - Build context, args, target, build log callback, builder
703
- * vCPUs/memory, timeout.
701
+ * @param fsCapacityBytesOrOptions - Optional filesystem capacity in bytes, or
702
+ * build options. When omitted, the server applies its default capacity.
703
+ * @param options - Build options when capacity is passed separately.
704
704
  * @returns Snapshot in "ready" status.
705
705
  */
706
- async createSnapshotFromDockerfile(name, dockerfile, fsCapacityBytes, options = {}) {
707
- const { context = ".", buildArgs, target, onBuildLog, vCpus, memBytes, timeout = 60, } = options;
706
+ async createSnapshotFromDockerfile(name, dockerfile, fsCapacityBytesOrOptions, options = {}) {
707
+ const fsCapacityBytes = typeof fsCapacityBytesOrOptions === "number"
708
+ ? fsCapacityBytesOrOptions
709
+ : undefined;
710
+ const resolvedOptions = typeof fsCapacityBytesOrOptions === "number"
711
+ ? options
712
+ : (fsCapacityBytesOrOptions ?? options);
713
+ const { context = ".", buildArgs, target, onBuildLog, vCpus, memBytes, timeout = 60, } = resolvedOptions;
708
714
  const { contextPath, dockerfileRel } = await resolveDockerfileContext(dockerfile, context);
709
715
  const builderName = `snapshot-builder-${(0, index_js_2.v4)().replace(/-/g, "").slice(0, 12)}`;
710
716
  // Stage the build on the capacity-backed root filesystem, not /tmp.
@@ -208,12 +208,12 @@ export declare class SandboxClient {
208
208
  *
209
209
  * @param name - Snapshot name.
210
210
  * @param dockerfile - Local Dockerfile path, relative to context by default.
211
- * @param fsCapacityBytes - Filesystem capacity in bytes.
212
- * @param options - Build context, args, target, build log callback, builder
213
- * vCPUs/memory, timeout.
211
+ * @param fsCapacityBytesOrOptions - Optional filesystem capacity in bytes, or
212
+ * build options. When omitted, the server applies its default capacity.
213
+ * @param options - Build options when capacity is passed separately.
214
214
  * @returns Snapshot in "ready" status.
215
215
  */
216
- createSnapshotFromDockerfile(name: string, dockerfile: string, fsCapacityBytes: number, options?: CreateDockerfileSnapshotOptions): Promise<Snapshot>;
216
+ createSnapshotFromDockerfile(name: string, dockerfile: string, fsCapacityBytesOrOptions?: number | CreateDockerfileSnapshotOptions, options?: CreateDockerfileSnapshotOptions): Promise<Snapshot>;
217
217
  /**
218
218
  * Capture a snapshot from a running sandbox.
219
219
  *
@@ -695,13 +695,19 @@ export class SandboxClient {
695
695
  *
696
696
  * @param name - Snapshot name.
697
697
  * @param dockerfile - Local Dockerfile path, relative to context by default.
698
- * @param fsCapacityBytes - Filesystem capacity in bytes.
699
- * @param options - Build context, args, target, build log callback, builder
700
- * vCPUs/memory, timeout.
698
+ * @param fsCapacityBytesOrOptions - Optional filesystem capacity in bytes, or
699
+ * build options. When omitted, the server applies its default capacity.
700
+ * @param options - Build options when capacity is passed separately.
701
701
  * @returns Snapshot in "ready" status.
702
702
  */
703
- async createSnapshotFromDockerfile(name, dockerfile, fsCapacityBytes, options = {}) {
704
- const { context = ".", buildArgs, target, onBuildLog, vCpus, memBytes, timeout = 60, } = options;
703
+ async createSnapshotFromDockerfile(name, dockerfile, fsCapacityBytesOrOptions, options = {}) {
704
+ const fsCapacityBytes = typeof fsCapacityBytesOrOptions === "number"
705
+ ? fsCapacityBytesOrOptions
706
+ : undefined;
707
+ const resolvedOptions = typeof fsCapacityBytesOrOptions === "number"
708
+ ? options
709
+ : (fsCapacityBytesOrOptions ?? options);
710
+ const { context = ".", buildArgs, target, onBuildLog, vCpus, memBytes, timeout = 60, } = resolvedOptions;
705
711
  const { contextPath, dockerfileRel } = await resolveDockerfileContext(dockerfile, context);
706
712
  const builderName = `snapshot-builder-${uuidv4().replace(/-/g, "").slice(0, 12)}`;
707
713
  // Stage the build on the capacity-backed root filesystem, not /tmp.
@@ -29,7 +29,7 @@
29
29
  * @packageDocumentation
30
30
  */
31
31
  Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.LangSmithDataplaneNotConfiguredError = exports.LangSmithCommandTimeoutError = exports.LangSmithSandboxOperationError = exports.LangSmithSandboxNotReadyError = exports.LangSmithSandboxCreationError = exports.LangSmithResourceCreationError = exports.LangSmithQuotaExceededError = exports.LangSmithValidationError = exports.LangSmithResourceNameConflictError = exports.LangSmithResourceAlreadyExistsError = exports.LangSmithResourceInUseError = exports.LangSmithResourceTimeoutError = exports.LangSmithResourceNotFoundError = exports.LangSmithSandboxServerReloadError = exports.LangSmithSandboxConnectTimeoutError = exports.LangSmithSandboxConnectionError = exports.LangSmithSandboxAuthenticationError = exports.LangSmithSandboxAPIError = exports.LangSmithSandboxError = exports.s3Mount = exports.mountConfig = exports.gitMount = exports.gcsMount = exports.workspaceSecret = exports.proxyConfig = exports.opaqueSecret = exports.gcpAuth = exports.awsAuth = exports.CommandHandle = exports.Sandbox = exports.SandboxClient = void 0;
32
+ exports.LangSmithDataplaneNotConfiguredError = exports.LangSmithCommandTimeoutError = exports.LangSmithSandboxOperationError = exports.LangSmithSandboxNotReadyError = exports.LangSmithSandboxCreationError = exports.LangSmithResourceCreationError = exports.LangSmithQuotaExceededError = exports.LangSmithValidationError = exports.LangSmithResourceNameConflictError = exports.LangSmithResourceAlreadyExistsError = exports.LangSmithResourceInUseError = exports.LangSmithResourceTimeoutError = exports.LangSmithResourceNotFoundError = exports.LangSmithSandboxServerReloadError = exports.LangSmithSandboxConnectTimeoutError = exports.LangSmithSandboxConnectionError = exports.LangSmithSandboxAuthenticationError = exports.LangSmithSandboxAPIError = exports.LangSmithSandboxError = exports.s3Mount = exports.mountConfig = exports.gitMount = exports.gcsMount = exports.contextHubMount = exports.workspaceSecret = exports.proxyConfig = exports.opaqueSecret = exports.gcpAuth = exports.awsAuth = exports.CommandHandle = exports.Sandbox = exports.SandboxClient = void 0;
33
33
  // Main classes
34
34
  var client_js_1 = require("./client.cjs");
35
35
  Object.defineProperty(exports, "SandboxClient", { enumerable: true, get: function () { return client_js_1.SandboxClient; } });
@@ -44,6 +44,7 @@ Object.defineProperty(exports, "opaqueSecret", { enumerable: true, get: function
44
44
  Object.defineProperty(exports, "proxyConfig", { enumerable: true, get: function () { return proxy_config_js_1.proxyConfig; } });
45
45
  Object.defineProperty(exports, "workspaceSecret", { enumerable: true, get: function () { return proxy_config_js_1.workspaceSecret; } });
46
46
  var mounts_js_1 = require("./mounts.cjs");
47
+ Object.defineProperty(exports, "contextHubMount", { enumerable: true, get: function () { return mounts_js_1.contextHubMount; } });
47
48
  Object.defineProperty(exports, "gcsMount", { enumerable: true, get: function () { return mounts_js_1.gcsMount; } });
48
49
  Object.defineProperty(exports, "gitMount", { enumerable: true, get: function () { return mounts_js_1.gitMount; } });
49
50
  Object.defineProperty(exports, "mountConfig", { enumerable: true, get: function () { return mounts_js_1.mountConfig; } });
@@ -31,6 +31,6 @@ export { SandboxClient } from "./client.js";
31
31
  export { Sandbox } from "./sandbox.js";
32
32
  export { CommandHandle } from "./command_handle.js";
33
33
  export { awsAuth, gcpAuth, opaqueSecret, proxyConfig, workspaceSecret, } from "./proxy_config.js";
34
- export { gcsMount, gitMount, mountConfig, s3Mount } from "./mounts.js";
35
- export type { ExecutionResult, OutputChunk, WsMessage, WsRunOptions, ResourceStatus, Snapshot, SandboxData, SandboxClientConfig, RunOptions, CreateSandboxOptions, SandboxAccessControl, SandboxAwsAuthRule, SandboxAwsMountAuthConfig, SandboxGcpAuthRule, SandboxGcpMountAuthConfig, SandboxMountAuth, SandboxMountAuthConfig, SandboxMountConfig, SandboxProxyConfig, SandboxProxyRule, SandboxProxySecret, SandboxMount, MountCacheConfig, GCSMountConfig, GCSMountSpec, GitMountConfig, GitMountRefSpec, GitMountSpec, S3MountConfig, S3MountSpec, CreateSnapshotOptions, CreateDockerfileSnapshotOptions, CaptureSnapshotOptions, ListSnapshotsOptions, WaitForSnapshotOptions, StartSandboxOptions, UpdateSandboxOptions, WaitForSandboxOptions, } from "./types.js";
34
+ export { contextHubMount, gcsMount, gitMount, mountConfig, s3Mount, } from "./mounts.js";
35
+ export type { ExecutionResult, OutputChunk, WsMessage, WsRunOptions, ResourceStatus, Snapshot, SandboxData, SandboxClientConfig, RunOptions, CreateSandboxOptions, SandboxAccessControl, SandboxAwsAuthRule, SandboxAwsMountAuthConfig, SandboxGcpAuthRule, SandboxGcpMountAuthConfig, SandboxMountAuth, SandboxMountAuthConfig, SandboxMountConfig, SandboxProxyConfig, SandboxProxyRule, SandboxProxySecret, SandboxMount, MountCacheConfig, ContextHubMountConfig, ContextHubMountSpec, GCSMountConfig, GCSMountSpec, GitMountConfig, GitMountRefSpec, GitMountSpec, S3MountConfig, S3MountSpec, CreateSnapshotOptions, CreateDockerfileSnapshotOptions, CaptureSnapshotOptions, ListSnapshotsOptions, WaitForSnapshotOptions, StartSandboxOptions, UpdateSandboxOptions, WaitForSandboxOptions, } from "./types.js";
36
36
  export { LangSmithSandboxError, LangSmithSandboxAPIError, LangSmithSandboxAuthenticationError, LangSmithSandboxConnectionError, LangSmithSandboxConnectTimeoutError, LangSmithSandboxServerReloadError, LangSmithResourceNotFoundError, LangSmithResourceTimeoutError, LangSmithResourceInUseError, LangSmithResourceAlreadyExistsError, LangSmithResourceNameConflictError, LangSmithValidationError, LangSmithQuotaExceededError, LangSmithResourceCreationError, LangSmithSandboxCreationError, LangSmithSandboxNotReadyError, LangSmithSandboxOperationError, LangSmithCommandTimeoutError, LangSmithDataplaneNotConfiguredError, } from "./errors.js";
@@ -32,7 +32,7 @@ export { SandboxClient } from "./client.js";
32
32
  export { Sandbox } from "./sandbox.js";
33
33
  export { CommandHandle } from "./command_handle.js";
34
34
  export { awsAuth, gcpAuth, opaqueSecret, proxyConfig, workspaceSecret, } from "./proxy_config.js";
35
- export { gcsMount, gitMount, mountConfig, s3Mount } from "./mounts.js";
35
+ export { contextHubMount, gcsMount, gitMount, mountConfig, s3Mount, } from "./mounts.js";
36
36
  // Errors
37
37
  export {
38
38
  // Base and connection errors
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.s3Mount = s3Mount;
4
4
  exports.gitMount = gitMount;
5
5
  exports.gcsMount = gcsMount;
6
+ exports.contextHubMount = contextHubMount;
6
7
  exports.mountConfig = mountConfig;
7
8
  exports.validateMountConfigProxyConfig = validateMountConfigProxyConfig;
8
9
  function requireNonEmptyString(value, field) {
@@ -132,6 +133,25 @@ function gcsMount({ id, mountPath, bucket, prefix, readOnly, cache, }) {
132
133
  }
133
134
  return mount;
134
135
  }
136
+ /**
137
+ * Build a read-only Context Hub mount. The sync is one-way: files written
138
+ * under the mount path inside the sandbox are never pushed back to the repo,
139
+ * and the next sync overwrites them.
140
+ */
141
+ function contextHubMount({ id, mountPath, repo, initialPullOnly, }) {
142
+ const mount = {
143
+ id: requireNonEmptyString(id, "id"),
144
+ type: "contexthub",
145
+ mount_path: requireNonEmptyString(mountPath, "mountPath"),
146
+ contexthub: {
147
+ repo: requireNonEmptyString(repo, "repo"),
148
+ },
149
+ };
150
+ if (initialPullOnly !== undefined) {
151
+ mount.contexthub.initial_pull_only = initialPullOnly;
152
+ }
153
+ return mount;
154
+ }
135
155
  function normalizeMounts(mounts) {
136
156
  if (!Array.isArray(mounts) || mounts.length === 0) {
137
157
  throw new Error("mounts must be a non-empty array of mount objects");
@@ -140,8 +160,11 @@ function normalizeMounts(mounts) {
140
160
  if (mount === null || typeof mount !== "object" || Array.isArray(mount)) {
141
161
  throw new Error("mounts must be a non-empty array of mount objects");
142
162
  }
143
- if (mount.type !== "s3" && mount.type !== "gcs" && mount.type !== "git") {
144
- throw new Error("mountConfig only supports s3, gcs, and git mounts");
163
+ if (mount.type !== "s3" &&
164
+ mount.type !== "gcs" &&
165
+ mount.type !== "git" &&
166
+ mount.type !== "contexthub") {
167
+ throw new Error("mountConfig only supports s3, gcs, git, and contexthub mounts");
145
168
  }
146
169
  rejectProviderCredentialsInMount(mount);
147
170
  return mount;
@@ -1,4 +1,4 @@
1
- import type { GCSMountSpec, GitMountRefSpec, GitMountSpec, MountCacheConfig, S3MountSpec, SandboxMount, SandboxMountAuth, SandboxMountConfig, SandboxProxyConfig } from "./types.js";
1
+ import type { ContextHubMountSpec, GCSMountSpec, GitMountRefSpec, GitMountSpec, MountCacheConfig, S3MountSpec, SandboxMount, SandboxMountAuth, SandboxMountConfig, SandboxProxyConfig } from "./types.js";
2
2
  export declare function s3Mount({ id, mountPath, bucket, region, prefix, endpointUrl, pathStyle, readOnly, cache, }: {
3
3
  id: string;
4
4
  mountPath: string;
@@ -25,6 +25,17 @@ export declare function gcsMount({ id, mountPath, bucket, prefix, readOnly, cach
25
25
  readOnly?: boolean;
26
26
  cache?: MountCacheConfig;
27
27
  }): GCSMountSpec;
28
+ /**
29
+ * Build a read-only Context Hub mount. The sync is one-way: files written
30
+ * under the mount path inside the sandbox are never pushed back to the repo,
31
+ * and the next sync overwrites them.
32
+ */
33
+ export declare function contextHubMount({ id, mountPath, repo, initialPullOnly, }: {
34
+ id: string;
35
+ mountPath: string;
36
+ repo: string;
37
+ initialPullOnly?: boolean;
38
+ }): ContextHubMountSpec;
28
39
  export declare function mountConfig({ auth, mounts, }: {
29
40
  auth?: SandboxMountAuth[];
30
41
  mounts: SandboxMount[];
@@ -125,6 +125,25 @@ export function gcsMount({ id, mountPath, bucket, prefix, readOnly, cache, }) {
125
125
  }
126
126
  return mount;
127
127
  }
128
+ /**
129
+ * Build a read-only Context Hub mount. The sync is one-way: files written
130
+ * under the mount path inside the sandbox are never pushed back to the repo,
131
+ * and the next sync overwrites them.
132
+ */
133
+ export function contextHubMount({ id, mountPath, repo, initialPullOnly, }) {
134
+ const mount = {
135
+ id: requireNonEmptyString(id, "id"),
136
+ type: "contexthub",
137
+ mount_path: requireNonEmptyString(mountPath, "mountPath"),
138
+ contexthub: {
139
+ repo: requireNonEmptyString(repo, "repo"),
140
+ },
141
+ };
142
+ if (initialPullOnly !== undefined) {
143
+ mount.contexthub.initial_pull_only = initialPullOnly;
144
+ }
145
+ return mount;
146
+ }
128
147
  function normalizeMounts(mounts) {
129
148
  if (!Array.isArray(mounts) || mounts.length === 0) {
130
149
  throw new Error("mounts must be a non-empty array of mount objects");
@@ -133,8 +152,11 @@ function normalizeMounts(mounts) {
133
152
  if (mount === null || typeof mount !== "object" || Array.isArray(mount)) {
134
153
  throw new Error("mounts must be a non-empty array of mount objects");
135
154
  }
136
- if (mount.type !== "s3" && mount.type !== "gcs" && mount.type !== "git") {
137
- throw new Error("mountConfig only supports s3, gcs, and git mounts");
155
+ if (mount.type !== "s3" &&
156
+ mount.type !== "gcs" &&
157
+ mount.type !== "git" &&
158
+ mount.type !== "contexthub") {
159
+ throw new Error("mountConfig only supports s3, gcs, git, and contexthub mounts");
138
160
  }
139
161
  rejectProviderCredentialsInMount(mount);
140
162
  return mount;
@@ -17,6 +17,22 @@ function requireNonEmptyStringArray(values, field) {
17
17
  }
18
18
  return values.map((value) => requireNonEmptyString(value, field));
19
19
  }
20
+ function requireEnvVars(envVars) {
21
+ if (envVars === null ||
22
+ typeof envVars !== "object" ||
23
+ Array.isArray(envVars)) {
24
+ throw new Error("envVars must be a non-empty object of names to values");
25
+ }
26
+ const entries = Object.entries(envVars);
27
+ if (entries.length === 0) {
28
+ throw new Error("envVars must be a non-empty object of names to values");
29
+ }
30
+ return Object.fromEntries(entries.map(([name, value]) => {
31
+ // Validated on the trimmed form, stored verbatim: whitespace can be significant.
32
+ requireNonEmptyString(value, `envVars[${name}]`);
33
+ return [requireNonEmptyString(name, "envVars name"), value];
34
+ }));
35
+ }
20
36
  function requireProxyRules(rules) {
21
37
  if (rules === undefined) {
22
38
  return [];
@@ -79,8 +95,8 @@ function proxyConfig({ rules, noProxy, accessControl, } = {}) {
79
95
  return config;
80
96
  }
81
97
  /** Build a sandbox proxy rule that signs AWS HTTPS requests with SigV4. */
82
- function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled = true, }) {
83
- return {
98
+ function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled = true, envVars, }) {
99
+ const rule = {
84
100
  name: requireNonEmptyString(name, "name"),
85
101
  type: "aws",
86
102
  enabled,
@@ -89,19 +105,27 @@ function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled = true, }
89
105
  secret_access_key: secretAccessKey,
90
106
  },
91
107
  };
108
+ if (envVars !== undefined) {
109
+ rule.env_vars = requireEnvVars(envVars);
110
+ }
111
+ return rule;
92
112
  }
93
113
  /** Build a sandbox proxy rule that injects GCP OAuth bearer auth. */
94
- function gcpAuth({ serviceAccountJson, scopes, name = "gcp", enabled = true, }) {
114
+ function gcpAuth({ serviceAccountJson, scopes, name = "gcp", enabled = true, envVars, }) {
95
115
  const gcp = {
96
116
  service_account_json: serviceAccountJson,
97
117
  };
98
118
  if (scopes !== undefined) {
99
119
  gcp.scopes = requireNonEmptyStringArray(scopes, "scopes");
100
120
  }
101
- return {
121
+ const rule = {
102
122
  name: requireNonEmptyString(name, "name"),
103
123
  type: "gcp",
104
124
  enabled,
105
125
  gcp,
106
126
  };
127
+ if (envVars !== undefined) {
128
+ rule.env_vars = requireEnvVars(envVars);
129
+ }
130
+ return rule;
107
131
  }
@@ -10,16 +10,18 @@ export declare function proxyConfig({ rules, noProxy, accessControl, }?: {
10
10
  accessControl?: SandboxAccessControl;
11
11
  }): SandboxProxyConfig;
12
12
  /** Build a sandbox proxy rule that signs AWS HTTPS requests with SigV4. */
13
- export declare function awsAuth({ accessKeyId, secretAccessKey, name, enabled, }: {
13
+ export declare function awsAuth({ accessKeyId, secretAccessKey, name, enabled, envVars, }: {
14
14
  accessKeyId: SandboxProxySecret;
15
15
  secretAccessKey: SandboxProxySecret;
16
16
  name?: string;
17
17
  enabled?: boolean;
18
+ envVars?: Record<string, string>;
18
19
  }): SandboxAwsAuthRule;
19
20
  /** Build a sandbox proxy rule that injects GCP OAuth bearer auth. */
20
- export declare function gcpAuth({ serviceAccountJson, scopes, name, enabled, }: {
21
+ export declare function gcpAuth({ serviceAccountJson, scopes, name, enabled, envVars, }: {
21
22
  serviceAccountJson: SandboxProxySecret;
22
23
  scopes?: string[];
23
24
  name?: string;
24
25
  enabled?: boolean;
26
+ envVars?: Record<string, string>;
25
27
  }): SandboxGcpAuthRule;
@@ -10,6 +10,22 @@ function requireNonEmptyStringArray(values, field) {
10
10
  }
11
11
  return values.map((value) => requireNonEmptyString(value, field));
12
12
  }
13
+ function requireEnvVars(envVars) {
14
+ if (envVars === null ||
15
+ typeof envVars !== "object" ||
16
+ Array.isArray(envVars)) {
17
+ throw new Error("envVars must be a non-empty object of names to values");
18
+ }
19
+ const entries = Object.entries(envVars);
20
+ if (entries.length === 0) {
21
+ throw new Error("envVars must be a non-empty object of names to values");
22
+ }
23
+ return Object.fromEntries(entries.map(([name, value]) => {
24
+ // Validated on the trimmed form, stored verbatim: whitespace can be significant.
25
+ requireNonEmptyString(value, `envVars[${name}]`);
26
+ return [requireNonEmptyString(name, "envVars name"), value];
27
+ }));
28
+ }
13
29
  function requireProxyRules(rules) {
14
30
  if (rules === undefined) {
15
31
  return [];
@@ -72,8 +88,8 @@ export function proxyConfig({ rules, noProxy, accessControl, } = {}) {
72
88
  return config;
73
89
  }
74
90
  /** Build a sandbox proxy rule that signs AWS HTTPS requests with SigV4. */
75
- export function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled = true, }) {
76
- return {
91
+ export function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled = true, envVars, }) {
92
+ const rule = {
77
93
  name: requireNonEmptyString(name, "name"),
78
94
  type: "aws",
79
95
  enabled,
@@ -82,19 +98,27 @@ export function awsAuth({ accessKeyId, secretAccessKey, name = "aws", enabled =
82
98
  secret_access_key: secretAccessKey,
83
99
  },
84
100
  };
101
+ if (envVars !== undefined) {
102
+ rule.env_vars = requireEnvVars(envVars);
103
+ }
104
+ return rule;
85
105
  }
86
106
  /** Build a sandbox proxy rule that injects GCP OAuth bearer auth. */
87
- export function gcpAuth({ serviceAccountJson, scopes, name = "gcp", enabled = true, }) {
107
+ export function gcpAuth({ serviceAccountJson, scopes, name = "gcp", enabled = true, envVars, }) {
88
108
  const gcp = {
89
109
  service_account_json: serviceAccountJson,
90
110
  };
91
111
  if (scopes !== undefined) {
92
112
  gcp.scopes = requireNonEmptyStringArray(scopes, "scopes");
93
113
  }
94
- return {
114
+ const rule = {
95
115
  name: requireNonEmptyString(name, "name"),
96
116
  type: "gcp",
97
117
  enabled,
98
118
  gcp,
99
119
  };
120
+ if (envVars !== undefined) {
121
+ rule.env_vars = requireEnvVars(envVars);
122
+ }
123
+ return rule;
100
124
  }
@@ -270,6 +270,13 @@ export interface SandboxAwsAuthRule {
270
270
  type: "aws";
271
271
  /** Whether the rule is enabled. */
272
272
  enabled?: boolean;
273
+ /**
274
+ * Plaintext environment variables set for every command in the sandbox while
275
+ * the rule is enabled, for tools that refuse to run unless a credential
276
+ * variable is present even though the proxy injects the real credential on
277
+ * the wire.
278
+ */
279
+ env_vars?: Record<string, string>;
273
280
  /** AWS credentials used by the proxy signer. */
274
281
  aws: {
275
282
  access_key_id: SandboxProxySecret;
@@ -284,6 +291,13 @@ export interface SandboxGcpAuthRule {
284
291
  type: "gcp";
285
292
  /** Whether the rule is enabled. */
286
293
  enabled?: boolean;
294
+ /**
295
+ * Plaintext environment variables set for every command in the sandbox while
296
+ * the rule is enabled, for tools that refuse to run unless a credential
297
+ * variable is present even though the proxy injects the real credential on
298
+ * the wire.
299
+ */
300
+ env_vars?: Record<string, string>;
287
301
  /** GCP service-account credential and OAuth scopes. */
288
302
  gcp: {
289
303
  service_account_json: SandboxProxySecret;
@@ -386,8 +400,29 @@ export interface GitMountSpec {
386
400
  /** Git mount configuration. */
387
401
  git: GitMountConfig;
388
402
  }
403
+ /** Context Hub configuration for a sandbox mount. */
404
+ export interface ContextHubMountConfig {
405
+ /**
406
+ * Context Hub repository to sync, as `owner/repo` (e.g. `-/my-agent`, where
407
+ * `-` is the current workspace).
408
+ */
409
+ repo: string;
410
+ /** Sync once at startup instead of polling for updates. */
411
+ initial_pull_only?: boolean;
412
+ }
413
+ /** Read-only Context Hub-backed sandbox mount specification. */
414
+ export interface ContextHubMountSpec {
415
+ /** Stable mount identifier. */
416
+ id: string;
417
+ /** Mount type. */
418
+ type: "contexthub";
419
+ /** Absolute path inside the sandbox where the repo tree appears. */
420
+ mount_path: string;
421
+ /** Context Hub mount configuration. */
422
+ contexthub: ContextHubMountConfig;
423
+ }
389
424
  /** Sandbox mount specification. */
390
- export type SandboxMount = S3MountSpec | GCSMountSpec | GitMountSpec;
425
+ export type SandboxMount = S3MountSpec | GCSMountSpec | GitMountSpec | ContextHubMountSpec;
391
426
  /** AWS credentials used by the backend to authenticate S3 mounts. */
392
427
  export interface SandboxAwsMountAuthConfig {
393
428
  access_key_id: SandboxProxySecret;
@@ -5,7 +5,36 @@ exports.createUsageMetadata = createUsageMetadata;
5
5
  const anthropic_managed_js_1 = require("./utils/anthropic_managed.cjs");
6
6
  const traceable_js_1 = require("../traceable.cjs");
7
7
  const usage_js_1 = require("../utils/usage.cjs");
8
+ const index_js_1 = require("../anonymizer/index.cjs");
8
9
  const TRACED_INVOCATION_KEYS = ["top_k", "top_p", "stream", "thinking"];
10
+ /** Keys of an MCP server definition that are safe to trace. */
11
+ const MCP_SERVER_SAFE_KEYS = new Set([
12
+ "name",
13
+ "type",
14
+ "url",
15
+ "tool_configuration",
16
+ ]);
17
+ /**
18
+ * Mask credentials in `mcp_servers` before tracing. Anything outside
19
+ * {@link MCP_SERVER_SAFE_KEYS} keeps its name but gets
20
+ * {@link SECRET_PLACEHOLDER} as its value, so the trace shows the field was set
21
+ * without exposing it, and fields the API adds later are masked by default.
22
+ *
23
+ * Returns new objects; the caller's are also sent to Anthropic.
24
+ */
25
+ function redactMcpServers(servers) {
26
+ if (!Array.isArray(servers))
27
+ return servers;
28
+ return servers.map((server) => {
29
+ if (typeof server !== "object" || server == null || Array.isArray(server)) {
30
+ return server;
31
+ }
32
+ return Object.fromEntries(Object.entries(server).map(([key, value]) => [
33
+ key,
34
+ MCP_SERVER_SAFE_KEYS.has(key) ? value : index_js_1.SECRET_PLACEHOLDER,
35
+ ]));
36
+ });
37
+ }
9
38
  /**
10
39
  * Create usage metadata from Anthropic's token usage format.
11
40
  */
@@ -222,11 +251,15 @@ const wrapAnthropic = (anthropic, options) => {
222
251
  * This provides parity with the Python SDK behavior and enables system prompts
223
252
  * to be viewed and edited in the LangSmith playground.
224
253
  */
225
- function processSystemMessage(params) {
254
+ function processTracedInputs(params) {
255
+ // Copy first: `params` also goes to the API and must keep its real values.
256
+ const processed = { ...params };
257
+ if (processed.mcp_servers != null) {
258
+ processed.mcp_servers = redactMcpServers(processed.mcp_servers);
259
+ }
226
260
  if (!params.system) {
227
- return params;
261
+ return processed;
228
262
  }
229
- const processed = { ...params };
230
263
  // Handle both string and ContentBlock[] formats
231
264
  const systemContent = Array.isArray(params.system)
232
265
  ? params.system
@@ -248,7 +281,7 @@ const wrapAnthropic = (anthropic, options) => {
248
281
  run_type: "llm",
249
282
  aggregator: messageAggregator,
250
283
  argsConfigPath: [1, "langsmithExtra"],
251
- processInputs: processSystemMessage,
284
+ processInputs: processTracedInputs,
252
285
  getInvocationParams: (payload) => {
253
286
  if (typeof payload !== "object" || payload == null)
254
287
  return undefined;
@@ -315,7 +348,7 @@ const wrapAnthropic = (anthropic, options) => {
315
348
  run_type: "llm",
316
349
  aggregator: messageAggregator,
317
350
  argsConfigPath: [1, "langsmithExtra"],
318
- processInputs: processSystemMessage,
351
+ processInputs: processTracedInputs,
319
352
  getInvocationParams: messagesCreateConfig.getInvocationParams,
320
353
  processOutputs: processMessageOutput,
321
354
  ...cleanedOptions,
@@ -341,7 +374,7 @@ const wrapAnthropic = (anthropic, options) => {
341
374
  run_type: "llm",
342
375
  aggregator: messageAggregator,
343
376
  argsConfigPath: [1, "langsmithExtra"],
344
- processInputs: processSystemMessage,
377
+ processInputs: processTracedInputs,
345
378
  getInvocationParams: messagesCreateConfig.getInvocationParams,
346
379
  processOutputs: processMessageOutput,
347
380
  ...cleanedOptions,
@@ -1,7 +1,36 @@
1
1
  import { wrapManagedAgentSessionEvents } from "./utils/anthropic_managed.js";
2
2
  import { isTraceableFunction, traceable, } from "../traceable.js";
3
3
  import { convertAnthropicUsageToInputTokenDetails } from "../utils/usage.js";
4
+ import { SECRET_PLACEHOLDER } from "../anonymizer/index.js";
4
5
  const TRACED_INVOCATION_KEYS = ["top_k", "top_p", "stream", "thinking"];
6
+ /** Keys of an MCP server definition that are safe to trace. */
7
+ const MCP_SERVER_SAFE_KEYS = new Set([
8
+ "name",
9
+ "type",
10
+ "url",
11
+ "tool_configuration",
12
+ ]);
13
+ /**
14
+ * Mask credentials in `mcp_servers` before tracing. Anything outside
15
+ * {@link MCP_SERVER_SAFE_KEYS} keeps its name but gets
16
+ * {@link SECRET_PLACEHOLDER} as its value, so the trace shows the field was set
17
+ * without exposing it, and fields the API adds later are masked by default.
18
+ *
19
+ * Returns new objects; the caller's are also sent to Anthropic.
20
+ */
21
+ function redactMcpServers(servers) {
22
+ if (!Array.isArray(servers))
23
+ return servers;
24
+ return servers.map((server) => {
25
+ if (typeof server !== "object" || server == null || Array.isArray(server)) {
26
+ return server;
27
+ }
28
+ return Object.fromEntries(Object.entries(server).map(([key, value]) => [
29
+ key,
30
+ MCP_SERVER_SAFE_KEYS.has(key) ? value : SECRET_PLACEHOLDER,
31
+ ]));
32
+ });
33
+ }
5
34
  /**
6
35
  * Create usage metadata from Anthropic's token usage format.
7
36
  */
@@ -218,11 +247,15 @@ export const wrapAnthropic = (anthropic, options) => {
218
247
  * This provides parity with the Python SDK behavior and enables system prompts
219
248
  * to be viewed and edited in the LangSmith playground.
220
249
  */
221
- function processSystemMessage(params) {
250
+ function processTracedInputs(params) {
251
+ // Copy first: `params` also goes to the API and must keep its real values.
252
+ const processed = { ...params };
253
+ if (processed.mcp_servers != null) {
254
+ processed.mcp_servers = redactMcpServers(processed.mcp_servers);
255
+ }
222
256
  if (!params.system) {
223
- return params;
257
+ return processed;
224
258
  }
225
- const processed = { ...params };
226
259
  // Handle both string and ContentBlock[] formats
227
260
  const systemContent = Array.isArray(params.system)
228
261
  ? params.system
@@ -244,7 +277,7 @@ export const wrapAnthropic = (anthropic, options) => {
244
277
  run_type: "llm",
245
278
  aggregator: messageAggregator,
246
279
  argsConfigPath: [1, "langsmithExtra"],
247
- processInputs: processSystemMessage,
280
+ processInputs: processTracedInputs,
248
281
  getInvocationParams: (payload) => {
249
282
  if (typeof payload !== "object" || payload == null)
250
283
  return undefined;
@@ -311,7 +344,7 @@ export const wrapAnthropic = (anthropic, options) => {
311
344
  run_type: "llm",
312
345
  aggregator: messageAggregator,
313
346
  argsConfigPath: [1, "langsmithExtra"],
314
- processInputs: processSystemMessage,
347
+ processInputs: processTracedInputs,
315
348
  getInvocationParams: messagesCreateConfig.getInvocationParams,
316
349
  processOutputs: processMessageOutput,
317
350
  ...cleanedOptions,
@@ -337,7 +370,7 @@ export const wrapAnthropic = (anthropic, options) => {
337
370
  run_type: "llm",
338
371
  aggregator: messageAggregator,
339
372
  argsConfigPath: [1, "langsmithExtra"],
340
- processInputs: processSystemMessage,
373
+ processInputs: processTracedInputs,
341
374
  getInvocationParams: messagesCreateConfig.getInvocationParams,
342
375
  processOutputs: processMessageOutput,
343
376
  ...cleanedOptions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.8.10",
3
+ "version": "0.8.11",
4
4
  "description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
5
5
  "packageManager": "pnpm@10.33.0",
6
6
  "files": [
@@ -481,7 +481,17 @@
481
481
  },
482
482
  "pnpm": {
483
483
  "overrides": {
484
- "js-yaml": "^4.1.1",
484
+ "@hono/node-server": "2.0.10",
485
+ "brace-expansion@<1.1.16": "1.1.16",
486
+ "brace-expansion@>=2.0.0 <2.1.2": "2.1.2",
487
+ "brace-expansion@>=3.0.0 <5.0.7": "5.0.7",
488
+ "fast-uri": "3.1.5",
489
+ "postcss": "8.5.23",
490
+ "js-yaml": "4.3.1",
491
+ "hono": "4.12.34",
492
+ "ip-address": "10.3.1",
493
+ "undici@>=7.0.0 <8.0.0": "7.29.0",
494
+ "undici@>=8.0.0 <9.0.0": "8.9.0",
485
495
  "vite": "^7.3.2",
486
496
  "form-data": "4.0.6",
487
497
  "langsmith": "0.6.0",