Combine the PR review fixes for push import validation, deduplication, system sender handling, and pull import lock scoping into one reviewable change.
- Change default port from 5200 to 3110 in sync config-manager, Vue store,
and settings UI to match CLI DEFAULT_API_PORT
- Desktop API server now tries up to 10 consecutive ports when preferred
port is occupied (e.g. CLI already running); reports actual bound port
- Scope Desktop import route lock to session (Set<string>) matching the
push-importer fix
- Docs: remove unimplemented JSONL/X-Dry-Run claims, fix port references,
replace platform-specific examples with generic ones
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When the first small response is empty with hasMore=false and carries
sync.nextSince, the file was deleted before that cursor value was saved.
If retry pages also omit nextSince, nextPullSince stays at the old
lastPullAt and the next poll re-fetches the same completed tail window.
Fold sync0.nextSince into nextPullSince immediately after cleanupTempFile,
before the retry loop, matching the existing pattern for retry pages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PullEngine gains an onSessionImported hook (hook errors never fail the
pull), wired in both the CLI server and Electron main to silently fill
session owner from the stored platform profile. The chatlab import CLI
command does the same after a successful import.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add "type": "module" to all workspace package.json files
- Replace __dirname with import.meta.url-based resolveCliPath() helper
- Convert stream-json/stream-chain CJS named imports to default + destructure
for ESM compatibility
- Use createRequire() for @node-rs/jieba native module loading in ESM context
Co-authored-by: Cursor <cursoragent@cursor.com>
P1: Small terminal pages with hasMore=false were incorrectly treated as
empty based on file size alone, causing valid messages to be silently
dropped. Now checks actual message content via fileContainsMessages().
P1: Retry import results were not validated, so import failures (including
needFullResync) were masked as success. Now properly handles all failure
cases and tracks retryHasMore to exit the retry loop correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
50 pages (50k messages) was too low for groups with 100k+ messages.
Raise to 5000 pages (5M messages) as a safety valve while allowing
full-sync to complete in a single pull cycle for most conversations.
- Show confirmation dialog with two choices: keep data or delete imported chats
- Backend supports deleteData param across CLI routes and Electron IPC
- DataSourceManager.removeSession now returns the removed session info
- Add i18n strings for the delete confirmation dialog (zh-CN/en-US/ja-JP/zh-TW)
- Add multi-retry (3 attempts, 2s/3s/5s delays) for cold-start empty responses
- Remove unused offset/end parameters from fetch URL construction
- Fix Accept header to application/json only (avoids content negotiation issues)
- Add PullProgress type and progress tracking in PullEngine
- Export progress via getProgress() for frontend polling
When a pullAllSessions was already running, the reloadTimer triggered
by adding sessions would be skipped by the source-level concurrency
lock, causing newly added sessions to wait until the next scheduled
interval (up to 60 minutes) before syncing.
Fix: trigger individual per-session pulls via triggerPull(sourceId,
sessionId) which bypasses the source-level lock, ensuring immediate
sync for newly added sessions regardless of concurrent pulls.
Also includes: connection pre-check on data source add, removal of
duplicate "browse remote sessions" button, hiding "other" session
types, and full resync fix for deleted local sessions.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Fix subscription sync not showing +xx: trigger foreground pull after
adding sessions instead of relying on background scheduler
- Fix negative message count (+-N): use messageCount directly as it
already represents net new writes after dedup
- Eliminate duplicated fullImportFile: delegate to importData() to avoid
missing fields (avatar, roles, reply_to_message_id, group_avatar)
- Fix member avatar not displaying in CLI Web: SQL alias mismatch
(avatar vs senderAvatar)
- Add skipInitialPull param to scheduler to avoid race with foreground pull
- Add @openchatlab/sync to server package.json for proper tsx watch support
Extract platform-agnostic sync logic (config, data source, discovery,
pull engine, scheduler) into @openchatlab/sync. Implement server-side
adapters (NodeFetcher, DirectImporter, NoopNotifier) and HTTP routes
(/_web/automation/*) for the CLI web UI. Adapt Pinia store with
dual-transport (IPC for Electron, HTTP for Web).