0.3.1-beta.0
Pre-release
Pre-release
·
16 commits
to master
since this release
💥 BREAKING CHANGES
-
due to
7cd348f- ✨ Add cloud API integration with authentication and credits (PR #48 by @jorben):Settings page now defaults to Account tab instead of Model Service
Co-Authored-By: Claude (anthropic/claude-opus-4.5) noreply@anthropic.com- feat(i18n): ✨ add internationalization for cloud features
Add i18n support for cloud-related UI components across all 6 languages:
- AccountCenter: translate account management, credit balance, and history
- UploadPanel: translate cloud provider and model names, status messages
- Layout: translate user profile tooltip
- List: translate cloud/local task type labels
- Settings: translate account tab label
Add new account.json namespace with translations for: - Account center title and sign in/out buttons
- Credit balance section (monthly free, paid credits)
- Credit history table columns and type labels
Co-Authored-By: Claude (anthropic/claude-opus-4.5) noreply@anthropic.com
- feat(i18n): ✨ update credit description texts for account center
- Change paid credits description to "$1 USD = 1,500 credits"
- Change free credits description to monthly quota with UTC+0 reset time
- Rename "Monthly Free Credits" to "Free Credits" across all locales
- Remove unused reset_hint and never_expire fields
- Align description layout between free and paid credit cards
Co-Authored-By: Claude (anthropic/claude-opus-4.5) noreply@anthropic.com
- refactor(ui): ♻️ remove local task type icon from task list
Remove HomeOutlined icon for local tasks, keeping only cloud icon indicator.
Co-Authored-By: Claude (anthropic/claude-opus-4.5) noreply@anthropic.com - fix(types): 🐛 resolve TypeScript type errors in cloud integration
- Remove unused imports in CloudService (net, fs, path, FormData)
- Add missing getCreditHistory method to CloudService
- Remove unused imports in Layout (Space, GithubOutlined)
- Remove unused openExternalLink function in Layout
- Add cloud API types to WindowAPI and ElectronAPI interfaces
- Add window, platform, and app types to electron.d.ts
- Add hasRunningTasks type to task API interface
- Create CloudFileInput interface for flexible file type handling
- Fix UploadPanel to properly convert UploadFile to CloudFileInput
Co-Authored-By: Claude (anthropic/claude-opus-4.5) noreply@anthropic.com
- feat(auth): ✨ add custom protocol handler for OAuth callback
Implement deep linking support for OAuth authentication flow:
- Register markpdfdown:// custom protocol for all platforms
- Handle OAuth callback URLs in main process
- Add IPC bridge to forward auth events to renderer
- Replace Clerk modal with inline SignIn component
- Configure ClerkProvider with allowedRedirectProtocols
- Add onOAuthCallback mock to test setup
Co-Authored-By: Claude (anthropic/claude-opus-4.5) noreply@anthropic.com
- feat(auth): ✨ replace Clerk SDK with device flow authentication
Remove @clerk/clerk-react dependency and implement a custom device flow
(RFC 8628) authentication system via AuthManager. The new flow:
- Main process manages tokens (access + refresh) with encrypted storage
- Renderer receives auth state changes via IPC event bridge
- AccountCenter UI shows user code for browser-based authorization
- CloudService retrieves tokens from AuthManager instead of receiving
them from the renderer
Also updates IPC channels, preload bridge, type definitions, i18n
strings, and test mocks to align with the new auth architecture.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(auth): 🐛 unwrap API response in fetchUserProfile
The fetchUserProfile method was assigning the raw API response
directly to userProfile instead of extracting the nested data
field. Since the API returns { success, data: CloudUserProfile },
the user's name, email, and avatar_url were all undefined in the
renderer, causing avatar and username not to display after login.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - feat(auth): ✨ 添加自定义 User-Agent 和自动 token 刷新功能
在 AuthManager 中添加以下改进:
- 添加 buildUserAgent() 函数,为所有 API 请求设置自定义 User-Agent 头
- 添加 fetchWithAuth() 方法,自动携带认证令牌并在 401 时自动刷新 token
- 所有 API 请求现在都包含 User-Agent 和正确的认证头
- 改进登出流程,使用 fetchWithAuth 处理认证失败情况
此变更提高了 API 调用的可追踪性和认证流程的健壮性。
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- feat(cloud): ✨ integrate credits API with real backend
Replace mock credit data with actual API calls:
- Add getCredits() endpoint to fetch current balance
- Add type filter support for credit history
- Update UI to show monthly and daily credit balances
- Add 7 credit transaction types (consume, topup, refund, etc.)
- Add TypeScript types for CreditsApiResponse
🤖 Generated with Claude Code
- feat(cloud): ✨ add multi-tier cloud model selection
Add three cloud model tiers with different credit pricing:
- Fit Lite: ~10 credits/page
- Fit Pro: ~20 credits/page
- Fit Ultra: ~60 credits/page
Changes: - Update model selector to display 3 options with i18n support
- Pass selected model tier through IPC to cloud conversion
- Add translations for all 6 supported languages
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- feat(cloud): ✨ add credit usage hint to Account page
Add i18n text explaining credit consumption rates for different
cloud models (Lite/Pro/Ultra) displayed next to Credit Balance title.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - feat(cloud): ✨ implement POST /api/v1/convert API integration
Replace mock implementation with real API call to create cloud conversion tasks:
- Add CreateTaskResponse and CloudModelTier types
- Use FormData for multipart/form-data file upload
- Support both file path and content as input
- Handle API errors properly with structured response
- Default to 'lite' model tier if not specified
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- feat(cloud): ✨ implement full task management API integration
Replace mock data with real cloud API calls for complete task
lifecycle management. This covers all 10 API endpoints from the
client integration guide:
Backend integration:
- Replace mock getTasks with GET /api/v1/tasks
- Add getTaskById, getTaskPages, cancelTask, retryTask,
retryPage, getTaskResult, downloadPdf methods to CloudService - Create CloudSSEManager for real-time task event streaming
with auto-reconnect, exponential backoff, and heartbeat
IPC & Preload: - Add 13 CLOUD IPC channels and CLOUD_TASK_EVENT event
- Register 9 new IPC handlers in cloud.handler.ts
- Expose all new methods and onCloudTaskEvent in preload bridge
Renderer: - Extend CloudContext with 7 new actions and SSE lifecycle
- Create cloudTaskMapper utility for API response mapping
- Update List page with cloud task actions and SSE live updates
- Create CloudPreview page for viewing cloud task results
- Add cloud-preview i18n translations for all 6 locales
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- feat(cloud): ✨ display page images in cloud task detail
Add page image support to CloudPreview component by:
- Add image_url field to CloudTaskPageResponse type
- Add getPageImage IPC channel and handler for proxying image requests
- Implement dual URL handling:
- Update CloudPreview left panel to display page images
- Handle image loading states and errors gracefully
This enables users to view the original PDF page images alongside
their markdown conversion results in cloud task details.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(auth): ⚡️ speed up token acquisition after OAuth callback
Add checkDeviceTokenStatus() method to immediately verify token status
when receiving protocol URL callback, instead of waiting for next polling
interval. This reduces token acquisition latency from ~5s to milliseconds.
The implementation:
- Calls /api/v1/auth/device/token immediately on callback
- Stops polling after successful token acquisition
- Handles 428 (authorization_pending) gracefully by continuing polling
- Thread-safe: concurrent requests don't cause issues
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- feat(cloud): ✨ display model tier in task list
Add model_tier field to CloudTaskResponse type and use it for
displaying the correct model tier (lite/pro/ultra) in the task list.
Previously the code incorrectly used status_name for model tier mapping.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(cloud): align model tier display with upload panel
Change task list model name from "Cloud Lite/Pro/Ultra" to
"Fit Lite/Pro/Ultra" to match the upload panel selector.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - feat(cloud): ✨ implement cloud task deletion with terminal state guard
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(cloud): 🐛 refresh credit balance when entering account page
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(ui): 🐛 fix account page content overflow by enabling tab-level scrolling
- Add height: 100vh and minHeight: 0 to Layout content area so flex
children get a constrained height - Make Settings Tabs a flex column filling its container, with only
the tab content holder scrolling (tab bar stays fixed) - Add scrollbar styles for settings-tabs consistent with existing
model-service-tabs
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- feat(cloud): ✨ add page_range support to cloud convert API
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(cloud): 🐛 prevent duplicate SSE connections causing repeated events
The cloud task list received each SSE event 3 times because multiple
SSE connections were being established concurrently:
- Main process auto-connect in initializeBackgroundServices
- Renderer CloudContext useEffect calling sseConnect on auth
- React re-renders causing disconnect+reconnect race conditions
Key changes:
- Remove main process SSE auto-connect; let renderer CloudContext
manage SSE lifecycle exclusively via IPC to avoid dual entry points - Set connected flag synchronously before any await in connect() to
prevent concurrent calls from passing the guard - Abort any lingering stream in startStream() before creating new one
- Use authManager.fetchWithAuth for automatic token refresh on 401
- Filter connected/heartbeat control events from renderer forwarding
- Fix page_completed counting to use page number (idempotent) instead
of naive increment that double-counts on SSE reconnect replay - Fix pdf_ready status mapping from SPLITTING(2) to PROCESSING(3)
- Move fetchTasks out of setState callback using queueMicrotask
- Add connected event type to CloudSSEEventType for type safety
- Reset lastEventId on disconnect to prevent cross-session replays
- Add diagnostic logging throughout SSE pipeline
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- feat(cloud): ✨ update credit transaction types for pre-auth billing model
- Replace consume_settle/page_retry with pre_auth, settle, pre_auth_release
- Add frozen fields to CreditsApiResponse for bonus and paid credits
- Fix description column to show API description instead of file_name
- Reorder credits column before description in history table
- Style pre_auth/pre_auth_release amounts as secondary (grey)
- Update transaction type translations for all 6 locales
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(cloud): 🐛 fix SSE event loss on reconnection by preserving Last-Event-ID
- disconnect() no longer resets lastEventId, preserving resumption point
- Add resetAndDisconnect() for explicit logout (clears lastEventId)
- Fix duplicate reconnect by clearing pending reconnectTimer
- Skip redundant reconnect when stream is aborted (not naturally ended)
- Log Last-Event-ID in reconnect/connect for debugging
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(auth): 🐛 distinguish transient vs permanent token refresh failures
- Add AuthTokenInvalidError for definitive auth failures (401/403)
- Only clear refresh token on permanent failures, keep it for transient errors
- Add retry logic for auto-refresh with exponential backoff
- Schedule init retry on transient failure during session restore
- Fix getAccessToken to attempt refresh when access token is missing
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- perf(cloud): ⚡️ reduce task list polling frequency to lower server load
Active tasks: 10s → 60s, idle: 30s → 120s. Real-time updates
are handled by SSE, polling serves only as a fallback.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - refactor(cloud): ♻️ align cloud preview actions with local task behavior
- Remove Download PDF entry from More Actions menu
- Add retry failed pages action (status=8 with failed pages)
- Add delete action for terminal-state tasks
- Use Dropdown.Button pattern matching local Preview
- Add i18n keys for all 6 locales
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(list): 🐛 fix pagination and sorting for combined local/cloud task list
- Fetch up to 100 items from each source, then paginate locally
- Add unified sortTimestamp field to CloudTask for cross-source sorting
- Sort combined list by timestamp (newest first) before pagination
- Fix pagination total to include both local and cloud task counts
- feat(cloud): ⏱️ add 8-second timeout to cloud API requests
Add timeout support to AuthManager.fetchWithAuth() using AbortController.
Both initial requests and 401 retry requests now have 8-second timeout.
SSE heartbeat timeout (90s) remains unchanged.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - feat(cloud): 🏷️ add provider name to cloud task model display
Append provider name 'Markdown.Fit' to cloud task model_name field
for clearer identification of cloud tasks in the task list.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - feat(upload): ✨ add Office file support for cloud conversion
Add support for selecting and uploading Office documents (doc, docx, xls, xlsx, ppt, pptx) when using cloud conversion with authenticated users.
- Add allowOffice parameter to file select dialog
- Add file type detection (pdf, image, office, unsupported)
- Show appropriate hints when Office files are not supported
- Add validation to prevent unsupported file types
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(cloud): ⏱️ adjust timeout based on request type
- FormData uploads: 120s timeout
- Download requests (/result, /download): no timeout
- Other API requests: 8s timeout
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- test(renderer): ✅ align list and preview tests with latest UI behavior
- chore(account): 🚧 disable recharge button until feature is ready
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(ci): 🐛 improve LLM PR review reliability for large diffs
- Reduce max diff size from 128KB to 64KB to avoid exceeding LLM context limits
- Replace silent curl failure with explicit HTTP status code checking and error output
- Add timeout (120s for LLM API, 30s for GitHub API) to prevent hanging requests
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(ci): 🐛 fix broken pipe error in diff truncation
Replace printf|head pipe with bash substring expansion to avoid
SIGPIPE under set -o pipefail when diff exceeds max size.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(ci): 🔧 restore max diff size to 128KB
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(ci): 🐛 fix jq argument list too long for large diffs
Use --rawfile to pass system prompt and diff content via temp files
instead of --arg CLI arguments, avoiding ARG_MAX limit on Linux.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(ci): 🐛 fix curl argument list too long for LLM request
Write request body to temp file and use curl -d @file syntax
to avoid ARG_MAX limit when sending large diffs to LLM API.
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com - fix(cloud): 🔒 address PR review security and quality issues
- Prevent refresh token plaintext persistence when encryption unavailable
- Strict-validate protocol URL paths (only allow auth/callback)
- Add missing page_range field to cloud.convert type definition
- Gate SSE verbose logging behind isDev check for production perf
- URL-encode all path parameters in CloudService API calls
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(cloud): 🔒 address second round PR review issues
- Add 100MB file size limit validation in cloud:convert IPC handler
- Normalize protocol URL path (lowercase, deduplicate slashes, decode)
- Deduplicate concurrent refresh token calls with in-flight promise
- Await shell.openExternal and handle browser launch failures
- Normalize CRLF to LF in SSE stream parser for server compatibility
- Sanitize Content-Disposition filename with path.basename and char filter
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(cloud): 🔒 address third round PR review issues
- Use async fs.readFile instead of sync readFileSync for upload (unblock main)
- Use async fs.promises.stat in cloud handler for file size validation
- Safe decodeURIComponent in protocol URL handler (catch malformed encoding)
- Replace brittle URL-substring timeout detection with explicit timeoutMs option
- Add content-type validation for SSE stream (reject non text/event-stream)
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(cloud): 🐛 fix SSE abort signal and normalize timeout errors
- Compose caller signal with timeout signal in fetchWithAuth using AbortSignal.any
- SSE disconnect/reconnect now reliably aborts in-flight fetch requests
- Normalize timeout AbortError to 'Request timeout' for better UX
- Remove duplicate comment line in UploadPanel
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- fix(cloud): 🔒 harden protocol URL validation and signal compatibility
- Validate protocol URL host structurally without decodeURIComponent
- Reject percent-encoded characters in host to prevent bypass
- Add AbortSignal.any fallback for older runtimes
- Reset SSE connected flag on startStream failure to prevent deadlock
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- feat(i18n): ✨ add internationalization for cloud features