v1.6.0 — AWS Bedrock engine, friendly PDF errors, animated splash, setup wizard#20
Merged
Conversation
Adds a built-in 'AWS Bedrock' conversion engine that talks to bedrock-runtime directly using AWS Signature V4 — no boto3, no LiteLLM proxy required. Uses the Bedrock Converse API so a single code path handles any vision-capable model (Claude, Nova, Llama-vision, …). - converters.py: _sigv4_signing_key/_bedrock_invoke (stdlib hmac+hashlib SigV4) + convert_bedrock(); HTTPError bodies surfaced as clean messages; cost table extended with Bedrock-style family ids (sonnet/haiku/opus/nova). - config.py: bedrock_access_key/secret_key/session_token/region/model defaults. - app.py: engine dispatch, engine-combo entry, cost-estimate lookup, and a Settings group for AWS credentials/region/model. - README: document the eighth engine. Signing-key derivation verified against the AWS SigV4 reference vector; request building and Converse response parsing covered by a mocked smoke test.
Root cause: convert_native, convert_pdfplumber and the LLM page runner all opened the PDF via pymupdf.open()/pdfplumber.open() and used it without checking doc.needs_pass (encryption) or catching FileDataError (corrupt / not-a-PDF). The worker also opened the file early just to read page_count. Any such failure propagated as a raw library exception to the worker's generic 'except Exception: failed.emit(traceback.format_exc())', which the dialog then printed verbatim — the scary 'Conversion failed + stack trace' experience (the KeyError dialog was one instance of this). Fix (defense in depth): - converters: add ConversionError (user-facing, message shown as-is) and PdfError; add _open_pdf() that validates and raises a clear message for password-protected and corrupt/invalid PDFs. Route convert_native, convert_pdfplumber and _run_llm through it. Promote the OpenAI/Bedrock backend errors and the 'pdfplumber not installed' error to ConversionError so they surface cleanly too. - app: validate the worker's early page_count open via _open_pdf, and catch converters.ConversionError to emit the clean message instead of a traceback (unexpected errors still show the traceback). Adds test/test_error_handling.py (encrypted + malformed fixtures) — was RED before the fix, GREEN after.
The launch splash was PyInstaller's static --splash icon.png, which cannot animate and showed a coloured border. Replace it with a pure-Qt splash (_SplashScreen) shown from main(): - Frameless, translucent, rounded PyDracula card with NO border. - Three beats: fade-in (windowOpacity) -> gentle 'breathing' of the brand mark (a looped 'pulse' property that scales the logo 0.93->1.0 and swells an accent-purple glow) -> fade-out, then the main window is revealed. - main() shows the splash, builds the window after the fade-in plays, then fades out with a minimum on-screen time so the breathing is seen. - release.yml: drop --splash (the app now provides its own animated splash). Verified by rendering the splash offscreen: transparent corners (no border), logo + wordmark paint correctly.
A QWizard that opens on first launch and from a '✨ New Project' button in the sidebar. Flow: Welcome → goal → engine → finish. - Four goals (study / convert / tables & data / research papers); each pre-selects a sensible engine and pre-enables the right options (e.g. tables→pdfplumber, research→math-mode, study→strip headers/footers and lands on Courses). - Engine step offers all engines with just the credential fields each one needs (key / region / base url / model), pre-filled from cfg. - On finish it writes settings to cfg, marks wizard_completed, applies them to the Convert page, and (optionally) navigates: Courses + new-course prompt for study, Convert + file picker otherwise. - First-run trigger fires from MainWindow.showEvent (after the splash reveals the window); cancelling first-run sets wizard_completed so it doesn't nag. Sidebar button reopens it anytime; hidden when collapsed. - config: add wizard_completed default. ConvertPage.apply_cfg() pushes cfg back into the widgets (reverse of _sync_cfg). Verified headless: 4 pages, goal→engine defaults, credential capture, option merge on finish, and MainWindow builds with the new button.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings
mainup to date with the v1.6.0 work (5 commits):bedrock-runtimedirectly via stdlib SigV4 (no boto3, no proxy), using the Converse API so any vision model works (Claude, Nova, Llama-vision). Settings UI + cost estimates included.ConversionError/PdfError+ a validated_open_pdf(), with a regression test (test/test_error_handling.py).--splash(the pink-border source) with a pure-Qt splash: fade-in → breathing logo → fade-out.All changes verified offline (regression test green; splash/wizard rendered headless; SigV4 checked against the AWS reference vector).
https://claude.ai/code/session_01Czo3Yd5iE3p8BnoqPHYmv6
Generated by Claude Code