langsmith 0.10.7 → 0.10.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 (101) hide show
  1. package/dist/_openapi_client/client.cjs +26 -2
  2. package/dist/_openapi_client/client.d.ts +15 -6
  3. package/dist/_openapi_client/client.js +27 -3
  4. package/dist/_openapi_client/internal/detect-platform.cjs +1 -1
  5. package/dist/_openapi_client/internal/detect-platform.js +1 -1
  6. package/dist/_openapi_client/resources/annotation-queues/items.cjs +13 -6
  7. package/dist/_openapi_client/resources/annotation-queues/items.d.ts +33 -8
  8. package/dist/_openapi_client/resources/annotation-queues/items.js +13 -6
  9. package/dist/_openapi_client/resources/datasets/datasets.cjs +9 -0
  10. package/dist/_openapi_client/resources/datasets/datasets.d.ts +4 -0
  11. package/dist/_openapi_client/resources/datasets/datasets.js +9 -0
  12. package/dist/_openapi_client/resources/datasets/examples.cjs +26 -0
  13. package/dist/_openapi_client/resources/datasets/examples.d.ts +23 -0
  14. package/dist/_openapi_client/resources/datasets/examples.js +22 -0
  15. package/dist/_openapi_client/resources/fleet/fleet.cjs +54 -0
  16. package/dist/_openapi_client/resources/fleet/fleet.d.ts +9 -0
  17. package/dist/_openapi_client/resources/fleet/fleet.js +17 -0
  18. package/dist/_openapi_client/resources/fleet/threads.cjs +18 -0
  19. package/dist/_openapi_client/resources/fleet/threads.d.ts +19 -0
  20. package/dist/_openapi_client/resources/fleet/threads.js +14 -0
  21. package/dist/_openapi_client/resources/index.cjs +8 -2
  22. package/dist/_openapi_client/resources/index.d.ts +6 -3
  23. package/dist/_openapi_client/resources/index.js +5 -2
  24. package/dist/_openapi_client/resources/info.d.ts +6 -0
  25. package/dist/_openapi_client/resources/issues.cjs +2 -2
  26. package/dist/_openapi_client/resources/issues.d.ts +188 -4
  27. package/dist/_openapi_client/resources/issues.js +2 -2
  28. package/dist/_openapi_client/resources/online-evaluators.cjs +7 -4
  29. package/dist/_openapi_client/resources/online-evaluators.d.ts +63 -4
  30. package/dist/_openapi_client/resources/online-evaluators.js +7 -4
  31. package/dist/_openapi_client/resources/product-feedback.cjs +33 -0
  32. package/dist/_openapi_client/resources/product-feedback.d.ts +77 -0
  33. package/dist/_openapi_client/resources/product-feedback.js +29 -0
  34. package/dist/_openapi_client/resources/runs/runs.d.ts +26 -16
  35. package/dist/_openapi_client/resources/sandboxes/boxes.cjs +44 -4
  36. package/dist/_openapi_client/resources/sandboxes/boxes.d.ts +256 -21
  37. package/dist/_openapi_client/resources/sandboxes/boxes.js +44 -4
  38. package/dist/_openapi_client/resources/sandboxes/registries.d.ts +10 -2
  39. package/dist/_openapi_client/resources/sandboxes/sandboxes.cjs +13 -0
  40. package/dist/_openapi_client/resources/sandboxes/sandboxes.d.ts +169 -14
  41. package/dist/_openapi_client/resources/sandboxes/sandboxes.js +13 -0
  42. package/dist/_openapi_client/resources/sandboxes/snapshots.cjs +10 -6
  43. package/dist/_openapi_client/resources/sandboxes/snapshots.d.ts +37 -6
  44. package/dist/_openapi_client/resources/sandboxes/snapshots.js +10 -6
  45. package/dist/_openapi_client/resources/sessions.cjs +23 -0
  46. package/dist/_openapi_client/resources/sessions.d.ts +732 -0
  47. package/dist/_openapi_client/resources/sessions.js +19 -0
  48. package/dist/_openapi_client/resources/threads/index.cjs +9 -0
  49. package/dist/_openapi_client/resources/threads/index.d.ts +2 -0
  50. package/dist/_openapi_client/resources/threads/index.js +4 -0
  51. package/dist/_openapi_client/resources/threads/share.cjs +61 -0
  52. package/dist/_openapi_client/resources/threads/share.d.ts +71 -0
  53. package/dist/_openapi_client/resources/threads/share.js +57 -0
  54. package/dist/_openapi_client/resources/threads/threads.cjs +143 -0
  55. package/dist/_openapi_client/resources/threads/threads.d.ts +973 -0
  56. package/dist/_openapi_client/resources/threads/threads.js +106 -0
  57. package/dist/_openapi_client/resources/threads.cjs +15 -67
  58. package/dist/_openapi_client/resources/threads.d.ts +1 -709
  59. package/dist/_openapi_client/resources/threads.js +1 -65
  60. package/dist/_openapi_client/resources/traces.d.ts +7 -1
  61. package/dist/_openapi_client/version.cjs +1 -1
  62. package/dist/_openapi_client/version.js +1 -1
  63. package/dist/address.cjs +176 -99
  64. package/dist/address.d.ts +63 -8
  65. package/dist/address.js +170 -90
  66. package/dist/anonymizer/index.cjs +1 -1
  67. package/dist/anonymizer/index.js +1 -1
  68. package/dist/client.cjs +39 -19
  69. package/dist/client.d.ts +20 -4
  70. package/dist/client.js +34 -14
  71. package/dist/experimental/otel/exporter.cjs +21 -4
  72. package/dist/experimental/otel/exporter.d.ts +4 -2
  73. package/dist/experimental/otel/exporter.js +21 -4
  74. package/dist/index.cjs +5 -2
  75. package/dist/index.d.ts +2 -2
  76. package/dist/index.js +2 -2
  77. package/dist/run_trees.cjs +26 -43
  78. package/dist/run_trees.d.ts +4 -4
  79. package/dist/run_trees.js +23 -40
  80. package/dist/sandbox/client.cjs +33 -4
  81. package/dist/sandbox/client.d.ts +4 -0
  82. package/dist/sandbox/client.js +34 -5
  83. package/dist/sandbox/command_handle.cjs +8 -0
  84. package/dist/sandbox/command_handle.js +8 -0
  85. package/dist/sandbox/sandbox.cjs +7 -0
  86. package/dist/sandbox/sandbox.js +7 -0
  87. package/dist/sandbox/service_url.cjs +9 -1
  88. package/dist/sandbox/service_url.d.ts +2 -1
  89. package/dist/sandbox/service_url.js +9 -1
  90. package/dist/sandbox/tracing.cjs +13 -0
  91. package/dist/sandbox/tracing.d.ts +1 -0
  92. package/dist/sandbox/tracing.js +10 -0
  93. package/dist/schemas.d.ts +3 -3
  94. package/dist/traceable.cjs +5 -4
  95. package/dist/traceable.js +4 -3
  96. package/dist/utils/{agent_addressing.cjs → addressing.cjs} +22 -23
  97. package/dist/utils/{agent_addressing.d.ts → addressing.d.ts} +5 -8
  98. package/dist/utils/{agent_addressing.js → addressing.js} +23 -23
  99. package/dist/utils/env.cjs +6 -4
  100. package/dist/utils/env.js +6 -4
  101. package/package.json +1 -1
package/dist/address.js CHANGED
@@ -1,21 +1,34 @@
1
- // Wire key per field; env var is `LANGSMITH_<WIRE KEY>`.
2
- const FIELDS = {
3
- agentId: "agent_id",
4
- agentEnvironment: "agent_environment",
5
- };
1
+ /**
2
+ * (beta) Addresses that name where runs are sent instead of a project.
3
+ * Enabled per workspace; a workspace without it rejects the runs.
4
+ *
5
+ * An `Address` names a tracing project held by a feature: an `AgentAddress`, an
6
+ * `ExperimentAddress` or the workspace's `EvaluatorAddress`. Any of them can be resolved to
7
+ * its project. Only an `AgentAddress` can receive traces, and ingestion rejects the
8
+ * others at its entry points.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { AgentAddress, traceable } from "langsmith";
13
+ *
14
+ * const support = new AgentAddress("customer-support", "production");
15
+ * const handle = traceable(fn, { address: support });
16
+ * ```
17
+ */
18
+ import { getEnvironmentVariable } from "./utils/env.js";
19
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
6
20
  // The server's agent id rule: a DNS label, so a hostname can carry the id.
7
21
  const AGENT_ID_PATTERN = /^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$/;
8
- // Not `utils/env`: it imports the package index, which imports this module.
9
- function getEnv(name) {
10
- try {
11
- // eslint-disable-next-line no-process-env
12
- return typeof process !== "undefined" ? process.env?.[name] : undefined;
13
- }
14
- catch {
15
- return undefined;
16
- }
17
- }
18
- /** The `LANGSMITH_AGENT_*` / project env vars name half an address, or both. */
22
+ const ENVIRONMENTS = [
23
+ "local",
24
+ "development",
25
+ "staging",
26
+ "production",
27
+ ];
28
+ // The wire form of an agent address. The parts are validated by `AgentAddress`.
29
+ const LRN_PATTERN = /^lrn:agents\/([^/]+)\/environments\/([^/]+)$/;
30
+ const ENV_NAMES = ["LANGSMITH_AGENT_ID", "LANGSMITH_AGENT_ENVIRONMENT"];
31
+ /** (beta) The `LANGSMITH_AGENT_*` / project env vars name half an address, or both. */
19
32
  export class EnvAddressError extends Error {
20
33
  constructor(message) {
21
34
  super(message);
@@ -23,98 +36,165 @@ export class EnvAddressError extends Error {
23
36
  }
24
37
  }
25
38
  /**
26
- * @internal Validate `value` and return a frozen copy of its fields.
27
- * @throws If it isn't an object with exactly the address fields, or a value is invalid.
39
+ * (beta) The address of an agent's environment.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * new AgentAddress("customer-support", "production");
44
+ * ```
28
45
  */
29
- export function normalizeAddress(value) {
30
- if (value == null || typeof value !== "object" || Array.isArray(value)) {
31
- throw new Error("`address` must be an object: { agentId, agentEnvironment }.");
46
+ export class AgentAddress {
47
+ /**
48
+ * @param id 1 to 63 lowercase ASCII letters, digits or hyphens, starting
49
+ * with a letter and ending with a letter or digit. The server creates the
50
+ * agent on first use.
51
+ * @param environment One of `local`, `development`, `staging` or `production`, in
52
+ * any case.
53
+ * @throws If a value is invalid.
54
+ */
55
+ constructor(id, environment) {
56
+ Object.defineProperty(this, "id", {
57
+ enumerable: true,
58
+ configurable: true,
59
+ writable: true,
60
+ value: void 0
61
+ });
62
+ /** Always lowercase. */
63
+ Object.defineProperty(this, "environment", {
64
+ enumerable: true,
65
+ configurable: true,
66
+ writable: true,
67
+ value: void 0
68
+ });
69
+ if (typeof id !== "string" || !AGENT_ID_PATTERN.test(id)) {
70
+ throw new Error("Address agent id must be 1 to 63 lowercase ASCII letters, digits, or " +
71
+ "hyphens, start with a letter, and end with a letter or digit, got " +
72
+ `${JSON.stringify(id)}. Use an id such as "support-agent".`);
73
+ }
74
+ const normalized = typeof environment === "string" ? environment.toLowerCase() : undefined;
75
+ if (normalized === undefined || !ENVIRONMENTS.includes(normalized)) {
76
+ throw new Error(`Address environment must be one of ${ENVIRONMENTS.join(", ")}, got ` +
77
+ `${JSON.stringify(environment)}.`);
78
+ }
79
+ this.id = id;
80
+ this.environment = normalized;
81
+ Object.freeze(this);
82
+ }
83
+ toApiAddress() {
84
+ return {
85
+ kind: "AGENT",
86
+ id: this.id,
87
+ environment: this.environment.toUpperCase(),
88
+ };
32
89
  }
33
- const fields = value;
34
- const unknown = Object.keys(fields).filter((key) => !(key in FIELDS));
35
- if (unknown.length > 0) {
36
- throw new Error(`Unknown address fields: ${unknown.join(", ")}.`);
90
+ /** @internal */
91
+ _toLrn() {
92
+ return `lrn:agents/${this.id}/environments/${this.environment}`;
37
93
  }
38
- for (const name of Object.keys(FIELDS)) {
39
- const field = fields[name];
40
- if (typeof field !== "string" || field === "") {
41
- throw new Error(`Address ${name} must be a non-empty string.`);
94
+ /**
95
+ * @internal Parse an LRN read from the wire, such as a `baggage` header. The
96
+ * value is untrusted, so it is not echoed in the error.
97
+ * @throws If `value` is not an agent LRN, or names an invalid id or environment.
98
+ */
99
+ static _fromLrn(value) {
100
+ const match = typeof value === "string" ? LRN_PATTERN.exec(value) : null;
101
+ if (match === null) {
102
+ throw new Error("Not an agent address.");
42
103
  }
104
+ return new AgentAddress(match[1], match[2]);
43
105
  }
44
- const { agentId, agentEnvironment } = fields;
45
- if (!AGENT_ID_PATTERN.test(agentId)) {
46
- throw new Error("Address agentId must be 1 to 63 lowercase ASCII letters, digits, or " +
47
- "hyphens, start with a letter, and end with a letter or digit, got " +
48
- `${JSON.stringify(agentId)}. Use an id such as "support-agent".`);
106
+ /**
107
+ * Read the agent named by `LANGSMITH_AGENT_ID` and
108
+ * `LANGSMITH_AGENT_ENVIRONMENT`; `undefined` if neither is set.
109
+ * @throws {EnvAddressError} If only one is set, or a value is invalid.
110
+ */
111
+ static fromEnv() {
112
+ const values = ENV_NAMES.map((name) => getEnvironmentVariable(name));
113
+ if (!values.some(Boolean)) {
114
+ return undefined;
115
+ }
116
+ try {
117
+ const missing = ENV_NAMES.filter((_, i) => !values[i]);
118
+ if (missing.length > 0) {
119
+ throw new Error(`An address needs ${missing.join(" and ")} as well.`);
120
+ }
121
+ return new AgentAddress(values[0], values[1]);
122
+ }
123
+ catch (e) {
124
+ const present = ENV_NAMES.flatMap((name, i) => values[i] ? [`${name}=${JSON.stringify(values[i])}`] : []).join(", ");
125
+ throw new EnvAddressError(`The LANGSMITH_AGENT_* env vars can't address a run (${present}): ${e.message}`);
126
+ }
49
127
  }
50
- return Object.freeze({ agentId, agentEnvironment });
51
128
  }
52
- /** @internal */
53
- export function wireKeys() {
54
- return Object.values(FIELDS);
129
+ /** (beta) The address of an experiment's tracing project. */
130
+ export class ExperimentAddress {
131
+ /**
132
+ * @param id The experiment's UUID.
133
+ * @throws If `id` is not a UUID.
134
+ */
135
+ constructor(id) {
136
+ /** Always lowercase. */
137
+ Object.defineProperty(this, "id", {
138
+ enumerable: true,
139
+ configurable: true,
140
+ writable: true,
141
+ value: void 0
142
+ });
143
+ if (typeof id !== "string" || !UUID_PATTERN.test(id)) {
144
+ throw new Error(`Experiment id must be a UUID, got ${JSON.stringify(id)}.`);
145
+ }
146
+ this.id = id.toLowerCase();
147
+ Object.freeze(this);
148
+ }
149
+ toApiAddress() {
150
+ return { kind: "EXPERIMENT", id: this.id };
151
+ }
55
152
  }
56
- /** @internal */
57
- export function envNames() {
58
- return wireKeys().map((key) => `LANGSMITH_${key.toUpperCase()}`);
153
+ /** (beta) The address of the workspace's shared evaluators project. */
154
+ export class EvaluatorAddress {
155
+ constructor() {
156
+ Object.freeze(this);
157
+ }
158
+ toApiAddress() {
159
+ return { kind: "EVALUATOR" };
160
+ }
59
161
  }
60
162
  /**
61
- * @internal The `address` object of a run / feedback payload. `kind` and
62
- * `environment` are uppercase and case-sensitive on the wire.
163
+ * @internal The ingestion entry-point guard: `value` must be an `AgentAddress` (or
164
+ * absent), and is returned as is. Other addresses and strings are rejected.
165
+ * @throws If `value` is not an `AgentAddress`.
63
166
  */
64
- export function toPayload(address) {
65
- return {
66
- address: {
67
- kind: "AGENT",
68
- id: address.agentId,
69
- environment: address.agentEnvironment.toUpperCase(),
70
- },
71
- };
72
- }
73
- /** @internal Header / replica fields. */
74
- export function toWire(address) {
75
- return {
76
- [FIELDS.agentId]: address.agentId,
77
- [FIELDS.agentEnvironment]: address.agentEnvironment,
78
- };
79
- }
80
- /** @internal `undefined` if no field is set; throws if only some are. */
81
- export function fromWire(values) {
82
- const fields = Object.fromEntries(Object.entries(FIELDS).map(([name, key]) => [
83
- name,
84
- values[key] ?? undefined,
85
- ]));
86
- const missing = Object.entries(FIELDS)
87
- .filter(([name]) => fields[name] === undefined)
88
- .map(([, key]) => key);
89
- if (missing.length === Object.keys(FIELDS).length) {
167
+ export function ensureAgent(value) {
168
+ if (value == null) {
90
169
  return undefined;
91
170
  }
92
- if (missing.length > 0) {
93
- throw new Error(`An address needs ${missing.join(" and ")} as well.`);
171
+ if (value instanceof AgentAddress) {
172
+ return value;
173
+ }
174
+ if (typeof value === "object" &&
175
+ typeof value.toApiAddress === "function") {
176
+ throw new Error(`Only an AgentAddress can receive traces, got ${value.constructor?.name ?? "an unknown address"}.`);
94
177
  }
95
- return normalizeAddress(fields);
178
+ throw new Error("address must be an AgentAddress such as `new AgentAddress(id, environment)`, got " +
179
+ `${typeof value === "string" ? JSON.stringify(value) : typeof value}.`);
96
180
  }
97
181
  /**
98
- * @internal
99
- * @throws {EnvAddressError} If only some `LANGSMITH_AGENT_*` vars are set, or one is invalid.
182
+ * Return `value` if it is an `Address` of any kind, as a lookup takes it.
183
+ * For the calls that only resolve an address to its project, such as
184
+ * `getRunUrl`. Whatever receives traces takes `ensureAgent`.
100
185
  */
101
- export function addressFromEnv() {
102
- const values = Object.fromEntries(wireKeys().map((key, i) => [key, getEnv(envNames()[i]) || undefined]));
103
- try {
104
- return fromWire(values);
186
+ export function ensureAddress(value) {
187
+ if (value == null) {
188
+ return undefined;
105
189
  }
106
- catch (e) {
107
- throw new EnvAddressError(`The LANGSMITH_AGENT_* env vars can't address a run: ${e.message}`);
190
+ if (typeof value === "object" &&
191
+ typeof value.toApiAddress === "function") {
192
+ return value;
108
193
  }
194
+ throw new Error("address must be an AgentAddress, ExperimentAddress or EvaluatorAddress, got " +
195
+ `${typeof value === "string" ? JSON.stringify(value) : typeof value}.`);
109
196
  }
110
- /** @internal Replica id derivation seed. */
111
- export function seed(address) {
112
- return ["agent", ...Object.values(toWire(address))].join("/");
113
- }
114
- /** @internal */
115
- export function sameAddress(a, b) {
116
- if (!a || !b) {
117
- return a === b;
118
- }
119
- return a.agentId === b.agentId && a.agentEnvironment === b.agentEnvironment;
197
+ /** @internal The `LANGSMITH_AGENT_*` env var names an address reads. */
198
+ export function envNames() {
199
+ return ENV_NAMES;
120
200
  }
@@ -224,7 +224,7 @@ exports.DEFAULT_SECRET_RULES = [
224
224
  // - value excludes & and ; so query-string params past the secret survive.
225
225
  // - requires a 6+ char value so short non-secret values are not touched.
226
226
  {
227
- pattern: /\b([A-Za-z0-9_.-]*(?:API[_-]?KEY|SECRET|TOKEN|PASSWORD|PASSWD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY|AUTH[_-]?TOKEN|CLIENT[_-]?SECRET)(?![A-Za-z0-9])(?:[_.-][A-Za-z0-9]+)*["']?\s*[:=]\s*["']?)(?:(?:bearer|token|basic)\s+)?[^\s"'&;]{6,}/gi,
227
+ pattern: /\b([A-Za-z0-9_.-]*(?:API[_-]?KEY[_-]?SALT|LICENSE[_-]?KEY|API[_-]?KEY|SECRET|TOKEN|PASSWORD|PASSWD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY|AUTH[_-]?TOKEN|CLIENT[_-]?SECRET)(?![A-Za-z0-9])(?:[_.-][A-Za-z0-9]+)*["']?\s*[:=]\s*["']?)(?:(?:bearer|token|basic)\s+)?[^\s"'&;]{6,}/gi,
228
228
  replace: `$1${exports.SECRET_PLACEHOLDER}`,
229
229
  },
230
230
  // Authorization / API-key headers. Keep the header name + separator ($1$2)
@@ -219,7 +219,7 @@ export const DEFAULT_SECRET_RULES = [
219
219
  // - value excludes & and ; so query-string params past the secret survive.
220
220
  // - requires a 6+ char value so short non-secret values are not touched.
221
221
  {
222
- pattern: /\b([A-Za-z0-9_.-]*(?:API[_-]?KEY|SECRET|TOKEN|PASSWORD|PASSWD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY|AUTH[_-]?TOKEN|CLIENT[_-]?SECRET)(?![A-Za-z0-9])(?:[_.-][A-Za-z0-9]+)*["']?\s*[:=]\s*["']?)(?:(?:bearer|token|basic)\s+)?[^\s"'&;]{6,}/gi,
222
+ pattern: /\b([A-Za-z0-9_.-]*(?:API[_-]?KEY[_-]?SALT|LICENSE[_-]?KEY|API[_-]?KEY|SECRET|TOKEN|PASSWORD|PASSWD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY|AUTH[_-]?TOKEN|CLIENT[_-]?SECRET)(?![A-Za-z0-9])(?:[_.-][A-Za-z0-9]+)*["']?\s*[:=]\s*["']?)(?:(?:bearer|token|basic)\s+)?[^\s"'&;]{6,}/gi,
223
223
  replace: `$1${SECRET_PLACEHOLDER}`,
224
224
  },
225
225
  // Authorization / API-key headers. Keep the header name + separator ($1$2)
package/dist/client.cjs CHANGED
@@ -48,7 +48,7 @@ const _uuid_js_1 = require("./utils/_uuid.cjs");
48
48
  const sampling_js_1 = require("./utils/sampling.cjs");
49
49
  const warn_js_1 = require("./utils/warn.cjs");
50
50
  const address_js_1 = require("./address.cjs");
51
- const agent_addressing_js_1 = require("./utils/agent_addressing.cjs");
51
+ const addressing_js_1 = require("./utils/addressing.cjs");
52
52
  const v2_migration_js_1 = require("./utils/v2_migration.cjs");
53
53
  const prompts_js_1 = require("./utils/prompts.cjs");
54
54
  const error_js_1 = require("./utils/error.cjs");
@@ -943,7 +943,7 @@ class Client {
943
943
  }
944
944
  // Cache metadata env vars once during construction to avoid repeatedly scanning process.env
945
945
  this.cachedLSEnvVarsForMetadata = (0, env_js_1.getLangSmithEnvVarsMetadata)();
946
- (0, agent_addressing_js_1.warnOnEnv)();
946
+ (0, addressing_js_1.warnOnEnv)();
947
947
  // Initialize prompt cache
948
948
  // Handle backwards compatibility for deprecated `cache` parameter
949
949
  if (config.cache !== undefined && config.disablePromptCache) {
@@ -1233,6 +1233,14 @@ class Client {
1233
1233
  this._checkStainlessVersion("0.16.0");
1234
1234
  return this.openAPIClient.traces;
1235
1235
  }
1236
+ /**
1237
+ * (beta) Access the sessions resource, which resolves an address to the
1238
+ * project its traces go to: `client.sessions.resolve(address.toApiAddress())`.
1239
+ */
1240
+ get sessions() {
1241
+ this._checkStainlessVersion("0.18.0");
1242
+ return this.openAPIClient.sessions;
1243
+ }
1236
1244
  /** Access the public shared-run resource. */
1237
1245
  get public() {
1238
1246
  this._checkStainlessVersion("0.16.0");
@@ -1313,7 +1321,7 @@ class Client {
1313
1321
  }
1314
1322
  async prepareRunCreateOrUpdateInputs(run, options) {
1315
1323
  const runParams = { ...run };
1316
- (0, agent_addressing_js_1.applyToPayload)(runParams, { update: options?.update ?? false });
1324
+ (0, addressing_js_1.applyToPayload)(runParams, { update: options?.update ?? false });
1317
1325
  if (runParams.inputs !== undefined) {
1318
1326
  runParams.inputs = await this.processInputs(runParams.inputs);
1319
1327
  }
@@ -1795,21 +1803,21 @@ class Client {
1795
1803
  ...this._mergedHeaders,
1796
1804
  "Content-Type": "application/json",
1797
1805
  };
1798
- const address = (0, agent_addressing_js_1.checkAddress)(run.address);
1806
+ const address = (0, address_js_1.ensureAgent)(run.address);
1799
1807
  // `RunTree.postRun` passes a built run body, carrying the wire `session_name`.
1800
1808
  const bodySessionName = run.session_name;
1801
- (0, agent_addressing_js_1.rejectConflicting)(run.project_name ?? bodySessionName, address);
1809
+ (0, addressing_js_1.rejectConflicting)(run.project_name ?? bodySessionName, address);
1802
1810
  const session_name = run.project_name;
1803
1811
  delete run.project_name;
1804
1812
  if (!session_name && bodySessionName == null && !address) {
1805
1813
  try {
1806
- run.address = (0, agent_addressing_js_1.resolveFromEnv)()[1];
1814
+ run.address = (0, addressing_js_1.resolveFromEnv)()[1];
1807
1815
  }
1808
1816
  catch (e) {
1809
1817
  if (!(e instanceof address_js_1.EnvAddressError)) {
1810
1818
  throw e;
1811
1819
  }
1812
- (0, agent_addressing_js_1.logUntraced)(e);
1820
+ (0, addressing_js_1.logUntraced)(e);
1813
1821
  return;
1814
1822
  }
1815
1823
  }
@@ -2222,8 +2230,8 @@ class Client {
2222
2230
  if (run.events) {
2223
2231
  run.events = this._filterNewTokenEvents(run.events);
2224
2232
  }
2225
- // On `run` too: the direct path below serializes it.
2226
- (0, agent_addressing_js_1.applyToPayload)(run, { update: true });
2233
+ // Fail on a bad address now; the queued path validates again when built.
2234
+ (0, address_js_1.ensureAgent)(run.address);
2227
2235
  // TODO: Untangle types
2228
2236
  const data = { ...run, id: runId };
2229
2237
  if (!this._filterForSampling([data]).length) {
@@ -2271,9 +2279,11 @@ class Client {
2271
2279
  if (options?.workspaceId !== undefined) {
2272
2280
  headers["x-tenant-id"] = options.workspaceId;
2273
2281
  }
2274
- const body = (0, index_js_4.serialize)(run.extra
2275
- ? mergeRuntimeEnvIntoRun(run, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo, this.tracingSampleRate)
2276
- : run, `Serializing payload to update run with id: ${runId}`);
2282
+ const wireRun = { ...run };
2283
+ (0, addressing_js_1.applyToPayload)(wireRun, { update: true });
2284
+ const body = (0, index_js_4.serialize)(wireRun.extra
2285
+ ? mergeRuntimeEnvIntoRun(wireRun, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo, this.tracingSampleRate)
2286
+ : wireRun, `Serializing payload to update run with id: ${runId}`);
2277
2287
  await this.caller.call(async () => {
2278
2288
  const res = await this._fetch(`${options?.apiUrl ?? this.apiUrl}/runs/${runId}`, {
2279
2289
  method: "PATCH",
@@ -2310,14 +2320,15 @@ class Client {
2310
2320
  return run;
2311
2321
  }
2312
2322
  /** @deprecated Use `client.runs.getURL()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration-runs#runs-get-url for the migration guide. Will be removed after Jan 31, 2027. */
2313
- async getRunUrl({ runId, run, projectOpts, }) {
2323
+ async getRunUrl({ runId, run, projectOpts, address: rawAddress, }) {
2314
2324
  (0, warn_js_1.warnOnce)("getRunUrl() is deprecated and will be removed after Jan 31, 2027. " +
2315
2325
  "Use client.runs.getURL() instead. " +
2316
2326
  "See https://docs.langchain.com/langsmith/smithdb-sdk-migration-runs#runs-get-url for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_GET_RUN_URL" });
2317
2327
  if (run !== undefined) {
2318
- if (!run.session_id && run.address) {
2319
- throw new Error("Addressed runs have no URL until read back.");
2320
- }
2328
+ const argumentAddress = (0, address_js_1.ensureAddress)(rawAddress);
2329
+ (0, addressing_js_1.rejectConflicting)(projectOpts?.projectName ?? projectOpts?.projectId, argumentAddress);
2330
+ const address = argumentAddress ??
2331
+ (0, address_js_1.ensureAgent)(run.address);
2321
2332
  let sessionId;
2322
2333
  if (run.session_id) {
2323
2334
  sessionId = run.session_id;
@@ -2328,6 +2339,9 @@ class Client {
2328
2339
  else if (projectOpts?.projectId) {
2329
2340
  sessionId = projectOpts?.projectId;
2330
2341
  }
2342
+ else if (address) {
2343
+ sessionId = await this._resolveAddress(address);
2344
+ }
2331
2345
  else {
2332
2346
  const project = await this.readProject({
2333
2347
  projectName: (0, env_js_1.getLangSmithEnvironmentVariable)("PROJECT") || "default",
@@ -2351,6 +2365,12 @@ class Client {
2351
2365
  throw new Error("Must provide either runId or run");
2352
2366
  }
2353
2367
  }
2368
+ /** The ID of the project an address names, with one request. */
2369
+ async _resolveAddress(address) {
2370
+ const { session_id: sessionId } = await this.sessions.resolve(address.toApiAddress());
2371
+ (0, _uuid_js_1.assertUuid)(sessionId);
2372
+ return sessionId;
2373
+ }
2354
2374
  async _loadChildRuns(run) {
2355
2375
  const childRuns = await toArray(this._listRuns({
2356
2376
  isRoot: false,
@@ -3943,8 +3963,8 @@ class Client {
3943
3963
  const { runId = null, key, score, value, correction, comment, sourceInfo, feedbackSourceType = "api", sourceRunId, feedbackId, feedbackConfig, projectId, traceId, comparativeExperimentId, sessionId, startTime, extendTraceRetention, address: rawAddress, } = typeof runIdOrParams === "object" && runIdOrParams !== null
3944
3964
  ? runIdOrParams
3945
3965
  : { runId: runIdOrParams, key: keyArg, ...optionsArg };
3946
- const address = (0, agent_addressing_js_1.checkAddress)(rawAddress);
3947
- (0, agent_addressing_js_1.rejectConflicting)(sessionId ?? projectId, address);
3966
+ const address = (0, address_js_1.ensureAgent)(rawAddress);
3967
+ (0, addressing_js_1.rejectConflicting)(sessionId ?? projectId, address);
3948
3968
  if (!runId && !projectId) {
3949
3969
  throw new Error("One of runId or projectId must be provided");
3950
3970
  }
@@ -3987,7 +4007,7 @@ class Client {
3987
4007
  if (samplingId != null && !this._shouldSample(samplingId)) {
3988
4008
  return feedback;
3989
4009
  }
3990
- const body = JSON.stringify(address ? { ...feedback, ...(0, address_js_1.toPayload)(address) } : feedback);
4010
+ const body = JSON.stringify(address ? { ...feedback, address: address._toLrn() } : feedback);
3991
4011
  const url = `${this.apiUrl}/feedback`;
3992
4012
  await this.caller.call(async () => {
3993
4013
  const res = await this._fetch(url, {
package/dist/client.d.ts CHANGED
@@ -10,8 +10,9 @@ import { Datasets } from "./_openapi_client/resources/datasets/datasets.js";
10
10
  import { AnnotationQueues } from "./_openapi_client/resources/annotation-queues/annotation-queues.js";
11
11
  import { Threads } from "./_openapi_client/resources/threads.js";
12
12
  import { Traces } from "./_openapi_client/resources/traces.js";
13
+ import { Sessions } from "./_openapi_client/resources/sessions.js";
13
14
  import { Public } from "./_openapi_client/resources/public/public.js";
14
- import { type Address } from "./address.js";
15
+ import { type Address, type AgentAddress } from "./address.js";
15
16
  import { PromptCache } from "./utils/prompt_cache/index.js";
16
17
  import { ProfileAuth } from "./utils/profiles.js";
17
18
  export interface ClientConfig {
@@ -328,7 +329,7 @@ interface CreateRunParams {
328
329
  parent_run_id?: string;
329
330
  project_name?: string;
330
331
  /** (beta) Send the run to this address instead of a project. */
331
- address?: Address;
332
+ address?: AgentAddress;
332
333
  revision_id?: string;
333
334
  trace_id?: string;
334
335
  dotted_order?: string;
@@ -386,7 +387,7 @@ export type CreateFeedbackParams = CreateFeedbackOptions & ({
386
387
  /** The run to provide feedback on. */
387
388
  runId: string;
388
389
  /** (beta) The address the run was sent to, e.g. `runTree.address`. */
389
- address: Address;
390
+ address: AgentAddress;
390
391
  sessionId?: never;
391
392
  projectId?: never;
392
393
  } | {
@@ -634,6 +635,11 @@ export declare class Client implements LangSmithTracingClientInterface {
634
635
  get threads(): Threads;
635
636
  /** Access the traces resource (query, listRuns). */
636
637
  get traces(): Traces;
638
+ /**
639
+ * (beta) Access the sessions resource, which resolves an address to the
640
+ * project its traces go to: `client.sessions.resolve(address.toApiAddress())`.
641
+ */
642
+ get sessions(): Sessions;
637
643
  /** Access the public shared-run resource. */
638
644
  get public(): Public;
639
645
  private processInputs;
@@ -750,11 +756,21 @@ export declare class Client implements LangSmithTracingClientInterface {
750
756
  loadChildRuns: boolean;
751
757
  }): Promise<Run>;
752
758
  /** @deprecated Use `client.runs.getURL()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration-runs#runs-get-url for the migration guide. Will be removed after Jan 31, 2027. */
753
- getRunUrl({ runId, run, projectOpts, }: {
759
+ getRunUrl({ runId, run, projectOpts, address: rawAddress, }: {
754
760
  runId?: string;
755
761
  run?: Run;
756
762
  projectOpts?: ProjectOptions;
763
+ /**
764
+ * (beta) An address that names the run's project, such as the
765
+ * `AgentAddress` the run was sent to or an `ExperimentAddress`, for a run
766
+ * that names no project. It is resolved to its project with one request,
767
+ * which needs LangSmith 0.18 or later. It must name the project the run is
768
+ * in. A run that carries its own `address` does not need it.
769
+ */
770
+ address?: Address;
757
771
  }): Promise<string>;
772
+ /** The ID of the project an address names, with one request. */
773
+ private _resolveAddress;
758
774
  private _loadChildRuns;
759
775
  /**
760
776
  * List runs from the LangSmith server.
package/dist/client.js CHANGED
@@ -9,8 +9,8 @@ import { Langsmith as OpenAPILangsmith } from "./_openapi_client/index.js";
9
9
  import { assertUuid } from "./utils/_uuid.js";
10
10
  import { isSampledById } from "./utils/sampling.js";
11
11
  import { warnOnce } from "./utils/warn.js";
12
- import { EnvAddressError, toPayload } from "./address.js";
13
- import { applyToPayload, checkAddress, logUntraced, rejectConflicting, resolveFromEnv, warnOnEnv, } from "./utils/agent_addressing.js";
12
+ import { EnvAddressError, ensureAddress, ensureAgent, } from "./address.js";
13
+ import { applyToPayload, logUntraced, rejectConflicting, resolveFromEnv, warnOnEnv, } from "./utils/addressing.js";
14
14
  import { getQueryBackend, QueryBackend } from "./utils/v2_migration.js";
15
15
  import { parseHubIdentifier } from "./utils/prompts.js";
16
16
  import { raiseForStatus, isLangSmithNotFoundError, isLangSmithConflictError, } from "./utils/error.js";
@@ -1194,6 +1194,14 @@ export class Client {
1194
1194
  this._checkStainlessVersion("0.16.0");
1195
1195
  return this.openAPIClient.traces;
1196
1196
  }
1197
+ /**
1198
+ * (beta) Access the sessions resource, which resolves an address to the
1199
+ * project its traces go to: `client.sessions.resolve(address.toApiAddress())`.
1200
+ */
1201
+ get sessions() {
1202
+ this._checkStainlessVersion("0.18.0");
1203
+ return this.openAPIClient.sessions;
1204
+ }
1197
1205
  /** Access the public shared-run resource. */
1198
1206
  get public() {
1199
1207
  this._checkStainlessVersion("0.16.0");
@@ -1756,7 +1764,7 @@ export class Client {
1756
1764
  ...this._mergedHeaders,
1757
1765
  "Content-Type": "application/json",
1758
1766
  };
1759
- const address = checkAddress(run.address);
1767
+ const address = ensureAgent(run.address);
1760
1768
  // `RunTree.postRun` passes a built run body, carrying the wire `session_name`.
1761
1769
  const bodySessionName = run.session_name;
1762
1770
  rejectConflicting(run.project_name ?? bodySessionName, address);
@@ -2183,8 +2191,8 @@ export class Client {
2183
2191
  if (run.events) {
2184
2192
  run.events = this._filterNewTokenEvents(run.events);
2185
2193
  }
2186
- // On `run` too: the direct path below serializes it.
2187
- applyToPayload(run, { update: true });
2194
+ // Fail on a bad address now; the queued path validates again when built.
2195
+ ensureAgent(run.address);
2188
2196
  // TODO: Untangle types
2189
2197
  const data = { ...run, id: runId };
2190
2198
  if (!this._filterForSampling([data]).length) {
@@ -2232,9 +2240,11 @@ export class Client {
2232
2240
  if (options?.workspaceId !== undefined) {
2233
2241
  headers["x-tenant-id"] = options.workspaceId;
2234
2242
  }
2235
- const body = serializePayloadForTracing(run.extra
2236
- ? mergeRuntimeEnvIntoRun(run, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo, this.tracingSampleRate)
2237
- : run, `Serializing payload to update run with id: ${runId}`);
2243
+ const wireRun = { ...run };
2244
+ applyToPayload(wireRun, { update: true });
2245
+ const body = serializePayloadForTracing(wireRun.extra
2246
+ ? mergeRuntimeEnvIntoRun(wireRun, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo, this.tracingSampleRate)
2247
+ : wireRun, `Serializing payload to update run with id: ${runId}`);
2238
2248
  await this.caller.call(async () => {
2239
2249
  const res = await this._fetch(`${options?.apiUrl ?? this.apiUrl}/runs/${runId}`, {
2240
2250
  method: "PATCH",
@@ -2271,14 +2281,15 @@ export class Client {
2271
2281
  return run;
2272
2282
  }
2273
2283
  /** @deprecated Use `client.runs.getURL()` instead. See https://docs.langchain.com/langsmith/smithdb-sdk-migration-runs#runs-get-url for the migration guide. Will be removed after Jan 31, 2027. */
2274
- async getRunUrl({ runId, run, projectOpts, }) {
2284
+ async getRunUrl({ runId, run, projectOpts, address: rawAddress, }) {
2275
2285
  warnOnce("getRunUrl() is deprecated and will be removed after Jan 31, 2027. " +
2276
2286
  "Use client.runs.getURL() instead. " +
2277
2287
  "See https://docs.langchain.com/langsmith/smithdb-sdk-migration-runs#runs-get-url for the migration guide.", { type: "DeprecationWarning", code: "LANGSMITH_DEPRECATED_GET_RUN_URL" });
2278
2288
  if (run !== undefined) {
2279
- if (!run.session_id && run.address) {
2280
- throw new Error("Addressed runs have no URL until read back.");
2281
- }
2289
+ const argumentAddress = ensureAddress(rawAddress);
2290
+ rejectConflicting(projectOpts?.projectName ?? projectOpts?.projectId, argumentAddress);
2291
+ const address = argumentAddress ??
2292
+ ensureAgent(run.address);
2282
2293
  let sessionId;
2283
2294
  if (run.session_id) {
2284
2295
  sessionId = run.session_id;
@@ -2289,6 +2300,9 @@ export class Client {
2289
2300
  else if (projectOpts?.projectId) {
2290
2301
  sessionId = projectOpts?.projectId;
2291
2302
  }
2303
+ else if (address) {
2304
+ sessionId = await this._resolveAddress(address);
2305
+ }
2292
2306
  else {
2293
2307
  const project = await this.readProject({
2294
2308
  projectName: getLangSmithEnvironmentVariable("PROJECT") || "default",
@@ -2312,6 +2326,12 @@ export class Client {
2312
2326
  throw new Error("Must provide either runId or run");
2313
2327
  }
2314
2328
  }
2329
+ /** The ID of the project an address names, with one request. */
2330
+ async _resolveAddress(address) {
2331
+ const { session_id: sessionId } = await this.sessions.resolve(address.toApiAddress());
2332
+ assertUuid(sessionId);
2333
+ return sessionId;
2334
+ }
2315
2335
  async _loadChildRuns(run) {
2316
2336
  const childRuns = await toArray(this._listRuns({
2317
2337
  isRoot: false,
@@ -3904,7 +3924,7 @@ export class Client {
3904
3924
  const { runId = null, key, score, value, correction, comment, sourceInfo, feedbackSourceType = "api", sourceRunId, feedbackId, feedbackConfig, projectId, traceId, comparativeExperimentId, sessionId, startTime, extendTraceRetention, address: rawAddress, } = typeof runIdOrParams === "object" && runIdOrParams !== null
3905
3925
  ? runIdOrParams
3906
3926
  : { runId: runIdOrParams, key: keyArg, ...optionsArg };
3907
- const address = checkAddress(rawAddress);
3927
+ const address = ensureAgent(rawAddress);
3908
3928
  rejectConflicting(sessionId ?? projectId, address);
3909
3929
  if (!runId && !projectId) {
3910
3930
  throw new Error("One of runId or projectId must be provided");
@@ -3948,7 +3968,7 @@ export class Client {
3948
3968
  if (samplingId != null && !this._shouldSample(samplingId)) {
3949
3969
  return feedback;
3950
3970
  }
3951
- const body = JSON.stringify(address ? { ...feedback, ...toPayload(address) } : feedback);
3971
+ const body = JSON.stringify(address ? { ...feedback, address: address._toLrn() } : feedback);
3952
3972
  const url = `${this.apiUrl}/feedback`;
3953
3973
  await this.caller.call(async () => {
3954
3974
  const res = await this._fetch(url, {