@vitest-evals/harness-ai-sdk 0.9.0-beta.0
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/LICENSE +201 -0
- package/README.md +56 -0
- package/dist/index.d.mts +60 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +598 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +588 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +33 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
aiSdkHarness: () => aiSdkHarness
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
var import_harness = require("vitest-evals/harness");
|
|
27
|
+
var import_replay = require("vitest-evals/replay");
|
|
28
|
+
function aiSdkHarness(options) {
|
|
29
|
+
validateOptions(options);
|
|
30
|
+
return {
|
|
31
|
+
name: options.name ?? "ai-sdk",
|
|
32
|
+
prompt: options.prompt,
|
|
33
|
+
run: async (input, context) => {
|
|
34
|
+
const agent = await resolveAgent(options);
|
|
35
|
+
return runAiSdkHarness(options, agent, input, context);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async function runAiSdkHarness(options, agent, input, context) {
|
|
40
|
+
const replayMetadataByToolCallId = /* @__PURE__ */ new Map();
|
|
41
|
+
const runtimeToolCalls = [];
|
|
42
|
+
const tools = createToolset({
|
|
43
|
+
input,
|
|
44
|
+
context,
|
|
45
|
+
tools: options.tools,
|
|
46
|
+
replayMetadataByToolCallId,
|
|
47
|
+
runtimeToolCalls
|
|
48
|
+
});
|
|
49
|
+
const runtime = {
|
|
50
|
+
tools,
|
|
51
|
+
signal: context.signal
|
|
52
|
+
};
|
|
53
|
+
try {
|
|
54
|
+
const result = await runAgent(options, {
|
|
55
|
+
agent,
|
|
56
|
+
input,
|
|
57
|
+
context,
|
|
58
|
+
runtime,
|
|
59
|
+
tools
|
|
60
|
+
});
|
|
61
|
+
if ((0, import_harness.isHarnessRun)(result) && !hasResultOverrides(options)) {
|
|
62
|
+
if (Object.keys(context.artifacts).length > 0 && !result.artifacts) {
|
|
63
|
+
result.artifacts = context.artifacts;
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
const resultArgs = {
|
|
68
|
+
agent,
|
|
69
|
+
input,
|
|
70
|
+
context,
|
|
71
|
+
runtime,
|
|
72
|
+
tools,
|
|
73
|
+
result
|
|
74
|
+
};
|
|
75
|
+
const output = options.output ? await options.output(resultArgs) : resolveOutput(result);
|
|
76
|
+
const usage = options.usage ? await options.usage(resultArgs) : resolveUsage(result, runtimeToolCalls.length);
|
|
77
|
+
const session = options.session ? await options.session(resultArgs) : resolveSession(
|
|
78
|
+
input,
|
|
79
|
+
result,
|
|
80
|
+
output,
|
|
81
|
+
replayMetadataByToolCallId,
|
|
82
|
+
runtimeToolCalls
|
|
83
|
+
);
|
|
84
|
+
return {
|
|
85
|
+
session,
|
|
86
|
+
output,
|
|
87
|
+
usage,
|
|
88
|
+
timings: options.timings ? await options.timings(resultArgs) : void 0,
|
|
89
|
+
artifacts: Object.keys(context.artifacts).length > 0 ? context.artifacts : void 0,
|
|
90
|
+
errors: options.errors ? await options.errors(resultArgs) : (0, import_harness.resolveHarnessRunErrors)(result)
|
|
91
|
+
};
|
|
92
|
+
} catch (error) {
|
|
93
|
+
const run = {
|
|
94
|
+
session: resolveSession(
|
|
95
|
+
input,
|
|
96
|
+
void 0,
|
|
97
|
+
void 0,
|
|
98
|
+
replayMetadataByToolCallId,
|
|
99
|
+
runtimeToolCalls
|
|
100
|
+
),
|
|
101
|
+
output: void 0,
|
|
102
|
+
usage: runtimeToolCalls.length > 0 ? { toolCalls: runtimeToolCalls.length } : {},
|
|
103
|
+
artifacts: Object.keys(context.artifacts).length > 0 ? context.artifacts : void 0,
|
|
104
|
+
errors: [(0, import_harness.serializeError)(error)]
|
|
105
|
+
};
|
|
106
|
+
throw (0, import_harness.attachHarnessRunToError)(error, run);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function hasResultOverrides(options) {
|
|
110
|
+
return Boolean(
|
|
111
|
+
options.output ?? options.session ?? options.usage ?? options.timings ?? options.errors
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
async function resolveAgent(options) {
|
|
115
|
+
return hasAgentSource(options) ? await resolveAgentSource(options.agent) : void 0;
|
|
116
|
+
}
|
|
117
|
+
async function runAgent(options, args) {
|
|
118
|
+
if (options.task) {
|
|
119
|
+
return options.task(args);
|
|
120
|
+
}
|
|
121
|
+
if (hasAiSdkRunMethod(args.agent)) {
|
|
122
|
+
return args.agent.run(args.input, args.runtime);
|
|
123
|
+
}
|
|
124
|
+
if (hasAiSdkGenerateMethod(args.agent)) {
|
|
125
|
+
return args.agent.generate(args.input, args.runtime);
|
|
126
|
+
}
|
|
127
|
+
throw new Error(
|
|
128
|
+
"aiSdkHarness agent must expose run(input, runtime) or generate(input, runtime), or use task() for a custom entrypoint."
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
function validateOptions(options) {
|
|
132
|
+
const hasAgent = hasAgentSource(options);
|
|
133
|
+
const hasTask = typeof options.task === "function";
|
|
134
|
+
if (hasAgent && hasTask) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
"aiSdkHarness accepts either agent or task, not both. Use agent for the zero-glue run(input, runtime) or generate(input, runtime) path, or task for a custom entrypoint."
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (!hasAgent && !hasTask) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
"aiSdkHarness requires either agent or task. Use agent for objects with run(input, runtime) or generate(input, runtime), or task for a custom entrypoint."
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function hasAgentSource(options) {
|
|
146
|
+
return "agent" in options && options.agent !== void 0;
|
|
147
|
+
}
|
|
148
|
+
async function resolveAgentSource(agent) {
|
|
149
|
+
if (isAgentFactory(agent)) {
|
|
150
|
+
return agent();
|
|
151
|
+
}
|
|
152
|
+
return agent;
|
|
153
|
+
}
|
|
154
|
+
function hasAiSdkRunMethod(agent) {
|
|
155
|
+
return (0, import_harness.hasCallableMethod)(agent, "run");
|
|
156
|
+
}
|
|
157
|
+
function hasAiSdkGenerateMethod(agent) {
|
|
158
|
+
return (0, import_harness.hasCallableMethod)(agent, "generate");
|
|
159
|
+
}
|
|
160
|
+
function isAgentFactory(agent) {
|
|
161
|
+
return typeof agent === "function" && !(0, import_harness.hasCallableMethod)(agent, "run") && !(0, import_harness.hasCallableMethod)(agent, "generate");
|
|
162
|
+
}
|
|
163
|
+
function createToolset({
|
|
164
|
+
input,
|
|
165
|
+
context,
|
|
166
|
+
tools,
|
|
167
|
+
replayMetadataByToolCallId,
|
|
168
|
+
runtimeToolCalls
|
|
169
|
+
}) {
|
|
170
|
+
return Object.fromEntries(
|
|
171
|
+
Object.entries(tools ?? {}).map(([toolName, tool]) => {
|
|
172
|
+
if (tool.replay && !tool.execute) {
|
|
173
|
+
throw new Error(
|
|
174
|
+
`Tool replay requires execute() for ${toolName}. Provider-executed tools cannot be recorded automatically.`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
if (!tool.execute) {
|
|
178
|
+
return [toolName, tool];
|
|
179
|
+
}
|
|
180
|
+
const execute = tool.execute;
|
|
181
|
+
const wrappedTool = {
|
|
182
|
+
...tool,
|
|
183
|
+
execute: async (toolInput, execution) => {
|
|
184
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
185
|
+
const normalizedArgs = normalizeArguments(toolInput);
|
|
186
|
+
const replayContext = {
|
|
187
|
+
input,
|
|
188
|
+
metadata: context.metadata,
|
|
189
|
+
signal: context.signal,
|
|
190
|
+
setArtifact: context.setArtifact,
|
|
191
|
+
execution
|
|
192
|
+
};
|
|
193
|
+
try {
|
|
194
|
+
const executionResult = tool.replay ? await executeToolWithReplay({
|
|
195
|
+
toolName,
|
|
196
|
+
toolInput,
|
|
197
|
+
execute,
|
|
198
|
+
execution,
|
|
199
|
+
context: replayContext,
|
|
200
|
+
replay: tool.replay
|
|
201
|
+
}) : {
|
|
202
|
+
result: await execute(toolInput, execution),
|
|
203
|
+
replay: void 0
|
|
204
|
+
};
|
|
205
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
206
|
+
const normalizedResult = (0, import_harness.toJsonValue)(executionResult.result);
|
|
207
|
+
const replayMetadata = (0, import_replay.normalizeReplayMetadata)(
|
|
208
|
+
executionResult.replay
|
|
209
|
+
);
|
|
210
|
+
if (executionResult.replay) {
|
|
211
|
+
replayMetadataByToolCallId.set(
|
|
212
|
+
execution.toolCallId,
|
|
213
|
+
executionResult.replay
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
runtimeToolCalls.push({
|
|
217
|
+
id: execution.toolCallId,
|
|
218
|
+
name: toolName,
|
|
219
|
+
...normalizedArgs ? { arguments: normalizedArgs } : {},
|
|
220
|
+
...normalizedResult !== void 0 ? { result: normalizedResult } : {},
|
|
221
|
+
startedAt: startedAt.toISOString(),
|
|
222
|
+
finishedAt: finishedAt.toISOString(),
|
|
223
|
+
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
224
|
+
...replayMetadata ? { metadata: replayMetadata } : {}
|
|
225
|
+
});
|
|
226
|
+
return executionResult.result;
|
|
227
|
+
} catch (error) {
|
|
228
|
+
const replay = (0, import_replay.getReplayMetadataFromError)(error);
|
|
229
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
230
|
+
const replayMetadata = (0, import_replay.normalizeReplayMetadata)(replay);
|
|
231
|
+
if (replay) {
|
|
232
|
+
replayMetadataByToolCallId.set(execution.toolCallId, replay);
|
|
233
|
+
}
|
|
234
|
+
runtimeToolCalls.push({
|
|
235
|
+
id: execution.toolCallId,
|
|
236
|
+
name: toolName,
|
|
237
|
+
...normalizedArgs ? { arguments: normalizedArgs } : {},
|
|
238
|
+
error: normalizeError(error),
|
|
239
|
+
startedAt: startedAt.toISOString(),
|
|
240
|
+
finishedAt: finishedAt.toISOString(),
|
|
241
|
+
durationMs: finishedAt.getTime() - startedAt.getTime(),
|
|
242
|
+
...replayMetadata ? { metadata: replayMetadata } : {}
|
|
243
|
+
});
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
return [toolName, wrappedTool];
|
|
249
|
+
})
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
async function executeToolWithReplay({
|
|
253
|
+
toolName,
|
|
254
|
+
toolInput,
|
|
255
|
+
execute,
|
|
256
|
+
execution,
|
|
257
|
+
context,
|
|
258
|
+
replay
|
|
259
|
+
}) {
|
|
260
|
+
const replayInput = toReplayJsonValue(
|
|
261
|
+
toolInput,
|
|
262
|
+
`${toolName} tool input`
|
|
263
|
+
);
|
|
264
|
+
return (0, import_replay.executeWithReplay)({
|
|
265
|
+
toolName,
|
|
266
|
+
args: replayInput,
|
|
267
|
+
context,
|
|
268
|
+
execute: async (replayedInput) => {
|
|
269
|
+
const output = await execute(
|
|
270
|
+
replayedInput,
|
|
271
|
+
execution
|
|
272
|
+
);
|
|
273
|
+
if (isAsyncIterable(output)) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
`Tool replay only supports JSON-serializable outputs. ${toolName} returned an async iterable.`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
return toReplayJsonValue(
|
|
279
|
+
output,
|
|
280
|
+
`${toolName} tool output`
|
|
281
|
+
);
|
|
282
|
+
},
|
|
283
|
+
replay
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function resolveOutput(result) {
|
|
287
|
+
if (!result || typeof result !== "object") {
|
|
288
|
+
return (0, import_harness.toJsonValue)(result);
|
|
289
|
+
}
|
|
290
|
+
const candidates = [
|
|
291
|
+
"output",
|
|
292
|
+
"object",
|
|
293
|
+
"experimental_output",
|
|
294
|
+
"result",
|
|
295
|
+
"text"
|
|
296
|
+
];
|
|
297
|
+
for (const key of candidates) {
|
|
298
|
+
const value = result[key];
|
|
299
|
+
const normalized = (0, import_harness.toJsonValue)(value);
|
|
300
|
+
if (normalized !== void 0) {
|
|
301
|
+
return normalized;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return void 0;
|
|
305
|
+
}
|
|
306
|
+
function resolveUsage(result, runtimeToolCallCount = 0) {
|
|
307
|
+
const steps = resolveSteps(result);
|
|
308
|
+
const usage = resolveLanguageModelUsage(result) ?? resolveStepUsage(steps);
|
|
309
|
+
const lastStep = steps.length > 0 ? steps[steps.length - 1] : void 0;
|
|
310
|
+
if (!usage) {
|
|
311
|
+
if (steps.length > 0) {
|
|
312
|
+
const toolCallCount2 = countStepToolCalls(steps);
|
|
313
|
+
return {
|
|
314
|
+
provider: lastStep?.model.provider,
|
|
315
|
+
model: lastStep?.model.modelId,
|
|
316
|
+
...toolCallCount2 > 0 ? { toolCalls: toolCallCount2 } : {}
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
return runtimeToolCallCount > 0 ? { toolCalls: runtimeToolCallCount } : {};
|
|
320
|
+
}
|
|
321
|
+
const stepToolCallCount = countStepToolCalls(steps);
|
|
322
|
+
const toolCallCount = stepToolCallCount > 0 ? stepToolCallCount : runtimeToolCallCount;
|
|
323
|
+
return {
|
|
324
|
+
provider: lastStep?.model.provider,
|
|
325
|
+
model: lastStep?.model.modelId,
|
|
326
|
+
inputTokens: usage.inputTokens,
|
|
327
|
+
outputTokens: usage.outputTokens,
|
|
328
|
+
reasoningTokens: usage.outputTokenDetails?.reasoningTokens ?? usage.reasoningTokens,
|
|
329
|
+
totalTokens: usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0),
|
|
330
|
+
toolCalls: toolCallCount > 0 ? toolCallCount : void 0,
|
|
331
|
+
metadata: (0, import_harness.normalizeMetadata)({
|
|
332
|
+
cacheReadTokens: usage.inputTokenDetails?.cacheReadTokens ?? usage.cachedInputTokens,
|
|
333
|
+
cacheWriteTokens: usage.inputTokenDetails?.cacheWriteTokens,
|
|
334
|
+
raw: usage.raw
|
|
335
|
+
})
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function resolveStepUsage(steps) {
|
|
339
|
+
const usages = steps.map((step) => step.usage).filter((usage) => Boolean(usage));
|
|
340
|
+
if (usages.length === 0) {
|
|
341
|
+
return void 0;
|
|
342
|
+
}
|
|
343
|
+
return usages.reduce(addLanguageModelUsage);
|
|
344
|
+
}
|
|
345
|
+
function addLanguageModelUsage(left, right) {
|
|
346
|
+
return {
|
|
347
|
+
inputTokens: addTokenCounts(left.inputTokens, right.inputTokens),
|
|
348
|
+
inputTokenDetails: {
|
|
349
|
+
noCacheTokens: addTokenCounts(
|
|
350
|
+
left.inputTokenDetails?.noCacheTokens,
|
|
351
|
+
right.inputTokenDetails?.noCacheTokens
|
|
352
|
+
),
|
|
353
|
+
cacheReadTokens: addTokenCounts(
|
|
354
|
+
left.inputTokenDetails?.cacheReadTokens,
|
|
355
|
+
right.inputTokenDetails?.cacheReadTokens
|
|
356
|
+
),
|
|
357
|
+
cacheWriteTokens: addTokenCounts(
|
|
358
|
+
left.inputTokenDetails?.cacheWriteTokens,
|
|
359
|
+
right.inputTokenDetails?.cacheWriteTokens
|
|
360
|
+
)
|
|
361
|
+
},
|
|
362
|
+
outputTokens: addTokenCounts(left.outputTokens, right.outputTokens),
|
|
363
|
+
outputTokenDetails: {
|
|
364
|
+
textTokens: addTokenCounts(
|
|
365
|
+
left.outputTokenDetails?.textTokens,
|
|
366
|
+
right.outputTokenDetails?.textTokens
|
|
367
|
+
),
|
|
368
|
+
reasoningTokens: addTokenCounts(
|
|
369
|
+
left.outputTokenDetails?.reasoningTokens,
|
|
370
|
+
right.outputTokenDetails?.reasoningTokens
|
|
371
|
+
)
|
|
372
|
+
},
|
|
373
|
+
totalTokens: addTokenCounts(left.totalTokens, right.totalTokens),
|
|
374
|
+
reasoningTokens: addTokenCounts(
|
|
375
|
+
left.reasoningTokens,
|
|
376
|
+
right.reasoningTokens
|
|
377
|
+
),
|
|
378
|
+
cachedInputTokens: addTokenCounts(
|
|
379
|
+
left.cachedInputTokens,
|
|
380
|
+
right.cachedInputTokens
|
|
381
|
+
)
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function addTokenCounts(left, right) {
|
|
385
|
+
return left == null && right == null ? void 0 : (left ?? 0) + (right ?? 0);
|
|
386
|
+
}
|
|
387
|
+
function countStepToolCalls(steps) {
|
|
388
|
+
return steps.reduce(
|
|
389
|
+
(count, step) => count + (step.toolCalls?.length ?? 0),
|
|
390
|
+
0
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
function resolveSession(input, result, output, replayMetadataByToolCallId, runtimeToolCalls = []) {
|
|
394
|
+
if ((0, import_harness.isNormalizedSession)(
|
|
395
|
+
result?.session
|
|
396
|
+
)) {
|
|
397
|
+
return result.session;
|
|
398
|
+
}
|
|
399
|
+
if ((0, import_harness.isNormalizedSession)(result?.trace)) {
|
|
400
|
+
return result.trace;
|
|
401
|
+
}
|
|
402
|
+
const steps = resolveSteps(result);
|
|
403
|
+
const messages = [
|
|
404
|
+
{
|
|
405
|
+
role: "user",
|
|
406
|
+
content: (0, import_harness.normalizeContent)(input)
|
|
407
|
+
}
|
|
408
|
+
];
|
|
409
|
+
const stepToolCallIds = /* @__PURE__ */ new Set();
|
|
410
|
+
for (const step of steps) {
|
|
411
|
+
for (const toolCall of step.toolCalls ?? []) {
|
|
412
|
+
stepToolCallIds.add(toolCall.toolCallId);
|
|
413
|
+
}
|
|
414
|
+
messages.push(...normalizeStep(step, replayMetadataByToolCallId));
|
|
415
|
+
}
|
|
416
|
+
const unmatchedRuntimeToolCalls = runtimeToolCalls.filter(
|
|
417
|
+
(call) => call.id === void 0 || !stepToolCallIds.has(call.id)
|
|
418
|
+
);
|
|
419
|
+
if (unmatchedRuntimeToolCalls.length > 0) {
|
|
420
|
+
messages.push(...normalizeRuntimeToolCalls(unmatchedRuntimeToolCalls));
|
|
421
|
+
}
|
|
422
|
+
if (output !== void 0 && !messages.some(
|
|
423
|
+
(message) => message.role === "assistant" && message.content !== void 0
|
|
424
|
+
)) {
|
|
425
|
+
messages.push({
|
|
426
|
+
role: "assistant",
|
|
427
|
+
content: output
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
const lastStep = steps.length > 0 ? steps[steps.length - 1] : void 0;
|
|
431
|
+
const outputText = resolveOutputText(result, output, lastStep);
|
|
432
|
+
return {
|
|
433
|
+
messages,
|
|
434
|
+
outputText,
|
|
435
|
+
provider: lastStep?.model.provider,
|
|
436
|
+
model: lastStep?.model.modelId
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
function normalizeRuntimeToolCalls(runtimeToolCalls) {
|
|
440
|
+
const messages = [
|
|
441
|
+
{
|
|
442
|
+
role: "assistant",
|
|
443
|
+
toolCalls: runtimeToolCalls
|
|
444
|
+
}
|
|
445
|
+
];
|
|
446
|
+
for (const call of runtimeToolCalls) {
|
|
447
|
+
if (call.result === void 0 && !call.error) {
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
const content = call.result !== void 0 ? call.result : call.error && call.error.message.length > 0 ? call.error.message : void 0;
|
|
451
|
+
messages.push({
|
|
452
|
+
role: "tool",
|
|
453
|
+
...content !== void 0 ? { content } : {},
|
|
454
|
+
metadata: (0, import_harness.normalizeMetadata)({
|
|
455
|
+
name: call.name,
|
|
456
|
+
toolCallId: call.id,
|
|
457
|
+
isError: Boolean(call.error)
|
|
458
|
+
})
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
return messages;
|
|
462
|
+
}
|
|
463
|
+
function resolveSteps(result) {
|
|
464
|
+
if (!result || typeof result !== "object") {
|
|
465
|
+
return [];
|
|
466
|
+
}
|
|
467
|
+
return Array.isArray(result.steps) ? result.steps ?? [] : [];
|
|
468
|
+
}
|
|
469
|
+
function resolveLanguageModelUsage(result) {
|
|
470
|
+
if (!result || typeof result !== "object") {
|
|
471
|
+
return void 0;
|
|
472
|
+
}
|
|
473
|
+
const aiResult = result;
|
|
474
|
+
return aiResult.totalUsage ?? aiResult.usage;
|
|
475
|
+
}
|
|
476
|
+
function resolveOutputText(result, output, lastStep) {
|
|
477
|
+
if (lastStep?.text) {
|
|
478
|
+
return lastStep.text;
|
|
479
|
+
}
|
|
480
|
+
if (result && typeof result === "object" && typeof result.text === "string") {
|
|
481
|
+
return result.text;
|
|
482
|
+
}
|
|
483
|
+
return typeof output === "string" ? output : void 0;
|
|
484
|
+
}
|
|
485
|
+
function normalizeStep(step, replayMetadataByToolCallId) {
|
|
486
|
+
const toolResultsById = new Map(
|
|
487
|
+
(step.toolResults ?? []).map((toolResult) => [
|
|
488
|
+
toolResult.toolCallId,
|
|
489
|
+
toolResult
|
|
490
|
+
])
|
|
491
|
+
);
|
|
492
|
+
const normalizedCalls = (step.toolCalls ?? []).map(
|
|
493
|
+
(toolCall) => normalizeToolCall(toolCall, toolResultsById, replayMetadataByToolCallId)
|
|
494
|
+
);
|
|
495
|
+
const normalizedCallsById = new Map(
|
|
496
|
+
normalizedCalls.map((toolCall) => [toolCall.id, toolCall])
|
|
497
|
+
);
|
|
498
|
+
const assistantMetadata = (0, import_harness.normalizeMetadata)({
|
|
499
|
+
stepNumber: step.stepNumber,
|
|
500
|
+
finishReason: step.finishReason,
|
|
501
|
+
rawFinishReason: step.rawFinishReason,
|
|
502
|
+
reasoningText: step.reasoningText,
|
|
503
|
+
response: step.response
|
|
504
|
+
});
|
|
505
|
+
const messages = [];
|
|
506
|
+
if (step.text || normalizedCalls.length > 0 || assistantMetadata) {
|
|
507
|
+
messages.push({
|
|
508
|
+
role: "assistant",
|
|
509
|
+
...step.text ? { content: step.text } : {},
|
|
510
|
+
...normalizedCalls.length > 0 ? { toolCalls: normalizedCalls } : {},
|
|
511
|
+
...assistantMetadata ? { metadata: assistantMetadata } : {}
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
for (const toolResult of step.toolResults ?? []) {
|
|
515
|
+
const content = toolResult.output === void 0 ? void 0 : (0, import_harness.normalizeContent)(toolResult.output);
|
|
516
|
+
messages.push({
|
|
517
|
+
role: "tool",
|
|
518
|
+
...content !== void 0 ? { content } : {},
|
|
519
|
+
metadata: (0, import_harness.normalizeMetadata)({
|
|
520
|
+
name: toolResult.toolName,
|
|
521
|
+
toolCallId: toolResult.toolCallId,
|
|
522
|
+
isError: Boolean(normalizedCallsById.get(toolResult.toolCallId)?.error),
|
|
523
|
+
preliminary: toolResult.preliminary,
|
|
524
|
+
providerExecuted: toolResult.providerExecuted,
|
|
525
|
+
title: toolResult.title,
|
|
526
|
+
providerMetadata: toolResult.providerMetadata
|
|
527
|
+
})
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
return messages;
|
|
531
|
+
}
|
|
532
|
+
function normalizeToolCall(toolCall, toolResultsById, replayMetadataByToolCallId) {
|
|
533
|
+
const toolResult = toolResultsById.get(toolCall.toolCallId);
|
|
534
|
+
const normalizedArguments = normalizeArguments(toolCall.input);
|
|
535
|
+
const normalizedResult = toolResult !== void 0 ? (0, import_harness.toJsonValue)(toolResult.output) : void 0;
|
|
536
|
+
const errorValue = toolCall.invalid || toolCall.error !== void 0 ? normalizeError(toolCall.error ?? toolCall.invalid) : void 0;
|
|
537
|
+
const replayMetadata = (0, import_replay.normalizeReplayMetadata)(
|
|
538
|
+
replayMetadataByToolCallId.get(toolCall.toolCallId)
|
|
539
|
+
);
|
|
540
|
+
return {
|
|
541
|
+
id: toolCall.toolCallId,
|
|
542
|
+
name: toolCall.toolName,
|
|
543
|
+
...normalizedArguments ? { arguments: normalizedArguments } : {},
|
|
544
|
+
...toolResult && normalizedResult !== void 0 ? { result: normalizedResult } : {},
|
|
545
|
+
...errorValue ? { error: errorValue } : {},
|
|
546
|
+
metadata: (0, import_harness.normalizeMetadata)({
|
|
547
|
+
providerExecuted: toolCall.providerExecuted ?? toolResult?.providerExecuted,
|
|
548
|
+
title: toolCall.title ?? toolResult?.title,
|
|
549
|
+
dynamic: toolCall.dynamic,
|
|
550
|
+
invalid: toolCall.invalid,
|
|
551
|
+
preliminary: toolResult?.preliminary,
|
|
552
|
+
providerMetadata: toolCall.providerMetadata ?? toolResult?.providerMetadata,
|
|
553
|
+
...replayMetadata ?? {}
|
|
554
|
+
})
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
function normalizeArguments(value) {
|
|
558
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
559
|
+
return void 0;
|
|
560
|
+
}
|
|
561
|
+
return (0, import_harness.normalizeRecord)(value);
|
|
562
|
+
}
|
|
563
|
+
function normalizeError(error) {
|
|
564
|
+
if (error instanceof Error) {
|
|
565
|
+
return {
|
|
566
|
+
type: error.name,
|
|
567
|
+
message: error.message
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
const normalized = (0, import_harness.toJsonValue)(error);
|
|
571
|
+
if (normalized && typeof normalized === "object" && !Array.isArray(normalized) && typeof normalized.message === "string") {
|
|
572
|
+
return {
|
|
573
|
+
message: normalized.message,
|
|
574
|
+
type: typeof normalized.type === "string" ? normalized.type : "Error"
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
return {
|
|
578
|
+
type: "Error",
|
|
579
|
+
message: String(error ?? "Unknown tool call error")
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
function toReplayJsonValue(value, label) {
|
|
583
|
+
const normalized = (0, import_harness.toJsonValue)(value);
|
|
584
|
+
if (normalized === void 0) {
|
|
585
|
+
throw new Error(
|
|
586
|
+
`Tool replay only supports JSON-serializable values. ${label} could not be normalized.`
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
return normalized;
|
|
590
|
+
}
|
|
591
|
+
function isAsyncIterable(value) {
|
|
592
|
+
return value !== null && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value;
|
|
593
|
+
}
|
|
594
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
595
|
+
0 && (module.exports = {
|
|
596
|
+
aiSdkHarness
|
|
597
|
+
});
|
|
598
|
+
//# sourceMappingURL=index.js.map
|