Commit Graph
311 Commits
Author SHA1 Message Date
digua 8ca3f0be8b feat(ai): add llm fallback for shadow routing 2026-06-10 00:15:25 +08:00
digua 712d5212c2 feat(ai): log shadow agent route decisions 2026-06-10 00:15:25 +08:00
diguaandClaude Sonnet 4.6 f5e83748ff fix(ai): register execute_sql tool in Electron tool registry
sqlQueryTool (execute_sql) was listed in BUILTIN_TOOL_CATALOG and
available in the CLI AGENT_TOOL_REGISTRY, but was never imported or
registered in the Electron-specific TOOL_REGISTRY. Users who enabled
the tool via the assistant config panel would trigger a missing-tool
error at inference time.

Add sqlQueryTool to the Electron registry following the same
adaptSharedTool pattern used by all other analysis tools. Add a
catalog/registry drift guard test (name + category) covering all
BUILTIN_TOOL_CATALOG entries, enabled via
--experimental-test-module-mocks to mock Electron runtime deps.
Document the general-over-specific assertion rule in AGENTS.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 00:15:25 +08:00
diguaandClaude Sonnet 4.6 c3a5d22a43 fix: enforce data directory compatibility gate at runtime boundaries
MCP server checks the gate at startup and exits before opening stdio if
the data directory requires a newer runtime. Desktop HTTP API maps
DataDirCompatibilityError (including wrapped causes) to a 409 response
so the renderer can surface a clear upgrade prompt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:14:42 +08:00
diguaandClaude Sonnet 4.6 e7561e224e fix: write data directory compatibility gate on migration and import
Harden the startup migration path: fail fast and show an error dialog if
schema migration cannot complete. Repair the gate retroactively for
databases that were already migrated before the gate system existed.

Raise the gate after every import path (full import, incremental import,
stream import) and after opening any database that already carries a
current-segment schema. Centralise gate-raising inside DatabaseManager so
call sites cannot accidentally skip it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:14:42 +08:00
diguaandClaude Sonnet 4.6 1c7781d85b fix: establish runtime identity for data directory gates
Use the packaged app version (not Electron's dev-mode 0.0.0) across all
compatibility checks. Make DatabaseManager require a RuntimeIdentity so
every gate write carries a verified version and kind.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:14:42 +08:00
digua 6ae32e8b57 feat(http): report incompatible data directories 2026-06-08 10:14:42 +08:00
digua ad8181d6f4 feat(desktop): enforce data directory compatibility 2026-06-08 10:14:42 +08:00
digua 84b42a68f7 feat(cli): block incompatible data directories at startup 2026-06-08 10:14:42 +08:00
digua 187268d8a5 test(core,import): rebalance database coverage 2026-06-08 10:14:42 +08:00
digua 2d88215d63 test: add default test runner 2026-06-08 10:14:42 +08:00
diguaandClaude Sonnet 4.6 62ad3c6248 fix: normalize legacy tool names and harden cli chat command
- Add normalizeBuiltinToolNames() to map old session-based tool names
  (search_sessions, get_session_messages, get_session_summaries) to
  current segment names; applied in assistant parser, agent-stream-runner,
  and desktop tool-filter so existing assistant configs keep working
- Propagate agent stream error chunks as thrown Errors in CLI chat command
- Pass assistantId through ResolvedAIChatTarget to agent stream
- Preserve legacy chat_session rows in v6 migration when segment table
  already exists (INSERT OR IGNORE + DROP); revert v3/v5 DDL to chat_session
- Rename session_id alias to segment_id in relationship query
- Add tests: assistant-parser normalization, tool-filter legacy names,
  agent-stream-runner legacy allowlist, REPL error resilience, migration paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:27:27 +08:00
digua 9b17b09354 feat: add cli ai chat command 2026-06-07 20:27:27 +08:00
digua c2295e317f refactor: align ai chat and segment identifiers 2026-06-07 20:27:27 +08:00
digua 31f3c610ce fix(ai): increase default tool rounds 2026-06-05 11:12:42 +08:00
digua 9b1f359699 fix(ai): register chart tool for electron auto skills 2026-06-05 11:12:42 +08:00
digua 296573ed5c refactor(ai): centralize chart runtime policy 2026-06-05 11:12:42 +08:00
CEQ151 15470444e5 feat(ai): improve chart runtime UX 2026-06-05 11:12:42 +08:00
CEQ151 782f67ba63 feat(ai): add slash-activated chart runtime with EChart init fix
- Add ChartSpec validation and chart data normalization (bar/line/pie/heatmap)
- Add render_chart analysis tool with SQL safety (readonly check, outer LIMIT wrapper, CTE write rejection)
- Add chart content block type and ChartBlockRenderer for inline chart rendering
- Add slash menu chart capability activation (single-use per message)
- Add chart payload transport through Electron and CLI Web tool adapters
- Add error block handling for render-only chart tool failures
- Add chart payload persistence through content_blocks JSON storage
- Fix EChart.vue init timing: defer initChart() to nextTick so container
  layout completes before ECharts reads width (was rendering 92px canvases)
- Add comprehensive test coverage: core, integration, agent flow, frontend, smoke
- Add i18n for render_chart and get_schema in 4 locales
- Add project handoff documentation
2026-06-05 11:12:42 +08:00
digua dbc377854a fix(desktop): reset titlebar overlay cache on theme change 2026-06-05 11:12:42 +08:00
CEQ151 8f785ee0a8 fix(desktop): smooth Windows title bar overlay 2026-06-05 11:12:42 +08:00
digua 5144c8070a fix(update): suppress cli dev update badge 2026-06-04 14:37:12 +08:00
digua 9030d6b0c3 feat(update): add in-app update notice 2026-06-04 14:37:12 +08:00
digua 218c3c9ee9 feat(ai): group desensitize rules 2026-06-04 14:37:12 +08:00
CEQ151andClaude Opus 4.8 185e88ba3e fix(import): refresh sidebar message count after incremental import
After incremental import via Electron IPC, the sidebar session list
showed stale message counts. Three contributing gaps:

1. The chat:incrementalImport IPC handler did not notify the renderer
   to refresh the session list (unlike the API route which calls
   notifySessionListChanged). Added win.webContents.send('api:importCompleted')
   to trigger the Sidebar's existing onImportCompleted listener.

2. The postImportHook in worker adapters was async (due to dynamic
   import()) but the caller did not await it, causing a race condition
   where loadSessions() could read stale overview cache before
   computeAndSetOverviewCache() finished. Converted to static import
   making the hook synchronous, and updated the type to void | Promise<void>
   with await at call sites in both incremental-importer and
   streaming-importer.

3. The @imported handlers on group-chat and private-chat pages only
   refreshed local analysis data without calling sessionStore.loadSessions().
   Added the call so the sidebar updates immediately on the client side.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 10:20:28 +08:00
digua e68ce77266 feat(data): support CLI web data directory migration 2026-06-03 00:46:34 +08:00
digua 04c97ca9cf fix(data): defer data directory migration until restart 2026-06-03 00:46:34 +08:00
diguaandClaude Opus 4.8 2f8591fb8c perf(build): minify main process and lazy-load tiktoken rank table
Enable esbuild minification for main/preload (was renderer-only by default),
reducing main process bundle by ~55%. Extract cl100k_base BPE rank table out
of the synchronous startup path via dynamic import — it now lands in its own
chunk and is loaded on first agent run instead of at app startup.

Also fix Windows CI step to use PowerShell syntax for version injection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 00:46:34 +08:00
digua eea1dad907 fix(electron): offload chart plugin compute to worker 2026-06-02 15:41:21 +08:00
digua bf14c68899 refactor(ai): migrate remaining AI IPC to shared HTTP routes 2026-06-02 15:41:21 +08:00
digua 7dcc37e714 refactor(electron): remove session index IPC 2026-06-02 15:41:21 +08:00
digua 9a0e6093f3 fix(ai): harden shared SSE streaming 2026-06-02 15:41:21 +08:00
digua 1af644e4ab refactor(ai): migrate streaming to shared HTTP SSE
Squash Phase 2-2 streaming migration: frontend stream service, LLM SSE route, Agent SSE route, and IPC/preload cleanup.
2026-06-02 15:41:21 +08:00
diguaandCursor 769115240e feat(cache): migrate cache routes to shared HTTP package
Create CacheServiceAdapter + FetchCacheAdapter service layer and move
7 cache routes (info, clear, data-dir, import-log, save-to-downloads,
open-dir, show-in-folder) to @openchatlab/http-routes. Inject platform
callbacks (shell.openPath, showItemInFolder) via HttpRouteContext.
Frontend calls converge from window.cacheApi to useCacheService().
Electron IPC retains only selectDataDir/setDataDir (native dialog).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
diguaandCursor fcca22a8dc refactor(ai): remove orphaned AI conversation/message IPC handlers
Migrate conversation/message CRUD and debug queries from IPC to HTTP
by having ElectronAIAdapter extend FetchAIAdapter. Remove 18 dead
handlers (14 CRUD + 3 debug + 1 compressContext) from ipc/ai.ts and
slim down preload AiApi to IPC-only methods (filtering, export, tool
testing, desensitize rules, native shell).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
diguaandCursor ae90db63a5 feat(merge): migrate merge routes from IPC to shared HTTP package
Unify the merge workflow (parse/conflicts/execute/clear/export-for-merge)
across CLI, Electron, and web-serve into a single set of shared routes in
@openchatlab/http-routes.

Key changes:
- Move MergeSessionCache from CLI to node-runtime shared package
- Add dual-mode parse route (multipart upload for web, JSON filePath for Electron)
- Integrate merge routes into Electron internal API server with @fastify/multipart
- Create installMergeShims() with filePath-to-handle mapping for frontend
- Remove Electron merge IPC handlers, merger module, and preload bridges (~790 lines deleted)
- Address CodeX review: CHAT_DB_TABLES in openDatabase, no chatApi patching,
  outputName sanitization, resp.ok checks, @fastify/multipart in desktop deps

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
diguaandCursor 65fb5179cd refactor(electron): remove orphaned LLM/Assistant/Skill IPC handlers
Delete 40 IPC handlers in ipc/ai.ts whose preload bridges were
removed in the previous commit. These handlers are dead code since
the frontend now uses HTTP service layer (FetchLLMAdapter,
FetchAssistantAdapter, FetchSkillAdapter) via the Internal Server.

Removed:
- 20 llm:* CRUD handlers (config, provider registry, model catalog,
  custom provider/model, validate, remote models)
- 11 assistant:* handlers (CRUD, builtin catalog, import/reimport)
- 9 skill:* handlers (CRUD, builtin catalog, import/reimport)

Retained on IPC (still used):
- llm:chat, llm:chatStream (streaming)
- agent:runStream, agent:abort (streaming)
- All ai:* handlers (conversation CRUD, tool testing, compression,
  desensitize rules, debug SQL, filter/export)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
diguaandCursor 3ab162162b feat(ai): migrate AI CRUD routes to shared package and establish frontend service layer
Extract LLM config, assistant, skill, conversation and summary CRUD
routes from CLI-specific ai.ts into @openchatlab/http-routes, enabling
Electron Internal Server to serve AI endpoints via shared routes.

Frontend service layer:
- Create src/services/{llm,assistant,skill}/ with typed adapters
- Migrate all window.llmApi/assistantApi/skillApi calls to service layer
- Clean up Electron preload: remove CRUD bridges, keep only streaming IPC

Shared AI routes (packages/http-routes):
- ai-llm: config CRUD, provider registry, model catalog, custom store
- ai-assistants: CRUD, import/reimport, tool catalog
- ai-skills: CRUD, import/reimport, builtin catalog
- ai-conversations: conversation/message/debug CRUD
- ai-summaries: summary generation with LLM config injection
- Add requireAi fail-fast option to registerSharedRoutes

Backend improvements:
- Extract CustomProviderStore/CustomModelStore to node-runtime
- Fix authProfile persistence (onApiKeyCreated returns profileName)
- Reuse AI manager singletons in Electron (avoid dual instances)
- Prevent plaintext API key leakage in addConfig response
- Add authProfile regression tests

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
diguaandCursor f9b5b6b13d refactor: consolidate IPC bridge to native-only
Remove business IPC handlers/preload APIs that are now served by
Internal HTTP Server: preferences, NLP, data queries, message search,
analytics, members, SQL lab. Migrate chart modules from window.*Api
direct calls to useDataService() and NLP components to HTTP.

Make Internal Server a hard dependency, delete ElectronDataAdapter/
MessageAdapter/PreferencesAdapter and IPC fallback path. Retain IPC
only for native capabilities: file import, AI/LLM, session-index
summaries, agent streaming.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
digua 96a9d143c4 feat(electron): add internal http server for renderer adapters 2026-06-02 15:41:21 +08:00
diguaandCursor a8f0d5cb88 refactor: extract shared HTTP routes into @openchatlab/http-routes package
Migrate 30+ endpoints from apps/cli/src/http/ to packages/http-routes/
with a platform-agnostic HttpRouteContext DI interface, enabling future
reuse by Electron Internal Server.

Batch 1: auth, errors, context, sessions, members, preferences
Batch 2: analytics, sql, session-index, export, nlp
Batch 3: REST system, REST sessions

Includes 7 smoke tests via Fastify inject covering /api/v1/* and /_web/*
route groups.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
diguaandCursor cd3ae8c5ba feat(auth): harden auth security and add remember-me login
Improve auth hook security: restructure URL classification to fix
/_web/* bypass when requireAuth is active, use HMAC-SHA256 for constant-
time token comparison, remove dead webModeEnabled code.

Improve frontend auth flow: extract initializeApp() with watch-based
re-init after login, add getToken callback for real-time store reads,
unify SSE 401 handling via fetchWithAuth, switch default storage to
sessionStorage, add router guard consuming meta.public.

Add "Remember this device" checkbox on login page with dual
localStorage/sessionStorage strategy and safety warning.

Add 23 unit tests for auth hook matrix and http client.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
diguaandCursor a75fd0186d feat(cli): add --require-auth flag for /_web/* API protection
When enabled, all /_web/* routes require Bearer token authentication,
same as /api/v1/*. This hardens security for server/headless/public
deployments where the same-origin assumption doesn't hold.

- Add `require_auth` field to config schema (default: false)
- Add `setRequireAuth()` to auth hook, conditionally enforce auth on /_web/*
- Support `--require-auth` in both `chatlab start` and `--daemon` mode
- Read from config.api.require_auth or CLI flag override

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:41:21 +08:00
diguaandClaude Sonnet 4.6 9853c33e0b fix(cli): improve port-check error handling
- isPortAvailable 只将 EADDRINUSE 映射为 false,其他错误(EACCES/
  EADDRNOTAVAIL 等)通过 reject 抛出,避免误报"端口被占用"
- 将端口预检移入 startup try/catch 块内,确保所有绑定错误都走
  统一的 "Startup failed" 报错路径,不产生未处理的 Promise rejection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:56:08 +08:00
diguaandClaude Sonnet 4.6 b01c6c7e7a fix(daemon): use bin/chatlab.mjs as launchd/systemd entry point
dist/cli.mjs 只导出 run() 而不调用它,直接运行会立即静默退出(exit 0)。
bin/chatlab.mjs 才是真正调用 run() 的可执行入口,与 npm bin 字段一致。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:56:08 +08:00
diguaandClaude Sonnet 4.6 8c98daa654 feat(cli): pre-check port availability before startup with friendly error
启动前主动探测端口是否可用,被占用时立即给出可操作的引导(换端口 / lsof 命令),
避免先初始化 DB/路由后才抛 EADDRINUSE 的延迟报错体验。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:56:08 +08:00
diguaandClaude Sonnet 4.6 0a916e4b17 fix(types): use AIMessageRole type for message role params & strengthen conversation test assertion
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:56:08 +08:00
diguaandClaude Sonnet 4.6 c1e317a38a feat(cli): add clb as a short alias for the chatlab command
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:56:08 +08:00
diguaandClaude Sonnet 4.6 b96ec69730 fix(cli): add /_proxy/chatlab.fun reverse proxy for web mode
在 Web 生产模式(chatlab start)下,浏览器无法直连 chatlab.fun(CORS 限制),
导致首页底部社交链接(如小红书)及云端助手/技能预设拉取失败。
Vite dev proxy 已有对应配置,但生产 Fastify server 缺少该代理,现补全。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:56:08 +08:00
diguaandClaude Sonnet 4.6 9db9614246 fix(build): export getAllIndexStats from query index & add pre-release checks to changelog skill
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 14:01:13 +08:00