After pull-sync imports new messages, generate session index incrementally
instead of full regeneration. This preserves existing sessions and their
summaries, only processing newly imported (unindexed) messages.
Adds generateIncremental method across the full stack:
- core: already had generateIncrementalSessionIndex
- node-runtime: expose generateIncrementalIndex
- CLI: add POST /_web/sessions/:id/generate-incremental-index route
- Electron: add session:generateIncremental IPC handler
- Frontend: add generateIncremental to SessionIndexAdapter interface
After importing messages via pull sync, automatically generate session
index for the affected sessions. This ensures the timeline and session
overview are immediately available without manual index generation.
After a sync finishes (triggerPull/triggerPullAll/onPullResult), reload the
session list so newly imported chats appear in the sidebar immediately.
Also refresh after removing a subscription with deleteData=true so the
deleted session disappears from the sidebar.
When the remote server doesn't return a `page` field and the result count
equals the requested limit, automatically re-fetch with limit=5000 to get
the complete session list instead of showing truncated results.
- 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
sessionExists() previously only checked file existence, causing pull sync
to enter incremental import path on invalid/empty DB files. Now validates
that the message table exists, and maps schema errors to needFullResync
as a safety fallback.
Add a hover-triggered CaptureButton to each expanded changelog entry so
users can screenshot individual version notes. Make the @zumer/snapdom
markdown list compatibility fix opt-in via a new `markdownFix` option
(default false), so custom-styled lists like changelog bullets are no
longer disrupted during capture.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract version/tag/prerelease detection into a shared prepare_release job,
split CLI packaging into its own build-cli artifact, switch publish-cli to
download the pre-built artifact instead of rebuilding inline, pin pnpm install
with --frozen-lockfile, and fix changelog summary lookup to match by version
instead of always selecting the first entry.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
Extract shared business logic from monolithic web.ts into reusable
services in @openchatlab/node-runtime (session, member, index, summary,
export), using SessionRuntimeAdapter to abstract platform differences.
Split web.ts into 12 domain-specific route modules under routes/web/.
Co-authored-by: Cursor <cursoragent@cursor.com>
MiniMax models embed thinking content as <think> tags in the content
field rather than using a separate reasoning field. Add a streaming
think-tag parser that detects these tags in real-time during streaming
and routes them to the thinking UI instead of displaying raw tags.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add directory import support for multi-file formats (e.g. shuakami chunked-jsonl).
Users can select or drag-and-drop a directory via the "Import Folder" checkbox.
- Add `findEntryFileInDirectory()` to parser layer for format-agnostic entry file discovery
- Add `importDirectory` method to ImportAdapter interface
- Implement FetchImportAdapter.importDirectory with multi-file FormData upload
- Add `POST /_web/import-directory` CLI route with directory reconstruction
- Add `chat:importDirectory` IPC handler in Electron main process
- Enhance FileDropZone with `directory` prop and drag-and-drop directory support
- Refactor FetchImportAdapter to extract reusable `consumeSseStream` helper
Co-authored-by: Cursor <cursoragent@cursor.com>
The IncrementalImportModal was Electron-only: showOpenDialog returned
canceled in web mode and FetchImportAdapter threw notSupported for both
analyzeIncrementalImport and incrementalImport despite CLI routes
already existing. Fix by using FileDropZone's built-in file input for
file selection and implementing the two fetch adapter methods via
FormData upload + SSE streaming.
Co-authored-by: Cursor <cursoragent@cursor.com>
The MCP entry was loading better-sqlite3 from node_modules which may
have been compiled for a different Node.js ABI. Now passes the
pre-built native binding from apps/cli/native/ (maintained by
ensure-native.mjs), matching how other CLI commands handle this.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Expand MCP_TOOL_REGISTRY from 8 to 33 tools by including all
AGENT_TOOL_REGISTRY tools (analytics, deep search, conversation, etc.)
- Add format=text|json parameter to all MCP tools (default: text for
most, json for SQL tools) for token-efficient LLM consumption
- Create format.ts: message filtering, consecutive-sender merging,
content truncation, and compact text output
- Inspired by community chatlab-mcp-server project
Co-authored-by: Cursor <cursoragent@cursor.com>
Move MCP Server logic (tool registration, resource registration, schema
conversion) from apps/cli/src/mcp.ts to packages/mcp-server so both CLI
and Desktop can share the same MCP implementation.
- New package: chatlab-mcp (packages/mcp-server) with McpDatabaseManager
interface abstraction
- CLI mcp.ts slimmed to thin entry (~37 lines) calling startMcpServer()
- Desktop helper prototype at apps/desktop/helper/mcp.ts for dev-time
MCP without GUI
- All 8 MCP tools and 3 resources unchanged
Co-authored-by: Cursor <cursoragent@cursor.com>
Add @electron/rebuild devDependency and postinstall script to
apps/desktop so that better-sqlite3 is automatically recompiled
against Electron's Node.js headers after every pnpm install,
preventing NODE_MODULE_VERSION mismatch at runtime.
- Add backendPersist Pinia plugin for declarative preferences.json persistence
- Move Preferences types to @openchatlab/shared-types (single source of truth)
- Migrate sessionGapThreshold from localStorage to config.toml [ui]
- Migrate chatlab_filter_history from localStorage to preferences.json
- Fix stale localStorage locale read in i18n/index.ts
- Simplify usePreferencesSync (172 → 75 lines) by delegating to plugin
Adding a new backend-synced preference now only requires 3 changes:
1. shared-types interface 2. node-runtime DEFAULTS 3. store backendPersist.pick
When a desktop app user installs the CLI, automatically detect existing
Electron data directory (including custom paths via storage.json),
repoint config.toml, and migrate system data (ai, settings, cache, etc.)
to ~/.chatlab/. Block CLI execution with actionable instructions when
Electron was used but databases cannot be located.
- Remove "type": "module" from apps/cli/package.json to avoid
ESM/CJS interop issues with workspace packages in tsx dev mode
- Configure tsup to output .mjs files (always treated as ESM by Node.js)
- Rename bin entry from chatlab.js to chatlab.mjs
- Change chatlab web default port to 3100 (serve keeps 3110)
- Fix vite plugin: use pnpm instead of npx for tsx invocation
All command descriptions, console output, option labels, comments
and error messages are now in English, consistent with AGENTS.md
rules and npm package positioning.
- Rename package to `chatlab-cli`, version 0.1.0
- Add tsup config with ESM output, bundle @openchatlab/* + stream-json
- Update bin/chatlab.js from stub to actual entry point
- Unify version reading via src/version.ts (CLI/MCP/HTTP API)
- Add publishing fields: type, files, engines, publishConfig, keywords
- Move @openchatlab/* to devDependencies (bundled into dist/)
- Add better-sqlite3 to dependencies, @node-rs/jieba to optionalDependencies
- Fix --web default path for bundled dist/ directory structure
Move the CLI application from packages/server/ to apps/cli/ to align
with the monorepo convention (apps/ for deployable applications,
packages/ for shared libraries). Rename package to @openchatlab/chatlab.
Also fix a bug in ensureToken() that used raw string manipulation to
write config.toml, causing duplicate token fields that corrupted the
TOML file. This led to config parse failures and user_data_dir being
overwritten with defaults. Now uses writeConfigField() for safe writes.
Worker thread crashed in packaged builds with "Cannot find module 'electron'"
because streamImport.ts transitively imported paths.ts (which requires electron)
through merger/tempCache.ts. Replaced with worker-local implementations that
receive tempDir via workerData, matching the existing dbDir/cacheDir pattern.
The extraction of Electron code to apps/desktop/ changed the package name
from "ChatLab" to "@openchatlab/desktop", which caused app.getPath('userData')
to return a wrong path in dev mode. This made the migration system unable to
find existing databases, resulting in a fresh-app experience for upgrading users.
- Add productName "ChatLab" to desktop package.json to ensure correct userData path
- Add verifyDataPath() safety net: auto-correct config.toml when configured dir
has no databases but old Electron path does
- Pin electron to 35.7.5 (electron-builder requires fixed version)
- Remove redundant @electron/rebuild (built into electron-builder)
- Use electron-builder install-app-deps for postinstall