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