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.
- Add POST /_web/demo/import backend endpoint: downloads demo data from
chatlab.fun and imports using streamImport with SSE progress
- Refactor DemoImportButton.vue to support both Electron (IPC) and
Web (SSE fetch) modes with shared result handling
- Add session index endpoints (generate-index, clear-index) with writable db
- Add window.sessionApi shims for web mode (getStats, generate, getSessions, etc.)
- Fix CORS: add Vite dev proxy for chatlab.fun, centralize CHATLAB_SITE_BASE
- Guard DemoImportButton: show fallback message in web mode
- Use tsx watch for dev:serve hot-reloading
- Reorganize dev scripts: dev:app (web frontend), dev:serve (backend), dev:web (both)
- 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
Add IS_ELECTRON guards around window.api.setThemeSource,
window.api.app.getOpenAtLogin, and window.api.app.setOpenAtLogin
to prevent crashes when opening settings in web mode.
Move all 14+ format parsers (QQ, WeChat, Telegram, WhatsApp, LINE,
Discord, Instagram, etc.) from electron/main/parser/ to packages/parser/
as a standalone shared package. Electron's parser module becomes a thin
re-export wrapper. This enables the server to use the same parser for
CLI serve Web import functionality.
Phase 3A.1: Create the HTTP bridge between the Vue SPA frontend
and chatlab serve backend for the CLI serve Web version.
Server side (packages/server):
- Add /_web/ route group (routes/web.ts) with no auth requirement,
covering: sessions CRUD, time range, member-activity/hourly/daily/
weekday/message-type stats, members CRUD+pagination+merge+history,
SQL Lab execute+schema.
- Skip auth hook for /_web/ prefix (same-origin internal API).
- Add getTimeRange() to @openchatlab/core basic queries.
Client side (src/adapters):
- FetchAdapter wrapping all /_web/ endpoints with proper HTTP verbs,
TimeFilter query param serialization, and error handling.
- Unimplemented analysis methods (catchphrase, mention, cluster, etc.)
throw descriptive errors for progressive enhancement.
- Wire FetchAdapter into adapter factory (non-Electron, non-browser).
Phase 3.0.3: Systematically replace all data-query window.chatApi
calls across 24 files with getAdapter() from the new adapter layer.
Replaced categories:
- Session CRUD (getSessions, getSession, deleteSession, renameSession)
- Statistics (getMemberActivity, getHourlyActivity, getDailyActivity,
getWeekdayActivity, getMessageTypeDistribution, getAvailableYears)
- Member management (getMembers, getMembersPaginated, updateMemberAliases,
mergeMembers, deleteMember, getMemberNameHistory)
- Social analysis (getMentionAnalysis, getLaughAnalysis,
getCatchphraseAnalysis, getLanguagePreferenceAnalysis,
getRelationshipStats)
- SQL Lab (executeSQL, getSchema)
Remaining window.chatApi calls are Electron-specific operations
(import, migration, file dialog, demo, export) that will be handled
separately with IS_ELECTRON guards in future phases.
Also adds initAdapter() call in App.vue onMounted to bootstrap the
adapter before any data loading occurs.