Commit Graph

96 Commits

Author SHA1 Message Date
fullex
2fdb01bfab refactor(i18n): give main process its own locale catalog and drop renderer imports
Main previously imported all 12 renderer translation JSONs by relative path to
build its t() table — a main->renderer boundary violation that also inlined
~3.86 MB of translations the main process never uses. Main now owns a small,
independent catalog under src/main/i18n (~59 keys: app menu, tray, dialogs,
context menu, the OAuth callback page and a few shared strings), statically
imported for all 12 languages (~48 KB total).

- src/main/utils/language.ts -> src/main/i18n/index.ts (git mv): swap the renderer
  JSON imports for the local catalog, add an en-US fallback to t(), and narrow the
  now-internal `locales` export. AppMenuService reads getI18n() instead of the
  locales map; the OAuth callback drops its duplicate translator for t().
- src/main/i18n/{locales,translate}/*.json: the main catalog, extracted from the
  renderer catalog (zero translation loss), aligned and sorted across all 12 files.
- Renderer catalog: delete the now main-exclusive keys (appMenu.*, tray.*, dialog.*,
  settings.mcp.oauth.callback.*, common.{inspect,paste,cut},
  agent.session.workspace_status.{missing,not_directory}).
- Composer delete buttons used t('appMenu.delete') by mistake; switch to
  t('common.delete') (byte-identical in all 12 languages) so appMenu is fully
  main-owned.
- readErrorMessage: take a pre-translated `fallback` string instead of an i18next
  key, and move it from @shared/ai into src/main/ai/provider/custom (main-only after
  the change); its 6 provider call sites pass main's t(...).
- Tooling: check-i18n now validates the main catalog's 12 files plus a literal-t()
  key-coverage check for main sources; sync-i18n and auto-translate-i18n cover both
  catalogs. eslint bans relative **/renderer/** in main/preload; TopicNamingService
  test reads the renderer catalog from disk instead of importing it.
- Docs: main-process-architecture.md records i18n as a governed top-level expansion
  and closes the resolved deviation; CLAUDE.md lists the new directory.
2026-07-03 08:13:04 -07:00
fullex
9b9570116a refactor(db): replace libsql with better-sqlite3 + sqlite-vec (#16626) 2026-07-02 13:21:13 +08:00
fullex
2dd0d7b8e1 feat(cache): add main-process persist cache tier
Add an independent, main-authoritative persist tier to the main-process
CacheService, stored as a JSON file at {userData}/cache.json. It is inline
(mirroring the renderer persist structure), fixed-keys-only, with no delete
or TTL; values are loseable and fall back to schema defaults on miss.

Writes are debounced (200ms) and flushed atomically (temp file + rename),
with a flush on service stop. Unknown/stale keys in the file are pruned on
load to keep the fixed-keys contract. The renderer persist IPC relay is
untouched: Main cannot read renderer persist and vice versa.

This phase is architecture-only: the schema ships a single scaffold key
(internal.persist_probe) and no business consumer; window-state and other
consumers will follow. Docs under docs/references/data and CLAUDE.md are
updated to distinguish the new Main persist store from the relay.
2026-06-26 09:51:04 -07:00
fullex
ecffd880f0 refactor(store): delete the deprecated v1 Redux store
With ImportService migrated to DataApi (#16415), the v1 Redux store at
src/renderer/store/ has zero runtime consumers. Delete the directory (30
files) along with the already-stubbed main-process ReduxService bridge.

Clean up the now-stale residue:
- Remove dead vi.mock('@renderer/store') factories from 14 test files
  whose code under test no longer imports the store.
- Drop Redux from the CLAUDE.md "Removing" enumerations and refresh the
  renderer-architecture / knowledge-service / v2-todo docs.
- Fix dangling store/ references in the MiniAppMigrator and
  builtinMcpServers comments.

The v2 migration's Redux Persist readers (ReduxStateReader etc.) are left
untouched: they read serialized on-disk data, not this store.
2026-06-26 01:08:20 -07:00
亢奋猫
eb2622e9af refactor(ui): remove antd dependency (#16336)
Co-authored-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: kangfenmao <kangfenmao@qq.com>
Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
2026-06-26 15:49:22 +08:00
fullex
c829c46476 docs(contributing): drop stale Security section and fix command/path inaccuracies
- remove the Security section: two bullets pointed at non-existent tooling (express-validator, ipaddr.js mislabeled as API-server validation) and the rest restated framework-enforced or generic Electron hygiene; the load-bearing conventions already live in their source files and reference docs
- pnpm lint: describe the final step as "format (writes files)" instead of "format check" — it mutates, it is not read-only
- pnpm build:check: drop the drift-prone "= pnpm lint && pnpm test" enumeration (the real chain also runs docs:check-links) and add a broken-doc-links troubleshooting hint
- data-classify: point classification.json / target-key-definitions.json at their real location (.../data-classify/data/)
2026-06-24 09:16:04 -07:00
fullex
c3aa53e163 docs(contributing): refine v1 cleanup posture and trim stale/duplicated guidance
- v1 residue: shift Coexistence Mindset from "leave alone" to opportunistic removal now that the refactor is in its cleanup stage, with a matching exception added to the Surgical Changes principle
- drop volatile specifics that duplicate the real source of truth: Node/pnpm version pins (enforced by package.json) and IpcApi migration progress ("Stage 0")
- de-duplicate: keep the v1-fix branch policy, the UI library prohibition, and the no-console.log rule in their durable homes; the v2 section and Logging section now point to them instead of restating
2026-06-24 08:47:02 -07:00
LiuVaayne
efecdd5007 refactor(binary-manager): unify CLI binary acquisition behind mise-backed BinaryManager (#15184)
### What this PR does

**Before this PR**, Cherry Studio managed external CLI binaries through
five uncoordinated mechanisms — each requiring its own download script,
IPC channel, and on-disk layout:

| Mechanism | Where it lived | How it worked |
|---|---|---|
| rtk extraction | `src/main/utils/rtk.ts` + `AgentBootstrapService` |
Copies bundled binary to `~/.cherrystudio/bin/` |
| OpenClaw installer | `resources/scripts/install-openclaw.js` |
Downloads from GitHub/mirror with custom extraction |
| CodeCliService | `src/main/services/CodeCliService.ts` | `bun install
-g` to `~/.cherrystudio/install/global/` |
| ripgrep | `node_modules/@anthropic-ai/claude-agent-sdk/vendor/` |
Vendored, hardcoded path in `FileStorage` |
| (old) MiseService | `src/main/services/MiseService.ts` | Bundled mise
+ `mise use -g` |

**After this PR**, a single `BinaryManager` lifecycle service owns all
third-party CLI binary acquisition. It wraps
[mise](https://mise.jdx.dev) as the only acquisition backend (no custom
`BinaryBackend` interface — mise's polyglot grammar already covers
`npm:`, `pipx:`, `github:`, registry entries). Tools install into an
isolated environment under `~/.cherrystudio/mise/` so user-level mise
installs are never touched. `uv`, `bun`, `rg`, and mise itself ship
bundled at build time for instant first-run availability; everything
else flows through mise on demand.

<img width=\"1304\" height=\"714\" alt=\"BinaryManager settings UI\"
src=\"https://github.com/user-attachments/assets/7a4b78ab-5aa2-4e97-9ab7-134b20a4d78d\"
/>
<img width=\"1165\" height=\"748\" alt=\"Three-state managed vs bundled
vs not-installed\"
src=\"https://github.com/user-attachments/assets/a0dcfb7d-8bc3-4acd-b563-0fc04d99e252\"
/>
<img width=\"523\" height=\"328\" alt=\"Custom tool dialog\"
src=\"https://github.com/user-attachments/assets/90c3ee95-7f2a-4daf-a334-f20de6ff5ca2\"
/>

Fixes #15183. Addresses #15370.

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

Adding a new managed CLI tool should be a one-line preset entry — not 4+
files of bespoke download/extract/IPC code. mise is a mature polyglot
tool manager that already speaks the backends Cherry needs.

**Tradeoffs made:**
- **mise bundled at build time** (~15 MB per platform) rather than
downloaded at first run — faster first-run UX, no chicken-and-egg on a
fresh install.
- **Fully isolated mise environment** (\`HOME\`/\`XDG_*\`/\`MISE_*\` all
relocated under \`feature.binaries.data\`) — Cherry never reads or
writes the user's own \`~/.config/mise/\` or \`~/.local/share/mise/\`.
- **No custom \`BinaryBackend\` interface.** mise's grammar (\`npm:\`,
\`pipx:\`, \`github:\`, registry) is already polyglot; wrapping it would
be a shallow seam that re-implements what mise owns. Removing this
abstraction makes consumers simpler (deletion test passes).
- **Auth-token policy: opt-in only.** Ambient \`GITHUB_TOKEN\` /
\`GH_TOKEN\` are not forwarded into mise's process env. Users who hit
GitHub's unauthenticated 60 req/hr API limit can set
\`CHERRY_GITHUB_TOKEN\` to raise it to 5000 req/hr without consenting to
share their general shell token.
- **China mirror auto-detection.** \`isUserInChina()\` toggles
\`NPM_CONFIG_REGISTRY=registry.npmmirror.com\` +
\`PIP_INDEX_URL=pypi.tuna.tsinghua.edu.cn\` for every npm/pipx backend
transparently.

**Alternatives considered:**
- *Keep per-tool install scripts.* Doesn't scale — each new tool is 4+
files of duplicated logic.
- *Use mise from user's \`PATH\`.* Would depend on user having mise
installed and could conflict with their config.
- *Custom \`BinaryBackend\` abstraction.* Shallow wrapper over mise's
grammar; no second backend in sight; deletion test passes.

**Scope (what's in / what's out):**
- **In:** uv, bun, ripgrep, claude-code, openclaw, gh, opencode,
gemini-cli, lark, kimi-cli, qwen-code, iflow-cli, github-copilot-cli —
anything mise can install as a single relocatable binary.
- **Out:** \`OvmsManager\` (multi-file server provisioning, hardware
detection, generated config); Tesseract OCR data (not a binary; lives
with \`OvOcrService\`).

### Breaking changes

None at the user-facing layer. v2 data is throwaway per CLAUDE.md, so
the preference-key rename (\`feature.mise.*\` → \`feature.binaries.*\`)
intentionally ships without a migrator.

### Special notes for your reviewer

**Architecture & docs**
- \`docs/references/binary-manager/README.md\` — scope criterion,
persisted/contract surface, bundled-vs-mise state contract, China mirror
behavior, \`CHERRY_GITHUB_TOKEN\` opt-in, adding a new managed binary.
- \`CLAUDE.md\` adds a \`**MUST READ**\` link next to Lifecycle / Window
Manager / Data / Paths.
- The mise-shim-wins-over-\`cherry.bin\` precedence rule is documented
in the README's "State contract" section.

**Code orientation**
- \`src/main/services/BinaryManager.ts\` — the lifecycle service. Wraps
mise via \`runMise()\`; isolated env in \`buildIsolatedEnv()\`; bundled
extraction with atomic tmp+rename; per-tool try/catch so a single
failure can't abort init; \`isManagedBinaryReady()\` verifies the
resolved file is executable (not just that mise thinks it's installed).
- \`packages/shared/data/presets/binary-tools.ts\` —
\`PREDEFINED_BINARY_TOOLS\` registry; \`tool\` field is a mise spec.
-
\`src/renderer/src/pages/settings/McpSettings/EnvironmentDependencies.tsx\`
— three-state UI (\`managed\` / \`bundled\` / \`not-installed\`) backed
by \`Binary_GetState\` + \`Binary_ProbeBundled\`.
- \`scripts/download-binaries.js\` — build-time downloader for mise / uv
/ bun / rg (HTTPS + sha256-verified, archive-aware extraction).

**Migration**
- \`OpenClawService.install()\` is now two lines delegating to
\`BinaryManager\` — \`install-openclaw.js\` is gone.
- \`CodeCliService\` no longer uses \`bun install -g\`; the
\`BUN_INSTALL\` / \`~/.cherrystudio/install/global/\` path is removed.
- \`FileStorage.getRipgrepBinaryPath()\` now resolves via
\`getBinaryPath('rg')\`; the vendored SDK rg is no longer used.
- \`extractRtkBinaries\` + the \`AgentBootstrapService\` call are
deleted. \`rtkRewrite()\` degrades gracefully when rtk is absent;
\`rtkAvailable\` caches with a 60s TTL so install-via-mise takes effect
without restart.

**Multi-round review**
Two adversarial review rounds against this branch (Bug Hunter / Security
/ Architecture / Correctness) ran during development; both rounds'
High-severity findings are addressed in commits \`70afde6af\` and
\`1d864439d\`. R3 known follow-ups (architecture duplications in
\`CodeCliService\`'s switch statements, etc.) are tracked as Medium and
intentionally deferred.

### Checklist

- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: Leaves binary acquisition meaningfully cleaner than
before (five mechanisms → one)
- [x] Upgrade: v2 data is throwaway; no migrator needed and the absence
is intentional
- [x] Documentation: \`docs/references/binary-manager/README.md\` +
\`CLAUDE.md\` Architecture section
- [x] Self-review: Two multi-perspective review rounds against the
branch; all Highs addressed

### Release note

\`\`\`release-note
NONE
\`\`\`

---------

Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: Vaayne Liu <vaayne@macos.shared>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
2026-06-24 15:15:25 +08:00
fullex
4e03ff0d8c docs(claude-md): link per-process architecture docs from Architecture section
Add a Code Organization subsection that points to the main, renderer, and shared-layer architecture references so contributors learn where code goes before adding it.
2026-06-20 07:16:54 -07:00
fullex
1ad784437b feat(ipc): IpcApi framework for type-safe IPC (#16033) 2026-06-15 12:34:56 +08:00
Phantom
48d1b88d1a docs(branch-strategy): align with #13984 (forward-port, drop v2-line framing) (#15461)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: icarus <eurfelux@gmail.com>
2026-05-31 15:34:31 +08:00
fullex
9c85be6fd7 docs(branch-strategy): correct v2/v1 guidance after v2 merged into main
The former v2 branch has merged into main, making the old "main is frozen,
submit to v2" guidance backwards. Update all contributor-facing entry points
to the current model: main is the active v2 development line; v1 maintenance
fixes target the v1 branch.

- CLAUDE.md: add a v2 "Current state" callout and a branch-targeting
  Operational Rule (the AI-facing context).
- gh-create-pr skill: route v1 maintenance PRs to base v1.
- PR template: replace the stale hidden comment with a visible branch
  callout and add a branch checklist item.
- CONTRIBUTING.md / docs/guides/contributing.md: rewrite the branch strategy
  section to the new model.
- docs/guides/branching-strategy.md: add a current-model note and fix the PR
  target guideline.
2026-05-30 09:32:48 -07:00
Phantom
05111349f3 fix(db-migrations): resolve snapshot chain collision (#15438) and gate against recurrence (#15440)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: icarus <eurfelux@gmail.com>
2026-05-30 15:30:49 +08:00
fullex
53a3577389 refactor(renderer): flatten src/renderer/src to src/renderer
Move all renderer source from src/renderer/src/* up one level to
src/renderer/*, removing the redundant nested src directory.

- Update path aliases (@renderer, @types, @logger, @data) and TanStack
  Router paths in electron.vite.config.ts; update tsconfig.{json,web,node}
  path mappings and include globs.
- Fix Vite root-relative script paths in the 8 renderer HTML entries.
- Update cross-process relative imports in main/preload (language,
  apiServer models, preload index) to drop the /src segment.
- Switch renderer test imports of the logger mock to the @test-mocks alias.
- Update hardcoded renderer paths in scripts and their fixtures, lint
  configs (eslint/oxlint/biome), CODEOWNERS, docs, and the data-classify tool.
- Convert deep (../../+) relative imports within the renderer to the
  @renderer alias (69 files, 108 imports); keep single-level relatives.
- Fix doc links broken by the move and correct one pre-existing broken
  link in naming-conventions.md.
2026-05-28 21:40:20 -07:00
fullex
c514dcc049 refactor(shared): move packages/shared to src/shared
packages/shared was never a real pnpm workspace package (no package.json); it was referenced only through the @shared TypeScript path alias. Relocate it under src/ via git mv (143 files, detected as pure renames).

Repoint the @shared alias and include globs to src/shared across electron.vite.config.ts, tsconfig.{json,node,web}.json and vitest.config.ts; update scripts/check-custom-exts.ts, scripts/update-languages.ts, the eslint.config.mjs generated-file globs, the data-classify generator output targets, .github/CODEOWNERS path rules, and CLAUDE.md/docs/source-comment references.

The @shared alias name is unchanged, so all 1403 @shared/* import sites resolve without modification. Verified with typecheck:node, typecheck:web and the full test suite (700 files, 9739 tests passing).
2026-05-28 21:02:49 -07:00
fullex
d5eafa0a9a docs(naming-conventions): add spec and link from CLAUDE.md 2026-05-22 01:04:42 -07:00
fullex
fd81de8a32 feat(db-service): add withWriteTx for serialized writes (libsql #288)
libsql client-ts upstream issue #288 makes PRAGMA busy_timeout ineffective
for async transactions, so concurrent db.transaction() calls reliably surface
SQLITE_BUSY. Introduce DbService.withWriteTx as a serialized write helper:

- Process-wide FIFO mutex (async-mutex) serializes write transactions.
- libsql client's default BEGIN IMMEDIATE protects against read-then-write
  tx upgrade failures (no override needed at the drizzle layer).
- Single 50ms BUSY retry guards against transient external locks.

Reads do NOT need this — WAL gives readers snapshot isolation that is never
blocked by writers.

Includes unit tests (FIFO ordering, finally release on throw, single BUSY
retry, persistent BUSY rethrow, non-BUSY passthrough) plus a real-libsql
integration test. Updates the DbService test mock with a passthrough
withWriteTx so dependent services do not throw "is not a function" in
tests. Documents the API in database-patterns.md and points
CLAUDE.md / data-api-overview.md at the new pattern.
2026-05-21 04:54:43 -07:00
fullex
16f2e1c7a8 feat(lifecycle): add BaseService.registerInterval helper
Wraps setInterval with auto-unref, exception isolation, and cleanup
via the existing registerDisposable channel. Returns a Disposable.

Replaces 5 ad-hoc setInterval patterns (CacheService, PreferenceService,
WindowManager, ProxyManager, FileProcessingTaskService) — unifies
three pre-existing cleanup styles and fixes a missing unref() in
ProxyManager.

WindowManager: warmupGcTimer cleanup moves from onDestroy to onStop
(via registerDisposable) — acceptable for this singleton.

Skipped (YAGNI): registerTimeout, immediate/unref options,
activation-scoped variant. QuickAssistantService keeps bare
setInterval — its lifecycle is finer than activation.
2026-05-08 20:25:04 -07:00
fullex
7a62c24dd4 docs(claude-md): regroup guiding principles and trim filler
- Add Mindset subsection covering Think Before Coding, Simplicity First,
  Surgical Changes, and Goal-Driven Execution so behavior guardrails sit
  alongside project-specific rules under a single MUST FOLLOW section.
- Reorganize existing rules into an Operational Rules subsection.
- Drop entries absorbed by the new mindset principles
  ("Start simple", "Match the house style").
- Trim GitHub section: drop narrative bridges and generic gh CLI listings
  that any LLM agent already knows; keep only project-specific policy.
2026-05-05 02:19:32 -07:00
fullex
750b867a60 chore(v2-refactor): set 2.0.0-dev and document v1 coexistence mindset
Reset version to 2.0.0-dev to reflect this branch is internal-only and
not user-facing, and add a Coexistence Mindset section to CLAUDE.md so
AI agents stop writing defensive code for two throwaway things:

- v1 code and data (Redux, Dexie, ElectronStore) — all v1 code is
  deleted before v2 ships; v1 data reaches v2 only via migrators in
  src/main/data/migration/v2/.
- Drizzle schemas and migrations/sqlite-drizzle/*.sql — rewritten
  freely until release, then wiped and regenerated as a single clean
  initial migration. Only the final regenerated migration is the
  correctness target.

Also extend the Data Layer "Removing" list with ElectronStore so the
v1 boundary referenced by the new section is canonical.
2026-05-01 05:39:39 -07:00
fullex
e97480c4c9 docs(breaking-changes): introduce v2 user-impact change log
Add an internal record for v2 changes that affect how users use the
app. PR authors drop a fragment .md per change; the release manager
aggregates and translates them into the Chinese user-facing release
note at v2.0.0, then discards the fragments with v2-refactor-temp/.

Also translate v2-refactor-temp/README.md to English and link the new
directory from it.
2026-04-29 19:10:45 -07:00
fullex
f60ef2bfd6 docs(cache): rewrite to match current API and add design invariants
Align cache-overview.md and cache-usage.md with the template-key and
subscribe* APIs (sharedCasual was dropped in 3fbc52e05). Extract the
"adding keys" content into a new cache-schema-guide.md aligned with
preference and boot-config schema guides. Lift non-obvious invariants
(isEqual short-circuit, TTL-with-hooks warning, Persist has no delete,
Main-wins convergence, template placeholder rules) into a first-class
Design Invariants section in the overview.

Fix two code-contradicted claims:
- useCache does not accept a TTL options argument (hook signature is
  (key, initValue?)).
- Persist is renderer-authoritative; Main only relays IPC and does
  not store (CacheService.ts:477-479 is "Reserved, not implemented").

Update peripheral references in the same pass so cross-references stay
coherent: v2-renderer skill, CLAUDE.md, architecture-overview.md,
api-design-guidelines.md (Cache vs DataApi matcher contrast), and the
package READMEs.

Net change: +249 / -579.
2026-04-22 22:56:34 -07:00
fullex
f9f8c0d65f docs(claude-md): add linear-history rule for git sync workflow
Add a guiding principle that forbids plain `git pull` on shared
branches and requires fetch-then-rebase before push, to prevent merge
commits from slipping into shared history.
2026-04-21 03:30:44 -07:00
fullex
9f181b6d7b docs(claude-md): reorganize by task clusters and trim redundancy
- Restructure into 7 task-driven H2 sections: Guiding Principles,
  Development, GitHub, Conventions, Architecture, v2 Refactoring,
  Security.
- Add Window Manager subsection under Architecture; link each Data
  system to its overview doc and add a Scope list covering
  process-availability and sync behavior.
- Add principles: Start simple, Fix upstream, Library-first,
  Read local READMEs first; document commit scope rule with
  concrete examples.
- Trim duplicate/outdated content: Tech Stack table, Build System,
  Testing Strategy, Key Patterns, Electron Structure, Code Style,
  Branch Strategy, and duplicate rules across sections.
- Fix `@packages/ui` -> `@cherrystudio/ui` (wrong package name).
- Drop redundant H1/subtitle preamble.
2026-04-18 09:26:50 -07:00
fullex
d5aa32e281 docs(lifecycle): clarify that cross-phase @DependsOn is redundant
Phase ordering already guarantees BeforeReady services (PreferenceService,
DbService, CacheService, DataApiService) are ready before WhenReady starts,
so declaring @DependsOn across phases adds noise and misleads readers about
same-phase coupling. The rule existed in lifecycle-overview but was buried
in a bullet; reinforce it in the docs AI assistants scan first.

- CLAUDE.md: add a bullet under the Lifecycle section stating @DependsOn
  is for same-phase deps only
- lifecycle/README.md: new "Cross-Phase Dependencies Are Automatic"
  callout section and a matching Anti-patterns row
- lifecycle/lifecycle-overview.md: promote the line-87 note to a blockquote
  callout and annotate the Dependency Rules table
- lifecycle/lifecycle-decision-guide.md: add Common Mistake #5 with
  bad/good code examples
2026-04-17 19:27:20 -07:00
fullex
6aeb14d6d1 docs(testing): add database-testing guide and update CLAUDE.md
New guide at docs/references/testing/database-testing.md describing:
  - When to use setupTestDatabase() (and when not to).
  - Options, lifecycle behaviour, and PRAGMA handling.
  - Migration recipe (before/after diffs) for converting legacy tests.
  - Anti-patterns: vi.mock('@application') override, hand-written
    CREATE TABLE SQL, describe.concurrent within harness scope,
    nested setupTestDatabase() calls, re-adding the
    vi.mock('node:fs', importOriginal) escape hatch.
  - Gotchas: LibSQL transaction connection recycle + setPragma replay,
    pathToFileURL for Windows, FTS5 with NULL content, truncate-vs-drop.

Linked from CLAUDE.md's Testing Guidelines section so future
contributors find the convention.
2026-04-15 09:34:28 -07:00
fullex
9b451b87a9 refactor(paths): add @application path alias for main/core/application
Align with the existing @logger alias convention by introducing
@application as a short alias for src/main/core/application. This
reduces import verbosity across ~130 main-process files while keeping
4 intentional sub-path imports (@main/core/application/Application)
unchanged to preserve the vi.mock bypass mechanism in tests.

Configured in tsconfig.node.json and electron.vite.config.ts; Vitest
inherits the alias automatically.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-04-11 22:06:00 -07:00
SuYao
34735feef5 docs: add design system specifications (DESIGN.md) (#14163)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 17:46:34 +08:00
亢奋猫
a83f98fd24 docs: consolidate bilingual docs, add link checker and architecture overview (#14138)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
2026-04-09 16:01:40 +08:00
fullex
57462524a9 feat(paths): introduce path registry and application.getPath
Centralize all main-process filesystem path access behind a single
entry point: application.getPath('namespace.key', filename?).

- Add src/main/core/paths/ module:
  * constants.ts — zero-dep CHERRY_HOME / BOOT_CONFIG_PATH for early
    boot use (importable before Electron `app` is ready).
  * pathRegistry.ts — frozen PATHS object with 49 keys across five
    namespaces (cherry / sys / app / feature / external).
  * index.ts — re-exports PATHS and PathKey only.
  * README.md — naming conventions, namespace taxonomy, dot semantics,
    how to add a new key, and testing patterns.
- Add Application.getPath(key, filename?) as the sole entry point.
  PathKey is a string-literal union derived from PATHS, so invalid keys
  fail at compile time. Suspicious filenames (absolute, '..', or path
  separator) are logged via loggerService and joined anyway — graceful
  degradation, not a hard error.
- Refactor BootConfigService to consume BOOT_CONFIG_PATH from
  paths/constants.ts instead of building the path from os.homedir() +
  HOME_CHERRY_DIR.
- Extend ESLint data-schema-key/valid-key rule to enforce the
  namespace.sub.key naming convention on pathRegistry.ts.
- Add Application.getPath unit tests covering filename validation
  graceful-degradation behavior.
- Document the rule in CLAUDE.md (new Guiding Principle + concise
  Path Management section); detailed conventions live in
  src/main/core/paths/README.md.

This PR is the scaffolding only. Migrating existing call sites
(getFilesDir(), os.homedir() + HOME_CHERRY_DIR, scattered app.getPath()
calls, etc.) is left to follow-up PRs.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-04-07 19:08:04 -07:00
fullex
a74f3f468f docs: add DataApi boundary rules to prevent misuse for non-data operations
Signed-off-by: fullex <0xfullex@gmail.com>
2026-04-05 01:27:37 -07:00
suyao
72a536295b Merge remote-tracking branch 'origin/main' into DeJeune/merge-settings-routes 2026-04-03 00:19:37 +08:00
亢奋猫
e9e7aef6f6 docs: update branch strategy for main code freeze (#13985) 2026-04-02 23:46:38 +08: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
c43e744e4a docs(CLAUDE.md): simplify lifecycle section, redirect details to docs
Replace ~70 lines of inline code examples and detailed explanations
with a concise bullet-point summary of core rules. All details are
already covered by the lifecycle documentation under docs/en/references/lifecycle/.

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-28 21:18:11 -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
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
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
c11967166a docs: update CLAUDE.md and data-classify toolchain for BootConfig
- CLAUDE.md: add Data Classification Toolchain section with generate command
- README.md: add bootConfig category, generate-boot-config.js script,
  update directory structure, dependency graph, script tables, and
  decision flowchart
- generate-all.js: include boot config generator as step 2/3
- package.json: add generate:boot-config script

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-25 09:50:13 -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
8adc713d91 docs: add named export singleton convention for non-lifecycle services
Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-24 23:39:15 -07:00
fullex
1371cbe16f test: unify application mock with mockApplicationFactory
Replace ad-hoc vi.mock('@main/core/application') calls across test files
with a centralized mockApplicationFactory(overrides?) utility that provides
all registered services by default and supports per-service overrides.

- Add tests/__mocks__/main/DbService.ts (standalone DbService mock)
- Add tests/__mocks__/main/application.ts (unified factory)
- Simplify tests/main.setup.ts global mock
- Migrate 4 test files to use mockApplicationFactory
- Document unified mock system in CLAUDE.md and README.md

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-24 03:36:08 -07:00
fullex
8180900a73 docs(lifecycle): align with application layer and add migration guide
- Update lifecycle README to reference application.get() instead of
  raw container/manager APIs
- Fix @Injectable() examples to include required name parameter
- Use actual service names (DbService) instead of fictional ones
- Add "Migrating from Old Service Patterns" section with step-by-step
  guide covering manual singleton, raw new, and free function patterns
- Cross-link lifecycle README from application README and CLAUDE.md

Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-24 03:27:53 -07:00
fullex
9b2dd784a4 docs(CLAUDE): add main process service lifecycle guidelines
Signed-off-by: fullex <0xfullex@gmail.com>
2026-03-24 00:11:48 -07:00
Phantom
f0f04eeda0 docs: update agents.db path in CLAUDE.md after #13392 (#13471)
### What this PR does

Before this PR:

CLAUDE.md described agents.db path as `~/.cherrystudio/data/agents.db`
(dev) / `userData/agents.db` (prod), which is outdated after #13392.

After this PR:

Updated to reflect the unified path `{userData}/Data/agents.db` with
macOS examples for both dev and prod.

Fixes #

N/A

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

The following tradeoffs were made:

None. Straightforward documentation update.

The following alternatives were considered:

N/A

Links to places where the discussion took place:

https://github.com/CherryHQ/cherry-studio/pull/13392

### Breaking changes

None.

### Special notes for your reviewer

N/A

### 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
- [ ] 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 23:02:35 +08:00
fullex
2104e234af Merge 'main' into v2 2026-03-12 02:20:13 -07:00
MontyDon7
1465da141f docs: Expand CLAUDE.md with comprehensive architecture and development guide (#13241)
### What this PR does

Before this PR:
- CLAUDE.md contained minimal guidance on development commands and
project structure
- Lacked detailed information about architecture, services, database
layers, and conventions
- Missing documentation on contribution restrictions and tech stack
details

After this PR:
- Comprehensive architecture documentation covering Electron structure,
main/renderer processes, and packages
- Detailed service registry for main process (WindowService, MCPService,
KnowledgeService, etc.)
- Complete Redux store slice documentation with state shape reference
- Database layer documentation (IndexedDB + SQLite/Drizzle)
- IPC communication patterns and tracing setup
- AI Core package architecture and provider abstraction details
- Multi-window architecture overview
- Tech stack matrix with all key dependencies
- Code style conventions, file naming, i18n guidelines
- Testing guidelines and v2 refactoring blockers
- Security best practices

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

This documentation update serves as a comprehensive reference for AI
coding assistants and contributors working on the Cherry Studio
codebase. The expanded guide:

1. **Reduces onboarding friction** - New contributors and AI assistants
can understand the full architecture without diving into source code
2. **Clarifies contribution restrictions** - Explicitly documents the
v2.0.0 refactoring blockers to prevent rejected PRs
3. **Standardizes conventions** - Provides clear guidelines on code
style, naming, i18n, and testing expectations
4. **Documents critical systems** - Details the complex multi-process
architecture, IPC patterns, and service layer
5. **Improves maintainability** - Future changes to architecture can be
documented here for consistency

The documentation is organized hierarchically from high-level overview
to specific implementation details, making it easy to navigate.

### Breaking changes

None - this is documentation only.

### Special notes for your reviewer

- Added new section "Current Contribution Restrictions" to highlight
v2.0.0 blockers
- Expanded development commands with detailed descriptions and all
available scripts
- Added comprehensive "Project Architecture" section with ASCII diagrams
and tables
- Included path aliases reference table for quick lookup
- Added "Tech Stack" matrix for technology overview
- Included "Conventions" section covering TypeScript, code style, file
naming, i18n, and patched packages
- Added "Testing Guidelines" and "Important Notes" sections for v2
refactoring and security

### Checklist

- [x] PR: The PR description is expressive and documents the changes
clearly
- [x] Documentation: Comprehensive guide added for future contributors
and AI assistants
- [x] Self-review: Content reviewed for accuracy and completeness

### Release note

```release-note
NONE
```

https://claude.ai/code/session_01DCYQm925rdYraLMBiQ9fZx

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-05 22:34:46 +08:00