langsmith 0.8.8 → 0.8.10

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 (65) hide show
  1. package/dist/_openapi_client/resources/annotation-queues/annotation-queues.cjs +10 -0
  2. package/dist/_openapi_client/resources/annotation-queues/annotation-queues.d.ts +10 -0
  3. package/dist/_openapi_client/resources/annotation-queues/annotation-queues.js +10 -0
  4. package/dist/_openapi_client/resources/annotation-queues/runs.cjs +13 -1
  5. package/dist/_openapi_client/resources/annotation-queues/runs.d.ts +13 -1
  6. package/dist/_openapi_client/resources/annotation-queues/runs.js +13 -1
  7. package/dist/_openapi_client/resources/datasets/experiment-runs.cjs +2 -0
  8. package/dist/_openapi_client/resources/datasets/experiment-runs.d.ts +2 -0
  9. package/dist/_openapi_client/resources/datasets/experiment-runs.js +2 -0
  10. package/dist/_openapi_client/resources/issues.d.ts +1 -1
  11. package/dist/_openapi_client/resources/public/runs.cjs +9 -7
  12. package/dist/_openapi_client/resources/public/runs.d.ts +8 -6
  13. package/dist/_openapi_client/resources/public/runs.js +9 -7
  14. package/dist/_openapi_client/resources/runs/runs.cjs +11 -6
  15. package/dist/_openapi_client/resources/runs/runs.d.ts +11 -6
  16. package/dist/_openapi_client/resources/runs/runs.js +11 -6
  17. package/dist/_openapi_client/resources/runs/share.cjs +4 -0
  18. package/dist/_openapi_client/resources/runs/share.d.ts +4 -0
  19. package/dist/_openapi_client/resources/runs/share.js +4 -0
  20. package/dist/_openapi_client/resources/threads.cjs +11 -8
  21. package/dist/_openapi_client/resources/threads.d.ts +11 -8
  22. package/dist/_openapi_client/resources/threads.js +11 -8
  23. package/dist/_openapi_client/resources/traces.cjs +6 -3
  24. package/dist/_openapi_client/resources/traces.d.ts +6 -3
  25. package/dist/_openapi_client/resources/traces.js +6 -3
  26. package/dist/client.cjs +295 -24
  27. package/dist/client.d.ts +63 -9
  28. package/dist/client.js +295 -24
  29. package/dist/evaluation/evaluate_comparative.cjs +7 -4
  30. package/dist/evaluation/evaluate_comparative.js +7 -4
  31. package/dist/experimental/vercel/_agent_type.cjs +30 -0
  32. package/dist/experimental/vercel/_agent_type.d.ts +5 -0
  33. package/dist/experimental/vercel/_agent_type.js +26 -0
  34. package/dist/experimental/vercel/telemetry.cjs +2 -7
  35. package/dist/experimental/vercel/telemetry.js +2 -7
  36. package/dist/experimental/vercel/wrap.cjs +5 -11
  37. package/dist/experimental/vercel/wrap.js +6 -12
  38. package/dist/index.cjs +1 -1
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +1 -1
  41. package/dist/sandbox/command_handle.cjs +34 -7
  42. package/dist/sandbox/command_handle.d.ts +1 -0
  43. package/dist/sandbox/command_handle.js +34 -7
  44. package/dist/sandbox/ws_execute.cjs +7 -3
  45. package/dist/sandbox/ws_execute.d.ts +4 -2
  46. package/dist/sandbox/ws_execute.js +7 -3
  47. package/dist/utils/_git.cjs +28 -1
  48. package/dist/utils/_git.js +28 -1
  49. package/dist/utils/ls_agent_type.cjs +31 -0
  50. package/dist/utils/ls_agent_type.d.ts +9 -0
  51. package/dist/utils/ls_agent_type.js +25 -0
  52. package/dist/utils/profiles.cjs +125 -1
  53. package/dist/utils/profiles.d.ts +6 -0
  54. package/dist/utils/profiles.js +124 -1
  55. package/dist/utils/v2_migration.cjs +18 -0
  56. package/dist/utils/v2_migration.d.ts +8 -0
  57. package/dist/utils/v2_migration.js +16 -0
  58. package/dist/utils/warn.cjs +30 -4
  59. package/dist/utils/warn.d.ts +4 -1
  60. package/dist/utils/warn.js +29 -4
  61. package/dist/wrappers/openai.cjs +4 -0
  62. package/dist/wrappers/openai.js +4 -0
  63. package/dist/wrappers/openai_agents.cjs +15 -12
  64. package/dist/wrappers/openai_agents.js +15 -12
  65. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -8,6 +8,7 @@ import { __version__ } from "./index.js";
8
8
  import { Langsmith as OpenAPILangsmith } from "./_openapi_client/index.js";
9
9
  import { assertUuid } from "./utils/_uuid.js";
10
10
  import { warnOnce } from "./utils/warn.js";
11
+ import { getQueryBackend, QueryBackend } from "./utils/v2_migration.js";
11
12
  import { parseHubIdentifier } from "./utils/prompts.js";
12
13
  import { raiseForStatus, isLangSmithNotFoundError, isLangSmithConflictError, } from "./utils/error.js";
13
14
  import { promptCacheSingleton, } from "./utils/prompt_cache/index.js";
@@ -154,6 +155,72 @@ export const DEFAULT_MAX_SIZE_BYTES = 1024 * 1024 * 1024; // 1GB
154
155
  const SERVER_INFO_REQUEST_TIMEOUT_MS = 10000;
155
156
  /** Maximum number of operations to batch in a single request. */
156
157
  const DEFAULT_BATCH_SIZE_LIMIT = 100;
158
+ /**
159
+ * Reject header names or values that could alter a request's framing.
160
+ *
161
+ * `Headers` does this for us, and does it the same way `fetch` will.
162
+ */
163
+ function assertValidHeader(name, value) {
164
+ new Headers({ [name]: value });
165
+ }
166
+ /** Reject a malformed header up front, before it can reach a request. */
167
+ function assertValidHeaders(headers) {
168
+ for (const [name, value] of Object.entries(headers ?? {})) {
169
+ assertValidHeader(name, value);
170
+ }
171
+ }
172
+ /**
173
+ * Fold a `HeadersInit` into a plain object so it can be spread.
174
+ *
175
+ * Names are matched case-insensitively with the last value winning, keeping the
176
+ * first spelling seen. A plain object would instead keep both spellings, which
177
+ * `Headers` later joins into a `"first, second"` list rather than an override.
178
+ * Every name and value is validated on the way through.
179
+ */
180
+ function normalizeHeaders(headers) {
181
+ if (!headers)
182
+ return {};
183
+ const entries = headers instanceof Headers
184
+ ? [...headers.entries()]
185
+ : Array.isArray(headers)
186
+ ? headers.map(([name, value]) => [name, value])
187
+ : Object.entries(headers);
188
+ const normalized = {};
189
+ const nameByLower = new Map();
190
+ for (const [name, value] of entries) {
191
+ assertValidHeader(name, value);
192
+ const lowerName = name.toLowerCase();
193
+ const existingName = nameByLower.get(lowerName);
194
+ if (existingName === undefined) {
195
+ nameByLower.set(lowerName, name);
196
+ normalized[name] = value;
197
+ }
198
+ else {
199
+ normalized[existingName] = value;
200
+ }
201
+ }
202
+ return normalized;
203
+ }
204
+ /**
205
+ * Merge the caller's two header channels, then drop the `reserved` names.
206
+ *
207
+ * `overrides` wins, matched case-insensitively so a header supplied through both
208
+ * channels is overridden rather than turned into a `"first, second"` list.
209
+ */
210
+ function mergeCallerHeaders(base, overrides, reserved) {
211
+ const merged = { ...base };
212
+ const nameByLower = new Map(Object.keys(merged).map((name) => [name.toLowerCase(), name]));
213
+ for (const [name, value] of Object.entries(overrides)) {
214
+ const lowerName = name.toLowerCase();
215
+ merged[nameByLower.get(lowerName) ?? name] = value;
216
+ }
217
+ for (const name of Object.keys(merged)) {
218
+ if (reserved.has(name.toLowerCase())) {
219
+ delete merged[name];
220
+ }
221
+ }
222
+ return merged;
223
+ }
157
224
  export class AutoBatchQueue {
158
225
  constructor(maxSizeBytes) {
159
226
  Object.defineProperty(this, "items", {
@@ -572,13 +639,26 @@ export class Client {
572
639
  writable: true,
573
640
  value: void 0
574
641
  });
642
+ /** `config.fetchOptions` without its `headers`, which are merged separately. */
575
643
  Object.defineProperty(this, "fetchOptions", {
576
644
  enumerable: true,
577
645
  configurable: true,
578
646
  writable: true,
579
647
  value: void 0
580
648
  });
581
- Object.defineProperty(this, "openAPIClient", {
649
+ Object.defineProperty(this, "_fetchOptionsHeaders", {
650
+ enumerable: true,
651
+ configurable: true,
652
+ writable: true,
653
+ value: {}
654
+ });
655
+ Object.defineProperty(this, "_openAPIClient", {
656
+ enumerable: true,
657
+ configurable: true,
658
+ writable: true,
659
+ value: void 0
660
+ });
661
+ Object.defineProperty(this, "_openAPIClientSignature", {
582
662
  enumerable: true,
583
663
  configurable: true,
584
664
  writable: true,
@@ -774,7 +854,8 @@ export class Client {
774
854
  config.hideInputs ?? config.anonymizer ?? defaultConfig.hideInputs;
775
855
  this.hideOutputs =
776
856
  config.hideOutputs ?? config.anonymizer ?? defaultConfig.hideOutputs;
777
- this.hideMetadata = config.hideMetadata ?? defaultConfig.hideMetadata;
857
+ this.hideMetadata =
858
+ config.hideMetadata ?? config.anonymizer ?? defaultConfig.hideMetadata;
778
859
  this.anonymizer = config.anonymizer;
779
860
  this.omitTracedRuntimeInfo = config.omitTracedRuntimeInfo ?? false;
780
861
  this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
@@ -783,8 +864,15 @@ export class Client {
783
864
  config.blockOnRootRunFinalization ?? this.blockOnRootRunFinalization;
784
865
  this.batchSizeBytesLimit = config.batchSizeBytesLimit;
785
866
  this.batchSizeLimit = config.batchSizeLimit;
786
- this.fetchOptions = config.fetchOptions || {};
787
- this.openAPIClient = this._newOpenAPIClient();
867
+ const { headers: fetchOptionsHeaders, ...fetchOptions } = config.fetchOptions || {};
868
+ this.fetchOptions = fetchOptions;
869
+ // Kept apart from `fetchOptions` so they can be merged *under* the required
870
+ // headers instead of replacing the whole set at each call site.
871
+ this._fetchOptionsHeaders = normalizeHeaders(fetchOptionsHeaders);
872
+ // Validated eagerly so malformed input fails at construction, but stored
873
+ // as given: `get headers` hands this object back to the caller.
874
+ assertValidHeaders(config.headers);
875
+ this._customHeaders = config.headers ?? {};
788
876
  this.manualFlushMode = config.manualFlushMode ?? this.manualFlushMode;
789
877
  this._tracingMode = resolveTracingMode(config.tracingMode);
790
878
  if (this._tracingMode === "otel") {
@@ -819,8 +907,6 @@ export class Client {
819
907
  // Use the global singleton instance
820
908
  this._promptCache = promptCacheSingleton;
821
909
  }
822
- // Initialize custom headers
823
- this._customHeaders = config.headers ?? {};
824
910
  }
825
911
  static getDefaultClientConfig() {
826
912
  const profileConfig = loadProfileClientConfig();
@@ -892,11 +978,46 @@ export class Client {
892
978
  return this.webUrl;
893
979
  }
894
980
  }
981
+ /**
982
+ * The headers this client sets from its own config, which a caller-supplied
983
+ * header must not replace.
984
+ *
985
+ * Only what the client *actually* supplies: passing an explicit `Authorization`
986
+ * or `x-api-key` header with no configured credential is a supported way to
987
+ * authenticate (see `hasExplicitAuthHeader`), so those must survive.
988
+ */
989
+ get _sdkControlledHeaders() {
990
+ const names = new Set();
991
+ if (this.apiKey !== undefined) {
992
+ names.add("x-api-key");
993
+ }
994
+ else {
995
+ const profileAuthHeader = this.profileAuth?.currentAuthHeader();
996
+ if (profileAuthHeader) {
997
+ names.add(profileAuthHeader.name.toLowerCase());
998
+ }
999
+ }
1000
+ if (this.workspaceId) {
1001
+ names.add("x-tenant-id");
1002
+ }
1003
+ return names;
1004
+ }
1005
+ /**
1006
+ * Headers supplied by the caller, through either `config.headers` or
1007
+ * `config.fetchOptions.headers`, with the ones this SDK sets removed.
1008
+ *
1009
+ * `_customHeaders` is normalized here rather than at assignment because it is
1010
+ * public and mutable: `get headers` hands back the caller's own object, so its
1011
+ * contents can change (and can become malformed) at any point.
1012
+ */
1013
+ get _callerHeaders() {
1014
+ return mergeCallerHeaders(normalizeHeaders(this._customHeaders), this._fetchOptionsHeaders, this._sdkControlledHeaders);
1015
+ }
895
1016
  get _mergedHeaders() {
896
- // Start with custom headers so they don't override required headers
1017
+ // Start with caller-supplied headers so they don't override required headers
897
1018
  const headers = {
898
1019
  "User-Agent": `langsmith-js/${__version__}`,
899
- ...this._customHeaders,
1020
+ ...this._callerHeaders,
900
1021
  };
901
1022
  // Required headers that should not be overridden
902
1023
  if (this.apiKey !== undefined) {
@@ -913,6 +1034,35 @@ export class Client {
913
1034
  }
914
1035
  return headers;
915
1036
  }
1037
+ /**
1038
+ * The auth options and caller headers to build the generated client with.
1039
+ *
1040
+ * The generated client applies `defaultHeaders` *after* its own auth headers,
1041
+ * so the ones this SDK sets are already dropped from `_callerHeaders` to keep
1042
+ * the precedence of `_mergedHeaders`, where required headers win.
1043
+ */
1044
+ get _openAPIAuth() {
1045
+ const headers = { ...this._callerHeaders };
1046
+ // A caller may authenticate by supplying `x-api-key` themselves. The
1047
+ // generated client rejects that as a header (its `validateHeaders` requires
1048
+ // its own `apiKey` to be set), so hand it over as the `apiKey` option and
1049
+ // drop the header to avoid sending the same value twice.
1050
+ const callerApiKeyName = Object.keys(headers).find((name) => name.toLowerCase() === "x-api-key");
1051
+ let apiKey = this.apiKey;
1052
+ if (apiKey === undefined && callerApiKeyName !== undefined) {
1053
+ apiKey = headers[callerApiKeyName] ?? undefined;
1054
+ delete headers[callerApiKeyName];
1055
+ }
1056
+ if (apiKey === undefined && this.workspaceId === undefined) {
1057
+ // Let the wrapped `fetch` supply auth (profile auth, an explicit
1058
+ // `Authorization` header, or none at all).
1059
+ headers["X-API-Key"] = null;
1060
+ }
1061
+ return {
1062
+ apiKey,
1063
+ defaultHeaders: Object.keys(headers).length > 0 ? headers : undefined,
1064
+ };
1065
+ }
916
1066
  /**
917
1067
  * Get or set custom headers for the client.
918
1068
  * Custom headers are merged with default headers (User-Agent, x-api-key, x-tenant-id).
@@ -922,6 +1072,7 @@ export class Client {
922
1072
  return this._customHeaders;
923
1073
  }
924
1074
  set headers(value) {
1075
+ assertValidHeaders(value);
925
1076
  this._customHeaders = value ?? {};
926
1077
  }
927
1078
  _getOpenAPIBaseUrl() {
@@ -932,19 +1083,36 @@ export class Client {
932
1083
  }
933
1084
  return url;
934
1085
  }
935
- _newOpenAPIClient() {
936
- const defaultHeaders = this.apiKey === undefined && this.workspaceId === undefined
937
- ? { "X-API-Key": null }
938
- : undefined;
939
- const { method: _method, headers: _headers, body: _body, signal: _signal, ...openAPIFetchOptions } = this.fetchOptions;
1086
+ /**
1087
+ * The generated OpenAPI client, rebuilt whenever its auth or headers change.
1088
+ *
1089
+ * The generated client captures `defaultHeaders` and `apiKey` when it is
1090
+ * built, while the handwritten paths recompute `_mergedHeaders` per request.
1091
+ * Rebuilding on change keeps the two halves from diverging when the inputs
1092
+ * move underneath us — a caller mutating the object returned by
1093
+ * `get headers`, or a profile whose auth header only becomes available after
1094
+ * its token is refreshed.
1095
+ */
1096
+ get openAPIClient() {
1097
+ const auth = this._openAPIAuth;
1098
+ const signature = JSON.stringify([auth.apiKey, auth.defaultHeaders]);
1099
+ if (this._openAPIClient === undefined ||
1100
+ this._openAPIClientSignature !== signature) {
1101
+ this._openAPIClientSignature = signature;
1102
+ this._openAPIClient = this._newOpenAPIClient(auth);
1103
+ }
1104
+ return this._openAPIClient;
1105
+ }
1106
+ _newOpenAPIClient(auth = this._openAPIAuth) {
1107
+ const { method: _method, body: _body, signal: _signal, ...openAPIFetchOptions } = this.fetchOptions;
940
1108
  return new OpenAPILangsmith({
941
- apiKey: this.apiKey,
1109
+ apiKey: auth.apiKey,
942
1110
  tenantID: this.workspaceId,
943
1111
  baseURL: this._getOpenAPIBaseUrl(),
944
1112
  timeout: this.timeout_ms,
945
1113
  fetch: this._fetch,
946
1114
  fetchOptions: openAPIFetchOptions,
947
- defaultHeaders,
1115
+ defaultHeaders: auth.defaultHeaders,
948
1116
  });
949
1117
  }
950
1118
  _getPlatformEndpointPath(path) {
@@ -1349,6 +1517,9 @@ export class Client {
1349
1517
  const batchSizeBytes = batch.reduce((sum, item) => sum + (item.size ?? 0), 0);
1350
1518
  try {
1351
1519
  if (this.langSmithToOTELTranslator !== undefined) {
1520
+ for (const item of batch) {
1521
+ item.item = await this._maskRunMetadata(item.item);
1522
+ }
1352
1523
  this._sendBatchToOTELTranslator(batch);
1353
1524
  }
1354
1525
  else {
@@ -1429,6 +1600,25 @@ export class Client {
1429
1600
  this.langSmithToOTELTranslator.exportBatch(operations, otelContextMap);
1430
1601
  }
1431
1602
  }
1603
+ async _maskRunMetadata(run) {
1604
+ if (run.extra?.metadata == null) {
1605
+ return run;
1606
+ }
1607
+ return {
1608
+ ...run,
1609
+ extra: {
1610
+ ...run.extra,
1611
+ metadata: await this.processMetadata(run.extra.metadata),
1612
+ },
1613
+ };
1614
+ }
1615
+ async _mergeRuntimeEnvAndMaskMetadata(run) {
1616
+ const merged = mergeRuntimeEnvIntoRun(run, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo);
1617
+ if (this.omitTracedRuntimeInfo) {
1618
+ return merged;
1619
+ }
1620
+ return this._maskRunMetadata(merged);
1621
+ }
1432
1622
  async processRunOperation(item) {
1433
1623
  clearTimeout(this.autoBatchTimeout);
1434
1624
  this.autoBatchTimeout = undefined;
@@ -1521,7 +1711,7 @@ export class Client {
1521
1711
  async _checkFeedbackSessionId() {
1522
1712
  const docs = "https://docs.langchain.com/langsmith/smithdb-sdk-migration#feedback-create";
1523
1713
  const serverInfo = await this._ensureServerInfo();
1524
- if (serverInfo.instance_flags?.ch_query_enabled === false) {
1714
+ if (getQueryBackend(serverInfo.instance_flags) === QueryBackend.SMITHDB_ONLY) {
1525
1715
  throw new Error(`sessionId must be provided when creating feedback for a run: this ` +
1526
1716
  `deployment cannot locate the run without it. See ${docs}`);
1527
1717
  }
@@ -1585,7 +1775,7 @@ export class Client {
1585
1775
  }).catch(console.error);
1586
1776
  return;
1587
1777
  }
1588
- const mergedRunCreateParam = mergeRuntimeEnvIntoRun(runCreate, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo);
1778
+ const mergedRunCreateParam = await this._mergeRuntimeEnvAndMaskMetadata(runCreate);
1589
1779
  if (options?.apiKey !== undefined) {
1590
1780
  headers["x-api-key"] = options.apiKey;
1591
1781
  }
@@ -2046,7 +2236,22 @@ export class Client {
2046
2236
  return res;
2047
2237
  });
2048
2238
  }
2239
+ /** @deprecated Use `client.runs.retrieve()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-retrieve for the migration guide. Will be removed after Jan 31, 2027. */
2049
2240
  async readRun(runId, { loadChildRuns } = { loadChildRuns: false }) {
2241
+ warnOnce("readRun() is deprecated and will be removed after Jan 31, 2027. " +
2242
+ "Use client.runs.retrieve() instead. " +
2243
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-retrieve for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_READ_RUN" });
2244
+ return this._readRun(runId, { loadChildRuns });
2245
+ }
2246
+ /**
2247
+ * Fetch a run without emitting the `readRun()` deprecation warning.
2248
+ *
2249
+ * Internal callers use this so that a supported method doesn't warn about a
2250
+ * deprecated one the caller never invoked.
2251
+ *
2252
+ * @internal
2253
+ */
2254
+ async _readRun(runId, { loadChildRuns } = { loadChildRuns: false }) {
2050
2255
  assertUuid(runId);
2051
2256
  let run = _normalizeRunTimestamps(await this._get(`/runs/${runId}`));
2052
2257
  if (loadChildRuns) {
@@ -2054,7 +2259,11 @@ export class Client {
2054
2259
  }
2055
2260
  return run;
2056
2261
  }
2262
+ /** @deprecated Use `client.runs.getURL()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-get-url for the migration guide. Will be removed after Jan 31, 2027. */
2057
2263
  async getRunUrl({ runId, run, projectOpts, }) {
2264
+ warnOnce("getRunUrl() is deprecated and will be removed after Jan 31, 2027. " +
2265
+ "Use client.runs.getURL() instead. " +
2266
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-get-url for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_GET_RUN_URL" });
2058
2267
  if (run !== undefined) {
2059
2268
  let sessionId;
2060
2269
  if (run.session_id) {
@@ -2076,7 +2285,9 @@ export class Client {
2076
2285
  return `${this.getHostUrl()}/o/${tenantId}/projects/p/${sessionId}/r/${run.id}?poll=true`;
2077
2286
  }
2078
2287
  else if (runId !== undefined) {
2079
- const run_ = await this.readRun(runId);
2288
+ // Via _readRun() rather than readRun() so callers don't also get a
2289
+ // readRun deprecation warning for a method they never called.
2290
+ const run_ = await this._readRun(runId);
2080
2291
  if (!run_.app_path) {
2081
2292
  throw new Error(`Run ${runId} has no app_path`);
2082
2293
  }
@@ -2088,7 +2299,7 @@ export class Client {
2088
2299
  }
2089
2300
  }
2090
2301
  async _loadChildRuns(run) {
2091
- const childRuns = await toArray(this.listRuns({
2302
+ const childRuns = await toArray(this._listRuns({
2092
2303
  isRoot: false,
2093
2304
  projectId: run.session_id,
2094
2305
  traceId: run.trace_id,
@@ -2121,6 +2332,7 @@ export class Client {
2121
2332
  }
2122
2333
  /**
2123
2334
  * List runs from the LangSmith server.
2335
+ * @deprecated Use `client.runs.query()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-query for the migration guide. Will be removed after Jan 31, 2027.
2124
2336
  * @param projectId - The ID of the project to filter by.
2125
2337
  * @param projectName - The name of the project to filter by.
2126
2338
  * @param parentRunId - The ID of the parent run to filter by.
@@ -2202,6 +2414,20 @@ export class Client {
2202
2414
  * });
2203
2415
  */
2204
2416
  async *listRuns(props) {
2417
+ warnOnce("listRuns() is deprecated and will be removed after Jan 31, 2027. " +
2418
+ "Use client.runs.query() instead. " +
2419
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-query for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_LIST_RUNS" });
2420
+ yield* this._listRuns(props);
2421
+ }
2422
+ /**
2423
+ * List runs without emitting the `listRuns()` deprecation warning.
2424
+ *
2425
+ * Internal callers use this so that a supported method doesn't warn about a
2426
+ * deprecated one the caller never invoked.
2427
+ *
2428
+ * @internal
2429
+ */
2430
+ async *_listRuns(props) {
2205
2431
  const { projectId, projectName, parentRunId, traceId, referenceExampleId, startTime, executionOrder, isRoot, runType, error, id, query, filter, traceFilter, treeFilter, limit, select, order, } = props;
2206
2432
  let projectIds = [];
2207
2433
  if (projectId) {
@@ -2335,7 +2561,11 @@ export class Client {
2335
2561
  }
2336
2562
  }
2337
2563
  }
2564
+ /** @deprecated Use `client.threads.listTraces()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#threads-list-traces for the migration guide. Will be removed after Jan 31, 2027. */
2338
2565
  async *readThread(props) {
2566
+ warnOnce("readThread() is deprecated and will be removed after Jan 31, 2027. " +
2567
+ "Use client.threads.listTraces() instead. " +
2568
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#threads-list-traces for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_READ_THREAD" });
2339
2569
  const { threadId, projectId, projectName, isRoot = true, limit, filter: userFilter, order = "asc", } = props;
2340
2570
  if (!projectId && !projectName) {
2341
2571
  throw new Error("threadId requires projectId or projectName");
@@ -2344,7 +2574,9 @@ export class Client {
2344
2574
  const combinedFilter = userFilter
2345
2575
  ? `and(${threadFilter}, ${userFilter})`
2346
2576
  : threadFilter;
2347
- yield* this.listRuns({
2577
+ // Via _listRuns() rather than listRuns(): readThread() already warned, and it
2578
+ // points at threads.listTraces() rather than listRuns()'s runs.query().
2579
+ yield* this._listRuns({
2348
2580
  projectId: projectId ?? undefined,
2349
2581
  projectName: projectName ?? undefined,
2350
2582
  isRoot,
@@ -2353,7 +2585,11 @@ export class Client {
2353
2585
  order,
2354
2586
  });
2355
2587
  }
2588
+ /** @deprecated Use `client.threads.query()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#threads-query for the migration guide. Will be removed after Jan 31, 2027. */
2356
2589
  async listThreads(props) {
2590
+ warnOnce("listThreads() is deprecated and will be removed after Jan 31, 2027. " +
2591
+ "Use client.threads.query() instead. " +
2592
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#threads-query for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_LIST_THREADS" });
2357
2593
  const { projectId, projectName, limit, offset = 0, filter, startTime, isRoot = true, } = props;
2358
2594
  if (!projectId && !projectName) {
2359
2595
  throw new Error("Either projectId or projectName must be provided");
@@ -2503,7 +2739,11 @@ export class Client {
2503
2739
  const result = await response.json();
2504
2740
  return result;
2505
2741
  }
2742
+ /** @deprecated Use `client.runs.share.create()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide. Will be removed after Jan 31, 2027. */
2506
2743
  async shareRun(runId, { shareId } = {}) {
2744
+ warnOnce("shareRun() is deprecated and will be removed after Jan 31, 2027. " +
2745
+ "Use client.runs.share.create() instead. " +
2746
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_SHARE_RUN" });
2507
2747
  const data = {
2508
2748
  run_id: runId,
2509
2749
  share_token: shareId || uuid.v4(),
@@ -2527,7 +2767,11 @@ export class Client {
2527
2767
  }
2528
2768
  return `${this.getHostUrl()}/public/${result["share_token"]}/r`;
2529
2769
  }
2770
+ /** @deprecated Use `client.runs.share.delete()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide. Will be removed after Jan 31, 2027. */
2530
2771
  async unshareRun(runId) {
2772
+ warnOnce("unshareRun() is deprecated and will be removed after Jan 31, 2027. " +
2773
+ "Use client.runs.share.delete() instead. " +
2774
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_UNSHARE_RUN" });
2531
2775
  assertUuid(runId);
2532
2776
  await this.caller.call(async () => {
2533
2777
  const res = await this._fetch(`${this.apiUrl}/runs/${runId}/share`, {
@@ -2540,7 +2784,14 @@ export class Client {
2540
2784
  return res;
2541
2785
  });
2542
2786
  }
2787
+ /** @deprecated Use `client.runs.retrieve({ selects: ["SHARE_URL"] })` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide. Will be removed after Jan 31, 2027. */
2543
2788
  async readRunSharedLink(runId) {
2789
+ warnOnce("readRunSharedLink() is deprecated and will be removed after Jan 31, 2027. " +
2790
+ 'Use client.runs.retrieve({ selects: ["SHARE_URL"] }) instead. ' +
2791
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide.", {
2792
+ type: "DeprecationWarning",
2793
+ code: "LANGSMITH_DEPRECATED_READ_RUN_SHARED_LINK",
2794
+ });
2544
2795
  assertUuid(runId);
2545
2796
  const response = await this.caller.call(async () => {
2546
2797
  const res = await this._fetch(`${this.apiUrl}/runs/${runId}/share`, {
@@ -2558,7 +2809,14 @@ export class Client {
2558
2809
  }
2559
2810
  return `${this.getHostUrl()}/public/${result["share_token"]}/r`;
2560
2811
  }
2812
+ /** @deprecated Use `client.public.runs.query()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide. Will be removed after Jan 31, 2027. */
2561
2813
  async listSharedRuns(shareToken, { runIds, } = {}) {
2814
+ warnOnce("listSharedRuns() is deprecated and will be removed after Jan 31, 2027. " +
2815
+ "Use client.public.runs.query() instead. " +
2816
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide.", {
2817
+ type: "DeprecationWarning",
2818
+ code: "LANGSMITH_DEPRECATED_LIST_SHARED_RUNS",
2819
+ });
2562
2820
  const queryParams = new URLSearchParams({
2563
2821
  share_token: shareToken,
2564
2822
  });
@@ -2706,7 +2964,7 @@ export class Client {
2706
2964
  _hostUrl: this.getHostUrl(),
2707
2965
  }));
2708
2966
  }
2709
- async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, numExamples = null, numRepetitions = null, evaluatorKeys = null, }) {
2967
+ async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, numExamples = null, numRepetitions = null, evaluatorKeys = null, tagValueIds = null, }) {
2710
2968
  const upsert_ = upsert ? `?upsert=true` : "";
2711
2969
  const endpoint = `${this.apiUrl}/sessions${upsert_}`;
2712
2970
  const extra = projectExtra || {};
@@ -2730,6 +2988,9 @@ export class Client {
2730
2988
  if (evaluatorKeys != null && evaluatorKeys.length > 0) {
2731
2989
  body["evaluator_keys"] = evaluatorKeys;
2732
2990
  }
2991
+ if (tagValueIds !== null) {
2992
+ body["tag_value_ids"] = tagValueIds;
2993
+ }
2733
2994
  const serializedBody = JSON.stringify(body);
2734
2995
  const response = await this.caller.call(async () => {
2735
2996
  const res = await this._fetch(endpoint, {
@@ -2973,7 +3234,7 @@ export class Client {
2973
3234
  const result = await response.json();
2974
3235
  return result;
2975
3236
  }
2976
- async createDataset(name, { description, dataType, inputsSchema, outputsSchema, metadata, } = {}) {
3237
+ async createDataset(name, { description, dataType, inputsSchema, outputsSchema, metadata, tagValueIds, } = {}) {
2977
3238
  const body = {
2978
3239
  name,
2979
3240
  description,
@@ -2988,6 +3249,9 @@ export class Client {
2988
3249
  if (outputsSchema) {
2989
3250
  body.outputs_schema_definition = outputsSchema;
2990
3251
  }
3252
+ if (tagValueIds !== undefined) {
3253
+ body.tag_value_ids = tagValueIds;
3254
+ }
2991
3255
  const serializedBody = JSON.stringify(body);
2992
3256
  const response = await this.caller.call(async () => {
2993
3257
  const res = await this._fetch(`${this.apiUrl}/datasets`, {
@@ -4147,8 +4411,9 @@ export class Client {
4147
4411
  * - `RunKey[]` (preferred): each entry carries the run's full lookup key, so
4148
4412
  * it can be located directly without a scan. Required for workspaces served
4149
4413
  * by SmithDB; routes to `POST /runs/by-key`.
4150
- * - `string[]`: a plain list of run IDs. This path will be deprecated in a
4151
- * future release; prefer the key form. Routes to `POST /runs`.
4414
+ * - `string[]`: a plain list of run IDs. **Deprecated**: this path will be
4415
+ * removed after Jan 31, 2027; prefer the key form. Routes to `POST /runs`.
4416
+ * See https://docs.langchain.com/langsmith/smithdb-sdk-migration#annotation-queues-add-runs.
4152
4417
  *
4153
4418
  * If every element is a string (or the list is empty) it is treated as run
4154
4419
  * IDs; otherwise the list is treated as `RunKey` objects.
@@ -4179,6 +4444,12 @@ export class Client {
4179
4444
  }));
4180
4445
  }
4181
4446
  else {
4447
+ warnOnce("Passing run IDs as strings to addRunsToAnnotationQueue() is deprecated and will be removed after Jan 31, 2027. " +
4448
+ "Use RunKey[] instead. " +
4449
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#annotation-queues-add-runs for the migration guide.", {
4450
+ type: "DeprecationWarning",
4451
+ code: "LANGSMITH_DEPRECATED_ADD_RUNS_STRING_IDS",
4452
+ });
4182
4453
  url = base;
4183
4454
  body = JSON.stringify(runs.map((id, i) => assertUuid(id, `runs[${i}]`).toString()));
4184
4455
  }
@@ -24,10 +24,13 @@ async function loadTracesForExperiment(client, project, options) {
24
24
  const isRoot = options.loadNested ? undefined : true;
25
25
  const runs = (await client._supportsSDBQuery())
26
26
  ? await (0, v2_migration_js_1.loadTracesV2)(client, project, { isRoot })
27
- : await client.listRuns({
28
- projectId: project.id,
29
- executionOrder: options.loadNested ? undefined : 1,
30
- });
27
+ : // Via _listRuns() rather than listRuns(): evaluate() is supported, so
28
+ // callers have nothing to migrate; how it loads traces is an
29
+ // implementation detail.
30
+ await client._listRuns({
31
+ projectId: project.id,
32
+ executionOrder: options.loadNested ? undefined : 1,
33
+ });
31
34
  const treeMap = {};
32
35
  const runIdMap = {};
33
36
  const results = [];
@@ -17,10 +17,13 @@ export async function loadTracesForExperiment(client, project, options) {
17
17
  const isRoot = options.loadNested ? undefined : true;
18
18
  const runs = (await client._supportsSDBQuery())
19
19
  ? await loadTracesV2(client, project, { isRoot })
20
- : await client.listRuns({
21
- projectId: project.id,
22
- executionOrder: options.loadNested ? undefined : 1,
23
- });
20
+ : // Via _listRuns() rather than listRuns(): evaluate() is supported, so
21
+ // callers have nothing to migrate; how it loads traces is an
22
+ // implementation detail.
23
+ await client._listRuns({
24
+ projectId: project.id,
25
+ executionOrder: options.loadNested ? undefined : 1,
26
+ });
24
27
  const treeMap = {};
25
28
  const runIdMap = {};
26
29
  const results = [];
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveVercelLsAgentType = resolveVercelLsAgentType;
4
+ exports.vercelLsAgentTypeMetadata = vercelLsAgentTypeMetadata;
5
+ const run_trees_js_1 = require("../../run_trees.cjs");
6
+ const traceable_js_1 = require("../../singletons/traceable.cjs");
7
+ const ls_agent_type_js_1 = require("../../utils/ls_agent_type.cjs");
8
+ // Vercel builds its traceable's `metadata` config eagerly, before traceable
9
+ // itself runs — this resolver stamps `ls_agent_type` at that moment.
10
+ // Traceable's own propagation would carry a parent's middleware/subagent/
11
+ // compaction/"root" tag down on its own. This resolver is needed
12
+ // for correct default tagging of the root `ls_agent_type` == root
13
+ // and tagging of subagents.
14
+ function resolveVercelLsAgentType(parentRunTree) {
15
+ const parent = parentRunTree ?? (0, traceable_js_1.getCurrentRunTree)(true);
16
+ if (!(0, run_trees_js_1.isRunTree)(parent))
17
+ return (0, ls_agent_type_js_1.resolveDefaultLsAgentType)(parent);
18
+ const parentTag = parent.extra?.metadata?.ls_agent_type;
19
+ if (typeof parentTag === "string" && ls_agent_type_js_1.NON_ROOT_LS_AGENT_TYPES.has(parentTag)) {
20
+ return parentTag;
21
+ }
22
+ if (parent.run_type === "tool")
23
+ return "subagent";
24
+ if (parentTag === "root")
25
+ return "root";
26
+ return undefined;
27
+ }
28
+ function vercelLsAgentTypeMetadata(parentRunTree) {
29
+ return (0, ls_agent_type_js_1.lsAgentTypeMetadata)(resolveVercelLsAgentType(parentRunTree));
30
+ }
@@ -0,0 +1,5 @@
1
+ import { LsAgentType } from "../../utils/ls_agent_type.js";
2
+ export declare function resolveVercelLsAgentType(parentRunTree?: unknown): LsAgentType | undefined;
3
+ export declare function vercelLsAgentTypeMetadata(parentRunTree?: unknown): {
4
+ ls_agent_type?: LsAgentType;
5
+ };
@@ -0,0 +1,26 @@
1
+ import { isRunTree } from "../../run_trees.js";
2
+ import { getCurrentRunTree } from "../../singletons/traceable.js";
3
+ import { NON_ROOT_LS_AGENT_TYPES, lsAgentTypeMetadata, resolveDefaultLsAgentType, } from "../../utils/ls_agent_type.js";
4
+ // Vercel builds its traceable's `metadata` config eagerly, before traceable
5
+ // itself runs — this resolver stamps `ls_agent_type` at that moment.
6
+ // Traceable's own propagation would carry a parent's middleware/subagent/
7
+ // compaction/"root" tag down on its own. This resolver is needed
8
+ // for correct default tagging of the root `ls_agent_type` == root
9
+ // and tagging of subagents.
10
+ export function resolveVercelLsAgentType(parentRunTree) {
11
+ const parent = parentRunTree ?? getCurrentRunTree(true);
12
+ if (!isRunTree(parent))
13
+ return resolveDefaultLsAgentType(parent);
14
+ const parentTag = parent.extra?.metadata?.ls_agent_type;
15
+ if (typeof parentTag === "string" && NON_ROOT_LS_AGENT_TYPES.has(parentTag)) {
16
+ return parentTag;
17
+ }
18
+ if (parent.run_type === "tool")
19
+ return "subagent";
20
+ if (parentTag === "root")
21
+ return "root";
22
+ return undefined;
23
+ }
24
+ export function vercelLsAgentTypeMetadata(parentRunTree) {
25
+ return lsAgentTypeMetadata(resolveVercelLsAgentType(parentRunTree));
26
+ }