Commit Graph
828 Commits
Author SHA1 Message Date
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
digua d1637b41b8 feat(ui): optimize page header and toolbar layout 2026-05-31 16:56:08 +08:00
digua 066564c64e release: v0.23.0 v0.23.0 2026-05-31 14:01:13 +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
diguaandClaude Sonnet 4.6 334544880f fix(ai): enable thinking for effort-based models when 'auto' is selected
When the user selects 'auto' thinking level for an effort-based reasoning
model (Kimi, Doubao) that has thinkingLevelMap but no thinkingFormat,
the previous code fell through to `return undefined`, causing pi-agent-core
to treat it as 'off' and send reasoning_effort:'none' to the API —
silently disabling thinking.

pi-ai's clampThinkingLevel only covers EXTENDED_THINKING_LEVELS (no 'auto'),
so 'auto' cannot be forwarded verbatim. Return 'high' instead, matching
the behavior for thinkingFormat models, to at least enable reasoning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 10:28:29 +08:00
diguaandClaude Sonnet 4.6 7558eed5a5 fix(ai): fall back to heuristic for non-builtin custom models in inferReasoning
Custom models auto-saved by ensureCustomProvidersAndModels carry only
capabilities:['chat'], so inferReasoning was returning reasoning=false
even for models like qwen3:8b whose names match the reasoning heuristic.
The UI still showed thinking levels via getSupportedThinkingLevels, but
selections were silently ignored by the backend.

Fix: for non-builtin (builtin=false) model definitions, also apply the
name/provider heuristic as a fallback alongside the capabilities check.
Builtin catalog models remain authoritative.

Adds a regression test covering the exact findModelFn shape produced by
ensureCustomProvidersAndModels.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 10:28:29 +08:00
diguaandCursor 999ce58007 fix(ai): use active slot modelId for thinking level and context window computation
The supportedThinkingLevels, modelContextWindow, and model name display
were reading from config.model (static config value) instead of the
slot's modelId (actual user-selected model). This caused the thinking
selector to show/hide incorrectly when users switched models.

Also fix HTTP utils sending Content-Type: application/json with empty
body when body is null (e.g. setFastModel(null)), which caused Fastify
to return 400.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-31 10:28:29 +08:00
diguaandCursor 9bc0c4279d refactor(ui): simplify model button and optimize session index loading
- StatusBar model button: show model name instead of provider, click opens
  settings directly (scrolls to default model section), remove dropdown
- SessionIndexSection: replace N serial pluginQuery calls with single batch
  API (GET /_web/sessions/index-stats), add IntersectionObserver lazy loading
- Full-stack implementation: CLI route, Electron IPC/Worker, frontend adapters

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-31 10:28:29 +08:00
diguaandCursor 783d61f742 feat(ai): upgrade thinking level control with default/auto options and broader model coverage
- Add 'default' option (no reasoning params sent, model uses native behavior)
- Add 'auto' option for models that natively support it (deepseek_hybrid, kimi, doubao)
- Expand model recognition with regex coverage for 15+ model families
- Add Gemini 2.5+ thinking level support via native Google provider
- Simplify deepseek_hybrid options to ['default', 'off', 'auto'] aligned with Cherry Studio
- Use primary theme color for thinking selector instead of hardcoded blue
- Update docs with thinking control architecture section

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-31 10:28:29 +08:00
diguaandClaude Opus 4.8 a31c672474 feat(ai): add per-model thinking level selector in chat status bar
Adds a lightbulb button next to the model switcher in ChatStatusBar
that lets users choose the thinking intensity for each reasoning model,
with the choice remembered per model slot (configId:modelId).

Key changes:
- packages/core/src/ai/thinking.ts (new): per-model-type thinking level
  table inspired by cherry-studio's MODEL_SUPPORTED_REASONING_EFFORT.
  Covers Qwen/GLM (on/off), DeepSeek V4 (high/max), o-series
  (low/medium/high), gpt-5.x (minimal–xhigh), Kimi/Doubao/Grok and a
  default bucket. Exports getSupportedThinkingLevels, isReasoningModel,
  getThinkingCompat.
- packages/node-runtime/src/ai/llm-builder.ts: inferReasoning now calls
  getThinkingCompat() which sets compat.supportsReasoningEffort and
  compat.thinkingLevelMap so pi-ai can inject the correct request param
  (reasoning_effort for OpenAI/DeepSeek, enable_thinking for Qwen/GLM).
- packages/node-runtime/src/ai/agent/types.ts + core.ts: AgentCoreOptions
  gains an optional thinkingLevel; core.ts:93 uses clampThinkingLevel()
  (from pi-ai) to honour it safely.
- Full transparent pass-through: desktop Agent → IPC handler → preload
  → agentApi.runStream; CLI HTTP route → runServerAgent → runAgentCore.
- src/stores/prompt.ts: thinkingLevels Record<configId:modelId,
  ThinkingLevel> persisted in backendPersist; getThinkingLevel/
  setThinkingLevel helpers.
- src/stores/aiChat.ts: reads current model slot and passes remembered
  level to both sendMessage and editCurrentRoundOnly runStream calls.
- ChatStatusBar.vue: UPopover thinking selector appears only for
  reasoning models, shows only the levels that model supports, highlights
  current choice, hides for non-reasoning models.
- 46 tests passing (26 new in thinking.test.ts + 20 in llm-builder).

Scope: openai-completions path only (Qwen, DeepSeek, OpenAI, xAI, Kimi,
Doubao, SiliconFlow, OpenRouter…). Anthropic/Gemini native thinking is
out of scope for this version.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:28:29 +08:00
diguaandClaude Opus 4.8 1716cf392f refactor(ai): replace manual reasoning switches with auto-inference
Remove the "Reasoning Model" and "Disable Thinking Mode" toggles from
the model config dialog. These switches were injecting `enable_thinking`
(a Qwen/DashScope-specific request parameter) into all providers,
causing 400 errors on OpenAI, Anthropic, Gemini, and other official
services.

Replace with automatic inference in buildPiModel:
- reasoning: true when the model's catalog capabilities include
  'reasoning'; falls back to a model-name heuristic for unlisted
  custom/self-hosted models (qwen3, qwq, deepseek-r, o1/o3, etc.).
- compat.thinkingFormat 'qwen': only set when reasoning is true AND
  the model is from the qwen provider or the model id contains
  "qwen"/"qwq". All other providers get compat: undefined and will
  never receive enable_thinking.

This means official reasoning models (o3, deepseek-reasoner, etc.) now
automatically get thinkingLevel:'medium', and self-hosted Qwen3
models continue to work as before — without any manual toggle.

Behavior change: models with 'reasoning' in their catalog capabilities
now default to thinkingLevel:'medium' (previously always 'off' unless
the manual switch was enabled).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:28:29 +08:00
diguaandCursor 886642c1a4 feat: split message view into type/time analysis tabs with enriched profile cards
Split the monolithic MessageView into two focused modules:
- TypeAnalysisView: type distribution, text depth analysis, length distributions
- TimeAnalysisView: hourly/weekday/monthly/yearly distributions, member trend, heatmap, calendar

Each tab has a redesigned narrative profile card with rich insights:
- TypeProfileCard: date range, total messages, non-text breakdown pills, 4 metric cards
- TimeProfileCard: active days narrative, time personality labels (multi-dimensional), 4 metric cards

Also: reduce responseLatency font size in RelationshipView for better readability.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-31 10:28:29 +08:00
diguaandClaude Sonnet 4.6 affb7a50e4 fix(daemon): quote ExecStart argv to handle paths with spaces on Linux
Wraps each argument in double quotes when building the systemd unit's
ExecStart= line, so installs under paths containing spaces (e.g. home
directories with spaces, nvm paths) no longer cause systemd to
mis-tokenize the command and fail to start the service.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 14:19:42 +08:00
diguaandCursor 969406915f feat(ai): add confirmation dialog before regenerating all session indexes
Warn users that regeneration will clear all existing AI summaries.
Uses the same UModal pattern as other confirmation dialogs in settings.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 14:19:42 +08:00
diguaandCursor fdb6d8f648 feat(import): update demo data sources to 4 files
Switch from 2 demo files (group + private) to 4 files:
- demo-group.json
- demo-private-A-cuilan.json
- demo-private-B-wukong.json
- demo-private-C-spider.json

Update DemoImportResult.privateSessionId to privateSessionIds array
to support multiple private chat demos.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 14:19:42 +08:00
diguaandCursor b3c2b20a9f fix(ai): make message editing safe against data loss and stale state
- insertMessageAfter: update active_message_id when appending to tail
  so the new reply is on the active path after reload
- editAndOverwriteAll: add hasConfig + abort checks before
  deleteMessagesFrom to prevent data loss when LLM is unconfigured or
  a concurrent request starts
- editCurrentRoundOnly: defer all DB mutations until after stream
  completes; on abort/error only in-memory state is restored
- sync in-memory parentId after relinking so follow-up edits send the
  correct historyLeafMessageId

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 14:19:42 +08:00
digua ce1065e295 docs(api): rename API import to API push 2026-05-30 14:19:42 +08:00
digua e78c8f9368 feat(ai): add fork conversation UI button on AI replies 2026-05-30 14:19:42 +08:00
diguaandCursor 6224ca996e refactor(ai): replace branching with edit-and-regenerate model
Remove the message branching/tree system in favor of a simpler editing model:
- Default: edit a message and only regenerate the current round's AI response
- Optional: overwrite all subsequent messages when editing

Key changes:
- Backend: add updateMessageContent, deleteAndRelinkMessage, insertMessageAfter,
  deleteMessagesFrom, forkConversation; remove createMessageBranch, switchMessageBranch
- Platform layer: add IPC/HTTP handlers for new methods across Electron and CLI
- Frontend store: refactor editMessageAndRegenerate with two modes
- UI: replace branch navigation with "overwrite subsequent" checkbox,
  auto-resizing edit textarea
- Fix insertMessageAfter missing debug_context from pendingDebugContextMap
- Update tests to cover new editing methods

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 14:19:42 +08:00
CEQ151 d3c62c4f9d feat(ai): support editable message branches 2026-05-30 14:19:42 +08:00
digua 3a8f61fdf0 fix(cli): start web dev backend with start command 2026-05-30 14:19:42 +08:00
diguaandClaude Sonnet 4.6 0e03295258 feat(cli): add daemon mode via start --daemon, stop, and status commands
- Replace 6-subcommand daemon group with simpler top-level design:
  chatlab start --daemon  install as system service (launchd/systemd)
  chatlab stop            uninstall service and disable auto-start
  chatlab status          show resident service status
- Drop temporary background process layer; daemon = system service only
- Store port/host meta in ~/.chatlab/daemon.json for status display
- Fix --no-open description: Web UI still runs, only browser is suppressed
- Update quick-start docs (cn/en/tw) to reflect new commands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 14:19:42 +08:00
diguaandClaude Sonnet 4.6 6cdc040ce8 feat(cli): replace serve/web commands with unified start command
- Add `chatlab start` with --headless (API-only) and --no-open flags
- Remove redundant `serve` and `web` commands
- Update fetch adapter comments to reference chatlab start
- Add chatlab start usage examples to quick-start docs (cn/en/tw)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 14:19:42 +08:00
digua 8e01121b7a release: v0.22.1 v0.22.1 2026-05-29 15:07:02 +08:00
diguaandClaude Opus 4.8 a653b5be6d docs: restructure docs nav and move quick-start under usage
- Move quick-start.md to usage/ across cn/en/tw
- Switch locale index pages from home to doc layout
- Add Baidu analytics script and adjust nav doc links

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 14:35:48 +08:00
digua 45dfa5026f fix(session-index): honor selected session IDs in CLI batch summary generation 2026-05-27 23:47:27 +08:00
digua 46204db9b8 fix(ai): revalidate credentials when base URL changes in openai-compat mode 2026-05-27 23:47:27 +08:00
digua 61380f53cc style(ui): optimize chat record list density and message bubble style 2026-05-27 23:47:27 +08:00
diguaandCursor 88ab0ae172 fix(ai): correct apiKeySet detection and prevent stale key reuse
- Fix apiKeySet reporting false positives for local no-key configs by
  resolving the actual key via resolveApiKey and excluding placeholders
- Prevent editing a config from reusing an incompatible API key when
  provider or connection mode has changed
- Pass summary strategy to single-session generation for consistency

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 23:47:27 +08:00
digua a9b8599417 refactor(i18n): move session index keys from storage to ai namespace 2026-05-27 23:47:27 +08:00
diguaandCursor 6faeee3042 fix(ui): make batch summary stop button respond immediately
Previously clicking stop would only take effect after the current LLM
request finished. Now the UI state updates instantly while the in-flight
request completes silently in the background.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 23:47:27 +08:00
diguaandCursor 6727ff609c feat(ai): add summary strategy with brief and standard detail levels
Support two summary strategies (brief/standard) for AI-generated session
summaries. Users can choose their preferred detail level in Settings > AI >
Session Index. Standard (default) produces richer summaries covering people,
events, and key details.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 23:47:27 +08:00
diguaandCursor eaff16d555 fix(cli): wire up batch summary generation in CLI Web to fix page freeze
- Implement generateSummary/checkCanGenerateSummary in FetchSessionIndexAdapter
  via existing HTTP endpoints instead of stubs that returned instantly
- Add checkCanGenerate service function in summary-service.ts
- Add POST /_web/sessions/:id/summaries/check-can-generate route

The page froze because stub methods returned synchronously, causing a tight
loop of hundreds of Vue reactive updates without any network delay.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 23:47:27 +08:00
diguaandCursor 63e101feb4 fix(cli): fix third-party service misidentified as local when editing in CLI Web
- Add apiKeySet field to GET /_web/ai/llm/configs response
- Allow saving in edit mode without re-entering API key when key already set
- Skip API key validation on save when editing with existing key unchanged
- Show edit-mode placeholder hint on API Key input
- Add missing customModels/disableThinking/isReasoningModel to CLI route types

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 23:47:27 +08:00
digua 1aee8133a3 release: v0.22.0 v0.22.0 2026-05-26 23:29:34 +08:00
digua bc3871c9b1 fix(settings): remove broken web update action 2026-05-26 23:19:47 +08:00
digua 8a54568cd4 style(ui): optimize sidebar density and enhance dark mode contrast for tab selectors 2026-05-26 23:19:47 +08:00
digua 3565cad5a9 feat(sidebar): add logo and update toggle icon to panel-right 2026-05-26 23:19:47 +08:00
digua d2c0edd389 fix(cli): continue web serve after data warning 2026-05-26 23:19:47 +08:00
digua 44e0517890 fix(home): restore shared quick start buttons 2026-05-26 23:19:47 +08:00
diguaandClaude Sonnet 4.6 7738b47ab7 refactor: migrate documentation links from chatlab.fun to docs.chatlab.fun
Update links pointing to documentation pages (usage guides, format specs,
troubleshooting, API docs) across README, source code, and i18n files to
use docs.chatlab.fun. Main site links (homepage, roadmap, community,
assets) remain unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 23:19:47 +08:00
digua c736fdc93b fix(cli): disable web self update execution 2026-05-26 23:19:47 +08:00
diguaandClaude Sonnet 4.6 5a524b8abf fix: correct i18n key path and replace deprecated ECharts api.style()
- ChatExplorer.vue: fix `ai.assistant.systemPrompt` → `ai.assistant.config.systemPrompt`
  (missing 'config' level in key path caused vue-i18n missing-key warnings)
- OverviewIdentityCard.vue: replace deprecated `api.style()` with
  `api.visual('color')` + literal style object (ECharts 6.x deprecation)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 23:19:47 +08:00
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