langsmith 0.5.19 → 0.6.0

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.
Files changed (161) hide show
  1. package/dist/client.cjs +460 -22
  2. package/dist/client.d.ts +165 -1
  3. package/dist/client.js +464 -26
  4. package/dist/evaluation/_runner.cjs +4 -7
  5. package/dist/evaluation/_runner.js +2 -5
  6. package/dist/evaluation/evaluate_comparative.cjs +10 -10
  7. package/dist/evaluation/evaluate_comparative.js +1 -1
  8. package/dist/evaluation/evaluator.cjs +2 -2
  9. package/dist/evaluation/evaluator.js +1 -1
  10. package/dist/experimental/anthropic/context.cjs +419 -49
  11. package/dist/experimental/anthropic/context.js +420 -50
  12. package/dist/experimental/anthropic/index.cjs +78 -10
  13. package/dist/experimental/anthropic/index.js +80 -12
  14. package/dist/experimental/anthropic/messages.cjs +53 -0
  15. package/dist/experimental/anthropic/messages.d.ts +6 -0
  16. package/dist/experimental/anthropic/messages.js +52 -0
  17. package/dist/experimental/anthropic/transcripts.cjs +144 -0
  18. package/dist/experimental/anthropic/transcripts.d.ts +22 -0
  19. package/dist/experimental/anthropic/transcripts.js +141 -0
  20. package/dist/experimental/anthropic/types.d.ts +1 -0
  21. package/dist/experimental/anthropic/usage.cjs +19 -20
  22. package/dist/experimental/anthropic/usage.d.ts +2 -1
  23. package/dist/experimental/anthropic/usage.js +18 -20
  24. package/dist/experimental/opencode/index.cjs +36 -0
  25. package/dist/experimental/opencode/index.d.ts +3 -0
  26. package/dist/experimental/opencode/index.js +32 -0
  27. package/dist/experimental/opencode/tracer.cjs +389 -0
  28. package/dist/experimental/opencode/tracer.d.ts +30 -0
  29. package/dist/experimental/opencode/tracer.js +385 -0
  30. package/dist/experimental/otel/setup.cjs +1 -1
  31. package/dist/experimental/otel/setup.js +1 -1
  32. package/dist/experimental/sandbox/client.cjs +308 -409
  33. package/dist/experimental/sandbox/client.d.ts +136 -157
  34. package/dist/experimental/sandbox/client.js +310 -411
  35. package/dist/experimental/sandbox/errors.cjs +1 -2
  36. package/dist/experimental/sandbox/errors.d.ts +1 -2
  37. package/dist/experimental/sandbox/errors.js +1 -2
  38. package/dist/experimental/sandbox/helpers.cjs +8 -98
  39. package/dist/experimental/sandbox/helpers.d.ts +0 -29
  40. package/dist/experimental/sandbox/helpers.js +9 -95
  41. package/dist/experimental/sandbox/index.cjs +6 -1
  42. package/dist/experimental/sandbox/index.d.ts +7 -2
  43. package/dist/experimental/sandbox/index.js +6 -1
  44. package/dist/experimental/sandbox/sandbox.cjs +71 -13
  45. package/dist/experimental/sandbox/sandbox.d.ts +39 -9
  46. package/dist/experimental/sandbox/sandbox.js +71 -13
  47. package/dist/experimental/sandbox/types.d.ts +147 -137
  48. package/dist/experimental/vercel/index.cjs +1 -1
  49. package/dist/experimental/vercel/index.js +1 -1
  50. package/dist/experimental/vercel/middleware.cjs +2 -1
  51. package/dist/experimental/vercel/middleware.js +2 -1
  52. package/dist/index.cjs +1 -1
  53. package/dist/index.d.ts +1 -1
  54. package/dist/index.js +1 -1
  55. package/dist/run_trees.cjs +8 -7
  56. package/dist/run_trees.d.ts +7 -0
  57. package/dist/run_trees.js +7 -6
  58. package/dist/schemas.d.ts +58 -0
  59. package/dist/singletons/otel.cjs +3 -2
  60. package/dist/singletons/otel.js +4 -3
  61. package/dist/singletons/traceable.cjs +1 -3
  62. package/dist/singletons/traceable.js +1 -3
  63. package/dist/traceable.cjs +2 -5
  64. package/dist/traceable.js +2 -5
  65. package/dist/utils/_git.cjs +2 -2
  66. package/dist/utils/_git.js +2 -2
  67. package/dist/utils/_uuid.cjs +2 -2
  68. package/dist/utils/_uuid.js +1 -1
  69. package/dist/utils/env.cjs +35 -2
  70. package/dist/utils/env.d.ts +9 -0
  71. package/dist/utils/env.js +34 -2
  72. package/dist/utils/error.cjs +9 -2
  73. package/dist/utils/error.d.ts +1 -0
  74. package/dist/utils/error.js +8 -2
  75. package/dist/utils/fast-safe-stringify/index.cjs +203 -0
  76. package/dist/utils/fast-safe-stringify/index.d.ts +46 -0
  77. package/dist/utils/fast-safe-stringify/index.js +202 -0
  78. package/dist/utils/jestlike/index.cjs +5 -5
  79. package/dist/utils/jestlike/index.js +1 -1
  80. package/dist/utils/jestlike/reporter.cjs +1 -1
  81. package/dist/utils/jestlike/reporter.js +1 -1
  82. package/dist/utils/jestlike/vendor/chain.cjs +2 -3
  83. package/dist/utils/jestlike/vendor/chain.js +2 -3
  84. package/dist/utils/jestlike/vendor/evaluatedBy.cjs +3 -3
  85. package/dist/utils/jestlike/vendor/evaluatedBy.js +1 -1
  86. package/dist/utils/prompts.cjs +7 -2
  87. package/dist/utils/prompts.d.ts +6 -1
  88. package/dist/utils/prompts.js +6 -1
  89. package/dist/utils/serialize_worker.cjs +388 -0
  90. package/dist/utils/serialize_worker.d.ts +66 -0
  91. package/dist/utils/serialize_worker.js +382 -0
  92. package/dist/utils/uuid/src/index.cjs +24 -0
  93. package/dist/utils/uuid/src/index.d.ts +10 -0
  94. package/dist/utils/uuid/src/index.js +9 -0
  95. package/dist/utils/uuid/src/max.cjs +3 -0
  96. package/dist/utils/uuid/src/max.d.ts +2 -0
  97. package/dist/utils/uuid/src/max.js +1 -0
  98. package/dist/utils/uuid/src/nil.cjs +3 -0
  99. package/dist/utils/uuid/src/nil.d.ts +2 -0
  100. package/dist/utils/uuid/src/nil.js +1 -0
  101. package/dist/utils/uuid/src/parse.cjs +23 -0
  102. package/dist/utils/uuid/src/parse.d.ts +3 -0
  103. package/dist/utils/uuid/src/parse.js +18 -0
  104. package/dist/utils/uuid/src/regex.cjs +3 -0
  105. package/dist/utils/uuid/src/regex.d.ts +2 -0
  106. package/dist/utils/uuid/src/regex.js +1 -0
  107. package/dist/utils/uuid/src/rng.cjs +10 -0
  108. package/dist/utils/uuid/src/rng.d.ts +1 -0
  109. package/dist/utils/uuid/src/rng.js +7 -0
  110. package/dist/utils/uuid/src/sha1.cjs +75 -0
  111. package/dist/utils/uuid/src/sha1.d.ts +2 -0
  112. package/dist/utils/uuid/src/sha1.js +73 -0
  113. package/dist/utils/uuid/src/stringify.cjs +55 -0
  114. package/dist/utils/uuid/src/stringify.d.ts +3 -0
  115. package/dist/utils/uuid/src/stringify.js +49 -0
  116. package/dist/utils/uuid/src/types.cjs +2 -0
  117. package/dist/utils/uuid/src/types.d.ts +22 -0
  118. package/dist/utils/uuid/src/types.js +1 -0
  119. package/dist/utils/uuid/src/v35.cjs +52 -0
  120. package/dist/utils/uuid/src/v35.d.ts +7 -0
  121. package/dist/utils/uuid/src/v35.js +44 -0
  122. package/dist/utils/uuid/src/v4.cjs +40 -0
  123. package/dist/utils/uuid/src/v4.d.ts +4 -0
  124. package/dist/utils/uuid/src/v4.js +35 -0
  125. package/dist/utils/uuid/src/v5.cjs +50 -0
  126. package/dist/utils/uuid/src/v5.d.ts +9 -0
  127. package/dist/utils/uuid/src/v5.js +9 -0
  128. package/dist/utils/uuid/src/v7.cjs +88 -0
  129. package/dist/utils/uuid/src/v7.d.ts +9 -0
  130. package/dist/utils/uuid/src/v7.js +82 -0
  131. package/dist/utils/uuid/src/validate.cjs +10 -0
  132. package/dist/utils/uuid/src/validate.d.ts +2 -0
  133. package/dist/utils/uuid/src/validate.js +5 -0
  134. package/dist/utils/uuid/src/version.cjs +13 -0
  135. package/dist/utils/uuid/src/version.d.ts +2 -0
  136. package/dist/utils/uuid/src/version.js +8 -0
  137. package/dist/utils/worker_threads.browser.cjs +16 -0
  138. package/dist/utils/worker_threads.browser.d.ts +14 -0
  139. package/dist/utils/worker_threads.browser.js +13 -0
  140. package/dist/utils/worker_threads.cjs +16 -0
  141. package/dist/utils/worker_threads.d.ts +13 -0
  142. package/dist/utils/worker_threads.js +13 -0
  143. package/dist/uuid.cjs +2 -2
  144. package/dist/uuid.js +1 -1
  145. package/dist/vitest/utils/esm.mjs +4 -4
  146. package/dist/wrappers/gemini.cjs +1 -1
  147. package/dist/wrappers/gemini.js +1 -1
  148. package/dist/wrappers/openai.cjs +2 -6
  149. package/dist/wrappers/openai.js +2 -6
  150. package/dist/wrappers/openai_agents.cjs +849 -0
  151. package/dist/wrappers/openai_agents.d.ts +92 -0
  152. package/dist/wrappers/openai_agents.js +845 -0
  153. package/experimental/opencode.cjs +1 -0
  154. package/experimental/opencode.d.cts +1 -0
  155. package/experimental/opencode.d.ts +1 -0
  156. package/experimental/opencode.js +1 -0
  157. package/package.json +47 -25
  158. package/wrappers/openai_agents.cjs +1 -0
  159. package/wrappers/openai_agents.d.cts +1 -0
  160. package/wrappers/openai_agents.d.ts +1 -0
  161. package/wrappers/openai_agents.js +1 -0
@@ -165,7 +165,6 @@ exports.LangSmithResourceNameConflictError = LangSmithResourceNameConflictError;
165
165
  * - Resource values exceeding server-defined limits (CPU, memory, storage)
166
166
  * - Invalid resource units
167
167
  * - Invalid name formats
168
- * - Pool validation failures (e.g., template has volumes)
169
168
  */
170
169
  class LangSmithValidationError extends LangSmithSandboxError {
171
170
  constructor(message, field, details, errorType) {
@@ -224,7 +223,7 @@ class LangSmithResourceCreationError extends LangSmithSandboxError {
224
223
  constructor(message, resourceType, errorType) {
225
224
  super(message);
226
225
  /**
227
- * Type of resource that failed (e.g., "sandbox", "volume").
226
+ * Type of resource that failed (e.g., "sandbox", "snapshot").
228
227
  */
229
228
  Object.defineProperty(this, "resourceType", {
230
229
  enumerable: true,
@@ -75,7 +75,6 @@ export declare class LangSmithResourceNameConflictError extends LangSmithSandbox
75
75
  * - Resource values exceeding server-defined limits (CPU, memory, storage)
76
76
  * - Invalid resource units
77
77
  * - Invalid name formats
78
- * - Pool validation failures (e.g., template has volumes)
79
78
  */
80
79
  export declare class LangSmithValidationError extends LangSmithSandboxError {
81
80
  field?: string;
@@ -97,7 +96,7 @@ export declare class LangSmithQuotaExceededError extends LangSmithSandboxError {
97
96
  */
98
97
  export declare class LangSmithResourceCreationError extends LangSmithSandboxError {
99
98
  /**
100
- * Type of resource that failed (e.g., "sandbox", "volume").
99
+ * Type of resource that failed (e.g., "sandbox", "snapshot").
101
100
  */
102
101
  resourceType?: string;
103
102
  /**
@@ -153,7 +153,6 @@ export class LangSmithResourceNameConflictError extends LangSmithSandboxError {
153
153
  * - Resource values exceeding server-defined limits (CPU, memory, storage)
154
154
  * - Invalid resource units
155
155
  * - Invalid name formats
156
- * - Pool validation failures (e.g., template has volumes)
157
156
  */
158
157
  export class LangSmithValidationError extends LangSmithSandboxError {
159
158
  constructor(message, field, details, errorType) {
@@ -210,7 +209,7 @@ export class LangSmithResourceCreationError extends LangSmithSandboxError {
210
209
  constructor(message, resourceType, errorType) {
211
210
  super(message);
212
211
  /**
213
- * Type of resource that failed (e.g., "sandbox", "volume").
212
+ * Type of resource that failed (e.g., "sandbox", "snapshot").
214
213
  */
215
214
  Object.defineProperty(this, "resourceType", {
216
215
  enumerable: true,
@@ -11,12 +11,8 @@ exports.parseErrorResponse = parseErrorResponse;
11
11
  exports.parseValidationError = parseValidationError;
12
12
  exports.extractQuotaType = extractQuotaType;
13
13
  exports.handleSandboxCreationError = handleSandboxCreationError;
14
- exports.handleVolumeCreationError = handleVolumeCreationError;
15
- exports.handlePoolError = handlePoolError;
16
14
  exports.handleClientHttpError = handleClientHttpError;
17
15
  exports.handleSandboxHttpError = handleSandboxHttpError;
18
- exports.handleConflictError = handleConflictError;
19
- exports.handleResourceInUseError = handleResourceInUseError;
20
16
  const errors_js_1 = require("./errors.cjs");
21
17
  // =============================================================================
22
18
  // Input validation
@@ -115,11 +111,6 @@ function extractQuotaType(message) {
115
111
  else if (messageLower.includes("memory")) {
116
112
  return "memory";
117
113
  }
118
- // Check for volume count quota
119
- else if (messageLower.includes("volume") &&
120
- (messageLower.includes("count") || messageLower.includes("limit"))) {
121
- return "volume_count";
122
- }
123
114
  else if (messageLower.includes("storage")) {
124
115
  return "storage";
125
116
  }
@@ -140,6 +131,7 @@ function extractQuotaType(message) {
140
131
  */
141
132
  async function handleSandboxCreationError(response) {
142
133
  const status = response.status;
134
+ const clonedResponse = response.clone();
143
135
  const data = await parseErrorResponse(response);
144
136
  if (status === 408) {
145
137
  // Timeout - include the message which contains last known status
@@ -147,7 +139,6 @@ async function handleSandboxCreationError(response) {
147
139
  }
148
140
  else if (status === 422) {
149
141
  // Check if this is a Pydantic validation error (bad input) vs creation error
150
- const clonedResponse = response.clone();
151
142
  const details = await parseValidationError(clonedResponse);
152
143
  if (details.length > 0 && details.some((d) => d.type === "value_error")) {
153
144
  // Pydantic validation error (bad input - exceeds server limits)
@@ -168,86 +159,20 @@ async function handleSandboxCreationError(response) {
168
159
  // Service Unavailable - scheduling failed
169
160
  throw new errors_js_1.LangSmithSandboxCreationError(data.message, data.errorType || "Unschedulable");
170
161
  }
171
- // Fall through to generic handling
172
- return handleClientHttpError(response);
173
- }
174
- /**
175
- * Handle HTTP errors specific to volume creation.
176
- *
177
- * Maps API error responses to specific exception types:
178
- * - 429: LangSmithQuotaExceededError (org limits exceeded)
179
- * - 503: LangSmithSandboxCreationError (provisioning failed)
180
- * - 504: LangSmithResourceTimeoutError (volume didn't become ready in time)
181
- * - Other: Falls through to generic error handling
182
- */
183
- async function handleVolumeCreationError(response) {
184
- const status = response.status;
185
- const data = await parseErrorResponse(response);
186
- if (status === 429) {
187
- // Organization quota exceeded - extract type or default to volume_count
188
- const quotaType = extractQuotaType(data.message) ?? "unknown";
189
- throw new errors_js_1.LangSmithQuotaExceededError(data.message, quotaType);
190
- }
191
- else if (status === 503) {
192
- // Provisioning failed (invalid storage class, quota exceeded)
193
- throw new errors_js_1.LangSmithSandboxCreationError(data.message, "VolumeProvisioning");
194
- }
195
- else if (status === 504) {
196
- // Timeout - volume didn't become ready in time
197
- throw new errors_js_1.LangSmithResourceTimeoutError(data.message, "volume");
198
- }
199
- // Fall through to generic handling
200
- return handleClientHttpError(response);
201
- }
202
- /**
203
- * Handle HTTP errors specific to pool creation/update.
204
- *
205
- * Maps API error responses to specific exception types:
206
- * - 400: LangSmithResourceNotFoundError or LangSmithValidationError (template has volumes)
207
- * - 409: LangSmithResourceAlreadyExistsError
208
- * - 429: LangSmithQuotaExceededError (org limits exceeded)
209
- * - 504: LangSmithResourceTimeoutError (timeout waiting for ready replicas)
210
- * - Other: Falls through to generic error handling
211
- */
212
- async function handlePoolError(response) {
213
- const status = response.status;
214
- const data = await parseErrorResponse(response);
215
- const errorType = data.errorType;
216
- if (status === 400) {
217
- // Check the error type to determine the specific exception
218
- if (errorType === "TemplateNotFound") {
219
- throw new errors_js_1.LangSmithResourceNotFoundError(data.message, "template");
220
- }
221
- else if (errorType === "LangSmithValidationError") {
222
- // Template has volumes attached
223
- throw new errors_js_1.LangSmithValidationError(data.message, undefined, undefined, errorType);
224
- }
225
- // Generic bad request - fall through to generic handling
226
- }
227
- else if (status === 409) {
228
- // Pool already exists
229
- throw new errors_js_1.LangSmithResourceAlreadyExistsError(data.message, "pool");
230
- }
231
- else if (status === 429) {
232
- // Organization quota exceeded - extract type or default to pool_count
233
- const quotaType = extractQuotaType(data.message) ?? "unknown";
234
- throw new errors_js_1.LangSmithQuotaExceededError(data.message, quotaType);
235
- }
236
- else if (status === 504) {
237
- // Timeout waiting for pool to be ready
238
- throw new errors_js_1.LangSmithResourceTimeoutError(data.message, "pool");
239
- }
240
- // Fall through to generic handling
241
- return handleClientHttpError(response);
162
+ // Fall through to generic handling — pass clone since body is already consumed
163
+ return handleClientHttpError(clonedResponse);
242
164
  }
243
165
  /**
244
166
  * Handle HTTP errors and raise appropriate exceptions (for client operations).
245
167
  */
246
168
  async function handleClientHttpError(response) {
169
+ const status = response.status;
170
+ // Only clone when we need to read the body twice (status 422 reads it again
171
+ // for structured validation details after parseErrorResponse consumes it).
172
+ const clonedResponse = status === 422 ? response.clone() : null;
247
173
  const data = await parseErrorResponse(response);
248
174
  const message = data.message;
249
175
  const errorType = data.errorType;
250
- const status = response.status;
251
176
  if (status === 401 || status === 403) {
252
177
  throw new errors_js_1.LangSmithSandboxAuthenticationError(message);
253
178
  }
@@ -255,8 +180,7 @@ async function handleClientHttpError(response) {
255
180
  throw new errors_js_1.LangSmithResourceNotFoundError(message);
256
181
  }
257
182
  // Handle validation errors (invalid resource values, formats, etc.)
258
- if (status === 422) {
259
- const clonedResponse = response.clone();
183
+ if (status === 422 && clonedResponse) {
260
184
  const details = await parseValidationError(clonedResponse);
261
185
  const field = details[0]?.loc?.slice(-1)[0];
262
186
  throw new errors_js_1.LangSmithValidationError(message, field, details);
@@ -321,17 +245,3 @@ async function handleSandboxHttpError(response) {
321
245
  }
322
246
  throw new errors_js_1.LangSmithSandboxError(message);
323
247
  }
324
- /**
325
- * Handle 409 Conflict errors for resource name conflicts.
326
- */
327
- async function handleConflictError(response, resourceType) {
328
- const data = await parseErrorResponse(response);
329
- throw new errors_js_1.LangSmithResourceNameConflictError(data.message, resourceType);
330
- }
331
- /**
332
- * Handle 409 Conflict errors for resources in use.
333
- */
334
- async function handleResourceInUseError(response, resourceType) {
335
- const data = await parseErrorResponse(response);
336
- throw new errors_js_1.LangSmithResourceInUseError(data.message, resourceType);
337
- }
@@ -49,27 +49,6 @@ export declare function extractQuotaType(message: string): string | undefined;
49
49
  * - Other: Falls through to generic error handling
50
50
  */
51
51
  export declare function handleSandboxCreationError(response: Response): Promise<never>;
52
- /**
53
- * Handle HTTP errors specific to volume creation.
54
- *
55
- * Maps API error responses to specific exception types:
56
- * - 429: LangSmithQuotaExceededError (org limits exceeded)
57
- * - 503: LangSmithSandboxCreationError (provisioning failed)
58
- * - 504: LangSmithResourceTimeoutError (volume didn't become ready in time)
59
- * - Other: Falls through to generic error handling
60
- */
61
- export declare function handleVolumeCreationError(response: Response): Promise<never>;
62
- /**
63
- * Handle HTTP errors specific to pool creation/update.
64
- *
65
- * Maps API error responses to specific exception types:
66
- * - 400: LangSmithResourceNotFoundError or LangSmithValidationError (template has volumes)
67
- * - 409: LangSmithResourceAlreadyExistsError
68
- * - 429: LangSmithQuotaExceededError (org limits exceeded)
69
- * - 504: LangSmithResourceTimeoutError (timeout waiting for ready replicas)
70
- * - Other: Falls through to generic error handling
71
- */
72
- export declare function handlePoolError(response: Response): Promise<never>;
73
52
  /**
74
53
  * Handle HTTP errors and raise appropriate exceptions (for client operations).
75
54
  */
@@ -87,12 +66,4 @@ export declare function handleClientHttpError(response: Response): Promise<never
87
66
  * - 403 -> LangSmithSandboxOperationError (permission denied)
88
67
  */
89
68
  export declare function handleSandboxHttpError(response: Response): Promise<never>;
90
- /**
91
- * Handle 409 Conflict errors for resource name conflicts.
92
- */
93
- export declare function handleConflictError(response: Response, resourceType: string): Promise<never>;
94
- /**
95
- * Handle 409 Conflict errors for resources in use.
96
- */
97
- export declare function handleResourceInUseError(response: Response, resourceType: string): Promise<never>;
98
69
  export {};
@@ -4,7 +4,7 @@
4
4
  * These functions are used to parse error responses and raise appropriate
5
5
  * exceptions. They contain no I/O operations.
6
6
  */
7
- import { LangSmithQuotaExceededError, LangSmithResourceAlreadyExistsError, LangSmithResourceInUseError, LangSmithResourceNameConflictError, LangSmithResourceNotFoundError, LangSmithResourceTimeoutError, LangSmithSandboxAPIError, LangSmithSandboxAuthenticationError, LangSmithSandboxError, LangSmithSandboxConnectionError, LangSmithSandboxCreationError, LangSmithSandboxNotReadyError, LangSmithSandboxOperationError, LangSmithValidationError, } from "./errors.js";
7
+ import { LangSmithQuotaExceededError, LangSmithResourceNotFoundError, LangSmithResourceTimeoutError, LangSmithSandboxAPIError, LangSmithSandboxAuthenticationError, LangSmithSandboxError, LangSmithSandboxConnectionError, LangSmithSandboxCreationError, LangSmithSandboxNotReadyError, LangSmithSandboxOperationError, LangSmithValidationError, } from "./errors.js";
8
8
  // =============================================================================
9
9
  // Input validation
10
10
  // =============================================================================
@@ -102,11 +102,6 @@ export function extractQuotaType(message) {
102
102
  else if (messageLower.includes("memory")) {
103
103
  return "memory";
104
104
  }
105
- // Check for volume count quota
106
- else if (messageLower.includes("volume") &&
107
- (messageLower.includes("count") || messageLower.includes("limit"))) {
108
- return "volume_count";
109
- }
110
105
  else if (messageLower.includes("storage")) {
111
106
  return "storage";
112
107
  }
@@ -127,6 +122,7 @@ export function extractQuotaType(message) {
127
122
  */
128
123
  export async function handleSandboxCreationError(response) {
129
124
  const status = response.status;
125
+ const clonedResponse = response.clone();
130
126
  const data = await parseErrorResponse(response);
131
127
  if (status === 408) {
132
128
  // Timeout - include the message which contains last known status
@@ -134,7 +130,6 @@ export async function handleSandboxCreationError(response) {
134
130
  }
135
131
  else if (status === 422) {
136
132
  // Check if this is a Pydantic validation error (bad input) vs creation error
137
- const clonedResponse = response.clone();
138
133
  const details = await parseValidationError(clonedResponse);
139
134
  if (details.length > 0 && details.some((d) => d.type === "value_error")) {
140
135
  // Pydantic validation error (bad input - exceeds server limits)
@@ -155,86 +150,20 @@ export async function handleSandboxCreationError(response) {
155
150
  // Service Unavailable - scheduling failed
156
151
  throw new LangSmithSandboxCreationError(data.message, data.errorType || "Unschedulable");
157
152
  }
158
- // Fall through to generic handling
159
- return handleClientHttpError(response);
160
- }
161
- /**
162
- * Handle HTTP errors specific to volume creation.
163
- *
164
- * Maps API error responses to specific exception types:
165
- * - 429: LangSmithQuotaExceededError (org limits exceeded)
166
- * - 503: LangSmithSandboxCreationError (provisioning failed)
167
- * - 504: LangSmithResourceTimeoutError (volume didn't become ready in time)
168
- * - Other: Falls through to generic error handling
169
- */
170
- export async function handleVolumeCreationError(response) {
171
- const status = response.status;
172
- const data = await parseErrorResponse(response);
173
- if (status === 429) {
174
- // Organization quota exceeded - extract type or default to volume_count
175
- const quotaType = extractQuotaType(data.message) ?? "unknown";
176
- throw new LangSmithQuotaExceededError(data.message, quotaType);
177
- }
178
- else if (status === 503) {
179
- // Provisioning failed (invalid storage class, quota exceeded)
180
- throw new LangSmithSandboxCreationError(data.message, "VolumeProvisioning");
181
- }
182
- else if (status === 504) {
183
- // Timeout - volume didn't become ready in time
184
- throw new LangSmithResourceTimeoutError(data.message, "volume");
185
- }
186
- // Fall through to generic handling
187
- return handleClientHttpError(response);
188
- }
189
- /**
190
- * Handle HTTP errors specific to pool creation/update.
191
- *
192
- * Maps API error responses to specific exception types:
193
- * - 400: LangSmithResourceNotFoundError or LangSmithValidationError (template has volumes)
194
- * - 409: LangSmithResourceAlreadyExistsError
195
- * - 429: LangSmithQuotaExceededError (org limits exceeded)
196
- * - 504: LangSmithResourceTimeoutError (timeout waiting for ready replicas)
197
- * - Other: Falls through to generic error handling
198
- */
199
- export async function handlePoolError(response) {
200
- const status = response.status;
201
- const data = await parseErrorResponse(response);
202
- const errorType = data.errorType;
203
- if (status === 400) {
204
- // Check the error type to determine the specific exception
205
- if (errorType === "TemplateNotFound") {
206
- throw new LangSmithResourceNotFoundError(data.message, "template");
207
- }
208
- else if (errorType === "LangSmithValidationError") {
209
- // Template has volumes attached
210
- throw new LangSmithValidationError(data.message, undefined, undefined, errorType);
211
- }
212
- // Generic bad request - fall through to generic handling
213
- }
214
- else if (status === 409) {
215
- // Pool already exists
216
- throw new LangSmithResourceAlreadyExistsError(data.message, "pool");
217
- }
218
- else if (status === 429) {
219
- // Organization quota exceeded - extract type or default to pool_count
220
- const quotaType = extractQuotaType(data.message) ?? "unknown";
221
- throw new LangSmithQuotaExceededError(data.message, quotaType);
222
- }
223
- else if (status === 504) {
224
- // Timeout waiting for pool to be ready
225
- throw new LangSmithResourceTimeoutError(data.message, "pool");
226
- }
227
- // Fall through to generic handling
228
- return handleClientHttpError(response);
153
+ // Fall through to generic handling — pass clone since body is already consumed
154
+ return handleClientHttpError(clonedResponse);
229
155
  }
230
156
  /**
231
157
  * Handle HTTP errors and raise appropriate exceptions (for client operations).
232
158
  */
233
159
  export async function handleClientHttpError(response) {
160
+ const status = response.status;
161
+ // Only clone when we need to read the body twice (status 422 reads it again
162
+ // for structured validation details after parseErrorResponse consumes it).
163
+ const clonedResponse = status === 422 ? response.clone() : null;
234
164
  const data = await parseErrorResponse(response);
235
165
  const message = data.message;
236
166
  const errorType = data.errorType;
237
- const status = response.status;
238
167
  if (status === 401 || status === 403) {
239
168
  throw new LangSmithSandboxAuthenticationError(message);
240
169
  }
@@ -242,8 +171,7 @@ export async function handleClientHttpError(response) {
242
171
  throw new LangSmithResourceNotFoundError(message);
243
172
  }
244
173
  // Handle validation errors (invalid resource values, formats, etc.)
245
- if (status === 422) {
246
- const clonedResponse = response.clone();
174
+ if (status === 422 && clonedResponse) {
247
175
  const details = await parseValidationError(clonedResponse);
248
176
  const field = details[0]?.loc?.slice(-1)[0];
249
177
  throw new LangSmithValidationError(message, field, details);
@@ -308,17 +236,3 @@ export async function handleSandboxHttpError(response) {
308
236
  }
309
237
  throw new LangSmithSandboxError(message);
310
238
  }
311
- /**
312
- * Handle 409 Conflict errors for resource name conflicts.
313
- */
314
- export async function handleConflictError(response, resourceType) {
315
- const data = await parseErrorResponse(response);
316
- throw new LangSmithResourceNameConflictError(data.message, resourceType);
317
- }
318
- /**
319
- * Handle 409 Conflict errors for resources in use.
320
- */
321
- export async function handleResourceInUseError(response, resourceType) {
322
- const data = await parseErrorResponse(response);
323
- throw new LangSmithResourceInUseError(data.message, resourceType);
324
- }
@@ -12,7 +12,12 @@
12
12
  * // Uses LANGSMITH_ENDPOINT and LANGSMITH_API_KEY from environment
13
13
  * const client = new SandboxClient();
14
14
  *
15
- * const sandbox = await client.createSandbox("python-sandbox");
15
+ * const snapshot = await client.createSnapshot(
16
+ * "python",
17
+ * "python:3.12-slim",
18
+ * 1_073_741_824
19
+ * );
20
+ * const sandbox = await client.createSandbox(snapshot.id);
16
21
  * try {
17
22
  * const result = await sandbox.run("python --version");
18
23
  * console.log(result.stdout);
@@ -11,7 +11,12 @@
11
11
  * // Uses LANGSMITH_ENDPOINT and LANGSMITH_API_KEY from environment
12
12
  * const client = new SandboxClient();
13
13
  *
14
- * const sandbox = await client.createSandbox("python-sandbox");
14
+ * const snapshot = await client.createSnapshot(
15
+ * "python",
16
+ * "python:3.12-slim",
17
+ * 1_073_741_824
18
+ * );
19
+ * const sandbox = await client.createSandbox(snapshot.id);
15
20
  * try {
16
21
  * const result = await sandbox.run("python --version");
17
22
  * console.log(result.stdout);
@@ -25,5 +30,5 @@
25
30
  export { SandboxClient } from "./client.js";
26
31
  export { Sandbox } from "./sandbox.js";
27
32
  export { CommandHandle } from "./command_handle.js";
28
- export type { ExecutionResult, OutputChunk, WsMessage, WsRunOptions, ResourceSpec, ResourceStatus, VolumeMountSpec, Volume, SandboxTemplate, Pool, SandboxData, SandboxClientConfig, RunOptions, CreateSandboxOptions, UpdateSandboxOptions, WaitForSandboxOptions, CreateVolumeOptions, CreateTemplateOptions, UpdateTemplateOptions, CreatePoolOptions, UpdateVolumeOptions, UpdatePoolOptions, } from "./types.js";
33
+ export type { ExecutionResult, OutputChunk, WsMessage, WsRunOptions, ResourceStatus, Snapshot, SandboxData, SandboxClientConfig, RunOptions, CreateSandboxOptions, SandboxAccessControl, SandboxProxyConfig, CreateSnapshotOptions, CaptureSnapshotOptions, ListSnapshotsOptions, WaitForSnapshotOptions, StartSandboxOptions, UpdateSandboxOptions, WaitForSandboxOptions, } from "./types.js";
29
34
  export { LangSmithSandboxError, LangSmithSandboxAPIError, LangSmithSandboxAuthenticationError, LangSmithSandboxConnectionError, LangSmithSandboxServerReloadError, LangSmithResourceNotFoundError, LangSmithResourceTimeoutError, LangSmithResourceInUseError, LangSmithResourceAlreadyExistsError, LangSmithResourceNameConflictError, LangSmithValidationError, LangSmithQuotaExceededError, LangSmithResourceCreationError, LangSmithSandboxCreationError, LangSmithSandboxNotReadyError, LangSmithSandboxOperationError, LangSmithCommandTimeoutError, LangSmithDataplaneNotConfiguredError, } from "./errors.js";
@@ -11,7 +11,12 @@
11
11
  * // Uses LANGSMITH_ENDPOINT and LANGSMITH_API_KEY from environment
12
12
  * const client = new SandboxClient();
13
13
  *
14
- * const sandbox = await client.createSandbox("python-sandbox");
14
+ * const snapshot = await client.createSnapshot(
15
+ * "python",
16
+ * "python:3.12-slim",
17
+ * 1_073_741_824
18
+ * );
19
+ * const sandbox = await client.createSandbox(snapshot.id);
15
20
  * try {
16
21
  * const result = await sandbox.run("python --version");
17
22
  * console.log(result.stdout);
@@ -17,7 +17,7 @@ const ws_execute_js_1 = require("./ws_execute.cjs");
17
17
  *
18
18
  * @example
19
19
  * ```typescript
20
- * const sandbox = await client.createSandbox("python-sandbox");
20
+ * const sandbox = await client.createSandbox(snapshot.id);
21
21
  * try {
22
22
  * const result = await sandbox.run("python --version");
23
23
  * console.log(result.stdout);
@@ -38,13 +38,6 @@ class Sandbox {
38
38
  writable: true,
39
39
  value: void 0
40
40
  });
41
- /** Name of the template used to create this sandbox. */
42
- Object.defineProperty(this, "template_name", {
43
- enumerable: true,
44
- configurable: true,
45
- writable: true,
46
- value: void 0
47
- });
48
41
  /** URL for data plane operations (file I/O, command execution). */
49
42
  Object.defineProperty(this, "dataplane_url", {
50
43
  enumerable: true,
@@ -52,7 +45,7 @@ class Sandbox {
52
45
  writable: true,
53
46
  value: void 0
54
47
  });
55
- /** Provisioning status ("provisioning", "ready", "failed"). */
48
+ /** Provisioning status ("provisioning", "ready", "failed", "stopped"). */
56
49
  Object.defineProperty(this, "status", {
57
50
  enumerable: true,
58
51
  configurable: true,
@@ -94,7 +87,11 @@ class Sandbox {
94
87
  writable: true,
95
88
  value: void 0
96
89
  });
97
- /** Idle timeout TTL in seconds (`0` means disabled). */
90
+ /**
91
+ * Idle timeout TTL in seconds (`0` means disabled).
92
+ * New sandboxes receive a server-side default of `600` seconds (10 minutes)
93
+ * when the caller did not set `idleTtlSeconds` explicitly.
94
+ */
98
95
  Object.defineProperty(this, "idle_ttl_seconds", {
99
96
  enumerable: true,
100
97
  configurable: true,
@@ -108,6 +105,34 @@ class Sandbox {
108
105
  writable: true,
109
106
  value: void 0
110
107
  });
108
+ /** Snapshot ID used to create this sandbox. */
109
+ Object.defineProperty(this, "snapshot_id", {
110
+ enumerable: true,
111
+ configurable: true,
112
+ writable: true,
113
+ value: void 0
114
+ });
115
+ /** Number of vCPUs allocated. */
116
+ Object.defineProperty(this, "vCpus", {
117
+ enumerable: true,
118
+ configurable: true,
119
+ writable: true,
120
+ value: void 0
121
+ });
122
+ /** Memory allocation in bytes. */
123
+ Object.defineProperty(this, "mem_bytes", {
124
+ enumerable: true,
125
+ configurable: true,
126
+ writable: true,
127
+ value: void 0
128
+ });
129
+ /** Root filesystem capacity in bytes. */
130
+ Object.defineProperty(this, "fs_capacity_bytes", {
131
+ enumerable: true,
132
+ configurable: true,
133
+ writable: true,
134
+ value: void 0
135
+ });
111
136
  Object.defineProperty(this, "_client", {
112
137
  enumerable: true,
113
138
  configurable: true,
@@ -115,7 +140,6 @@ class Sandbox {
115
140
  value: void 0
116
141
  });
117
142
  this.name = data.name;
118
- this.template_name = data.template_name;
119
143
  this.dataplane_url = data.dataplane_url;
120
144
  this.status = data.status;
121
145
  this.status_message = data.status_message;
@@ -125,6 +149,10 @@ class Sandbox {
125
149
  this.ttl_seconds = data.ttl_seconds;
126
150
  this.idle_ttl_seconds = data.idle_ttl_seconds;
127
151
  this.expires_at = data.expires_at;
152
+ this.snapshot_id = data.snapshot_id;
153
+ this.vCpus = data.vcpus;
154
+ this.mem_bytes = data.mem_bytes;
155
+ this.fs_capacity_bytes = data.fs_capacity_bytes;
128
156
  this._client = client;
129
157
  }
130
158
  /**
@@ -177,7 +205,7 @@ class Sandbox {
177
205
  catch (e) {
178
206
  // Fall back to HTTP on connection errors or missing ws package
179
207
  const name = e != null && typeof e === "object" ? e.name : "";
180
- const message = e != null && typeof e === "object" ? e.message ?? "" : "";
208
+ const message = e != null && typeof e === "object" ? (e.message ?? "") : "";
181
209
  if (name === "LangSmithSandboxConnectionError" ||
182
210
  name === "LangSmithSandboxServerReloadError" ||
183
211
  message.includes("'ws' package")) {
@@ -328,7 +356,7 @@ class Sandbox {
328
356
  *
329
357
  * @example
330
358
  * ```typescript
331
- * const sandbox = await client.createSandbox("python-sandbox");
359
+ * const sandbox = await client.createSandbox(snapshot.id);
332
360
  * try {
333
361
  * await sandbox.run("echo hello");
334
362
  * } finally {
@@ -339,5 +367,35 @@ class Sandbox {
339
367
  async delete() {
340
368
  await this._client.deleteSandbox(this.name);
341
369
  }
370
+ /**
371
+ * Start a stopped sandbox and wait until ready.
372
+ *
373
+ * Updates this sandbox's status and dataplane_url in place.
374
+ *
375
+ * @param timeout - Timeout in seconds when waiting for ready. Default: 120.
376
+ */
377
+ async start(options = {}) {
378
+ const refreshed = await this._client.startSandbox(this.name, options);
379
+ this.status = refreshed.status;
380
+ this.dataplane_url = refreshed.dataplane_url;
381
+ }
382
+ /**
383
+ * Stop a running sandbox (preserves sandbox files for later restart).
384
+ */
385
+ async stop() {
386
+ await this._client.stopSandbox(this.name);
387
+ this.status = "stopped";
388
+ this.dataplane_url = undefined;
389
+ }
390
+ /**
391
+ * Capture a snapshot from this sandbox.
392
+ *
393
+ * @param name - Snapshot name.
394
+ * @param options - Capture options (timeout).
395
+ * @returns Snapshot in "ready" status.
396
+ */
397
+ async captureSnapshot(name, options = {}) {
398
+ return this._client.captureSnapshot(this.name, name, options);
399
+ }
342
400
  }
343
401
  exports.Sandbox = Sandbox;