import {z} from 'zod' export type GetApiV2ListTestRunsTestCaseBatchJobIdArgs = {test_case_batch_job_id: string, limit?: number | undefined, pagination_key?: string | undefined}; export type GetApiV2ListTestRunsTestCaseBatchJobIdOptions = {baseUrl?: string | undefined, apiKey?: string | undefined, fetch?: typeof fetch | undefined}; export const responseEngineRetellLm = z.object({type: z.literal("retell-llm"), llm_id: z.string(), version: z.number().nullable().optional()}); export const responseEngineConversationFlow = z.object({type: z.literal("conversation-flow"), conversation_flow_id: z.string(), version: z.number().nullable().optional()}); export const retellResponseEngine = z.union([responseEngineRetellLm, responseEngineConversationFlow]); export const toolMockInputMatchRule = z.union([z.object({type: z.literal("any")}), z.object({type: z.literal("partial_match"), args: z.object({})})]); export const toolMock = z.object({tool_name: z.string().optional(), node_id: z.string().optional(), input_match_rule: toolMockInputMatchRule, output: z.string().max(15000), result: z.boolean().nullable().optional()}); export const lLMModel = z.enum(["gpt-4.1", "gpt-4.1-mini", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5.1", "gpt-5.2", "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.5", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-6-astra", "gpt-6-sol", "gpt-6.1-sol", "gpt-6.1-terra", "gpt-6-luna", "tell-1", "claude-4.6-sonnet", "claude-5-opus", "claude-5.5-opus", "claude-5-sonnet", "claude-5.5-sonnet", "claude-5.5-haiku", "claude-4.5-haiku", "gemini-3.0-flash", "gemini-3.1-flash-lite", "gemini-3.5-flash", "gemini-3.5-flash-lite", "gemini-3.6-flash", "gemini-3.7-flash", "gemini-3.8-flash", "gemini-4-argon"]); export const testCaseDefinition = z.object({name: z.string(), response_engine: retellResponseEngine, user_prompt: z.string(), metrics: z.array(z.string()), dynamic_variables: z.record(z.string(), z.string()), tool_mocks: z.array(toolMock), llm_model: lLMModel, test_case_definition_id: z.string(), type: z.literal("simulation"), creation_timestamp: z.number().int(), user_modified_timestamp: z.number().int()}); export const testCaseJob = z.object({test_case_job_id: z.string(), status: z.enum(["pending", "in_progress", "pass", "fail", "error"]), test_case_definition_id: z.string(), test_case_definition_snapshot: testCaseDefinition, transcript_snapshot: z.object({}).nullable().optional(), result_explanation: z.string().nullable().optional(), creation_timestamp: z.number().int(), user_modified_timestamp: z.number().int()}); export const getApiV2ListTestRunsTestCaseBatchJobIdResponse = z.object({pagination_key: z.string().optional(), has_more: z.boolean(), items: z.array(testCaseJob)}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * List test case jobs (test runs) for a batch test job with pagination * * GET /v2/list-test-runs/{test_case_batch_job_id} */ export const getApiV2ListTestRunsTestCaseBatchJobId = async (args: GetApiV2ListTestRunsTestCaseBatchJobIdArgs, options?: GetApiV2ListTestRunsTestCaseBatchJobIdOptions) => { const {baseUrl = "https://api.retellai.com", fetch: fetchFn = fetch, apiKey} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.limit != null) query.append("limit", String(args.limit)) if (args.pagination_key != null) query.append("pagination_key", String(args.pagination_key)) if (apiKey !== undefined) headers.set('authorization', `Bearer ${apiKey}`) const url = `${baseUrl.replace(/\/+$/, '')}/v2/list-test-runs/${encodeURIComponent(String(args.test_case_batch_job_id))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApiV2ListTestRunsTestCaseBatchJobIdResponse, await res.json()) };