// The OCR port over the platform's document reader: the one file of this module that knows the SDK's // error type. // // `DocumentReader` (kit-platform) is `@conusai-sdk/ocr` wired to the deployment contract: `submit` // returns when the platform has accepted the document and `wait` polls the job to its document. What // this adapter adds is the one distinction core needs and the SDK only encodes in a string: "the // platform says this job failed" (permanent, the document is marked failed) against everything else // (a network error, a timeout, a 5xx: the job throws and the queue retries it). A page image the platform // has none of is not a failure either: the page is read from its text. import type { DocumentReader } from "@conusai-kit/platform" import { OcrError } from "@conusai-sdk/ocr" import { type DocumentOcr, OcrJobFailed } from "../core/ports.js" export interface SdkOcrOptions { /** Poll interval of `wait`, in milliseconds. */ readonly intervalMs?: number /** Give up on one job after this long; the document then retries from its stored job id. */ readonly timeoutMs?: number } export function sdkDocumentOcr( reader: Pick, options: SdkOcrOptions = {}, ): DocumentOcr { return { async submit(bytes, { filename, idempotencyKey }) { const job = await reader.submit(bytes, { filename, idempotencyKey }) return { jobId: job.id } }, async wait(jobId, { signal } = {}) { try { return await reader.wait(jobId, { ...(options.intervalMs === undefined ? {} : { intervalMs: options.intervalMs }), ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }), ...(signal ? { signal } : {}), }) } catch (error) { if (error instanceof OcrError && error.type === "job-failed") throw new OcrJobFailed() throw error } }, async page(jobId, page, { signal } = {}) { try { const image = await reader.page(jobId, page, signal ? { signal } : {}) return { bytes: image.bytes, mediaType: image.contentType } } catch (error) { // The platform keeps a job's input for a day and draws a page on demand: a job past that, or a // page it has none of, is a page read from its text. Anything else is transient and thrown. if (error instanceof OcrError && (error.status === 404 || error.status === 422)) return undefined throw error } }, } }