langsmith 0.5.26 → 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.
package/dist/client.cjs CHANGED
@@ -51,6 +51,12 @@ const fsUtils = __importStar(require("./utils/fs.cjs"));
51
51
  const fetch_js_1 = require("./singletons/fetch.cjs");
52
52
  const index_js_3 = require("./utils/fast-safe-stringify/index.cjs");
53
53
  const serialize_worker_js_1 = require("./utils/serialize_worker.cjs");
54
+ function assertPullPublicPromptAllowed(promptIdentifier, dangerouslyPullPublicPrompt) {
55
+ const [owner] = (0, prompts_js_1.parseHubIdentifier)(promptIdentifier);
56
+ if (owner !== "-" && !dangerouslyPullPublicPrompt) {
57
+ throw new Error("Pulling a public prompt by owner/name is disabled by default because prompts may contain untrusted serialized LangChain objects. If you trust this prompt, set `dangerouslyPullPublicPrompt: true` to acknowledge the risk.");
58
+ }
59
+ }
54
60
  /**
55
61
  * Catches timestamps without a timezone suffix.
56
62
  */
@@ -190,19 +196,11 @@ class AutoBatchQueue {
190
196
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise
191
197
  itemPromiseResolve = resolve;
192
198
  });
193
- // By default we compute the exact serialized size here by stringifying
194
- // the payload. This is expensive: JSON.stringify on large payloads
195
- // blocks the event loop on the user's hot path.
196
- //
197
- // Opting into LANGSMITH_PERF_OPTIMIZATION=true switches to a cheap
198
- // structural estimate instead. The estimate is only used for soft
199
- // memory accounting (queue size limit and downstream async caller
200
- // memory tracking), never for anything correctness-critical -- the
201
- // real serialization still happens later, off the hot path, when the
202
- // batch is assembled for sending.
203
- const size = (0, env_js_1.getLangSmithEnvironmentVariable)("PERF_OPTIMIZATION") === "true"
204
- ? (0, index_js_3.estimateSerializedSize)(item.item).size
205
- : (0, index_js_3.serialize)(item.item, `Serializing run with id: ${item.item.id}`).length;
199
+ // Use a cheap structural estimate for soft memory accounting (queue size
200
+ // limit and downstream async caller memory tracking). The exact
201
+ // serialization still happens later, off the hot path, when the batch is
202
+ // assembled for sending.
203
+ const size = (0, index_js_3.estimateSerializedSize)(item.item).size;
206
204
  // Check if adding this item would exceed the size limit
207
205
  // Allow the run if the queue is empty (to support large single traces)
208
206
  if (this.sizeBytes + size > this.maxSizeBytes && this.items.length > 0) {
@@ -274,11 +272,9 @@ class Client {
274
272
  }
275
273
  /**
276
274
  * Serialize a payload for tracing, optionally offloading the work to a
277
- * Node worker thread when LANGSMITH_PERF_OPTIMIZATION=true and the runtime
278
- * supports worker_threads.
275
+ * Node worker thread when the runtime supports worker_threads.
279
276
  *
280
277
  * Falls back to synchronous serialization when:
281
- * - the perf flag is off
282
278
  * - manualFlushMode is enabled (serverless: worker boot cost > benefit)
283
279
  * - worker_threads is unavailable (non-Node runtimes)
284
280
  * - the payload contains values that can't be structured-cloned across
@@ -294,8 +290,7 @@ class Client {
294
290
  });
295
291
  }
296
292
  async _serializeBody(payload, errorContext) {
297
- const perfOptIn = (0, env_js_1.getLangSmithEnvironmentVariable)("PERF_OPTIMIZATION") === "true";
298
- if (!perfOptIn || this.manualFlushMode) {
293
+ if (this.manualFlushMode) {
299
294
  return (0, index_js_3.serialize)(payload, errorContext);
300
295
  }
301
296
  // Shape-aware gate: worker offload pays for itself only when the
@@ -4498,7 +4493,24 @@ class Client {
4498
4493
  hub_model_provider: result.model_provider,
4499
4494
  };
4500
4495
  }
4496
+ /**
4497
+ * Pull a prompt commit from the LangSmith API.
4498
+ *
4499
+ * Public prompts referenced by owner/name cross a trust boundary because the
4500
+ * prompt manifest may contain serialized LangChain objects and configuration
4501
+ * that affect runtime behavior. For example, a prompt can intentionally
4502
+ * configure a model with a custom base URL, headers, model name, or other
4503
+ * constructor arguments. These are supported features, but they also mean the
4504
+ * prompt contents should be treated as executable configuration rather than
4505
+ * plain text.
4506
+ *
4507
+ * Set `dangerouslyPullPublicPrompt: true` only after reviewing and trusting
4508
+ * the prompt contents, not merely the publishing account. Prompts from your
4509
+ * own or your organization's account can still be unsafe if that account or
4510
+ * prompt was compromised.
4511
+ */
4501
4512
  async pullPromptCommit(promptIdentifier, options) {
4513
+ assertPullPublicPromptAllowed(promptIdentifier, options?.dangerouslyPullPublicPrompt);
4502
4514
  // Check cache first if not skipped
4503
4515
  const refreshFunc = this._fetchPromptFromApi.bind(this, promptIdentifier, options);
4504
4516
  if (!options?.skipCache && this._promptCache) {
@@ -4518,12 +4530,26 @@ class Client {
4518
4530
  /**
4519
4531
  * This method should not be used directly, use `import { pull } from "langchain/hub"` instead.
4520
4532
  * Using this method directly returns the JSON string of the prompt rather than a LangChain object.
4533
+ *
4534
+ * Public prompts referenced by owner/name cross a trust boundary because the
4535
+ * prompt manifest may contain serialized LangChain objects and configuration
4536
+ * that affect runtime behavior. For example, a prompt can intentionally
4537
+ * configure a model with a custom base URL, headers, model name, or other
4538
+ * constructor arguments. These are supported features, but they also mean the
4539
+ * prompt contents should be treated as executable configuration rather than
4540
+ * plain text.
4541
+ *
4542
+ * Set `dangerouslyPullPublicPrompt: true` only after reviewing and trusting
4543
+ * the prompt contents, not merely the publishing account. Prompts from your
4544
+ * own or your organization's account can still be unsafe if that account or
4545
+ * prompt was compromised.
4521
4546
  * @private
4522
4547
  */
4523
4548
  async _pullPrompt(promptIdentifier, options) {
4524
4549
  const promptObject = await this.pullPromptCommit(promptIdentifier, {
4525
4550
  includeModel: options?.includeModel,
4526
4551
  skipCache: options?.skipCache,
4552
+ dangerouslyPullPublicPrompt: options?.dangerouslyPullPublicPrompt,
4527
4553
  });
4528
4554
  const prompt = JSON.stringify(promptObject.manifest);
4529
4555
  return prompt;
package/dist/client.d.ts CHANGED
@@ -442,11 +442,9 @@ export declare class Client implements LangSmithTracingClientInterface {
442
442
  private get _fetch();
443
443
  /**
444
444
  * Serialize a payload for tracing, optionally offloading the work to a
445
- * Node worker thread when LANGSMITH_PERF_OPTIMIZATION=true and the runtime
446
- * supports worker_threads.
445
+ * Node worker thread when the runtime supports worker_threads.
447
446
  *
448
447
  * Falls back to synchronous serialization when:
449
- * - the perf flag is off
450
448
  * - manualFlushMode is enabled (serverless: worker boot cost > benefit)
451
449
  * - worker_threads is unavailable (non-Node runtimes)
452
450
  * - the payload contains values that can't be structured-cloned across
@@ -1322,18 +1320,57 @@ export declare class Client implements LangSmithTracingClientInterface {
1322
1320
  * Fetch a prompt commit directly from the API (bypassing cache).
1323
1321
  */
1324
1322
  private _fetchPromptFromApi;
1323
+ /**
1324
+ * Pull a prompt commit from the LangSmith API.
1325
+ *
1326
+ * Public prompts referenced by owner/name cross a trust boundary because the
1327
+ * prompt manifest may contain serialized LangChain objects and configuration
1328
+ * that affect runtime behavior. For example, a prompt can intentionally
1329
+ * configure a model with a custom base URL, headers, model name, or other
1330
+ * constructor arguments. These are supported features, but they also mean the
1331
+ * prompt contents should be treated as executable configuration rather than
1332
+ * plain text.
1333
+ *
1334
+ * Set `dangerouslyPullPublicPrompt: true` only after reviewing and trusting
1335
+ * the prompt contents, not merely the publishing account. Prompts from your
1336
+ * own or your organization's account can still be unsafe if that account or
1337
+ * prompt was compromised.
1338
+ */
1325
1339
  pullPromptCommit(promptIdentifier: string, options?: {
1326
1340
  includeModel?: boolean;
1327
1341
  skipCache?: boolean;
1342
+ /**
1343
+ * Set to `true` to allow pulling a public prompt by owner/name, for
1344
+ * example `username/promptname`. Defaults to `false`.
1345
+ */
1346
+ dangerouslyPullPublicPrompt?: boolean;
1328
1347
  }): Promise<PromptCommit>;
1329
1348
  /**
1330
1349
  * This method should not be used directly, use `import { pull } from "langchain/hub"` instead.
1331
1350
  * Using this method directly returns the JSON string of the prompt rather than a LangChain object.
1351
+ *
1352
+ * Public prompts referenced by owner/name cross a trust boundary because the
1353
+ * prompt manifest may contain serialized LangChain objects and configuration
1354
+ * that affect runtime behavior. For example, a prompt can intentionally
1355
+ * configure a model with a custom base URL, headers, model name, or other
1356
+ * constructor arguments. These are supported features, but they also mean the
1357
+ * prompt contents should be treated as executable configuration rather than
1358
+ * plain text.
1359
+ *
1360
+ * Set `dangerouslyPullPublicPrompt: true` only after reviewing and trusting
1361
+ * the prompt contents, not merely the publishing account. Prompts from your
1362
+ * own or your organization's account can still be unsafe if that account or
1363
+ * prompt was compromised.
1332
1364
  * @private
1333
1365
  */
1334
1366
  _pullPrompt(promptIdentifier: string, options?: {
1335
1367
  includeModel?: boolean;
1336
1368
  skipCache?: boolean;
1369
+ /**
1370
+ * Set to `true` to allow pulling a public prompt by owner/name, for
1371
+ * example `username/promptname`. Defaults to `false`.
1372
+ */
1373
+ dangerouslyPullPublicPrompt?: boolean;
1337
1374
  }): Promise<any>;
1338
1375
  pushPrompt(promptIdentifier: string, options?: {
1339
1376
  object?: any;
package/dist/client.js CHANGED
@@ -14,6 +14,12 @@ import * as fsUtils from "./utils/fs.js";
14
14
  import { _shouldStreamForGlobalFetchImplementation, _getFetchImplementation, } from "./singletons/fetch.js";
15
15
  import { serialize as serializePayloadForTracing, estimateSerializedSize, } from "./utils/fast-safe-stringify/index.js";
16
16
  import { getSharedSerializeWorker, hasLargeString, } from "./utils/serialize_worker.js";
17
+ function assertPullPublicPromptAllowed(promptIdentifier, dangerouslyPullPublicPrompt) {
18
+ const [owner] = parseHubIdentifier(promptIdentifier);
19
+ if (owner !== "-" && !dangerouslyPullPublicPrompt) {
20
+ throw new Error("Pulling a public prompt by owner/name is disabled by default because prompts may contain untrusted serialized LangChain objects. If you trust this prompt, set `dangerouslyPullPublicPrompt: true` to acknowledge the risk.");
21
+ }
22
+ }
17
23
  /**
18
24
  * Catches timestamps without a timezone suffix.
19
25
  */
@@ -153,19 +159,11 @@ export class AutoBatchQueue {
153
159
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise
154
160
  itemPromiseResolve = resolve;
155
161
  });
156
- // By default we compute the exact serialized size here by stringifying
157
- // the payload. This is expensive: JSON.stringify on large payloads
158
- // blocks the event loop on the user's hot path.
159
- //
160
- // Opting into LANGSMITH_PERF_OPTIMIZATION=true switches to a cheap
161
- // structural estimate instead. The estimate is only used for soft
162
- // memory accounting (queue size limit and downstream async caller
163
- // memory tracking), never for anything correctness-critical -- the
164
- // real serialization still happens later, off the hot path, when the
165
- // batch is assembled for sending.
166
- const size = getLangSmithEnvironmentVariable("PERF_OPTIMIZATION") === "true"
167
- ? estimateSerializedSize(item.item).size
168
- : serializePayloadForTracing(item.item, `Serializing run with id: ${item.item.id}`).length;
162
+ // Use a cheap structural estimate for soft memory accounting (queue size
163
+ // limit and downstream async caller memory tracking). The exact
164
+ // serialization still happens later, off the hot path, when the batch is
165
+ // assembled for sending.
166
+ const size = estimateSerializedSize(item.item).size;
169
167
  // Check if adding this item would exceed the size limit
170
168
  // Allow the run if the queue is empty (to support large single traces)
171
169
  if (this.sizeBytes + size > this.maxSizeBytes && this.items.length > 0) {
@@ -236,11 +234,9 @@ export class Client {
236
234
  }
237
235
  /**
238
236
  * Serialize a payload for tracing, optionally offloading the work to a
239
- * Node worker thread when LANGSMITH_PERF_OPTIMIZATION=true and the runtime
240
- * supports worker_threads.
237
+ * Node worker thread when the runtime supports worker_threads.
241
238
  *
242
239
  * Falls back to synchronous serialization when:
243
- * - the perf flag is off
244
240
  * - manualFlushMode is enabled (serverless: worker boot cost > benefit)
245
241
  * - worker_threads is unavailable (non-Node runtimes)
246
242
  * - the payload contains values that can't be structured-cloned across
@@ -256,8 +252,7 @@ export class Client {
256
252
  });
257
253
  }
258
254
  async _serializeBody(payload, errorContext) {
259
- const perfOptIn = getLangSmithEnvironmentVariable("PERF_OPTIMIZATION") === "true";
260
- if (!perfOptIn || this.manualFlushMode) {
255
+ if (this.manualFlushMode) {
261
256
  return serializePayloadForTracing(payload, errorContext);
262
257
  }
263
258
  // Shape-aware gate: worker offload pays for itself only when the
@@ -4460,7 +4455,24 @@ export class Client {
4460
4455
  hub_model_provider: result.model_provider,
4461
4456
  };
4462
4457
  }
4458
+ /**
4459
+ * Pull a prompt commit from the LangSmith API.
4460
+ *
4461
+ * Public prompts referenced by owner/name cross a trust boundary because the
4462
+ * prompt manifest may contain serialized LangChain objects and configuration
4463
+ * that affect runtime behavior. For example, a prompt can intentionally
4464
+ * configure a model with a custom base URL, headers, model name, or other
4465
+ * constructor arguments. These are supported features, but they also mean the
4466
+ * prompt contents should be treated as executable configuration rather than
4467
+ * plain text.
4468
+ *
4469
+ * Set `dangerouslyPullPublicPrompt: true` only after reviewing and trusting
4470
+ * the prompt contents, not merely the publishing account. Prompts from your
4471
+ * own or your organization's account can still be unsafe if that account or
4472
+ * prompt was compromised.
4473
+ */
4463
4474
  async pullPromptCommit(promptIdentifier, options) {
4475
+ assertPullPublicPromptAllowed(promptIdentifier, options?.dangerouslyPullPublicPrompt);
4464
4476
  // Check cache first if not skipped
4465
4477
  const refreshFunc = this._fetchPromptFromApi.bind(this, promptIdentifier, options);
4466
4478
  if (!options?.skipCache && this._promptCache) {
@@ -4480,12 +4492,26 @@ export class Client {
4480
4492
  /**
4481
4493
  * This method should not be used directly, use `import { pull } from "langchain/hub"` instead.
4482
4494
  * Using this method directly returns the JSON string of the prompt rather than a LangChain object.
4495
+ *
4496
+ * Public prompts referenced by owner/name cross a trust boundary because the
4497
+ * prompt manifest may contain serialized LangChain objects and configuration
4498
+ * that affect runtime behavior. For example, a prompt can intentionally
4499
+ * configure a model with a custom base URL, headers, model name, or other
4500
+ * constructor arguments. These are supported features, but they also mean the
4501
+ * prompt contents should be treated as executable configuration rather than
4502
+ * plain text.
4503
+ *
4504
+ * Set `dangerouslyPullPublicPrompt: true` only after reviewing and trusting
4505
+ * the prompt contents, not merely the publishing account. Prompts from your
4506
+ * own or your organization's account can still be unsafe if that account or
4507
+ * prompt was compromised.
4483
4508
  * @private
4484
4509
  */
4485
4510
  async _pullPrompt(promptIdentifier, options) {
4486
4511
  const promptObject = await this.pullPromptCommit(promptIdentifier, {
4487
4512
  includeModel: options?.includeModel,
4488
4513
  skipCache: options?.skipCache,
4514
+ dangerouslyPullPublicPrompt: options?.dangerouslyPullPublicPrompt,
4489
4515
  });
4490
4516
  const prompt = JSON.stringify(promptObject.manifest);
4491
4517
  return prompt;
package/dist/index.cjs CHANGED
@@ -18,4 +18,4 @@ Object.defineProperty(exports, "PromptCache", { enumerable: true, get: function
18
18
  Object.defineProperty(exports, "configureGlobalPromptCache", { enumerable: true, get: function () { return index_js_1.configureGlobalPromptCache; } });
19
19
  Object.defineProperty(exports, "promptCacheSingleton", { enumerable: true, get: function () { return index_js_1.promptCacheSingleton; } });
20
20
  // Update using pnpm bump-version
21
- exports.__version__ = "0.5.26";
21
+ exports.__version__ = "0.6.0";
package/dist/index.d.ts CHANGED
@@ -5,4 +5,4 @@ export { overrideFetchImplementation } from "./singletons/fetch.js";
5
5
  export { getDefaultProjectName } from "./utils/project.js";
6
6
  export { uuid7, uuid7FromTime } from "./uuid.js";
7
7
  export { Cache, PromptCache, type CacheConfig, type CacheMetrics, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
8
- export declare const __version__ = "0.5.26";
8
+ export declare const __version__ = "0.6.0";
package/dist/index.js CHANGED
@@ -5,4 +5,4 @@ export { getDefaultProjectName } from "./utils/project.js";
5
5
  export { uuid7, uuid7FromTime } from "./uuid.js";
6
6
  export { Cache, PromptCache, configureGlobalPromptCache, promptCacheSingleton, } from "./utils/prompt_cache/index.js";
7
7
  // Update using pnpm bump-version
8
- export const __version__ = "0.5.26";
8
+ export const __version__ = "0.6.0";
@@ -2,8 +2,7 @@
2
2
  /**
3
3
  * Off-thread serialization using Node worker_threads.
4
4
  *
5
- * Gated behind LANGSMITH_PERF_OPTIMIZATION=true. Falls back silently to
6
- * synchronous serialize() when:
5
+ * Falls back silently to synchronous serialize() when:
7
6
  * - worker_threads is unavailable (browsers, Deno, Bun without compat,
8
7
  * Cloudflare Workers, Vercel Edge, React Native)
9
8
  * - the worker cannot be constructed (bundler/runtime constraints)
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Off-thread serialization using Node worker_threads.
3
3
  *
4
- * Gated behind LANGSMITH_PERF_OPTIMIZATION=true. Falls back silently to
5
- * synchronous serialize() when:
4
+ * Falls back silently to synchronous serialize() when:
6
5
  * - worker_threads is unavailable (browsers, Deno, Bun without compat,
7
6
  * Cloudflare Workers, Vercel Edge, React Native)
8
7
  * - the worker cannot be constructed (bundler/runtime constraints)
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Off-thread serialization using Node worker_threads.
3
3
  *
4
- * Gated behind LANGSMITH_PERF_OPTIMIZATION=true. Falls back silently to
5
- * synchronous serialize() when:
4
+ * Falls back silently to synchronous serialize() when:
6
5
  * - worker_threads is unavailable (browsers, Deno, Bun without compat,
7
6
  * Cloudflare Workers, Vercel Edge, React Native)
8
7
  * - the worker cannot be constructed (bundler/runtime constraints)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.5.26",
3
+ "version": "0.6.0",
4
4
  "description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
5
5
  "packageManager": "pnpm@10.33.0",
6
6
  "files": [