langsmith 0.8.8 → 0.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_openapi_client/resources/annotation-queues/annotation-queues.cjs +10 -0
- package/dist/_openapi_client/resources/annotation-queues/annotation-queues.d.ts +10 -0
- package/dist/_openapi_client/resources/annotation-queues/annotation-queues.js +10 -0
- package/dist/_openapi_client/resources/annotation-queues/runs.cjs +13 -1
- package/dist/_openapi_client/resources/annotation-queues/runs.d.ts +13 -1
- package/dist/_openapi_client/resources/annotation-queues/runs.js +13 -1
- package/dist/_openapi_client/resources/datasets/experiment-runs.cjs +2 -0
- package/dist/_openapi_client/resources/datasets/experiment-runs.d.ts +2 -0
- package/dist/_openapi_client/resources/datasets/experiment-runs.js +2 -0
- package/dist/_openapi_client/resources/issues.d.ts +1 -1
- package/dist/_openapi_client/resources/public/runs.cjs +9 -7
- package/dist/_openapi_client/resources/public/runs.d.ts +8 -6
- package/dist/_openapi_client/resources/public/runs.js +9 -7
- package/dist/_openapi_client/resources/runs/runs.cjs +11 -6
- package/dist/_openapi_client/resources/runs/runs.d.ts +11 -6
- package/dist/_openapi_client/resources/runs/runs.js +11 -6
- package/dist/_openapi_client/resources/runs/share.cjs +4 -0
- package/dist/_openapi_client/resources/runs/share.d.ts +4 -0
- package/dist/_openapi_client/resources/runs/share.js +4 -0
- package/dist/_openapi_client/resources/threads.cjs +11 -8
- package/dist/_openapi_client/resources/threads.d.ts +11 -8
- package/dist/_openapi_client/resources/threads.js +11 -8
- package/dist/_openapi_client/resources/traces.cjs +6 -3
- package/dist/_openapi_client/resources/traces.d.ts +6 -3
- package/dist/_openapi_client/resources/traces.js +6 -3
- package/dist/client.cjs +295 -24
- package/dist/client.d.ts +63 -9
- package/dist/client.js +295 -24
- package/dist/evaluation/evaluate_comparative.cjs +7 -4
- package/dist/evaluation/evaluate_comparative.js +7 -4
- package/dist/experimental/vercel/_agent_type.cjs +30 -0
- package/dist/experimental/vercel/_agent_type.d.ts +5 -0
- package/dist/experimental/vercel/_agent_type.js +26 -0
- package/dist/experimental/vercel/telemetry.cjs +2 -7
- package/dist/experimental/vercel/telemetry.js +2 -7
- package/dist/experimental/vercel/wrap.cjs +5 -11
- package/dist/experimental/vercel/wrap.js +6 -12
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/sandbox/command_handle.cjs +34 -7
- package/dist/sandbox/command_handle.d.ts +1 -0
- package/dist/sandbox/command_handle.js +34 -7
- package/dist/sandbox/ws_execute.cjs +7 -3
- package/dist/sandbox/ws_execute.d.ts +4 -2
- package/dist/sandbox/ws_execute.js +7 -3
- package/dist/utils/_git.cjs +28 -1
- package/dist/utils/_git.js +28 -1
- package/dist/utils/ls_agent_type.cjs +31 -0
- package/dist/utils/ls_agent_type.d.ts +9 -0
- package/dist/utils/ls_agent_type.js +25 -0
- package/dist/utils/profiles.cjs +125 -1
- package/dist/utils/profiles.d.ts +6 -0
- package/dist/utils/profiles.js +124 -1
- package/dist/utils/v2_migration.cjs +18 -0
- package/dist/utils/v2_migration.d.ts +8 -0
- package/dist/utils/v2_migration.js +16 -0
- package/dist/utils/warn.cjs +30 -4
- package/dist/utils/warn.d.ts +4 -1
- package/dist/utils/warn.js +29 -4
- package/dist/wrappers/openai.cjs +4 -0
- package/dist/wrappers/openai.js +4 -0
- package/dist/wrappers/openai_agents.cjs +15 -12
- package/dist/wrappers/openai_agents.js +15 -12
- package/package.json +1 -1
package/dist/utils/profiles.cjs
CHANGED
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.ProfileAuth = exports.DEFAULT_API_URL = void 0;
|
|
37
37
|
exports.hasValue = hasValue;
|
|
38
|
+
exports.resolveTokenEndpoint = resolveTokenEndpoint;
|
|
38
39
|
exports.loadProfileClientConfig = loadProfileClientConfig;
|
|
39
40
|
const env_js_1 = require("./env.cjs");
|
|
40
41
|
const fsUtils = __importStar(require("./fs.cjs"));
|
|
@@ -43,6 +44,8 @@ exports.DEFAULT_API_URL = "https://api.smith.langchain.com";
|
|
|
43
44
|
const OAUTH_CLIENT_ID = "langsmith-cli";
|
|
44
45
|
const TOKEN_REFRESH_LEEWAY_MS = 60_000;
|
|
45
46
|
const TOKEN_REFRESH_TIMEOUT_MS = 10_000;
|
|
47
|
+
const OAUTH_DISCOVERY_TIMEOUT_MS = 5_000;
|
|
48
|
+
const WELL_KNOWN_OAUTH_PATH = "/.well-known/oauth-authorization-server";
|
|
46
49
|
function isBrowserLikeRuntime() {
|
|
47
50
|
const env = (0, env_js_1.getEnv)();
|
|
48
51
|
return env === "browser" || env === "webworker";
|
|
@@ -125,6 +128,126 @@ function normalizeConfigUrl(apiUrl) {
|
|
|
125
128
|
? normalized.slice(0, -apiV1Suffix.length)
|
|
126
129
|
: normalized;
|
|
127
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Metadata base URLs to probe, most specific first: the configured mount point,
|
|
133
|
+
* then the self-hosted and SaaS locations, so both a bare origin and an
|
|
134
|
+
* explicit `/api` resolve.
|
|
135
|
+
*/
|
|
136
|
+
function oauthDiscoveryCandidates(apiUrl) {
|
|
137
|
+
const given = normalizeConfigUrl(apiUrl);
|
|
138
|
+
const origin = given.endsWith("/api")
|
|
139
|
+
? given.slice(0, -"/api".length)
|
|
140
|
+
: given;
|
|
141
|
+
const candidates = [];
|
|
142
|
+
for (const candidate of [given, `${origin}/api`, origin]) {
|
|
143
|
+
if (candidate && candidate !== "/api" && !candidates.includes(candidate)) {
|
|
144
|
+
candidates.push(candidate);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return candidates;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check the document describes the deployment we probed. RFC 8414 requires the
|
|
151
|
+
* issuer to match the URL the well-known path was built from, and every
|
|
152
|
+
* endpoint must share the issuer's origin. Refresh tokens are posted to these
|
|
153
|
+
* endpoints, so an unvalidated document could redirect credentials elsewhere.
|
|
154
|
+
*/
|
|
155
|
+
function isTrustedOAuthMetadata(doc, base) {
|
|
156
|
+
const { issuer } = doc;
|
|
157
|
+
if (typeof issuer !== "string" ||
|
|
158
|
+
issuer.replace(/\/+$/, "") !== base.replace(/\/+$/, "")) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
let issuerUrl;
|
|
162
|
+
try {
|
|
163
|
+
issuerUrl = new URL(issuer);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
for (const endpoint of [
|
|
169
|
+
doc.device_authorization_endpoint,
|
|
170
|
+
doc.token_endpoint,
|
|
171
|
+
]) {
|
|
172
|
+
if (typeof endpoint !== "string" || !endpoint) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const url = new URL(endpoint);
|
|
177
|
+
if (url.protocol !== issuerUrl.protocol || url.host !== issuerUrl.host) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Metadata URLs for an issuer, RFC 8414 form first. RFC 8414 inserts the
|
|
189
|
+
* well-known segment between the origin and the issuer path, so
|
|
190
|
+
* `https://host/api` is described at
|
|
191
|
+
* `https://host/.well-known/oauth-authorization-server/api`. Deployments
|
|
192
|
+
* commonly also serve the appended form, and for a path-less issuer the two are
|
|
193
|
+
* identical.
|
|
194
|
+
*/
|
|
195
|
+
function oauthMetadataUrls(base) {
|
|
196
|
+
const appended = `${base}${WELL_KNOWN_OAUTH_PATH}`;
|
|
197
|
+
let inserted;
|
|
198
|
+
try {
|
|
199
|
+
const url = new URL(base);
|
|
200
|
+
inserted = `${url.origin}${WELL_KNOWN_OAUTH_PATH}${url.pathname === "/" ? "" : url.pathname}`;
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return [appended];
|
|
204
|
+
}
|
|
205
|
+
return inserted === appended ? [inserted] : [inserted, appended];
|
|
206
|
+
}
|
|
207
|
+
async function fetchOAuthMetadata(url, base, fetchImplementation) {
|
|
208
|
+
let response;
|
|
209
|
+
try {
|
|
210
|
+
response = await fetchImplementation(url, {
|
|
211
|
+
method: "GET",
|
|
212
|
+
headers: { Accept: "application/json" },
|
|
213
|
+
signal: AbortSignal.timeout(OAUTH_DISCOVERY_TIMEOUT_MS),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
if (!response.ok) {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
let doc;
|
|
223
|
+
try {
|
|
224
|
+
// Self-hosted answers unknown paths with an HTML 200 from the SPA.
|
|
225
|
+
doc = (await response.json());
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
if (!doc || typeof doc !== "object" || !isTrustedOAuthMetadata(doc, base)) {
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
return doc;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Resolve the token endpoint, preferring the deployment's metadata document.
|
|
237
|
+
* Falls back to `<mount>/oauth/token`, keeping a trailing `/api` because
|
|
238
|
+
* self-hosted mounts the authorization server under it.
|
|
239
|
+
*/
|
|
240
|
+
async function resolveTokenEndpoint(apiUrl, fetchImplementation) {
|
|
241
|
+
for (const base of oauthDiscoveryCandidates(apiUrl)) {
|
|
242
|
+
for (const url of oauthMetadataUrls(base)) {
|
|
243
|
+
const doc = await fetchOAuthMetadata(url, base, fetchImplementation);
|
|
244
|
+
if (doc) {
|
|
245
|
+
return doc.token_endpoint;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return `${normalizeConfigUrl(apiUrl)}/oauth/token`;
|
|
250
|
+
}
|
|
128
251
|
function applyTokenResponse(profile, token) {
|
|
129
252
|
profile.oauth ??= {};
|
|
130
253
|
if (token.access_token) {
|
|
@@ -262,7 +385,8 @@ class ProfileAuth {
|
|
|
262
385
|
client_id: OAUTH_CLIENT_ID,
|
|
263
386
|
refresh_token: this.state.profile.oauth?.refresh_token ?? refreshToken,
|
|
264
387
|
});
|
|
265
|
-
const
|
|
388
|
+
const tokenEndpoint = await resolveTokenEndpoint(refreshApiUrl, fetchImplementation);
|
|
389
|
+
const response = await fetchImplementation(tokenEndpoint, {
|
|
266
390
|
method: "POST",
|
|
267
391
|
headers: {
|
|
268
392
|
"Content-Type": "application/x-www-form-urlencoded",
|
package/dist/utils/profiles.d.ts
CHANGED
|
@@ -33,6 +33,12 @@ export type ProfileClientConfig = {
|
|
|
33
33
|
profileAuth?: ProfileAuth;
|
|
34
34
|
};
|
|
35
35
|
export declare function hasValue(value?: string | null): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the token endpoint, preferring the deployment's metadata document.
|
|
38
|
+
* Falls back to `<mount>/oauth/token`, keeping a trailing `/api` because
|
|
39
|
+
* self-hosted mounts the authorization server under it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveTokenEndpoint(apiUrl: string, fetchImplementation: typeof fetch): Promise<string>;
|
|
36
42
|
export declare function loadProfileClientConfig(): ProfileClientConfig;
|
|
37
43
|
export declare class ProfileAuth {
|
|
38
44
|
private state;
|
package/dist/utils/profiles.js
CHANGED
|
@@ -5,6 +5,8 @@ export const DEFAULT_API_URL = "https://api.smith.langchain.com";
|
|
|
5
5
|
const OAUTH_CLIENT_ID = "langsmith-cli";
|
|
6
6
|
const TOKEN_REFRESH_LEEWAY_MS = 60_000;
|
|
7
7
|
const TOKEN_REFRESH_TIMEOUT_MS = 10_000;
|
|
8
|
+
const OAUTH_DISCOVERY_TIMEOUT_MS = 5_000;
|
|
9
|
+
const WELL_KNOWN_OAUTH_PATH = "/.well-known/oauth-authorization-server";
|
|
8
10
|
function isBrowserLikeRuntime() {
|
|
9
11
|
const env = getEnv();
|
|
10
12
|
return env === "browser" || env === "webworker";
|
|
@@ -87,6 +89,126 @@ function normalizeConfigUrl(apiUrl) {
|
|
|
87
89
|
? normalized.slice(0, -apiV1Suffix.length)
|
|
88
90
|
: normalized;
|
|
89
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Metadata base URLs to probe, most specific first: the configured mount point,
|
|
94
|
+
* then the self-hosted and SaaS locations, so both a bare origin and an
|
|
95
|
+
* explicit `/api` resolve.
|
|
96
|
+
*/
|
|
97
|
+
function oauthDiscoveryCandidates(apiUrl) {
|
|
98
|
+
const given = normalizeConfigUrl(apiUrl);
|
|
99
|
+
const origin = given.endsWith("/api")
|
|
100
|
+
? given.slice(0, -"/api".length)
|
|
101
|
+
: given;
|
|
102
|
+
const candidates = [];
|
|
103
|
+
for (const candidate of [given, `${origin}/api`, origin]) {
|
|
104
|
+
if (candidate && candidate !== "/api" && !candidates.includes(candidate)) {
|
|
105
|
+
candidates.push(candidate);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return candidates;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check the document describes the deployment we probed. RFC 8414 requires the
|
|
112
|
+
* issuer to match the URL the well-known path was built from, and every
|
|
113
|
+
* endpoint must share the issuer's origin. Refresh tokens are posted to these
|
|
114
|
+
* endpoints, so an unvalidated document could redirect credentials elsewhere.
|
|
115
|
+
*/
|
|
116
|
+
function isTrustedOAuthMetadata(doc, base) {
|
|
117
|
+
const { issuer } = doc;
|
|
118
|
+
if (typeof issuer !== "string" ||
|
|
119
|
+
issuer.replace(/\/+$/, "") !== base.replace(/\/+$/, "")) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
let issuerUrl;
|
|
123
|
+
try {
|
|
124
|
+
issuerUrl = new URL(issuer);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
for (const endpoint of [
|
|
130
|
+
doc.device_authorization_endpoint,
|
|
131
|
+
doc.token_endpoint,
|
|
132
|
+
]) {
|
|
133
|
+
if (typeof endpoint !== "string" || !endpoint) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const url = new URL(endpoint);
|
|
138
|
+
if (url.protocol !== issuerUrl.protocol || url.host !== issuerUrl.host) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Metadata URLs for an issuer, RFC 8414 form first. RFC 8414 inserts the
|
|
150
|
+
* well-known segment between the origin and the issuer path, so
|
|
151
|
+
* `https://host/api` is described at
|
|
152
|
+
* `https://host/.well-known/oauth-authorization-server/api`. Deployments
|
|
153
|
+
* commonly also serve the appended form, and for a path-less issuer the two are
|
|
154
|
+
* identical.
|
|
155
|
+
*/
|
|
156
|
+
function oauthMetadataUrls(base) {
|
|
157
|
+
const appended = `${base}${WELL_KNOWN_OAUTH_PATH}`;
|
|
158
|
+
let inserted;
|
|
159
|
+
try {
|
|
160
|
+
const url = new URL(base);
|
|
161
|
+
inserted = `${url.origin}${WELL_KNOWN_OAUTH_PATH}${url.pathname === "/" ? "" : url.pathname}`;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return [appended];
|
|
165
|
+
}
|
|
166
|
+
return inserted === appended ? [inserted] : [inserted, appended];
|
|
167
|
+
}
|
|
168
|
+
async function fetchOAuthMetadata(url, base, fetchImplementation) {
|
|
169
|
+
let response;
|
|
170
|
+
try {
|
|
171
|
+
response = await fetchImplementation(url, {
|
|
172
|
+
method: "GET",
|
|
173
|
+
headers: { Accept: "application/json" },
|
|
174
|
+
signal: AbortSignal.timeout(OAUTH_DISCOVERY_TIMEOUT_MS),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
if (!response.ok) {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
let doc;
|
|
184
|
+
try {
|
|
185
|
+
// Self-hosted answers unknown paths with an HTML 200 from the SPA.
|
|
186
|
+
doc = (await response.json());
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
if (!doc || typeof doc !== "object" || !isTrustedOAuthMetadata(doc, base)) {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
return doc;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Resolve the token endpoint, preferring the deployment's metadata document.
|
|
198
|
+
* Falls back to `<mount>/oauth/token`, keeping a trailing `/api` because
|
|
199
|
+
* self-hosted mounts the authorization server under it.
|
|
200
|
+
*/
|
|
201
|
+
export async function resolveTokenEndpoint(apiUrl, fetchImplementation) {
|
|
202
|
+
for (const base of oauthDiscoveryCandidates(apiUrl)) {
|
|
203
|
+
for (const url of oauthMetadataUrls(base)) {
|
|
204
|
+
const doc = await fetchOAuthMetadata(url, base, fetchImplementation);
|
|
205
|
+
if (doc) {
|
|
206
|
+
return doc.token_endpoint;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return `${normalizeConfigUrl(apiUrl)}/oauth/token`;
|
|
211
|
+
}
|
|
90
212
|
function applyTokenResponse(profile, token) {
|
|
91
213
|
profile.oauth ??= {};
|
|
92
214
|
if (token.access_token) {
|
|
@@ -224,7 +346,8 @@ export class ProfileAuth {
|
|
|
224
346
|
client_id: OAUTH_CLIENT_ID,
|
|
225
347
|
refresh_token: this.state.profile.oauth?.refresh_token ?? refreshToken,
|
|
226
348
|
});
|
|
227
|
-
const
|
|
349
|
+
const tokenEndpoint = await resolveTokenEndpoint(refreshApiUrl, fetchImplementation);
|
|
350
|
+
const response = await fetchImplementation(tokenEndpoint, {
|
|
228
351
|
method: "POST",
|
|
229
352
|
headers: {
|
|
230
353
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueryBackend = void 0;
|
|
4
|
+
exports.getQueryBackend = getQueryBackend;
|
|
3
5
|
exports.v2RunToRun = v2RunToRun;
|
|
4
6
|
exports.loadTracesV2 = loadTracesV2;
|
|
7
|
+
exports.QueryBackend = {
|
|
8
|
+
CLICKHOUSE_ONLY: "clickhouse_only",
|
|
9
|
+
SMITHDB_ONLY: "smithdb_only",
|
|
10
|
+
DUAL: "dual",
|
|
11
|
+
};
|
|
12
|
+
/** Which backend(s) `/info`'s `instance_flags` indicate for run/trace queries. */
|
|
13
|
+
function getQueryBackend(instanceFlags) {
|
|
14
|
+
const flags = instanceFlags ?? {};
|
|
15
|
+
const chEnabled = Boolean(flags.ch_query_enabled ?? true);
|
|
16
|
+
const sdbEnabled = Boolean(flags.sdb_query_enabled ?? false);
|
|
17
|
+
if (!chEnabled && sdbEnabled)
|
|
18
|
+
return exports.QueryBackend.SMITHDB_ONLY;
|
|
19
|
+
if (chEnabled && sdbEnabled)
|
|
20
|
+
return exports.QueryBackend.DUAL;
|
|
21
|
+
return exports.QueryBackend.CLICKHOUSE_ONLY;
|
|
22
|
+
}
|
|
5
23
|
// Omitting selects from `/v2/runs/query` returns only the run ID.
|
|
6
24
|
const V2_RUN_SELECTS = [
|
|
7
25
|
"ID",
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { Run as V2Run } from "../_openapi_client/resources/runs/runs.js";
|
|
2
2
|
import type { Client } from "../client.js";
|
|
3
3
|
import type { Run, TracerSession } from "../schemas.js";
|
|
4
|
+
export declare const QueryBackend: {
|
|
5
|
+
readonly CLICKHOUSE_ONLY: "clickhouse_only";
|
|
6
|
+
readonly SMITHDB_ONLY: "smithdb_only";
|
|
7
|
+
readonly DUAL: "dual";
|
|
8
|
+
};
|
|
9
|
+
export type QueryBackend = (typeof QueryBackend)[keyof typeof QueryBackend];
|
|
10
|
+
/** Which backend(s) `/info`'s `instance_flags` indicate for run/trace queries. */
|
|
11
|
+
export declare function getQueryBackend(instanceFlags?: Record<string, unknown> | null): QueryBackend;
|
|
4
12
|
export declare function v2RunToRun(run: V2Run): Run;
|
|
5
13
|
export declare function loadTracesV2(client: Client, project: TracerSession, options: {
|
|
6
14
|
isRoot?: boolean;
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
export const QueryBackend = {
|
|
2
|
+
CLICKHOUSE_ONLY: "clickhouse_only",
|
|
3
|
+
SMITHDB_ONLY: "smithdb_only",
|
|
4
|
+
DUAL: "dual",
|
|
5
|
+
};
|
|
6
|
+
/** Which backend(s) `/info`'s `instance_flags` indicate for run/trace queries. */
|
|
7
|
+
export function getQueryBackend(instanceFlags) {
|
|
8
|
+
const flags = instanceFlags ?? {};
|
|
9
|
+
const chEnabled = Boolean(flags.ch_query_enabled ?? true);
|
|
10
|
+
const sdbEnabled = Boolean(flags.sdb_query_enabled ?? false);
|
|
11
|
+
if (!chEnabled && sdbEnabled)
|
|
12
|
+
return QueryBackend.SMITHDB_ONLY;
|
|
13
|
+
if (chEnabled && sdbEnabled)
|
|
14
|
+
return QueryBackend.DUAL;
|
|
15
|
+
return QueryBackend.CLICKHOUSE_ONLY;
|
|
16
|
+
}
|
|
1
17
|
// Omitting selects from `/v2/runs/query` returns only the run ID.
|
|
2
18
|
const V2_RUN_SELECTS = [
|
|
3
19
|
"ID",
|
package/dist/utils/warn.cjs
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports._resetWarnedMessages = _resetWarnedMessages;
|
|
3
4
|
exports.warnOnce = warnOnce;
|
|
4
5
|
const warnedMessages = {};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Clear the warn-once record so a later call warns again.
|
|
8
|
+
*
|
|
9
|
+
* Test-only. `warnedMessages` is module-global and never otherwise reset, so
|
|
10
|
+
* without this a test asserting "warning X was (not) emitted" depends on whether
|
|
11
|
+
* an earlier test in the same file already consumed X.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
function _resetWarnedMessages() {
|
|
16
|
+
for (const key of Object.keys(warnedMessages)) {
|
|
17
|
+
delete warnedMessages[key];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function warnOnce(message, options) {
|
|
21
|
+
const key = options?.code ?? message;
|
|
22
|
+
if (!warnedMessages[key]) {
|
|
23
|
+
warnedMessages[key] = true;
|
|
24
|
+
if (options?.type &&
|
|
25
|
+
typeof process !== "undefined" &&
|
|
26
|
+
typeof process.emitWarning === "function") {
|
|
27
|
+
process.emitWarning(message, { type: options.type, code: options.code });
|
|
28
|
+
}
|
|
29
|
+
else if (options?.type && options?.code) {
|
|
30
|
+
console.warn(`${options.type} [${options.code}]: ${message}`);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.warn(message);
|
|
34
|
+
}
|
|
9
35
|
}
|
|
10
36
|
}
|
package/dist/utils/warn.d.ts
CHANGED
package/dist/utils/warn.js
CHANGED
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
const warnedMessages = {};
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Clear the warn-once record so a later call warns again.
|
|
4
|
+
*
|
|
5
|
+
* Test-only. `warnedMessages` is module-global and never otherwise reset, so
|
|
6
|
+
* without this a test asserting "warning X was (not) emitted" depends on whether
|
|
7
|
+
* an earlier test in the same file already consumed X.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export function _resetWarnedMessages() {
|
|
12
|
+
for (const key of Object.keys(warnedMessages)) {
|
|
13
|
+
delete warnedMessages[key];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function warnOnce(message, options) {
|
|
17
|
+
const key = options?.code ?? message;
|
|
18
|
+
if (!warnedMessages[key]) {
|
|
19
|
+
warnedMessages[key] = true;
|
|
20
|
+
if (options?.type &&
|
|
21
|
+
typeof process !== "undefined" &&
|
|
22
|
+
typeof process.emitWarning === "function") {
|
|
23
|
+
process.emitWarning(message, { type: options.type, code: options.code });
|
|
24
|
+
}
|
|
25
|
+
else if (options?.type && options?.code) {
|
|
26
|
+
console.warn(`${options.type} [${options.code}]: ${message}`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
console.warn(message);
|
|
30
|
+
}
|
|
6
31
|
}
|
|
7
32
|
}
|
package/dist/wrappers/openai.cjs
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.wrapOpenAI = void 0;
|
|
4
4
|
const traceable_js_1 = require("../traceable.cjs");
|
|
5
|
+
const traceable_js_2 = require("../singletons/traceable.cjs");
|
|
6
|
+
const ls_agent_type_js_1 = require("../utils/ls_agent_type.cjs");
|
|
5
7
|
const TRACED_INVOCATION_KEYS = [
|
|
6
8
|
"frequency_penalty",
|
|
7
9
|
"n",
|
|
@@ -261,6 +263,7 @@ const getChatModelInvocationParamsFn = (provider, prepopulatedInvocationParams,
|
|
|
261
263
|
...prepopulatedInvocationParams,
|
|
262
264
|
...ls_invocation_params,
|
|
263
265
|
},
|
|
266
|
+
...(0, ls_agent_type_js_1.defaultLsAgentTypeMetadata)(requestMetadata, (0, traceable_js_2.getCurrentRunTree)(true)),
|
|
264
267
|
};
|
|
265
268
|
};
|
|
266
269
|
};
|
|
@@ -416,6 +419,7 @@ const wrapOpenAI = (openai, options) => {
|
|
|
416
419
|
...prepopulatedInvocationParams,
|
|
417
420
|
...ls_invocation_params,
|
|
418
421
|
},
|
|
422
|
+
...(0, ls_agent_type_js_1.defaultLsAgentTypeMetadata)({}, (0, traceable_js_2.getCurrentRunTree)(true)),
|
|
419
423
|
};
|
|
420
424
|
},
|
|
421
425
|
...cleanedOptions,
|
package/dist/wrappers/openai.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { isTraceableFunction, traceable, } from "../traceable.js";
|
|
2
|
+
import { getCurrentRunTree } from "../singletons/traceable.js";
|
|
3
|
+
import { defaultLsAgentTypeMetadata } from "../utils/ls_agent_type.js";
|
|
2
4
|
const TRACED_INVOCATION_KEYS = [
|
|
3
5
|
"frequency_penalty",
|
|
4
6
|
"n",
|
|
@@ -258,6 +260,7 @@ const getChatModelInvocationParamsFn = (provider, prepopulatedInvocationParams,
|
|
|
258
260
|
...prepopulatedInvocationParams,
|
|
259
261
|
...ls_invocation_params,
|
|
260
262
|
},
|
|
263
|
+
...defaultLsAgentTypeMetadata(requestMetadata, getCurrentRunTree(true)),
|
|
261
264
|
};
|
|
262
265
|
};
|
|
263
266
|
};
|
|
@@ -413,6 +416,7 @@ export const wrapOpenAI = (openai, options) => {
|
|
|
413
416
|
...prepopulatedInvocationParams,
|
|
414
417
|
...ls_invocation_params,
|
|
415
418
|
},
|
|
419
|
+
...defaultLsAgentTypeMetadata({}, getCurrentRunTree(true)),
|
|
416
420
|
};
|
|
417
421
|
},
|
|
418
422
|
...cleanedOptions,
|
|
@@ -10,6 +10,7 @@ const node_async_hooks_1 = require("node:async_hooks");
|
|
|
10
10
|
const run_trees_js_1 = require("../run_trees.cjs");
|
|
11
11
|
const client_js_1 = require("../client.cjs");
|
|
12
12
|
const traceable_js_1 = require("../singletons/traceable.cjs");
|
|
13
|
+
const ls_agent_type_js_1 = require("../utils/ls_agent_type.cjs");
|
|
13
14
|
traceable_js_1.AsyncLocalStorageProviderSingleton.initializeGlobalInstance(new node_async_hooks_1.AsyncLocalStorage());
|
|
14
15
|
/**
|
|
15
16
|
* Set the current AsyncLocalStorage store to the given RunTree without a
|
|
@@ -521,14 +522,15 @@ class OpenAIAgentsTracingProcessor {
|
|
|
521
522
|
else {
|
|
522
523
|
runName = "Agent workflow";
|
|
523
524
|
}
|
|
524
|
-
//
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
},
|
|
525
|
+
// Merge three sources: processor defaults, trace.metadata (user's per-run
|
|
526
|
+
// ls_agent_type), and force-set ls_integration.
|
|
527
|
+
const mergedMetadata = {
|
|
528
|
+
...this._metadata,
|
|
529
|
+
...(trace.metadata ?? {}),
|
|
530
|
+
ls_integration: "openai-agents-sdk",
|
|
531
531
|
};
|
|
532
|
+
Object.assign(mergedMetadata, (0, ls_agent_type_js_1.defaultLsAgentTypeMetadata)(mergedMetadata, currentRunTree));
|
|
533
|
+
const runExtra = { metadata: mergedMetadata };
|
|
532
534
|
const traceDict = trace.toJSON() ?? {};
|
|
533
535
|
const groupId = trace.groupId ??
|
|
534
536
|
traceDict.groupId ??
|
|
@@ -589,9 +591,10 @@ class OpenAIAgentsTracingProcessor {
|
|
|
589
591
|
}
|
|
590
592
|
this._runs.delete(trace.traceId);
|
|
591
593
|
const traceDict = trace.toJSON() ?? {};
|
|
594
|
+
// trace.metadata may have new keys since onTraceStart; pull them in.
|
|
592
595
|
const metadata = {
|
|
593
|
-
...traceDict.metadata,
|
|
594
596
|
...this._metadata,
|
|
597
|
+
...traceDict.metadata,
|
|
595
598
|
};
|
|
596
599
|
try {
|
|
597
600
|
// Update run with final inputs/outputs
|
|
@@ -695,10 +698,10 @@ class OpenAIAgentsTracingProcessor {
|
|
|
695
698
|
if (!childRun.extra.metadata) {
|
|
696
699
|
childRun.extra.metadata = {};
|
|
697
700
|
}
|
|
698
|
-
childRun.extra.metadata
|
|
699
|
-
|
|
700
|
-
ls_agent_type
|
|
701
|
-
}
|
|
701
|
+
const meta = childRun.extra.metadata;
|
|
702
|
+
if (!ls_agent_type_js_1.NON_ROOT_LS_AGENT_TYPES.has(meta.ls_agent_type)) {
|
|
703
|
+
meta.ls_agent_type = "subagent";
|
|
704
|
+
}
|
|
702
705
|
}
|
|
703
706
|
}
|
|
704
707
|
// Track span data type for parent lookups
|
|
@@ -7,6 +7,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
7
7
|
import { RunTree } from "../run_trees.js";
|
|
8
8
|
import { Client } from "../client.js";
|
|
9
9
|
import { AsyncLocalStorageProviderSingleton, getCurrentRunTree, } from "../singletons/traceable.js";
|
|
10
|
+
import { NON_ROOT_LS_AGENT_TYPES, defaultLsAgentTypeMetadata, } from "../utils/ls_agent_type.js";
|
|
10
11
|
AsyncLocalStorageProviderSingleton.initializeGlobalInstance(new AsyncLocalStorage());
|
|
11
12
|
/**
|
|
12
13
|
* Set the current AsyncLocalStorage store to the given RunTree without a
|
|
@@ -518,14 +519,15 @@ export class OpenAIAgentsTracingProcessor {
|
|
|
518
519
|
else {
|
|
519
520
|
runName = "Agent workflow";
|
|
520
521
|
}
|
|
521
|
-
//
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
},
|
|
522
|
+
// Merge three sources: processor defaults, trace.metadata (user's per-run
|
|
523
|
+
// ls_agent_type), and force-set ls_integration.
|
|
524
|
+
const mergedMetadata = {
|
|
525
|
+
...this._metadata,
|
|
526
|
+
...(trace.metadata ?? {}),
|
|
527
|
+
ls_integration: "openai-agents-sdk",
|
|
528
528
|
};
|
|
529
|
+
Object.assign(mergedMetadata, defaultLsAgentTypeMetadata(mergedMetadata, currentRunTree));
|
|
530
|
+
const runExtra = { metadata: mergedMetadata };
|
|
529
531
|
const traceDict = trace.toJSON() ?? {};
|
|
530
532
|
const groupId = trace.groupId ??
|
|
531
533
|
traceDict.groupId ??
|
|
@@ -586,9 +588,10 @@ export class OpenAIAgentsTracingProcessor {
|
|
|
586
588
|
}
|
|
587
589
|
this._runs.delete(trace.traceId);
|
|
588
590
|
const traceDict = trace.toJSON() ?? {};
|
|
591
|
+
// trace.metadata may have new keys since onTraceStart; pull them in.
|
|
589
592
|
const metadata = {
|
|
590
|
-
...traceDict.metadata,
|
|
591
593
|
...this._metadata,
|
|
594
|
+
...traceDict.metadata,
|
|
592
595
|
};
|
|
593
596
|
try {
|
|
594
597
|
// Update run with final inputs/outputs
|
|
@@ -692,10 +695,10 @@ export class OpenAIAgentsTracingProcessor {
|
|
|
692
695
|
if (!childRun.extra.metadata) {
|
|
693
696
|
childRun.extra.metadata = {};
|
|
694
697
|
}
|
|
695
|
-
childRun.extra.metadata
|
|
696
|
-
|
|
697
|
-
ls_agent_type
|
|
698
|
-
}
|
|
698
|
+
const meta = childRun.extra.metadata;
|
|
699
|
+
if (!NON_ROOT_LS_AGENT_TYPES.has(meta.ls_agent_type)) {
|
|
700
|
+
meta.ls_agent_type = "subagent";
|
|
701
|
+
}
|
|
699
702
|
}
|
|
700
703
|
}
|
|
701
704
|
// Track span data type for parent lookups
|