Commit Graph

355 Commits

Author SHA1 Message Date
亢奋猫
e9e7aef6f6 docs: update branch strategy for main code freeze (#13985) 2026-04-02 23:46:38 +08:00
LiuVaayne
7d0e066a9a feat(agents): add CherryClaw autonomous agent type (#13359)
### What this PR does

Before this PR:
Cherry Studio only supports `claude-code` as an agent type. Agents have
no autonomous scheduling, no IM channel integration, and no
soul/personality system.

After this PR:
Introduces **CherryClaw** — a new autonomous agent type with:
- **Soul-driven personality**: Markdown-based soul files with
mtime-cached reading
- **Task-based scheduler**: Poll-loop scheduler with drift-resistant
interval computation, tasks as first-class DB entities
(nanoclaw-inspired)
- **Internal claw MCP server**: `cron` tool (add/list/remove)
auto-injected into CherryClaw sessions for autonomous task management
- **Channel abstraction layer**: Pluggable adapter pattern with Telegram
as the first implementation (grammY, long polling, streaming drafts,
typing indicators)
- **Headless message persistence**: Channel and scheduler messages now
persist to the agent SQLite DB
- **Basic sandbox mode**: PreToolUse hook path enforcement + OS-level
sandbox toggle
- **Full UI**: Agent creation modal with type selector, settings tabs
(soul, tasks, channels, advanced), task management CRUD, channel catalog
with inline config
- **53 unit tests** across 8 test files covering all new services

<!-- Fixes # -->

### Why we need it and why it was done in this way

CherryClaw enables Cherry Studio agents to operate autonomously —
executing scheduled tasks and responding to IM messages without user
interaction. This is the foundation for "always-on" AI assistants.

The following tradeoffs were made:
- **Poll-loop scheduler over timer-based**: DB is the source of truth;
no timer state to restore on restart. Simpler, more robust at the cost
of up to 60s latency.
- **AgentServiceRegistry pattern**: Replaced hardcoded
`ClaudeCodeService` in `SessionMessageService` with a registry mapping
`AgentType` → service. Extensible for future agent types.
- **Internal MCP server for cron**: Rather than extending the SDK's tool
system, the `cron` tool is served as a standard MCP server at
`/v1/claw/:agentId/claw-mcp`. This lets the agent discover and use it
naturally.
- **Channel abstraction over direct Telegram integration**:
`ChannelAdapter` + factory registration enables future Discord/Slack
adapters without touching core routing logic.
- **Basic sandbox (not security boundary)**: PreToolUse hook + OS
sandbox provides best-effort restriction for well-behaved agents. Known
bypass vectors documented; hardening deferred.

The following alternatives were considered:
- cron-based OS scheduling (rejected: harder to manage lifecycle, no DB
integration)
- Direct Telegram bot API calls (rejected: grammY provides typed API,
connection management, and middleware)
- Modifying SDK builtin tools (rejected: internal MCP server is cleaner
separation)

### Breaking changes

None. This is a new agent type (`cherry-claw`) alongside the existing
`claude-code` type. No existing behavior is modified.

### Special notes for your reviewer

- **New DB migration**: `0003_wise_meltdown.sql` adds `scheduled_tasks`
and `task_run_logs` tables (agents DB only, not IndexedDB)
- **New dependencies**: `cron-parser` ^5.5.0, `grammy` ^1.41
- **Placeholder avatar**: `cherry-claw.png` is currently a copy of
`claude.png` — needs a proper distinct image
- **74 files changed, ~7400 lines added** — large PR, recommend
reviewing by phase (type system → backend services → MCP → channels → UI
→ tests)
- **Sandbox is basic only**: The PreToolUse path checking has known
bypasses (relative paths, variable expansion). Documented in handoff.md.
Hardening is follow-up work.
- The `handoff.md` file in the repo root contains full architectural
context and decisions

### Checklist

- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [x] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [ ] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. Check this only
when the PR introduces or changes a user-facing feature or behavior.
- [ ] Self-review: I have reviewed my own code (e.g., via
[`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`,
or GitHub UI) before requesting review from others

### Release note

```release-note
New CherryClaw agent type: autonomous agents with soul-driven personality, task-based scheduling (cron/interval/one-time), internal cron MCP tool for self-managed tasks, Telegram channel integration with streaming responses, and basic sandbox mode for filesystem restriction.
```

---------

Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: Siin Xu <31815270+SiinXu@users.noreply.github.com>
Signed-off-by: zhangjiadi225 <625013594@qq.com>
Signed-off-by: greycheng255 <greycheng255@gmail.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
Co-authored-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Siin Xu <31815270+SiinXu@users.noreply.github.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Co-authored-by: zhangjiadi225 <625013594@qq.com>
2026-04-02 19:58:34 +08:00
suyao
4dc1aac287 Merge remote-tracking branch 'origin/main' into DeJeune/merge-main-to-v2
Signed-off-by: suyao <sy20010504@gmail.com>

# Conflicts:
#	packages/aiCore/src/core/plugins/built-in/webSearchPlugin/helper.ts
#	pnpm-lock.yaml
#	src/main/ipc.ts
#	src/main/services/CodeCliService.ts
#	src/main/services/ProxyManager.ts
#	src/main/services/WebviewService.ts
#	src/main/services/WindowService.ts
#	src/main/services/__tests__/ProxyManager.test.ts
#	src/main/services/agents/services/claudecode/index.ts
#	src/preload/index.ts
#	src/renderer/src/aiCore/index_new.ts
#	src/renderer/src/aiCore/legacy/clients/BaseApiClient.ts
#	src/renderer/src/aiCore/legacy/clients/__tests__/index.clientCompatibilityTypes.test.ts
#	src/renderer/src/aiCore/legacy/clients/ovms/OVMSClient.ts
#	src/renderer/src/aiCore/legacy/clients/types.ts
#	src/renderer/src/aiCore/legacy/clients/zhipu/ZhipuAPIClient.ts
#	src/renderer/src/aiCore/legacy/middleware/feat/ImageGenerationMiddleware.ts
#	src/renderer/src/aiCore/plugins/PluginBuilder.ts
#	src/renderer/src/pages/code/CodeCliPage.tsx
#	src/renderer/src/pages/home/Messages/Blocks/ErrorBlock.tsx
#	src/renderer/src/pages/paintings/ZhipuPage.tsx
#	src/renderer/src/pages/settings/ProviderSettings/ModelList/ModelListItem.tsx
#	src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx
#	src/renderer/src/services/AssistantService.ts
#	src/renderer/src/services/__tests__/ApiService.test.ts
#	tsconfig.web.json
2026-04-02 18:03:03 +08:00
SuYao
1c0a5a95fa refactor: migrate to ai sdk v6 Phase 3 (#12235)
Continued from #12227

## Summary

Phase 3 of AI SDK v6 migration:

- **Image generation**: Migrate to native AI SDK
`generateImage`/`editImage`, remove legacy image middleware
- **Embedding**: Migrate to AI SDK `embedMany`, remove legacy embedding
clients
- **Model listing**: Refactor `ModelListService` to Strategy Registry
pattern (`listModels.ts`), consolidate 7 schema files into one
`schemas.ts`
- **OpenRouter image**: Bump `@openrouter/ai-sdk-provider` to 2.3.3 with
native image endpoint support, remove `isNativeImageGenerationProvider`
guard
- **GitHub Copilot**: Simplify extension by removing `ProviderV2` cast
and `wrapProvider`
- **Legacy removal**: Delete all legacy API clients, middleware
pipeline, and barrel `index.ts`
- **Rename**: `index_new.ts` → `AiProvider.ts`, `ModelListService.ts` →
`listModels.ts`

## Manual Test Plan

### P0 — Core paths + PR change focus

#### 1. Core Chat
- [ ] OpenAI model (e.g. GPT-4o): send text, verify streaming output
- [ ] Anthropic model (e.g. Claude Sonnet): verify chat works
- [ ] Gemini model: verify chat works
- [ ] DeepSeek model: verify chat works
- [ ] Reasoning mode (o3-mini, DeepSeek R1): verify thinking process
displays
- [ ] Send message with image (multimodal): verify model recognizes
image
- [ ] Abort mid-stream: verify clean termination, no errors

#### 2. Image Generation (key change area)
- [ ] DALL-E 3 / GPT-Image-1: verify image generation works
- [ ] OpenRouter image model: verify **native image endpoint** is used
(no longer chat completions)
- [ ] Image editing: upload image + text prompt, verify editImage path
- [ ] Verify generated images display correctly (both base64 and URL
formats)

#### 3. Model Listing (refactored area)
- [ ] Sync OpenAI models: verify names and groups
- [ ] Sync Gemini models: verify `models/` prefix stripped
- [ ] Sync Ollama models (local): verify display
- [ ] Sync OpenRouter models: verify chat + embedding models both appear
- [ ] Sync SiliconFlow models: verify grouping (e.g. `deepseek-ai/`)
- [ ] Sync GitHub Models
- [ ] Sync Together models
- [ ] Sync NewAPI service (e.g. CherryIn)
- [ ] Sync PPIO models: verify chat + embedding + reranker endpoints
merged

### P1 — Affected by refactor

#### 4. Provider Extensions
- [ ] GitHub Copilot: verify chat works (simplified wrapProvider logic)
- [ ] Ollama: verify chat works
- [ ] Vertex AI / Bedrock: verify chat works (if configured)

#### 5. MCP Tool Calling
- [ ] Enable MCP server, send tool-requiring message, verify tool
execution
- [ ] Verify both prompt tool use and function calling modes

#### 6. Auxiliary Functions
- [ ] Auto topic title generation (fetchMessagesSummary)
- [ ] Note summary (fetchNoteSummary)
- [ ] Translation/generation (fetchGenerate)
- [ ] API check (click "Check" button in settings)

### P2 — Indirect impact

#### 7. Knowledge Base
- [ ] Create knowledge base, associate with assistant, verify RAG
retrieval and embedding

#### 8. Web Search
- [ ] Enable native web search (Gemini/Perplexity), verify search
results in response

#### 9. Tracing
- [ ] Enable developer mode, send message, verify trace spans recorded
and displayed

---------

Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: icarus <eurfelux@gmail.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
2026-04-02 15:38:23 +08:00
fullex
ac9e434c9e refactor(ocr): migrate OcrService to lifecycle management
Move OcrService from direct-import singleton to lifecycle-managed
service. IPC handlers now use BaseService's tracked ipcHandle() for
auto-cleanup, and TesseractService worker is properly disposed on
shutdown via onStop(), fixing a resource leak.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-31 21:05:56 -07:00
fullex
92a99da758 refactor(lifecycle): adopt Activatable for TrayService, ApiServerService, AnalyticsService
- TrayService: replace manual createTray/destroyTray with activate/deactivate,
  driven by app.tray.enabled preference subscription
- ApiServerService: defer ApiServer creation to onActivate, delegate public
  start/stop/restart to activate/deactivate, extract shouldAutoStart from
  autoStartIfNeeded
- AnalyticsService: gate client creation behind activate, add preference
  subscription for data_collection.enabled so isActivated guard replaces
  per-call preference check
- LifecycleManager: improve bootstrap summary with fixed-width tag columns
  and Conditional/Activatable counts
- Decision guide: document that Activatable applies to runtime toggle
  scenarios even for lightweight resources

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-29 03:58:05 -07:00
fullex
6aa21a2feb refactor(lifecycle): unify resource cleanup into single Disposable mechanism
- Add toDisposable() utility to bridge () => void callbacks to Disposable
- Overload registerDisposable() to accept both Disposable and () => void,
  with return value for inline assignment
- Unify IPC tracking into Disposable: remove _ipcHandleChannels,
  _ipcOnListeners, _cleanupIpc(); ipcHandle/ipcOn now return Disposable
  and delegate cleanup to registerDisposable
- Add _doDestroy idempotency guard (safe no-op on already-destroyed)
- Export toDisposable from lifecycle module
- Update lifecycle docs to reflect unified cleanup and new APIs

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-29 00:25:15 -07:00
fullex
79bc26da04 feat(lifecycle): add Activatable interface for on-demand resource loading
Add a new optional lifecycle capability (symmetric with Pausable) that
allows services to defer loading heavy resources (native modules,
windows, caches) until a runtime condition is met.

- Add Activatable interface with onActivate()/onDeactivate() hooks
- Add isActivatable() type guard
- Add _doActivate()/_doDeactivate() to BaseService with idempotency
  and concurrency guards (_activating flag)
- Add protected activate()/deactivate() for self-activation within
  services
- Add activate()/deactivate() to LifecycleManager and Application
- Auto-deactivate in _doStop() (independent try/catch) and
  _doDestroy() (safety net)
- Add SERVICE_ACTIVATED/DEACTIVATED lifecycle events
- Add [A]/[C] tags to bootstrap summary for Activatable/Conditional
- Add comprehensive tests (20 cases)
- Update lifecycle-usage.md, lifecycle-decision-guide.md, CLAUDE.md

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-28 21:13:45 -07:00
fullex
1a68af729d refactor(lan-transfer): merge LocalTransferService and LanTransferClientService into unified LanTransferService
Merge the mDNS discovery service (LocalTransferService) and TCP transfer
service (LanTransferClientService) into a single LanTransferService. Unify
all naming from mixed Local/Lan prefixes to consistent Lan/lanTransfer.

- Merge two services into one, eliminating cross-service dependency
- Rename IPC channels: LocalTransfer_* → LanTransfer_* (values: lan-transfer:*)
- Rename shared types: LocalTransferPeer → LanTransferPeer, etc.
- Rename preload API: window.api.localTransfer → window.api.lanTransfer
- Lazy-start mDNS scanning: only scan when LAN transfer popup opens,
  stop when it closes (previously scanned from app boot)
- Fix missing @DependsOn(['WindowService']) on former LocalTransferService

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-28 07:19:49 -07:00
fullex
e356c53770 refactor(lifecycle): centralize quit event handling in Application
- Move before-quit/will-quit handlers from index.ts into Application:
  before-quit acts as preventQuit gate + markQuitting,
  will-quit runs shutdown() with timeout protection
- Add preventQuit(reason)/allowQuit(holdId) API replacing old
  setStopQuitApp boolean toggle, using UUID-based hold pattern
- Register quit handlers early in bootstrap (alongside SIGINT/SIGTERM)
  so quit is handled correctly even during early bootstrap stages
- Consolidate Application-scoped IPC (quit, relaunch, preventQuit,
  allowQuit) into Application.registerApplicationIpc()
- Move activate handler from index.ts into WindowService with proper
  lifecycle cleanup in onStop()
- Replace BrowserServer app.on('before-quit') with server.onclose
  callback, driven by MCP connection lifecycle instead of Electron events
- Include bootConfigService.flush() and loggerService.finish() in
  shutdown() so they execute on all quit paths
- Fix _isQuitting flag not resetting when before-quit blocks quit,
  which previously caused permanently broken quit state
- Namespace IPC channels: Application_Quit, Application_Relaunch,
  Application_PreventQuit, Application_AllowQuit under application: scope
- Expose renderer API as window.api.application.{quit, relaunch,
  preventQuit, allowQuit}
- Remove APP_ACTIVATE lifecycle event (WindowService listens directly)
- Update lifecycle documentation (bootstrap flow, shutdown flow,
  App Quit section with renderer usage)

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-28 04:02:39 -07:00
fullex
fb9a0dfcc5 feat(lifecycle): add Emitter/Event and Signal for inter-service communication
Introduce VS Code-style typed event primitives to the lifecycle system,
replacing ad-hoc app.emit patterns with type-safe, lifecycle-managed
alternatives.

- Add Emitter<T>/Event<T> for repeatable inter-service events
- Add Signal<T> for one-shot completion (implements PromiseLike)
- Add Disposable interface and BaseService.registerDisposable()
  for automatic cleanup on service stop/destroy
- Add comprehensive tests for event, signal, and disposable cleanup
- Update lifecycle documentation with new patterns and usage guide

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-27 10:07:24 -07:00
fullex
793a71ad8c docs(lifecycle): update documentation for @Conditional and getOptional
- Replace @ExcludePlatforms references with @Conditional in all docs
- Add Conditional Activation section to lifecycle-usage.md
- Document get()/getOptional() mutual exclusion in application-overview.md
- Add conditional service migration guidance
- Update file structure comments

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-27 06:38:34 -07:00
fullex
caed3b6166 refactor(ipc): migrate all lifecycle services to BaseService IPC tracking
Migrate 8 existing lifecycle services from direct ipcMain.handle()/ipcMain.on()
to this.ipcHandle()/this.ipcOn(), enabling automatic IPC handler cleanup on
service stop/destroy. Also move 6 residual handlers from the centralized ipc.ts
into their owning lifecycle services (CodeCliService, AnalyticsService).

Services migrated:
- LanTransferClientService (4 handlers)
- LocalTransferService (3 handlers)
- NodeTraceService (2 handlers, ipcMain import retained for monkey-patch)
- SpanCacheService (11 handlers)
- WindowService (14 handlers)
- CacheService (1 handle + 1 on)
- PreferenceService (6 handlers)
- SelectionService (9 handlers, 1 conditional Linux)

Handlers moved from ipc.ts to lifecycle services:
- CodeCliService (5 handlers)
- AnalyticsService (1 handler)

Standardize registerIpcHandlers() as the conventional method name across all
services (CacheService: setupIpcHandlers→registerIpcHandlers, PreferenceService:
registerIpcHandler→registerIpcHandlers). Update lifecycle docs and CLAUDE.md to
recommend the extracted registerIpcHandlers() pattern.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-27 02:57:02 -07:00
fullex
e83548bc28 feat(lifecycle): add built-in IPC handler tracking to BaseService
Add ipcHandle() and ipcOn() helper methods to BaseService that
automatically track registered IPC handlers and clean them up on
service stop/destroy, eliminating manual unregisterIpcHandlers()
boilerplate and preventing handler leaks.

Key changes:
- BaseService.ipcHandle(): wraps ipcMain.handle() with auto-tracking
- BaseService.ipcOn(): wraps ipcMain.on() with auto-tracking
- _doStop(): uses try/finally to guarantee IPC cleanup even on error
- _doDestroy(): safety-net cleanup for services destroyed without stop
- 9 new test cases covering all IPC lifecycle scenarios
- Updated lifecycle docs (decision guide, usage, overview, migration)

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-26 23:06:20 -07:00
fullex
c5b7d4a11a refactor(analytics): migrate AnalyticsService to lifecycle-managed pattern
Replace manual singleton with @Injectable lifecycle service (Phase.WhenReady).
Replace legacy configManager.getClientId() with v2 getClientId() from systemInfo.
Remove manual init/destroy calls from index.ts; consumers now use application.get().
Update lifecycle docs to remove incorrect Background phase analytics example.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-26 18:29:43 -07:00
fullex
7d20aa9576 refactor(application): unify app quit/exit through application.quit() and application.forceExit()
Replace scattered app.quit()/app.exit() calls across the codebase with
centralized application.quit() and application.forceExit() methods.

- Add quit(), forceExit(), markQuitting(), isQuitting to Application class
- Replace app.quit() with application.quit() in TrayService, WindowService,
  ipc.ts, and index.ts
- Replace app.exit(1) with application.forceExit(1) in WindowService and
  Application internal error handlers
- Replace app.isQuitting flag with application.isQuitting/markQuitting()
- Remove electron.d.ts type augmentation for app.isQuitting
- Add ESLint no-restricted-properties rule to warn on direct app.quit/exit
- Document quit API in application-overview.md

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-26 07:24:50 -07:00
fullex
8291f6b56c fix(migration): disable FK before each batch transaction
libsql is compiled with SQLITE_DEFAULT_FOREIGN_KEYS=1 (libsql-ffi/build.rs),
so every new connection defaults to foreign_keys = ON. Combined with
@libsql/client's transaction() nullifying its internal connection after each
use (this.#db = null), subsequent batch transactions ran on fresh connections
with FK enabled, causing SQLITE_CONSTRAINT_FOREIGNKEY on message.parentId
self-references.

Fix: run PRAGMA foreign_keys = OFF before each db.transaction() call in
ChatMigrator. Update comments across DbService, MigrationDbService, and
ChatMigrator to reference the confirmed libsql compile-time default.
Add FK caveat to migration guide and README.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-26 06:59:49 -07:00
fullex
f727662142 refactor(application): unify app relaunch through application.relaunch()
Centralize all relaunch logic in application.relaunch():
- Accept optional Electron.RelaunchOptions
- Add dev mode / unpackaged detection with user-facing dialog
- Absorb Linux AppImage and Windows Portable platform fixes from ipc.ts
- Replace direct app.relaunch() in BackupManager and IPC handler
- Document the convention in application-overview.md

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-26 03:08:27 -07:00
fullex
94729f8baa refactor(application): drop redundant suffixes from service control methods
Align naming with `get()` — remove `Service` suffix from pause/resume/
stop/start/restart and `App` suffix from relaunch. Matches industry DI
container conventions (Spring, NestJS, Inversify). Update lifecycle docs
accordingly.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-26 02:45:37 -07:00
fullex
600c01efa1 docs(bootConfig): add Boot Config system documentation
Add overview and schema guide for the BootConfig data system,
which provides synchronous file-based configuration before the
lifecycle system takes over. Update data README with BootConfig
navigation, decision table, and characteristics. Add BootConfig
row to CLAUDE.md data management table.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-26 01:53:37 -07:00
fullex
e8070115cf docs: move lifecycle/application docs to docs/en/references/lifecycle
Move detailed lifecycle and application documentation from source-adjacent
READMEs to docs/en/references/lifecycle/, following the same organizational
pattern as docs/en/references/data/. Source-adjacent READMEs are reduced to
lean pointers. Also add main process application.get() examples to data docs.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-25 01:17:57 -07:00
fullex
3d3f2d8932 docs(data): update code examples to use application.get() pattern
Replace outdated static/singleton access patterns in data documentation
with the lifecycle-managed application.get() pattern to match actual code.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-24 03:10:55 -07:00
fullex
cc697894fc Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2
Signed-off-by: fullex <0xfullex@gmail.com>

# Conflicts:
#	.agents/skills/.gitignore
#	.agents/skills/public-skills.txt
#	.claude/skills/.gitignore
#	.github/CODEOWNERS
#	.oxlintrc.json
#	CLAUDE.md
#	biome.jsonc
#	package.json
#	src/main/services/AnalyticsService.ts
#	src/main/services/AppUpdater.ts
#	src/main/services/agents/services/SessionService.ts
#	src/renderer/src/Router.tsx
#	src/renderer/src/aiCore/legacy/clients/BaseApiClient.ts
#	src/renderer/src/components/Icons/SVGIcon.tsx
#	src/renderer/src/components/Popups/UpdateDialogPopup.tsx
#	src/renderer/src/components/app/Sidebar.tsx
#	src/renderer/src/config/minapps.ts
#	src/renderer/src/config/providers.ts
#	src/renderer/src/config/sidebar.ts
#	src/renderer/src/hooks/agents/useActiveAgent.ts
#	src/renderer/src/hooks/agents/useAgentSessionInitializer.ts
#	src/renderer/src/hooks/agents/useAgents.ts
#	src/renderer/src/hooks/agents/useCreateDefaultSession.ts
#	src/renderer/src/hooks/useApiServer.ts
#	src/renderer/src/hooks/useAppUpdate.ts
#	src/renderer/src/pages/agents/AgentSettingsTab.tsx
#	src/renderer/src/pages/agents/components/AgentSessionInputbar.tsx
#	src/renderer/src/pages/agents/components/Sessions.tsx
#	src/renderer/src/pages/home/Chat.tsx
#	src/renderer/src/pages/home/HomePage.tsx
#	src/renderer/src/pages/home/Inputbar/tools/components/WebSearchQuickPanelManager.tsx
#	src/renderer/src/pages/home/Messages/MessageHeader.tsx
#	src/renderer/src/pages/home/Navbar.tsx
#	src/renderer/src/pages/home/Tabs/AssistantsTab.tsx
#	src/renderer/src/pages/home/Tabs/SessionsTab.tsx
#	src/renderer/src/pages/home/Tabs/TopicsTab.tsx
#	src/renderer/src/pages/home/Tabs/components/AssistantItem.tsx
#	src/renderer/src/pages/home/Tabs/components/AssistantTagGroups.tsx
#	src/renderer/src/pages/home/Tabs/components/Topics.tsx
#	src/renderer/src/pages/home/Tabs/components/UnifiedAddButton.tsx
#	src/renderer/src/pages/home/Tabs/components/UnifiedList.tsx
#	src/renderer/src/pages/home/Tabs/hooks/useActiveAgent.ts
#	src/renderer/src/pages/home/Tabs/index.tsx
#	src/renderer/src/pages/home/components/ChatNavBar/ChatNavbarContent/index.tsx
#	src/renderer/src/pages/home/components/ChatNavBar/Tools/SettingsButton.tsx
#	src/renderer/src/pages/home/components/ChatNavBar/Tools/SettingsTab/AssistantSettingsTab.tsx
#	src/renderer/src/pages/settings/AboutSettings.tsx
#	src/renderer/src/pages/settings/AgentSettings/components/ModelSetting.tsx
#	src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx
#	src/renderer/src/pages/settings/WebSearchSettings/BasicSettings.tsx
#	src/renderer/src/pages/settings/WebSearchSettings/WebSearchProviderSetting.tsx
#	src/renderer/src/pages/settings/WebSearchSettings/index.tsx
#	src/renderer/src/services/messageStreaming/callbacks/baseCallbacks.ts
#	src/renderer/src/store/runtime.ts
#	src/renderer/src/store/thunk/__tests__/streamCallback.integration.test.ts
#	src/renderer/src/types/index.ts
#	tsconfig.node.json
#	tsconfig.web.json
2026-03-17 06:17:41 -07:00
Phantom
fe0678a206 chore: migrate .claude/skills to directory symlinks (#13486)
### What this PR does

Before this PR:

`.claude/skills/<name>/SKILL.md` files were **copied** from
`.agents/skills/<name>/SKILL.md` via `pnpm skills:sync`. A dedicated
`skills-check-windows` CI job ran on `windows-latest` to verify
cross-platform file-copy compatibility.

After this PR:

`.claude/skills/<name>` entries are **directory symlinks** pointing to
`../../.agents/skills/<name>`, following the Single Source of Truth
(SSoT) principle. The Windows-specific CI job is removed; Windows
developers are expected to enable symlink support.

### Why we need it and why it was done in this way

The following tradeoffs were made:

- Windows developers must now manually enable symlink support (Developer
Mode + `git config --global core.symlinks true`). This is acceptable
because:
1. The existing `AGENTS.md` is already a symlink, so Windows
compatibility was never fully enforced.
2. Symlinks eliminate the need for file-copy synchronization, reducing
maintenance complexity.
3. Contributors are expected to have sufficient technical capability to
configure their environments.

The following alternatives were considered:

- Keeping file-copy sync: rejected because it duplicates content and
requires extra CI to verify consistency.

### Breaking changes

Windows developers who clone without symlink support enabled will get
plain text files instead of symlinks. They must:
1. Enable Developer Mode or grant `SeCreateSymbolicLinkPrivilege`
2. Run `git config --global core.symlinks true`
3. Re-clone or run `pnpm skills:sync`

### Special notes for your reviewer

- The `.github/workflows/ci.yml` diff includes minor quote-style changes
(`'` → `"`) from the YAML formatter — these are cosmetic only.

### Checklist

- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [x] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [x] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. Check this only
when the PR introduces or changes a user-facing feature or behavior.
- [ ] Self-review: I have reviewed my own code (e.g., via
[`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`,
or GitHub UI) before requesting review from others

### Release note

```release-note
NONE
```

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 08:46:46 +08:00
Phantom
d676b3b39a chore: add Zed editor settings example, clean up configs, and improve dev guides (#13457)
### What this PR does

Before this PR:
- No Zed editor configuration example existed for contributors using Zed
- Several config files had inconsistent JSON array formatting
- `biome.jsonc` had redundant exclude rules
- Contributing guides did not reference the development guide
- `development.md` (zh) was not translated to Chinese
- Node.js and pnpm versions were hardcoded in the development guide

After this PR:
- Added `.zed/settings.json.example` with Biome formatter,
oxc/eslint/biome fixAll, and import organization
- Cleaned up redundant Biome exclude rules and unified JSON array
formatting
- Added "Setting Up Your Development Environment" section to
`CONTRIBUTING.md` (en/zh) linking to the development guide
- Added Zed editor setup guide to `development.md` (en/zh)
- Translated `docs/zh/guides/development.md` to Chinese
- Node.js version now references `.node-version`; pnpm version
references `packageManager` in `package.json`
- VSCode extensions now reference `.vscode/extensions.json`

### Why we need it and why it was done in this way

The following tradeoffs were made:
- The Zed settings file is provided as an `.example` rather than a
direct `.zed/settings.json` to avoid overriding individual contributor
preferences.
- Versions reference their source of truth files rather than being
hardcoded, so docs stay in sync automatically.

The following alternatives were considered:
- N/A

### Breaking changes

None

### Special notes for your reviewer

- The JSON formatting changes are purely cosmetic — no behavior changes.
They align with Biome's default formatting rules.
- The `.zed/settings.json.example` includes `source.fixAll.eslint` and
`source.fixAll.oxc` alongside Biome, matching the project's
triple-linter setup.

### Checklist

- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [x] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [x] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. Check this only
when the PR introduces or changes a user-facing feature or behavior.
- [x] Self-review: I have reviewed my own code (e.g., via
[`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`,
or GitHub UI) before requesting review from others

### Release note

```release-note
NONE
```

---------

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 18:03:54 +08:00
fullex
072dd67a87 merge main into v2 2026-02-09 13:02:41 +08:00
Tony
816083f0ce docs: fix enterprise url (#12666)
Signed-off-by: Tony <TonyRL@users.noreply.github.com>
2026-02-01 16:15:44 +08:00
fullex
7ec65d2558 docs(README): add Layered Preset Pattern reference to documentation
Included a new entry for the Layered Preset Pattern in the README, providing guidance on presets with user overrides. This addition enhances the documentation by offering best practices for users.
2026-01-22 23:22:22 +08:00
fullex
f45485925e chore(docs): remove outdated database reference documentation
Deleted the Chinese database reference documentation as it is no longer relevant. This cleanup helps maintain the accuracy and relevance of the documentation.
2026-01-22 22:48:48 +08:00
fullex
3ee278aed2 docs(preferences): update preference documentation with related guides and streamlined instructions
Enhanced the preference documentation by adding a "Related Documentation" section in the preference-overview.md file and providing a concise summary for adding new preference keys in preference-usage.md. This improves navigation and clarity for users looking to implement preferences.
2026-01-19 23:02:07 +08:00
fullex
12e62782b1 feat(api): introduce success status constants and enhance handler response behavior
- Added `SuccessStatus` constants to standardize success status codes (200, 201, 202, 204) and improve type safety.
- Updated API handler to support custom status codes by returning `{ data, status }` format.
- Enhanced automatic status code inference based on HTTP methods in the API server.
- Updated documentation to reflect new status handling guidelines and examples.
2026-01-14 14:38:07 +08:00
fullex
ee4d1a227c feat(PreferenceService): add preference statistics functionality
- Introduced methods to retrieve comprehensive statistics for preferences, including summary and detailed per-key information.
- Implemented a new `getStats` method to provide insights into subscription counts and active windows.
- Enhanced the PreferenceService with additional interfaces for better type safety and clarity in statistics handling.
- Updated documentation to reflect the new statistics features and their usage.
2026-01-10 14:09:53 +08:00
fullex
ad37f0991a merge main into v2 2026-01-10 00:39:06 +08:00
fullex
fd95b9fe7d feat(CacheService): add cache statistics functionality
- Implemented comprehensive cache statistics in CacheService, allowing retrieval of summary and detailed information about cache tiers (memory, shared, persist).
- Introduced methods to estimate memory usage and format byte sizes for better readability.
- Enhanced the Inputbar component to log cache statistics for monitoring purposes.
- Updated related types to support new cache statistics features.
2026-01-09 23:58:13 +08:00
Phantom
43a48a4a38 feat(scripts): migrate feishu-notify to TypeScript CLI tool with subcommands (#12371)
* build: add commander package as dependency

* refactor(scripts): migrate feishu-notify to TypeScript with CLI interface

- Convert JavaScript implementation to TypeScript with proper type definitions
- Add CLI interface using commander for better usability
- Improve error handling and input validation
- Add version management and subcommand support

* ci(workflows): update feishu notification command and add pnpm install step

Update the feishu notification command to use CLI tool with proper arguments instead of direct node script execution
Add pnpm install step to ensure dependencies are available before running the workflow

* docs: add feishu notification script documentation

Add Chinese and English documentation for the feishu-notify.ts CLI tool

* feat(notify): add generic send command to feishu-notify

Add a new 'send' subcommand to send simple notifications to Feishu with customizable title, description and header color. This provides a more flexible way to send notifications without being tied to specific business logic like the existing 'issue' command.

The implementation includes:
- New send command handler and options interface
- Simple card creation function
- Zod schema for header color validation
- Documentation updates in both Chinese and English
2026-01-08 16:55:46 +08:00
fullex
190f7ba2e1 refactor(database-patterns): enhance schema guidelines and file organization
- Added new section on schema file organization, detailing principles and decision criteria for merging or separating table files.
- Updated file naming conventions for single and multi-table files, as well as helper utilities.
- Refactored import paths in various schema files to use the new `_columnHelpers` module instead of the deprecated `columnHelpers`.
- Removed obsolete `customSql.ts`, `columnHelpers.ts`, `messageFts.ts`, `tag.ts`, `entityTag.ts`, and other related files to streamline the codebase.

This refactor improves clarity in database schema management and aligns file organization with best practices.
2026-01-07 20:46:09 +08:00
fullex
2b815d8209 Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2 2026-01-06 00:00:43 +08:00
George·Dong
2a31fa2ad5 refactor: switch yarn to pnpm (#12260)
* refactor: switch workflows from yarn to pnpm

Replace Yarn usage with pnpm in CI workflows to standardize package
management and leverage pnpm's store/cache behavior.

- Use pnpm/action-setup to install pnpm (v) instead of enabling corepack
  and preparing Yarn.
- Retrieve pnpm store path and update cache actions to cache the pnpm
  store and use pnpm-lock.yaml for cache keys and restores.
- Replace yarn commands with pnpm equivalents across workflows:
  install, i18n:sync/translate, format, build:* and tsx invocation.
- Avoid committing lockfile changes by resetting pnpm-lock.yaml instead
  of yarn.lock when checking for changes.
- Update install flags: use pnpm install --frozen-lockfile / --install
  semantics where appropriate.

These changes unify dependency tooling, improve caching correctness,
and ensure CI uses pnpm-specific lockfile and cache paths.

* build: switch pre-commit hook to pnpm lint-staged

Update .husky/pre-commit to run pnpm lint-staged instead of yarn.
This aligns the pre-commit hook with the project's package manager
and ensures lint-staged runs using pnpm's environment and caching.

* chore(ci): remove pinned pnpm version from GH Action steps

Remove the explicit `with: version: 9` lines from multiple GitHub Actions workflows
(auto-i18n.yml, nightly-build.yml, pr-ci.yml, update-app-upgrade-config.yml,
sync-to-gitcode.yml, release.yml). The workflows still call `pnpm/action-setup@v4`
but no longer hardcode a pnpm version.

This simplifies maintenance and allows the action to resolve an appropriate pnpm
version (or use its default) without needing updates whenever the pinned
version becomes outdated. It reduces churn when bumping pnpm across CI configs
and prevents accidental pin drift between workflow files.

* build: Update pnpm to 10.27.0 and add onlyBuiltDependencies config

* Update @cherrystudio/openai to 6.15.0 and consolidate overrides

* Add @langchain/core to overrides

* Add override for openai-compatible 1.0.27

* build: optimize pnpm config and add missing dependencies

- Comment out shamefully-hoist in .npmrc for better pnpm compatibility
- Add React-related packages to optimizeDeps in electron.vite.config.ts
- Add missing peer dependencies and packages that were previously hoisted

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* build: refine pnpm configuration and dependency management

- Simplify .npmrc to only essential electron mirror config
- Move platform-specific dependencies to devDependencies
- Pin sharp version to 0.34.3 for consistency
- Update sharp-libvips versions to 1.2.4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* reduce app size

* format

* build: remove unnecessary disableOxcRecommendation option from react plugin configuration

* docs: Replace yarn commands with pnpm in documentation and scripts

* Revert "build: optimize pnpm config and add missing dependencies"

This reverts commit acffad31f8.

* build: import dependencies from yarn.lock

* build: Add some phantom dependencies and reorganize dependencies

* build: Keep consistent by removing types of semver

It's not in the previous package.json

* build: Add some phantom dependencies

Keep same version with yarn.lock

* build: Add form-data dependency version 4.0.4

* Add chalk dependency

* build: downgrade some dependencies

Reference: .yarn-state-copy.yml. These phantom dependencies should use top-level package of that version in node_modules

* build: Add phantom dependencies

* build: pin tiptap dependencies to exact versions

Ensure consistent dependency resolution by removing caret ranges and pinning all @tiptap packages to exact version 3.2.0

* chore: pin embedjs dependencies to exact versions

* build: pin @modelcontextprotocol/sdk to exact version 1.23.0

Remove caret from version specifier to prevent automatic upgrades and ensure consistent dependencies

* chore: update @types/node dependency to 22.17.2

Update package.json and pnpm-lock.yaml to use @types/node version 22.17.2 instead of 22.19.3 to maintain consistency across dependencies

* build: move some dependencies to dev deps and pin dependency versions to exact numbers

Remove caret (^) from version ranges to ensure consistent dependency resolution across environments

* chore: move dependencies from prod to dev and update lockfile

Move @ant-design/icons, chalk, form-data, and open from dependencies to devDependencies
Update pnpm-lock.yaml to reflect dependency changes

* build: update package dependencies

- Add new dependencies: md5, @libsql/win32-x64-msvc, @strongtz/win32-arm64-msvc, bonjour-service, emoji-picker-element-data, gray-matter, js-yaml
- Remove redundant dependencies from devDependencies

* build: add cors, katex and pako dependencies

add new dependencies to support cross-origin requests, mathematical notation rendering and data compression

* move some js deps to dev deps

* test: update snapshot tests for Spinner and InputEmbeddingDimension

* chore: exclude .zed directory from biome formatting

* Update @ai-sdk/openai-compatible patch hash

* chore: update @kangfenmao/keyv-storage to version 0.1.3 in package.json and pnpm-lock.yaml

---------

Co-authored-by: icarus <eurfelux@gmail.com>
Co-authored-by: beyondkmp <beyondkmp@gmail.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
2026-01-05 22:16:34 +08:00
fullex
2093452e69 fix(cache): enforce dot-separated naming for template keys
- Update template key pattern to use dots instead of colons
  (e.g., 'scroll.position.${id}' not 'scroll.position:${id}')
- Template keys follow same naming convention as fixed keys
- Add example template keys to schema for testing
- Add comprehensive type tests for template key inference
- Update mock files to support template key types
- Update documentation with correct template key examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 13:17:58 +08:00
fullex
fb51df99d0 feat(cache): add template key support for useCache with type inference
- Add type utilities for template key matching (IsTemplateKey, ExpandTemplateKey, ProcessKey)
- Add InferUseCacheValue<K> for automatic value type inference from template patterns
- Update useCache hook to support template keys with default value fallback
- Extend ESLint rule to validate template key syntax (e.g., 'scroll.position:${id}')
- Update CacheService.get() docs: clarify | undefined return is intentional
  (developers need to know when value doesn't exist after deletion/TTL expiry)
- Update cache documentation with template key usage examples

BREAKING CHANGE: CacheService.get() now explicitly returns T | undefined
(was implicit before). Callers should use ?? defaultValue for fallback.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 12:23:19 +08:00
fullex
9b6c8f1f60 Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2 2026-01-05 01:01:11 +08:00
fullex
6567d9d255 feat: update useDataApi hook and documentation for improved loading states and refetch logic
- Refactored `useQuery` and `useMutation` hooks to replace `loading` with `isLoading` for consistency in naming conventions.
- Enhanced `useQuery` to include `isRefreshing` state for better tracking of background revalidation.
- Updated documentation and examples to reflect changes in hook signatures and loading state management.
- Improved mock implementations in tests to align with the new hook signatures, ensuring accurate testing of loading states.
2026-01-05 00:12:01 +08:00
fullex
7cac5b55f6 feat: enhance cursor-based pagination in API documentation and types
- Added detailed explanations and examples for cursor semantics in `api-types.md`, clarifying the exclusive nature of cursors in pagination.
- Updated `CursorPaginationParams` interface to emphasize the cursor's role as an exclusive boundary in responses.
- Refactored `BranchMessagesQueryParams` to extend `CursorPaginationParams`, aligning with the new pagination logic.
- Modified `MessageService` to implement cursor-based pagination semantics, ensuring accurate message retrieval and response structure.
- Enhanced documentation throughout to provide clearer guidance on pagination behavior and usage patterns.
2026-01-04 22:31:15 +08:00
fullex
81bb8e7981 feat: implement new pagination types and enhance API documentation
- Introduced `OffsetPaginationParams`, `CursorPaginationParams`, and their corresponding response types to standardize pagination handling across the API.
- Updated existing API types and hooks to support both offset and cursor-based pagination, improving data fetching capabilities.
- Enhanced documentation with detailed usage examples for pagination, including request parameters and response structures, to aid developers in implementing pagination effectively.
- Refactored related components to utilize the new pagination types, ensuring consistency and clarity in data management.
2026-01-04 21:12:41 +08:00
kangfenmao
4c67e5b43a fix: update links in README and AboutSettings for correct documentation paths 2026-01-04 16:07:56 +08:00
fullex
37eac8c7fd feat: update documentation and enhance test mocks for data management
- Added a new section in the data management documentation for testing, including a link to unified test mocks for Cache, Preference, and DataApi.
- Refined the README for test mocks, providing a clearer overview and detailed descriptions of available mocks and their organization.
- Improved the structure and clarity of mock usage examples, ensuring better guidance for developers on utilizing the testing utilities effectively.
2026-01-04 10:44:38 +08:00
fullex
3dfd5c7c2b feat: add custom SQL handling for triggers and virtual tables
- Introduced a new method `runCustomMigrations` in `DbService` to execute custom SQL statements that Drizzle cannot manage, such as triggers and virtual tables.
- Updated `database-patterns.md` and `README.md` to document the handling of custom SQL and its importance in maintaining database integrity during migrations.
- Refactored `messageFts.ts` to define FTS5 virtual table and associated triggers as idempotent SQL statements for better migration management.
2026-01-04 01:07:04 +08:00
fullex
4f4785396a feat(migration): enhance ChatMigrator for comprehensive chat data migration
- Implemented detailed preparation, execution, and validation phases for migrating chat topics and messages from Dexie to SQLite.
- Added robust logging and error handling to track migration progress and issues.
- Introduced data transformation strategies to convert old message structures into a new tree format, ensuring data integrity and consistency.
- Updated migration guide documentation to reflect changes in migrator registration and detailed comments for maintainability.
2026-01-01 23:13:43 +08:00
fullex
799db1f8d1 Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2 2026-01-01 13:57:42 +08:00
beyondkmp
bc9eeb9f30 feat: add fuzzy search for file list with relevance scoring (#12131)
* feat: add fuzzy search for file list with relevance scoring

- Add fuzzy option to DirectoryListOptions (default: true)
- Implement isFuzzyMatch for subsequence matching
- Add getFuzzyMatchScore for relevance-based sorting
- Remove searchByContent method (content-based search)
- Increase maxDepth to 10 and maxEntries to 20

* perf: optimize fuzzy search with ripgrep glob pre-filtering

- Add queryToGlobPattern to convert query to glob pattern
- Use ripgrep --iglob for initial filtering instead of loading all files
- Reduces memory footprint and improves performance for large directories

* feat: add greedy substring match fallback for fuzzy search

- Add isGreedySubstringMatch for flexible matching
- Fallback to greedy match when glob pre-filter returns empty
- Allows 'updatercontroller' to match 'updateController.ts'

* fix: improve greedy substring match algorithm

- Search from longest to shortest substring for better matching
- Fix issue where 'updatercontroller' couldn't match 'updateController'

* docs: add fuzzy search documentation (en/zh)

* refactor: extract MAX_ENTRIES_PER_SEARCH constant

* refactor: use logarithmic scaling for path length penalty

- Replace linear penalty (0.8 * length) with logarithmic scaling
- Prevents long paths from dominating the score
- Add PATH_LENGTH_PENALTY_FACTOR constant with explanation

* refactor: extract scoring constants with documentation

- Add named constants for scoring factors (SCORE_SEGMENT_MATCH, etc.)
- Update en/zh documentation with scoring strategy explanation

* refactor: move PATH_LENGTH_PENALTY_FACTOR to class level constant

* refactor: extract buildRipgrepBaseArgs helper method

- Reduce code duplication for ripgrep argument building
- Consolidate directory exclusion patterns and depth handling

* refactor: rename MAX_ENTRIES_PER_SEARCH to MAX_SEARCH_RESULTS

* fix: escape ! character in glob pattern for negation support

* fix: avoid duplicate scoring for filename starts and contains

* docs: clarify fuzzy search filtering and scoring strategies

* fix: limit word boundary bonus to single match

* fix: add dedicated scoring for greedy substring match

- Add getGreedyMatchScore function that rewards fewer fragments and tighter matches
- Add isFuzzyMatch validation before scoring in fuzzy glob path
- Use greedy scoring for fallback path to properly rank longest matches first

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>

---------

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2025-12-30 19:42:56 +08:00