langsmith 0.8.7 → 0.8.9

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 (83) hide show
  1. package/dist/_openapi_client/client.cjs +8 -0
  2. package/dist/_openapi_client/client.d.ts +3 -0
  3. package/dist/_openapi_client/client.js +8 -0
  4. package/dist/_openapi_client/resources/annotation-queues/annotation-queues.cjs +157 -0
  5. package/dist/_openapi_client/resources/annotation-queues/annotation-queues.d.ts +382 -0
  6. package/dist/_openapi_client/resources/annotation-queues/annotation-queues.js +120 -0
  7. package/dist/_openapi_client/resources/annotation-queues/items.cjs +84 -0
  8. package/dist/_openapi_client/resources/annotation-queues/items.d.ts +207 -0
  9. package/dist/_openapi_client/resources/annotation-queues/items.js +80 -0
  10. package/dist/_openapi_client/resources/annotation-queues/runs.cjs +73 -0
  11. package/dist/_openapi_client/resources/annotation-queues/runs.d.ts +197 -0
  12. package/dist/_openapi_client/resources/annotation-queues/runs.js +69 -0
  13. package/dist/_openapi_client/resources/datasets/experiment-runs.cjs +3 -1
  14. package/dist/_openapi_client/resources/datasets/experiment-runs.d.ts +2 -0
  15. package/dist/_openapi_client/resources/datasets/experiment-runs.js +3 -1
  16. package/dist/_openapi_client/resources/index.cjs +3 -1
  17. package/dist/_openapi_client/resources/index.d.ts +1 -0
  18. package/dist/_openapi_client/resources/index.js +1 -0
  19. package/dist/_openapi_client/resources/info.cjs +3 -1
  20. package/dist/_openapi_client/resources/info.d.ts +16 -22
  21. package/dist/_openapi_client/resources/info.js +3 -1
  22. package/dist/_openapi_client/resources/issues.cjs +2 -2
  23. package/dist/_openapi_client/resources/issues.d.ts +1 -1
  24. package/dist/_openapi_client/resources/issues.js +2 -2
  25. package/dist/_openapi_client/resources/online-evaluators.cjs +7 -7
  26. package/dist/_openapi_client/resources/online-evaluators.d.ts +8 -0
  27. package/dist/_openapi_client/resources/online-evaluators.js +7 -7
  28. package/dist/_openapi_client/resources/public/runs.cjs +10 -8
  29. package/dist/_openapi_client/resources/public/runs.d.ts +9 -7
  30. package/dist/_openapi_client/resources/public/runs.js +10 -8
  31. package/dist/_openapi_client/resources/runs/runs.cjs +14 -9
  32. package/dist/_openapi_client/resources/runs/runs.d.ts +20 -10
  33. package/dist/_openapi_client/resources/runs/runs.js +14 -9
  34. package/dist/_openapi_client/resources/runs/share.cjs +6 -2
  35. package/dist/_openapi_client/resources/runs/share.d.ts +4 -0
  36. package/dist/_openapi_client/resources/runs/share.js +6 -2
  37. package/dist/_openapi_client/resources/sandboxes/boxes.cjs +10 -10
  38. package/dist/_openapi_client/resources/sandboxes/boxes.d.ts +40 -0
  39. package/dist/_openapi_client/resources/sandboxes/boxes.js +10 -10
  40. package/dist/_openapi_client/resources/sandboxes/registries.cjs +5 -5
  41. package/dist/_openapi_client/resources/sandboxes/registries.js +5 -5
  42. package/dist/_openapi_client/resources/sandboxes/sandboxes.d.ts +17 -0
  43. package/dist/_openapi_client/resources/sandboxes/snapshots.cjs +4 -4
  44. package/dist/_openapi_client/resources/sandboxes/snapshots.d.ts +12 -0
  45. package/dist/_openapi_client/resources/sandboxes/snapshots.js +4 -4
  46. package/dist/_openapi_client/resources/threads.cjs +14 -11
  47. package/dist/_openapi_client/resources/threads.d.ts +13 -9
  48. package/dist/_openapi_client/resources/threads.js +14 -11
  49. package/dist/_openapi_client/resources/traces.cjs +8 -5
  50. package/dist/_openapi_client/resources/traces.d.ts +7 -4
  51. package/dist/_openapi_client/resources/traces.js +8 -5
  52. package/dist/client.cjs +318 -40
  53. package/dist/client.d.ts +111 -25
  54. package/dist/client.js +318 -40
  55. package/dist/evaluation/evaluate_comparative.cjs +7 -4
  56. package/dist/evaluation/evaluate_comparative.js +7 -4
  57. package/dist/index.cjs +1 -1
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.js +1 -1
  60. package/dist/sandbox/command_handle.cjs +38 -11
  61. package/dist/sandbox/command_handle.d.ts +1 -0
  62. package/dist/sandbox/command_handle.js +39 -12
  63. package/dist/sandbox/errors.cjs +16 -1
  64. package/dist/sandbox/errors.d.ts +11 -0
  65. package/dist/sandbox/errors.js +14 -0
  66. package/dist/sandbox/index.cjs +2 -1
  67. package/dist/sandbox/index.d.ts +1 -1
  68. package/dist/sandbox/index.js +1 -1
  69. package/dist/sandbox/sandbox.cjs +22 -4
  70. package/dist/sandbox/sandbox.js +24 -6
  71. package/dist/sandbox/ws_execute.cjs +82 -11
  72. package/dist/sandbox/ws_execute.d.ts +12 -2
  73. package/dist/sandbox/ws_execute.js +79 -11
  74. package/dist/utils/v2_migration.cjs +18 -0
  75. package/dist/utils/v2_migration.d.ts +8 -0
  76. package/dist/utils/v2_migration.js +16 -0
  77. package/dist/utils/warn.cjs +30 -4
  78. package/dist/utils/warn.d.ts +4 -1
  79. package/dist/utils/warn.js +29 -4
  80. package/package.json +1 -1
  81. package/dist/utils/constants.cjs +0 -4
  82. package/dist/utils/constants.d.ts +0 -1
  83. package/dist/utils/constants.js +0 -1
package/dist/client.js CHANGED
@@ -8,7 +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 { _MIN_BACKEND_VERSION } from "./utils/constants.js";
11
+ import { getQueryBackend, QueryBackend } from "./utils/v2_migration.js";
12
12
  import { parseHubIdentifier } from "./utils/prompts.js";
13
13
  import { raiseForStatus, isLangSmithNotFoundError, isLangSmithConflictError, } from "./utils/error.js";
14
14
  import { promptCacheSingleton, } from "./utils/prompt_cache/index.js";
@@ -123,9 +123,13 @@ function _formatFeedbackScore(score) {
123
123
  }
124
124
  return score;
125
125
  }
126
- export function _checkBackendVersion(version, minVersion = _MIN_BACKEND_VERSION) {
126
+ export function _checkBackendVersion(backendVersion, minVersion) {
127
+ if (!backendVersion) {
128
+ // /info was unreachable (or skipped): nothing to compare against.
129
+ return;
130
+ }
127
131
  const parse = (v) => v.split(".").map((s) => parseInt(s, 10));
128
- const [maj, min, pat] = parse(version);
132
+ const [maj, min, pat] = parse(backendVersion);
129
133
  const [rMaj, rMin, rPat] = parse(minVersion);
130
134
  if (isNaN(maj) ||
131
135
  isNaN(min) ||
@@ -133,13 +137,16 @@ export function _checkBackendVersion(version, minVersion = _MIN_BACKEND_VERSION)
133
137
  isNaN(rMaj) ||
134
138
  isNaN(rMin) ||
135
139
  isNaN(rPat)) {
136
- console.warn(`[LANGSMITH]: Could not parse backend version ${JSON.stringify(version)} for compatibility check.`);
140
+ console.warn(`[LANGSMITH]: Could not parse backend version ${JSON.stringify(backendVersion)} for compatibility check.`);
137
141
  return;
138
142
  }
139
143
  if (maj < rMaj ||
140
144
  (maj === rMaj && min < rMin) ||
141
145
  (maj === rMaj && min === rMin && pat < rPat)) {
142
- console.warn(`[LANGSMITH]: Backend version ${JSON.stringify(version)} is older than the minimum version required by this SDK (${JSON.stringify(minVersion)}). Some features may not work as expected.`);
146
+ console.warn(`[LANGSMITH]: Backend version ${JSON.stringify(backendVersion)} is older than ` +
147
+ `the minimum version required by this SDK (${JSON.stringify(minVersion)}). ` +
148
+ "Some features may not work as expected. See " +
149
+ "https://docs.langchain.com/langsmith/smithdb-sdk-migration");
143
150
  }
144
151
  }
145
152
  export const DEFAULT_UNCOMPRESSED_BATCH_SIZE_LIMIT_BYTES = 24 * 1024 * 1024;
@@ -148,6 +155,72 @@ export const DEFAULT_MAX_SIZE_BYTES = 1024 * 1024 * 1024; // 1GB
148
155
  const SERVER_INFO_REQUEST_TIMEOUT_MS = 10000;
149
156
  /** Maximum number of operations to batch in a single request. */
150
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
+ }
151
224
  export class AutoBatchQueue {
152
225
  constructor(maxSizeBytes) {
153
226
  Object.defineProperty(this, "items", {
@@ -566,13 +639,26 @@ export class Client {
566
639
  writable: true,
567
640
  value: void 0
568
641
  });
642
+ /** `config.fetchOptions` without its `headers`, which are merged separately. */
569
643
  Object.defineProperty(this, "fetchOptions", {
570
644
  enumerable: true,
571
645
  configurable: true,
572
646
  writable: true,
573
647
  value: void 0
574
648
  });
575
- 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", {
576
662
  enumerable: true,
577
663
  configurable: true,
578
664
  writable: true,
@@ -609,11 +695,11 @@ export class Client {
609
695
  writable: true,
610
696
  value: void 0
611
697
  });
612
- Object.defineProperty(this, "_stainlessVersionChecked", {
698
+ Object.defineProperty(this, "_stainlessVersionsChecked", {
613
699
  enumerable: true,
614
700
  configurable: true,
615
701
  writable: true,
616
- value: false
702
+ value: new Set()
617
703
  });
618
704
  Object.defineProperty(this, "manualFlushMode", {
619
705
  enumerable: true,
@@ -777,8 +863,15 @@ export class Client {
777
863
  config.blockOnRootRunFinalization ?? this.blockOnRootRunFinalization;
778
864
  this.batchSizeBytesLimit = config.batchSizeBytesLimit;
779
865
  this.batchSizeLimit = config.batchSizeLimit;
780
- this.fetchOptions = config.fetchOptions || {};
781
- this.openAPIClient = this._newOpenAPIClient();
866
+ const { headers: fetchOptionsHeaders, ...fetchOptions } = config.fetchOptions || {};
867
+ this.fetchOptions = fetchOptions;
868
+ // Kept apart from `fetchOptions` so they can be merged *under* the required
869
+ // headers instead of replacing the whole set at each call site.
870
+ this._fetchOptionsHeaders = normalizeHeaders(fetchOptionsHeaders);
871
+ // Validated eagerly so malformed input fails at construction, but stored
872
+ // as given: `get headers` hands this object back to the caller.
873
+ assertValidHeaders(config.headers);
874
+ this._customHeaders = config.headers ?? {};
782
875
  this.manualFlushMode = config.manualFlushMode ?? this.manualFlushMode;
783
876
  this._tracingMode = resolveTracingMode(config.tracingMode);
784
877
  if (this._tracingMode === "otel") {
@@ -813,8 +906,6 @@ export class Client {
813
906
  // Use the global singleton instance
814
907
  this._promptCache = promptCacheSingleton;
815
908
  }
816
- // Initialize custom headers
817
- this._customHeaders = config.headers ?? {};
818
909
  }
819
910
  static getDefaultClientConfig() {
820
911
  const profileConfig = loadProfileClientConfig();
@@ -886,11 +977,46 @@ export class Client {
886
977
  return this.webUrl;
887
978
  }
888
979
  }
980
+ /**
981
+ * The headers this client sets from its own config, which a caller-supplied
982
+ * header must not replace.
983
+ *
984
+ * Only what the client *actually* supplies: passing an explicit `Authorization`
985
+ * or `x-api-key` header with no configured credential is a supported way to
986
+ * authenticate (see `hasExplicitAuthHeader`), so those must survive.
987
+ */
988
+ get _sdkControlledHeaders() {
989
+ const names = new Set();
990
+ if (this.apiKey !== undefined) {
991
+ names.add("x-api-key");
992
+ }
993
+ else {
994
+ const profileAuthHeader = this.profileAuth?.currentAuthHeader();
995
+ if (profileAuthHeader) {
996
+ names.add(profileAuthHeader.name.toLowerCase());
997
+ }
998
+ }
999
+ if (this.workspaceId) {
1000
+ names.add("x-tenant-id");
1001
+ }
1002
+ return names;
1003
+ }
1004
+ /**
1005
+ * Headers supplied by the caller, through either `config.headers` or
1006
+ * `config.fetchOptions.headers`, with the ones this SDK sets removed.
1007
+ *
1008
+ * `_customHeaders` is normalized here rather than at assignment because it is
1009
+ * public and mutable: `get headers` hands back the caller's own object, so its
1010
+ * contents can change (and can become malformed) at any point.
1011
+ */
1012
+ get _callerHeaders() {
1013
+ return mergeCallerHeaders(normalizeHeaders(this._customHeaders), this._fetchOptionsHeaders, this._sdkControlledHeaders);
1014
+ }
889
1015
  get _mergedHeaders() {
890
- // Start with custom headers so they don't override required headers
1016
+ // Start with caller-supplied headers so they don't override required headers
891
1017
  const headers = {
892
1018
  "User-Agent": `langsmith-js/${__version__}`,
893
- ...this._customHeaders,
1019
+ ...this._callerHeaders,
894
1020
  };
895
1021
  // Required headers that should not be overridden
896
1022
  if (this.apiKey !== undefined) {
@@ -907,6 +1033,35 @@ export class Client {
907
1033
  }
908
1034
  return headers;
909
1035
  }
1036
+ /**
1037
+ * The auth options and caller headers to build the generated client with.
1038
+ *
1039
+ * The generated client applies `defaultHeaders` *after* its own auth headers,
1040
+ * so the ones this SDK sets are already dropped from `_callerHeaders` to keep
1041
+ * the precedence of `_mergedHeaders`, where required headers win.
1042
+ */
1043
+ get _openAPIAuth() {
1044
+ const headers = { ...this._callerHeaders };
1045
+ // A caller may authenticate by supplying `x-api-key` themselves. The
1046
+ // generated client rejects that as a header (its `validateHeaders` requires
1047
+ // its own `apiKey` to be set), so hand it over as the `apiKey` option and
1048
+ // drop the header to avoid sending the same value twice.
1049
+ const callerApiKeyName = Object.keys(headers).find((name) => name.toLowerCase() === "x-api-key");
1050
+ let apiKey = this.apiKey;
1051
+ if (apiKey === undefined && callerApiKeyName !== undefined) {
1052
+ apiKey = headers[callerApiKeyName] ?? undefined;
1053
+ delete headers[callerApiKeyName];
1054
+ }
1055
+ if (apiKey === undefined && this.workspaceId === undefined) {
1056
+ // Let the wrapped `fetch` supply auth (profile auth, an explicit
1057
+ // `Authorization` header, or none at all).
1058
+ headers["X-API-Key"] = null;
1059
+ }
1060
+ return {
1061
+ apiKey,
1062
+ defaultHeaders: Object.keys(headers).length > 0 ? headers : undefined,
1063
+ };
1064
+ }
910
1065
  /**
911
1066
  * Get or set custom headers for the client.
912
1067
  * Custom headers are merged with default headers (User-Agent, x-api-key, x-tenant-id).
@@ -916,24 +1071,47 @@ export class Client {
916
1071
  return this._customHeaders;
917
1072
  }
918
1073
  set headers(value) {
1074
+ assertValidHeaders(value);
919
1075
  this._customHeaders = value ?? {};
920
1076
  }
921
1077
  _getOpenAPIBaseUrl() {
922
- return this.apiUrl.endsWith("/v1") ? this.apiUrl.slice(0, -3) : this.apiUrl;
1078
+ const url = this.apiUrl.replace(/\/$/, "");
1079
+ for (const suffix of ["/api/v1", "/api"]) {
1080
+ if (url.endsWith(suffix))
1081
+ return url.slice(0, -suffix.length);
1082
+ }
1083
+ return url;
923
1084
  }
924
- _newOpenAPIClient() {
925
- const defaultHeaders = this.apiKey === undefined && this.workspaceId === undefined
926
- ? { "X-API-Key": null }
927
- : undefined;
928
- const { method: _method, headers: _headers, body: _body, signal: _signal, ...openAPIFetchOptions } = this.fetchOptions;
1085
+ /**
1086
+ * The generated OpenAPI client, rebuilt whenever its auth or headers change.
1087
+ *
1088
+ * The generated client captures `defaultHeaders` and `apiKey` when it is
1089
+ * built, while the handwritten paths recompute `_mergedHeaders` per request.
1090
+ * Rebuilding on change keeps the two halves from diverging when the inputs
1091
+ * move underneath us — a caller mutating the object returned by
1092
+ * `get headers`, or a profile whose auth header only becomes available after
1093
+ * its token is refreshed.
1094
+ */
1095
+ get openAPIClient() {
1096
+ const auth = this._openAPIAuth;
1097
+ const signature = JSON.stringify([auth.apiKey, auth.defaultHeaders]);
1098
+ if (this._openAPIClient === undefined ||
1099
+ this._openAPIClientSignature !== signature) {
1100
+ this._openAPIClientSignature = signature;
1101
+ this._openAPIClient = this._newOpenAPIClient(auth);
1102
+ }
1103
+ return this._openAPIClient;
1104
+ }
1105
+ _newOpenAPIClient(auth = this._openAPIAuth) {
1106
+ const { method: _method, body: _body, signal: _signal, ...openAPIFetchOptions } = this.fetchOptions;
929
1107
  return new OpenAPILangsmith({
930
- apiKey: this.apiKey,
1108
+ apiKey: auth.apiKey,
931
1109
  tenantID: this.workspaceId,
932
1110
  baseURL: this._getOpenAPIBaseUrl(),
933
1111
  timeout: this.timeout_ms,
934
1112
  fetch: this._fetch,
935
1113
  fetchOptions: openAPIFetchOptions,
936
- defaultHeaders,
1114
+ defaultHeaders: auth.defaultHeaders,
937
1115
  });
938
1116
  }
939
1117
  _getPlatformEndpointPath(path) {
@@ -942,35 +1120,42 @@ export class Client {
942
1120
  return needsV1Prefix ? `/v1/platform/${path}` : `/platform/${path}`;
943
1121
  }
944
1122
  get evaluators() {
945
- this._checkStainlessVersion();
1123
+ this._checkStainlessVersion("0.16.0");
946
1124
  return this.openAPIClient.onlineEvaluators;
947
1125
  }
948
1126
  get runs() {
949
- this._checkStainlessVersion();
1127
+ this._checkStainlessVersion("0.16.0");
950
1128
  return this.openAPIClient.runs;
951
1129
  }
952
1130
  /** Access the v2 sandboxes resource (registries, snapshots, boxes). */
953
1131
  get sandboxes() {
954
- this._checkStainlessVersion();
1132
+ this._checkStainlessVersion("0.16.0");
955
1133
  return this.openAPIClient.sandboxes;
956
1134
  }
957
1135
  /** Access the v2 datasets resource (experimentRuns, etc.). */
958
1136
  get datasets() {
959
- this._checkStainlessVersion();
1137
+ this._checkStainlessVersion("0.16.0");
960
1138
  return this.openAPIClient.datasets;
961
1139
  }
1140
+ /** Access the annotation queues resource (runs, items). */
1141
+ get annotationQueues() {
1142
+ // The items endpoints landed in backend 0.16.14; the rest are older.
1143
+ this._checkStainlessVersion("0.16.14");
1144
+ return this.openAPIClient.annotationQueues;
1145
+ }
962
1146
  /** Access the threads resource (query, stats, listTraces). */
963
1147
  get threads() {
964
- this._checkStainlessVersion();
1148
+ this._checkStainlessVersion("0.16.0");
965
1149
  return this.openAPIClient.threads;
966
1150
  }
967
1151
  /** Access the traces resource (query, listRuns). */
968
1152
  get traces() {
969
- this._checkStainlessVersion();
1153
+ this._checkStainlessVersion("0.16.0");
970
1154
  return this.openAPIClient.traces;
971
1155
  }
972
1156
  /** Access the public shared-run resource. */
973
1157
  get public() {
1158
+ this._checkStainlessVersion("0.16.0");
974
1159
  return this.openAPIClient.public;
975
1160
  }
976
1161
  async processInputs(inputs) {
@@ -1459,15 +1644,13 @@ export class Client {
1459
1644
  }
1460
1645
  return json;
1461
1646
  }
1462
- _checkStainlessVersion() {
1463
- if (this._stainlessVersionChecked)
1647
+ _checkStainlessVersion(minVersion) {
1648
+ if (this._stainlessVersionsChecked.has(minVersion))
1464
1649
  return;
1465
- this._stainlessVersionChecked = true;
1650
+ this._stainlessVersionsChecked.add(minVersion);
1466
1651
  this._ensureServerInfo()
1467
1652
  .then((serverInfo) => {
1468
- if (serverInfo?.version) {
1469
- _checkBackendVersion(serverInfo.version);
1470
- }
1653
+ _checkBackendVersion(serverInfo?.version, minVersion);
1471
1654
  })
1472
1655
  .catch(() => {
1473
1656
  // _ensureServerInfo handles and logs its own errors
@@ -1498,6 +1681,20 @@ export class Client {
1498
1681
  const serverInfo = await this._ensureServerInfo();
1499
1682
  return serverInfo.instance_flags?.sdb_query_enabled === true;
1500
1683
  }
1684
+ /**
1685
+ * Throw on SmithDB-only deployments, warn elsewhere. Call only when run-level
1686
+ * feedback has no sessionId.
1687
+ */
1688
+ async _checkFeedbackSessionId() {
1689
+ const docs = "https://docs.langchain.com/langsmith/smithdb-sdk-migration#feedback-create";
1690
+ const serverInfo = await this._ensureServerInfo();
1691
+ if (getQueryBackend(serverInfo.instance_flags) === QueryBackend.SMITHDB_ONLY) {
1692
+ throw new Error(`sessionId must be provided when creating feedback for a run: this ` +
1693
+ `deployment cannot locate the run without it. See ${docs}`);
1694
+ }
1695
+ warnOnce(`Creating feedback for a run without sessionId is deprecated and will ` +
1696
+ `stop working in a future release. See ${docs}`);
1697
+ }
1501
1698
  async _getSettings() {
1502
1699
  if (!this.settings) {
1503
1700
  this.settings = this._get("/settings");
@@ -2016,7 +2213,22 @@ export class Client {
2016
2213
  return res;
2017
2214
  });
2018
2215
  }
2216
+ /** @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. */
2019
2217
  async readRun(runId, { loadChildRuns } = { loadChildRuns: false }) {
2218
+ warnOnce("readRun() is deprecated and will be removed after Jan 31, 2027. " +
2219
+ "Use client.runs.retrieve() instead. " +
2220
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-retrieve for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_READ_RUN" });
2221
+ return this._readRun(runId, { loadChildRuns });
2222
+ }
2223
+ /**
2224
+ * Fetch a run without emitting the `readRun()` deprecation warning.
2225
+ *
2226
+ * Internal callers use this so that a supported method doesn't warn about a
2227
+ * deprecated one the caller never invoked.
2228
+ *
2229
+ * @internal
2230
+ */
2231
+ async _readRun(runId, { loadChildRuns } = { loadChildRuns: false }) {
2020
2232
  assertUuid(runId);
2021
2233
  let run = _normalizeRunTimestamps(await this._get(`/runs/${runId}`));
2022
2234
  if (loadChildRuns) {
@@ -2024,7 +2236,11 @@ export class Client {
2024
2236
  }
2025
2237
  return run;
2026
2238
  }
2239
+ /** @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. */
2027
2240
  async getRunUrl({ runId, run, projectOpts, }) {
2241
+ warnOnce("getRunUrl() is deprecated and will be removed after Jan 31, 2027. " +
2242
+ "Use client.runs.getURL() instead. " +
2243
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-get-url for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_GET_RUN_URL" });
2028
2244
  if (run !== undefined) {
2029
2245
  let sessionId;
2030
2246
  if (run.session_id) {
@@ -2046,7 +2262,9 @@ export class Client {
2046
2262
  return `${this.getHostUrl()}/o/${tenantId}/projects/p/${sessionId}/r/${run.id}?poll=true`;
2047
2263
  }
2048
2264
  else if (runId !== undefined) {
2049
- const run_ = await this.readRun(runId);
2265
+ // Via _readRun() rather than readRun() so callers don't also get a
2266
+ // readRun deprecation warning for a method they never called.
2267
+ const run_ = await this._readRun(runId);
2050
2268
  if (!run_.app_path) {
2051
2269
  throw new Error(`Run ${runId} has no app_path`);
2052
2270
  }
@@ -2058,7 +2276,7 @@ export class Client {
2058
2276
  }
2059
2277
  }
2060
2278
  async _loadChildRuns(run) {
2061
- const childRuns = await toArray(this.listRuns({
2279
+ const childRuns = await toArray(this._listRuns({
2062
2280
  isRoot: false,
2063
2281
  projectId: run.session_id,
2064
2282
  traceId: run.trace_id,
@@ -2091,6 +2309,7 @@ export class Client {
2091
2309
  }
2092
2310
  /**
2093
2311
  * List runs from the LangSmith server.
2312
+ * @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.
2094
2313
  * @param projectId - The ID of the project to filter by.
2095
2314
  * @param projectName - The name of the project to filter by.
2096
2315
  * @param parentRunId - The ID of the parent run to filter by.
@@ -2172,6 +2391,20 @@ export class Client {
2172
2391
  * });
2173
2392
  */
2174
2393
  async *listRuns(props) {
2394
+ warnOnce("listRuns() is deprecated and will be removed after Jan 31, 2027. " +
2395
+ "Use client.runs.query() instead. " +
2396
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#runs-query for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_LIST_RUNS" });
2397
+ yield* this._listRuns(props);
2398
+ }
2399
+ /**
2400
+ * List runs without emitting the `listRuns()` deprecation warning.
2401
+ *
2402
+ * Internal callers use this so that a supported method doesn't warn about a
2403
+ * deprecated one the caller never invoked.
2404
+ *
2405
+ * @internal
2406
+ */
2407
+ async *_listRuns(props) {
2175
2408
  const { projectId, projectName, parentRunId, traceId, referenceExampleId, startTime, executionOrder, isRoot, runType, error, id, query, filter, traceFilter, treeFilter, limit, select, order, } = props;
2176
2409
  let projectIds = [];
2177
2410
  if (projectId) {
@@ -2305,7 +2538,11 @@ export class Client {
2305
2538
  }
2306
2539
  }
2307
2540
  }
2541
+ /** @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. */
2308
2542
  async *readThread(props) {
2543
+ warnOnce("readThread() is deprecated and will be removed after Jan 31, 2027. " +
2544
+ "Use client.threads.listTraces() instead. " +
2545
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#threads-list-traces for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_READ_THREAD" });
2309
2546
  const { threadId, projectId, projectName, isRoot = true, limit, filter: userFilter, order = "asc", } = props;
2310
2547
  if (!projectId && !projectName) {
2311
2548
  throw new Error("threadId requires projectId or projectName");
@@ -2314,7 +2551,9 @@ export class Client {
2314
2551
  const combinedFilter = userFilter
2315
2552
  ? `and(${threadFilter}, ${userFilter})`
2316
2553
  : threadFilter;
2317
- yield* this.listRuns({
2554
+ // Via _listRuns() rather than listRuns(): readThread() already warned, and it
2555
+ // points at threads.listTraces() rather than listRuns()'s runs.query().
2556
+ yield* this._listRuns({
2318
2557
  projectId: projectId ?? undefined,
2319
2558
  projectName: projectName ?? undefined,
2320
2559
  isRoot,
@@ -2323,7 +2562,11 @@ export class Client {
2323
2562
  order,
2324
2563
  });
2325
2564
  }
2565
+ /** @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. */
2326
2566
  async listThreads(props) {
2567
+ warnOnce("listThreads() is deprecated and will be removed after Jan 31, 2027. " +
2568
+ "Use client.threads.query() instead. " +
2569
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#threads-query for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_LIST_THREADS" });
2327
2570
  const { projectId, projectName, limit, offset = 0, filter, startTime, isRoot = true, } = props;
2328
2571
  if (!projectId && !projectName) {
2329
2572
  throw new Error("Either projectId or projectName must be provided");
@@ -2473,7 +2716,11 @@ export class Client {
2473
2716
  const result = await response.json();
2474
2717
  return result;
2475
2718
  }
2719
+ /** @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. */
2476
2720
  async shareRun(runId, { shareId } = {}) {
2721
+ warnOnce("shareRun() is deprecated and will be removed after Jan 31, 2027. " +
2722
+ "Use client.runs.share.create() instead. " +
2723
+ "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" });
2477
2724
  const data = {
2478
2725
  run_id: runId,
2479
2726
  share_token: shareId || uuid.v4(),
@@ -2497,7 +2744,11 @@ export class Client {
2497
2744
  }
2498
2745
  return `${this.getHostUrl()}/public/${result["share_token"]}/r`;
2499
2746
  }
2747
+ /** @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. */
2500
2748
  async unshareRun(runId) {
2749
+ warnOnce("unshareRun() is deprecated and will be removed after Jan 31, 2027. " +
2750
+ "Use client.runs.share.delete() instead. " +
2751
+ "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" });
2501
2752
  assertUuid(runId);
2502
2753
  await this.caller.call(async () => {
2503
2754
  const res = await this._fetch(`${this.apiUrl}/runs/${runId}/share`, {
@@ -2510,7 +2761,14 @@ export class Client {
2510
2761
  return res;
2511
2762
  });
2512
2763
  }
2764
+ /** @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. */
2513
2765
  async readRunSharedLink(runId) {
2766
+ warnOnce("readRunSharedLink() is deprecated and will be removed after Jan 31, 2027. " +
2767
+ 'Use client.runs.retrieve({ selects: ["SHARE_URL"] }) instead. ' +
2768
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide.", {
2769
+ type: "DeprecationWarning",
2770
+ code: "LANGSMITH_DEPRECATED_READ_RUN_SHARED_LINK",
2771
+ });
2514
2772
  assertUuid(runId);
2515
2773
  const response = await this.caller.call(async () => {
2516
2774
  const res = await this._fetch(`${this.apiUrl}/runs/${runId}/share`, {
@@ -2528,7 +2786,14 @@ export class Client {
2528
2786
  }
2529
2787
  return `${this.getHostUrl()}/public/${result["share_token"]}/r`;
2530
2788
  }
2789
+ /** @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. */
2531
2790
  async listSharedRuns(shareToken, { runIds, } = {}) {
2791
+ warnOnce("listSharedRuns() is deprecated and will be removed after Jan 31, 2027. " +
2792
+ "Use client.public.runs.query() instead. " +
2793
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#share-and-read-public-runs for the migration guide.", {
2794
+ type: "DeprecationWarning",
2795
+ code: "LANGSMITH_DEPRECATED_LIST_SHARED_RUNS",
2796
+ });
2532
2797
  const queryParams = new URLSearchParams({
2533
2798
  share_token: shareToken,
2534
2799
  });
@@ -3592,13 +3857,19 @@ export class Client {
3592
3857
  return res;
3593
3858
  });
3594
3859
  }
3595
- async createFeedback(runId, key, { score, value, correction, comment, sourceInfo, feedbackSourceType = "api", sourceRunId, feedbackId, feedbackConfig, projectId, comparativeExperimentId, sessionId, startTime, extendTraceRetention, }) {
3860
+ async createFeedback(runIdOrParams, keyArg, optionsArg) {
3861
+ const { runId = null, key, score, value, correction, comment, sourceInfo, feedbackSourceType = "api", sourceRunId, feedbackId, feedbackConfig, projectId, comparativeExperimentId, sessionId, startTime, extendTraceRetention, } = typeof runIdOrParams === "object" && runIdOrParams !== null
3862
+ ? runIdOrParams
3863
+ : { runId: runIdOrParams, key: keyArg, ...optionsArg };
3596
3864
  if (!runId && !projectId) {
3597
3865
  throw new Error("One of runId or projectId must be provided");
3598
3866
  }
3599
3867
  if (runId && projectId) {
3600
3868
  throw new Error("Only one of runId or projectId can be provided");
3601
3869
  }
3870
+ if (runId && sessionId === undefined) {
3871
+ await this._checkFeedbackSessionId();
3872
+ }
3602
3873
  const feedback_source = {
3603
3874
  type: feedbackSourceType ?? "api",
3604
3875
  metadata: sourceInfo ?? {},
@@ -4111,8 +4382,9 @@ export class Client {
4111
4382
  * - `RunKey[]` (preferred): each entry carries the run's full lookup key, so
4112
4383
  * it can be located directly without a scan. Required for workspaces served
4113
4384
  * by SmithDB; routes to `POST /runs/by-key`.
4114
- * - `string[]`: a plain list of run IDs. This path will be deprecated in a
4115
- * future release; prefer the key form. Routes to `POST /runs`.
4385
+ * - `string[]`: a plain list of run IDs. **Deprecated**: this path will be
4386
+ * removed after Jan 31, 2027; prefer the key form. Routes to `POST /runs`.
4387
+ * See https://docs.langchain.com/langsmith/smithdb-sdk-migration#annotation-queues-add-runs.
4116
4388
  *
4117
4389
  * If every element is a string (or the list is empty) it is treated as run
4118
4390
  * IDs; otherwise the list is treated as `RunKey` objects.
@@ -4143,6 +4415,12 @@ export class Client {
4143
4415
  }));
4144
4416
  }
4145
4417
  else {
4418
+ warnOnce("Passing run IDs as strings to addRunsToAnnotationQueue() is deprecated and will be removed after Jan 31, 2027. " +
4419
+ "Use RunKey[] instead. " +
4420
+ "See https://docs.langchain.com/langsmith/smithdb-sdk-migration#annotation-queues-add-runs for the migration guide.", {
4421
+ type: "DeprecationWarning",
4422
+ code: "LANGSMITH_DEPRECATED_ADD_RUNS_STRING_IDS",
4423
+ });
4146
4424
  url = base;
4147
4425
  body = JSON.stringify(runs.map((id, i) => assertUuid(id, `runs[${i}]`).toString()));
4148
4426
  }
@@ -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 = [];