langsmith 0.10.12 → 0.10.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/lib/address.d.mts +35 -56
- package/lib/address.d.mts.map +1 -1
- package/lib/address.d.ts +35 -56
- package/lib/address.d.ts.map +1 -1
- package/lib/address.js +91 -156
- package/lib/address.js.map +1 -1
- package/lib/address.mjs +83 -151
- package/lib/address.mjs.map +1 -1
- package/lib/client.d.mts +1 -1
- package/lib/client.d.mts.map +1 -1
- package/lib/client.d.ts +1 -1
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +11 -10
- package/lib/client.js.map +1 -1
- package/lib/client.mjs +4 -3
- package/lib/client.mjs.map +1 -1
- package/lib/run_trees.d.mts +1 -1
- package/lib/run_trees.d.mts.map +1 -1
- package/lib/run_trees.d.ts +1 -1
- package/lib/run_trees.d.ts.map +1 -1
- package/lib/run_trees.js +11 -9
- package/lib/run_trees.js.map +1 -1
- package/lib/run_trees.mjs +7 -5
- package/lib/run_trees.mjs.map +1 -1
- package/lib/utils/addressing.d.mts +1 -1
- package/lib/utils/addressing.d.mts.map +1 -1
- package/lib/utils/addressing.d.ts +1 -1
- package/lib/utils/addressing.d.ts.map +1 -1
- package/lib/utils/addressing.js +4 -4
- package/lib/utils/addressing.js.map +1 -1
- package/lib/utils/addressing.mjs +5 -5
- package/lib/utils/addressing.mjs.map +1 -1
- package/package.json +10 -7
- package/src/lib/address.ts +138 -180
- package/src/lib/client.ts +4 -5
- package/src/lib/run_trees.ts +8 -5
- package/src/lib/utils/addressing.ts +8 -5
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
package/lib/utils/addressing.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { addressFromEnv, addressFromLrn, addressToLrn, EnvAddressError, ensureAgent, envNames, } from "../address.mjs";
|
|
2
2
|
import { getEnvironmentVariable, getLangSmithEnvironmentVariable, } from "./env.mjs";
|
|
3
3
|
import { warnOnce } from "./warn.mjs";
|
|
4
4
|
export function rejectConflicting(project, address) {
|
|
@@ -28,7 +28,7 @@ function getEnvProject() {
|
|
|
28
28
|
*/
|
|
29
29
|
export function resolveFromEnv() {
|
|
30
30
|
const project = getEnvProject();
|
|
31
|
-
const address =
|
|
31
|
+
const address = addressFromEnv();
|
|
32
32
|
if (project && address) {
|
|
33
33
|
throw new EnvAddressError("LANGSMITH_AGENT_* and a project are both set in the environment.");
|
|
34
34
|
}
|
|
@@ -64,7 +64,7 @@ export function applyToPayload(run, { update = false } = {}) {
|
|
|
64
64
|
// is sent. It is parsed again, so a malformed one cannot fail the whole
|
|
65
65
|
// batch in the backend.
|
|
66
66
|
try {
|
|
67
|
-
address =
|
|
67
|
+
address = addressFromLrn(payload.address);
|
|
68
68
|
}
|
|
69
69
|
catch {
|
|
70
70
|
throw new Error("The run's `address` is not a valid agent address.");
|
|
@@ -76,14 +76,14 @@ export function applyToPayload(run, { update = false } = {}) {
|
|
|
76
76
|
delete payload.address;
|
|
77
77
|
const namedProject = payload.session_id != null || payload.session_name != null;
|
|
78
78
|
if (!address && !update && !namedProject) {
|
|
79
|
-
address =
|
|
79
|
+
address = addressFromEnv();
|
|
80
80
|
}
|
|
81
81
|
if (!address) {
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
warnOnce("Sending runs to an `address` is in beta and enabled per workspace; a " +
|
|
85
85
|
"workspace without it rejects the runs.");
|
|
86
|
-
payload.address = address
|
|
86
|
+
payload.address = addressToLrn(address);
|
|
87
87
|
if (!namedProject) {
|
|
88
88
|
delete payload.session_name;
|
|
89
89
|
delete payload.session_id;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addressing.mjs","sourceRoot":"","sources":["../../src/lib/utils/addressing.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"addressing.mjs","sourceRoot":"","sources":["../../src/lib/utils/addressing.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.13",
|
|
4
4
|
"description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
|
|
5
5
|
"author": "LangChain <>",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -34,12 +34,13 @@
|
|
|
34
34
|
"overrides": {
|
|
35
35
|
"minimatch": "^9.0.7",
|
|
36
36
|
"@hono/node-server": "2.0.10",
|
|
37
|
-
"brace-expansion@<1.1.
|
|
37
|
+
"brace-expansion@<1.1.21": "1.1.21",
|
|
38
38
|
"brace-expansion@>=2.0.0 <2.1.7": "2.1.7",
|
|
39
39
|
"source-map-js": "1.2.2",
|
|
40
40
|
"@modelcontextprotocol/sdk": "1.31.0",
|
|
41
41
|
"handlebars": "4.7.10",
|
|
42
|
-
"brace-expansion@>=3.0.0 <
|
|
42
|
+
"brace-expansion@>=3.0.0 <3.0.9": "3.0.9",
|
|
43
|
+
"brace-expansion@>=4.0.0 <5.0.12": "5.0.12",
|
|
43
44
|
"fast-uri": "3.1.8",
|
|
44
45
|
"postcss": "8.5.23",
|
|
45
46
|
"js-yaml": "4.3.2",
|
|
@@ -59,12 +60,13 @@
|
|
|
59
60
|
"overrides": {
|
|
60
61
|
"minimatch": "^9.0.7",
|
|
61
62
|
"@hono/node-server": "2.0.10",
|
|
62
|
-
"brace-expansion@<1.1.
|
|
63
|
+
"brace-expansion@<1.1.21": "1.1.21",
|
|
63
64
|
"brace-expansion@>=2.0.0 <2.1.7": "2.1.7",
|
|
64
65
|
"source-map-js": "1.2.2",
|
|
65
66
|
"@modelcontextprotocol/sdk": "1.31.0",
|
|
66
67
|
"handlebars": "4.7.10",
|
|
67
|
-
"brace-expansion@>=3.0.0 <
|
|
68
|
+
"brace-expansion@>=3.0.0 <3.0.9": "3.0.9",
|
|
69
|
+
"brace-expansion@>=4.0.0 <5.0.12": "5.0.12",
|
|
68
70
|
"fast-uri": "3.1.8",
|
|
69
71
|
"postcss": "8.5.23",
|
|
70
72
|
"js-yaml": "4.3.2",
|
|
@@ -84,12 +86,13 @@
|
|
|
84
86
|
"resolutions": {
|
|
85
87
|
"minimatch": "^9.0.7",
|
|
86
88
|
"@hono/node-server": "2.0.10",
|
|
87
|
-
"brace-expansion@<1.1.
|
|
89
|
+
"brace-expansion@<1.1.21": "1.1.21",
|
|
88
90
|
"brace-expansion@>=2.0.0 <2.1.7": "2.1.7",
|
|
89
91
|
"source-map-js": "1.2.2",
|
|
90
92
|
"@modelcontextprotocol/sdk": "1.31.0",
|
|
91
93
|
"handlebars": "4.7.10",
|
|
92
|
-
"brace-expansion@>=3.0.0 <
|
|
94
|
+
"brace-expansion@>=3.0.0 <3.0.9": "3.0.9",
|
|
95
|
+
"brace-expansion@>=4.0.0 <5.0.12": "5.0.12",
|
|
93
96
|
"fast-uri": "3.1.8",
|
|
94
97
|
"postcss": "8.5.23",
|
|
95
98
|
"js-yaml": "4.3.2",
|
package/src/lib/address.ts
CHANGED
|
@@ -26,32 +26,67 @@ export type Environment = "local" | "development" | "staging" | "production";
|
|
|
26
26
|
*/
|
|
27
27
|
export type Lrn = `lrn:agents/${string}/environments/${Environment}`;
|
|
28
28
|
|
|
29
|
-
/** (beta) The
|
|
30
|
-
export
|
|
31
|
-
kind: "AGENT"
|
|
32
|
-
id
|
|
33
|
-
environment
|
|
34
|
-
}
|
|
29
|
+
/** (beta) The address of an agent's environment. */
|
|
30
|
+
export interface AgentAddress {
|
|
31
|
+
kind: "AGENT";
|
|
32
|
+
id: string;
|
|
33
|
+
environment: Uppercase<Environment>;
|
|
34
|
+
}
|
|
35
35
|
|
|
36
|
-
/** (beta)
|
|
37
|
-
export
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
/** (beta) Construct and validate an agent address; plain objects are also accepted. */
|
|
37
|
+
export class AgentAddress {
|
|
38
|
+
constructor(id: string, environment: Environment | (string & {})) {
|
|
39
|
+
const address = ensureAgent({ kind: "AGENT", id, environment });
|
|
40
|
+
this.kind = address.kind;
|
|
41
|
+
this.id = address.id;
|
|
42
|
+
this.environment = address.environment;
|
|
43
|
+
Object.freeze(this);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** (beta) The address of an experiment's tracing project. */
|
|
48
|
+
export interface ExperimentAddress {
|
|
49
|
+
kind: "EXPERIMENT";
|
|
50
|
+
id: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** (beta) Construct and validate an experiment address. */
|
|
54
|
+
export class ExperimentAddress {
|
|
55
|
+
constructor(id: string) {
|
|
56
|
+
const address = ensureAddress({ kind: "EXPERIMENT", id });
|
|
57
|
+
this.kind = address.kind;
|
|
58
|
+
this.id = address.id;
|
|
59
|
+
Object.freeze(this);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** (beta) The address of the workspace's shared evaluators project. */
|
|
64
|
+
export interface EvaluatorAddress {
|
|
65
|
+
kind: "EVALUATOR";
|
|
40
66
|
}
|
|
41
67
|
|
|
68
|
+
/** (beta) Construct the workspace's evaluators address. */
|
|
69
|
+
export class EvaluatorAddress {
|
|
70
|
+
constructor() {
|
|
71
|
+
this.kind = "EVALUATOR";
|
|
72
|
+
Object.freeze(this);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** (beta) A feature that holds traces in a tracing project. */
|
|
77
|
+
export type Address = AgentAddress | ExperimentAddress | EvaluatorAddress;
|
|
78
|
+
|
|
79
|
+
/** (beta) An address as the resolve endpoint takes it. */
|
|
80
|
+
export type ApiAddress = Address;
|
|
81
|
+
|
|
42
82
|
const UUID_PATTERN =
|
|
43
83
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
44
84
|
|
|
45
85
|
// The server's agent id rule: a DNS label, so a hostname can carry the id.
|
|
46
86
|
const AGENT_ID_PATTERN = /^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
47
|
-
const ENVIRONMENTS
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"staging",
|
|
51
|
-
"production",
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
// The wire form of an agent address. The parts are validated by `AgentAddress`.
|
|
87
|
+
const ENVIRONMENTS = ["local", "development", "staging", "production"];
|
|
88
|
+
|
|
89
|
+
// The wire form of an agent address. The parts are validated at entrypoints.
|
|
55
90
|
const LRN_PATTERN = /^lrn:agents\/([^/]+)\/environments\/([^/]+)$/;
|
|
56
91
|
|
|
57
92
|
const ENV_NAMES = ["LANGSMITH_AGENT_ID", "LANGSMITH_AGENT_ENVIRONMENT"];
|
|
@@ -64,189 +99,112 @@ export class EnvAddressError extends Error {
|
|
|
64
99
|
}
|
|
65
100
|
}
|
|
66
101
|
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @param id 1 to 63 lowercase ASCII letters, digits or hyphens, starting
|
|
83
|
-
* with a letter and ending with a letter or digit. The server creates the
|
|
84
|
-
* agent on first use.
|
|
85
|
-
* @param environment One of `local`, `development`, `staging` or `production`, in
|
|
86
|
-
* any case.
|
|
87
|
-
* @throws If a value is invalid.
|
|
88
|
-
*/
|
|
89
|
-
constructor(id: string, environment: Environment | (string & {})) {
|
|
90
|
-
if (typeof id !== "string" || !AGENT_ID_PATTERN.test(id)) {
|
|
91
|
-
throw new Error(
|
|
92
|
-
"Address agent id must be 1 to 63 lowercase ASCII letters, digits, or " +
|
|
93
|
-
"hyphens, start with a letter, and end with a letter or digit, got " +
|
|
94
|
-
`${JSON.stringify(id)}. Use an id such as "support-agent".`,
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
const normalized =
|
|
98
|
-
typeof environment === "string" ? environment.toLowerCase() : undefined;
|
|
99
|
-
if (normalized === undefined || !ENVIRONMENTS.includes(normalized)) {
|
|
100
|
-
throw new Error(
|
|
101
|
-
`Address environment must be one of ${ENVIRONMENTS.join(", ")}, got ` +
|
|
102
|
-
`${JSON.stringify(environment)}.`,
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
this.id = id;
|
|
106
|
-
this.environment = normalized as Environment;
|
|
107
|
-
Object.freeze(this);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
toApiAddress(): ApiAddress {
|
|
111
|
-
return {
|
|
112
|
-
kind: "AGENT",
|
|
113
|
-
id: this.id,
|
|
114
|
-
environment: this.environment.toUpperCase() as Uppercase<Environment>,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** @internal */
|
|
119
|
-
_toLrn(): Lrn {
|
|
120
|
-
return `lrn:agents/${this.id}/environments/${this.environment}`;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* @internal Parse an LRN read from the wire, such as a `baggage` header. The
|
|
125
|
-
* value is untrusted, so it is not echoed in the error.
|
|
126
|
-
* @throws If `value` is not an agent LRN, or names an invalid id or environment.
|
|
127
|
-
*/
|
|
128
|
-
static _fromLrn(value: unknown): AgentAddress {
|
|
129
|
-
const match = typeof value === "string" ? LRN_PATTERN.exec(value) : null;
|
|
130
|
-
if (match === null) {
|
|
131
|
-
throw new Error("Not an agent address.");
|
|
132
|
-
}
|
|
133
|
-
return new AgentAddress(match[1], match[2]);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Read the agent named by `LANGSMITH_AGENT_ID` and
|
|
138
|
-
* `LANGSMITH_AGENT_ENVIRONMENT`; `undefined` if neither is set.
|
|
139
|
-
* @throws {EnvAddressError} If only one is set, or a value is invalid.
|
|
140
|
-
*/
|
|
141
|
-
static fromEnv(): AgentAddress | undefined {
|
|
142
|
-
const values = ENV_NAMES.map((name) => getEnvironmentVariable(name));
|
|
143
|
-
if (!values.some(Boolean)) {
|
|
144
|
-
return undefined;
|
|
145
|
-
}
|
|
146
|
-
try {
|
|
147
|
-
const missing = ENV_NAMES.filter((_, i) => !values[i]);
|
|
148
|
-
if (missing.length > 0) {
|
|
149
|
-
throw new Error(`An address needs ${missing.join(" and ")} as well.`);
|
|
150
|
-
}
|
|
151
|
-
return new AgentAddress(values[0] as string, values[1] as string);
|
|
152
|
-
} catch (e) {
|
|
153
|
-
const present = ENV_NAMES.flatMap((name, i) =>
|
|
154
|
-
values[i] ? [`${name}=${JSON.stringify(values[i])}`] : [],
|
|
155
|
-
).join(", ");
|
|
156
|
-
throw new EnvAddressError(
|
|
157
|
-
`The LANGSMITH_AGENT_* env vars can't address a run (${present}): ${
|
|
158
|
-
(e as Error).message
|
|
159
|
-
}`,
|
|
160
|
-
);
|
|
161
|
-
}
|
|
102
|
+
/** Validate an address at an SDK entrypoint and return a normalized copy. */
|
|
103
|
+
export function ensureAddress<K extends Address["kind"]>(value: {
|
|
104
|
+
kind: K;
|
|
105
|
+
id?: unknown;
|
|
106
|
+
environment?: unknown;
|
|
107
|
+
}): Extract<Address, { kind: K }>;
|
|
108
|
+
export function ensureAddress(value: unknown): Address | undefined;
|
|
109
|
+
export function ensureAddress(value: unknown): Address | undefined {
|
|
110
|
+
if (value == null) return undefined;
|
|
111
|
+
if (typeof value !== "object") {
|
|
112
|
+
throw new Error(
|
|
113
|
+
"address must be an AgentAddress, ExperimentAddress or EvaluatorAddress object.",
|
|
114
|
+
);
|
|
162
115
|
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
export class ExperimentAddress implements Address {
|
|
167
|
-
/** Always lowercase. */
|
|
168
|
-
readonly id: string;
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* @param id The experiment's UUID.
|
|
172
|
-
* @throws If `id` is not a UUID.
|
|
173
|
-
*/
|
|
174
|
-
constructor(id: string) {
|
|
116
|
+
const { kind, id, environment } = value as Record<string, unknown>;
|
|
117
|
+
if (kind === "EVALUATOR") return { kind };
|
|
118
|
+
if (kind === "EXPERIMENT") {
|
|
175
119
|
if (typeof id !== "string" || !UUID_PATTERN.test(id)) {
|
|
176
120
|
throw new Error(
|
|
177
121
|
`Experiment id must be a UUID, got ${JSON.stringify(id)}.`,
|
|
178
122
|
);
|
|
179
123
|
}
|
|
180
|
-
|
|
181
|
-
Object.freeze(this);
|
|
124
|
+
return { kind, id: id.toLowerCase() };
|
|
182
125
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
126
|
+
if (kind !== "AGENT") {
|
|
127
|
+
throw new Error(
|
|
128
|
+
"address must be an AgentAddress, ExperimentAddress or EvaluatorAddress object.",
|
|
129
|
+
);
|
|
186
130
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
131
|
+
if (typeof id !== "string" || !AGENT_ID_PATTERN.test(id)) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
"Address agent id must be 1 to 63 lowercase ASCII letters, digits, or " +
|
|
134
|
+
"hyphens, start with a letter, and end with a letter or digit, got " +
|
|
135
|
+
`${JSON.stringify(id)}. Use an id such as "support-agent".`,
|
|
136
|
+
);
|
|
193
137
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
138
|
+
const normalized =
|
|
139
|
+
typeof environment === "string" ? environment.toLowerCase() : undefined;
|
|
140
|
+
if (normalized === undefined || !ENVIRONMENTS.includes(normalized)) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`Address environment must be one of ${ENVIRONMENTS.join(
|
|
143
|
+
", ",
|
|
144
|
+
)}, got ${JSON.stringify(environment)}.`,
|
|
145
|
+
);
|
|
197
146
|
}
|
|
147
|
+
return {
|
|
148
|
+
kind,
|
|
149
|
+
id,
|
|
150
|
+
environment: normalized.toUpperCase() as Uppercase<Environment>,
|
|
151
|
+
};
|
|
198
152
|
}
|
|
199
153
|
|
|
200
|
-
/**
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
154
|
+
/** @internal Only agent addresses can receive traces. */
|
|
155
|
+
export function ensureAgent(value: {
|
|
156
|
+
kind: "AGENT";
|
|
157
|
+
id?: unknown;
|
|
158
|
+
environment?: unknown;
|
|
159
|
+
}): AgentAddress;
|
|
160
|
+
export function ensureAgent(value: unknown): AgentAddress | undefined;
|
|
205
161
|
export function ensureAgent(value: unknown): AgentAddress | undefined {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
if (value instanceof AgentAddress) {
|
|
210
|
-
return value;
|
|
211
|
-
}
|
|
212
|
-
if (
|
|
213
|
-
typeof value === "object" &&
|
|
214
|
-
typeof (value as Address).toApiAddress === "function"
|
|
215
|
-
) {
|
|
162
|
+
const address = ensureAddress(value);
|
|
163
|
+
if (address && address.kind !== "AGENT") {
|
|
216
164
|
throw new Error(
|
|
217
|
-
`Only an AgentAddress can receive traces, got ${
|
|
218
|
-
(value as object).constructor?.name ?? "an unknown address"
|
|
219
|
-
}.`,
|
|
165
|
+
`Only an AgentAddress can receive traces, got ${address.kind}.`,
|
|
220
166
|
);
|
|
221
167
|
}
|
|
222
|
-
|
|
223
|
-
"address must be an AgentAddress such as `new AgentAddress(id, environment)`, got " +
|
|
224
|
-
`${typeof value === "string" ? JSON.stringify(value) : typeof value}.`,
|
|
225
|
-
);
|
|
168
|
+
return address;
|
|
226
169
|
}
|
|
227
170
|
|
|
228
|
-
/**
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
171
|
+
/** @internal Convert a validated address to the ingestion wire format. */
|
|
172
|
+
export function addressToLrn(address: AgentAddress): Lrn {
|
|
173
|
+
return `lrn:agents/${address.id}/environments/${
|
|
174
|
+
address.environment.toLowerCase() as Environment
|
|
175
|
+
}`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** @internal Parse and validate an address from untrusted wire data. */
|
|
179
|
+
export function addressFromLrn(value: unknown): AgentAddress {
|
|
180
|
+
const match = typeof value === "string" ? LRN_PATTERN.exec(value) : null;
|
|
181
|
+
if (!match) throw new Error("Not an agent address.");
|
|
182
|
+
return ensureAgent({ kind: "AGENT", id: match[1], environment: match[2] });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** @internal Read and validate the address named by environment variables. */
|
|
186
|
+
export function addressFromEnv(): AgentAddress | undefined {
|
|
187
|
+
const values = ENV_NAMES.map((name) => getEnvironmentVariable(name));
|
|
188
|
+
if (!values.some(Boolean)) return undefined;
|
|
189
|
+
try {
|
|
190
|
+
const missing = ENV_NAMES.filter((_, i) => !values[i]);
|
|
191
|
+
if (missing.length)
|
|
192
|
+
throw new Error(`An address needs ${missing.join(" and ")} as well.`);
|
|
193
|
+
return ensureAgent({
|
|
194
|
+
kind: "AGENT",
|
|
195
|
+
id: values[0],
|
|
196
|
+
environment: values[1],
|
|
197
|
+
});
|
|
198
|
+
} catch (e) {
|
|
199
|
+
throw new EnvAddressError(
|
|
200
|
+
`The LANGSMITH_AGENT_* env vars can't address a run: ${
|
|
201
|
+
(e as Error).message
|
|
202
|
+
}`,
|
|
203
|
+
);
|
|
242
204
|
}
|
|
243
|
-
throw new Error(
|
|
244
|
-
"address must be an AgentAddress, ExperimentAddress or EvaluatorAddress, got " +
|
|
245
|
-
`${typeof value === "string" ? JSON.stringify(value) : typeof value}.`,
|
|
246
|
-
);
|
|
247
205
|
}
|
|
248
206
|
|
|
249
|
-
/** @internal The
|
|
207
|
+
/** @internal The environment variable names an address reads. */
|
|
250
208
|
export function envNames(): string[] {
|
|
251
209
|
return ENV_NAMES;
|
|
252
210
|
}
|
package/src/lib/client.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addressToLrn } from "./address.js";
|
|
1
2
|
import * as uuid from "./utils/uuid/src/index.js";
|
|
2
3
|
import { getOpenAPIBaseUrl } from "./utils/api_url.js";
|
|
3
4
|
import type { OTELContext } from "./experimental/otel/types.js";
|
|
@@ -1861,7 +1862,7 @@ export class Client implements LangSmithTracingClientInterface {
|
|
|
1861
1862
|
|
|
1862
1863
|
/**
|
|
1863
1864
|
* (beta) Access the sessions resource, which resolves an address to the
|
|
1864
|
-
* project its traces go to: `client.sessions.resolve(address
|
|
1865
|
+
* project its traces go to: `client.sessions.resolve(address)`.
|
|
1865
1866
|
*/
|
|
1866
1867
|
public get sessions(): Sessions {
|
|
1867
1868
|
this._checkStainlessVersion("0.18.0");
|
|
@@ -3359,9 +3360,7 @@ export class Client implements LangSmithTracingClientInterface {
|
|
|
3359
3360
|
|
|
3360
3361
|
/** The ID of the project an address names, with one request. */
|
|
3361
3362
|
private async _resolveAddress(address: Address): Promise<string> {
|
|
3362
|
-
const { session_id: sessionId } = await this.sessions.resolve(
|
|
3363
|
-
address.toApiAddress(),
|
|
3364
|
-
);
|
|
3363
|
+
const { session_id: sessionId } = await this.sessions.resolve(address);
|
|
3365
3364
|
assertUuid(sessionId);
|
|
3366
3365
|
return sessionId;
|
|
3367
3366
|
}
|
|
@@ -5672,7 +5671,7 @@ export class Client implements LangSmithTracingClientInterface {
|
|
|
5672
5671
|
return feedback as Feedback;
|
|
5673
5672
|
}
|
|
5674
5673
|
const body = JSON.stringify(
|
|
5675
|
-
address ? { ...feedback, address: address
|
|
5674
|
+
address ? { ...feedback, address: addressToLrn(address) } : feedback,
|
|
5676
5675
|
);
|
|
5677
5676
|
const url = `${this.apiUrl}/feedback`;
|
|
5678
5677
|
await this.caller.call(async () => {
|
package/src/lib/run_trees.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addressToLrn, addressFromLrn } from "./address.js";
|
|
1
2
|
import { Client } from "./client.js";
|
|
2
3
|
import { isEnvTracingEnabled } from "./env.js";
|
|
3
4
|
import {
|
|
@@ -33,7 +34,7 @@ import {
|
|
|
33
34
|
rejectConflicting,
|
|
34
35
|
resolveFromEnv,
|
|
35
36
|
} from "./utils/addressing.js";
|
|
36
|
-
import { AgentAddress, EnvAddressError, ensureAgent } from "./address.js";
|
|
37
|
+
import { type AgentAddress, EnvAddressError, ensureAgent } from "./address.js";
|
|
37
38
|
|
|
38
39
|
const TIMESTAMP_LENGTH = 36;
|
|
39
40
|
// DNS namespace for UUID v5 (same as Python's uuid.NAMESPACE_DNS)
|
|
@@ -197,7 +198,7 @@ const HEADER_SAFE_REPLICA_FIELDS = new Set([
|
|
|
197
198
|
/** Rebuilds an untrusted header address; `undefined` if unusable. */
|
|
198
199
|
function addressFromHeader(value: unknown): AgentAddress | undefined {
|
|
199
200
|
try {
|
|
200
|
-
return
|
|
201
|
+
return addressFromLrn(value);
|
|
201
202
|
} catch {
|
|
202
203
|
// Values are untrusted, so not logged.
|
|
203
204
|
console.warn("Ignoring an unusable address in a `baggage` header.");
|
|
@@ -301,7 +302,7 @@ class Baggage {
|
|
|
301
302
|
}
|
|
302
303
|
if (this.address) {
|
|
303
304
|
items.push(
|
|
304
|
-
`langsmith-address=${encodeURIComponent(this.address
|
|
305
|
+
`langsmith-address=${encodeURIComponent(addressToLrn(this.address))}`,
|
|
305
306
|
);
|
|
306
307
|
}
|
|
307
308
|
|
|
@@ -752,7 +753,8 @@ export class RunTree implements BaseRun {
|
|
|
752
753
|
primary === undefined &&
|
|
753
754
|
!this.replicas?.some((r) => r.primary === true) &&
|
|
754
755
|
projectName === this.project_name &&
|
|
755
|
-
address
|
|
756
|
+
(address ? addressToLrn(address) : undefined) ===
|
|
757
|
+
(this.address ? addressToLrn(this.address) : undefined)
|
|
756
758
|
) {
|
|
757
759
|
return {
|
|
758
760
|
...baseRun,
|
|
@@ -760,7 +762,8 @@ export class RunTree implements BaseRun {
|
|
|
760
762
|
address,
|
|
761
763
|
};
|
|
762
764
|
}
|
|
763
|
-
const seed =
|
|
765
|
+
const seed =
|
|
766
|
+
projectName ?? (address ? addressToLrn(address) : undefined) ?? "agent//";
|
|
764
767
|
|
|
765
768
|
// Apply reroot logic before ID remapping
|
|
766
769
|
if (reroot) {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AgentAddress,
|
|
2
|
+
type AgentAddress,
|
|
3
|
+
addressFromEnv,
|
|
4
|
+
addressFromLrn,
|
|
5
|
+
addressToLrn,
|
|
3
6
|
EnvAddressError,
|
|
4
7
|
ensureAgent,
|
|
5
8
|
envNames,
|
|
@@ -47,7 +50,7 @@ function getEnvProject(): string | undefined {
|
|
|
47
50
|
*/
|
|
48
51
|
export function resolveFromEnv(): Tier {
|
|
49
52
|
const project = getEnvProject();
|
|
50
|
-
const address =
|
|
53
|
+
const address = addressFromEnv();
|
|
51
54
|
if (project && address) {
|
|
52
55
|
throw new EnvAddressError(
|
|
53
56
|
"LANGSMITH_AGENT_* and a project are both set in the environment.",
|
|
@@ -92,7 +95,7 @@ export function applyToPayload(
|
|
|
92
95
|
// is sent. It is parsed again, so a malformed one cannot fail the whole
|
|
93
96
|
// batch in the backend.
|
|
94
97
|
try {
|
|
95
|
-
address =
|
|
98
|
+
address = addressFromLrn(payload.address);
|
|
96
99
|
} catch {
|
|
97
100
|
throw new Error("The run's `address` is not a valid agent address.");
|
|
98
101
|
}
|
|
@@ -103,7 +106,7 @@ export function applyToPayload(
|
|
|
103
106
|
const namedProject =
|
|
104
107
|
payload.session_id != null || payload.session_name != null;
|
|
105
108
|
if (!address && !update && !namedProject) {
|
|
106
|
-
address =
|
|
109
|
+
address = addressFromEnv();
|
|
107
110
|
}
|
|
108
111
|
if (!address) {
|
|
109
112
|
return;
|
|
@@ -112,7 +115,7 @@ export function applyToPayload(
|
|
|
112
115
|
"Sending runs to an `address` is in beta and enabled per workspace; a " +
|
|
113
116
|
"workspace without it rejects the runs.",
|
|
114
117
|
);
|
|
115
|
-
payload.address = address
|
|
118
|
+
payload.address = addressToLrn(address);
|
|
116
119
|
if (!namedProject) {
|
|
117
120
|
delete payload.session_name;
|
|
118
121
|
delete payload.session_id;
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.10.
|
|
1
|
+
export const VERSION = '0.10.13'; // x-release-please-version
|
package/version.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.10.
|
|
1
|
+
export declare const VERSION = "0.10.13";
|
|
2
2
|
//# sourceMappingURL=version.d.mts.map
|
package/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.10.
|
|
1
|
+
export declare const VERSION = "0.10.13";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/version.js
CHANGED
package/version.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = '0.10.
|
|
1
|
+
export const VERSION = '0.10.13'; // x-release-please-version
|
|
2
2
|
//# sourceMappingURL=version.mjs.map
|