Commit Graph
100 Commits
Author SHA1 Message Date
digua 8ae8ff6cda fix(cli): avoid shell for file manager actions 2026-05-26 23:19:47 +08:00
digua 19a45f9e5f fix: protect self update and migration retry 2026-05-26 23:19:47 +08:00
diguaandClaude Sonnet 4.6 e05016c512 refactor(settings): move session index to AI settings and reorder tabs
Move SessionIndexSection from StorageTab to AISettingsTab (placed above
export settings), rename label from "会话管理" to "会话索引" across all
locales, swap automation tab before data management tab, and simplify
StorageTab by removing its now-unnecessary SubTabs navigation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 23:19:47 +08:00
diguaandClaude Sonnet 4.6 10a2677d74 feat(home): refactor import area and add API/auto-sync import methods
Restructure import components into dedicated import/ directory with new
ImportTabSelector, ApiImportCard, and AutoSyncCard components. Add demo
import, entry animation, and tutorial links to home page. Update i18n
translations for all locales. Add chatApi init guard in registry and
defaultPath to DataDirInfo preload interface.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 23:19:47 +08:00
diguaandCursor 6c3d36e7df feat(ai): upgrade pi-ai from @mariozechner 0.54 to @earendil-works 0.74
- Replace @mariozechner/pi-ai and pi-agent-core with @earendil-works scope
- Adapt to AgentTool.execute() params type change (Record → unknown)
- Migrate Agent constructor to use initialState for systemPrompt/tools/messages
- Update onPayload callback signature to include model parameter
- Filter finalMessages with isPiMessage() for new AgentMessage union type
- Use state.errorMessage instead of deprecated state.error

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 23:19:47 +08:00
diguaandCursor 0ba9ae04a6 chore: migrate workspace packages to ESM
- 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>
2026-05-26 23:19:47 +08:00
digua 83151fd8e7 fix(cli): improve update checker with async cache, keypress UX, and dev bypass 2026-05-26 23:19:47 +08:00
digua a105d7ab8e feat(cli): implement update checking and auto-update for CLI and CLI Web 2026-05-26 23:19:47 +08:00
diguaandCursor 1a35d2bb9a fix(cli): add merge API shims for CLI Web batch manage
CLI Web was missing chatApi.exportSessionsToTempFiles,
chatApi.cleanupTempExportFiles and the entire mergeApi shim,
causing "not a function" errors when merging sessions in
Settings > Data Management.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 23:19:47 +08:00
diguaandCursor 6ec03d330f fix(electron): prevent unified migration from reverting data dir changes
The unified directory migration (needsUnifiedDirMigration) would
re-trigger after a user changed their data directory, overwriting
config.toml back to the old Electron path.

Root cause: no persistent flag tracking whether the migration had
already completed. If old databases remained (cleanup failure or
timing), it would re-detect and re-run.

Fix:
- Add `electron_migration_done` flag to config.toml [data] section
- Set flag after migrateToUnifiedDirs succeeds and in setCustomDataDir
- Check flag at start of needsUnifiedDirMigration to skip if done
- Add "migrate to default" button when data is at non-default path
- Fix NLP directory path: move from userDataDir to systemDir (~/.chatlab/nlp)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 23:19:47 +08:00
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>
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 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 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
digua 0aa30359ab fix(cli): resolve ESM module resolution for tsx dev mode
- 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
2026-05-19 22:13:00 +08:00
digua e363e8bd75 refactor(cli): unify all CLI text to English
All command descriptions, console output, option labels, comments
and error messages are now in English, consistent with AGENTS.md
rules and npm package positioning.
2026-05-19 21:59:00 +08:00
digua 09d4b1ddac feat(cli): add chatlab web command for one-click Web UI launch
- New `chatlab web` subcommand: starts HTTP API + serves Web SPA + auto-opens browser
- Options: --port, --host, --no-open
- Cross-platform `openBrowser()` using open/start/xdg-open
- Add `setWebMode()` in auth: static resources bypass token auth in web mode
- Add `build:full` and `prepare:web` scripts for dist-web preparation
2026-05-19 21:53:00 +08:00
digua b1427e2422 feat(cli): add tsup build pipeline for npm publishing
- 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
2026-05-19 21:46:00 +08:00
digua 78e41a65b5 refactor: migrate CLI from packages/server to apps/cli
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.
2026-05-19 21:33:00 +08:00
digua 9db30879d3 fix(electron): decouple worker thread from electron module dependency
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.
2026-05-19 21:13:59 +08:00
digua ba851f4ae9 fix(electron): fix data migration path mismatch after package extraction
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
2026-05-19 20:39:25 +08:00
digua 1c6f4b3776 fix(electron): avoid install-app-deps during workspace install 2026-05-19 19:40:54 +08:00
digua c08a465116 chore(electron): remove Linux desktop build targets
Linux users will be served by the upcoming CLI package instead.
2026-05-19 19:17:59 +08:00
digua d058e8a60f fix(electron): fix CI build by pinning electron version and cleanup
- 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
2026-05-19 19:14:11 +08:00
digua 9099b15ce6 chore(deps): upgrade vite toolchain 2026-05-19 18:39:14 +08:00
digua e80d8e471e docs: update 2026-05-19 00:40:00 +08:00
digua 2bcbb84711 feat: add interactive dev mode selector (pnpm dev)
Adds a zero-dependency Node.js script with arrow-key selection
for choosing between Desktop (Electron), Web (CLI serve + frontend),
Server Only (API backend), and Frontend-only dev modes.

Remembers last selection in node_modules/.cache/dev-mode.
2026-05-19 00:35:00 +08:00
digua b12c07dc32 refactor: extract Electron shell to apps/desktop/
Move Electron-specific code (main, preload, shared) and configs
(electron.vite, electron-builder) into apps/desktop/ to prepare
for multi-platform support (Web Browser standalone).

- Create apps/desktop/ with dedicated package.json and tsconfig
- Split Electron deps (electron, electron-updater, better-sqlite3,
  etc.) from shared frontend deps in root package.json
- Declare better-sqlite3 and @node-rs/jieba in packages/node-runtime
- Add stream-json to packages/parser where it belongs
- Update all path aliases (@electron/* → apps/desktop/*) in tsconfig,
  vite configs, and relative imports in preload/main
- Keep slim root tsconfig.node.json as shared base for packages
- Update CI/CD release workflow for new directory layout
- Fix pre-existing type errors (pi-ai Model generic, SQLLabTab
  LLMChatStreamChunk, filter.test.ts empty methods)
2026-05-19 00:31:00 +08:00
digua ba29346bfe refactor: move chart-* modules from packages/ to src/features/
These are frontend-only Vue/ECharts components that depend on app internals (@/),
not cross-platform shared packages. Moving them to src/features/charts-* keeps
packages/ purely for reusable Node.js libraries.
2026-05-18 23:57:00 +08:00
digua d3ce4023e5 fix(core): add missing re-exports in query/index.ts
The query barrel file was missing re-exports for getSessionsByTimeRange,
getRecentChatSessions, loadSessionMessages, getPrivateChatMemberAvatar,
getExportSessionData, and searchMessagesWithFtsAsync.
2026-05-18 23:43:00 +08:00
digua 31359712b3 refactor(core): extract remaining inline SQL from electron adapters
- Extract getPrivateChatMemberAvatar to @openchatlab/core
- Extract getExportSessionData (meta/members/messages SQL) to @openchatlab/core
- Extract loadSessionMessages for summary generation to @openchatlab/core
- Replace inline SQL in summary buildDeps with shared core query functions
- Extract createCompressionLlmAdapter factory to @openchatlab/node-runtime
- Simplify server and electron compression adapter creation via shared factory
2026-05-18 23:36:42 +08:00
digua 53fa23f488 refactor(ai): unify formatAIError and extract FTS search SQL to core
- Extract formatAIError to @openchatlab/node-runtime, eliminate duplicate in Electron and Server
- Extract stripAvatarFields to @openchatlab/core
- Extract FTS message search SQL to core (searchMessagesWithFtsAsync)
- Remove redundant sync searchMessagesWithLike from Electron worker
2026-05-18 23:28:39 +08:00
digua 0d454d8a52 refactor(core): extract session time queries and remove dead code
- Remove dead code: electron/main/ai/agent/content-parser.ts (duplicate of @openchatlab/core)
- Extract getSessionsByTimeRange and getRecentChatSessions to @openchatlab/core
- Route IPC session:getByTimeRange and session:getRecent through Worker instead of inline SQL
- Eliminate duplicate getSessionSummaries in workerManager.ts, delegate to core via Worker
2026-05-18 23:22:25 +08:00
digua 1536e241fc docs: add versioning and commit scope conventions to AGENTS.md
- All distribution targets share root package.json version (lock-step)
- Commit scope: free-form for shared changes, platform scope (electron/
  cli/web) only when the change is platform-specific
2026-05-18 22:58:00 +08:00
digua 620ae40d45 fix(web): show app version in sidebar instead of empty string
Inject __APP_VERSION__ from package.json via Vite define, read it in
WebPlatformAdapter.getVersion(), and call getVersion() on all platforms
(not just Electron) in Sidebar onMounted.
2026-05-18 22:43:00 +08:00
digua e5dc1fcb9b fix(dev): tsx watch not detecting workspace package changes
tsx watch's symlink-based file watching doesn't trigger on changes to
pnpm workspace packages (tsx#221). Add --include flags for packages/core
and packages/node-runtime source directories to both dev:serve script
and vite.web.config.mts auto-serve plugin. Extract long command to
scripts/dev-serve.sh for cleaner package.json.
2026-05-18 22:43:00 +08:00
digua cdb2bfea7c feat: unify LLM streaming with thinking display and Web/cache API shims
- Extract runSimpleLlmStream to @openchatlab/node-runtime for shared
  Electron/Server streaming with thinking_start/delta/end event handling
- Simplify Electron IPC ai.ts by delegating to shared stream function
- Add thinking/thinkingDone fields to LlmStreamChunk and preload types
- Add collapsible thinking process display in SQL LAB with auto-scroll
- Implement Web chatStream via SSE with proper error propagation
- Add /_web/cache/save-to-downloads and show-in-folder server routes
- Add cacheApi shim in Web registry for server-side file operations
- Increase SQL LAB maxTokens to 4096 to accommodate reasoning models
- Detect finishReason:length and show token limit error message
- Add i18n keys for thinking/thinkingProcess/errorTokenLimit (4 locales)
2026-05-18 22:32:00 +08:00
digua 58a558b7aa fix(server): align web AI agent with Electron implementation
- Replace mapCoreEventToStream with shared AgentEventHandler for rich
  status events (contextTokens, totalUsage, updatedAt)
- Add formatAIError for user-friendly error messages (429/503/quota)
- Compute maxToolResultTokens dynamically from model contextWindow
- Add steerMessage (answerWithoutTools) and onConvertToLlm callback
- Forward ownerInfo/mentionedMembers from web frontend to server
2026-05-18 22:23:44 +08:00
digua 7190606ca7 refactor: extract AI translations to shared i18n module in node-runtime
Move AI-related translations (tools, agent prompts, LLM, summary) from
Electron-specific locale files into @openchatlab/node-runtime, enabling
single-source maintenance across Electron and Server.

- Add packages/node-runtime/src/ai/i18n/ with createAiTranslate() and
  bundled locale data (zh-CN, en-US, ja-JP, zh-TW)
- Electron locale files now compose: Electron-specific keys + shared AI
  translations from node-runtime
- Server agent.ts switches to shared buildSystemPrompt with evidence
  policy, data snapshot injection, ownerInfo and mentionedMembers support
- Server route fetches dataSnapshot from getChatOverview before agent run
2026-05-18 22:04:01 +08:00
digua 1620a5b4a3 refactor: remove pure re-export files from electron/main
Delete 9 files that were pure passthrough re-exports with zero logic:
- database/sessionCache.ts → consumers import @openchatlab/node-runtime directly
- nlp/stopwords.ts, ftsTokenizer.ts, types.ts, segmenter.ts, index.ts → consumers import @openchatlab/core or @openchatlab/node-runtime directly
- ai/agent/event-handler.ts → consumer imports @openchatlab/node-runtime directly
- ai/llm/provider-registry.ts, model-catalog.ts → consumer imports @openchatlab/core directly

This eliminates unnecessary indirection layers while keeping thin adapters
that contain real Electron-specific logic (DI, singletons, path wiring).
2026-05-18 21:19:15 +08:00
digua 09cdf165b5 feat(server): add merge HTTP routes and simplify Electron merger layer
- Server: add MergeSessionCache + 5 merge endpoints (parse, conflicts, execute, clear, export-for-merge)
- Electron tempCache.ts: delegate to shared TempDbReader/TempDbWriter via BetterSqliteAdapter
- Electron merger/index.ts: remove dead wrapTempDbReader, use reader.toDataSource() directly
2026-05-18 21:07:04 +08:00
digua a3a1d289ba feat(node-runtime): extract Markdown export engine and add server export route
- Extract exportFilterResultToMarkdown to node-runtime/export with writer abstraction
- Electron export.ts becomes thin wrapper (fs.createWriteStream + worker IPC progress)
- Server adds POST /_web/sessions/:id/export/markdown returning downloadable Markdown
2026-05-18 21:01:27 +08:00
digua 8c130c7221 feat(core): unified SQL execution with executeSql() and getSchemaDetailed()
- Add executeSql() with options: columnar, timing, maxRows (stmt.readonly + regex fallback)
- Add getSchemaDetailed() returning table + column info via PRAGMA table_info
- Electron sql.ts delegates to shared executeSql (columnar=true, timing=true)
- Server web.ts uses executeSql (with timing) and getSchemaDetailed (simplified schema route)
2026-05-18 20:45:24 +08:00
digua 9ee3060377 feat(node-runtime): extract session cache to shared package
- Extract JSON cache CRUD + overview/members compute to node-runtime/cache
- Functions now accept DatabaseAdapter instead of better-sqlite3 Database
- Electron sessionCache.ts becomes pure re-export
- Updated all Electron callers to wrap DB with BetterSqliteAdapter
2026-05-18 20:41:48 +08:00
digua 064f3ce144 feat(node-runtime): extract chat DB migrations and add auto-migration on writable open
- Extract migration definitions (v1-v4) to shared getChatDbMigrations() with DI for tokenizer
- DatabaseManager.openWritable() auto-runs pending migrations
- Electron migrations.ts becomes thin wrapper delegating to shared definitions
2026-05-18 20:38:38 +08:00
digua f78077655f fix(server): auto-generate session index after import
After streaming or incremental import, automatically generate the
session index (chat_session table) so the frontend does not show
the "generate index" prompt when entering a conversation.
2026-05-18 20:21:30 +08:00
digua 7b29b34e9a feat(server): rewire import to shared StreamingImporter + add incremental routes
- Replace buffered import with high-performance streaming pipeline
- Add POST /_web/sessions/:id/import/incremental (SSE)
- Add POST /_web/sessions/:id/import/incremental/analyze
- Add POST /_web/import/analyze (dry-run)
- CLI import now reports diagnostics from StreamingImporter
2026-05-18 20:06:57 +08:00
digua 58f87133c7 refactor(electron): rewire worker import modules to shared implementations
streamImport.ts: 1080 -> ~110 lines, delegates to node-runtime StreamingImporter
incrementalImport.ts: 451 -> ~65 lines, delegates to node-runtime IncrementalImporter
Both inject Electron-specific deps: IPC progress, better-sqlite3 adapter, cache hook
2026-05-18 20:03:11 +08:00
digua 8d430249c9 feat(node-runtime): extract TempDbWriter/Reader and session export
Platform-agnostic temp DB management for merge operations using
DatabaseAdapter. Includes TempDbWriter (streaming write), TempDbReader
(streaming read + MergerDataSource adapter), exportSessionToJson,
and cleanup helpers.
2026-05-18 20:00:59 +08:00
digua 2e564e8063 feat(node-runtime): extract IncrementalImporter from Electron worker
Platform-agnostic incremental import with dual-path dedup
(platformMessageId + content hash), member upsert, meta patching,
FTS sync, and injectable dependencies (IncrementalImportDeps).
2026-05-18 19:58:25 +08:00
digua bf91c4b7df feat(node-runtime): extract StreamingImporter from Electron worker
Platform-agnostic streaming import with batched transactions, deferred
indexes, nickname history tracking, FTS indexing, and format fallback.
All Electron-specific dependencies replaced with injectable interfaces
(StreamImportDeps, ImportLogger, ImportProgressCallback).
2026-05-18 19:56:27 +08:00
digua 3830ccdd1b feat(server): wire shared managers, FTS, and summary routes to web API
Add Assistant/Skill CRUD routes using shared AssistantManager/SkillManagerCore,
FTS search/rebuild routes, and session summary generation routes. Clean up
unused imports in ai.ts.
2026-05-18 19:43:16 +08:00
digua 1294448959 refactor(electron): introduce ElectronPathProvider and convert modules to PathProvider
Create ElectronPathProvider implementing @openchatlab/core PathProvider interface,
and convert 12 modules from direct paths.ts imports to PathProvider-based access.

Key changes:
- New: ElectronPathProvider + path-context.ts singleton
- assistant/manager.ts: delegate to @openchatlab/node-runtime AssistantManager (394→115 lines)
- skills/manager.ts: delegate to @openchatlab/node-runtime SkillManagerCore (369→100 lines)
- 10 other modules: replace getXxxDir() imports with getPathProvider().getXxxDir()

Desktop-only modules (IPC, workerManager, i18n, index) intentionally kept as-is.
2026-05-18 19:25:12 +08:00
digua f597c9b1b8 chore(electron): remove dead code crypto.ts and device-key.ts
encryptApiKey/decryptApiKey and device key management have zero
importers — legacy functionality already handled by
@openchatlab/config/migrations/crypto-legacy. Removes ~278 lines.
2026-05-18 19:07:22 +08:00