langsmith 0.7.5 → 0.7.7
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/README.md +41 -0
- package/dist/client.cjs +13 -4
- package/dist/client.d.ts +4 -1
- package/dist/client.js +13 -4
- package/dist/evaluation/_runner.cjs +77 -0
- package/dist/evaluation/_runner.d.ts +4 -0
- package/dist/evaluation/_runner.js +77 -0
- 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 +16 -0
- package/dist/sandbox/command_handle.d.ts +2 -0
- package/dist/sandbox/command_handle.js +16 -0
- package/dist/sandbox/index.cjs +5 -1
- package/dist/sandbox/index.d.ts +2 -1
- package/dist/sandbox/index.js +1 -0
- package/dist/sandbox/proxy_config.cjs +47 -0
- package/dist/sandbox/proxy_config.d.ts +12 -0
- package/dist/sandbox/proxy_config.js +42 -0
- package/dist/sandbox/sandbox.cjs +6 -4
- package/dist/sandbox/sandbox.js +6 -4
- package/dist/sandbox/types.d.ts +29 -1
- package/dist/utils/fs.browser.cjs +11 -0
- package/dist/utils/fs.browser.d.ts +3 -0
- package/dist/utils/fs.browser.js +8 -0
- package/dist/utils/fs.cjs +22 -0
- package/dist/utils/fs.d.ts +3 -0
- package/dist/utils/fs.js +19 -0
- package/dist/utils/profile-lock.cjs +140 -0
- package/dist/utils/profile-lock.d.ts +20 -0
- package/dist/utils/profile-lock.js +103 -0
- package/dist/utils/profiles.cjs +28 -2
- package/dist/utils/profiles.d.ts +1 -0
- package/dist/utils/profiles.js +28 -2
- package/dist/wrappers/gemini.cjs +3 -40
- package/dist/wrappers/gemini.js +3 -40
- package/dist/wrappers/gemini.utils.cjs +41 -0
- package/dist/wrappers/gemini.utils.d.ts +3 -0
- package/dist/wrappers/gemini.utils.js +37 -0
- package/package.json +4 -4
package/dist/utils/profiles.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getEnv, getEnvironmentVariable } from "./env.js";
|
|
2
2
|
import * as fsUtils from "./fs.js";
|
|
3
|
+
import { acquireOAuthRefreshLock } from "./profile-lock.js";
|
|
3
4
|
export const DEFAULT_API_URL = "https://api.smith.langchain.com";
|
|
4
5
|
const OAUTH_CLIENT_ID = "langsmith-cli";
|
|
5
6
|
const TOKEN_REFRESH_LEEWAY_MS = 60_000;
|
|
@@ -189,17 +190,39 @@ export class ProfileAuth {
|
|
|
189
190
|
isProfileAuthorizationHeader(value) {
|
|
190
191
|
return value === this.managedAuthorizationValue;
|
|
191
192
|
}
|
|
193
|
+
reloadProfile() {
|
|
194
|
+
try {
|
|
195
|
+
const config = JSON.parse(fsUtils.readFileSync(this.state.configPath));
|
|
196
|
+
const profile = config.profiles?.[this.state.profileName];
|
|
197
|
+
if (!profile) {
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
this.state.config = config;
|
|
201
|
+
this.state.profile = profile;
|
|
202
|
+
return profile;
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
192
208
|
async refreshOAuthToken(fetchImplementation) {
|
|
193
209
|
const refreshToken = this.state.profile.oauth?.refresh_token;
|
|
194
210
|
if (!refreshToken) {
|
|
195
211
|
return;
|
|
196
212
|
}
|
|
197
213
|
const refreshApiUrl = trimConfigValue(this.state.profile.api_url) ?? DEFAULT_API_URL;
|
|
214
|
+
const deadline = Date.now() + TOKEN_REFRESH_TIMEOUT_MS;
|
|
215
|
+
let lock;
|
|
198
216
|
try {
|
|
217
|
+
lock = await acquireOAuthRefreshLock(this.state.configPath, deadline);
|
|
218
|
+
const fresh = this.reloadProfile();
|
|
219
|
+
if (fresh && !shouldRefreshProfileToken(this.state.profile)) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
199
222
|
const body = new URLSearchParams({
|
|
200
223
|
grant_type: "refresh_token",
|
|
201
224
|
client_id: OAUTH_CLIENT_ID,
|
|
202
|
-
refresh_token: refreshToken,
|
|
225
|
+
refresh_token: this.state.profile.oauth?.refresh_token ?? refreshToken,
|
|
203
226
|
});
|
|
204
227
|
const response = await fetchImplementation(`${normalizeConfigUrl(refreshApiUrl)}/oauth/token`, {
|
|
205
228
|
method: "POST",
|
|
@@ -207,7 +230,7 @@ export class ProfileAuth {
|
|
|
207
230
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
208
231
|
},
|
|
209
232
|
body: body.toString(),
|
|
210
|
-
signal: AbortSignal.timeout(
|
|
233
|
+
signal: AbortSignal.timeout(Math.max(0, deadline - Date.now())),
|
|
211
234
|
});
|
|
212
235
|
if (!response.ok) {
|
|
213
236
|
return;
|
|
@@ -224,6 +247,9 @@ export class ProfileAuth {
|
|
|
224
247
|
catch {
|
|
225
248
|
return;
|
|
226
249
|
}
|
|
250
|
+
finally {
|
|
251
|
+
await lock?.release();
|
|
252
|
+
}
|
|
227
253
|
}
|
|
228
254
|
rememberProfileAuthHeader(header) {
|
|
229
255
|
this.managedAuthorizationValue =
|
package/dist/wrappers/gemini.cjs
CHANGED
|
@@ -2,44 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.wrapGemini = wrapGemini;
|
|
4
4
|
const traceable_js_1 = require("../traceable.cjs");
|
|
5
|
-
const
|
|
6
|
-
const usageMetadata = {
|
|
7
|
-
input_tokens: usage.promptTokenCount || 0,
|
|
8
|
-
output_tokens: (() => {
|
|
9
|
-
if ("responseTokenCount" in usage) {
|
|
10
|
-
return usage.responseTokenCount || 0;
|
|
11
|
-
}
|
|
12
|
-
if ("candidatesTokenCount" in usage) {
|
|
13
|
-
return usage.candidatesTokenCount || 0;
|
|
14
|
-
}
|
|
15
|
-
return 0;
|
|
16
|
-
})(),
|
|
17
|
-
total_tokens: usage.totalTokenCount || 0,
|
|
18
|
-
};
|
|
19
|
-
// Add input token details if available
|
|
20
|
-
usageMetadata.input_token_details = {
|
|
21
|
-
...(usage.cachedContentTokenCount && {
|
|
22
|
-
cache_read_over_200k: Math.max(0, usage.cachedContentTokenCount - 200000),
|
|
23
|
-
}),
|
|
24
|
-
...(usage.promptTokenCount && {
|
|
25
|
-
over_200k: Math.max(0, usage.promptTokenCount - 200000),
|
|
26
|
-
}),
|
|
27
|
-
...(usage.cachedContentTokenCount && {
|
|
28
|
-
cache_read: usage.cachedContentTokenCount,
|
|
29
|
-
}),
|
|
30
|
-
};
|
|
31
|
-
// Add output token details if available
|
|
32
|
-
usageMetadata.output_token_details = {
|
|
33
|
-
...("candidatesTokenCount" in usage &&
|
|
34
|
-
usage.candidatesTokenCount != null && {
|
|
35
|
-
over_200k: Math.max(0, usage.candidatesTokenCount - 200000),
|
|
36
|
-
}),
|
|
37
|
-
...(usage.thoughtsTokenCount && {
|
|
38
|
-
reasoning: usage.thoughtsTokenCount,
|
|
39
|
-
}),
|
|
40
|
-
};
|
|
41
|
-
return usageMetadata;
|
|
42
|
-
};
|
|
5
|
+
const gemini_utils_js_1 = require("./gemini.utils.cjs");
|
|
43
6
|
const chatAggregator = (input) => {
|
|
44
7
|
const chunks = Array.isArray(input) &&
|
|
45
8
|
input.every((item) => typeof item === "object" && item !== null)
|
|
@@ -161,7 +124,7 @@ const chatAggregator = (input) => {
|
|
|
161
124
|
result.safety_ratings = safetyRatings;
|
|
162
125
|
}
|
|
163
126
|
if (usageMetadata) {
|
|
164
|
-
result.usage_metadata =
|
|
127
|
+
result.usage_metadata = (0, gemini_utils_js_1.createGeminiUsageMetadata)(usageMetadata);
|
|
165
128
|
}
|
|
166
129
|
return result;
|
|
167
130
|
};
|
|
@@ -354,7 +317,7 @@ function processGeminiOutputs(outputs) {
|
|
|
354
317
|
result.safety_ratings = safetyRatings;
|
|
355
318
|
}
|
|
356
319
|
if ("usageMetadata" in response && response.usageMetadata) {
|
|
357
|
-
result.usage_metadata =
|
|
320
|
+
result.usage_metadata = (0, gemini_utils_js_1.createGeminiUsageMetadata)(response.usageMetadata);
|
|
358
321
|
}
|
|
359
322
|
return result;
|
|
360
323
|
}
|
package/dist/wrappers/gemini.js
CHANGED
|
@@ -1,42 +1,5 @@
|
|
|
1
1
|
import { isTraceableFunction, traceable, } from "../traceable.js";
|
|
2
|
-
|
|
3
|
-
const usageMetadata = {
|
|
4
|
-
input_tokens: usage.promptTokenCount || 0,
|
|
5
|
-
output_tokens: (() => {
|
|
6
|
-
if ("responseTokenCount" in usage) {
|
|
7
|
-
return usage.responseTokenCount || 0;
|
|
8
|
-
}
|
|
9
|
-
if ("candidatesTokenCount" in usage) {
|
|
10
|
-
return usage.candidatesTokenCount || 0;
|
|
11
|
-
}
|
|
12
|
-
return 0;
|
|
13
|
-
})(),
|
|
14
|
-
total_tokens: usage.totalTokenCount || 0,
|
|
15
|
-
};
|
|
16
|
-
// Add input token details if available
|
|
17
|
-
usageMetadata.input_token_details = {
|
|
18
|
-
...(usage.cachedContentTokenCount && {
|
|
19
|
-
cache_read_over_200k: Math.max(0, usage.cachedContentTokenCount - 200000),
|
|
20
|
-
}),
|
|
21
|
-
...(usage.promptTokenCount && {
|
|
22
|
-
over_200k: Math.max(0, usage.promptTokenCount - 200000),
|
|
23
|
-
}),
|
|
24
|
-
...(usage.cachedContentTokenCount && {
|
|
25
|
-
cache_read: usage.cachedContentTokenCount,
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
28
|
-
// Add output token details if available
|
|
29
|
-
usageMetadata.output_token_details = {
|
|
30
|
-
...("candidatesTokenCount" in usage &&
|
|
31
|
-
usage.candidatesTokenCount != null && {
|
|
32
|
-
over_200k: Math.max(0, usage.candidatesTokenCount - 200000),
|
|
33
|
-
}),
|
|
34
|
-
...(usage.thoughtsTokenCount && {
|
|
35
|
-
reasoning: usage.thoughtsTokenCount,
|
|
36
|
-
}),
|
|
37
|
-
};
|
|
38
|
-
return usageMetadata;
|
|
39
|
-
};
|
|
2
|
+
import { createGeminiUsageMetadata } from "./gemini.utils.js";
|
|
40
3
|
const chatAggregator = (input) => {
|
|
41
4
|
const chunks = Array.isArray(input) &&
|
|
42
5
|
input.every((item) => typeof item === "object" && item !== null)
|
|
@@ -158,7 +121,7 @@ const chatAggregator = (input) => {
|
|
|
158
121
|
result.safety_ratings = safetyRatings;
|
|
159
122
|
}
|
|
160
123
|
if (usageMetadata) {
|
|
161
|
-
result.usage_metadata =
|
|
124
|
+
result.usage_metadata = createGeminiUsageMetadata(usageMetadata);
|
|
162
125
|
}
|
|
163
126
|
return result;
|
|
164
127
|
};
|
|
@@ -351,7 +314,7 @@ function processGeminiOutputs(outputs) {
|
|
|
351
314
|
result.safety_ratings = safetyRatings;
|
|
352
315
|
}
|
|
353
316
|
if ("usageMetadata" in response && response.usageMetadata) {
|
|
354
|
-
result.usage_metadata =
|
|
317
|
+
result.usage_metadata = createGeminiUsageMetadata(response.usageMetadata);
|
|
355
318
|
}
|
|
356
319
|
return result;
|
|
357
320
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createGeminiUsageMetadata = void 0;
|
|
4
|
+
const createGeminiUsageMetadata = (usage) => {
|
|
5
|
+
const usageMetadata = {
|
|
6
|
+
input_tokens: usage.promptTokenCount || 0,
|
|
7
|
+
output_tokens: (() => {
|
|
8
|
+
if ("responseTokenCount" in usage) {
|
|
9
|
+
return usage.responseTokenCount || 0;
|
|
10
|
+
}
|
|
11
|
+
if ("candidatesTokenCount" in usage) {
|
|
12
|
+
return usage.candidatesTokenCount || 0;
|
|
13
|
+
}
|
|
14
|
+
return 0;
|
|
15
|
+
})(),
|
|
16
|
+
total_tokens: usage.totalTokenCount || 0,
|
|
17
|
+
};
|
|
18
|
+
// Add input token details if available
|
|
19
|
+
usageMetadata.input_token_details = {
|
|
20
|
+
cache_read: usage.cachedContentTokenCount != null
|
|
21
|
+
? Math.min(usage.cachedContentTokenCount, 200_000)
|
|
22
|
+
: undefined,
|
|
23
|
+
cache_read_over_200k: usage.cachedContentTokenCount != null
|
|
24
|
+
? Math.max(0, usage.cachedContentTokenCount - 200_000)
|
|
25
|
+
: undefined,
|
|
26
|
+
over_200k: usage.promptTokenCount != null
|
|
27
|
+
? Math.max(0, usage.promptTokenCount -
|
|
28
|
+
(usage.cachedContentTokenCount || 0) -
|
|
29
|
+
200_000)
|
|
30
|
+
: undefined,
|
|
31
|
+
};
|
|
32
|
+
// Add output token details if available
|
|
33
|
+
usageMetadata.output_token_details = {
|
|
34
|
+
over_200k: "candidatesTokenCount" in usage && usage.candidatesTokenCount != null
|
|
35
|
+
? Math.max(0, usage.candidatesTokenCount - 200_000)
|
|
36
|
+
: undefined,
|
|
37
|
+
reasoning: usage.thoughtsTokenCount ?? undefined,
|
|
38
|
+
};
|
|
39
|
+
return usageMetadata;
|
|
40
|
+
};
|
|
41
|
+
exports.createGeminiUsageMetadata = createGeminiUsageMetadata;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const createGeminiUsageMetadata = (usage) => {
|
|
2
|
+
const usageMetadata = {
|
|
3
|
+
input_tokens: usage.promptTokenCount || 0,
|
|
4
|
+
output_tokens: (() => {
|
|
5
|
+
if ("responseTokenCount" in usage) {
|
|
6
|
+
return usage.responseTokenCount || 0;
|
|
7
|
+
}
|
|
8
|
+
if ("candidatesTokenCount" in usage) {
|
|
9
|
+
return usage.candidatesTokenCount || 0;
|
|
10
|
+
}
|
|
11
|
+
return 0;
|
|
12
|
+
})(),
|
|
13
|
+
total_tokens: usage.totalTokenCount || 0,
|
|
14
|
+
};
|
|
15
|
+
// Add input token details if available
|
|
16
|
+
usageMetadata.input_token_details = {
|
|
17
|
+
cache_read: usage.cachedContentTokenCount != null
|
|
18
|
+
? Math.min(usage.cachedContentTokenCount, 200_000)
|
|
19
|
+
: undefined,
|
|
20
|
+
cache_read_over_200k: usage.cachedContentTokenCount != null
|
|
21
|
+
? Math.max(0, usage.cachedContentTokenCount - 200_000)
|
|
22
|
+
: undefined,
|
|
23
|
+
over_200k: usage.promptTokenCount != null
|
|
24
|
+
? Math.max(0, usage.promptTokenCount -
|
|
25
|
+
(usage.cachedContentTokenCount || 0) -
|
|
26
|
+
200_000)
|
|
27
|
+
: undefined,
|
|
28
|
+
};
|
|
29
|
+
// Add output token details if available
|
|
30
|
+
usageMetadata.output_token_details = {
|
|
31
|
+
over_200k: "candidatesTokenCount" in usage && usage.candidatesTokenCount != null
|
|
32
|
+
? Math.max(0, usage.candidatesTokenCount - 200_000)
|
|
33
|
+
: undefined,
|
|
34
|
+
reasoning: usage.thoughtsTokenCount ?? undefined,
|
|
35
|
+
};
|
|
36
|
+
return usageMetadata;
|
|
37
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.7",
|
|
4
4
|
"description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
|
|
5
5
|
"packageManager": "pnpm@10.33.0",
|
|
6
6
|
"files": [
|
|
@@ -128,8 +128,8 @@
|
|
|
128
128
|
"watch:single": "NODE_OPTIONS=--experimental-vm-modules pnpm jest --watch --config jest.config.cjs --testTimeout 100000",
|
|
129
129
|
"test:vitest": "vitest run --config vitest.config.ts",
|
|
130
130
|
"test:eval:vitest": "vitest run --config ls.vitest.config.ts",
|
|
131
|
-
"lint": "oxlint src/",
|
|
132
|
-
"lint:fix": "oxlint --fix src/",
|
|
131
|
+
"lint": "oxlint src/ --ignore-pattern 'src/_openapi_client/**'",
|
|
132
|
+
"lint:fix": "oxlint --fix src/ --ignore-pattern 'src/_openapi_client/**'",
|
|
133
133
|
"format": "oxfmt --write 'src/**/*.{ts,tsx,mts}'",
|
|
134
134
|
"format:check": "oxfmt --check 'src/**/*.{ts,tsx,mts}'",
|
|
135
135
|
"check:types": "tsc --noEmit",
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
"@babel/preset-env": "^7.22.4",
|
|
165
165
|
"@faker-js/faker": "^8.4.1",
|
|
166
166
|
"@google/genai": "^2.0.1",
|
|
167
|
-
"@jest/globals": "^
|
|
167
|
+
"@jest/globals": "^30.4.1",
|
|
168
168
|
"@jest/reporters": "^30.2.0",
|
|
169
169
|
"@langchain/core": "^0.3.72",
|
|
170
170
|
"@langchain/langgraph": "^0.3.6",
|