Description
When docutray convert --async starts polling, it never prints the conversion_id. If polling times out, the user has no way to recover the result later. Additionally, the polling timeout is hardcoded at 300s which is insufficient for large documents (e.g., 70 pages in multi_prompt mode).
Bundles TODO items #8 (expose conversionId) and #10 (configurable timeout).
Motivation
When a conversion times out after 5 minutes of polling, the user loses all ability to check the result because the conversion_id was never shown. The only recourse is to resubmit the document. For large documents that legitimately take longer than 300s, users need a way to extend the timeout.
Acceptance Criteria
Technical Approach
Expose conversionId (src/commands/convert.ts)
The SDK's runAsync returns a ConversionStatus with conversion_id. Currently at line 52:
const status = await client.convert.runAsync(params)
// status.conversion_id is available but never used
Changes:
- Print
conversion_id to stderr right after runAsync (line 52)
- Include
conversion_id in the onStatus callback output (lines 54-59)
- Wrap the
.wait() call in a try/catch to enrich timeout errors with the conversion_id
Add --timeout flag
Add a --timeout flag (in seconds) and pass it to the SDK's .wait() options:
const result = await status.wait({
timeout: flags.timeout * 1000, // convert to ms
onStatus(s) { /* ... */ },
})
Affected Components
src/commands/convert.ts (lines 51-62): Add --timeout flag, print conversion_id, enrich status and error output
test/commands/convert.test.ts: Add tests for conversion_id output and --timeout flag
Implementation Checklist
Testing Strategy
// Mock runAsync to return a status with conversion_id
const mockWait = vi.fn().mockResolvedValue({ status: 'SUCCESS', data: {} })
const mockRunAsync = vi.fn().mockResolvedValue({
conversion_id: 'conv_abc123',
status: 'ENQUEUED',
wait: mockWait,
})
await Convert.run(['file.pdf', '-t', 'invoice', '--async'])
// Verify conversion_id printed to stderr
expect(stderrSpy).toHaveBeenCalledWith(
expect.stringContaining('conv_abc123')
)
// Verify timeout passed to wait
await Convert.run(['file.pdf', '-t', 'invoice', '--async', '--timeout', '600'])
expect(mockWait).toHaveBeenCalledWith(
expect.objectContaining({ timeout: 600000 })
)
Dependencies
None — uses existing SDK runAsync and .wait() capabilities.
Considerations
- The
--timeout flag uses seconds (not ms) for user-friendliness, converted to ms before passing to SDK
- The
conversion_id is printed to stderr (not stdout) to avoid polluting the JSON result on stdout
- A future
docutray convert status <conversionId> subcommand (out of scope) could complement this by allowing manual status checks
Definition of Done
🤖 Generated with Claude Code
Description
When
docutray convert --asyncstarts polling, it never prints theconversion_id. If polling times out, the user has no way to recover the result later. Additionally, the polling timeout is hardcoded at 300s which is insufficient for large documents (e.g., 70 pages inmulti_promptmode).Bundles TODO items #8 (expose conversionId) and #10 (configurable timeout).
Motivation
When a conversion times out after 5 minutes of polling, the user loses all ability to check the result because the
conversion_idwas never shown. The only recourse is to resubmit the document. For large documents that legitimately take longer than 300s, users need a way to extend the timeout.Acceptance Criteria
conversion_idis printed to stderr immediately afterrunAsyncreturns (before polling starts)conversion_id⟳ Conversion cmnp36ska005d01tm5gxakfdl: PROCESSING{"conversionId":"cmnp36ska005d01tm5gxakfdl","status":"PROCESSING"}conversion_id--timeout <seconds>flag controls the polling timeout (default: 300)--timeoutvalue is passed to the SDK's.wait()methodTechnical Approach
Expose conversionId (
src/commands/convert.ts)The SDK's
runAsyncreturns aConversionStatuswithconversion_id. Currently at line 52:Changes:
conversion_idto stderr right afterrunAsync(line 52)conversion_idin theonStatuscallback output (lines 54-59).wait()call in a try/catch to enrich timeout errors with theconversion_idAdd --timeout flag
Add a
--timeoutflag (in seconds) and pass it to the SDK's.wait()options:Affected Components
src/commands/convert.ts(lines 51-62): Add--timeoutflag, printconversion_id, enrich status and error outputtest/commands/convert.test.ts: Add tests forconversion_idoutput and--timeoutflagImplementation Checklist
--timeoutflag definition (default: 300, description mentions seconds)conversion_idto stderr immediately afterrunAsyncconversion_idin eachonStatusoutput (both TTY and JSON)conversion_id+ recovery hinttimeout(in ms) to SDK.wait()methodconversion_idappears in stderr output--timeoutflag is passed to.wait()conversion_idTesting Strategy
Dependencies
None — uses existing SDK
runAsyncand.wait()capabilities.Considerations
--timeoutflag uses seconds (not ms) for user-friendliness, converted to ms before passing to SDKconversion_idis printed to stderr (not stdout) to avoid polluting the JSON result on stdoutdocutray convert status <conversionId>subcommand (out of scope) could complement this by allowing manual status checksDefinition of Done
npm run buildpassesnpm run testpasses🤖 Generated with Claude Code