Commit Graph

355 Commits

Author SHA1 Message Date
槑囿脑袋
ab61ca0d12 refactor(knowledge): derive retrieval mode and keep rerank threshold (#16699)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-07-06 16:58:54 +08:00
亢奋猫
3a65255ce3 refactor(settings): remove standalone settings window (#16489)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-07-06 16:47:10 +08:00
fullex
88f141790c refactor(core): dissolve paths & application barrels, seal lifecycle (naming §6.4)
Three core barrels, three diagnoses under naming-conventions §6.4:

- paths: remove the barrel — it only re-exported types while the real entry
  is application.getPath(). constants.ts and pathRegistry.ts are independent
  building blocks deep-imported by their specific consumers (rules 2/3/4).
- lifecycle: keep the barrel (a cohesive framework consumed as a set by 80+
  services), route the last deep-import leaks through it, and prune 13
  framework-internal machinery exports (resolver, decorator getters, capability
  guards) that no consumer touches — tightening the door to its public surface.
- application: remove the barrel and repoint @application directly at
  Application.ts. The barrel bundled the hot `application` locator (~218
  consumers) with the bootstrap-only serviceRegistry, so every @application
  import dragged in the whole service graph — the root of the JobManager-to-
  serviceRegistry eval-time cycle. The locator now loads on its own.

Relocate SHUTDOWN_TIMEOUT_MS from an Application static into
lifecycle/constants.ts: a shared shutdown-grace policy honored by both
Application and JobManager, so JobManager no longer imports the Application
class at all.

Docs (paths/README, application/README, application-overview) and per-file
test mocks (vi.mock('@main/core/application') to '@application';
Application.getPath vi.unmock) are updated in lockstep.
2026-07-05 22:06:52 -07:00
fullex
28af4b6d85 docs(file): fix broken source links after barrel refactor
The FileHandle type union moved to src/shared/data/types/file.ts and the
watcher/ directory was flattened to watcher.ts during the naming §6.4
barrel refactor, leaving two dead links caught by docs:check-links.
2026-07-05 20:39:51 -07:00
fullex
2d677c8204 refactor(api-gateway): dissolve adapters sub-barrels, curate root barrel (naming §6.4)
The adapters/ root barrel deep-imported leaves inside four sub-barrels
(stream/converters/formatters/factory), tripping both no-nesting and closed.
The sub-barrels were themselves dead — incomplete and imported by nobody: the
root barrel, the factories, and the tests all bypassed them for leaves.

- Delete the four internal sub-barrels; the subdirs become plain folders, so
  the factory/formatter/root leaf imports are now legal (no barrel to bypass).
- Curate adapters/index.ts to the real public surface — the two factories plus
  the interface/format types actually consumed by proxyStream and errors. The
  concrete stream adapters, converters, and formatters have zero external
  consumers and stay internal.
- Move openrouter.ts up to apiGateway/, next to its sole consumer
  reasoningCache.ts — it is a reasoning-cache type contract, not adapter
  machinery — clearing the last closed violation.
- Document openrouter.ts's new home in the api-gateway README tree.

apiGateway barrel warnings: ~38 -> 0.
2026-07-05 20:17:47 -07:00
fullex
d9475b2562 refactor(stream-manager): make root barrel the public surface, drop internal sub-barrels
Rewrite streamManager/index.ts to export the full consumed surface (all
listeners, startAgentSessionRun, PersistenceBackend contract, TranslationBackend,
stream types); route all 15 external deep imports through it. Remove the
internal-only context/ and lifecycle/ sub-barrels so internal siblings import
directly. Expose AiStreamRequest/CallOverrides on the ai/types barrel and route
ChannelAdapter through the channels barrel.

Two deep imports remain, blocked by nested sub-barrels in sibling dirs
(runtime/claudeCode, channels/security) — deferred to those dirs' cleanup.
2026-07-05 10:59:09 -07:00
fullex
840f812690 refactor(barrels): move impl out of index barrels per naming §6.4
Clear all `barrel/index-no-impl` violations in src/main (14 barrels) by
turning each index.ts into a pure re-export or dissolving it:

- Aggregation buckets → drop the barrel, move the assembled object/array/fn
  to a named file, deep-import at the sole consumer: data/api/handlers →
  apiHandlers.ts, ipc/handlers → ipcHandlers.ts, migrators → migratorRegistry.ts,
  params/features → internalFeatures.ts, browser/tools → registry.ts,
  builtin → registerBuiltinTools.ts, db/seeding → seederRegistry.ts.
- Single-impl dirs flattened: provider/extensions.ts, provider/cherryai.ts.
- Barrel kept, impl extracted to a named file: i18n/resolver.ts,
  ai/types/providerConfig.ts.
- Route subdir flattened to match its flat siblings: routes/knowledge.ts +
  routes/knowledgeSchemas.ts.
- runtime: replace the import-time `claudeCode/register` side effect with an
  explicit registerRuntimeDrivers() invoked from AgentSessionRuntimeService.onInit,
  so runtime/index.ts stays a pure re-export.
- loop: dissolve the non-enforced barrel into loop/types.ts + loop/hookRunner.ts.

Also route DataApiService's apiHandlers import through the data/api barrel,
and expose ClaudeCodeRuntimeDriver via the claudeCode barrel, clearing the two
deep-import warnings this batch touched. Docs and comments updated to the new paths.
2026-07-05 09:48:02 -07:00
fullex
1bac7ac18c refactor(shared-ipc): flatten schemas/errors impl-indexes to named modules per naming §6.4
schemas/index.ts and errors/index.ts carried real local declarations — the
`ipcRequestSchemas` runtime registry plus composed types, and the `IpcError`
class plus `IpcErrorCode` — yet sat under the index.ts name, tripping
barrel/index-no-impl (§6.4 rule 1: an index must be a pure re-export barrel).
Unlike the api barrel there is no outer barrel to remove — ipc/ is already an
open namespace — so this is a straight rename to named modules.

- schemas/index.ts -> schemas/ipcSchemas.ts; errors/index.ts -> errors/IpcError.ts.
- Repoint all consumers (18 deep imports + one intra-package import), including
  directory-form relative imports (./schemas, ../errors) that resolved via Node's
  index lookup.
- Sync the ipc docs: rename path references and reword the "no errors/index.ts
  aggregation" prose, since errors/ now has no index at all.
2026-07-04 22:23:29 -07:00
fullex
35256975e3 refactor(shared-data-api): drop the api barrel and flatten module names per naming §6.4
The api/index.ts barrel re-exported only infra types yet required domain DTOs
to deep-import schemas/<domain>, colliding with naming §6.4 rule 2
(enforced-or-no-barrel) and accounting for the bulk of barrel/closed lint
violations. Because schema files carry zod runtime values, any aggregating
barrel drags all 24 domains in on a single import — exactly what the barrel
reform removes.

- Remove api/index.ts; api/ is now an open namespace.
- Flatten infra file names: apiTypes/apiErrors/apiPaths -> types/errors/paths;
  schemas/index.ts -> schemas/apiSchemas.ts.
- Rewrite all consumers: 71 deep-import path renames + 106 barrel imports split
  to their owning module (types/paths/errors), including two dynamic imports and
  the tests/__mocks__ fixtures.
- Sync data docs and codify the schemas/ `_xxx.ts` = cross-resource construct
  convention in naming-conventions §3.2.
2026-07-04 21:51:21 -07:00
fullex
87b2b64ba5 refactor(process-entry): rename main/preload entries to named files per naming §6.4
src/main/index.ts → main.ts and src/preload/index.ts → preload.ts, so the process entries stop occupying the barrel-reserved index filename (§6.4) without needing an exemption list. The rename is wired through electron.vite (main build.lib.entry — rollupOptions.input would bypass electron-vite's output-format detection — and the preload input key), package.json main (out/main/main.js), WindowManager's default preload filename, MainWindowService's webview preload path, and DbService's slow-query stack filter, which matches the bundled artifact name. preload.d.ts becomes globals.d.ts: sharing preload.ts's basename makes TypeScript drop the .d.ts as that file's presumed output declaration, and tsgo only applies its global Window augmentation when the declaration sorts before its importer, so the file keeps a distinct, alphabetically-early name. Entry-path mentions in code comments and reference docs follow.
2026-07-04 20:18:14 -07:00
fullex
c5342b29f4 refactor(routes): adopt flat dot-form index routes, closing naming §6.4's last exception
Rename the four directory-form index routes (settings/, settings/mcp/, app/mini-app/, app/paintings/) to TanStack's default-supported flat dot form (settings.index.tsx, …) so no file under routes/ is named index.* and the §6.4 iron rule — the index filename is reserved for barrels — holds across src with no exceptions. URLs and route ids are unchanged; routeTree.gen.ts regenerates with only the four import paths moved. Naming §6.4 drops the routes/ carve-out, §6.6 documents the dot-form token, and the routes READMEs replace a stale bare-index example.
2026-07-04 20:17:54 -07:00
fullex
7664b5cc18 docs(conventions): make naming §6.4 the cross-process authority for barrel/module boundaries
Promote §6.4 from three loose rules to the full barrel contract (re-export-only, enforced-sole-entry-or-no-barrel, no nesting, one-cohesive-unit) and point shared §3.1 / main §2.1 / renderer §5 at it, fixing main's stale pointer to shared. Reserve the index filename for barrels — always index.ts, never .tsx outside routes/ — with implementations in named files; add the renderer component-directory form and align §4.2's component test. Note what the contract does not remove: dev builds load a barrel's full graph (rule 4 is the bound), and dynamic import() crosses a boundary through the barrel, with the React.lazy form in renderer §5. Docs only; lint enforcement and call-site fixes follow.
2026-07-04 18:55:04 -07:00
fullex
458fb42054 feat(job): typed settled events, list filters, and transactional enqueue
Implements the accepted upstream items from issue 16738:

- JobSettledEvent<TPayload> now carries typed input, parentId, and the
  final metadata (post-patchMetadata); JobContext gains parentId. Both
  are projections of the persisted snapshot - no extra DB reads.
- JobListFilter.type widened to string | string[] (inArray), parentId
  filter added (rides job_parent_id_idx); ACTIVE_JOB_STATUSES exported
  from shared schemas replacing JobService's private copy; list/count
  WHERE composition extracted into a shared listConditions helper.
- JobManager.enqueueTx(tx, ...) rides the caller's withWriteTx
  transaction so business writes and the job INSERT commit atomically;
  post-commit side effects are deferred one microtask and re-read the
  row (a rollback discards the resolver). JobService gains createTx /
  findActiveByIdempotencyKeyTx; enqueue is refactored onto the shared
  prepareEnqueue with unchanged external behavior.

Refs #16738
2026-07-04 05:14:14 -07:00
fullex
f6e0cf9525 docs(architecture): codify ownership-first routing and services topic dirs
Replace the fuzzy business-orchestration routing criterion with an outward-side-effects test: stateless shared modules default to utils/ and promote to services/ only for a stated reason (side effects, or a forced services import).
Rekey the Service/Manager suffix from stateful classes to stateful singleton capabilities, mechanism-independent: module-scope mutable state must take the class + singleton form, multi-instance helper classes take no suffix, and what counts as state is defined.
Codify renderer services/<topic>/ topic directories (single barrel entry, private topic-specific satellites exempt from shape routing, no UI) mirroring the existing main-process rule, and add the middle growth step to Naming 4.10.
Align residual wording across the three docs: same-kind peering edges in the renderer dependency table, the section-6 corollary vs its own worked example, quick-reference suffix note, utils charter and examples.
2026-07-04 03:57:57 -07:00
fullex
9017fc661f docs(architecture): trim renderer §8 to outstanding gaps
Re-sync the "Target vs Current State" section with the code after the
dependency-cleanup landed. §8 now tracks only what is still unfinished:

- Drop the "Already aligned" list and the six resolved deviations
  (config/, queue/, components/app/Navbar, the utils/ root barrel, and
  the "Boundary enforcement: none" row) -- once resolved they no longer
  violate the target, so they need not appear.
- Correct the components/app/Sidebar row: it is not dead code. It is
  rendered by components/layout/AppShell.tsx (main-window shell), so it
  folds into the App-shell row and moves to windows/main with that shell.
- Sync the enforcement status in §5 and §8: the import/no-restricted-paths
  gate is live -- shared-layer edges at error, pages -> pages at warn -- and
  the remaining pages -> pages coupling is ~13, not ~35.
- Keep only the still-open half of the barrel item: utils/message/ still
  needs a curated index.ts.

Add a maintenance note so resolved deviations are dropped, not recorded
as done -- the "already aligned" list is what rots.
2026-07-04 02:44:16 -07:00
fullex
289f05847a docs(architecture): route utils/services by role, not purity
Record the placement rule settled during the renderer cleanup: utils/ is
stateless and domain-agnostic and MAY import downward infra
(data/ipc/workers), while services/ owns state/lifecycle or performs
business/domain orchestration. A helper touching infra is still a helper;
the decisive test is role, not purity.

- renderer-architecture.md: co-equal utils/data/ipc/workers foundation
  (§2); positive service identity and the revised utils row (§3).
- naming-conventions.md §5.2: add the stateless-orchestration -> services
  routing row; note utils may call downward infra.
- main-process-architecture.md: Pure -> Stateless; route by role.
2026-07-04 00:54:30 -07:00
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
LiuVaayne
9eb784fc2f feat(provider): add login-based providers — Claude Code, OpenAI Codex & Grok CLI (#16283)
Co-authored-by: 亢奋猫 <kangfenmao@qq.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-07-03 21:03:21 +08:00
fullex
6f10acbf7d refactor(migration): remove backup step from v2 migration flow
The pre-migration backup was a redundant safety net: the migration engine
never deletes v1 data (it stays on disk, so a failed run is retryable), and
StartMigration never required or verified a backup. Removing it shortens the
wizard to introduction -> migration -> completion/error (progress rail 3 steps).

- shared: drop the backup_required/progress/confirmed stages, the
  backupInfo/isCompressing fields, MigrationBackupInfo, and the 5 backup IPC
  channels; delete the dead DataMigrate_* IpcChannel enum block (superseded by
  MigrationIpcChannels, zero consumers)
- main: remove the backup handlers, LegacyBackupManager wiring, progress
  bridge, and single-flight guards from MigrationIpcHandler; simplify
  updateProgress; Retry now returns to the introduction stage
- main: flip to the protected `migration` stage before running the engine so
  the destructive verifyAndClearNewTables() runs under the close-confirm /
  write-deferral guard instead of the unprotected introduction stage
- renderer: the introduction Start button now runs the migration directly
  (with a loading state; Skip is disabled while exporting); drop the backup
  stages, choice UI, and completed-screen backup path; remove the now-dead
  ProgressBar indeterminate branch and its keyframe
- i18n, docs, and tests updated accordingly

LegacyBackupManager and IpcChannel.BackupProgress are retained -- still used by
the in-app backup/restore feature.
2026-07-03 02:02:31 -07:00
fullex
7d07a7c1e6 fix(data-api): stabilize function identities returned by data hooks
useMutation's trigger was rebuilt on every render — the only non-memoized
function return in useDataApi.ts. Consumers place trigger in dependency
arrays, so the identity churn cascades downstream and can drive infinite
render loops (Maximum update depth exceeded).

Codify stable function identity as an official contract of the data-hook
layer, consistent with SWR's own mutate/trigger:

- Wrap useMutation's trigger in useCallback; options are still read via
  optionsRef at call time, so option freshness is unchanged
- Wrap useInvalidateCache's invalidate in useCallback
- Wrap usePaginatedQuery's nextPage/prevPage/reset in useCallback, keyed
  on their gating booleans so page clamping stays fresh
- Return a frozen shared EMPTY_ITEMS constant for usePaginatedQuery's
  empty state and tighten the result type to readonly T[]
- Document the contract in data-api-in-renderer.md and pin it with
  identity, option-freshness, and clamp regression tests

Refs #16696
2026-07-03 00:48:38 -07:00
LiuVaayne
b497a49826 refactor(env-utils): consolidate shell/binary env handling and clean up BinaryManager (#16594) 2026-07-03 13:50:20 +08:00
槑囿脑袋
2fbc7bda1c feat(knowledge): optional embedding model with BM25-only fallback (#16553)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-07-02 20:19:21 +08:00
fullex
9b9570116a refactor(db): replace libsql with better-sqlite3 + sqlite-vec (#16626) 2026-07-02 13:21:13 +08:00
fullex
15fb07a3c0 chore(agents-migration): remove dead v1 agents-db drizzle migrations
The resources/database/drizzle SQL files and meta snapshots are v1-era CherryClaw agents-db migrations with no runtime consumer — the active v2 migrations live in migrations/sqlite-drizzle and are loaded from app.database.migrations. Delete the directory and clean up the now-dangling references: three source comments in AgentsDbMappings.ts that cited the deleted SQL files as the v1 column-type source (the epoch-ms notes are kept inline), and a stale doc row in cherryclaw/scheduler.md pointing to a migration file that no longer exists.
2026-07-01 07:24:34 -07:00
Phantom
4ef2889fd3 refactor(file-ref): split persistent ref ownership (#16532)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: eurfelux <eurfelux@gmail.com>
2026-06-30 18:44:44 +08:00
fullex
a77f6f5c9a docs(cache): require functional updaters to be side-effect-free
The setter updater contract previously said "must be pure" only in the sense of "don't mutate prev / return a new value" (the isEqual short-circuit footgun); it did not cover side effects inside the updater.

Document that updaters must also be side-effect-free: don't smuggle a derived value out (e.g. into an enclosing-scope variable) to drive post-write work, and don't rely on how often or when the updater runs. To react to what changed, derive it from the value transition in a useEffect that watches the value.

Deliberately does not promise single synchronous invocation, to keep the setter free to batch/retry/defer later. Updates the CacheSetStateAction type doc, the useCache @remarks (canonical reference for all three hooks), and cache-usage.md.
2026-06-29 07:57:25 -07:00
fullex
b424475573 feat(cache): add functional updater support to renderer cache hooks
useCache, useSharedCache and usePersistCache setters now accept a React-style functional updater `(prev) => next` in addition to a concrete value. The updater resolves `prev` from the latest stored value at write time rather than the render-time snapshot, making read-modify-write correct across an `await` — the root cause of the keep-alive overwrite race behind #16460.

`prev` is typed shallow-readonly (`ReadonlyValue<T>`), so mutating it in place and returning the same reference — which the CacheService `isEqual` short-circuit would otherwise swallow silently — is a compile error. Concrete-value calls are unchanged, so existing consumers keep compiling.

The renderer useCache mock mirrors the functional branch with the same default fallback; docs and hook tests updated. Consumer call-site adoption lands separately.
2026-06-29 01:34:05 -07:00
SuYao
611944599f refactor(deps): replace lodash with es-toolkit/compat and drop it (#16528)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-29 12:28:57 +08:00
fullex
e161112a1a refactor(ai-transport): relocate renderer transport runtime into services/aiTransport
Move the renderer-side AI-streaming runtime (IpcChatTransport,
TopicStreamSubscription, streamDispatchCoordinator) out of the top-level
src/renderer/transport/ directory into the shared services/aiTransport/
bucket. By shape these are stateful runtime singletons/classes, and the
runtime is cross-surface (consumed by chat, quick-assistant, selection),
so per the renderer architecture it routes into services/, not its own
top-level directory.

- Add a curated index.ts barrel exposing only the externally consumed
  symbols (ipcChatTransport, TopicStreamSubscription, ExecutionTerminal);
  the class, dispatch coordinator and helpers stay private.
- Update the 6 consumer sites (5 imports + 1 vi.mock) to the barrel.
- Sync architecture and AI docs to the new path; drop the now-resolved
  transport/ deviation from the renderer-architecture pending table.
2026-06-27 09:27:21 -07:00
fullex
7cbf30222d refactor(shared-error): route error cluster to real homes; drop dead @shared AI-SDK guards
- Slim @shared/types/error.ts to the cross-process SerializedError shape
- Relocate serializeError (+ toSerializable) to src/main/ai/utils/serializeError.ts;
  re-point the 4 main/ai consumers
- Delete the @shared-side dead AI-SDK subtype family + 23 isSerialized* guards
  (utils/error.ts) and the unused ProviderSpecificError class
  (renderer keeps its own live parallel copy)
- Move the serializeError test to main/ai/utils; assert discriminant fields directly
  instead of via the deleted guards
- Doc: mark the section 6 error/serializable row resolved
2026-06-27 06:16:26 -07:00
fullex
bf5910f424 refactor(shared): clean up @shared residue, single-process residents, barrels, naming
- Drop dead @deprecated LanFileChunk{,Ack}Message types; de-Redux a stale comment
- Relocate single-process modules out of @shared (Invariant 1.1):
  - types/plugin.ts -> main/utils (markdownParser-only)
  - utils/ocr.ts + types/ocr.ts -> renderer (renderer-only; types now standalone)
  - utils/searchSnippet.ts, utils/pdf.ts -> main/utils (main-only)
  - utils/externalApp.ts EXTERNAL_APPS -> inlined into ExternalAppsService
- Convert types/file, utils/file, utils/command, utils/api barrels from
  `export *` to explicit named exports (section 3.1)
- Naming: urlUtil.ts->url.ts; api/utils.ts->api/format.ts (+fold formatApiHost/
  formatOllamaApiHost); hasAPIVersion->hasApiVersion; URLString/FileURLString->
  UrlString/FileUrlString; enum codeCLI->CodeCli, terminalApps->TerminalApp with
  UPPER_SNAKE_CASE members
- Sync docs to the moves/renames; track data/types route-by-shape as an open question
2026-06-27 06:16:26 -07:00
SuYao
c4bae482df feat(read-file): agentic read_file tool for chat attachments (#16257)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-27 18:47:51 +08:00
jd
2d59508232 fix(streaming): preserve steer continuation chunks (#16445)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-27 18:22:30 +08:00
fullex
0aadb7a75f refactor(renderer-config): dissolve config directory into owning domains
Eliminate src/renderer/config entirely, completing the §8 dissolution
started in 1065cd4dfd. The two remaining files held a mix of genuinely
app-global constants, domain-owned constants, and v1 dead code.

- Add utils/platform.ts for the platform predicates (platform/isMac/
  isWin/isLinux/isDev/isProd) and repoint ~60 cross-domain consumers.
- Relocate domain constants to their owners: LONG_TEXT_PASTE_THRESHOLD
  -> composer/composerPaste; knowledge defaults -> knowledge/rag;
  THEME_COLOR_PRESETS + defaultByPassRules -> CommonSettings;
  MAX_COLLAPSED_CODE_HEIGHT -> CodeBlockView/constants;
  API_SERVER_DEFAULTS -> ApiGatewaySettings; SiliconFlow/PPIO client ids
  + TOKENFLUX_HOST -> utils/oauth (kept below the consuming pages layer);
  occupiedDirs -> BasicDataSettings (still @deprecated v1).
- Dissolve env.ts: inline the APP_NAME literal at AboutSettings and
  import the avatar/logo PNGs directly at each consumer; drop the now
  obsolete config/env test mocks (Vite resolves the assets natively).
- Delete v1 dead constants with no consumers (DEFAULT_TEMPERATURE,
  DEFAULT_CONTEXTCOUNT, SYSTEM_PROMPT_THRESHOLD, message-count caps,
  context caps, DEFAULT_STREAM_OPTIONS_INCLUDE_USAGE).
- Update renderer-architecture (§3/target layout/§8) and the preboot
  doc/comment references that pointed at the old occupiedDirs location.
2026-06-27 03:20:11 -07:00
fullex
fae1e5fe1b refactor(hooks-agent): rename agents/ dir to singular agent/
src/renderer/hooks/agents/ is a feature namespace grouping the agent
feature's hooks, not a collection of agents. Per naming conventions
§4.9 it should be singular, matching sibling namespaces hooks/chat/,
hooks/tab/, hooks/translate/.

- git mv src/renderer/hooks/agents -> src/renderer/hooks/agent
- update 62 import paths across 33 files
- clarify §4.9 so the plural `agents/` example is read by role
  (collection bucket vs feature namespace), not by the word
2026-06-27 02:33:59 -07:00
槑囿脑袋
dc6626d064 fix(knowledge): stop the UI freeze when deleting a large folder and reclaim its disk space (#16447)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: SuYao <sy20010504@gmail.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-06-27 16:24:10 +08:00
fullex
32e8ef273c feat(window-manager): add declarative rememberBounds persistence
Migrate window-bounds persistence off the electron-window-state library into
a WindowManager built-in `rememberBounds` capability, backed by the main-process
persist cache (`window.bounds` key — its first real consumer).

- New `windowBoundsTracker` free-function module: validates the stored record
  (including displayBounds), restores onto the display the window was last on
  (clamping into its work area, never resetting to primary), and snapshots at
  teardown via getNormalBounds + isMaximized.
- Singleton-only gate (dev warning for non-singleton types). Runtime toggle
  `wm.setRememberBounds` (orthogonal to the registry flag; OFF drops only that
  type's slot) plus `wm.peekWindowBounds`.
- Persist at three teardown exits: native close (singletons), before
  window.destroy() in destroyWindow (programmatic destroys), and a new onStop
  so shutdown writes land before CacheService flushes its persist map.
- Wire Main + QuickAssistant. Main re-applies maximize consumer-side on its own
  show schedule (tray-on-launch defers to first show); remove electron-window-state
  and its orphaned keepers/constants/comments.

Fullscreen is not persisted and old *-state.json is not migrated (one-time
reset, loseable). Adds tracker/integration/persist tests, extends the main
CacheService mock with persist methods, and documents the capability plus a
breaking-change note.
2026-06-26 22:39:52 -07:00
fullex
eab541d5fc docs(renderer-architecture): clarify feature consumption, promotion, and same-kind rules
State the previously-implicit rules that produced "features is an isolated
island" misreadings, then tighten the result for concision:

- Make explicit that the app layer (windows/routes/pages) is a feature's
  only legal consumer (window/page -> feature are legal downward edges); a
  feature is isolated only horizontally, from sibling features.
- Add the same-kind-peering vs same-slice-isolation distinction
  (component -> component allowed; feature -> feature not) and note that a
  feature-internal piece follows identical type-axis rules as its top-level
  counterpart.
- Add a 4.1 Promotion Rule with an operational trigger and a
  chat -> features/chat worked example; fix the dangling 4.4 references.
- Add the DAG rationale for the two banned edges (shared -> feature,
  feature -> feature).
- Fix small inconsistencies: pages/ may depend on primitives; shared-layer
  order includes workers; disambiguate bare (4.8) -> (Naming Conventions
  4.8); reclassify transport/ as a cross-surface ai runtime (not
  chat-exclusive) bound for the shared services/ bucket.

Also clean up two dead command mocks targeting the non-existent
@renderer/features/command path: fix the stale path in TopicBranchPanel's
test so the mock intercepts the real @renderer/components/command import,
and drop the unused mock in GlobalSearchPanel's test.
2026-06-26 20:50:04 -07:00
fullex
15e569b992 feat(cache): align persist semantics across processes, tune debounce
Make the main-authoritative and renderer persist tiers express presence as
deviation from the schema default rather than backing-store membership, extend
the API symmetrically, and unify the debounced-write cadence.

- hasPersist now reports whether the effective value differs from the schema
  default (main + renderer). loadPersist/loadPersistCache seed every key, so the
  old Map-membership check was always true and carried no information.
- Add deletePersist (reset-to-default) on both tiers; delegates to setPersist so
  it inherits the same-value no-op, subscriber notify, and renderer cross-window
  broadcast.
- Add subscribePersistChange on the main tier for in-main consumers, mirroring
  subscribeChange (main-local, never relayed to renderers). setPersist now
  notifies persist subscribers on actual change.
- Align persist debounce to 350ms (main + renderer) and BootConfig save debounce
  to 350ms for more coalescing of paused/bursty writes; extract the renderer
  magic number into a named constant.
- Normalize CacheService comments to JSDoc on core methods and document the
  default-relative persist semantics; update cache-overview.md.
2026-06-26 19:10:53 -07: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
8753856223 refactor(renderer-context): dissolve context/ bucket by shape
The context/ directory was a by-kind bucket: React providers are
components, not their own layer. Dissolve it per renderer-architecture
section 8 by splitting each provider into its component (-> components/)
and its context object + accessor hooks (-> hooks/), mirroring the
existing command decomposition.

- ThemeProvider -> components/ThemeProvider.tsx + hooks/useTheme.ts
- CodeStyleProvider -> components/CodeStyleProvider.tsx + hooks/useCodeStyle.ts
- Tab behavior layer -> hooks/tab/ (useTabsContext, useCurrentTab,
  useTabSelfMetadata, useTabs, index); TabsProvider/TabIdProvider ->
  components/layout/
- Extract pure emoji-icon logic to utils/tabIcons.ts
- Remove dead TabsContextValue ops (hibernateTab/wakeTab/setTabs) and a
  stale ThemeProvider comment
- Repoint ~90 import sites and test mocks; migrate provider/hook tests
- Update routes README and renderer-architecture section 8
2026-06-26 09:45:17 -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
SuYao
e6f70f556f feat(paintings): rebuild prompt bar on the shared composer (#16326)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Pleasurecruise <3196812536@qq.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-25 19:32:32 +08:00
Phantom
e2f479d912 feat(files): wire file page to real data (#15338)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: icarus <eurfelux@gmail.com>
2026-06-25 18:09:59 +08:00
fullex
d0cf4ab4e5 refactor(types): repoint consumers off the types barrel and remove the @types alias
Dissolve the renderer types/index.ts re-export barrel (Phase 2):
- Repoint 252 consumers to @renderer/types/<topic> (intra-types files use
  relative ./topic); covers @renderer/types, @types, and the equivalent
  './', './index', '@renderer/types/index' specifier forms.
- Delete src/renderer/types/index.ts.
- Remove the @types alias from tsconfig.web.json, electron.vite.config.ts,
  and the eslint main/preload boundary guard.
- Retire the resolved types-barrel and @types deviations from the renderer
  and main architecture docs.
2026-06-25 00:39:49 -07:00
fullex
787e9e8bdf refactor(ipc): split errors module into directory for per-domain error codes
Move src/shared/ipc/errors.ts to src/shared/ipc/errors/index.ts so each migrated domain can host its own error-code map as a sibling errors/<domain>.ts — value-importable by both processes and zod-free. The @shared/ipc/errors barrel path is unchanged, so every importer and test resolves identically (typecheck + IPC tests green).

Document the IpcErrorCode usage convention that previously lived only in code comments: the framework-code single source of truth, the open (string & {}) tail for domain codes, where domain codes belong (errors/, not schemas/, since the renderer may only import type from schemas), and why they are imported directly rather than aggregated through a barrel.
2026-06-24 04:38:38 -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
42a5b6320f docs(shared-layer): note Cache schema registry carve-out to cross-process rule 2026-06-23 06:39:01 -07:00
SuYao
32a6666bb3 chore(chat-page): scaffold chat component tree (#14997)
Co-authored-by: jdzhang <625013594@qq.com>
Co-authored-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
Co-authored-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: kangfenmao <kangfenmao@qq.com>
Signed-off-by: jdzhang <625013594@qq.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-23 20:31:49 +08:00
fullex
793d33ab51 refactor(logger): derive renderer window source from index.html meta
Renderer windows set their logger source inline via initWindowSource() in
entryPoint.tsx, which had to execute before any import-time log or the source
fell back to 'UNKNOWN'. ESM hoists imports above statements, so this ordering
was fragile and applied inconsistently across windows.

LoggerService now derives the source at construction from a
<meta name="logger-window-source"> tag in each window's index.html. The meta
is parsed before any module script runs, so the source is set before any
import-time log -- no ordering rules in entryPoint.tsx. initWindowSource() is
kept as an explicit override for documentless contexts (workers, tests) and
takes precedence over the derived value.

- Add resolveWindowSourceFromMeta() and derivedWindow with
  explicit > derived > UNKNOWN precedence; export the LoggerService class
- Declare the meta in all 7 window index.html files (source strings unchanged)
- Drop the 7 inline initWindowSource() calls and the subWindow initLogger.ts
  module; keep the worker's explicit initWindowSource('Worker')
- Update windows/README.md and docs/guides/logging.md
- Add LoggerService unit tests
2026-06-22 22:11:01 -07:00