import {z} from 'zod' export type GetApiJobJobIdArgs = {job_id: string}; export type GetApiJobJobIdOptions = {baseUrl?: string | undefined, SkippableHTTPBearer?: string | undefined, fetch?: typeof fetch | undefined}; export const parseUsageBreakdown = z.object({parse_model: z.enum(["R-1", "R-1 Mini", "Legacy"]), tier: z.enum(["Default", "Batch"]), parse_pages: z.number().int().optional(), parse_native_pages: z.number().int().optional(), legacy_parse_credits: z.number().optional(), ocr_pages: z.number().int().optional(), charts: z.number().int().optional(), prompted_blocks: z.number().int().optional()}); export const splitUsageBreakdown = z.object({split_model: z.enum(["Split", "Deep Split"]), split_pages: z.number().int().optional(), ocr_pages: z.number().int().optional(), charts: z.number().int().optional(), prompted_blocks: z.number().int().optional()}); export const editUsageBreakdown = z.object({edit_model: z.enum(["Normal", "Prefill"]), edit_pages: z.number().int().optional(), prefill_pages: z.number().int().optional()}); export const parseUsage = z.object({num_pages: z.number().int(), credits: z.number().nullable().optional(), credit_breakdown: z.record(z.string(), z.number()).nullable().optional(), page_billing_breakdown: z.record(z.string(), z.array(z.enum(["page", "html_page", "docx_native_page", "agentic", "complex", "chart_agent", "spreadsheet_cells", "billable_spreadsheet_pages", "enrich_table", "figure_summary", "table_summary", "key_value", "agentic_text", "promptable_agentic_text", "reducto_lite_page"]))).nullable().optional(), non_empty_cell_count: z.number().int().nullable().optional(), usage_breakdown: z.union([parseUsageBreakdown, splitUsageBreakdown, editUsageBreakdown]).nullable().optional()}); export const boundingBox = z.object({left: z.number(), top: z.number(), width: z.number(), height: z.number(), page: z.number().int(), original_page: z.number().int().optional()}); export const granularConfidence = z.object({extract_confidence: z.number().nullable().optional(), parse_confidence: z.number().nullable().optional()}); export const mergedTable = z.object({content: z.string(), bbox: boundingBox, image_url: z.string().nullable().optional()}); export const parseBlock = z.object({type: z.enum(["Header", "Footer", "Title", "Section Header", "Page Number", "List Item", "Figure", "Table", "Key Value", "Text", "Comment", "Signature"]), bbox: boundingBox, content: z.string(), image_url: z.string().nullable().optional(), chart_data: z.array(z.string()).nullable().optional(), confidence: z.string().nullable().optional(), granular_confidence: granularConfidence.nullable().optional(), merged_tables: z.array(mergedTable).nullable().optional(), extra: z.record(z.string(), z.unknown()).nullable().optional()}); export const parseChunk = z.object({content: z.string(), embed: z.string(), enriched: z.string().nullable(), enrichment_success: z.boolean().optional(), blocks: z.array(parseBlock)}); export const oCRWord = z.object({text: z.string(), bbox: boundingBox, confidence: z.number().nullable().optional(), chunk_index: z.number().int().nullable().optional(), rotation: z.number().int().nullable().optional()}); export const oCRLine = z.object({text: z.string(), bbox: boundingBox, confidence: z.number().nullable().optional(), chunk_index: z.number().int().nullable().optional(), rotation: z.number().int().nullable().optional()}); export const oCRResult = z.object({words: z.array(oCRWord), lines: z.array(oCRLine)}); export const fullResult = z.object({type: z.literal("full"), chunks: z.array(parseChunk), ocr: oCRResult.nullable().optional(), custom: z.unknown()}); export const urlResult = z.object({type: z.literal("url"), url: z.string(), result_id: z.string()}); export const documentProperties = z.object({title: z.string().nullable().optional(), author: z.string().nullable().optional(), subject: z.string().nullable().optional(), keywords: z.string().nullable().optional(), creator: z.string().nullable().optional(), producer: z.string().nullable().optional(), last_modified_by: z.string().nullable().optional(), created_at: z.string().nullable().optional(), modified_at: z.string().nullable().optional()}); export const parseResponse = z.object({response_type: z.literal("parse").optional(), job_id: z.string(), duration: z.number(), pdf_url: z.string().nullable().optional(), studio_link: z.string().nullable().optional(), usage: parseUsage, result: z.union([fullResult, urlResult]), document_properties: documentProperties.nullable().optional()}); export const extractUsageBreakdown = z.object({extract_model: z.enum(["Extract", "Deep Extract"]), tier: z.enum(["Default", "Batch"]).optional(), extract_pages: z.number().int().optional(), extract_fields: z.number().int().optional(), ocr_pages: z.number().int().optional(), charts: z.number().int().optional(), prompted_blocks: z.number().int().optional()}); export const extractUsage = z.object({num_pages: z.number().int(), num_fields: z.number().int(), credits: z.number().nullable().optional(), extract_mode: z.enum(["super_agent", "extract", "spreadsheet_agent"]).nullable().optional(), usage_breakdown: extractUsageBreakdown.nullable().optional()}); export const extractResponse = z.object({response_type: z.literal("extract").optional(), job_id: z.string().nullable().optional(), usage: extractUsage, duration: z.number().nullable().optional(), studio_link: z.string().nullable().optional(), result: z.union([z.array(z.unknown()), urlResult]), citations: z.union([z.array(z.unknown()), urlResult]).nullable(), response_confidence: z.record(z.string(), z.unknown()).nullable().optional()}); export const splitPartition = z.object({name: z.string(), pages: z.array(z.number().int()), conf: z.enum(["high", "low"]).optional()}); export const split = z.object({name: z.string(), pages: z.array(z.number().int()), conf: z.enum(["high", "low"]).optional(), partitions: z.array(splitPartition).nullable().optional()}); export const splitResult = z.object({section_mapping: z.record(z.string(), z.array(z.number().int())).nullable(), splits: z.array(split)}); export const deepSplitPageEvidence = z.object({page_number: z.number().int(), evidence: z.string(), confidence: z.enum(["high", "medium", "low"]).nullable().optional()}); export const deepSplitPartition = z.object({name: z.string(), pages: z.array(deepSplitPageEvidence)}); export const deepSplit = z.object({name: z.string(), pages: z.array(deepSplitPageEvidence), partitions: z.array(deepSplitPartition).nullable().optional()}); export const deepSplitResult = z.object({splits: z.array(deepSplit)}); export const splitResponse = z.object({response_type: z.literal("split").optional(), job_id: z.string().nullable().optional(), usage: parseUsage, duration: z.number().nullable().optional(), result: z.union([splitResult, deepSplitResult, urlResult])}); export const editWidget = z.object({bbox: boundingBox, description: z.string(), type: z.enum(["text", "checkbox", "radio", "dropdown", "barcode"]), fill: z.boolean().optional(), value: z.string().nullable().optional(), font_size: z.number().gte(1).lte(72).nullable().optional()}); export const editResponse = z.object({response_type: z.literal("edit").optional(), job_id: z.string().nullable().optional(), document_url: z.string(), form_schema: z.array(editWidget).nullable().optional(), usage: parseUsage.nullable().optional()}); export const v3ExtractResponse = z.object({response_type: z.literal("v3_extract").optional(), job_id: z.string().nullable().optional(), usage: extractUsage, duration: z.number().nullable().optional(), studio_link: z.string().nullable().optional(), confidence: z.enum(["high", "low"]).nullable().optional(), confidence_reason: z.string().nullable().optional(), result: z.union([z.unknown(), z.array(z.unknown())])}); export const extractSplitResponse = z.object({split_name: z.string(), page_range: z.array(z.number().int()), partition: z.string().nullable().optional(), result: z.union([extractResponse, v3ExtractResponse])}); export const pipelineResult = z.object({parse: z.union([parseResponse, z.array(parseResponse)]).nullable(), extract: z.union([z.array(extractSplitResponse), extractResponse, v3ExtractResponse]).nullable(), split: splitResponse.nullable(), edit: editResponse.nullable().optional()}); export const pipelineResponse = z.object({response_type: z.literal("pipeline").optional(), job_id: z.string(), usage: parseUsage, result: pipelineResult}); export const classifyResponseCategory = z.object({category: z.string()}); export const criteriaConfidence = z.object({criterion: z.string(), confidence: z.enum(["high", "low"])}); export const categoryConfidence = z.object({category: z.string(), confidence: z.number(), criteria_confidence: z.array(criteriaConfidence)}); export const responseConfidence = z.object({categories: z.array(categoryConfidence)}); export const classifyUsageBreakdown = z.object({classify_model: z.enum(["Classify", "Deep Classify"]), classify_pages: z.number().int().optional()}); export const classifyUsage = z.object({num_pages: z.number().int(), num_categories: z.number().int(), credits: z.number().nullable().optional(), usage_breakdown: classifyUsageBreakdown.nullable().optional()}); export const classifyResponse = z.object({response_type: z.literal("classify").optional(), job_id: z.string(), result: z.union([classifyResponseCategory, urlResult]), response_confidence: responseConfidence.nullable().optional(), usage: classifyUsage.nullable().optional(), extra_metadata: z.record(z.string(), z.string()).optional(), duration: z.number().nullable().optional()}); export const chartResult = z.object({chart_data: z.record(z.string(), z.unknown()), summary: z.string(), reconstruction_url: z.string(), verified: z.boolean()}); export const chartUsage = z.object({num_charts: z.literal(1).optional(), credits: z.number().optional()}); export const chartResponse = z.object({response_type: z.literal("chart").optional(), job_id: z.string(), result: chartResult, usage: chartUsage.optional(), duration: z.number().nullable().optional()}); export const errorCode = z.enum(["TIMEOUT", "CAPACITY_TIMEOUT", "CUSTOMER_TIMEOUT", "INTERNAL_ERROR", "SERVICE_UNAVAILABLE", "GPU_ALLOCATION_ERROR", "GPU_POOL_SATURATED", "BATCH_QUEUE_FULL", "QUEUE_FULL", "JOB_STATE_ERROR", "DOCUMENT_CORRUPT", "DOCUMENT_EMPTY", "DOCUMENT_UNSUPPORTED", "DOCUMENT_TOO_LARGE", "OFFICE_CONVERSION_TOO_LARGE", "IMAGE_TOO_LARGE", "IMAGE_TOO_SMALL", "IMAGE_INVALID_ASPECT_RATIO", "DOCUMENT_PASSWORD_PROTECTED", "FORM_FILL_FAILED", "INTERNAL_INVARIANT_VIOLATION", "GPU_UNAVAILABLE", "CONTEXT_WINDOW_EXCEEDED", "OUTPUT_LIMIT_EXCEEDED", "PROCESSING_FAILED", "INFERENCE_METHOD_UNSUPPORTED", "SUBPROCESS_CRASHED", "BATCH_ORPHANED", "OVERSIZED_RESULT", "LLM_OUTPUT_PARSE_FAILED", "LLM_PROVIDER_ERROR", "INVALID_CONFIG", "INVALID_SCHEMA", "AUTH_ERROR", "NOT_APPLICABLE", "REGION_UNAVAILABLE", "NOT_FOUND", "JOB_DELETION_IN_PROGRESS", "JOB_DELETED", "JOB_NOT_COMPLETE", "JOB_CANCELLED", "RATE_LIMIT", "CELL_COUNT_EXCEEDED", "URL_NOT_ALLOWED"]); export const errorDetail = z.object({code: z.number().int(), name: errorCode, message: z.string(), job_id: z.string().nullable().optional()}); export const asyncJobResponse = z.object({status: z.enum(["Pending", "Completed", "Failed", "Idle"]), result: z.union([parseResponse, extractResponse, splitResponse, editResponse, pipelineResponse, v3ExtractResponse, classifyResponse, chartResponse]).nullable().optional(), progress: z.number().nullable().optional(), reason: z.string().nullable().optional(), error: errorDetail.nullable().optional()}); export const enhancedAsyncJobResponse = z.object({status: z.enum(["Pending", "Completed", "Failed", "Idle"]), result: z.union([parseResponse, extractResponse, splitResponse, editResponse, pipelineResponse, v3ExtractResponse, classifyResponse, chartResponse]).nullable().optional(), progress: z.number().nullable().optional(), reason: z.string().nullable().optional(), error: errorDetail.nullable().optional(), type: z.enum(["Parse", "Extract", "Split", "Edit", "Pipeline", "Classify", "Chart"]).nullable().optional(), num_pages: z.number().int().nullable().optional(), total_pages: z.number().int().nullable().optional(), source: z.unknown(), duration: z.number().nullable().optional(), created_at: z.string().nullable().optional(), raw_config: z.string().nullable().optional(), bucket: z.unknown()}); export const getApiJobJobIdResponse = z.union([asyncJobResponse, enhancedAsyncJobResponse]); 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 }; /** * Retrieve Parse * * GET /job/{job_id} */ export const getApiJobJobId = async (args: GetApiJobJobIdArgs, options?: GetApiJobJobIdOptions) => { const {baseUrl = "https://platform.reducto.ai", fetch: fetchFn = fetch, SkippableHTTPBearer} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (SkippableHTTPBearer !== undefined) headers.set('authorization', `Bearer ${SkippableHTTPBearer}`) const url = `${baseUrl.replace(/\/+$/, '')}/job/${encodeURIComponent(String(args.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(getApiJobJobIdResponse, await res.json()) };