Commit Graph
774 Commits
Author SHA1 Message Date
diguaandCursor 8819dff62c feat(cli): implement storage management for CLI Web
CLI Web's Settings > Storage Management was completely non-functional
(stub cacheApi returning empty data). This adds real HTTP endpoints
and wires the frontend to use them.

Backend (cache.ts):
- GET /_web/cache/info — scan databases/ai/cache/logs directory sizes
- POST /_web/cache/clear — clear cache or logs directory (allowlist)
- POST /_web/cache/open-dir — open directory in system file manager
- GET /_web/cache/data-dir — return current data directory path
- GET /_web/cache/latest-import-log — find latest import log file

Frontend:
- Replace cacheApi stubs with real HTTP calls in registry.ts
- Hide data directory migration UI in CLI Web (IS_ELECTRON guard)
- Add "Open Root Dir" button for ~/.chatlab/ in header area

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 23:19:47 +08:00
digua 9e88dcbd09 feat(changelog): bundle changelogs locally 2026-05-26 23:19:47 +08:00
digua ab90e06089 chore(docs): isolate docs workspace dependencies 2026-05-23 23:59:40 +08:00
digua 7a6d0e9586 docs: restructure public documentation site 2026-05-23 23:38:02 +08:00
digua c8d218251d feat(docs): add standalone VitePress docs site 2026-05-23 23:38:02 +08:00
digua 2d714857ef chore(changelog): move release changelogs out of docs 2026-05-23 23:38:02 +08:00
diguaandClaude Sonnet 4.6 8564db7241 release: v0.21.1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.21.1
2026-05-23 16:37:59 +08:00
diguaandClaude Sonnet 4.6 fa123bab49 fix: keep forced index modal open on generation failure
Move auto-close logic from finally to success path so the modal
remains open for retry when generate() fails in force mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 16:28:50 +08:00
diguaandClaude Sonnet 4.6 53e0d21ec7 fix(sync): prevent data loss on small pages and validate retry import results
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>
2026-05-23 16:28:50 +08:00
digua 92c8a795f9 fix(ui): spin sync icon in-place instead of showing separate loader
Replace UButton :loading with animate-spin on the arrow-path icon itself.
The sync button's icon now rotates when syncing, and the button is disabled.
The "sync all" button is also disabled when any session is syncing.
2026-05-23 16:28:50 +08:00
digua 811bb3c09a fix: prevent SessionIndexModal from blocking empty sessions 2026-05-23 16:28:50 +08:00
digua cb516daea0 fix(sync): raise page limit from 50 to 5000 for large chat histories
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.
2026-05-23 16:28:50 +08:00
digua a5bbff34e4 feat(sync): use incremental session index after pull sync
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
2026-05-23 16:28:50 +08:00
digua fcfa5d0167 fix(sync): auto-generate session index after pull sync completes
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.
2026-05-23 16:28:50 +08:00
digua 9cf6ac7725 fix(sync): refresh sidebar session list after pull completes or data deleted
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.
2026-05-23 16:28:50 +08:00
digua b952ebc8bf fix(sync): fetch all sessions when remote server lacks pagination support
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.
2026-05-23 16:28:50 +08:00
digua 4cd60aa0c1 docs: update Pull protocol to since+nextSince pagination model
- Change Accept header to application/json (NDJSON reserved for future)
- Remove offset/end request params, recommend since+limit only
- Mark hasMore+nextSince as required sync fields
- Move nextOffset/watermark to "protocol reserved" section
- Add cold-start retry explanation and pagination flow example
2026-05-23 16:28:50 +08:00
digua 7d5c541933 feat(sync): add option to delete imported chats when removing subscription
- 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)
2026-05-23 16:28:50 +08:00
digua 31fc9be1ed fix(sync): improve pull reliability with retry logic and simplified pagination
- 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
2026-05-23 16:28:50 +08:00
diguaandClaude Sonnet 4.6 f55fb9cf00 fix(desktop): fall back to package version when app.getVersion returns 0.0.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 16:28:50 +08:00
digua 5aaf1ce331 fix(sync): validate DB schema in sessionExists to prevent "no such table: message" error
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.
2026-05-23 16:28:50 +08:00
digua 795d10d8c9 feat(changelog): add icon and i18n for ci change type 2026-05-23 16:28:50 +08:00
diguaandClaude Sonnet 4.6 2d342865ff feat(capture): add per-version screenshot to ChangelogModal and make markdown list fix opt-in
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>
2026-05-23 16:28:50 +08:00
digua b984b79bc9 release: v0.21.0 v0.21.0 2026-05-22 14:45:17 +08:00
diguaandClaude Sonnet 4.6 dc5ab71521 ci(release): centralize version metadata and split CLI build into dedicated job
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>
2026-05-21 22:59:13 +08:00
digua 1171fec7d0 docs(changelog): clarify platform-specific entries 2026-05-21 22:50:03 +08:00
digua 3a2d4e753a refactor(mcp): trim exposed tool registry 2026-05-21 22:38:10 +08:00
digua 5db4b3bf9d fix(import): harden directory import path handling 2026-05-21 22:26:55 +08:00
digua 56902fea1c ci(release): publish CLI package from release workflow 2026-05-21 21:59:10 +08:00
digua 1e7325197c fix(web): preserve session not-found and member history behavior 2026-05-22 10:20:39 +08:00
diguaandCursor 5f76e65359 fix(sync): prevent race condition when adding new subscriptions
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>
2026-05-22 10:20:39 +08:00
diguaandCursor dd3cb10414 refactor(services): unify CLI Web and Electron service layer
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>
2026-05-22 10:20:39 +08:00
diguaandCursor 808b9026f2 fix(ai): parse MiniMax streaming <think> tags as thinking events
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>
2026-05-22 10:20:39 +08:00
diguaandCursor 9421662a52 feat(import): support unified directory import for Electron and Web
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>
2026-05-22 10:20:39 +08:00
diguaandCursor 8bb904fb22 fix(import): support incremental import in CLI web mode
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>
2026-05-22 10:20:39 +08:00
digua 04427a98d8 chore(cli): prepare npm release docs 2026-05-22 10:20:39 +08:00
digua 6fa92bc2e4 chore(mcp): prepare npm publish 2026-05-22 10:20:39 +08:00
digua d1737c7e8d chore: update npm config 2026-05-22 10:20:39 +08:00
digua 6c7e9f746f refactor(mcp): simplify MCP settings integration 2026-05-22 10:20:39 +08:00
diguaandCursor 6e7a3aa235 feat(mcp): add standalone bin entry and settings page MCP integration
- Add packages/mcp-server/src/bin.ts for `npx -y chatlab-mcp` standalone usage
- Add MCP sub-tab under Automation settings (Settings → Automation → MCP)
- MCP settings page: mode selector (npx/CLI/desktop), config generator with
  one-click copy for Cursor/Claude Desktop, troubleshooting tips
- Add i18n translations for settings.mcp.* (zh-CN, en-US, zh-TW, ja-JP)
- Update tsup config: add bin entry, enable splitting, externalize native modules

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 10:20:39 +08:00
diguaandCursor 584f581433 fix(mcp): pass nativeBinding to DatabaseManager for ABI compatibility
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>
2026-05-22 10:20:39 +08:00
diguaandCursor 68652248fe feat(mcp): enrich toolset to 33 tools with token compression and dual format
- 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>
2026-05-22 10:20:39 +08:00
diguaandCursor d022bed48f refactor(mcp): extract MCP core into shared chatlab-mcp package
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>
2026-05-22 10:20:39 +08:00
digua e3370b52c2 fix(web): align dev server node runtime 2026-05-22 10:20:39 +08:00
digua eebb428dd3 release: v0.20.0 v0.20.0 2026-05-19 23:59:11 +08:00
digua 9c93aa9701 fix(home): sequence onboarding modals 2026-05-19 23:55:00 +08:00
digua 415dcefc7d fix(ai): use provider name instead of config name for auth profile keys 2026-05-19 23:50:50 +08:00
digua 0bd5bc9f38 fix(electron): auto-rebuild better-sqlite3 for Electron headers
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.
2026-05-19 22:47:00 +08:00
digua 08260499f8 feat: migrate localStorage to backend storage with declarative persist plugin
- 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
2026-05-19 22:42:00 +08:00
digua 05394c2155 feat(cli): auto-detect and migrate Electron desktop data on first CLI run
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.
2026-05-19 22:19:00 +08:00