langsmith 0.3.81 → 0.3.82

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.
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.AsyncCaller = void 0;
7
- const p_retry_1 = __importDefault(require("p-retry"));
7
+ const index_js_1 = __importDefault(require("../utils/p-retry/index.cjs"));
8
8
  const p_queue_1 = __importDefault(require("p-queue"));
9
9
  const STATUS_RETRYABLE = [
10
10
  408, // Request Timeout
@@ -100,7 +100,7 @@ class AsyncCaller {
100
100
  this.queueSizeBytes += sizeBytes;
101
101
  }
102
102
  const onFailedResponseHook = this.onFailedResponseHook;
103
- let promise = this.queue.add(() => (0, p_retry_1.default)(() => callable(...args).catch((error) => {
103
+ let promise = this.queue.add(() => (0, index_js_1.default)(() => callable(...args).catch((error) => {
104
104
  // eslint-disable-next-line no-instanceof/no-instanceof
105
105
  if (error instanceof Error) {
106
106
  throw error;
@@ -110,7 +110,7 @@ class AsyncCaller {
110
110
  }
111
111
  }), {
112
112
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
- async onFailedAttempt(error) {
113
+ async onFailedAttempt({ error }) {
114
114
  if (error.message.startsWith("Cancel") ||
115
115
  error.message.startsWith("TimeoutError") ||
116
116
  error.name === "TimeoutError" ||
@@ -1,4 +1,4 @@
1
- import pRetry from "p-retry";
1
+ import pRetry from "../utils/p-retry/index.js";
2
2
  import PQueueMod from "p-queue";
3
3
  const STATUS_RETRYABLE = [
4
4
  408, // Request Timeout
@@ -104,7 +104,7 @@ export class AsyncCaller {
104
104
  }
105
105
  }), {
106
106
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
107
- async onFailedAttempt(error) {
107
+ async onFailedAttempt({ error }) {
108
108
  if (error.message.startsWith("Cancel") ||
109
109
  error.message.startsWith("TimeoutError") ||
110
110
  error.name === "TimeoutError" ||
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getContextVar = getContextVar;
4
+ exports.setContextVar = setContextVar;
5
+ const constants_js_1 = require("../singletons/constants.cjs");
6
+ /**
7
+ * Get a context variable from a run tree instance
8
+ */
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ function getContextVar(runTree, key) {
11
+ if (constants_js_1._LC_CONTEXT_VARIABLES_KEY in runTree) {
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ const contextVars = runTree[constants_js_1._LC_CONTEXT_VARIABLES_KEY];
14
+ return contextVars[key];
15
+ }
16
+ return undefined;
17
+ }
18
+ /**
19
+ * Set a context variable on a run tree instance
20
+ */
21
+ function setContextVar(
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ runTree, key, value) {
24
+ const contextVars = constants_js_1._LC_CONTEXT_VARIABLES_KEY in runTree
25
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ runTree[constants_js_1._LC_CONTEXT_VARIABLES_KEY]
27
+ : {};
28
+ contextVars[key] = value;
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ runTree[constants_js_1._LC_CONTEXT_VARIABLES_KEY] = contextVars;
31
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Get a context variable from a run tree instance
3
+ */
4
+ export declare function getContextVar(runTree: any, key: symbol): unknown;
5
+ /**
6
+ * Set a context variable on a run tree instance
7
+ */
8
+ export declare function setContextVar(runTree: any, key: symbol, value: unknown): void;
@@ -0,0 +1,27 @@
1
+ import { _LC_CONTEXT_VARIABLES_KEY } from "../singletons/constants.js";
2
+ /**
3
+ * Get a context variable from a run tree instance
4
+ */
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ export function getContextVar(runTree, key) {
7
+ if (_LC_CONTEXT_VARIABLES_KEY in runTree) {
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ const contextVars = runTree[_LC_CONTEXT_VARIABLES_KEY];
10
+ return contextVars[key];
11
+ }
12
+ return undefined;
13
+ }
14
+ /**
15
+ * Set a context variable on a run tree instance
16
+ */
17
+ export function setContextVar(
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ runTree, key, value) {
20
+ const contextVars = _LC_CONTEXT_VARIABLES_KEY in runTree
21
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ runTree[_LC_CONTEXT_VARIABLES_KEY]
23
+ : {};
24
+ contextVars[key] = value;
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ runTree[_LC_CONTEXT_VARIABLES_KEY] = contextVars;
27
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = isNetworkError;
4
+ /* eslint-disable */
5
+ // @ts-nocheck
6
+ // is-network-error vendored to avoid import issues
7
+ // Source: https://github.com/sindresorhus/is-network-error
8
+ const objectToString = Object.prototype.toString;
9
+ const isError = (value) => objectToString.call(value) === "[object Error]";
10
+ const errorMessages = new Set([
11
+ "network error", // Chrome
12
+ "Failed to fetch", // Chrome
13
+ "NetworkError when attempting to fetch resource.", // Firefox
14
+ "The Internet connection appears to be offline.", // Safari 16
15
+ "Network request failed", // `cross-fetch`
16
+ "fetch failed", // Undici (Node.js)
17
+ "terminated", // Undici (Node.js)
18
+ " A network error occurred.", // Bun (WebKit)
19
+ "Network connection lost", // Cloudflare Workers (fetch)
20
+ ]);
21
+ function isNetworkError(error) {
22
+ const isValid = error &&
23
+ isError(error) &&
24
+ error.name === "TypeError" &&
25
+ typeof error.message === "string";
26
+ if (!isValid) {
27
+ return false;
28
+ }
29
+ const { message, stack } = error;
30
+ // Safari 17+ has generic message but no stack for network errors
31
+ if (message === "Load failed") {
32
+ return (stack === undefined ||
33
+ // Sentry adds its own stack trace to the fetch error, so also check for that
34
+ "__sentry_captured__" in error);
35
+ }
36
+ // Deno network errors start with specific text
37
+ if (message.startsWith("error sending request for url")) {
38
+ return true;
39
+ }
40
+ // Standard network error messages
41
+ return errorMessages.has(message);
42
+ }
@@ -0,0 +1 @@
1
+ export default function isNetworkError(error: any): boolean;
@@ -0,0 +1,39 @@
1
+ /* eslint-disable */
2
+ // @ts-nocheck
3
+ // is-network-error vendored to avoid import issues
4
+ // Source: https://github.com/sindresorhus/is-network-error
5
+ const objectToString = Object.prototype.toString;
6
+ const isError = (value) => objectToString.call(value) === "[object Error]";
7
+ const errorMessages = new Set([
8
+ "network error", // Chrome
9
+ "Failed to fetch", // Chrome
10
+ "NetworkError when attempting to fetch resource.", // Firefox
11
+ "The Internet connection appears to be offline.", // Safari 16
12
+ "Network request failed", // `cross-fetch`
13
+ "fetch failed", // Undici (Node.js)
14
+ "terminated", // Undici (Node.js)
15
+ " A network error occurred.", // Bun (WebKit)
16
+ "Network connection lost", // Cloudflare Workers (fetch)
17
+ ]);
18
+ export default function isNetworkError(error) {
19
+ const isValid = error &&
20
+ isError(error) &&
21
+ error.name === "TypeError" &&
22
+ typeof error.message === "string";
23
+ if (!isValid) {
24
+ return false;
25
+ }
26
+ const { message, stack } = error;
27
+ // Safari 17+ has generic message but no stack for network errors
28
+ if (message === "Load failed") {
29
+ return (stack === undefined ||
30
+ // Sentry adds its own stack trace to the fetch error, so also check for that
31
+ "__sentry_captured__" in error);
32
+ }
33
+ // Deno network errors start with specific text
34
+ if (message.startsWith("error sending request for url")) {
35
+ return true;
36
+ }
37
+ // Standard network error messages
38
+ return errorMessages.has(message);
39
+ }
@@ -2,4 +2,4 @@ export declare function printReporterTable(testSuiteName: string, results: {
2
2
  title: string;
3
3
  duration: number;
4
4
  status: "pass" | "passed" | "fail" | "failed" | "pending" | "skipped";
5
- }[], testStatus: "pass" | "skip" | "fail", failureMessage?: string): Promise<void>;
5
+ }[], testStatus: "pass" | "skip" | "fail" | "passed" | "failed" | "skipped", failureMessage?: string): Promise<void>;
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AbortError = void 0;
7
+ exports.default = pRetry;
8
+ exports.makeRetriable = makeRetriable;
9
+ /* eslint-disable */
10
+ // @ts-nocheck
11
+ // p-retry code vendored to avoid import issues
12
+ // Source: https://github.com/sindresorhus/p-retry
13
+ const index_js_1 = __importDefault(require("../is-network-error/index.cjs"));
14
+ function validateRetries(retries) {
15
+ if (typeof retries === "number") {
16
+ if (retries < 0) {
17
+ throw new TypeError("Expected `retries` to be a non-negative number.");
18
+ }
19
+ if (Number.isNaN(retries)) {
20
+ throw new TypeError("Expected `retries` to be a valid number or Infinity, got NaN.");
21
+ }
22
+ }
23
+ else if (retries !== undefined) {
24
+ throw new TypeError("Expected `retries` to be a number or Infinity.");
25
+ }
26
+ }
27
+ function validateNumberOption(name, value, { min = 0, allowInfinity = false } = {}) {
28
+ if (value === undefined) {
29
+ return;
30
+ }
31
+ if (typeof value !== "number" || Number.isNaN(value)) {
32
+ throw new TypeError(`Expected \`${name}\` to be a number${allowInfinity ? " or Infinity" : ""}.`);
33
+ }
34
+ if (!allowInfinity && !Number.isFinite(value)) {
35
+ throw new TypeError(`Expected \`${name}\` to be a finite number.`);
36
+ }
37
+ if (value < min) {
38
+ throw new TypeError(`Expected \`${name}\` to be \u2265 ${min}.`);
39
+ }
40
+ }
41
+ class AbortError extends Error {
42
+ constructor(message) {
43
+ super();
44
+ if (message instanceof Error) {
45
+ this.originalError = message;
46
+ ({ message } = message);
47
+ }
48
+ else {
49
+ this.originalError = new Error(message);
50
+ this.originalError.stack = this.stack;
51
+ }
52
+ this.name = "AbortError";
53
+ this.message = message;
54
+ }
55
+ }
56
+ exports.AbortError = AbortError;
57
+ function calculateDelay(retriesConsumed, options) {
58
+ const attempt = Math.max(1, retriesConsumed + 1);
59
+ const random = options.randomize ? Math.random() + 1 : 1;
60
+ let timeout = Math.round(random * options.minTimeout * options.factor ** (attempt - 1));
61
+ timeout = Math.min(timeout, options.maxTimeout);
62
+ return timeout;
63
+ }
64
+ function calculateRemainingTime(start, max) {
65
+ if (!Number.isFinite(max)) {
66
+ return max;
67
+ }
68
+ return max - (performance.now() - start);
69
+ }
70
+ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTime, options, }) {
71
+ const normalizedError = error instanceof Error
72
+ ? error
73
+ : new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`);
74
+ if (normalizedError instanceof AbortError) {
75
+ throw normalizedError.originalError;
76
+ }
77
+ const retriesLeft = Number.isFinite(options.retries)
78
+ ? Math.max(0, options.retries - retriesConsumed)
79
+ : options.retries;
80
+ const maxRetryTime = options.maxRetryTime ?? Number.POSITIVE_INFINITY;
81
+ const context = Object.freeze({
82
+ error: normalizedError,
83
+ attemptNumber,
84
+ retriesLeft,
85
+ retriesConsumed,
86
+ });
87
+ await options.onFailedAttempt(context);
88
+ if (calculateRemainingTime(startTime, maxRetryTime) <= 0) {
89
+ throw normalizedError;
90
+ }
91
+ const consumeRetry = await options.shouldConsumeRetry(context);
92
+ const remainingTime = calculateRemainingTime(startTime, maxRetryTime);
93
+ if (remainingTime <= 0 || retriesLeft <= 0) {
94
+ throw normalizedError;
95
+ }
96
+ if (normalizedError instanceof TypeError &&
97
+ !(0, index_js_1.default)(normalizedError)) {
98
+ if (consumeRetry) {
99
+ throw normalizedError;
100
+ }
101
+ options.signal?.throwIfAborted();
102
+ return false;
103
+ }
104
+ if (!(await options.shouldRetry(context))) {
105
+ throw normalizedError;
106
+ }
107
+ if (!consumeRetry) {
108
+ options.signal?.throwIfAborted();
109
+ return false;
110
+ }
111
+ const delayTime = calculateDelay(retriesConsumed, options);
112
+ const finalDelay = Math.min(delayTime, remainingTime);
113
+ if (finalDelay > 0) {
114
+ await new Promise((resolve, reject) => {
115
+ const onAbort = () => {
116
+ clearTimeout(timeoutToken);
117
+ options.signal?.removeEventListener("abort", onAbort);
118
+ reject(options.signal.reason);
119
+ };
120
+ const timeoutToken = setTimeout(() => {
121
+ options.signal?.removeEventListener("abort", onAbort);
122
+ resolve();
123
+ }, finalDelay);
124
+ if (options.unref) {
125
+ timeoutToken.unref?.();
126
+ }
127
+ options.signal?.addEventListener("abort", onAbort, { once: true });
128
+ });
129
+ }
130
+ options.signal?.throwIfAborted();
131
+ return true;
132
+ }
133
+ async function pRetry(input, options = {}) {
134
+ options = { ...options };
135
+ validateRetries(options.retries);
136
+ if (Object.hasOwn(options, "forever")) {
137
+ throw new Error("The `forever` option is no longer supported. For many use-cases, you can set `retries: Infinity` instead.");
138
+ }
139
+ options.retries ??= 10;
140
+ options.factor ??= 2;
141
+ options.minTimeout ??= 1000;
142
+ options.maxTimeout ??= Number.POSITIVE_INFINITY;
143
+ options.maxRetryTime ??= Number.POSITIVE_INFINITY;
144
+ options.randomize ??= false;
145
+ options.onFailedAttempt ??= () => { };
146
+ options.shouldRetry ??= () => true;
147
+ options.shouldConsumeRetry ??= () => true;
148
+ // Validate numeric options and normalize edge cases
149
+ validateNumberOption("factor", options.factor, {
150
+ min: 0,
151
+ allowInfinity: false,
152
+ });
153
+ validateNumberOption("minTimeout", options.minTimeout, {
154
+ min: 0,
155
+ allowInfinity: false,
156
+ });
157
+ validateNumberOption("maxTimeout", options.maxTimeout, {
158
+ min: 0,
159
+ allowInfinity: true,
160
+ });
161
+ validateNumberOption("maxRetryTime", options.maxRetryTime, {
162
+ min: 0,
163
+ allowInfinity: true,
164
+ });
165
+ // Treat non-positive factor as 1 to avoid zero backoff or negative behavior
166
+ if (!(options.factor > 0)) {
167
+ options.factor = 1;
168
+ }
169
+ options.signal?.throwIfAborted();
170
+ let attemptNumber = 0;
171
+ let retriesConsumed = 0;
172
+ const startTime = performance.now();
173
+ while (Number.isFinite(options.retries) ? retriesConsumed <= options.retries : true) {
174
+ attemptNumber++;
175
+ try {
176
+ options.signal?.throwIfAborted();
177
+ const result = await input(attemptNumber);
178
+ options.signal?.throwIfAborted();
179
+ return result;
180
+ }
181
+ catch (error) {
182
+ if (await onAttemptFailure({
183
+ error,
184
+ attemptNumber,
185
+ retriesConsumed,
186
+ startTime,
187
+ options,
188
+ })) {
189
+ retriesConsumed++;
190
+ }
191
+ }
192
+ }
193
+ // Should not reach here, but in case it does, throw an error
194
+ throw new Error("Retry attempts exhausted without throwing an error.");
195
+ }
196
+ function makeRetriable(function_, options) {
197
+ return function (...arguments_) {
198
+ return pRetry(() => function_.apply(this, arguments_), options);
199
+ };
200
+ }
@@ -0,0 +1,5 @@
1
+ export declare class AbortError extends Error {
2
+ constructor(message: any);
3
+ }
4
+ export default function pRetry(input: any, options?: {}): Promise<any>;
5
+ export declare function makeRetriable(function_: any, options: any): (...arguments_: any[]) => Promise<any>;
@@ -0,0 +1,191 @@
1
+ /* eslint-disable */
2
+ // @ts-nocheck
3
+ // p-retry code vendored to avoid import issues
4
+ // Source: https://github.com/sindresorhus/p-retry
5
+ import isNetworkError from "../is-network-error/index.js";
6
+ function validateRetries(retries) {
7
+ if (typeof retries === "number") {
8
+ if (retries < 0) {
9
+ throw new TypeError("Expected `retries` to be a non-negative number.");
10
+ }
11
+ if (Number.isNaN(retries)) {
12
+ throw new TypeError("Expected `retries` to be a valid number or Infinity, got NaN.");
13
+ }
14
+ }
15
+ else if (retries !== undefined) {
16
+ throw new TypeError("Expected `retries` to be a number or Infinity.");
17
+ }
18
+ }
19
+ function validateNumberOption(name, value, { min = 0, allowInfinity = false } = {}) {
20
+ if (value === undefined) {
21
+ return;
22
+ }
23
+ if (typeof value !== "number" || Number.isNaN(value)) {
24
+ throw new TypeError(`Expected \`${name}\` to be a number${allowInfinity ? " or Infinity" : ""}.`);
25
+ }
26
+ if (!allowInfinity && !Number.isFinite(value)) {
27
+ throw new TypeError(`Expected \`${name}\` to be a finite number.`);
28
+ }
29
+ if (value < min) {
30
+ throw new TypeError(`Expected \`${name}\` to be \u2265 ${min}.`);
31
+ }
32
+ }
33
+ export class AbortError extends Error {
34
+ constructor(message) {
35
+ super();
36
+ if (message instanceof Error) {
37
+ this.originalError = message;
38
+ ({ message } = message);
39
+ }
40
+ else {
41
+ this.originalError = new Error(message);
42
+ this.originalError.stack = this.stack;
43
+ }
44
+ this.name = "AbortError";
45
+ this.message = message;
46
+ }
47
+ }
48
+ function calculateDelay(retriesConsumed, options) {
49
+ const attempt = Math.max(1, retriesConsumed + 1);
50
+ const random = options.randomize ? Math.random() + 1 : 1;
51
+ let timeout = Math.round(random * options.minTimeout * options.factor ** (attempt - 1));
52
+ timeout = Math.min(timeout, options.maxTimeout);
53
+ return timeout;
54
+ }
55
+ function calculateRemainingTime(start, max) {
56
+ if (!Number.isFinite(max)) {
57
+ return max;
58
+ }
59
+ return max - (performance.now() - start);
60
+ }
61
+ async function onAttemptFailure({ error, attemptNumber, retriesConsumed, startTime, options, }) {
62
+ const normalizedError = error instanceof Error
63
+ ? error
64
+ : new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`);
65
+ if (normalizedError instanceof AbortError) {
66
+ throw normalizedError.originalError;
67
+ }
68
+ const retriesLeft = Number.isFinite(options.retries)
69
+ ? Math.max(0, options.retries - retriesConsumed)
70
+ : options.retries;
71
+ const maxRetryTime = options.maxRetryTime ?? Number.POSITIVE_INFINITY;
72
+ const context = Object.freeze({
73
+ error: normalizedError,
74
+ attemptNumber,
75
+ retriesLeft,
76
+ retriesConsumed,
77
+ });
78
+ await options.onFailedAttempt(context);
79
+ if (calculateRemainingTime(startTime, maxRetryTime) <= 0) {
80
+ throw normalizedError;
81
+ }
82
+ const consumeRetry = await options.shouldConsumeRetry(context);
83
+ const remainingTime = calculateRemainingTime(startTime, maxRetryTime);
84
+ if (remainingTime <= 0 || retriesLeft <= 0) {
85
+ throw normalizedError;
86
+ }
87
+ if (normalizedError instanceof TypeError &&
88
+ !isNetworkError(normalizedError)) {
89
+ if (consumeRetry) {
90
+ throw normalizedError;
91
+ }
92
+ options.signal?.throwIfAborted();
93
+ return false;
94
+ }
95
+ if (!(await options.shouldRetry(context))) {
96
+ throw normalizedError;
97
+ }
98
+ if (!consumeRetry) {
99
+ options.signal?.throwIfAborted();
100
+ return false;
101
+ }
102
+ const delayTime = calculateDelay(retriesConsumed, options);
103
+ const finalDelay = Math.min(delayTime, remainingTime);
104
+ if (finalDelay > 0) {
105
+ await new Promise((resolve, reject) => {
106
+ const onAbort = () => {
107
+ clearTimeout(timeoutToken);
108
+ options.signal?.removeEventListener("abort", onAbort);
109
+ reject(options.signal.reason);
110
+ };
111
+ const timeoutToken = setTimeout(() => {
112
+ options.signal?.removeEventListener("abort", onAbort);
113
+ resolve();
114
+ }, finalDelay);
115
+ if (options.unref) {
116
+ timeoutToken.unref?.();
117
+ }
118
+ options.signal?.addEventListener("abort", onAbort, { once: true });
119
+ });
120
+ }
121
+ options.signal?.throwIfAborted();
122
+ return true;
123
+ }
124
+ export default async function pRetry(input, options = {}) {
125
+ options = { ...options };
126
+ validateRetries(options.retries);
127
+ if (Object.hasOwn(options, "forever")) {
128
+ throw new Error("The `forever` option is no longer supported. For many use-cases, you can set `retries: Infinity` instead.");
129
+ }
130
+ options.retries ??= 10;
131
+ options.factor ??= 2;
132
+ options.minTimeout ??= 1000;
133
+ options.maxTimeout ??= Number.POSITIVE_INFINITY;
134
+ options.maxRetryTime ??= Number.POSITIVE_INFINITY;
135
+ options.randomize ??= false;
136
+ options.onFailedAttempt ??= () => { };
137
+ options.shouldRetry ??= () => true;
138
+ options.shouldConsumeRetry ??= () => true;
139
+ // Validate numeric options and normalize edge cases
140
+ validateNumberOption("factor", options.factor, {
141
+ min: 0,
142
+ allowInfinity: false,
143
+ });
144
+ validateNumberOption("minTimeout", options.minTimeout, {
145
+ min: 0,
146
+ allowInfinity: false,
147
+ });
148
+ validateNumberOption("maxTimeout", options.maxTimeout, {
149
+ min: 0,
150
+ allowInfinity: true,
151
+ });
152
+ validateNumberOption("maxRetryTime", options.maxRetryTime, {
153
+ min: 0,
154
+ allowInfinity: true,
155
+ });
156
+ // Treat non-positive factor as 1 to avoid zero backoff or negative behavior
157
+ if (!(options.factor > 0)) {
158
+ options.factor = 1;
159
+ }
160
+ options.signal?.throwIfAborted();
161
+ let attemptNumber = 0;
162
+ let retriesConsumed = 0;
163
+ const startTime = performance.now();
164
+ while (Number.isFinite(options.retries) ? retriesConsumed <= options.retries : true) {
165
+ attemptNumber++;
166
+ try {
167
+ options.signal?.throwIfAborted();
168
+ const result = await input(attemptNumber);
169
+ options.signal?.throwIfAborted();
170
+ return result;
171
+ }
172
+ catch (error) {
173
+ if (await onAttemptFailure({
174
+ error,
175
+ attemptNumber,
176
+ retriesConsumed,
177
+ startTime,
178
+ options,
179
+ })) {
180
+ retriesConsumed++;
181
+ }
182
+ }
183
+ }
184
+ // Should not reach here, but in case it does, throw an error
185
+ throw new Error("Retry attempts exhausted without throwing an error.");
186
+ }
187
+ export function makeRetriable(function_, options) {
188
+ return function (...arguments_) {
189
+ return pRetry(() => function_.apply(this, arguments_), options);
190
+ };
191
+ }
@@ -10,5 +10,11 @@ class LangSmithEvalReporter extends reporters_1.DefaultReporter {
10
10
  super.onFinished(files, errors);
11
11
  await (0, reporter_js_1.printVitestReporterTable)(files, this.ctx);
12
12
  }
13
+ // @ts-expect-error Vitest 4.x introduces a new `onTestRunEnd` method
14
+ async onTestRunEnd(testModules, unhandledErrors, reason) {
15
+ // @ts-expect-error Vitest 4.x introduces a new `onTestRunEnd` method
16
+ super.onTestRunEnd(testModules, unhandledErrors, reason);
17
+ await (0, reporter_js_1.printVitestTestModulesReporterTable)(testModules);
18
+ }
13
19
  }
14
20
  exports.default = LangSmithEvalReporter;
@@ -1,5 +1,11 @@
1
+ import { type VitestTestModule } from "./utils/reporter.js";
1
2
  declare const DefaultReporter: any;
2
3
  declare class LangSmithEvalReporter extends DefaultReporter {
4
+ private skipOnFinished;
3
5
  onFinished(files: unknown[], errors: unknown[]): Promise<void>;
6
+ onTestRunEnd(testModules: VitestTestModule[], unhandledErrors: {
7
+ message: string;
8
+ name?: string;
9
+ }[], reason: "passed" | "interrupted" | "failed"): Promise<void>;
4
10
  }
5
11
  export default LangSmithEvalReporter;
@@ -1,6 +1,8 @@
1
1
  import { DefaultReporter } from "vitest/reporters";
2
2
  import { RunnerTestFile } from "vitest";
3
+ import { type VitestTestModule } from "./utils/reporter.js";
3
4
  declare class LangSmithEvalReporter extends DefaultReporter {
4
5
  onFinished(files: RunnerTestFile[], errors: unknown[]): Promise<void>;
6
+ onTestRunEnd(testModules: VitestTestModule[], unhandledErrors: unknown[], reason: "passed" | "interrupted" | "failed"): Promise<void>;
5
7
  }
6
8
  export default LangSmithEvalReporter;
@@ -2,11 +2,17 @@
2
2
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3
3
  // @ts-ignore Import throws an error in internal CJS build, but seems to work fine after build
4
4
  import { DefaultReporter } from "vitest/reporters";
5
- import { printVitestReporterTable } from "./utils/reporter.js";
5
+ import { printVitestReporterTable, printVitestTestModulesReporterTable, } from "./utils/reporter.js";
6
6
  class LangSmithEvalReporter extends DefaultReporter {
7
7
  async onFinished(files, errors) {
8
8
  super.onFinished(files, errors);
9
9
  await printVitestReporterTable(files, this.ctx);
10
10
  }
11
+ // @ts-expect-error Vitest 4.x introduces a new `onTestRunEnd` method
12
+ async onTestRunEnd(testModules, unhandledErrors, reason) {
13
+ // @ts-expect-error Vitest 4.x introduces a new `onTestRunEnd` method
14
+ super.onTestRunEnd(testModules, unhandledErrors, reason);
15
+ await printVitestTestModulesReporterTable(testModules);
16
+ }
11
17
  }
12
18
  export default LangSmithEvalReporter;