langsmith 0.7.6 → 0.7.8

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.
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._ExperimentManager = void 0;
4
4
  exports.evaluate = evaluate;
5
5
  exports._reorderResultRowsByExampleIndex = _reorderResultRowsByExampleIndex;
6
+ exports._extractEvaluatorFeedbackKeys = _extractEvaluatorFeedbackKeys;
7
+ exports._collectEvaluatorKeys = _collectEvaluatorKeys;
6
8
  exports._mapWithConcurrency = _mapWithConcurrency;
7
9
  const index_js_1 = require("../index.cjs");
8
10
  const traceable_js_1 = require("../traceable.cjs");
@@ -888,14 +890,40 @@ Try setting "LANGSMITH_TRACING=true" in your environment.`);
888
890
  example,
889
891
  };
890
892
  }
893
+ // best effort feedback key extraction using regex parsing.
894
+ // may be fragile but seems okay as a best effort option and doesn't break anything significant.
895
+ // TODO: find a better way to resolve this.
896
+ function _extractEvaluatorFeedbackKeys(evaluator) {
897
+ const name = evaluator.name;
898
+ const fallback = name && name.length > 0 ? [name] : [];
899
+ try {
900
+ const source = typeof evaluator === "function" ? evaluator.toString() : "";
901
+ if (!source)
902
+ return fallback;
903
+ // Match `key: "literal"`, `"key": "literal"`, or backtick literals without
904
+ // interpolation. Word boundaries avoid matching `keys`, and the required
905
+ // colon + quoted value avoids matching destructuring/`for (const key of)`.
906
+ const regex = /["']?\bkey\b["']?\s*:\s*(?:"([^"]+)"|'([^']+)'|`([^`$]+)`)/g;
907
+ const keys = [];
908
+ let match;
909
+ while ((match = regex.exec(source)) !== null) {
910
+ const value = match[1] ?? match[2] ?? match[3];
911
+ if (value)
912
+ keys.push(value);
913
+ }
914
+ const unique = [...new Set(keys)];
915
+ return unique.length > 0 ? unique : fallback;
916
+ }
917
+ catch {
918
+ return fallback;
919
+ }
920
+ }
891
921
  function _collectEvaluatorKeys(evaluators) {
892
922
  if (!evaluators)
893
923
  return [];
894
924
  const keys = [];
895
925
  for (const ev of evaluators) {
896
- const name = ev.name;
897
- if (name && name.length > 0)
898
- keys.push(name);
926
+ keys.push(..._extractEvaluatorFeedbackKeys(ev));
899
927
  }
900
928
  return keys;
901
929
  }
@@ -265,6 +265,8 @@ declare class ExperimentResults implements AsyncIterableIterator<ExperimentResul
265
265
  processData(manager: _ExperimentManager): Promise<void>;
266
266
  get length(): number;
267
267
  }
268
+ export declare function _extractEvaluatorFeedbackKeys(evaluator: EvaluatorT | RunEvaluator): string[];
269
+ export declare function _collectEvaluatorKeys(evaluators: Array<EvaluatorT | RunEvaluator> | undefined): string[];
268
270
  /**
269
271
  * Map over an iterable with bounded concurrency using p-queue.
270
272
  * Results are yielded as soon as they resolve (input order is not preserved).
@@ -881,14 +881,40 @@ Try setting "LANGSMITH_TRACING=true" in your environment.`);
881
881
  example,
882
882
  };
883
883
  }
884
- function _collectEvaluatorKeys(evaluators) {
884
+ // best effort feedback key extraction using regex parsing.
885
+ // may be fragile but seems okay as a best effort option and doesn't break anything significant.
886
+ // TODO: find a better way to resolve this.
887
+ export function _extractEvaluatorFeedbackKeys(evaluator) {
888
+ const name = evaluator.name;
889
+ const fallback = name && name.length > 0 ? [name] : [];
890
+ try {
891
+ const source = typeof evaluator === "function" ? evaluator.toString() : "";
892
+ if (!source)
893
+ return fallback;
894
+ // Match `key: "literal"`, `"key": "literal"`, or backtick literals without
895
+ // interpolation. Word boundaries avoid matching `keys`, and the required
896
+ // colon + quoted value avoids matching destructuring/`for (const key of)`.
897
+ const regex = /["']?\bkey\b["']?\s*:\s*(?:"([^"]+)"|'([^']+)'|`([^`$]+)`)/g;
898
+ const keys = [];
899
+ let match;
900
+ while ((match = regex.exec(source)) !== null) {
901
+ const value = match[1] ?? match[2] ?? match[3];
902
+ if (value)
903
+ keys.push(value);
904
+ }
905
+ const unique = [...new Set(keys)];
906
+ return unique.length > 0 ? unique : fallback;
907
+ }
908
+ catch {
909
+ return fallback;
910
+ }
911
+ }
912
+ export function _collectEvaluatorKeys(evaluators) {
885
913
  if (!evaluators)
886
914
  return [];
887
915
  const keys = [];
888
916
  for (const ev of evaluators) {
889
- const name = ev.name;
890
- if (name && name.length > 0)
891
- keys.push(name);
917
+ keys.push(..._extractEvaluatorFeedbackKeys(ev));
892
918
  }
893
919
  return keys;
894
920
  }
package/dist/index.cjs CHANGED
@@ -18,6 +18,6 @@ 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.7.6";
21
+ exports.__version__ = "0.7.8";
22
22
  // Metadata key to hide a traced run from LangSmith's Messages View.
23
23
  exports.LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
package/dist/index.d.ts CHANGED
@@ -5,5 +5,5 @@ 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.7.6";
8
+ export declare const __version__ = "0.7.8";
9
9
  export declare const LS_MESSAGE_VIEW_EXCLUDE: "ls_message_view_exclude";
package/dist/index.js CHANGED
@@ -5,6 +5,6 @@ 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.7.6";
8
+ export const __version__ = "0.7.8";
9
9
  // Metadata key to hide a traced run from LangSmith's Messages View.
10
10
  export const LS_MESSAGE_VIEW_EXCLUDE = "ls_message_view_exclude";
@@ -107,11 +107,25 @@ class CommandHandle {
107
107
  writable: true,
108
108
  value: void 0
109
109
  });
110
+ Object.defineProperty(this, "_onStdout", {
111
+ enumerable: true,
112
+ configurable: true,
113
+ writable: true,
114
+ value: void 0
115
+ });
116
+ Object.defineProperty(this, "_onStderr", {
117
+ enumerable: true,
118
+ configurable: true,
119
+ writable: true,
120
+ value: void 0
121
+ });
110
122
  this._stream = messageStream;
111
123
  this._control = control;
112
124
  this._sandbox = sandbox;
113
125
  this._lastStdoutOffset = options?.stdoutOffset ?? 0;
114
126
  this._lastStderrOffset = options?.stderrOffset ?? 0;
127
+ this._onStdout = options?.onStdout;
128
+ this._onStderr = options?.onStderr;
115
129
  // New executions (no commandId): _ensureStarted reads "started".
116
130
  // Reconnections (commandId set): skip since reconnect streams
117
131
  // don't send a "started" message.
@@ -221,10 +235,12 @@ class CommandHandle {
221
235
  if (chunk.stream === "stdout") {
222
236
  this._lastStdoutOffset =
223
237
  chunk.offset + new TextEncoder().encode(chunk.data).length;
238
+ this._onStdout?.(chunk.data);
224
239
  }
225
240
  else {
226
241
  this._lastStderrOffset =
227
242
  chunk.offset + new TextEncoder().encode(chunk.data).length;
243
+ this._onStderr?.(chunk.data);
228
244
  }
229
245
  yield chunk;
230
246
  }
@@ -45,6 +45,8 @@ export declare class CommandHandle {
45
45
  private _lastStdoutOffset;
46
46
  private _lastStderrOffset;
47
47
  private _started;
48
+ private _onStdout?;
49
+ private _onStderr?;
48
50
  /**
49
51
  * Read the 'started' message to populate commandId and pid.
50
52
  *
@@ -104,11 +104,25 @@ export class CommandHandle {
104
104
  writable: true,
105
105
  value: void 0
106
106
  });
107
+ Object.defineProperty(this, "_onStdout", {
108
+ enumerable: true,
109
+ configurable: true,
110
+ writable: true,
111
+ value: void 0
112
+ });
113
+ Object.defineProperty(this, "_onStderr", {
114
+ enumerable: true,
115
+ configurable: true,
116
+ writable: true,
117
+ value: void 0
118
+ });
107
119
  this._stream = messageStream;
108
120
  this._control = control;
109
121
  this._sandbox = sandbox;
110
122
  this._lastStdoutOffset = options?.stdoutOffset ?? 0;
111
123
  this._lastStderrOffset = options?.stderrOffset ?? 0;
124
+ this._onStdout = options?.onStdout;
125
+ this._onStderr = options?.onStderr;
112
126
  // New executions (no commandId): _ensureStarted reads "started".
113
127
  // Reconnections (commandId set): skip since reconnect streams
114
128
  // don't send a "started" message.
@@ -218,10 +232,12 @@ export class CommandHandle {
218
232
  if (chunk.stream === "stdout") {
219
233
  this._lastStdoutOffset =
220
234
  chunk.offset + new TextEncoder().encode(chunk.data).length;
235
+ this._onStdout?.(chunk.data);
221
236
  }
222
237
  else {
223
238
  this._lastStderrOffset =
224
239
  chunk.offset + new TextEncoder().encode(chunk.data).length;
240
+ this._onStderr?.(chunk.data);
225
241
  }
226
242
  yield chunk;
227
243
  }
@@ -197,7 +197,8 @@ exports.LangSmithValidationError = LangSmithValidationError;
197
197
  /**
198
198
  * Raised when organization quota limits are exceeded.
199
199
  *
200
- * Users should contact support@langchain.dev to increase quotas.
200
+ * Users should contact technical support via our Support Portal
201
+ * (https://support.langchain.com) to increase quotas.
201
202
  */
202
203
  class LangSmithQuotaExceededError extends LangSmithSandboxError {
203
204
  constructor(message, quotaType) {
@@ -85,7 +85,8 @@ export declare class LangSmithValidationError extends LangSmithSandboxError {
85
85
  /**
86
86
  * Raised when organization quota limits are exceeded.
87
87
  *
88
- * Users should contact support@langchain.dev to increase quotas.
88
+ * Users should contact technical support via our Support Portal
89
+ * (https://support.langchain.com) to increase quotas.
89
90
  */
90
91
  export declare class LangSmithQuotaExceededError extends LangSmithSandboxError {
91
92
  quotaType?: string;
@@ -184,7 +184,8 @@ export class LangSmithValidationError extends LangSmithSandboxError {
184
184
  /**
185
185
  * Raised when organization quota limits are exceeded.
186
186
  *
187
- * Users should contact support@langchain.dev to increase quotas.
187
+ * Users should contact technical support via our Support Portal
188
+ * (https://support.langchain.com) to increase quotas.
188
189
  */
189
190
  export class LangSmithQuotaExceededError extends LangSmithSandboxError {
190
191
  constructor(message, quotaType) {
@@ -225,7 +225,7 @@ class Sandbox {
225
225
  * @internal
226
226
  */
227
227
  async _runWs(command, options = {}) {
228
- const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, idleTimeout, killOnDisconnect, ttlSeconds, pty, } = options;
228
+ const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, commandId, idleTimeout, killOnDisconnect, ttlSeconds, pty, } = options;
229
229
  const dataplaneUrl = this.requireDataplaneUrl();
230
230
  const clientHeaders = this._client.getDefaultHeaders();
231
231
  const [stream, control] = await (0, ws_execute_js_1.runWsStream)(dataplaneUrl, this._client.getApiKey(), command, {
@@ -233,8 +233,7 @@ class Sandbox {
233
233
  env,
234
234
  cwd,
235
235
  shell,
236
- onStdout,
237
- onStderr,
236
+ commandId,
238
237
  idleTimeout,
239
238
  killOnDisconnect,
240
239
  ttlSeconds,
@@ -243,7 +242,10 @@ class Sandbox {
243
242
  ? { headers: clientHeaders }
244
243
  : {}),
245
244
  });
246
- const handle = new command_handle_js_1.CommandHandle(stream, control, this);
245
+ const handle = new command_handle_js_1.CommandHandle(stream, control, this, {
246
+ onStdout,
247
+ onStderr,
248
+ });
247
249
  await handle._ensureStarted();
248
250
  return handle;
249
251
  }
@@ -222,7 +222,7 @@ export class Sandbox {
222
222
  * @internal
223
223
  */
224
224
  async _runWs(command, options = {}) {
225
- const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, idleTimeout, killOnDisconnect, ttlSeconds, pty, } = options;
225
+ const { timeout = 60, env, cwd, shell = "/bin/bash", onStdout, onStderr, commandId, idleTimeout, killOnDisconnect, ttlSeconds, pty, } = options;
226
226
  const dataplaneUrl = this.requireDataplaneUrl();
227
227
  const clientHeaders = this._client.getDefaultHeaders();
228
228
  const [stream, control] = await runWsStream(dataplaneUrl, this._client.getApiKey(), command, {
@@ -230,8 +230,7 @@ export class Sandbox {
230
230
  env,
231
231
  cwd,
232
232
  shell,
233
- onStdout,
234
- onStderr,
233
+ commandId,
235
234
  idleTimeout,
236
235
  killOnDisconnect,
237
236
  ttlSeconds,
@@ -240,7 +239,10 @@ export class Sandbox {
240
239
  ? { headers: clientHeaders }
241
240
  : {}),
242
241
  });
243
- const handle = new CommandHandle(stream, control, this);
242
+ const handle = new CommandHandle(stream, control, this, {
243
+ onStdout,
244
+ onStderr,
245
+ });
244
246
  await handle._ensureStarted();
245
247
  return handle;
246
248
  }
@@ -202,6 +202,12 @@ export interface RunOptions {
202
202
  * When false, returns a CommandHandle for streaming output.
203
203
  */
204
204
  wait?: boolean;
205
+ /**
206
+ * Client-assigned command ID. Executing with an existing command ID
207
+ * re-attaches to that command (get-or-create) instead of starting a
208
+ * new one. Only used by the WebSocket path.
209
+ */
210
+ commandId?: string;
205
211
  /**
206
212
  * Callback invoked with each stdout chunk during streaming execution.
207
213
  * When provided, WebSocket streaming is used.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.7.6",
3
+ "version": "0.7.8",
4
4
  "description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
5
5
  "packageManager": "pnpm@10.33.0",
6
6
  "files": [
@@ -128,8 +128,8 @@
128
128
  "watch:single": "NODE_OPTIONS=--experimental-vm-modules pnpm jest --watch --config jest.config.cjs --testTimeout 100000",
129
129
  "test:vitest": "vitest run --config vitest.config.ts",
130
130
  "test:eval:vitest": "vitest run --config ls.vitest.config.ts",
131
- "lint": "oxlint src/",
132
- "lint:fix": "oxlint --fix src/",
131
+ "lint": "oxlint src/ --ignore-pattern 'src/_openapi_client/**'",
132
+ "lint:fix": "oxlint --fix src/ --ignore-pattern 'src/_openapi_client/**'",
133
133
  "format": "oxfmt --write 'src/**/*.{ts,tsx,mts}'",
134
134
  "format:check": "oxfmt --check 'src/**/*.{ts,tsx,mts}'",
135
135
  "check:types": "tsc --noEmit",