okrapdf 0.12.0 → 0.13.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.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Upload a PDF, get an OpenAI-compatible endpoint.
6
6
  npm install okrapdf
7
7
  ```
8
8
 
9
- Get your API key at [app.okrapdf.com/sign-up](https://app.okrapdf.com/sign-up).
9
+ Get your API key at [app.okrapdf.com/settings](https://app.okrapdf.com/settings).
10
10
 
11
11
  ## Quick Start
12
12
 
package/dist/browser.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { doc } from './url.js';
2
- import './types-58dvD4Yj.js';
2
+ import './types-D2JaySEg.js';
3
3
  import 'zod';
4
4
 
5
5
  declare const _default: {
@@ -52,6 +52,18 @@ function inferBlobName(input, fallback) {
52
52
  }
53
53
  return fallback;
54
54
  }
55
+ function toHeaderSafeFileName(fileName) {
56
+ const leaf = fileName.split(/[\\/]/).pop() || fileName;
57
+ const cleaned = leaf.replace(/[\r\n]/g, " ").trim();
58
+ if (/^[\x20-\x7E]+$/.test(cleaned)) {
59
+ return cleaned;
60
+ }
61
+ const extMatch = cleaned.match(/(\.[A-Za-z0-9]{1,10})$/);
62
+ const extension = extMatch?.[1].toLowerCase() ?? "";
63
+ const base = extension ? cleaned.slice(0, -extension.length) : cleaned;
64
+ const asciiBase = base.normalize("NFKD").replace(/[^\x20-\x7E]/g, "").replace(/[^A-Za-z0-9._ -]/g, "_").replace(/\s+/g, "_").replace(/_+/g, "_").replace(/^[._-]+|[._-]+$/g, "");
65
+ return `${asciiBase || "document"}${extension || ".pdf"}`;
66
+ }
55
67
  async function readLocalFileFromNode(inputPath) {
56
68
  try {
57
69
  const [fsModule, pathModule] = await Promise.all([
@@ -64,9 +76,35 @@ async function readLocalFileFromNode(inputPath) {
64
76
  fileName: pathModule.basename(inputPath)
65
77
  };
66
78
  } catch (error) {
79
+ const code = typeof error === "object" && error && "code" in error ? String(error.code) : void 0;
80
+ const msg = error instanceof Error ? error.message : String(error);
81
+ if (code === "ENOENT") {
82
+ throw new OkraRuntimeError(
83
+ "INVALID_REQUEST",
84
+ `Local file not found: ${inputPath}`,
85
+ 400,
86
+ error
87
+ );
88
+ }
89
+ if (code === "EACCES" || code === "EPERM") {
90
+ throw new OkraRuntimeError(
91
+ "INVALID_REQUEST",
92
+ `Cannot read local file (${code}): ${inputPath}`,
93
+ 400,
94
+ error
95
+ );
96
+ }
97
+ if (code === "ERR_MODULE_NOT_FOUND" || code === "ERR_UNKNOWN_BUILTIN_MODULE") {
98
+ throw new OkraRuntimeError(
99
+ "INVALID_REQUEST",
100
+ "Local file path uploads are only supported in Node.js. In browser runtimes, pass File/Blob, ArrayBuffer, Uint8Array, or URL.",
101
+ 400,
102
+ error
103
+ );
104
+ }
67
105
  throw new OkraRuntimeError(
68
106
  "INVALID_REQUEST",
69
- "Local file path uploads are only supported in Node.js. In browser runtimes, pass File/Blob, ArrayBuffer, Uint8Array, or URL.",
107
+ `Failed to read local file "${inputPath}": ${msg}`,
70
108
  400,
71
109
  error
72
110
  );
@@ -187,7 +225,7 @@ var OkraClient = class {
187
225
  }
188
226
  if (typeof globalThis !== "undefined" && "window" in globalThis && this.apiKey && !this.apiKey.startsWith("okra_pk_")) {
189
227
  console.warn(
190
- "[OkraPDF] Secret API key detected in browser. Use a publishable key (okra_pk_...) for client-side usage. See https://docs.okrapdf.dev/api-keys#publishable-keys"
228
+ "[OkraPDF] Secret API key detected in browser. Use a publishable key (okra_pk_...) for client-side usage. See https://docs.okrapdf.com/api-keys#publishable-keys"
191
229
  );
192
230
  }
193
231
  this.sessions = {
@@ -224,7 +262,8 @@ var OkraClient = class {
224
262
  this.collections = {
225
263
  list: (signal) => this.collectionList(signal),
226
264
  get: (collectionId, signal) => this.collectionGet(collectionId, signal),
227
- query: (collectionId, prompt, options2) => this.collectionQuery(collectionId, prompt, options2)
265
+ query: (collectionId, prompt, options2) => this.collectionQuery(collectionId, prompt, options2),
266
+ exportMarkdown: (collectionId, options2) => this.collectionExportMarkdown(collectionId, options2)
228
267
  };
229
268
  }
230
269
  // ─── Collections ────────────────────────────────────────────────────────
@@ -377,6 +416,99 @@ var OkraClient = class {
377
416
  };
378
417
  return stream;
379
418
  }
419
+ // ─── Collection Export (markdown from R2) ────────────────────────────────
420
+ collectionExportPath(collectionId, format) {
421
+ return `/v1/collections/${encodeURIComponent(collectionId)}/export?format=${encodeURIComponent(format)}`;
422
+ }
423
+ async collectionExportMarkdown(collectionId, options) {
424
+ let format = "markdown";
425
+ let signal;
426
+ if (options && typeof options === "object" && "aborted" in options) {
427
+ signal = options;
428
+ } else if (options) {
429
+ format = options.format ?? "markdown";
430
+ signal = options.signal;
431
+ }
432
+ const response = await this.rawRequest(
433
+ this.collectionExportPath(collectionId, format),
434
+ { method: "GET", signal }
435
+ );
436
+ if (!response.ok) {
437
+ const text = await response.text();
438
+ throw new OkraRuntimeError("HTTP_ERROR", `Collection export failed: ${text}`, response.status);
439
+ }
440
+ if (format === "zip") {
441
+ const body = await response.arrayBuffer();
442
+ return new Uint8Array(body);
443
+ }
444
+ if (!response.body) {
445
+ throw new OkraRuntimeError("INVALID_RESPONSE", "No response body for collection export", 500);
446
+ }
447
+ const reader = response.body.getReader();
448
+ const decoder = new TextDecoder();
449
+ let buffer = "";
450
+ const documents = [];
451
+ let totalPages = 0;
452
+ let collectionName = "";
453
+ try {
454
+ while (true) {
455
+ const { done, value } = await reader.read();
456
+ if (done) break;
457
+ buffer += decoder.decode(value, { stream: true });
458
+ const lines = buffer.split("\n");
459
+ buffer = lines.pop() || "";
460
+ for (const line of lines) {
461
+ const trimmed = line.trim();
462
+ if (!trimmed) continue;
463
+ try {
464
+ const event = JSON.parse(trimmed);
465
+ if (event.type === "result") {
466
+ documents.push({
467
+ docId: event.doc_id,
468
+ fileName: event.file_name,
469
+ pageCount: event.page_count,
470
+ pages: event.pages
471
+ });
472
+ totalPages += event.page_count;
473
+ }
474
+ } catch {
475
+ }
476
+ }
477
+ }
478
+ const remaining = buffer.trim();
479
+ if (remaining) {
480
+ try {
481
+ const event = JSON.parse(remaining);
482
+ if (event.type === "result") {
483
+ documents.push({
484
+ docId: event.doc_id,
485
+ fileName: event.file_name,
486
+ pageCount: event.page_count,
487
+ pages: event.pages
488
+ });
489
+ totalPages += event.page_count;
490
+ }
491
+ } catch {
492
+ }
493
+ }
494
+ } finally {
495
+ reader.releaseLock();
496
+ }
497
+ try {
498
+ const col = await this.collectionGet(collectionId);
499
+ collectionName = col.name;
500
+ } catch {
501
+ collectionName = collectionId;
502
+ }
503
+ return {
504
+ collectionId,
505
+ collectionName,
506
+ documents,
507
+ totalDocuments: documents.length,
508
+ totalPages,
509
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString()
510
+ };
511
+ }
380
512
  // ─── Upload ──────────────────────────────────────────────────────────────
381
513
  async upload(input, options = {}) {
382
514
  const documentId = options.documentId || makeDocId();
@@ -415,7 +547,7 @@ var OkraClient = class {
415
547
  }
416
548
  const headers = {
417
549
  "Content-Type": "application/pdf",
418
- "X-File-Name": fileName
550
+ "X-File-Name": toHeaderSafeFileName(fileName)
419
551
  };
420
552
  if (options.capabilities) {
421
553
  headers["X-Capabilities"] = JSON.stringify(options.capabilities);
@@ -436,6 +568,66 @@ var OkraClient = class {
436
568
  });
437
569
  return this.sessions.from(documentId);
438
570
  }
571
+ // ─── Workflow Config / Reparse ───────────────────────────────────────────
572
+ async updateConfig(documentId, update, signal) {
573
+ if (!documentId.trim()) {
574
+ throw new OkraRuntimeError("INVALID_REQUEST", "updateConfig requires a non-empty documentId", 400);
575
+ }
576
+ return this.requestJson(
577
+ `/v1/documents/${encodeURIComponent(documentId)}/config`,
578
+ {
579
+ method: "PUT",
580
+ headers: { "Content-Type": "application/json" },
581
+ body: JSON.stringify(update),
582
+ signal
583
+ }
584
+ );
585
+ }
586
+ async reparse(documentId, options = {}) {
587
+ if (!documentId.trim()) {
588
+ throw new OkraRuntimeError("INVALID_REQUEST", "reparse requires a non-empty documentId", 400);
589
+ }
590
+ const strategy = options.strategy && options.strategy !== "auto" ? `?strategy=${encodeURIComponent(options.strategy)}` : "";
591
+ return this.requestJson(
592
+ `/v1/documents/${encodeURIComponent(documentId)}/reparse${strategy}`,
593
+ { method: "POST", signal: options.signal }
594
+ );
595
+ }
596
+ async applyWorkflow(documentId, options) {
597
+ if (!options?.capabilities) {
598
+ throw new OkraRuntimeError("INVALID_REQUEST", "applyWorkflow requires capabilities", 400);
599
+ }
600
+ const config = await this.updateConfig(
601
+ documentId,
602
+ { capabilities: options.capabilities },
603
+ options.signal
604
+ );
605
+ if (options.reparse === false) {
606
+ return { config };
607
+ }
608
+ const reparse = await this.reparse(documentId, {
609
+ strategy: options.strategy,
610
+ signal: options.signal
611
+ });
612
+ return { config, reparse };
613
+ }
614
+ async getKeyWorkflow(signal) {
615
+ return this.requestJson(
616
+ "/v1/key-workflow",
617
+ { method: "GET", signal }
618
+ );
619
+ }
620
+ async setKeyWorkflow(defaultCapabilities, signal) {
621
+ return this.requestJson(
622
+ "/v1/key-workflow",
623
+ {
624
+ method: "PUT",
625
+ headers: { "Content-Type": "application/json" },
626
+ body: JSON.stringify({ default_capabilities: defaultCapabilities }),
627
+ signal
628
+ }
629
+ );
630
+ }
439
631
  // ─── Status / Wait ───────────────────────────────────────────────────────
440
632
  async status(documentId, signal) {
441
633
  return this.requestJson(
@@ -652,6 +844,42 @@ var OkraClient = class {
652
844
  data
653
845
  };
654
846
  }
847
+ // ─── List Documents ─────────────────────────────────────────────────────
848
+ async listDocuments(signal) {
849
+ const res = await this.requestJson(
850
+ "/v1/documents",
851
+ { method: "GET", signal }
852
+ );
853
+ return res.documents;
854
+ }
855
+ // ─── Delete Document ──────────────────────────────────────────────────
856
+ async deleteDocument(documentId, signal) {
857
+ if (!documentId.trim()) {
858
+ throw new OkraRuntimeError("INVALID_REQUEST", "deleteDocument requires a non-empty documentId", 400);
859
+ }
860
+ await this.requestJson(
861
+ `/document/${encodeURIComponent(documentId)}`,
862
+ { method: "DELETE", signal }
863
+ );
864
+ return { deleted: true, documentId };
865
+ }
866
+ // ─── Read Document (full markdown) ────────────────────────────────────
867
+ async read(documentId, options) {
868
+ if (!documentId.trim()) {
869
+ throw new OkraRuntimeError("INVALID_REQUEST", "read requires a non-empty documentId", 400);
870
+ }
871
+ const params = options?.pages ? `?pages=${encodeURIComponent(options.pages)}` : "";
872
+ const response = await this.rawRequest(
873
+ `/v1/documents/${encodeURIComponent(documentId)}/full.md${params}`,
874
+ { method: "GET", signal: options?.signal }
875
+ );
876
+ if (!response.ok) {
877
+ const text = await response.text();
878
+ throw new OkraRuntimeError("HTTP_ERROR", `Read failed: ${text}`, response.status);
879
+ }
880
+ const markdown = await response.text();
881
+ return { documentId, markdown };
882
+ }
655
883
  // ─── Model Endpoint ──────────────────────────────────────────────────────
656
884
  modelEndpoint(documentId) {
657
885
  return `${this.baseUrl}/v1/documents/${encodeURIComponent(documentId)}`;
@@ -750,4 +978,4 @@ var OkraClient = class {
750
978
  export {
751
979
  OkraClient
752
980
  };
753
- //# sourceMappingURL=chunk-XM4MS5WV.js.map
981
+ //# sourceMappingURL=chunk-2VKGPLAA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { z, type ZodType } from 'zod';\nimport { OkraRuntimeError, StructuredOutputError } from './errors';\nimport type {\n OkraClientOptions,\n Collection,\n CollectionExportFormat,\n CollectionExportOptions,\n CollectionExportEvent,\n CollectionMarkdownExport,\n CollectionQueryEvent,\n CollectionQueryOptions,\n CollectionQueryResult,\n CollectionQueryStream,\n CollectionSummary,\n CompletionEvent,\n CompletionOptions,\n DeleteDocumentResult,\n DocumentAnswer,\n DocumentConfigResult,\n DocumentConfigUpdate,\n DocumentListItem,\n DocumentListResponse,\n DocumentMarkdownExport,\n DocumentStatus,\n EntitiesResponse,\n GenerateOptions,\n GenerateResult,\n JsonSchema,\n LogEntry,\n LogsOptions,\n MarkdownPage,\n Page,\n PublishResult,\n QueryResult,\n ReadDocumentOptions,\n ReadDocumentResult,\n ReparseOptions,\n ReparseResult,\n RuntimeErrorCode,\n ShareLinkOptions,\n ShareLinkResult,\n SessionAttachOptions,\n SessionCreateOptions,\n SessionState,\n OkraSession,\n StructuredOutputErrorCode,\n StructuredSchema,\n ApiKeyWorkflowConfigResponse,\n ApplyWorkflowOptions,\n ApplyWorkflowResult,\n UploadInput,\n UploadOptions,\n WaitOptions,\n} from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.okrapdf.com';\nconst DEFAULT_WAIT_TIMEOUT_MS = 5 * 60_000;\nconst DEFAULT_WAIT_POLL_MS = 1_500;\nconst COMPLETE_PHASES = new Set(['complete', 'awaiting_review']);\nconst TERMINAL_ERROR_PHASES = new Set(['error']);\nconst STRUCTURED_CODES = new Set<StructuredOutputErrorCode>([\n 'SCHEMA_VALIDATION_FAILED',\n 'EXTRACTION_FAILED',\n 'TIMEOUT',\n 'DOCUMENT_NOT_FOUND',\n]);\nconst NODE_FS_PROMISES_SPECIFIER = `node:${'fs/promises'}`;\nconst NODE_PATH_SPECIFIER = `node:${'path'}`;\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction isHttpUrl(value: string): boolean {\n return /^https?:\\/\\//i.test(value);\n}\n\nfunction isDocumentId(value: string): boolean {\n return /^(?:ocr|doc)-[A-Za-z0-9_-]+$/.test(value);\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, '');\n}\n\nfunction makeDocId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return `doc-${crypto.randomUUID().replace(/-/g, '').slice(0, 20)}`;\n }\n const rand = Math.random().toString(36).slice(2, 22);\n return `doc-${rand}`;\n}\n\nfunction toUint8Array(input: ArrayBuffer | Uint8Array): Uint8Array {\n if (input instanceof Uint8Array) return input;\n return new Uint8Array(input);\n}\n\ninterface NodeFsModule {\n readFile(path: string): Promise<ArrayBuffer | Uint8Array>;\n}\n\ninterface NodePathModule {\n basename(path: string): string;\n}\n\ninterface NamedBlob extends Blob {\n name?: string;\n}\n\nfunction isBlobLike(input: unknown): input is Blob {\n if (typeof Blob !== 'undefined' && input instanceof Blob) return true;\n return !!input\n && typeof input === 'object'\n && typeof (input as { arrayBuffer?: unknown }).arrayBuffer === 'function';\n}\n\nfunction inferBlobName(input: Blob, fallback: string): string {\n const named = input as NamedBlob;\n if (typeof named.name === 'string' && named.name.trim() !== '') {\n return named.name;\n }\n return fallback;\n}\n\nfunction toHeaderSafeFileName(fileName: string): string {\n const leaf = fileName.split(/[\\\\/]/).pop() || fileName;\n const cleaned = leaf.replace(/[\\r\\n]/g, ' ').trim();\n\n if (/^[\\x20-\\x7E]+$/.test(cleaned)) {\n return cleaned;\n }\n\n const extMatch = cleaned.match(/(\\.[A-Za-z0-9]{1,10})$/);\n const extension = extMatch?.[1].toLowerCase() ?? '';\n const base = extension ? cleaned.slice(0, -extension.length) : cleaned;\n\n const asciiBase = base\n .normalize('NFKD')\n .replace(/[^\\x20-\\x7E]/g, '')\n .replace(/[^A-Za-z0-9._ -]/g, '_')\n .replace(/\\s+/g, '_')\n .replace(/_+/g, '_')\n .replace(/^[._-]+|[._-]+$/g, '');\n\n return `${asciiBase || 'document'}${extension || '.pdf'}`;\n}\n\nasync function readLocalFileFromNode(inputPath: string): Promise<{ bytes: Uint8Array; fileName: string }> {\n try {\n const [fsModule, pathModule] = await Promise.all([\n import(NODE_FS_PROMISES_SPECIFIER) as Promise<NodeFsModule>,\n import(NODE_PATH_SPECIFIER) as Promise<NodePathModule>,\n ]);\n const raw = await fsModule.readFile(inputPath);\n return {\n bytes: toUint8Array(raw),\n fileName: pathModule.basename(inputPath),\n };\n } catch (error) {\n const code = typeof error === 'object' && error && 'code' in error\n ? String((error as { code?: unknown }).code)\n : undefined;\n const msg = error instanceof Error ? error.message : String(error);\n\n if (code === 'ENOENT') {\n throw new OkraRuntimeError(\n 'INVALID_REQUEST',\n `Local file not found: ${inputPath}`,\n 400,\n error,\n );\n }\n\n if (code === 'EACCES' || code === 'EPERM') {\n throw new OkraRuntimeError(\n 'INVALID_REQUEST',\n `Cannot read local file (${code}): ${inputPath}`,\n 400,\n error,\n );\n }\n\n if (code === 'ERR_MODULE_NOT_FOUND' || code === 'ERR_UNKNOWN_BUILTIN_MODULE') {\n throw new OkraRuntimeError(\n 'INVALID_REQUEST',\n 'Local file path uploads are only supported in Node.js. In browser runtimes, pass File/Blob, ArrayBuffer, Uint8Array, or URL.',\n 400,\n error,\n );\n }\n\n throw new OkraRuntimeError(\n 'INVALID_REQUEST',\n `Failed to read local file \"${inputPath}\": ${msg}`,\n 400,\n error,\n );\n }\n}\n\ninterface StructuredErrorEnvelope {\n code?: string;\n message?: string;\n details?: unknown;\n error?: string;\n}\n\ninterface NormalizedSchema<T> {\n jsonSchema: JsonSchema;\n parser?: ZodType<T>;\n}\n\nfunction normalizeSchema<T>(schema: StructuredSchema<T>): NormalizedSchema<T> {\n const maybeZod = schema as ZodType<T>;\n const hasSafeParse = typeof (maybeZod as { safeParse?: unknown }).safeParse === 'function';\n if (hasSafeParse) {\n return {\n jsonSchema: z.toJSONSchema(maybeZod, { target: 'draft-2020-12' }) as JsonSchema,\n parser: maybeZod,\n };\n }\n return { jsonSchema: schema as JsonSchema };\n}\n\nfunction isStructuredCode(code: string | undefined): code is StructuredOutputErrorCode {\n return !!code && STRUCTURED_CODES.has(code as StructuredOutputErrorCode);\n}\n\n// ─── Session Handle ──────────────────────────────────────────────────────────\n\nclass OkraSessionHandle implements OkraSession {\n readonly id: string;\n readonly modelEndpoint: string;\n #model?: string;\n #client: OkraClient;\n\n constructor(client: OkraClient, documentId: string, model?: string) {\n this.#client = client;\n this.id = documentId;\n this.modelEndpoint = client.modelEndpoint(documentId);\n this.#model = model;\n }\n\n get model(): string | undefined {\n return this.#model;\n }\n\n state(): SessionState {\n return {\n id: this.id,\n model: this.#model,\n modelEndpoint: this.modelEndpoint,\n };\n }\n\n async setModel(model: string): Promise<void> {\n const normalized = model.trim();\n if (!normalized) {\n throw new OkraRuntimeError('INVALID_REQUEST', 'session.setModel requires a non-empty model', 400);\n }\n this.#model = normalized;\n }\n\n status(signal?: AbortSignal): Promise<DocumentStatus> {\n return this.#client.status(this.id, signal);\n }\n\n wait(options?: WaitOptions): Promise<DocumentStatus> {\n return this.#client.wait(this.id, options);\n }\n\n pages(options?: { range?: string; signal?: AbortSignal }): Promise<Page[]> {\n return this.#client.pages(this.id, options);\n }\n\n page(pageNumber: number, signal?: AbortSignal): Promise<Page> {\n return this.#client.page(this.id, pageNumber, signal);\n }\n\n entities(options?: { type?: string; limit?: number; offset?: number; signal?: AbortSignal }): Promise<EntitiesResponse> {\n return this.#client.entities(this.id, options);\n }\n\n downloadUrl(): string {\n return this.#client.downloadUrl(this.id);\n }\n\n query(sql: string, signal?: AbortSignal): Promise<QueryResult> {\n return this.#client.query(this.id, sql, signal);\n }\n\n logs(options?: LogsOptions): Promise<LogEntry[]> {\n return this.#client.logs(this.id, options);\n }\n\n publish(signal?: AbortSignal): Promise<PublishResult> {\n return this.#client.publish(this.id, signal);\n }\n\n shareLink(options?: ShareLinkOptions): Promise<ShareLinkResult> {\n return this.#client.shareLink(this.id, options);\n }\n\n prompt(\n query: string,\n options?: GenerateOptions & { schema?: undefined },\n ): Promise<GenerateResult>;\n prompt<T>(\n query: string,\n options: GenerateOptions & { schema: StructuredSchema<T> },\n ): Promise<GenerateResult<T>>;\n prompt<T = undefined>(\n query: string,\n options?: GenerateOptions,\n ): Promise<GenerateResult<T>> {\n const model = options?.model ?? this.#model;\n const merged = model ? { ...options, model } : options;\n if (merged?.schema !== undefined) {\n return this.#client.generate(\n this.id,\n query,\n merged as GenerateOptions & { schema: StructuredSchema<unknown> },\n ) as Promise<GenerateResult<T>>;\n }\n return this.#client.generate(\n this.id,\n query,\n merged as GenerateOptions & { schema?: undefined },\n ) as Promise<GenerateResult<T>>;\n }\n\n stream(\n query: string,\n options?: CompletionOptions,\n ): AsyncGenerator<CompletionEvent> {\n const model = options?.model ?? this.#model;\n const merged = model ? { ...options, model } : options;\n return this.#client.stream(this.id, query, merged);\n }\n}\n\n// ─── Client ──────────────────────────────────────────────────────────────────\n\nexport class OkraClient {\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n private readonly sharedSecret?: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n readonly sessions: {\n create: (sourceOrDocId: UploadInput, options?: SessionCreateOptions) => Promise<OkraSession>;\n from: (documentId: string, options?: SessionAttachOptions) => OkraSession;\n };\n readonly collections: {\n list: (signal?: AbortSignal) => Promise<CollectionSummary[]>;\n get: (collectionId: string, signal?: AbortSignal) => Promise<Collection>;\n query: <T = undefined>(\n collectionId: string,\n prompt: string,\n options?: CollectionQueryOptions<T>,\n ) => CollectionQueryStream<T>;\n exportMarkdown: (\n collectionId: string,\n options?: AbortSignal | CollectionExportOptions,\n ) => Promise<CollectionMarkdownExport | Uint8Array>;\n };\n constructor(options: OkraClientOptions) {\n this.baseUrl = normalizeBaseUrl(options.baseUrl || DEFAULT_BASE_URL);\n this.apiKey = options.apiKey;\n this.sharedSecret = options.sharedSecret;\n this.fetchImpl = options.fetch || globalThis.fetch.bind(globalThis);\n\n if (!this.apiKey && !this.sharedSecret) {\n throw new OkraRuntimeError(\n 'UNAUTHORIZED',\n 'OkraClient requires either apiKey or sharedSecret',\n 401,\n );\n }\n\n if (\n typeof globalThis !== 'undefined' && 'window' in globalThis\n && this.apiKey\n && !this.apiKey.startsWith('okra_pk_')\n ) {\n console.warn(\n '[OkraPDF] Secret API key detected in browser. Use a publishable key (okra_pk_...) for client-side usage. ' +\n 'See https://docs.okrapdf.com/api-keys#publishable-keys',\n );\n }\n\n this.sessions = {\n create: async (sourceOrDocId, sessionOptions = {}) => {\n let documentId: string;\n if (typeof sourceOrDocId === 'string' && isDocumentId(sourceOrDocId.trim())) {\n documentId = sourceOrDocId.trim();\n } else {\n const session = await this.upload(sourceOrDocId, sessionOptions.upload);\n documentId = session.id;\n }\n\n const session = this.sessions.from(documentId, { model: sessionOptions.model });\n if (sessionOptions.wait ?? true) {\n await session.wait(sessionOptions.waitOptions);\n }\n return session;\n },\n from: (documentId, sessionOptions = {}) => {\n const normalized = documentId.trim();\n if (!normalized) {\n throw new OkraRuntimeError(\n 'INVALID_REQUEST',\n 'sessions.from requires a non-empty documentId',\n 400,\n );\n }\n\n return new OkraSessionHandle(\n this,\n normalized,\n sessionOptions.model?.trim() || undefined,\n );\n },\n };\n\n this.collections = {\n list: (signal) => this.collectionList(signal),\n get: (collectionId, signal) => this.collectionGet(collectionId, signal),\n query: <T = undefined>(collectionId: string, prompt: string, options?: CollectionQueryOptions<T>) =>\n this.collectionQuery<T>(collectionId, prompt, options),\n exportMarkdown: (collectionId, options?) => this.collectionExportMarkdown(collectionId, options),\n };\n }\n\n // ─── Collections ────────────────────────────────────────────────────────\n\n private async collectionList(signal?: AbortSignal): Promise<CollectionSummary[]> {\n const res = await this.requestJson<{ collections: CollectionSummary[] }>(\n '/v1/collections',\n { method: 'GET', signal },\n );\n return res.collections;\n }\n\n private async collectionGet(collectionId: string, signal?: AbortSignal): Promise<Collection> {\n return this.requestJson<Collection>(\n `/v1/collections/${encodeURIComponent(collectionId)}`,\n { method: 'GET', signal },\n );\n }\n\n private collectionQuery<T = undefined>(\n collectionId: string,\n prompt: string,\n options?: CollectionQueryOptions<T>,\n ): CollectionQueryStream<T> {\n const ac = new AbortController();\n if (options?.signal) {\n options.signal.addEventListener('abort', () => ac.abort(), { once: true });\n }\n\n const body: Record<string, unknown> = { prompt, stream: true };\n if (options?.schema) {\n const normalized = normalizeSchema(options.schema);\n body.response_format = {\n type: 'json_schema',\n json_schema: { name: 'result', schema: normalized.jsonSchema },\n };\n }\n if (options?.docIds) {\n body.doc_ids = options.docIds;\n }\n\n const responsePromise = this.rawRequest(\n `/v1/collections/${encodeURIComponent(collectionId)}/query`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: ac.signal,\n },\n );\n\n async function* iterateNdjson(): AsyncGenerator<CollectionQueryEvent> {\n const response = await responsePromise;\n if (!response.ok) {\n const text = await response.text();\n throw new OkraRuntimeError('HTTP_ERROR', `Collection query failed: ${text}`, response.status);\n }\n if (!response.body) {\n throw new OkraRuntimeError('INVALID_RESPONSE', 'No response body for collection query', 500);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n yield JSON.parse(trimmed) as CollectionQueryEvent;\n } catch {\n // skip malformed lines\n }\n }\n }\n\n // flush remaining buffer\n const remaining = buffer.trim();\n if (remaining) {\n try {\n yield JSON.parse(remaining) as CollectionQueryEvent;\n } catch {\n // skip\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n // Tee the generator so gather() and iteration don't conflict\n let iteratorInstance: AsyncGenerator<CollectionQueryEvent> | null = null;\n function getIterator(): AsyncGenerator<CollectionQueryEvent> {\n if (!iteratorInstance) iteratorInstance = iterateNdjson();\n return iteratorInstance;\n }\n\n const stream: CollectionQueryStream<T> = {\n [Symbol.asyncIterator]() {\n return getIterator();\n },\n\n async gather(): Promise<CollectionQueryResult<T>> {\n const startTime = Date.now();\n const answers = new Map<string, DocumentAnswer<T>>();\n let queryId = '';\n let queryPrompt = prompt;\n let totalCostUsd = 0;\n let completed = 0;\n let failed = 0;\n\n for await (const event of getIterator()) {\n if (event.type === 'start') {\n queryId = event.query_id;\n queryPrompt = event.prompt;\n } else if (event.type === 'result') {\n answers.set(event.doc_id, {\n docId: event.doc_id,\n status: event.status,\n answer: event.answer,\n data: event.data as T | undefined,\n costUsd: event.usage?.cost_usd ?? 0,\n durationMs: event.duration_ms,\n error: event.error,\n });\n } else if (event.type === 'done') {\n totalCostUsd = event.total_cost_usd;\n completed = event.completed;\n failed = event.failed;\n } else if (event.type === 'error') {\n throw new OkraRuntimeError('HTTP_ERROR', event.error, 500);\n }\n }\n\n return {\n queryId,\n prompt: queryPrompt,\n answers,\n totalCostUsd,\n durationMs: Date.now() - startTime,\n completed,\n failed,\n };\n },\n\n abort() {\n ac.abort();\n },\n\n toReadableStream(): ReadableStream<Uint8Array> {\n // Return raw body — lazy, only fetched if called before iteration\n const encoder = new TextEncoder();\n const iter = getIterator();\n return new ReadableStream({\n async pull(controller) {\n const { done, value } = await iter.next();\n if (done) {\n controller.close();\n } else {\n controller.enqueue(encoder.encode(JSON.stringify(value) + '\\n'));\n }\n },\n cancel() {\n ac.abort();\n },\n });\n },\n };\n\n return stream;\n }\n\n // ─── Collection Export (markdown from R2) ────────────────────────────────\n\n private collectionExportPath(collectionId: string, format: CollectionExportFormat): string {\n return `/v1/collections/${encodeURIComponent(collectionId)}/export?format=${encodeURIComponent(format)}`;\n }\n\n private async collectionExportMarkdown(\n collectionId: string,\n options?: AbortSignal | CollectionExportOptions,\n ): Promise<CollectionMarkdownExport | Uint8Array> {\n let format: CollectionExportFormat = 'markdown';\n let signal: AbortSignal | undefined;\n\n if (options && typeof options === 'object' && 'aborted' in options) {\n signal = options as AbortSignal;\n } else if (options) {\n format = options.format ?? 'markdown';\n signal = options.signal;\n }\n\n const response = await this.rawRequest(\n this.collectionExportPath(collectionId, format),\n { method: 'GET', signal },\n );\n\n if (!response.ok) {\n const text = await response.text();\n throw new OkraRuntimeError('HTTP_ERROR', `Collection export failed: ${text}`, response.status);\n }\n\n if (format === 'zip') {\n const body = await response.arrayBuffer();\n return new Uint8Array(body);\n }\n\n if (!response.body) {\n throw new OkraRuntimeError('INVALID_RESPONSE', 'No response body for collection export', 500);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n const documents: DocumentMarkdownExport[] = [];\n let totalPages = 0;\n let collectionName = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const event = JSON.parse(trimmed) as CollectionExportEvent;\n if (event.type === 'result') {\n documents.push({\n docId: event.doc_id,\n fileName: event.file_name,\n pageCount: event.page_count,\n pages: event.pages,\n });\n totalPages += event.page_count;\n }\n } catch {\n // skip malformed lines\n }\n }\n }\n\n // flush remaining buffer\n const remaining = buffer.trim();\n if (remaining) {\n try {\n const event = JSON.parse(remaining) as CollectionExportEvent;\n if (event.type === 'result') {\n documents.push({\n docId: event.doc_id,\n fileName: event.file_name,\n pageCount: event.page_count,\n pages: event.pages,\n });\n totalPages += event.page_count;\n }\n } catch {\n // skip\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n // Try to get collection name from metadata\n try {\n const col = await this.collectionGet(collectionId);\n collectionName = col.name;\n } catch {\n collectionName = collectionId;\n }\n\n return {\n collectionId,\n collectionName,\n documents,\n totalDocuments: documents.length,\n totalPages,\n exportedAt: new Date().toISOString(),\n };\n }\n\n // ─── Upload ──────────────────────────────────────────────────────────────\n\n async upload(input: UploadInput, options: UploadOptions = {}): Promise<OkraSession> {\n const documentId = options.documentId || makeDocId();\n const path = `/document/${encodeURIComponent(documentId)}`;\n const visibility = options.visibility || 'private';\n\n if (typeof input === 'string' && isHttpUrl(input)) {\n const urlHeaders: Record<string, string> = { 'Content-Type': 'application/json' };\n if (options.vendorKeys) {\n urlHeaders['X-Vendor-Keys'] = JSON.stringify(options.vendorKeys);\n }\n await this.requestJson<{ phase?: string }>(`${path}/upload-url`, {\n method: 'POST',\n headers: urlHeaders,\n body: JSON.stringify({\n url: input,\n capabilities: options.capabilities,\n visibility,\n redact: options.redact,\n }),\n });\n return this.sessions.from(documentId);\n }\n\n let bytes: Uint8Array;\n let fileName = options.fileName || 'document.pdf';\n if (typeof input === 'string') {\n const local = await readLocalFileFromNode(input);\n bytes = local.bytes;\n if (!options.fileName) fileName = local.fileName;\n } else if (isBlobLike(input)) {\n bytes = toUint8Array(await input.arrayBuffer());\n if (!options.fileName) {\n fileName = inferBlobName(input, fileName);\n }\n } else {\n bytes = toUint8Array(input);\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/pdf',\n 'X-File-Name': toHeaderSafeFileName(fileName),\n };\n if (options.capabilities) {\n headers['X-Capabilities'] = JSON.stringify(options.capabilities);\n }\n if (options.vendorKeys) {\n headers['X-Vendor-Keys'] = JSON.stringify(options.vendorKeys);\n }\n if (options.redact) {\n headers['X-Redact'] = JSON.stringify(options.redact);\n }\n if (visibility === 'public') {\n headers['X-Visibility'] = 'public';\n }\n\n await this.requestJson<{ phase?: string }>(`${path}/upload`, {\n method: 'POST',\n headers,\n body: bytes as unknown as BodyInit,\n });\n\n return this.sessions.from(documentId);\n }\n\n // ─── Workflow Config / Reparse ───────────────────────────────────────────\n\n async updateConfig(\n documentId: string,\n update: DocumentConfigUpdate,\n signal?: AbortSignal,\n ): Promise<DocumentConfigResult> {\n if (!documentId.trim()) {\n throw new OkraRuntimeError('INVALID_REQUEST', 'updateConfig requires a non-empty documentId', 400);\n }\n return this.requestJson<DocumentConfigResult>(\n `/v1/documents/${encodeURIComponent(documentId)}/config`,\n {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(update),\n signal,\n },\n );\n }\n\n async reparse(\n documentId: string,\n options: ReparseOptions = {},\n ): Promise<ReparseResult> {\n if (!documentId.trim()) {\n throw new OkraRuntimeError('INVALID_REQUEST', 'reparse requires a non-empty documentId', 400);\n }\n const strategy = options.strategy && options.strategy !== 'auto'\n ? `?strategy=${encodeURIComponent(options.strategy)}`\n : '';\n return this.requestJson<ReparseResult>(\n `/v1/documents/${encodeURIComponent(documentId)}/reparse${strategy}`,\n { method: 'POST', signal: options.signal },\n );\n }\n\n async applyWorkflow(\n documentId: string,\n options: ApplyWorkflowOptions,\n ): Promise<ApplyWorkflowResult> {\n if (!options?.capabilities) {\n throw new OkraRuntimeError('INVALID_REQUEST', 'applyWorkflow requires capabilities', 400);\n }\n\n const config = await this.updateConfig(\n documentId,\n { capabilities: options.capabilities },\n options.signal,\n );\n\n if (options.reparse === false) {\n return { config };\n }\n\n const reparse = await this.reparse(documentId, {\n strategy: options.strategy,\n signal: options.signal,\n });\n return { config, reparse };\n }\n\n async getKeyWorkflow(signal?: AbortSignal): Promise<ApiKeyWorkflowConfigResponse> {\n return this.requestJson<ApiKeyWorkflowConfigResponse>(\n '/v1/key-workflow',\n { method: 'GET', signal },\n );\n }\n\n async setKeyWorkflow(\n defaultCapabilities: ApiKeyWorkflowConfigResponse['default_capabilities'],\n signal?: AbortSignal,\n ): Promise<ApiKeyWorkflowConfigResponse> {\n return this.requestJson<ApiKeyWorkflowConfigResponse>(\n '/v1/key-workflow',\n {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ default_capabilities: defaultCapabilities }),\n signal,\n },\n );\n }\n\n // ─── Status / Wait ───────────────────────────────────────────────────────\n\n async status(documentId: string, signal?: AbortSignal): Promise<DocumentStatus> {\n return this.requestJson<DocumentStatus>(\n `/document/${encodeURIComponent(documentId)}/status`,\n { method: 'GET', signal },\n );\n }\n\n async wait(documentId: string, options: WaitOptions = {}): Promise<DocumentStatus> {\n const startedAt = Date.now();\n const timeoutMs = options.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_WAIT_POLL_MS;\n\n while (true) {\n if (options.signal?.aborted) {\n throw new OkraRuntimeError('TIMEOUT', 'Wait aborted', 499);\n }\n\n const current = await this.status(documentId, options.signal);\n if (COMPLETE_PHASES.has(current.phase)) {\n return current;\n }\n if (TERMINAL_ERROR_PHASES.has(current.phase)) {\n throw new OkraRuntimeError(\n 'EXTRACTION_FAILED',\n `Document entered terminal error phase (${current.phase})`,\n 500,\n current,\n );\n }\n\n const elapsed = Date.now() - startedAt;\n if (elapsed >= timeoutMs) {\n throw new OkraRuntimeError(\n 'TIMEOUT',\n `Timed out waiting for document ${documentId} after ${timeoutMs}ms`,\n 504,\n current,\n );\n }\n\n await sleep(pollIntervalMs);\n }\n }\n\n // ─── Pages ───────────────────────────────────────────────────────────────\n\n async pages(documentId: string, options?: { range?: string; signal?: AbortSignal }): Promise<Page[]> {\n const params = options?.range ? `?range=${encodeURIComponent(options.range)}` : '';\n return this.requestJson<Page[]>(\n `/document/${encodeURIComponent(documentId)}/pages${params}`,\n { method: 'GET', signal: options?.signal },\n );\n }\n\n async page(documentId: string, pageNumber: number, signal?: AbortSignal): Promise<Page> {\n return this.requestJson<Page>(\n `/document/${encodeURIComponent(documentId)}/page/${pageNumber}`,\n { method: 'GET', signal },\n );\n }\n\n // ─── Download ──────────────────────────────────────────────────────────\n\n downloadUrl(documentId: string): string {\n return `${this.baseUrl}/document/${encodeURIComponent(documentId)}/download`;\n }\n\n // ─── Entities ────────────────────────────────────────────────────────────\n\n async entities(\n documentId: string,\n options?: { type?: string; limit?: number; offset?: number; signal?: AbortSignal },\n ): Promise<EntitiesResponse> {\n const params = new URLSearchParams();\n if (options?.type) params.set('type', options.type);\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.offset) params.set('offset', String(options.offset));\n const qs = params.toString();\n return this.requestJson<EntitiesResponse>(\n `/document/${encodeURIComponent(documentId)}/nodes${qs ? `?${qs}` : ''}`,\n { method: 'GET', signal: options?.signal },\n );\n }\n\n // ─── Query (SQL) ─────────────────────────────────────────────────────────\n\n async query(documentId: string, sql: string, signal?: AbortSignal): Promise<QueryResult> {\n return this.requestJson<QueryResult>(\n `/document/${encodeURIComponent(documentId)}/query?select=${encodeURIComponent(sql)}`,\n { method: 'GET', signal },\n );\n }\n\n // ─── Logs ───────────────────────────────────────────────────────────────\n\n async logs(documentId: string, options?: LogsOptions): Promise<LogEntry[]> {\n const limit = options?.limit ?? 100;\n const res = await this.requestJson<{ entries: LogEntry[] }>(\n `/document/${encodeURIComponent(documentId)}/log?limit=${limit}`,\n { method: 'GET', signal: options?.signal },\n );\n return res.entries;\n }\n\n // ─── Stream (streaming completion via OpenAI SSE) ────────────────────────\n\n async *stream(\n documentId: string,\n query: string,\n options?: CompletionOptions,\n ): AsyncGenerator<CompletionEvent> {\n const response = await this.rawRequest(\n `/document/${encodeURIComponent(documentId)}/chat/completions`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: [{ role: 'user', content: query }],\n stream: options?.stream !== false,\n ...(options?.model ? { model: options.model } : {}),\n }),\n signal: options?.signal,\n },\n );\n\n if (!response.ok) {\n const text = await response.text();\n throw new OkraRuntimeError('HTTP_ERROR', `Completion failed: ${text}`, response.status);\n }\n\n if (!response.body) {\n throw new OkraRuntimeError('INVALID_RESPONSE', 'No response body for completion stream', 500);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let fullText = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (!trimmed.startsWith('data: ')) continue;\n const json = trimmed.slice(6);\n try {\n const chunk = JSON.parse(json) as {\n choices?: Array<{ delta?: { content?: string }; finish_reason?: string | null }>;\n usage?: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number };\n error?: { message?: string };\n };\n\n if (chunk.error) {\n yield { type: 'error', message: chunk.error.message || 'Stream error' };\n continue;\n }\n\n const delta = chunk.choices?.[0]?.delta?.content;\n if (delta) {\n fullText += delta;\n yield { type: 'text_delta', text: delta };\n }\n\n if (chunk.choices?.[0]?.finish_reason === 'stop') {\n yield { type: 'done', answer: fullText };\n }\n } catch {\n // skip malformed lines\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n // ─── Generate (non-streaming AI) ─────────────────────────────────────────\n\n async generate(\n documentId: string,\n query: string,\n options?: GenerateOptions & { schema?: undefined },\n ): Promise<GenerateResult>;\n async generate<T>(\n documentId: string,\n query: string,\n options: GenerateOptions & { schema: StructuredSchema<T> },\n ): Promise<GenerateResult<T>>;\n async generate<T = undefined>(\n documentId: string,\n query: string,\n options?: GenerateOptions,\n ): Promise<GenerateResult<T>> {\n if (options?.schema) {\n return this.generateStructured<T>(documentId, query, options);\n }\n\n const result = await this.requestJson<{\n id: string;\n choices: Array<{ message: { content: string } }>;\n usage?: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number };\n }>(\n `/document/${encodeURIComponent(documentId)}/chat/completions`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: [{ role: 'user', content: query }],\n ...(options?.model ? { model: options.model } : {}),\n }),\n signal: options?.signal,\n },\n );\n\n return {\n answer: result.choices?.[0]?.message?.content || '',\n };\n }\n\n private async generateStructured<T>(\n documentId: string,\n query: string,\n options: GenerateOptions,\n ): Promise<GenerateResult<T>> {\n if (!query || query.trim() === '') {\n throw new OkraRuntimeError('INVALID_REQUEST', 'generate with schema requires a non-empty query', 400);\n }\n\n const normalized = normalizeSchema(options.schema as StructuredSchema<T>);\n const result = await this.requestJson<{\n id: string;\n choices: Array<{ message: { content: string } }>;\n usage?: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number };\n }>(\n `/document/${encodeURIComponent(documentId)}/chat/completions`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: [{ role: 'user', content: query }],\n response_format: {\n type: 'json_schema',\n json_schema: { name: 'result', schema: normalized.jsonSchema },\n },\n ...(options.model ? { model: options.model } : {}),\n }),\n signal: options.signal,\n },\n );\n\n const raw = result.choices?.[0]?.message?.content;\n if (!raw) {\n throw new OkraRuntimeError('INVALID_RESPONSE', 'No content in structured output response', 500);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new OkraRuntimeError('INVALID_RESPONSE', 'Structured output response is not valid JSON', 500);\n }\n\n let data: T;\n if (normalized.parser) {\n const zodResult = normalized.parser.safeParse(parsed);\n if (!zodResult.success) {\n throw new StructuredOutputError(\n 'SCHEMA_VALIDATION_FAILED',\n 'Client-side schema validation failed for structured output response',\n 422,\n zodResult.error.issues,\n );\n }\n data = zodResult.data;\n } else {\n data = parsed as T;\n }\n\n return {\n answer: '',\n data,\n };\n }\n\n // ─── List Documents ─────────────────────────────────────────────────────\n\n async listDocuments(signal?: AbortSignal): Promise<DocumentListItem[]> {\n const res = await this.requestJson<DocumentListResponse>(\n '/v1/documents',\n { method: 'GET', signal },\n );\n return res.documents;\n }\n\n // ─── Delete Document ──────────────────────────────────────────────────\n\n async deleteDocument(documentId: string, signal?: AbortSignal): Promise<DeleteDocumentResult> {\n if (!documentId.trim()) {\n throw new OkraRuntimeError('INVALID_REQUEST', 'deleteDocument requires a non-empty documentId', 400);\n }\n await this.requestJson<{ ok: boolean }>(\n `/document/${encodeURIComponent(documentId)}`,\n { method: 'DELETE', signal },\n );\n return { deleted: true, documentId };\n }\n\n // ─── Read Document (full markdown) ────────────────────────────────────\n\n async read(documentId: string, options?: ReadDocumentOptions): Promise<ReadDocumentResult> {\n if (!documentId.trim()) {\n throw new OkraRuntimeError('INVALID_REQUEST', 'read requires a non-empty documentId', 400);\n }\n const params = options?.pages ? `?pages=${encodeURIComponent(options.pages)}` : '';\n const response = await this.rawRequest(\n `/v1/documents/${encodeURIComponent(documentId)}/full.md${params}`,\n { method: 'GET', signal: options?.signal },\n );\n if (!response.ok) {\n const text = await response.text();\n throw new OkraRuntimeError('HTTP_ERROR', `Read failed: ${text}`, response.status);\n }\n const markdown = await response.text();\n return { documentId, markdown };\n }\n\n // ─── Model Endpoint ──────────────────────────────────────────────────────\n\n modelEndpoint(documentId: string): string {\n return `${this.baseUrl}/v1/documents/${encodeURIComponent(documentId)}`;\n }\n\n // ─── Publish / Share ────────────────────────────────────────────────────\n\n async publish(documentId: string, signal?: AbortSignal): Promise<PublishResult> {\n const result = await this.requestJson<Omit<PublishResult, 'url'>>(\n `/document/${encodeURIComponent(documentId)}/publish`,\n { method: 'POST', signal },\n );\n return {\n ...result,\n url: `${this.baseUrl}/v1/documents/${encodeURIComponent(documentId)}`,\n };\n }\n\n async shareLink(documentId: string, options?: ShareLinkOptions): Promise<ShareLinkResult> {\n return this.requestJson<ShareLinkResult>(\n `/document/${encodeURIComponent(documentId)}/share-link`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n role: options?.role,\n label: options?.label,\n expiresInMs: options?.expiresInMs,\n maxViews: options?.maxViews,\n }),\n signal: options?.signal,\n },\n );\n }\n\n // ─── Public HTTP ─────────────────────────────────────────────────────────\n\n async request<T>(path: string, init: RequestInit = {}): Promise<T> {\n return this.requestJson<T>(path, init);\n }\n\n get url(): string {\n return this.baseUrl;\n }\n\n // ─── Internal HTTP ───────────────────────────────────────────────────────\n\n private authHeaders(): Record<string, string> {\n if (this.apiKey) return { Authorization: `Bearer ${this.apiKey}` };\n if (this.sharedSecret) return { 'x-document-agent-secret': this.sharedSecret };\n return {};\n }\n\n private async rawRequest(path: string, init: RequestInit): Promise<Response> {\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(this.authHeaders())) {\n if (!headers.has(key)) headers.set(key, value);\n }\n\n try {\n return await this.fetchImpl(`${this.baseUrl}${path}`, { ...init, headers });\n } catch (err) {\n throw new OkraRuntimeError(\n 'HTTP_ERROR',\n err instanceof Error ? err.message : String(err),\n 502,\n );\n }\n }\n\n private async requestJson<T>(path: string, init: RequestInit): Promise<T> {\n const response = await this.rawRequest(path, init);\n const text = await response.text();\n const parsed = this.parseBody(text);\n\n if (!response.ok) {\n const envelope = parsed as StructuredErrorEnvelope | null;\n const code = envelope?.code;\n const message = envelope?.message || envelope?.error || `Request failed with status ${response.status}`;\n const details = envelope?.details ?? parsed ?? text;\n if (isStructuredCode(code)) {\n throw new StructuredOutputError(code, message, response.status, details);\n }\n const runtimeCode: RuntimeErrorCode = response.status === 401 ? 'UNAUTHORIZED' : 'HTTP_ERROR';\n throw new OkraRuntimeError(runtimeCode, message, response.status, details);\n }\n\n if (parsed === null) {\n throw new OkraRuntimeError(\n 'INVALID_RESPONSE',\n `Expected JSON response for ${path}`,\n response.status,\n text,\n );\n }\n\n return parsed as T;\n }\n\n private parseBody(text: string): unknown | null {\n const trimmed = text.trim();\n if (!trimmed) return null;\n try {\n return JSON.parse(trimmed);\n } catch {\n return null;\n }\n }\n}\n"],"mappings":"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","names":["session","options"]}