Commit Graph
49 Commits
Author SHA1 Message Date
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
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 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 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 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 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 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 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 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 249df9c8e3 feat(node-runtime): extract RAG subsystem to shared package
Move the entire RAG module (~2458 lines) from electron/main/ai/rag/ to
@openchatlab/node-runtime. Includes chunking, embedding, vector store,
and semantic pipeline.

Key changes:
- Config operations use injected aiDataDir instead of getAiDataDir()
- Logger uses injectable RagLogger interface
- LLM config provided via getLLMConfig/getAssistantConfig callbacks
- Deduplicated cosineSimilarity into shared utils.ts
- Electron rag/index.ts is now a thin wrapper (~128 lines)
2026-05-18 19:06:01 +08:00
digua 1796731535 feat(node-runtime): extract import perf logger to shared package
Move performance logging from electron/main/worker/core/perfLogger.ts to
@openchatlab/node-runtime. Log directory is now caller-provided instead
of derived from Electron paths. Electron wrapper provides the path.

Reduces Electron perfLogger from ~181 lines to ~28 lines.
2026-05-18 18:50:30 +08:00
digua 0017dcbf9e feat(node-runtime): extract FTS5 index operations to shared package
Move core FTS operations (create, build, rebuild, insert, search) to
@openchatlab/node-runtime working with DatabaseAdapter. Electron fts.ts
becomes a thin adapter that adds session-level DB connection management.

Reduces Electron fts.ts from ~207 lines to ~90 lines of pure wrappers.
2026-05-18 18:49:14 +08:00
digua 1f11f94212 feat(node-runtime): extract writeParseResultToDb to shared import module
Move the core data writing logic (meta/member/message insertion with
member_name_history tracking) from electron/main/database/core.ts to
@openchatlab/node-runtime. Electron importData() now delegates to the
shared function via BetterSqliteAdapter, reducing ~130 lines to ~10.

This enables both Electron and Server to share the same import logic
including name history tracking.
2026-05-18 18:45:40 +08:00
CEQ151 3583548f1f fix: strengthen agent evidence retrieval 2026-05-18 17:31:54 +08:00
diguaandCursor 8412180470 feat(node-runtime): extract SkillManagerCore class with abstract FS
Platform-agnostic skill CRUD manager with dependency injection for file
system ops, builtin skill resources, and content hashing. Supports init,
CRUD, builtin import/reimport, cloud markdown import, and AI skill menu
generation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 00:14:51 +08:00
diguaandCursor cb9849c164 feat(node-runtime): extract AssistantManager class with abstract FS
Platform-agnostic AssistantManager with dependency injection for file
system ops, builtin configs, and ID generation. Supports init, CRUD,
builtin import/reimport/reset, and cloud markdown import.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 00:10:52 +08:00
diguaandCursor 7feab45447 feat(node-runtime): extract LLM config CRUD to shared LLMConfigStore class
Introduce ConfigStorage abstraction and LLMConfigStore class with
dependency injection for i18n, UUID generation, and auth profile hooks.
All CRUD operations (add/update/delete/slots) are platform-agnostic.
Electron can implement ConfigStorage with fs + getAiDataDir.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 00:07:28 +08:00
diguaandCursor 640d16c6ec feat(node-runtime): extract merger orchestration to @openchatlab/node-runtime
Move merge orchestration (data source reading, conflict checking,
ChatLab output assembly, JSONL serialization) to shared package with
abstract MergerDataSource interface. Electron merger becomes thin adapter
wrapping TempDbReader and handling file I/O.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-18 00:02:20 +08:00
diguaandCursor 03cb8aa196 feat(core): extract merger pure algorithms to @openchatlab/core
Move platform ID collision detection, normalization, conflict detection,
member merge, and message dedup-sort from electron/main/merger to a
shared package with zero Node.js dependencies.

Also fix pre-existing unused-variable TS errors in summary test.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 23:54:07 +08:00
diguaandCursor d24ad22980 refactor(node-runtime): extract summary pipeline to @openchatlab/node-runtime
Move session summary generation (573 lines) to shared package with
SummaryDeps injection for DB/LLM/i18n. Pure algorithms (isValidMessage,
filterValidMessages, splitIntoSegments, prompt builders) are now shared.
Electron summary/index.ts implements SummaryDeps and delegates.
Added 14 unit tests covering message filtering, segmentation,
summary generation, and eligibility checks.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 23:36:21 +08:00
diguaandCursor 38b599034f refactor(node-runtime): extract event-handler to @openchatlab/node-runtime
Move AgentEventHandler, TokenUsage, AgentRuntimeStatus, AgentStreamChunk
to packages/node-runtime/src/ai/agent/event-handler.ts.
Token estimation and event-to-chunk mapping are now shared.
Electron agent/types.ts re-exports from node-runtime.
Added 8 unit tests covering token estimation, tool tracking, usage cloning.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 23:32:54 +08:00
diguaandCursor 0ac90030cb refactor(node-runtime): extract prompt-builder to @openchatlab/node-runtime
Move buildSystemPrompt from electron/main/ai/agent/ to shared package.
i18n t() is now injected via BuildSystemPromptOptions parameter.
Types OwnerInfo, MentionedMember, SkillContext are shared.
Electron prompt-builder.ts injects its own t() and delegates.
Added 8 unit tests with mock translation function.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 23:28:28 +08:00
diguaandCursor f42c8d71ec refactor(node-runtime): extract ftsTokenizer to @openchatlab/node-runtime
Move tokenizeForFts and tokenizeQueryForFts from electron/main/nlp/ to
packages/node-runtime/src/nlp/fts-tokenizer.ts. Uses the already-shared
getJieba() internally. Electron ftsTokenizer.ts now re-exports.
Added 9 unit tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 23:13:17 +08:00
diguaandCursor 226c053006 refactor: extract fetchRemoteModels + validateApiKey to @openchatlab/node-runtime
Move remote LLM API operations into shared module with optional
headers and logger injection. Electron wraps with UA headers and
aiLogger; server re-exports directly.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 14:15:00 +08:00
diguaandCursor 73569c69bf refactor: extract shared buildPiModel to @openchatlab/node-runtime
Move URL normalization helpers and PiModel construction into a shared
llm-builder module. Electron and server both delegate to the core
builder, with Electron adding optional headers and provider validation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 14:11:49 +08:00
digua 6090c6689f refactor: extract AiLogger to @openchatlab/node-runtime for shared use
Move the file-based AI logging implementation from Electron-specific
code to a shared AiLogger class in @openchatlab/node-runtime. Both
Electron and Server/CLI now use the same logger writing to
~/.chatlab/logs/ai/. Server-side agent, tool adapter, and compression
now produce the same structured log files as Electron.
2026-05-15 22:23:49 +08:00
digua 787e645a60 refactor: remove redundant electron/main/ai/preprocessor directory
The 4-file preprocessor wrapper directory was entirely re-exports from
@openchatlab/node-runtime after the pipeline unification. Replace all
consumers with direct imports and add logger injection support to
PreprocessingPipelineOptions so Electron retains aiLogger integration.
2026-05-15 19:58:03 +08:00
digua 984b778033 refactor: extract shared preprocessing pipeline to @openchatlab/node-runtime
Unify the duplicated preprocessing logic between Electron (wrapWithPreprocessing)
and Server (applyPreprocessing) into a single applyPreprocessingPipeline() function
in @openchatlab/node-runtime. Both platforms now delegate to the same implementation,
eliminating ~50 lines of redundant code and fixing a redundant token counting bug
in the Server version.
2026-05-15 19:52:01 +08:00
digua 8dd3e2396c refactor(ai): extract shared Agent core to @openchatlab/node-runtime
- Create runAgentCore() in node-runtime/src/ai/agent/ encapsulating
  PiAgentCore construction, history conversion, event subscription,
  abort forwarding, tool round management, and usage collection
- Re-export pi-agent-core/pi-ai types (AgentTool, Type, Model, etc.)
  and functions (completeSimple, streamSimple) from node-runtime
- Refactor Server agent.ts to use runAgentCore, removing all direct
  pi-agent-core/pi-ai imports (~335→~210 lines)
- Remove pi-agent-core and pi-ai from Server package.json dependencies
- Refactor Electron agent/index.ts and event-handler.ts to use
  runAgentCore with DI hooks (streamFn, onConvertToLlm, onDebugContext)
- Document remaining Electron pi-ai usage points for future migration
2026-05-14 23:36:11 +08:00
digua 07056a2258 feat: extract context compression to @openchatlab/node-runtime
Move compression logic from Electron to shared package with pluggable
LLM adapter interface. Integrate into server agent with pre-run
compression support. Electron side becomes a thin compatibility wrapper.
2026-05-14 21:43:10 +08:00
digua 58d7da6367 feat: add SkillManager and activate_skill tool to shared package
Extract SkillManager from Electron to @openchatlab/node-runtime.
Create shared createActivateSkillTool factory.
Integrate skill menu into server agent system prompt and SSE route.
2026-05-14 21:34:58 +08:00
digua 76b4be1264 refactor: extract preprocessor pipeline to @openchatlab/node-runtime
Move preprocessing (pipeline, types, builtin-rules, format utilities)
from Electron to shared package. Electron side becomes thin wrappers.
2026-05-14 21:32:27 +08:00
digua b195750f34 refactor: extract tokenizer to @openchatlab/node-runtime
Move countTokens/countMessagesTokens from Electron to shared package.
Electron side becomes a thin re-export wrapper.
2026-05-14 21:27:39 +08:00
digua b479fd3b2d feat(web): enable AI chat in web mode with shared conversation module
- Extract AIConversationManager to @openchatlab/node-runtime for Electron + Server reuse
- Add /_web/ai/conversations/* HTTP endpoints for conversation/message CRUD
- Create FetchAIAdapter to replace WebAIAdapter stub
- Implement server-side Agent with SSE streaming (/_web/ai/agent/stream)
- Add agentApi SSE client shim in frontend registry
- Migrate API key storage from encrypted llm-config.json to auth-profiles.json
- Add @openchatlab/config auth-profiles module for credential management
2026-05-14 20:55:54 +08:00
digua 12f9ae90eb feat(web): enable AI page data loading in web mode via HTTP endpoints
- Move assistant/skill MD parsers to @openchatlab/node-runtime (shared)
- Move BUILTIN_TOOL_CATALOG, provider-registry, model-catalog to @openchatlab/core
- Add /_web/ai/* HTTP routes for assistants, skills, LLM config, providers, models, tools
- Frontend shims: read ops call HTTP, write/agent ops return stubs
- Remove IS_ELECTRON guard in llm.ts to enable web-mode config loading
- Improve web-mode AI chat error message to be user-friendly
2026-05-14 20:29:06 +08:00
digua 4b15d65b13 refactor(nlp): extract shared NLP logic to core + node-runtime
Move platform-agnostic NLP types, stopwords, POS tag definitions, and
text utilities into @openchatlab/core. Move segmenter engine, word
frequency computation, and dict manager into @openchatlab/node-runtime.

Electron nlp/ becomes a thin re-export layer; server nlp.ts shrinks
from ~450 to ~85 lines retaining only HTTP route definitions. Both
platforms now share the same NLP implementation via node-runtime.

Also fixes createJiebaNlpProvider to use shared getJieba() with disk
dict loading (was using empty Jieba instance causing degraded POS tags
in language preference analysis), adds ensureDefaultDict at server
startup, and adds /_web/nlp/* HTTP routes with window.nlpApi shim.
2026-05-14 19:50:03 +08:00
digua 61a6e72c64 refactor: unify data directory for Electron and CLI
Split PathProvider into dual-root architecture: systemDir (~/.chatlab/)
for config/logs/cache/ai/settings, and userDataDir (~/.chatlab/data/ by
default) for chat databases. Both Electron and CLI share the same
config.toml for user_data_dir resolution.

- Refactor PathProvider interface (getSystemDir + getUserDataDir)
- Update config schema (data.dir → data.user_data_dir)
- Add writeConfigField() for config.toml manipulation
- Fix needsUnifiedDirMigration() to detect old Electron data even when
  user_data_dir was already set by CLI (compare paths instead of
  checking existence)
2026-05-14 19:35:36 +08:00
digua 6ca27b1194 refactor: unify query logic into @openchatlab/core and add analytics HTTP routes 2026-05-14 19:20:51 +08:00
digua 6695181759 fix(web): resolve runtime errors in web mode
- Fix streamImport error handling: close db before deleting files on failure
- Add POST /_web/sessions/:id/query endpoint for parameterized readonly SQL
- Expose PreparedStatement.readonly property in DatabaseAdapter interface
- Fix Fastify error handler to respect statusCode on non-ApiError errors
- Implement FetchAdapter.pluginQuery via HTTP endpoint
- Add web-api-shim.ts: window.chatApi/aiApi polyfills for chart-* and
  MessageList (pluginQuery, pluginCompute, getMemberActivity,
  getAvailableYears, message browsing methods)
- Fix Sidebar: navigate to home after deleting the currently viewed session
2026-05-13 21:25:50 +08:00
digua d040aaaa98 feat(server): isolate better-sqlite3 native binary for Electron/Node coexistence
Add rebuild-native.sh script that compiles better-sqlite3 in an isolated
temp directory for system Node.js, storing the binary at packages/server/native/.
DatabaseManager and openBetterSqliteDatabase now accept nativeBinding option.
CLI auto-detects non-Electron environment and uses the isolated binary.
2026-05-11 20:24:39 +08:00
digua 7535f77eaa feat(node-runtime): add DatabaseManager for session DB lifecycle
Phase 1.7: add DatabaseManager to @openchatlab/node-runtime that handles
opening, caching, listing, and closing chat session databases using the
DatabaseAdapter and PathProvider interfaces from core.
2026-05-11 19:56:14 +08:00
digua ebf941b53f feat(node-runtime): add NodePathProvider for standalone Node.js
Phase 1.3: implement PathProvider for CLI/service mode using
~/.chatlab/data/ as default data directory with CHATLAB_DATA_DIR
environment variable override support.
2026-05-11 19:46:27 +08:00
digua 7c99ae2d26 feat(node-runtime): add BetterSqliteAdapter implementing DatabaseAdapter
Phase 1.2: create @openchatlab/node-runtime package with better-sqlite3
adapter that implements the DatabaseAdapter interface from core. Also add
pragma() method to the DatabaseAdapter interface.
2026-05-11 19:45:45 +08:00