okrapdf 0.10.0 → 0.12.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * okra CLI — Agent-friendly PDF extraction and collection queries.\n *\n * Global flags:\n * -j, --json Structured JSON output\n * -q, --quiet Suppress progress (just data to stdout)\n * -o, --output Write output to file (CSV/JSON)\n *\n * Action commands (agent-grade):\n * okra upload <source> # Upload + wait\n * okra collection list # List collections\n * okra collection query <name> \"<question>\" # Fan-out → CSV\n *\n * Review commands (existing):\n * okra tree / find / page / search / tables / history / toc\n *\n * Exit codes: 0=success, 1=client error, 2=server error\n */\n\nimport { Command } from 'commander';\nimport { OkraClient } from '../client';\nimport {\n tree,\n formatTreeOutput,\n find,\n formatFindOutput,\n formatStats,\n pageGet,\n pageEdit,\n pageResolve,\n pageVersions,\n formatPageOutput,\n formatVersionsOutput,\n search,\n formatSearchOutput,\n tables,\n formatTablesOutput,\n history,\n formatHistoryOutput,\n toc,\n formatTocOutput,\n authLogin,\n authStatus,\n authLogout,\n upload,\n collectionList,\n collectionSetVisibility,\n collectionQueryRaw,\n formatCollectionList,\n formatCollectionCsv,\n formatCollectionTable,\n formatQueryJsonl,\n} from './commands';\nimport { getApiKey, getBaseUrl } from './config';\nimport { handleError, writeOutput, progress } from './output';\nimport type { GlobalFlags } from './output';\n\nconst program = new Command();\n\nprogram\n .name('okra')\n .description('OkraPDF CLI — upload PDFs, query collections, extract data')\n .version('0.9.0')\n .option('-j, --json', 'Output JSON (structured, machine-readable)')\n .option('-q, --quiet', 'Suppress progress and human-readable frills')\n .option('-o, --output <file>', 'Write output to file instead of stdout');\n\n/** Read global flags from program.opts(). */\nfunction globals(): GlobalFlags {\n return program.opts();\n}\n\n// Create client with proper config priority:\n// 1. Environment variable (OKRA_API_KEY)\n// 2. Project config (.okrarc, .okra.json)\n// 3. Global config (~/.okra/config.json)\nfunction getClient(): OkraClient {\n const apiKey = getApiKey();\n const baseUrl = getBaseUrl();\n\n if (!apiKey) {\n const g = globals();\n if (g.json) {\n process.stderr.write(JSON.stringify({ error: 'No API key found', code: 401 }) + '\\n');\n } else {\n process.stderr.write(\n 'No API key found.\\n\\n' +\n ' Get one: https://okrapdf.dev/api-keys\\n' +\n ' Then: export OKRA_API_KEY=\"okra_xxx\"\\n' +\n ' Or: npx okra auth login\\n\\n' +\n ' Docs: https://okrapdf.dev/docs\\n' +\n ' Discord: https://discord.gg/BHNmbZVs\\n',\n );\n }\n process.exit(1);\n }\n\n return new OkraClient({ apiKey, baseUrl });\n}\n\n// ============================================================================\n// upload command\n// ============================================================================\nprogram\n .command('upload <source>')\n .description('Upload a PDF (file path or URL), wait for processing')\n .option('--no-wait', 'Fire-and-forget (don\\'t wait for processing)')\n .action(async (source, options) => {\n const g = globals();\n try {\n const client = getClient();\n const result = await upload(client, source, {\n ...g,\n noWait: options.wait === false,\n });\n\n if (g.json) {\n writeOutput(JSON.stringify(result), g.output);\n } else {\n const lines = [`Done — ${result.pages ?? '?'} pages`, ''];\n lines.push(` ${result.id}`);\n if (result.urls) {\n const short = result.id.slice(0, 11) + '...';\n lines.push('');\n lines.push(` Markdown: ${result.urls.full_md.replace(result.id, short)}`);\n lines.push(` Page 1: ${result.urls.page_png.replace(result.id, short).replace('{N}', '1')}`);\n lines.push(` Completion: ${result.urls.completion.replace(result.id, short)}`);\n lines.push('');\n lines.push(' URL patterns:');\n lines.push(' /v1/documents/{id}/pg_{N}.md page markdown');\n lines.push(' /v1/documents/{id}/d_shimmer/pg_{N}.png page image');\n lines.push(' /v1/documents/{id}/full.md full document');\n lines.push('');\n lines.push(' Docs: https://okrapdf.dev/docs Discord: https://discord.gg/BHNmbZVs');\n }\n writeOutput(lines.join('\\n'), g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// collection command\n// ============================================================================\nconst collectionCmd = program.command('collection').description('Collection operations');\n\ncollectionCmd\n .command('list')\n .description('List available collections')\n .action(async () => {\n const g = globals();\n try {\n const client = getClient();\n const rows = await collectionList(client, g);\n writeOutput(formatCollectionList(rows, g.json), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\ncollectionCmd\n .command('query <nameOrId> <question>')\n .description('Fan-out query across collection documents')\n .option('--schema <file>', 'JSON Schema file for structured extraction')\n .action(async (nameOrId, question, options) => {\n const g = globals();\n try {\n const apiKey = getApiKey();\n const baseUrl = getBaseUrl();\n if (!apiKey) {\n handleError(new Error('No API key found'), g.json);\n }\n\n const { results, summary } = await collectionQueryRaw(\n baseUrl!,\n apiKey!,\n nameOrId,\n question,\n { ...g, schema: options.schema },\n );\n\n // Determine output format based on flags\n if (g.json) {\n // --json: JSONL events to stdout\n writeOutput(formatQueryJsonl(results), g.output);\n } else if (g.output && g.output.endsWith('.csv')) {\n // -o file.csv → CSV\n writeOutput(formatCollectionCsv(results), g.output);\n } else if (g.output) {\n // -o file.json or other → JSON\n writeOutput(JSON.stringify({ results, summary }), g.output);\n } else {\n // Default: compact table to stdout\n writeOutput(formatCollectionTable(results));\n }\n\n progress(\n `${summary.completed} completed, ${summary.failed} failed — $${summary.total_cost_usd.toFixed(4)}`,\n g.quiet,\n );\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\ncollectionCmd\n .command('publish <nameOrId>')\n .description('Make a collection publicly queryable')\n .action(async (nameOrId) => {\n const g = globals();\n try {\n const client = getClient();\n await collectionSetVisibility(client, nameOrId, 'public');\n if (g.json) {\n writeOutput(JSON.stringify({ ok: true, visibility: 'public', collection: nameOrId }), g.output);\n } else {\n writeOutput(\n `Published \"${nameOrId}\"\\n` +\n `Share with: okra collection query ${nameOrId} \"your question\"`,\n g.output,\n );\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\ncollectionCmd\n .command('unpublish <nameOrId>')\n .description('Make a collection private (owner-only)')\n .action(async (nameOrId) => {\n const g = globals();\n try {\n const client = getClient();\n await collectionSetVisibility(client, nameOrId, 'private');\n if (g.json) {\n writeOutput(JSON.stringify({ ok: true, visibility: 'private', collection: nameOrId }), g.output);\n } else {\n writeOutput(`Unpublished \"${nameOrId}\" — now private`, g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// auth command - Authentication management\n// ============================================================================\nconst authCmd = program.command('auth').description('Manage authentication');\n\nauthCmd\n .command('login')\n .description('Save API key to global config')\n .action(async () => {\n try {\n await authLogin();\n } catch (error) {\n handleError(error, globals().json);\n }\n });\n\nauthCmd\n .command('status')\n .description('Show authentication status')\n .action(async () => {\n try {\n await authStatus();\n } catch (error) {\n handleError(error, globals().json);\n }\n });\n\nauthCmd\n .command('logout')\n .description('Remove API key from global config')\n .action(async () => {\n try {\n await authLogout();\n } catch (error) {\n handleError(error, globals().json);\n }\n });\n\n// ============================================================================\n// tree command - Document verification tree\n// ============================================================================\nprogram\n .command('tree <jobId>')\n .description('Show document verification tree')\n .option('-s, --status <status>', 'Filter by status (complete|partial|pending|flagged|empty|gap)')\n .option('-e, --entity <type>', 'Filter by entity type (table|figure|footnote)')\n .option('-f, --format <format>', 'Output format (text|json|markdown)', 'text')\n .action(async (jobId, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await tree(client, jobId, {\n status: options.status,\n entity: options.entity,\n });\n writeOutput(formatTreeOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// find command - jQuery-like entity search\n// ============================================================================\nprogram\n .command('find <jobId> <selector>')\n .description('Find entities using jQuery-like selectors')\n .option('-k, --top-k <n>', 'Limit results', parseInt)\n .option('-c, --min-confidence <n>', 'Minimum confidence (0-1)', parseFloat)\n .option('-p, --pages <range>', 'Page range (e.g., 1-10)')\n .option('--sort <by>', 'Sort by (confidence|page|type)')\n .option('--stats', 'Show aggregate statistics')\n .option('-f, --format <format>', 'Output format (text|json|entities|ids)', 'text')\n .action(async (jobId, selector, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const pageRange = options.pages\n ? options.pages.split('-').map(Number) as [number, number]\n : undefined;\n\n const result = await find(client, jobId, selector, {\n topK: options.topK,\n minConfidence: options.minConfidence,\n pageRange,\n sortBy: options.sort,\n });\n\n if (options.stats && fmt === 'text') {\n writeOutput(formatStats(result.stats), g.output);\n } else {\n writeOutput(formatFindOutput(result, fmt, options.stats), g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// page command - Page content operations\n// ============================================================================\nconst pageCmd = program.command('page').description('Page content operations');\n\npageCmd\n .command('get <jobId> <pageNum>')\n .description('Get page content')\n .option('-v, --version <n>', 'Specific version', parseInt)\n .option('-f, --format <format>', 'Output format (text|json|markdown)', 'markdown')\n .action(async (jobId, pageNum, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const content = await pageGet(client, jobId, parseInt(pageNum), {\n version: options.version,\n });\n writeOutput(formatPageOutput(content, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\npageCmd\n .command('edit <jobId> <pageNum>')\n .description('Edit page content (reads from stdin)')\n .action(async (jobId, pageNum) => {\n const g = globals();\n try {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n const content = Buffer.concat(chunks).toString('utf8');\n\n const client = getClient();\n const result = await pageEdit(client, jobId, parseInt(pageNum), content);\n if (g.json) {\n writeOutput(JSON.stringify({ version: result.version }), g.output);\n } else {\n writeOutput(`Saved as version ${result.version}`, g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\npageCmd\n .command('resolve <jobId> <pageNum> <resolution>')\n .description('Resolve page verification status')\n .option('-c, --classification <class>', 'Classification')\n .option('-r, --reason <reason>', 'Reason')\n .action(async (jobId, pageNum, resolution, options) => {\n const g = globals();\n try {\n const client = getClient();\n const result = await pageResolve(client, jobId, parseInt(pageNum), {\n resolution,\n classification: options.classification,\n reason: options.reason,\n });\n if (g.json) {\n writeOutput(JSON.stringify({ success: result.success }), g.output);\n } else {\n writeOutput(result.success ? 'Resolved' : 'Failed', g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\npageCmd\n .command('versions <jobId> <pageNum>')\n .description('List page versions')\n .option('-f, --format <format>', 'Output format (text|json)', 'text')\n .action(async (jobId, pageNum, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const versions = await pageVersions(client, jobId, parseInt(pageNum));\n writeOutput(formatVersionsOutput(versions, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// search command - Full-text search\n// ============================================================================\nprogram\n .command('search <jobId> <query>')\n .description('Search page content')\n .option('-f, --format <format>', 'Output format (text|json)', 'text')\n .action(async (jobId, query, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await search(client, jobId, query);\n writeOutput(formatSearchOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// tables command - List tables\n// ============================================================================\nprogram\n .command('tables <jobId>')\n .description('List extracted tables')\n .option('-p, --page <n>', 'Filter by page', parseInt)\n .option('-s, --status <status>', 'Filter by status (pending|verified|flagged|rejected)')\n .option('-f, --format <format>', 'Output format (text|json|markdown)', 'text')\n .action(async (jobId, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await tables(client, jobId, {\n page: options.page,\n status: options.status,\n });\n writeOutput(formatTablesOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// history command - Verification audit trail\n// ============================================================================\nprogram\n .command('history <jobId>')\n .description('Show verification history')\n .option('-l, --limit <n>', 'Limit entries', parseInt, 50)\n .option('-f, --format <format>', 'Output format (text|json)', 'text')\n .action(async (jobId, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await history(client, jobId, { limit: options.limit });\n writeOutput(formatHistoryOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// toc command - Table of contents extraction\n// ============================================================================\nprogram\n .command('toc <jobId>')\n .description('Extract table of contents from PDF')\n .option('--max-depth <n>', 'Maximum TOC depth', parseInt)\n .option('-f, --format <format>', 'Output format (text|json|markdown)', 'text')\n .option('--watch', 'Watch live extraction events via WebSocket')\n .action(async (jobId, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await toc(client, jobId, {\n maxDepth: options.maxDepth,\n watch: options.watch,\n });\n writeOutput(formatTocOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\nprogram.parse();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * okra CLI — Agent-friendly PDF extraction and collection queries.\n *\n * Global flags:\n * -j, --json Structured JSON output\n * -q, --quiet Suppress progress (just data to stdout)\n * -o, --output Write output to file (CSV/JSON)\n *\n * Action commands (agent-grade):\n * okra upload <source> # Upload + wait\n * okra collection list # List collections\n * okra collection query <name> \"<question>\" # Fan-out → CSV\n *\n * Review commands (existing):\n * okra tree / find / page / search / tables / history / toc\n *\n * Exit codes: 0=success, 1=client error, 2=server error\n */\n\nimport { Command } from 'commander';\nimport { OkraClient } from '../client';\nimport {\n tree,\n formatTreeOutput,\n find,\n formatFindOutput,\n formatStats,\n pageGet,\n pageEdit,\n pageResolve,\n pageVersions,\n formatPageOutput,\n formatVersionsOutput,\n search,\n formatSearchOutput,\n tables,\n formatTablesOutput,\n history,\n formatHistoryOutput,\n toc,\n formatTocOutput,\n authLogin,\n authStatus,\n authLogout,\n upload,\n collectionList,\n collectionSetVisibility,\n collectionQueryRaw,\n formatCollectionList,\n formatCollectionCsv,\n formatCollectionTable,\n formatQueryJsonl,\n} from './commands';\nimport { getApiKey, getBaseUrl } from './config';\nimport { handleError, writeOutput, progress } from './output';\nimport type { GlobalFlags } from './output';\n\nconst program = new Command();\n\nprogram\n .name('okra')\n .description('OkraPDF CLI — upload PDFs, query collections, extract data')\n .version('0.9.0')\n .option('-j, --json', 'Output JSON (structured, machine-readable)')\n .option('-q, --quiet', 'Suppress progress and human-readable frills')\n .option('-o, --output <file>', 'Write output to file instead of stdout');\n\n/** Read global flags from program.opts(). */\nfunction globals(): GlobalFlags {\n return program.opts();\n}\n\n// Create client with proper config priority:\n// 1. Environment variable (OKRA_API_KEY)\n// 2. Project config (.okrarc, .okra.json)\n// 3. Global config (~/.okra/config.json)\nfunction getClient(): OkraClient {\n const apiKey = getApiKey();\n const baseUrl = getBaseUrl();\n\n if (!apiKey) {\n const g = globals();\n if (g.json) {\n process.stderr.write(JSON.stringify({ error: 'No API key found', code: 401 }) + '\\n');\n } else {\n process.stderr.write(\n 'No API key found.\\n\\n' +\n ' Get one: https://okrapdf.dev/api-keys\\n' +\n ' Then: export OKRA_API_KEY=\"okra_xxx\"\\n' +\n ' Or: npx okra auth login\\n\\n' +\n ' Docs: https://okrapdf.dev/docs\\n' +\n ' Discord: https://discord.gg/BHNmbZVs\\n',\n );\n }\n process.exit(1);\n }\n\n return new OkraClient({ apiKey, baseUrl });\n}\n\n// ============================================================================\n// upload command\n// ============================================================================\nprogram\n .command('upload <source>')\n .description('Upload a PDF (file path or URL), wait for processing')\n .option('--no-wait', 'Fire-and-forget (don\\'t wait for processing)')\n .action(async (source, options) => {\n const g = globals();\n try {\n const client = getClient();\n const result = await upload(client, source, {\n ...g,\n noWait: options.wait === false,\n });\n\n if (g.json) {\n writeOutput(JSON.stringify(result), g.output);\n } else {\n const lines = [`Done — ${result.pages ?? '?'} pages`, ''];\n lines.push(` ${result.id}`);\n if (result.urls) {\n const short = result.id.slice(0, 11) + '...';\n lines.push('');\n lines.push(` Markdown: ${result.urls.full_md.replace(result.id, short)}`);\n lines.push(` Page 1: ${result.urls.page_png.replace(result.id, short).replace('{N}', '1')}`);\n lines.push(` Completion: ${result.urls.completion.replace(result.id, short)}`);\n lines.push('');\n lines.push(' URL patterns:');\n lines.push(' /v1/documents/{id}/pg_{N}.md page markdown');\n lines.push(' /v1/documents/{id}/d_shimmer/pg_{N}.png page image');\n lines.push(' /v1/documents/{id}/full.md full document');\n lines.push('');\n lines.push(' Docs: https://okrapdf.dev/docs Discord: https://discord.gg/BHNmbZVs');\n }\n writeOutput(lines.join('\\n'), g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// collection command\n// ============================================================================\nconst collectionCmd = program.command('collection').description('Collection operations');\n\ncollectionCmd\n .command('list')\n .description('List available collections')\n .action(async () => {\n const g = globals();\n try {\n const client = getClient();\n const rows = await collectionList(client, g);\n writeOutput(formatCollectionList(rows, g.json), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\ncollectionCmd\n .command('query <nameOrId> <question>')\n .description('Fan-out query across collection documents')\n .option('--schema <file>', 'JSON Schema file for structured extraction')\n .action(async (nameOrId, question, options) => {\n const g = globals();\n try {\n const client = getClient();\n const { results, summary } = await collectionQueryRaw(\n client,\n nameOrId,\n question,\n { ...g, schema: options.schema },\n );\n\n // Determine output format based on flags\n if (g.json) {\n // --json: JSONL events to stdout\n writeOutput(formatQueryJsonl(results), g.output);\n } else if (g.output && g.output.endsWith('.csv')) {\n // -o file.csv → CSV\n writeOutput(formatCollectionCsv(results), g.output);\n } else if (g.output) {\n // -o file.json or other → JSON\n writeOutput(JSON.stringify({ results, summary }), g.output);\n } else {\n // Default: compact table to stdout\n writeOutput(formatCollectionTable(results));\n }\n\n progress(\n `${summary.completed} completed, ${summary.failed} failed — $${summary.total_cost_usd.toFixed(4)}`,\n g.quiet,\n );\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\ncollectionCmd\n .command('publish <nameOrId>')\n .description('Make a collection publicly queryable')\n .action(async (nameOrId) => {\n const g = globals();\n try {\n const client = getClient();\n await collectionSetVisibility(client, nameOrId, 'public');\n if (g.json) {\n writeOutput(JSON.stringify({ ok: true, visibility: 'public', collection: nameOrId }), g.output);\n } else {\n writeOutput(\n `Published \"${nameOrId}\"\\n` +\n `Share with: okra collection query ${nameOrId} \"your question\"`,\n g.output,\n );\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\ncollectionCmd\n .command('unpublish <nameOrId>')\n .description('Make a collection private (owner-only)')\n .action(async (nameOrId) => {\n const g = globals();\n try {\n const client = getClient();\n await collectionSetVisibility(client, nameOrId, 'private');\n if (g.json) {\n writeOutput(JSON.stringify({ ok: true, visibility: 'private', collection: nameOrId }), g.output);\n } else {\n writeOutput(`Unpublished \"${nameOrId}\" — now private`, g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// auth command - Authentication management\n// ============================================================================\nconst authCmd = program.command('auth').description('Manage authentication');\n\nauthCmd\n .command('login')\n .description('Save API key to global config')\n .action(async () => {\n try {\n await authLogin();\n } catch (error) {\n handleError(error, globals().json);\n }\n });\n\nauthCmd\n .command('status')\n .description('Show authentication status')\n .action(async () => {\n try {\n await authStatus();\n } catch (error) {\n handleError(error, globals().json);\n }\n });\n\nauthCmd\n .command('logout')\n .description('Remove API key from global config')\n .action(async () => {\n try {\n await authLogout();\n } catch (error) {\n handleError(error, globals().json);\n }\n });\n\n// ============================================================================\n// tree command - Document verification tree\n// ============================================================================\nprogram\n .command('tree <jobId>')\n .description('Show document verification tree')\n .option('-s, --status <status>', 'Filter by status (complete|partial|pending|flagged|empty|gap)')\n .option('-e, --entity <type>', 'Filter by entity type (table|figure|footnote)')\n .option('-f, --format <format>', 'Output format (text|json|markdown)', 'text')\n .action(async (jobId, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await tree(client, jobId, {\n status: options.status,\n entity: options.entity,\n });\n writeOutput(formatTreeOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// find command - jQuery-like entity search\n// ============================================================================\nprogram\n .command('find <jobId> <selector>')\n .description('Find entities using jQuery-like selectors')\n .option('-k, --top-k <n>', 'Limit results', parseInt)\n .option('-c, --min-confidence <n>', 'Minimum confidence (0-1)', parseFloat)\n .option('-p, --pages <range>', 'Page range (e.g., 1-10)')\n .option('--sort <by>', 'Sort by (confidence|page|type)')\n .option('--stats', 'Show aggregate statistics')\n .option('-f, --format <format>', 'Output format (text|json|entities|ids)', 'text')\n .action(async (jobId, selector, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const pageRange = options.pages\n ? options.pages.split('-').map(Number) as [number, number]\n : undefined;\n\n const result = await find(client, jobId, selector, {\n topK: options.topK,\n minConfidence: options.minConfidence,\n pageRange,\n sortBy: options.sort,\n });\n\n if (options.stats && fmt === 'text') {\n writeOutput(formatStats(result.stats), g.output);\n } else {\n writeOutput(formatFindOutput(result, fmt, options.stats), g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// page command - Page content operations\n// ============================================================================\nconst pageCmd = program.command('page').description('Page content operations');\n\npageCmd\n .command('get <jobId> <pageNum>')\n .description('Get page content')\n .option('-v, --version <n>', 'Specific version', parseInt)\n .option('-f, --format <format>', 'Output format (text|json|markdown)', 'markdown')\n .action(async (jobId, pageNum, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const content = await pageGet(client, jobId, parseInt(pageNum), {\n version: options.version,\n });\n writeOutput(formatPageOutput(content, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\npageCmd\n .command('edit <jobId> <pageNum>')\n .description('Edit page content (reads from stdin)')\n .action(async (jobId, pageNum) => {\n const g = globals();\n try {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n const content = Buffer.concat(chunks).toString('utf8');\n\n const client = getClient();\n const result = await pageEdit(client, jobId, parseInt(pageNum), content);\n if (g.json) {\n writeOutput(JSON.stringify({ version: result.version }), g.output);\n } else {\n writeOutput(`Saved as version ${result.version}`, g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\npageCmd\n .command('resolve <jobId> <pageNum> <resolution>')\n .description('Resolve page verification status')\n .option('-c, --classification <class>', 'Classification')\n .option('-r, --reason <reason>', 'Reason')\n .action(async (jobId, pageNum, resolution, options) => {\n const g = globals();\n try {\n const client = getClient();\n const result = await pageResolve(client, jobId, parseInt(pageNum), {\n resolution,\n classification: options.classification,\n reason: options.reason,\n });\n if (g.json) {\n writeOutput(JSON.stringify({ success: result.success }), g.output);\n } else {\n writeOutput(result.success ? 'Resolved' : 'Failed', g.output);\n }\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\npageCmd\n .command('versions <jobId> <pageNum>')\n .description('List page versions')\n .option('-f, --format <format>', 'Output format (text|json)', 'text')\n .action(async (jobId, pageNum, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const versions = await pageVersions(client, jobId, parseInt(pageNum));\n writeOutput(formatVersionsOutput(versions, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// search command - Full-text search\n// ============================================================================\nprogram\n .command('search <jobId> <query>')\n .description('Search page content')\n .option('-f, --format <format>', 'Output format (text|json)', 'text')\n .action(async (jobId, query, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await search(client, jobId, query);\n writeOutput(formatSearchOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// tables command - List tables\n// ============================================================================\nprogram\n .command('tables <jobId>')\n .description('List extracted tables')\n .option('-p, --page <n>', 'Filter by page', parseInt)\n .option('-s, --status <status>', 'Filter by status (pending|verified|flagged|rejected)')\n .option('-f, --format <format>', 'Output format (text|json|markdown)', 'text')\n .action(async (jobId, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await tables(client, jobId, {\n page: options.page,\n status: options.status,\n });\n writeOutput(formatTablesOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// history command - Verification audit trail\n// ============================================================================\nprogram\n .command('history <jobId>')\n .description('Show verification history')\n .option('-l, --limit <n>', 'Limit entries', parseInt, 50)\n .option('-f, --format <format>', 'Output format (text|json)', 'text')\n .action(async (jobId, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await history(client, jobId, { limit: options.limit });\n writeOutput(formatHistoryOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\n// ============================================================================\n// toc command - Table of contents extraction\n// ============================================================================\nprogram\n .command('toc <jobId>')\n .description('Extract table of contents from PDF')\n .option('--max-depth <n>', 'Maximum TOC depth', parseInt)\n .option('-f, --format <format>', 'Output format (text|json|markdown)', 'text')\n .option('--watch', 'Watch live extraction events via WebSocket')\n .action(async (jobId, options) => {\n const g = globals();\n try {\n const client = getClient();\n const fmt = g.json ? 'json' : options.format;\n const result = await toc(client, jobId, {\n maxDepth: options.maxDepth,\n watch: options.watch,\n });\n writeOutput(formatTocOutput(result, fmt), g.output);\n } catch (error) {\n handleError(error, g.json);\n }\n });\n\nprogram.parse();\n"],"mappings":"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","names":[]}
@@ -1,5 +1,5 @@
1
- import { O as OkraClient } from '../client-CyA8BgrE.js';
2
- import '../types-DpLY63Cg.js';
1
+ import { O as OkraClient } from '../client-CdCU6Div.js';
2
+ import '../types-58dvD4Yj.js';
3
3
  import 'zod';
4
4
 
5
5
  /**
package/dist/cli/index.js CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  toc,
34
34
  tree,
35
35
  writeGlobalConfig
36
- } from "../chunk-4IHOG655.js";
36
+ } from "../chunk-YY44NPDZ.js";
37
37
  import "../chunk-NIZM2ETT.js";
38
38
  export {
39
39
  authLogin,
@@ -1,4 +1,4 @@
1
- import { b as UploadInput, S as SessionCreateOptions, O as OkraSession, c as SessionAttachOptions, C as CollectionSummary, d as Collection, e as OkraClientOptions, f as UploadOptions, g as DocumentStatus, W as WaitOptions, P as Page, E as EntitiesResponse, Q as QueryResult, h as CompletionOptions, i as CompletionEvent, G as GenerateOptions, j as GenerateResult, k as StructuredSchema, l as PublishResult, m as ShareLinkOptions, n as ShareLinkResult } from './types-DpLY63Cg.js';
1
+ import { b as UploadInput, S as SessionCreateOptions, O as OkraSession, c as SessionAttachOptions, C as CollectionSummary, d as Collection, e as CollectionQueryOptions, f as CollectionQueryStream, g as OkraClientOptions, h as UploadOptions, i as DocumentStatus, W as WaitOptions, P as Page, E as EntitiesResponse, Q as QueryResult, L as LogsOptions, j as LogEntry, k as CompletionOptions, l as CompletionEvent, G as GenerateOptions, m as GenerateResult, n as StructuredSchema, o as PublishResult, p as ShareLinkOptions, q as ShareLinkResult } from './types-58dvD4Yj.js';
2
2
 
3
3
  declare class OkraClient {
4
4
  private readonly baseUrl;
@@ -12,10 +12,12 @@ declare class OkraClient {
12
12
  readonly collections: {
13
13
  list: (signal?: AbortSignal) => Promise<CollectionSummary[]>;
14
14
  get: (collectionId: string, signal?: AbortSignal) => Promise<Collection>;
15
+ query: <T = undefined>(collectionId: string, prompt: string, options?: CollectionQueryOptions<T>) => CollectionQueryStream<T>;
15
16
  };
16
17
  constructor(options: OkraClientOptions);
17
18
  private collectionList;
18
19
  private collectionGet;
20
+ private collectionQuery;
19
21
  upload(input: UploadInput, options?: UploadOptions): Promise<OkraSession>;
20
22
  status(documentId: string, signal?: AbortSignal): Promise<DocumentStatus>;
21
23
  wait(documentId: string, options?: WaitOptions): Promise<DocumentStatus>;
@@ -32,6 +34,7 @@ declare class OkraClient {
32
34
  signal?: AbortSignal;
33
35
  }): Promise<EntitiesResponse>;
34
36
  query(documentId: string, sql: string, signal?: AbortSignal): Promise<QueryResult>;
37
+ logs(documentId: string, options?: LogsOptions): Promise<LogEntry[]>;
35
38
  stream(documentId: string, query: string, options?: CompletionOptions): AsyncGenerator<CompletionEvent>;
36
39
  generate(documentId: string, query: string, options?: GenerateOptions & {
37
40
  schema?: undefined;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { O as OkraClient } from './client-CyA8BgrE.js';
2
- import { e as OkraClientOptions, O as OkraSession, h as CompletionOptions, i as CompletionEvent, o as SessionState, g as DocumentStatus, W as WaitOptions, P as Page, E as EntitiesResponse, Q as QueryResult, l as PublishResult, m as ShareLinkOptions, n as ShareLinkResult, G as GenerateOptions, j as GenerateResult, k as StructuredSchema, R as RuntimeErrorCode, p as StructuredOutputErrorCode } from './types-DpLY63Cg.js';
3
- export { d as Collection, q as CollectionDocument, r as CollectionQueryEvent, s as CollectionQueryOptions, t as CollectionQueryResult, u as CollectionQueryStream, C as CollectionSummary, D as DocUrlOptions, v as DocumentAnswer, w as Entity, J as JsonSchema, x as OkraCollections, y as PageBlock, z as PageEntity, c as SessionAttachOptions, S as SessionCreateOptions, A as ShareLinkCapabilities, B as ShareLinkLinks, F as StructuredOutputMeta, b as UploadInput, f as UploadOptions, H as UploadRedactOptions, I as UploadRedactPiiOptions, U as UrlBuilderOptions } from './types-DpLY63Cg.js';
1
+ import { O as OkraClient } from './client-CdCU6Div.js';
2
+ import { g as OkraClientOptions, O as OkraSession, k as CompletionOptions, l as CompletionEvent, r as SessionState, i as DocumentStatus, W as WaitOptions, P as Page, E as EntitiesResponse, Q as QueryResult, L as LogsOptions, j as LogEntry, o as PublishResult, p as ShareLinkOptions, q as ShareLinkResult, G as GenerateOptions, m as GenerateResult, n as StructuredSchema, R as RuntimeErrorCode, s as StructuredOutputErrorCode } from './types-58dvD4Yj.js';
3
+ export { d as Collection, t as CollectionDocument, u as CollectionQueryEvent, e as CollectionQueryOptions, v as CollectionQueryResult, f as CollectionQueryStream, C as CollectionSummary, D as DocUrlOptions, w as DocumentAnswer, x as Entity, J as JsonSchema, y as OkraCollections, z as PageBlock, A as PageEntity, c as SessionAttachOptions, S as SessionCreateOptions, B as ShareLinkCapabilities, F as ShareLinkLinks, H as StructuredOutputMeta, b as UploadInput, h as UploadOptions, I as UploadRedactOptions, K as UploadRedactPiiOptions, U as UrlBuilderOptions } from './types-58dvD4Yj.js';
4
4
  export { doc } from './url.js';
5
5
  import 'zod';
6
6
 
@@ -43,19 +43,6 @@ declare function withSecret(namespace: string, opts?: {
43
43
  required?: boolean;
44
44
  }): OkraMiddleware;
45
45
 
46
- /**
47
- * WsSession — OkraSession adapter that routes `stream()` over an existing
48
- * WebSocket connection instead of HTTP SSE.
49
- *
50
- * All non-streaming methods delegate to the inner HTTP-backed session.
51
- * Only `stream()` is overridden to send CHAT_COMPLETION over WS and yield
52
- * CompletionEvents from CHAT_STREAM_* responses.
53
- *
54
- * Usage:
55
- * const wsSession = new WsSession(httpSession, { send, subscribe });
56
- * const chat = useChat({ session: wsSession });
57
- */
58
-
59
46
  type ChatStreamServerEvent = {
60
47
  type: 'CHAT_STREAM_START';
61
48
  requestId: string;
@@ -111,6 +98,7 @@ declare class WsSession implements OkraSession {
111
98
  }): Promise<EntitiesResponse>;
112
99
  downloadUrl(): string;
113
100
  query(sql: string, signal?: AbortSignal): Promise<QueryResult>;
101
+ logs(options?: LogsOptions): Promise<LogEntry[]>;
114
102
  publish(signal?: AbortSignal): Promise<PublishResult>;
115
103
  shareLink(options?: ShareLinkOptions): Promise<ShareLinkResult>;
116
104
  prompt(query: string, options?: GenerateOptions & {
@@ -132,4 +120,4 @@ declare class StructuredOutputError extends OkraRuntimeError {
132
120
  constructor(code: StructuredOutputErrorCode, message: string, status: number, details?: unknown);
133
121
  }
134
122
 
135
- export { type ChatStreamServerEvent, CompletionEvent, CompletionOptions, type CreateOkraOptions, DocumentStatus, EntitiesResponse, type ExtractionPhase, GenerateOptions, GenerateResult, OkraClient, OkraClientOptions, type OkraMiddleware, type OkraProvider, OkraClient as OkraRuntime, OkraRuntimeError, OkraSession, Page, PublishResult, QueryResult, RuntimeErrorCode, SessionState, ShareLinkOptions, ShareLinkResult, StructuredOutputError, StructuredOutputErrorCode, StructuredSchema, WaitOptions, type WsSendFn, WsSession, type WsSessionOptions, type WsSubscribeFn, createOkra, withCache, withQualityScore, withSecret };
123
+ export { type ChatStreamServerEvent, CompletionEvent, CompletionOptions, type CreateOkraOptions, DocumentStatus, EntitiesResponse, type ExtractionPhase, GenerateOptions, GenerateResult, LogEntry, LogsOptions, OkraClient, OkraClientOptions, type OkraMiddleware, type OkraProvider, OkraClient as OkraRuntime, OkraRuntimeError, OkraSession, Page, PublishResult, QueryResult, RuntimeErrorCode, SessionState, ShareLinkOptions, ShareLinkResult, StructuredOutputError, StructuredOutputErrorCode, StructuredSchema, WaitOptions, type WsSendFn, WsSession, type WsSessionOptions, type WsSubscribeFn, createOkra, withCache, withQualityScore, withSecret };
package/dist/index.js CHANGED
@@ -6,10 +6,10 @@ import {
6
6
  withCache,
7
7
  withQualityScore,
8
8
  withSecret
9
- } from "./chunk-Y72DLYYO.js";
9
+ } from "./chunk-ADVWUO22.js";
10
10
  import {
11
11
  OkraClient
12
- } from "./chunk-EZLAOKOP.js";
12
+ } from "./chunk-XM4MS5WV.js";
13
13
  import {
14
14
  OkraRuntimeError,
15
15
  StructuredOutputError
@@ -128,6 +128,9 @@ var WsSession = class {
128
128
  query(sql, signal) {
129
129
  return this.#inner.query(sql, signal);
130
130
  }
131
+ logs(options) {
132
+ return this.#inner.logs(options);
133
+ }
131
134
  publish(signal) {
132
135
  return this.#inner.publish(signal);
133
136
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ws-session.ts"],"sourcesContent":["/**\n * WsSession — OkraSession adapter that routes `stream()` over an existing\n * WebSocket connection instead of HTTP SSE.\n *\n * All non-streaming methods delegate to the inner HTTP-backed session.\n * Only `stream()` is overridden to send CHAT_COMPLETION over WS and yield\n * CompletionEvents from CHAT_STREAM_* responses.\n *\n * Usage:\n * const wsSession = new WsSession(httpSession, { send, subscribe });\n * const chat = useChat({ session: wsSession });\n */\n\nimport type {\n OkraSession,\n CompletionEvent,\n CompletionOptions,\n DocumentStatus,\n WaitOptions,\n Page,\n EntitiesResponse,\n QueryResult,\n PublishResult,\n ShareLinkOptions,\n ShareLinkResult,\n GenerateOptions,\n GenerateResult,\n SessionState,\n StructuredSchema,\n} from './types';\n\n// Chat stream event types — mirrors @okrapdf/schemas ChatStreamServerEvent\n// Inlined to avoid adding @okrapdf/schemas as a dependency of the published SDK.\n\nexport type ChatStreamServerEvent =\n | { type: 'CHAT_STREAM_START'; requestId: string }\n | { type: 'CHAT_STREAM_DELTA'; requestId: string; delta: string }\n | { type: 'CHAT_STREAM_DONE'; requestId: string; usage?: { inputTokens: number; outputTokens: number; costUsd: number }; model?: string }\n | { type: 'CHAT_STREAM_ERROR'; requestId: string; error: string };\n\n/** Function that sends a JSON string over the WebSocket. Returns false if WS is closed. */\nexport type WsSendFn = (message: string) => boolean;\n\n/** Subscribe to chat stream events. Returns unsubscribe function. */\nexport type WsSubscribeFn = (\n requestId: string,\n handler: (event: ChatStreamServerEvent) => void,\n) => () => void;\n\nexport interface WsSessionOptions {\n /** Send JSON string over the existing WebSocket connection */\n send: WsSendFn;\n /** Subscribe to CHAT_STREAM_* events for a given requestId */\n subscribe: WsSubscribeFn;\n}\n\nfunction uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport class WsSession implements OkraSession {\n readonly id: string;\n readonly modelEndpoint: string;\n readonly model?: string;\n\n #inner: OkraSession;\n #opts: WsSessionOptions;\n\n constructor(inner: OkraSession, opts: WsSessionOptions) {\n this.#inner = inner;\n this.#opts = opts;\n this.id = inner.id;\n this.modelEndpoint = inner.modelEndpoint;\n this.model = inner.model;\n }\n\n // ── Overridden: stream via WebSocket ──────────────────────────────────────\n\n async *stream(\n query: string,\n options?: CompletionOptions,\n ): AsyncGenerator<CompletionEvent> {\n const requestId = uuid();\n\n // Build message history (single user message for now — matches HTTP path)\n const messages = [{ role: 'user', content: query }];\n\n const sent = this.#opts.send(JSON.stringify({\n type: 'CHAT_COMPLETION',\n requestId,\n messages,\n }));\n\n if (!sent) {\n yield { type: 'error', message: 'WebSocket not connected' };\n return;\n }\n\n // Create a promise-based event queue\n type QueueItem =\n | { done: false; event: ChatStreamServerEvent }\n | { done: true };\n\n const queue: QueueItem[] = [];\n let resolve: (() => void) | null = null;\n let finished = false;\n\n const unsubscribe = this.#opts.subscribe(requestId, (event) => {\n if (finished) return;\n queue.push({ done: false, event });\n resolve?.();\n });\n\n const cleanup = () => {\n finished = true;\n unsubscribe();\n };\n\n // Handle abort signal\n if (options?.signal) {\n options.signal.addEventListener('abort', () => {\n cleanup();\n queue.push({ done: true });\n resolve?.();\n }, { once: true });\n }\n\n try {\n let fullText = '';\n\n while (true) {\n if (queue.length === 0) {\n await new Promise<void>((r) => { resolve = r; });\n resolve = null;\n }\n\n const item = queue.shift();\n if (!item || item.done) break;\n\n const evt = item.event;\n\n switch (evt.type) {\n case 'CHAT_STREAM_START':\n // No CompletionEvent for start — just skip\n break;\n\n case 'CHAT_STREAM_DELTA':\n fullText += evt.delta;\n yield { type: 'text_delta', text: evt.delta };\n break;\n\n case 'CHAT_STREAM_DONE':\n yield { type: 'done', answer: fullText };\n cleanup();\n return;\n\n case 'CHAT_STREAM_ERROR':\n yield { type: 'error', message: evt.error };\n cleanup();\n return;\n }\n }\n } finally {\n cleanup();\n }\n }\n\n // ── Delegated to inner HTTP session ───────────────────────────────────────\n\n state(): SessionState { return this.#inner.state(); }\n setModel(model: string): Promise<void> { return this.#inner.setModel(model); }\n status(signal?: AbortSignal): Promise<DocumentStatus> { return this.#inner.status(signal); }\n wait(options?: WaitOptions): Promise<DocumentStatus> { return this.#inner.wait(options); }\n pages(options?: { range?: string; signal?: AbortSignal }): Promise<Page[]> { return this.#inner.pages(options); }\n page(pageNumber: number, signal?: AbortSignal): Promise<Page> { return this.#inner.page(pageNumber, signal); }\n entities(options?: { type?: string; limit?: number; offset?: number; signal?: AbortSignal }): Promise<EntitiesResponse> { return this.#inner.entities(options); }\n downloadUrl(): string { return this.#inner.downloadUrl(); }\n query(sql: string, signal?: AbortSignal): Promise<QueryResult> { return this.#inner.query(sql, signal); }\n publish(signal?: AbortSignal): Promise<PublishResult> { return this.#inner.publish(signal); }\n shareLink(options?: ShareLinkOptions): Promise<ShareLinkResult> { return this.#inner.shareLink(options); }\n\n prompt(query: string, options?: GenerateOptions & { schema?: undefined }): Promise<GenerateResult>;\n prompt<T>(query: string, options: GenerateOptions & { schema: StructuredSchema<T> }): Promise<GenerateResult<T>>;\n prompt<T = undefined>(query: string, options?: GenerateOptions): Promise<GenerateResult<T>> {\n if (options?.schema !== undefined) {\n return this.#inner.prompt(query, options as GenerateOptions & { schema: StructuredSchema<unknown> }) as Promise<GenerateResult<T>>;\n }\n return this.#inner.prompt(query, options as GenerateOptions & { schema?: undefined }) as Promise<GenerateResult<T>>;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/ws-session.ts"],"sourcesContent":["/**\n * WsSession — OkraSession adapter that routes `stream()` over an existing\n * WebSocket connection instead of HTTP SSE.\n *\n * All non-streaming methods delegate to the inner HTTP-backed session.\n * Only `stream()` is overridden to send CHAT_COMPLETION over WS and yield\n * CompletionEvents from CHAT_STREAM_* responses.\n *\n * Usage:\n * const wsSession = new WsSession(httpSession, { send, subscribe });\n * const chat = useChat({ session: wsSession });\n */\n\nimport type {\n OkraSession,\n CompletionEvent,\n CompletionOptions,\n DocumentStatus,\n WaitOptions,\n Page,\n EntitiesResponse,\n QueryResult,\n PublishResult,\n ShareLinkOptions,\n ShareLinkResult,\n GenerateOptions,\n GenerateResult,\n SessionState,\n StructuredSchema,\n} from './types';\n\n// Chat stream event types — mirrors @okrapdf/schemas ChatStreamServerEvent\n// Inlined to avoid adding @okrapdf/schemas as a dependency of the published SDK.\n\nexport type ChatStreamServerEvent =\n | { type: 'CHAT_STREAM_START'; requestId: string }\n | { type: 'CHAT_STREAM_DELTA'; requestId: string; delta: string }\n | { type: 'CHAT_STREAM_DONE'; requestId: string; usage?: { inputTokens: number; outputTokens: number; costUsd: number }; model?: string }\n | { type: 'CHAT_STREAM_ERROR'; requestId: string; error: string };\n\n/** Function that sends a JSON string over the WebSocket. Returns false if WS is closed. */\nexport type WsSendFn = (message: string) => boolean;\n\n/** Subscribe to chat stream events. Returns unsubscribe function. */\nexport type WsSubscribeFn = (\n requestId: string,\n handler: (event: ChatStreamServerEvent) => void,\n) => () => void;\n\nexport interface WsSessionOptions {\n /** Send JSON string over the existing WebSocket connection */\n send: WsSendFn;\n /** Subscribe to CHAT_STREAM_* events for a given requestId */\n subscribe: WsSubscribeFn;\n}\n\nfunction uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport class WsSession implements OkraSession {\n readonly id: string;\n readonly modelEndpoint: string;\n readonly model?: string;\n\n #inner: OkraSession;\n #opts: WsSessionOptions;\n\n constructor(inner: OkraSession, opts: WsSessionOptions) {\n this.#inner = inner;\n this.#opts = opts;\n this.id = inner.id;\n this.modelEndpoint = inner.modelEndpoint;\n this.model = inner.model;\n }\n\n // ── Overridden: stream via WebSocket ──────────────────────────────────────\n\n async *stream(\n query: string,\n options?: CompletionOptions,\n ): AsyncGenerator<CompletionEvent> {\n const requestId = uuid();\n\n // Build message history (single user message for now — matches HTTP path)\n const messages = [{ role: 'user', content: query }];\n\n const sent = this.#opts.send(JSON.stringify({\n type: 'CHAT_COMPLETION',\n requestId,\n messages,\n }));\n\n if (!sent) {\n yield { type: 'error', message: 'WebSocket not connected' };\n return;\n }\n\n // Create a promise-based event queue\n type QueueItem =\n | { done: false; event: ChatStreamServerEvent }\n | { done: true };\n\n const queue: QueueItem[] = [];\n let resolve: (() => void) | null = null;\n let finished = false;\n\n const unsubscribe = this.#opts.subscribe(requestId, (event) => {\n if (finished) return;\n queue.push({ done: false, event });\n resolve?.();\n });\n\n const cleanup = () => {\n finished = true;\n unsubscribe();\n };\n\n // Handle abort signal\n if (options?.signal) {\n options.signal.addEventListener('abort', () => {\n cleanup();\n queue.push({ done: true });\n resolve?.();\n }, { once: true });\n }\n\n try {\n let fullText = '';\n\n while (true) {\n if (queue.length === 0) {\n await new Promise<void>((r) => { resolve = r; });\n resolve = null;\n }\n\n const item = queue.shift();\n if (!item || item.done) break;\n\n const evt = item.event;\n\n switch (evt.type) {\n case 'CHAT_STREAM_START':\n // No CompletionEvent for start — just skip\n break;\n\n case 'CHAT_STREAM_DELTA':\n fullText += evt.delta;\n yield { type: 'text_delta', text: evt.delta };\n break;\n\n case 'CHAT_STREAM_DONE':\n yield { type: 'done', answer: fullText };\n cleanup();\n return;\n\n case 'CHAT_STREAM_ERROR':\n yield { type: 'error', message: evt.error };\n cleanup();\n return;\n }\n }\n } finally {\n cleanup();\n }\n }\n\n // ── Delegated to inner HTTP session ───────────────────────────────────────\n\n state(): SessionState { return this.#inner.state(); }\n setModel(model: string): Promise<void> { return this.#inner.setModel(model); }\n status(signal?: AbortSignal): Promise<DocumentStatus> { return this.#inner.status(signal); }\n wait(options?: WaitOptions): Promise<DocumentStatus> { return this.#inner.wait(options); }\n pages(options?: { range?: string; signal?: AbortSignal }): Promise<Page[]> { return this.#inner.pages(options); }\n page(pageNumber: number, signal?: AbortSignal): Promise<Page> { return this.#inner.page(pageNumber, signal); }\n entities(options?: { type?: string; limit?: number; offset?: number; signal?: AbortSignal }): Promise<EntitiesResponse> { return this.#inner.entities(options); }\n downloadUrl(): string { return this.#inner.downloadUrl(); }\n query(sql: string, signal?: AbortSignal): Promise<QueryResult> { return this.#inner.query(sql, signal); }\n logs(options?: import('./types').LogsOptions): Promise<import('./types').LogEntry[]> { return this.#inner.logs(options); }\n publish(signal?: AbortSignal): Promise<PublishResult> { return this.#inner.publish(signal); }\n shareLink(options?: ShareLinkOptions): Promise<ShareLinkResult> { return this.#inner.shareLink(options); }\n\n prompt(query: string, options?: GenerateOptions & { schema?: undefined }): Promise<GenerateResult>;\n prompt<T>(query: string, options: GenerateOptions & { schema: StructuredSchema<T> }): Promise<GenerateResult<T>>;\n prompt<T = undefined>(query: string, options?: GenerateOptions): Promise<GenerateResult<T>> {\n if (options?.schema !== undefined) {\n return this.#inner.prompt(query, options as GenerateOptions & { schema: StructuredSchema<unknown> }) as Promise<GenerateResult<T>>;\n }\n return this.#inner.prompt(query, options as GenerateOptions & { schema?: undefined }) as Promise<GenerateResult<T>>;\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
- import { O as OkraClient } from '../client-CyA8BgrE.js';
3
- import { O as OkraSession, g as DocumentStatus, P as Page, k as StructuredSchema, j as GenerateResult } from '../types-DpLY63Cg.js';
4
- export { i as CompletionEvent } from '../types-DpLY63Cg.js';
2
+ import { O as OkraClient } from '../client-CdCU6Div.js';
3
+ import { O as OkraSession, i as DocumentStatus, P as Page, n as StructuredSchema, m as GenerateResult } from '../types-58dvD4Yj.js';
4
+ export { l as CompletionEvent } from '../types-58dvD4Yj.js';
5
5
  import 'zod';
6
6
 
7
7
  interface OkraContextValue {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createOkra
3
- } from "../chunk-Y72DLYYO.js";
4
- import "../chunk-EZLAOKOP.js";
3
+ } from "../chunk-ADVWUO22.js";
4
+ import "../chunk-XM4MS5WV.js";
5
5
  import "../chunk-NIZM2ETT.js";
6
6
 
7
7
  // src/react/provider.ts
@@ -110,6 +110,21 @@ interface QueryResult {
110
110
  rows: Record<string, unknown>[];
111
111
  columns: string[];
112
112
  }
113
+ interface LogEntry {
114
+ seq: number;
115
+ event: string;
116
+ actor_type: string;
117
+ actor_id: string;
118
+ target_id: string | null;
119
+ detail: string;
120
+ created_at: number;
121
+ prev_hash: string;
122
+ chain_hash: string;
123
+ }
124
+ interface LogsOptions {
125
+ limit?: number;
126
+ signal?: AbortSignal;
127
+ }
113
128
  /** Events yielded by `session.stream()` / `client.stream()`. */
114
129
  type CompletionEvent = {
115
130
  type: 'text_delta';
@@ -189,6 +204,7 @@ interface OkraSession {
189
204
  }): Promise<EntitiesResponse>;
190
205
  downloadUrl(): string;
191
206
  query(sql: string, signal?: AbortSignal): Promise<QueryResult>;
207
+ logs(options?: LogsOptions): Promise<LogEntry[]>;
192
208
  publish(signal?: AbortSignal): Promise<PublishResult>;
193
209
  shareLink(options?: ShareLinkOptions): Promise<ShareLinkResult>;
194
210
  prompt(query: string, options?: GenerateOptions & {
@@ -424,4 +440,4 @@ interface DocUrlOptions {
424
440
  output?: string;
425
441
  }
426
442
 
427
- export type { ShareLinkCapabilities as A, ShareLinkLinks as B, CollectionSummary as C, DocUrlOptions as D, EntitiesResponse as E, StructuredOutputMeta as F, GenerateOptions as G, UploadRedactOptions as H, UploadRedactPiiOptions as I, JsonSchema as J, OkraSession as O, Page as P, QueryResult as Q, RuntimeErrorCode as R, SessionCreateOptions as S, UrlBuilderOptions as U, WaitOptions as W, DeliveryTransform as a, UploadInput as b, SessionAttachOptions as c, Collection as d, OkraClientOptions as e, UploadOptions as f, DocumentStatus as g, CompletionOptions as h, CompletionEvent as i, GenerateResult as j, StructuredSchema as k, PublishResult as l, ShareLinkOptions as m, ShareLinkResult as n, SessionState as o, StructuredOutputErrorCode as p, CollectionDocument as q, CollectionQueryEvent as r, CollectionQueryOptions as s, CollectionQueryResult as t, CollectionQueryStream as u, DocumentAnswer as v, Entity as w, OkraCollections as x, PageBlock as y, PageEntity as z };
443
+ export type { PageEntity as A, ShareLinkCapabilities as B, CollectionSummary as C, DocUrlOptions as D, EntitiesResponse as E, ShareLinkLinks as F, GenerateOptions as G, StructuredOutputMeta as H, UploadRedactOptions as I, JsonSchema as J, UploadRedactPiiOptions as K, LogsOptions as L, OkraSession as O, Page as P, QueryResult as Q, RuntimeErrorCode as R, SessionCreateOptions as S, UrlBuilderOptions as U, WaitOptions as W, DeliveryTransform as a, UploadInput as b, SessionAttachOptions as c, Collection as d, CollectionQueryOptions as e, CollectionQueryStream as f, OkraClientOptions as g, UploadOptions as h, DocumentStatus as i, LogEntry as j, CompletionOptions as k, CompletionEvent as l, GenerateResult as m, StructuredSchema as n, PublishResult as o, ShareLinkOptions as p, ShareLinkResult as q, SessionState as r, StructuredOutputErrorCode as s, CollectionDocument as t, CollectionQueryEvent as u, CollectionQueryResult as v, DocumentAnswer as w, Entity as x, OkraCollections as y, PageBlock as z };
package/dist/url.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as DocUrlOptions, U as UrlBuilderOptions, a as DeliveryTransform } from './types-DpLY63Cg.js';
1
+ import { D as DocUrlOptions, U as UrlBuilderOptions, a as DeliveryTransform } from './types-58dvD4Yj.js';
2
2
  import 'zod';
3
3
 
4
4
  interface PgPage {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okrapdf",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "OkraPDF — upload a PDF, get an API. Runtime client, React hooks, and CLI.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -76,6 +76,21 @@
76
76
  "vitest": "^2.0.0"
77
77
  },
78
78
  "license": "MIT",
79
+ "repository": {
80
+ "type": "git",
81
+ "url": "https://github.com/okrapdf/okrapdf-sdk"
82
+ },
83
+ "homepage": "https://okrapdf.com",
84
+ "author": "OkraPDF",
85
+ "keywords": [
86
+ "pdf",
87
+ "ocr",
88
+ "document",
89
+ "extraction",
90
+ "api",
91
+ "sdk",
92
+ "structured-output"
93
+ ],
79
94
  "publishConfig": {
80
95
  "access": "public"
81
96
  }
@@ -1 +0,0 @@
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 CollectionSummary,\n CompletionEvent,\n CompletionOptions,\n DocumentStatus,\n EntitiesResponse,\n GenerateOptions,\n GenerateResult,\n JsonSchema,\n Page,\n PublishResult,\n QueryResult,\n RuntimeErrorCode,\n ShareLinkOptions,\n ShareLinkResult,\n SessionAttachOptions,\n SessionCreateOptions,\n SessionState,\n OkraSession,\n StructuredOutputErrorCode,\n StructuredSchema,\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\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 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\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 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 };\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.dev/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 };\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 // ─── 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': 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 // ─── 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 // ─── 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 // ─── 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"]}