langsmith 0.3.80 → 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.
- package/README.md +2 -1
- package/dist/evaluation/evaluate_comparative.cjs +2 -2
- package/dist/evaluation/evaluate_comparative.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/run_trees.cjs +212 -17
- package/dist/run_trees.d.ts +5 -0
- package/dist/run_trees.js +214 -19
- package/dist/singletons/constants.cjs +2 -1
- package/dist/singletons/constants.d.ts +1 -0
- package/dist/singletons/constants.js +1 -0
- package/dist/utils/async_caller.cjs +5 -3
- package/dist/utils/async_caller.js +4 -2
- package/dist/utils/context_vars.cjs +31 -0
- package/dist/utils/context_vars.d.ts +8 -0
- package/dist/utils/context_vars.js +27 -0
- package/dist/utils/is-network-error/index.cjs +42 -0
- package/dist/utils/is-network-error/index.d.ts +1 -0
- package/dist/utils/is-network-error/index.js +39 -0
- package/dist/utils/jestlike/reporter.d.ts +1 -1
- package/dist/utils/p-retry/index.cjs +200 -0
- package/dist/utils/p-retry/index.d.ts +5 -0
- package/dist/utils/p-retry/index.js +191 -0
- package/dist/vitest/reporter.cjs +6 -0
- package/dist/vitest/reporter.d.mts +6 -0
- package/dist/vitest/reporter.d.ts +2 -0
- package/dist/vitest/reporter.js +7 -1
- package/dist/vitest/reporter.mjs +20 -1
- package/dist/vitest/utils/reporter.cjs +14 -1
- package/dist/vitest/utils/reporter.d.ts +30 -0
- package/dist/vitest/utils/reporter.js +12 -0
- package/package.json +1 -2
|
@@ -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,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
|
+
}
|
package/dist/vitest/reporter.cjs
CHANGED
|
@@ -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;
|
package/dist/vitest/reporter.js
CHANGED
|
@@ -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;
|
package/dist/vitest/reporter.mjs
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
/* eslint-disable import/no-extraneous-dependencies */
|
|
2
|
-
import { printVitestReporterTable } from "./utils/reporter.js";
|
|
2
|
+
import { printVitestReporterTable, printVitestTestModulesReporterTable, } from "./utils/reporter.js";
|
|
3
3
|
import { importVitestModule } from "./utils/esm.mjs";
|
|
4
4
|
const vitestReporters = await importVitestModule("reporters");
|
|
5
5
|
const DefaultReporter = vitestReporters.DefaultReporter;
|
|
6
6
|
class LangSmithEvalReporter extends DefaultReporter {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
Object.defineProperty(this, "skipOnFinished", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true,
|
|
13
|
+
value: false
|
|
14
|
+
});
|
|
15
|
+
}
|
|
7
16
|
async onFinished(files, errors) {
|
|
8
17
|
super.onFinished(files, errors);
|
|
18
|
+
// Vitest 3.x will call `onFinished` after `onTestRunEnd`,
|
|
19
|
+
// thus we need to gate this to avoid double printing.
|
|
20
|
+
if (this.skipOnFinished)
|
|
21
|
+
return;
|
|
9
22
|
await printVitestReporterTable(files, this.ctx);
|
|
10
23
|
}
|
|
24
|
+
// `onFinished` is removed in Vitest 4.x, so we use `onTestRunEnd` instead.
|
|
25
|
+
async onTestRunEnd(testModules, unhandledErrors, reason) {
|
|
26
|
+
super.onTestRunEnd(testModules, unhandledErrors, reason);
|
|
27
|
+
this.skipOnFinished = true;
|
|
28
|
+
await printVitestTestModulesReporterTable(testModules);
|
|
29
|
+
}
|
|
11
30
|
}
|
|
12
31
|
export default LangSmithEvalReporter;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.printVitestReporterTable = void 0;
|
|
3
|
+
exports.printVitestTestModulesReporterTable = exports.printVitestReporterTable = void 0;
|
|
4
4
|
const reporter_js_1 = require("../../utils/jestlike/reporter.cjs");
|
|
5
5
|
// Can't use types here because of module resolution issues
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -23,3 +23,16 @@ const printVitestReporterTable = async (files, ctx) => {
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
exports.printVitestReporterTable = printVitestReporterTable;
|
|
26
|
+
const printVitestTestModulesReporterTable = async (testModules) => {
|
|
27
|
+
for (const testModule of testModules) {
|
|
28
|
+
const tests = [...testModule.children.allTests()].map((test) => {
|
|
29
|
+
return {
|
|
30
|
+
title: test.name,
|
|
31
|
+
status: test.result()?.state ?? "skipped",
|
|
32
|
+
duration: Math.round(test.diagnostic()?.duration ?? 0),
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
await (0, reporter_js_1.printReporterTable)(testModule.relativeModuleId, tests, testModule.state());
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
exports.printVitestTestModulesReporterTable = printVitestTestModulesReporterTable;
|
|
@@ -1 +1,31 @@
|
|
|
1
1
|
export declare const printVitestReporterTable: (files: any, ctx: any) => Promise<void>;
|
|
2
|
+
export interface VitestTestModule {
|
|
3
|
+
children: {
|
|
4
|
+
allTests: () => {
|
|
5
|
+
name: string;
|
|
6
|
+
result: () => {
|
|
7
|
+
state: "pending" | "passed" | "failed" | "skipped";
|
|
8
|
+
};
|
|
9
|
+
diagnostic: () => {
|
|
10
|
+
duration: number;
|
|
11
|
+
};
|
|
12
|
+
}[];
|
|
13
|
+
};
|
|
14
|
+
state: () => "skipped" | "passed" | "failed";
|
|
15
|
+
relativeModuleId: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const printVitestTestModulesReporterTable: (testModules: {
|
|
18
|
+
children: {
|
|
19
|
+
allTests: () => {
|
|
20
|
+
name: string;
|
|
21
|
+
result: () => {
|
|
22
|
+
state: "pending" | "passed" | "failed" | "skipped";
|
|
23
|
+
};
|
|
24
|
+
diagnostic: () => {
|
|
25
|
+
duration: number;
|
|
26
|
+
};
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
state: () => "skipped" | "passed" | "failed";
|
|
30
|
+
relativeModuleId: string;
|
|
31
|
+
}[]) => Promise<void>;
|
|
@@ -19,3 +19,15 @@ export const printVitestReporterTable = async (files, ctx) => {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
+
export const printVitestTestModulesReporterTable = async (testModules) => {
|
|
23
|
+
for (const testModule of testModules) {
|
|
24
|
+
const tests = [...testModule.children.allTests()].map((test) => {
|
|
25
|
+
return {
|
|
26
|
+
title: test.name,
|
|
27
|
+
status: test.result()?.state ?? "skipped",
|
|
28
|
+
duration: Math.round(test.diagnostic()?.duration ?? 0),
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
await printReporterTable(testModule.relativeModuleId, tests, testModule.state());
|
|
32
|
+
}
|
|
33
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.82",
|
|
4
4
|
"description": "Client library to connect to the LangSmith Observability and Evaluation Platform.",
|
|
5
5
|
"packageManager": "yarn@1.22.19",
|
|
6
6
|
"files": [
|
|
@@ -144,7 +144,6 @@
|
|
|
144
144
|
"chalk": "^4.1.2",
|
|
145
145
|
"console-table-printer": "^2.12.1",
|
|
146
146
|
"p-queue": "^6.6.2",
|
|
147
|
-
"p-retry": "4",
|
|
148
147
|
"semver": "^7.6.3",
|
|
149
148
|
"uuid": "^10.0.0"
|
|
150
149
|
},
|