// Generated from openapi.json. Use only in your backend/BFF. export type CaseHistory = { "items": Array>; "next": number | null }; export type CasePage = { "items": Array; "next": string | null }; export type CaseView = { "case_id": string; "app_key": string; "major_version": number; "revision": number; "status": string; "version": Record; "input": EvaluationRequest; "prediction": EvaluationResult | null; "decision": Record | null; "error_code": string | null; "replayed"?: boolean }; export type Column = { "key": string; "type": "string" | "decimal" | "integer" | "boolean"; "nullable"?: boolean; "unit"?: string | null; "tolerance"?: string }; export type Difference = { "key": Array; "column": string; "expected": JsonValue; "actual": JsonValue }; export type EvaluationRequest = { "snapshot": { "grain": string; "primary_key": Array; "columns": Array<{ "key": string; "type": "string" | "decimal" | "integer" | "boolean"; "nullable"?: boolean; "unit"?: string | null; "tolerance"?: string }>; "rows": Array>; "complete": boolean } }; export type EvaluationResult = { "state": "equal" | "different" | "unverified"; "expected_rows": number; "actual_rows": number; "expected_digest": string; "actual_digest": string; "differences": Array; "reason"?: string | null; "missing_rows"?: number | null; "extra_rows"?: number | null; "duplicate_expected"?: number | null; "duplicate_actual"?: number | null; "different_values"?: number | null; "differences_truncated"?: boolean | null }; export type ExtractResult = { "run_id": string; "document_version_id": string; "parser_revision": string; "complete": boolean; "issues": Array>; "fields": Array>; "rows": Array>; "decision": "pending"; "document_type": string; "template_version": number; "usage": ExtractionUsage; "customer_certified"?: false }; export type ExtractionUsage = { "documents": number; "pages": number; "llm_tokens": number; "llm_tokens_estimated": number; "tokens_exact": boolean }; export type HTTPValidationError = { "detail"?: Array }; export type JsonValue = unknown; export type PoRow = { "key": string; "po_number": string; "supplier": string; "currency": string; "remaining": string }; export type ResolveResult = { "mode"?: "isolated_replay"; "state": "matched" | "unmatched" | "ambiguous" | "insufficient_remaining"; "candidates": Array; "reservation_created"?: false }; export type Snapshot = { "grain": string; "primary_key": Array; "columns": Array; "rows": Array>; "complete": boolean }; export type SourceQueryResult = { "columns": Array; "rows": Array>; "mode": "workload" | "delegated_oauth" | "kerberos" }; export type ValidationError = { "loc": Array; "msg": string; "type": string; "input"?: unknown; "ctx"?: Record }; export type CaseSubmission = { "input": { "snapshot": { "grain": string; "primary_key": Array; "columns": Array<{ "key": string; "type": "string" | "decimal" | "integer" | "boolean"; "nullable"?: boolean; "unit"?: string | null; "tolerance"?: string }>; "rows": Array>; "complete": boolean } } }; export type CaseMutation = { "expected_revision": number }; export type CaseDecision = { "expected_revision": number; "decision": "approve" | "reject" | "correct"; "reason": string; "correction"?: { "snapshot": { "grain": string; "primary_key": Array; "columns": Array<{ "key": string; "type": "string" | "decimal" | "integer" | "boolean"; "nullable"?: boolean; "unit"?: string | null; "tolerance"?: string }>; "rows": Array>; "complete": boolean } } | null; "golden_consent"?: boolean }; export type CompareRequest = { "expected": { "grain": string; "primary_key": Array; "columns": Array<{ "key": string; "type": "string" | "decimal" | "integer" | "boolean"; "nullable"?: boolean; "unit"?: string | null; "tolerance"?: string }>; "rows": Array>; "complete": boolean }; "actual": { "grain": string; "primary_key": Array; "columns": Array<{ "key": string; "type": "string" | "decimal" | "integer" | "boolean"; "nullable"?: boolean; "unit"?: string | null; "tolerance"?: string }>; "rows": Array>; "complete": boolean } }; export type ResolveRequest = { "snapshot": { "schema_version"?: "1"; "mode": "isolated_replay"; "provenance": string; "policy": { "currency": string; "decimal_places": number; "normalization": "exact" | "trim_casefold"; "amount_basis": string; "revision": string }; "rows": Array<{ "key": string; "po_number": string; "supplier": string; "currency": string; "remaining": string }>; "authority"?: { "capture_id": string; "snapshot_digest": string } | null }; "invoice": { "invoice_number": string; "po_number": string; "supplier": string; "currency": string; "amount": string; "po_row_key"?: string | null } }; export type QueryRequest = { "app_key": string; "major_version": number; "query_key": string; "after"?: string }; export type NotifyRequest = { "app_key": string; "major_version": number; "case_id": string; "expected_revision": number }; export type ExtractRequest = { "document_type": string; "mime_type": "application/pdf" | "image/png" | "image/jpeg"; "content_base64": string; "inputs"?: Record }; export type SourceQueryRequest = { "query_key": string; "parameters"?: Record; "identity_session"?: string | null }; export class ApiError extends Error { constructor(public readonly status: number, public readonly retryAfter: string | null) { super(`AgentData API returned HTTP ${status}`); } } export interface ClientOptions { baseUrl: string; credential: () => string | Promise; subject?: () => string | undefined | Promise; timeoutMilliseconds: number; maxResponseBytes: number; } export class AgentDataClient { private readonly baseUrl: string; constructor(private readonly options: ClientOptions) { const origin = new URL(options.baseUrl); if (origin.protocol !== 'https:' || origin.username || origin.password || origin.search || origin.hash || options.timeoutMilliseconds <= 0 || options.maxResponseBytes <= 0) { throw new Error('Configure an HTTPS origin and positive timeout/response limits'); } this.baseUrl = options.baseUrl.replace(/\/$/, ''); } private async request(method: string, path: string, body?: unknown, extraHeaders?: Record, query?: Record): Promise { const endpoint = new URL(this.baseUrl + path); for (const [key, value] of Object.entries(query ?? {})) { if (value !== undefined) endpoint.searchParams.set(key, String(value)); } const headers: Record = { Authorization: `Bearer ${await this.options.credential()}`, Accept: 'application/json', ...extraHeaders, }; const proof = await this.options.subject?.(); if (proof) headers['X-AgentData-Subject'] = proof; if (body !== undefined) headers['Content-Type'] = 'application/json'; const response = await fetch(endpoint, { method, headers, body: body === undefined ? undefined : JSON.stringify(body), redirect: 'error', signal: AbortSignal.timeout(this.options.timeoutMilliseconds), }); if (!response.ok) { await response.body?.cancel(); throw new ApiError(response.status, response.headers.get('Retry-After')); } if (!response.body) throw new Error('API response has no body'); const reader = response.body.getReader(); const chunks: Uint8Array[] = []; let size = 0; try { while (true) { const item = await reader.read(); if (item.done) break; size += item.value.byteLength; if (size > this.options.maxResponseBytes) throw new Error('API response exceeds configured limit'); chunks.push(item.value); } } catch (error) { await reader.cancel(); throw error; } finally { reader.releaseLock(); } const content = new Uint8Array(size); let offset = 0; for (const chunk of chunks) { content.set(chunk, offset); offset += chunk.byteLength; } return JSON.parse(new TextDecoder().decode(content)) as T; } session(args: { }): Promise { return this.request("GET", `/app-api/v1/session`, undefined, {}, {}); } app_schema(args: { app_key: string; major: number }): Promise { return this.request("GET", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/openapi.json`, undefined, {}, {}); } app_evaluate(args: { app_key: string; major: number; body: EvaluationRequest }): Promise { return this.request("POST", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/evaluate`, args.body, {}, {}); } submit(args: { app_key: string; major: number; idempotency_key: string; body: CaseSubmission }): Promise { return this.request("POST", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/cases`, args.body, {"Idempotency-Key": args.idempotency_key}, {}); } listing(args: { app_key: string; major: number; after?: string }): Promise { return this.request("GET", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/cases`, undefined, {}, {"after": args.after}); } read(args: { app_key: string; major: number; case_id: string }): Promise { return this.request("GET", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/cases/${encodeURIComponent(String(args.case_id))}`, undefined, {}, {}); } history(args: { app_key: string; major: number; case_id: string; after?: number }): Promise { return this.request("GET", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/cases/${encodeURIComponent(String(args.case_id))}/history`, undefined, {}, {"after": args.after}); } cancel(args: { app_key: string; major: number; case_id: string; body: CaseMutation }): Promise { return this.request("POST", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/cases/${encodeURIComponent(String(args.case_id))}/cancel`, args.body, {}, {}); } retry(args: { app_key: string; major: number; case_id: string; body: CaseMutation }): Promise { return this.request("POST", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/cases/${encodeURIComponent(String(args.case_id))}/retry`, args.body, {}, {}); } decide(args: { app_key: string; major: number; case_id: string; body: CaseDecision }): Promise { return this.request("POST", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/cases/${encodeURIComponent(String(args.case_id))}/decisions`, args.body, {}, {}); } golden(args: { app_key: string; major: number; case_id: string }): Promise { return this.request("GET", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/cases/${encodeURIComponent(String(args.case_id))}/golden-candidate`, undefined, {}, {}); } compare(args: { body: CompareRequest }): Promise { return this.request("POST", `/app-api/v1/capabilities/compare`, args.body, {}, {}); } resolve(args: { body: ResolveRequest }): Promise { return this.request("POST", `/app-api/v1/capabilities/resolve`, args.body, {}, {}); } query(args: { body: QueryRequest }): Promise { return this.request("POST", `/app-api/v1/capabilities/query`, args.body, {}, {}); } notify(args: { body: NotifyRequest }): Promise { return this.request("POST", `/app-api/v1/capabilities/notify`, args.body, {}, {}); } extract(args: { body: ExtractRequest }): Promise { return this.request("POST", `/app-api/v1/capabilities/extract`, args.body, {}, {}); } source_query(args: { body: SourceQueryRequest }): Promise { return this.request("POST", `/app-api/v1/capabilities/query/source`, args.body, {}, {}); } saved_query(args: { app_key: string; major: number; query_key: string; after?: string }): Promise { return this.request("GET", `/app-api/apps/${encodeURIComponent(String(args.app_key))}/v${encodeURIComponent(String(args.major))}/queries/${encodeURIComponent(String(args.query_key))}`, undefined, {}, {"after": args.after}); } } export async function verifyWebhook(args: { secret: string; timestamp: string; eventId: string; body: Uint8Array; signature: string; now: number; replaySeconds: number; }): Promise { if (args.replaySeconds <= 0) throw new Error('Configure a positive replay window'); if (!/^\d+$/.test(args.timestamp)) return false; const stamp = Number(args.timestamp); if (!Number.isSafeInteger(stamp) || Math.abs(args.now - stamp) > args.replaySeconds) return false; if (!/^v1=[a-f0-9]{64}$/.test(args.signature)) return false; const key = await crypto.subtle.importKey('raw', new TextEncoder().encode(args.secret), {name: 'HMAC', hash: 'SHA-256'}, false, ['verify']); const prefix = new TextEncoder().encode(`${stamp}.${args.eventId}.`); const message = new Uint8Array(prefix.length + args.body.length); message.set(prefix); message.set(args.body, prefix.length); const supplied = Uint8Array.from(args.signature.slice(3).match(/../g)!, byte => parseInt(byte, 16)); return crypto.subtle.verify('HMAC', key, supplied, message); }