Commit graph

52 commits

Author SHA1 Message Date
Richard R
46c4be614d refactor(pdf-parse): extract encodeParserVersion utility and strengthen artifact readiness
Move encodeParserVersion to a dedicated module for unified access and remove local duplicates. Update all consumers to import from the new entrypoint. Tighten artifact readiness checks in both client and API route to ensure 'ready' is only reported when the artifact is accessible, with retries and stricter validation. Add tests for edge cases and operation state validation.
2026-06-04 20:46:02 -06:00
Richard R
7a86ce6a94 refactor(pdf-parse): migrate PDF parse state to worker-owned model
This change removes legacy server-side PDF parse state management and transitions
to a fully worker-owned model for PDF parsing operations. Key updates include:

- Deletes all code related to server-managed parse state, including:
  - parse-state.ts, parse-state-backfill.ts, parse-state-healing.ts,
    parsed-pdf-reuse.ts, pdf-parse-operation.ts, and related job logic
- Removes the user-pdf-layout-job queue and associated job logic
- Refactors API routes for parsed PDF documents and events to use the new
  worker-owned PDF parse operation flow under src/lib/server/pdf-parse/
- Updates S3 parsed PDF artifact keying to include parser version for
  deduplication and compatibility
- Refactors client API and hooks to handle new error and progress reporting
- Removes all tests for the legacy parse state and job system, updating remaining
  tests to mock the new worker-owned flow

BREAKING CHANGE: Server no longer manages per-user PDF parse state or jobs.
All PDF parsing is now managed by the compute worker and new artifact keying.
Legacy parse state and jobs are no longer supported. Existing parsed PDFs may
need to be reprocessed for compatibility with the new model.
2026-06-04 20:00:21 -06:00
Richard R
1074a60462 feat(build): improve Docker image layering and embed migration/worker tools
Refactor Dockerfile to optimize layering, embed entrypoint migration tools and compute worker as deployable bundles, and merge only required dependencies for runtime scripts. Add docker/entrypoint-migration-tools package and update workspace configuration. Refactor PDF parsing to resolve standard font data path robustly at runtime. Update dependencies and output config for Next.js standalone mode. Enhance entrypoint script to launch embedded compute worker from deployed bundle.

- Dockerfile now deploys migration tools and compute worker as separate bundles
- compute/core/pdf uses new pdfjs-runtime utility for robust font path resolution
- docker/entrypoint-migration-tools added for migration script dependencies
- scripts/openreader-entrypoint.mjs launches embedded worker from deployed bundle
- next.config.ts enables standalone output and includes standard_fonts in tracing
- Dependency updates across package.json and compute/worker/package.json

BREAKING CHANGE: Docker image structure and runtime entrypoint logic have changed; custom deployment scripts or Docker overrides may require updates.
2026-06-03 14:08:33 -06:00
Richard R
f0e0daae77
feat: improve PDF parsing recovery and reader UI (#98)
* refactor(ui): replace anchor tags with next/link in SidebarNavLink and UserMenu

Update SidebarNavLink to use next/link for navigation instead of anchor tags,
ensuring proper routing and improved accessibility in Next.js. Refactor UserMenu
to remove legacy Link wrappers and directly use SidebarNavLink for signin and
signup links. This streamlines navigation components and aligns with Next.js
best practices.

* fix(pdf): handle non-zero viewport origins and improve layout model ordering

Update normalizeTextItemsForLayout to correctly apply viewport transforms,
including non-zero page origins, ensuring accurate mapping of PDF text items
to top-left coordinates. Refactor runLayoutModel to implement a custom order
sequence builder for layout regions using model order logits, improving
region ordering consistency with model semantics. Update related tests to
cover viewport transform edge cases.

* refactor(pdf): improve text normalization with font ascent and vertical overlap logic

Enhance text normalization by incorporating font ascent and descent data to more accurately position glyphs, especially for decorative initials. Update merge logic to better detect line membership using vertical overlap, ensuring drop caps and overlapping glyphs are merged correctly. Extend tests to cover these layout scenarios.

* style(range): redesign slider with precision gauge and ruler ticks

Revamp the range input to feature a minimalist "precision gauge" style.
Introduce a hairline rail, ruler notches for discrete steps, and a slim
needle thumb. Add CSS variables and logic for per-instance tick sizing
and coloring. Remove bulky inline class-based styling in favor of
centralized CSS for improved maintainability and visual clarity.

* refactor(ui): modularize PDF loader and range slider visuals

Move PDF layout scan visualization and range slider styles into dedicated CSS
modules, isolating their styles from the global scope. Integrate PdfLayoutScan
component into the PDF viewer loader UI for animated parse progress. Refactor
progress bars to use a reusable progress-fill class with animated sheen effect.
Update range input to use CSS module for precision gauge styling.

* style(reader): remove grid overlay from PdfLayoutScan visualization

* refactor(api): add staleness detection for inflight worker operation states

Integrate isWorkerOperationStateStale checks into document parse API endpoints to ensure inflight worker operation states are not reused if stale. Introduce helper for staleness detection and corresponding unit tests. Enhance SSE event streaming with keepalive intervals and improve progress acknowledgment error handling.

* feat(worker): recover and fail stale in-flight pdf ops on startup

Add orphaned operation recovery logic to detect and mark stale in-flight pdf_layout jobs as failed during worker startup. Extend OperationStateStore with listOpStates for state enumeration. Update tests and documentation to cover recovery behavior and new environment variable COMPUTE_PDF_JOB_ATTEMPTS.

* refactor(worker): distinguish staleness thresholds for running and queued pdf ops

Update orphan recovery logic to apply separate timeouts for 'running' and
'queued' pdf_layout operations. Adjust tests to verify that only stale
'running' operations are failed, while stale 'queued' operations remain
untouched.

* feat(worker): extend orphan recovery to handle whisper_align ops and improve logging

Update orphan recovery to detect and fail stale 'running' whisper_align operations
in addition to pdf_layout. Refactor recovery logic to generalize staleness checks
across operation kinds and enhance log output with detailed operation info.
Expand tests to verify correct handling of both whisper_align and pdf_layout
operations in running and queued states.

* refactor(control-plane): introduce revision-based CAS for operation state updates

Add revision tracking and compare-and-set (CAS) semantics to operation state
stores, enabling atomic state transitions and preventing lost updates. Extend
the OperationStateStore interface with getOpStateRecord and compareAndSetOpState
methods. Update orchestrator and worker runtime to utilize CAS for marking
operations as failed only if the state is unchanged. Enhance in-memory,
JetStream, and test control plane implementations to support revision logic.

This change improves concurrency safety and correctness of operation state
management across distributed components.

* feat(ui): add parse failure state to PDF layout scan animation

Display a distinct "parse halted" visual state in the PDF layout scan
component and PDF viewer page when parsing fails. The loader animation
is replaced by a static, dimmed page with an alert glyph and updated
styling, ensuring users are not misled by an active animation after a
failure. CSS and component logic updated to support the new state.

* feat(worker): extract orphaned operation recovery to module with periodic sweep

Move orphaned operation recovery logic into a dedicated orphan-recovery module,
introducing a periodic sweep timer that triggers recovery every 15 seconds while
the worker is connected. Refactor runtime to delegate orphan detection and
handling to the new module, improving modularity and maintainability. Add
unit tests for orphan-recovery to ensure correctness.

* fix(ui): adjust PDF viewer layout and update parse loader description

* refactor(pdf): streamline layout model region extraction and update test coverage

- Replace custom order sequence logic with softmax-based class selection in runLayoutModel
- Remove unused sigmoid and buildOrderSequence functions
- Simplify detection loop to filter and map regions directly
- Add targeted tests for layout model extraction logic
- Update CSS animation naming for consistency
- Clarify test description and add inline comments for orphan recovery scenario

* fix(pdf): add strict validation for layout model output shapes and extend test coverage

Add explicit error handling for invalid or inconsistent pred_boxes and logits array lengths in runLayoutModel to prevent silent failures. Expand test suite to verify correct region filtering and error scenarios, ensuring only labeled regions are returned and malformed outputs are handled robustly.
2026-06-03 04:44:55 -06:00
Alex Errant
beea1961bf
Fix container crash on startup: onnxruntime-node requires glibc (switch Alpine → Debian slim) (#97)
* docker fixes

* fix(worker): default COMPUTE_PREWARM_MODELS to false and update docs, env, and compose

Set COMPUTE_PREWARM_MODELS to false by default in runtime, docker-compose,
and .env.example to avoid pre-downloading ONNX models during worker startup.
Update Dockerfile and deployment documentation to reflect this change and
clarify configuration for model prewarming.

* fix(docker): downgrade pnpm version to 10.33.4 for compatibility

---------

Co-authored-by: Richard R <me@richardr.dev>
2026-06-02 20:50:37 -06:00
Richard R
e1483ab80a refactor(worker): modularize worker entrypoint and add vitest infra
move worker startup logic from server.ts to runtime.ts for better modularity
add worker-loop-policy.ts for loop control abstraction
delete legacy unit tests under tests/unit/ related to compute worker and control-plane
add vitest config and test directories for compute-core and compute-worker
add vitest workflow for CI
update package.json scripts for new test commands and add vitest as dev dependency

BREAKING CHANGE: worker entrypoint is now compute/worker/src/runtime.ts instead of server.ts; legacy Playwright-based unit tests for compute worker are removed in favor of Vitest
2026-05-30 11:00:01 -06:00
Richard R
fe59685454 feat(worker): add granular PDF progress reporting and abort error handling
Introduce per-page progress events for PDF parsing by adding onPageStarted
hooks throughout the compute worker and core PDF pipeline. Add
compute/worker/src/pdf-progress.ts to encapsulate progress event builders.
Update server logic to emit page start and page parsed events, improving
client feedback during long-running PDF jobs.

Add src/lib/server/compute/abort-like-error.ts and integrate isAbortLikeError
to robustly detect and suppress expected aborts in API event streaming.
Update API route to ignore abort-like errors on worker proxy crash.

Add unit tests for abort-like error detection and PDF progress event
generation. Refactor PDF parse logic to allow empty merged regions without
throwing, ensuring downstream flows remain resilient to edge cases.

These changes improve observability, error handling, and reliability for
document parsing and event streaming.
2026-05-29 20:13:59 -06:00
Richard R
59d0101c0c feat(server): implement unified structured logging with pino and enforce usage
Introduce `serverLogger` utility based on pino for consistent, structured logging across all server and API modules. Replace direct console logging with `serverLogger` and add request-scoped logging helpers. Update environment variable handling, documentation, and deployment guides to reflect new logging configuration (`LOG_FORMAT`, `LOG_LEVEL`, `COMPUTE_LOG_LEVEL`). Enforce no-console in server code via ESLint and add pino/pino-pretty dependencies.

This change standardizes log output, improves observability, and prepares the codebase for ingestion by log platforms.
2026-05-27 04:20:17 -06:00
Richard R
5c24ea5763 docs(env): clarify env var ownership split for external compute worker mode
Expand documentation and example env files to explicitly distinguish which
environment variables belong in the app/root `.env` versus the `compute/worker/.env*`
files when deploying in external worker mode. This clarifies routing/auth
settings versus worker runtime configuration, reducing misconfiguration risk.
2026-05-27 01:19:37 -06:00
Richard R
cd530a365d refactor(whisper): migrate default ONNX model references to q4 variant
Update all configuration, manifest, and documentation references to use the q4
Whisper ONNX model files instead of int8. Adjust expected file names, hashes,
and environment variable descriptions to reflect this new default. This aligns
runtime, deployment, and developer documentation with the updated model artifact
expectations for improved consistency.
2026-05-26 19:22:07 -06:00
Richard R
1de7ed67b4 refactor(worker): extract op helpers and shared parse mapping 2026-05-26 18:54:11 -06:00
Richard R
0b1ce1c8dc refactor(worker): remove unused job_state kv writes 2026-05-26 18:47:53 -06:00
Richard R
02979a98af refactor(config): remove START_EMBEDDED_COMPUTE_WORKER env and enforce nats-server for embedded mode
Eliminates the START_EMBEDDED_COMPUTE_WORKER environment variable from configuration,
documentation, and entrypoint logic. Embedded compute worker startup is now strictly
determined by the absence of COMPUTE_WORKER_URL. If embedded mode is triggered,
the presence of the nats-server binary is mandatory; otherwise, an error is thrown.
Documentation and example env files have been updated to reflect this streamlined
behavior and clarify requirements for both embedded and external compute worker setups.
2026-05-26 17:37:18 -06:00
Richard R
e3ac1b1dac docs/env: clarify embedded vs external worker env ownership 2026-05-26 17:16:38 -06:00
Richard R
df05a7d7a3 refactor(control-plane): hard-cut worker events and shared SSE helpers 2026-05-26 11:41:33 -06:00
Richard R
084cbdfac1 refactor(worker-control-plane): route ops through core orchestrator 2026-05-26 11:16:54 -06:00
Richard R
cd06201f5c refactor(parse-progress): rely on sse reconnect and document mode behavior 2026-05-25 21:37:43 -06:00
Richard R
be7ec2c254 feat(worker-events): stream op events via jetstream and proxy in app 2026-05-25 21:37:27 -06:00
Richard R
12c586d7be refactor(core,server): migrate contracts to api-contracts and modularize job handlers
Move shared type contracts from `contracts` to new `api-contracts` module in `compute/core` for clearer API boundaries. Remove legacy `contracts`, `pdf`, and `whisper` index files. Update all imports to use `api-contracts`. Refactor server job logic by replacing `parsePdfJob.ts` with modular `user-pdf-layout-job.ts` and `user-whisper-align-job.ts`, updating all relevant API routes and compute integration. This improves maintainability and separation of concerns across compute and server layers.
2026-05-24 11:39:25 -06:00
Richard R
3dcda2b4b7 refactor(logging): enhance logger configuration and streamline event logging 2026-05-22 13:11:51 -06:00
Richard R
ad82aede73 feat(worker,whisper): improve logging for operation lifecycle and remove align mutex
Enhance worker operation handling by adding detailed logging for operation
acceptance, reuse, replacement, and stale detection, including opKey hashes and
reasons for replacement. Remove the alignMutex from Whisper alignment logic to
simplify concurrency control and reduce unnecessary serialization of alignment
requests. These changes improve observability and throughput for alignment and
layout parsing jobs.
2026-05-22 12:49:33 -06:00
Richard R
653dbedaee refactor(worker): add configurable NATS JetStream replica count
Introduce COMPUTE_NATS_REPLICAS environment variable to control the number of
replicas for JetStream streams and key-value buckets. Only values 1, 3, or 5
are accepted, defaulting to 1 for other inputs. Update worker server logic and
deployment documentation to describe and support this configuration.
2026-05-22 09:32:25 -06:00
Richard R
64a68b1011 docs(worker): document and implement idle-based NATS disconnect for Railway sleep
Add lazy NATS connection lifecycle and idle disconnect logic to the worker,
enabling automatic disconnection after 120s of inactivity to support Railway
container sleep. Update deployment docs to describe this behavior, including
caveats and reconnection flow.
2026-05-22 09:01:14 -06:00
Richard R
09e8898683 feat(pdf,config): implement stale parse-state healing and unify op stale window config
Introduce automatic healing for stale PDF parse states in API routes. Add
`isDocumentParseStateStale` utility and use a shared `COMPUTE_OP_STALE_MS`
environment variable (with config getter) to control the stale window for both
worker op replacement and app-side parse-state healing. Update documentation and
environment variable references to reflect new config.

Enables automatic marking of stuck parses as failed, improving reliability and
retry behavior in distributed compute environments.
2026-05-22 01:21:18 -06:00
Richard R
7a49ff9896 chore(lint): fix eslint violations in worker config and e2e tests 2026-05-21 21:44:58 -06:00
Richard R
37b6999c2c refactor(compute-core): collapse to root/local-runtime entrypoints 2026-05-21 21:30:44 -06:00
Richard R
37d11bf9b8 refactor(compute): remove legacy app whisper duplicate and unify core whisper boundary 2026-05-21 21:15:10 -06:00
Richard R
1612e6694b refactor(compute-core): capability-boundary exports for runtime and pdf-layout 2026-05-21 21:11:28 -06:00
Richard R
a29e6fc250 docs(compute): align worker env docs and model override vars 2026-05-21 20:57:10 -06:00
Richard R
51fbfa117d worker: avoid idle consumer blocking shared compute gate 2026-05-21 20:06:24 -06:00
Richard R
4664806ba0 worker: enrich single-line request logs with status and opId 2026-05-21 19:48:46 -06:00
Richard R
bcdff35200 worker: simplify request logs to single-line entries 2026-05-21 19:44:25 -06:00
Richard R
1f13ecaed9 worker: use default JetStream long-poll for consumer next 2026-05-21 19:04:16 -06:00
Richard R
c9dad9c23c compute: reuse shared timeout helpers across worker and local 2026-05-21 16:32:24 -06:00
Richard R
fbb6f484ce compute: centralize timeout config in compute-core and use in worker 2026-05-21 16:15:34 -06:00
Richard R
0d494cf5e5 docs(config): update PDF job attempts default to 1 for layout parsing
Align COMPUTE_PDF_JOB_ATTEMPTS default value with new ONNX-based PDF layout
parsing approach by setting it to 1 in environment examples, worker config,
and deployment documentation. This reflects improved reliability and reduces
unnecessary retries for PDF processing jobs.
2026-05-21 16:04:17 -06:00
Richard R
f8672b073e refactor(compute): unify job concurrency and CPU thread allocation logic
Standardize compute job concurrency configuration by introducing a shared
COMPUTE_JOB_CONCURRENCY setting, replacing separate PDF and Whisper concurrency
controls. Add cross-platform CPU core detection and thread budgeting utilities,
and update both ONNX model execution and concurrency limiters to use dynamic
thread allocation per job. Refactor environment variable docs and examples to
reflect unified concurrency management. Streamline PDF.js font path resolution
for improved reliability across environments.
2026-05-21 15:58:29 -06:00
Richard R
671d5c6adb feat(pdf,worker): enhance PDF layout parsing UX and add robust timeout controls
Introduce idle and hard cap timeouts for PDF layout parsing in the compute worker,
ensuring long-running jobs are capped and progress is tracked with explicit
timeouts. Refactor NATS JetStream client initialization to use a configurable
API timeout. Update PDF viewer UI to treat parse state as 'pending' by default,
improving clarity during document preparation and parsing. Refine parse loader
labels and progress logic for more accurate user feedback.
2026-05-21 13:50:40 -06:00
Richard R
a2c714c2a5 refactor(worker,tts): unify PDF and Whisper retry config, add alignment timeouts
Update compute worker to use separate environment variable for PDF job attempts
(`COMPUTE_PDF_JOB_ATTEMPTS`) and set Whisper job max deliveries to 1, clarifying
and separating retry logic between job types. Adjust `.env.example` and deployment
docs to comment out defaults and document new/renamed variables for advanced tuning.

In TTS segment ensure route, introduce explicit timeouts for Whisper alignment
operations, with configurable durations for local and worker modes, improving
robustness and error handling for long-running alignments.
2026-05-21 12:37:21 -06:00
Richard R
fe9104e8fc docs(pdf,spinner,config): update parse state UI, spinner theming, and worker env docs
Revise PDF viewer to introduce an explicit 'unknown' parse state and improve
loader and status messaging for better user clarity. Refactor Spinner to use
'currentColor' for border styling and simplify conditional rendering based on
className. Expand compute worker .env.example with explicit concurrency,
timeout, and job attempt variables for enhanced configuration transparency.
2026-05-21 11:59:12 -06:00
Richard R
4497f610c0 feat(pdf): implement granular PDF parse progress tracking and migrate to parseState
Introduce detailed progress reporting for PDF layout parsing, exposing phase and page-level updates to clients. Replace legacy parseStatus with a structured parseState field in the database schema, updating all relevant backend and API logic. Add SSE endpoint for real-time parse progress updates. Update client hooks and UI to reflect granular progress and improve user feedback during document parsing. Includes migration scripts and new parse-state utility module.
2026-05-21 10:27:16 -06:00
Richard R
a7b955e1ca refactor(worker): adopt operation-based API and opKey deduplication for compute flows
Migrate worker and backend contract to an operation-centric model, introducing opKey-based deduplication for Whisper alignment and PDF layout parsing. Add new operation request/state types and update worker endpoints to accept generic operation requests and expose operation status via SSE. Refactor client and server logic to support operation flows. Update deployment docs, environment examples, and Dockerfile to reflect new architecture and dependency management.
2026-05-21 09:05:26 -06:00
Richard R
49d9735237 refactor(worker): unify port environment variable usage and update deployment docs
Align compute worker to use PORT environment variable consistently across
Dockerfile, docker-compose, and server code, replacing COMPUTE_WORKER_PORT.
Update .env.example and deployment documentation to clarify platform-specific
behavior, especially for Railway and similar environments. This simplifies
configuration and reduces platform-specific issues.
2026-05-20 17:05:35 -06:00
Richard R
086329505f fix(worker): improve environment variable handling and URL normalization
Update worker server to prioritize platform-specific PORT environment variable
when setting the compute worker port. Add robust normalization for
COMPUTE_WORKER_URL, ensuring proper scheme and validation, and trim trailing
slashes for consistency. This enhances reliability in diverse deployment
environments.
2026-05-20 17:01:14 -06:00
Richard R
88809b826b fix(compute): unify PDF layout result handling with object key support
Update compute backend interfaces and job logic to consistently handle parsed
PDF layout results as either direct data or S3 object key references. Refactor
result types, local and worker backends, and job processing to support this
pattern. Improves flexibility for large document parsing and object storage
integration.
2026-05-20 15:38:24 -06:00
Richard R
4ddedee8ec docs(worker): document and expose JetStream storage limits for jobs and KV state
Add `COMPUTE_JOBS_STREAM_MAX_BYTES` and `COMPUTE_JOB_STATES_MAX_BYTES` to
environment example, worker server configuration, and deployment docs. These
variables allow tuning JetStream resource caps for job queue and state storage
to better fit deployment requirements.
2026-05-20 15:34:17 -06:00
Richard R
1bd13c02fe refactor(compute): modularize core contracts and runtime, enable flexible backend resolution
Restructure compute core by extracting job contracts and runtime logic into separate
modules (`contracts.ts`, `local-runtime.ts`) for improved modularity and clearer
API boundaries. Update exports and imports across worker, server, and local
compute backends to use the new modules. Enhance Next.js config to support
dynamic backend selection via build-time constants and aliasing, enabling
seamless switching between local and worker compute modes. Adjust TypeScript
paths and Dockerfile entrypoint to align with the new structure.
2026-05-20 15:07:22 -06:00
Richard R
3a1dd41d91 refactor(build): update Dockerfiles for improved dependency isolation and workspace handling
Remove legacy .npmrc config. Revise root and worker Dockerfiles to enhance
layer caching, explicitly copy only required build artifacts, and streamline
runtime dependencies. Switch to pnpm workspace-aware install for compute worker
to ensure correct dependency resolution. Set Next.js output to standalone mode
for optimized server builds. Update docker-compose sync targets for consistency.
2026-05-20 13:21:12 -06:00
Richard R
b30304a119 docs(worker): document NATS credentials options and update authentication support
Expand compute worker documentation to explain NATS authentication using
either a credentials file or raw credentials string, including Synadia Cloud
integration steps. Update environment variable examples and server connection
logic to support both `NATS_CREDS_FILE` and `NATS_CREDS`. Add `.creds` to
.gitignore to avoid accidental credential leaks.

This improves deployment flexibility for cloud and on-prem environments by
supporting multiple authentication methods for NATS JetStream.
2026-05-20 12:25:13 -06:00
Richard R
4b26531172 chore(worker): migrate compute worker from Redis/BullMQ to NATS JetStream
Replace Redis and BullMQ with NATS JetStream and KV for job queuing and state management
in the compute worker service. Update environment variables, Docker Compose, and documentation
to reflect the new message queue backend. Adjust dependencies and code to use NATS-based
work queue and key-value storage for durable job processing.

This change improves scalability and reliability of distributed compute workloads by leveraging
NATS JetStream's work queue and persistence features. Documentation and configuration examples
are updated to guide deployments using the new backend.
2026-05-20 07:38:03 -06:00