langsmith 0.1.5 → 0.1.6
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/client.cjs +34 -15
- package/dist/client.d.ts +1 -0
- package/dist/client.js +34 -15
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/utils/async_caller.cjs +14 -2
- package/dist/utils/async_caller.d.ts +4 -0
- package/dist/utils/async_caller.js +14 -2
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -98,6 +98,18 @@ function assertUuid(str) {
|
|
|
98
98
|
throw new Error(`Invalid UUID: ${str}`);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
+
const handle429 = async (response) => {
|
|
102
|
+
if (response?.status === 429) {
|
|
103
|
+
const retryAfter = parseInt(response.headers.get("retry-after") ?? "30", 10) * 1000;
|
|
104
|
+
if (retryAfter > 0) {
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, retryAfter));
|
|
106
|
+
// Return directly after calling this check
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Fall back to existing status checks
|
|
111
|
+
return false;
|
|
112
|
+
};
|
|
101
113
|
class Queue {
|
|
102
114
|
constructor() {
|
|
103
115
|
Object.defineProperty(this, "items", {
|
|
@@ -161,6 +173,12 @@ class Client {
|
|
|
161
173
|
writable: true,
|
|
162
174
|
value: void 0
|
|
163
175
|
});
|
|
176
|
+
Object.defineProperty(this, "batchIngestCaller", {
|
|
177
|
+
enumerable: true,
|
|
178
|
+
configurable: true,
|
|
179
|
+
writable: true,
|
|
180
|
+
value: void 0
|
|
181
|
+
});
|
|
164
182
|
Object.defineProperty(this, "timeout_ms", {
|
|
165
183
|
enumerable: true,
|
|
166
184
|
configurable: true,
|
|
@@ -246,6 +264,10 @@ class Client {
|
|
|
246
264
|
this.webUrl = trimQuotes(config.webUrl ?? defaultConfig.webUrl);
|
|
247
265
|
this.timeout_ms = config.timeout_ms ?? 12000;
|
|
248
266
|
this.caller = new async_caller_js_1.AsyncCaller(config.callerOptions ?? {});
|
|
267
|
+
this.batchIngestCaller = new async_caller_js_1.AsyncCaller({
|
|
268
|
+
...(config.callerOptions ?? {}),
|
|
269
|
+
onFailedResponseHook: handle429,
|
|
270
|
+
});
|
|
249
271
|
this.hideInputs = config.hideInputs ?? defaultConfig.hideInputs;
|
|
250
272
|
this.hideOutputs = config.hideOutputs ?? defaultConfig.hideOutputs;
|
|
251
273
|
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
@@ -448,7 +470,9 @@ class Client {
|
|
|
448
470
|
if (this.autoBatchQueue.size > 0) {
|
|
449
471
|
this.autoBatchTimeout = setTimeout(() => {
|
|
450
472
|
this.autoBatchTimeout = undefined;
|
|
451
|
-
|
|
473
|
+
// This error would happen in the background and is uncatchable
|
|
474
|
+
// from the outside. So just log instead.
|
|
475
|
+
void this.drainAutoBatchQueue().catch(console.error);
|
|
452
476
|
}, oldTimeout
|
|
453
477
|
? this.autoBatchAggregationDelayMs
|
|
454
478
|
: this.autoBatchInitialDelayMs);
|
|
@@ -487,7 +511,7 @@ class Client {
|
|
|
487
511
|
void this.processRunOperation({
|
|
488
512
|
action: "create",
|
|
489
513
|
item: runCreate,
|
|
490
|
-
});
|
|
514
|
+
}).catch(console.error);
|
|
491
515
|
return;
|
|
492
516
|
}
|
|
493
517
|
const mergedRunCreateParams = await mergeRuntimeEnvIntoRunCreates([
|
|
@@ -562,18 +586,13 @@ class Client {
|
|
|
562
586
|
"Content-Type": "application/json",
|
|
563
587
|
Accept: "application/json",
|
|
564
588
|
};
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
await raiseForStatus(response, "batch create run");
|
|
573
|
-
}
|
|
574
|
-
catch (e) {
|
|
575
|
-
console.error(`Failed to batch create runs: ${e}`);
|
|
576
|
-
}
|
|
589
|
+
const response = await this.batchIngestCaller.call(fetch, `${this.apiUrl}/runs/batch`, {
|
|
590
|
+
method: "POST",
|
|
591
|
+
headers,
|
|
592
|
+
body: JSON.stringify(body),
|
|
593
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
594
|
+
});
|
|
595
|
+
await raiseForStatus(response, "batch create run");
|
|
577
596
|
}
|
|
578
597
|
async updateRun(runId, run) {
|
|
579
598
|
assertUuid(runId);
|
|
@@ -598,7 +617,7 @@ class Client {
|
|
|
598
617
|
return;
|
|
599
618
|
}
|
|
600
619
|
else {
|
|
601
|
-
void this.processRunOperation({ action: "update", item: data });
|
|
620
|
+
void this.processRunOperation({ action: "update", item: data }).catch(console.error);
|
|
602
621
|
}
|
|
603
622
|
return;
|
|
604
623
|
}
|
package/dist/client.d.ts
CHANGED
package/dist/client.js
CHANGED
|
@@ -72,6 +72,18 @@ function assertUuid(str) {
|
|
|
72
72
|
throw new Error(`Invalid UUID: ${str}`);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
const handle429 = async (response) => {
|
|
76
|
+
if (response?.status === 429) {
|
|
77
|
+
const retryAfter = parseInt(response.headers.get("retry-after") ?? "30", 10) * 1000;
|
|
78
|
+
if (retryAfter > 0) {
|
|
79
|
+
await new Promise((resolve) => setTimeout(resolve, retryAfter));
|
|
80
|
+
// Return directly after calling this check
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Fall back to existing status checks
|
|
85
|
+
return false;
|
|
86
|
+
};
|
|
75
87
|
export class Queue {
|
|
76
88
|
constructor() {
|
|
77
89
|
Object.defineProperty(this, "items", {
|
|
@@ -134,6 +146,12 @@ export class Client {
|
|
|
134
146
|
writable: true,
|
|
135
147
|
value: void 0
|
|
136
148
|
});
|
|
149
|
+
Object.defineProperty(this, "batchIngestCaller", {
|
|
150
|
+
enumerable: true,
|
|
151
|
+
configurable: true,
|
|
152
|
+
writable: true,
|
|
153
|
+
value: void 0
|
|
154
|
+
});
|
|
137
155
|
Object.defineProperty(this, "timeout_ms", {
|
|
138
156
|
enumerable: true,
|
|
139
157
|
configurable: true,
|
|
@@ -219,6 +237,10 @@ export class Client {
|
|
|
219
237
|
this.webUrl = trimQuotes(config.webUrl ?? defaultConfig.webUrl);
|
|
220
238
|
this.timeout_ms = config.timeout_ms ?? 12000;
|
|
221
239
|
this.caller = new AsyncCaller(config.callerOptions ?? {});
|
|
240
|
+
this.batchIngestCaller = new AsyncCaller({
|
|
241
|
+
...(config.callerOptions ?? {}),
|
|
242
|
+
onFailedResponseHook: handle429,
|
|
243
|
+
});
|
|
222
244
|
this.hideInputs = config.hideInputs ?? defaultConfig.hideInputs;
|
|
223
245
|
this.hideOutputs = config.hideOutputs ?? defaultConfig.hideOutputs;
|
|
224
246
|
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
@@ -421,7 +443,9 @@ export class Client {
|
|
|
421
443
|
if (this.autoBatchQueue.size > 0) {
|
|
422
444
|
this.autoBatchTimeout = setTimeout(() => {
|
|
423
445
|
this.autoBatchTimeout = undefined;
|
|
424
|
-
|
|
446
|
+
// This error would happen in the background and is uncatchable
|
|
447
|
+
// from the outside. So just log instead.
|
|
448
|
+
void this.drainAutoBatchQueue().catch(console.error);
|
|
425
449
|
}, oldTimeout
|
|
426
450
|
? this.autoBatchAggregationDelayMs
|
|
427
451
|
: this.autoBatchInitialDelayMs);
|
|
@@ -460,7 +484,7 @@ export class Client {
|
|
|
460
484
|
void this.processRunOperation({
|
|
461
485
|
action: "create",
|
|
462
486
|
item: runCreate,
|
|
463
|
-
});
|
|
487
|
+
}).catch(console.error);
|
|
464
488
|
return;
|
|
465
489
|
}
|
|
466
490
|
const mergedRunCreateParams = await mergeRuntimeEnvIntoRunCreates([
|
|
@@ -535,18 +559,13 @@ export class Client {
|
|
|
535
559
|
"Content-Type": "application/json",
|
|
536
560
|
Accept: "application/json",
|
|
537
561
|
};
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
await raiseForStatus(response, "batch create run");
|
|
546
|
-
}
|
|
547
|
-
catch (e) {
|
|
548
|
-
console.error(`Failed to batch create runs: ${e}`);
|
|
549
|
-
}
|
|
562
|
+
const response = await this.batchIngestCaller.call(fetch, `${this.apiUrl}/runs/batch`, {
|
|
563
|
+
method: "POST",
|
|
564
|
+
headers,
|
|
565
|
+
body: JSON.stringify(body),
|
|
566
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
567
|
+
});
|
|
568
|
+
await raiseForStatus(response, "batch create run");
|
|
550
569
|
}
|
|
551
570
|
async updateRun(runId, run) {
|
|
552
571
|
assertUuid(runId);
|
|
@@ -571,7 +590,7 @@ export class Client {
|
|
|
571
590
|
return;
|
|
572
591
|
}
|
|
573
592
|
else {
|
|
574
|
-
void this.processRunOperation({ action: "update", item: data });
|
|
593
|
+
void this.processRunOperation({ action: "update", item: data }).catch(console.error);
|
|
575
594
|
}
|
|
576
595
|
return;
|
|
577
596
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -6,4 +6,4 @@ Object.defineProperty(exports, "Client", { enumerable: true, get: function () {
|
|
|
6
6
|
var run_trees_js_1 = require("./run_trees.cjs");
|
|
7
7
|
Object.defineProperty(exports, "RunTree", { enumerable: true, get: function () { return run_trees_js_1.RunTree; } });
|
|
8
8
|
// Update using yarn bump-version
|
|
9
|
-
exports.__version__ = "0.1.
|
|
9
|
+
exports.__version__ = "0.1.6";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { Client } from "./client.js";
|
|
2
2
|
export type { Dataset, Example, TracerSession, Run, Feedback, } from "./schemas.js";
|
|
3
3
|
export { RunTree, type RunTreeConfig } from "./run_trees.js";
|
|
4
|
-
export declare const __version__ = "0.1.
|
|
4
|
+
export declare const __version__ = "0.1.6";
|
package/dist/index.js
CHANGED
|
@@ -52,13 +52,21 @@ class AsyncCaller {
|
|
|
52
52
|
writable: true,
|
|
53
53
|
value: void 0
|
|
54
54
|
});
|
|
55
|
+
Object.defineProperty(this, "onFailedResponseHook", {
|
|
56
|
+
enumerable: true,
|
|
57
|
+
configurable: true,
|
|
58
|
+
writable: true,
|
|
59
|
+
value: void 0
|
|
60
|
+
});
|
|
55
61
|
this.maxConcurrency = params.maxConcurrency ?? Infinity;
|
|
56
62
|
this.maxRetries = params.maxRetries ?? 6;
|
|
57
63
|
const PQueue = "default" in p_queue_1.default ? p_queue_1.default.default : p_queue_1.default;
|
|
58
64
|
this.queue = new PQueue({ concurrency: this.maxConcurrency });
|
|
65
|
+
this.onFailedResponseHook = params?.onFailedResponseHook;
|
|
59
66
|
}
|
|
60
67
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
68
|
call(callable, ...args) {
|
|
69
|
+
const onFailedResponseHook = this.onFailedResponseHook;
|
|
62
70
|
return this.queue.add(() => (0, p_retry_1.default)(() => callable(...args).catch((error) => {
|
|
63
71
|
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
64
72
|
if (error instanceof Error) {
|
|
@@ -68,7 +76,7 @@ class AsyncCaller {
|
|
|
68
76
|
throw new Error(error);
|
|
69
77
|
}
|
|
70
78
|
}), {
|
|
71
|
-
onFailedAttempt(error) {
|
|
79
|
+
async onFailedAttempt(error) {
|
|
72
80
|
if (error.message.startsWith("Cancel") ||
|
|
73
81
|
error.message.startsWith("TimeoutError") ||
|
|
74
82
|
error.message.startsWith("AbortError")) {
|
|
@@ -79,7 +87,8 @@ class AsyncCaller {
|
|
|
79
87
|
throw error;
|
|
80
88
|
}
|
|
81
89
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
-
const
|
|
90
|
+
const response = error?.response;
|
|
91
|
+
const status = response?.status;
|
|
83
92
|
if (status) {
|
|
84
93
|
if (STATUS_NO_RETRY.includes(+status)) {
|
|
85
94
|
throw error;
|
|
@@ -87,6 +96,9 @@ class AsyncCaller {
|
|
|
87
96
|
else if (STATUS_IGNORE.includes(+status)) {
|
|
88
97
|
return;
|
|
89
98
|
}
|
|
99
|
+
if (onFailedResponseHook) {
|
|
100
|
+
await onFailedResponseHook(response);
|
|
101
|
+
}
|
|
90
102
|
}
|
|
91
103
|
},
|
|
92
104
|
// If needed we can change some of the defaults here,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
type ResponseCallback = (response?: Response) => Promise<boolean>;
|
|
1
2
|
export interface AsyncCallerParams {
|
|
2
3
|
/**
|
|
3
4
|
* The maximum number of concurrent calls that can be made.
|
|
@@ -9,6 +10,7 @@ export interface AsyncCallerParams {
|
|
|
9
10
|
* with an exponential backoff between each attempt. Defaults to 6.
|
|
10
11
|
*/
|
|
11
12
|
maxRetries?: number;
|
|
13
|
+
onFailedResponseHook?: ResponseCallback;
|
|
12
14
|
}
|
|
13
15
|
export interface AsyncCallerCallOptions {
|
|
14
16
|
signal?: AbortSignal;
|
|
@@ -30,8 +32,10 @@ export declare class AsyncCaller {
|
|
|
30
32
|
protected maxConcurrency: AsyncCallerParams["maxConcurrency"];
|
|
31
33
|
protected maxRetries: AsyncCallerParams["maxRetries"];
|
|
32
34
|
private queue;
|
|
35
|
+
private onFailedResponseHook?;
|
|
33
36
|
constructor(params: AsyncCallerParams);
|
|
34
37
|
call<A extends any[], T extends (...args: A) => Promise<any>>(callable: T, ...args: Parameters<T>): Promise<Awaited<ReturnType<T>>>;
|
|
35
38
|
callWithOptions<A extends any[], T extends (...args: A) => Promise<any>>(options: AsyncCallerCallOptions, callable: T, ...args: Parameters<T>): Promise<Awaited<ReturnType<T>>>;
|
|
36
39
|
fetch(...args: Parameters<typeof fetch>): ReturnType<typeof fetch>;
|
|
37
40
|
}
|
|
41
|
+
export {};
|
|
@@ -46,13 +46,21 @@ export class AsyncCaller {
|
|
|
46
46
|
writable: true,
|
|
47
47
|
value: void 0
|
|
48
48
|
});
|
|
49
|
+
Object.defineProperty(this, "onFailedResponseHook", {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
configurable: true,
|
|
52
|
+
writable: true,
|
|
53
|
+
value: void 0
|
|
54
|
+
});
|
|
49
55
|
this.maxConcurrency = params.maxConcurrency ?? Infinity;
|
|
50
56
|
this.maxRetries = params.maxRetries ?? 6;
|
|
51
57
|
const PQueue = "default" in PQueueMod ? PQueueMod.default : PQueueMod;
|
|
52
58
|
this.queue = new PQueue({ concurrency: this.maxConcurrency });
|
|
59
|
+
this.onFailedResponseHook = params?.onFailedResponseHook;
|
|
53
60
|
}
|
|
54
61
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
62
|
call(callable, ...args) {
|
|
63
|
+
const onFailedResponseHook = this.onFailedResponseHook;
|
|
56
64
|
return this.queue.add(() => pRetry(() => callable(...args).catch((error) => {
|
|
57
65
|
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
58
66
|
if (error instanceof Error) {
|
|
@@ -62,7 +70,7 @@ export class AsyncCaller {
|
|
|
62
70
|
throw new Error(error);
|
|
63
71
|
}
|
|
64
72
|
}), {
|
|
65
|
-
onFailedAttempt(error) {
|
|
73
|
+
async onFailedAttempt(error) {
|
|
66
74
|
if (error.message.startsWith("Cancel") ||
|
|
67
75
|
error.message.startsWith("TimeoutError") ||
|
|
68
76
|
error.message.startsWith("AbortError")) {
|
|
@@ -73,7 +81,8 @@ export class AsyncCaller {
|
|
|
73
81
|
throw error;
|
|
74
82
|
}
|
|
75
83
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
|
-
const
|
|
84
|
+
const response = error?.response;
|
|
85
|
+
const status = response?.status;
|
|
77
86
|
if (status) {
|
|
78
87
|
if (STATUS_NO_RETRY.includes(+status)) {
|
|
79
88
|
throw error;
|
|
@@ -81,6 +90,9 @@ export class AsyncCaller {
|
|
|
81
90
|
else if (STATUS_IGNORE.includes(+status)) {
|
|
82
91
|
return;
|
|
83
92
|
}
|
|
93
|
+
if (onFailedResponseHook) {
|
|
94
|
+
await onFailedResponseHook(response);
|
|
95
|
+
}
|
|
84
96
|
}
|
|
85
97
|
},
|
|
86
98
|
// If needed we can change some of the defaults here,
|