The ImportMetaEnv/ImportMeta interfaces were declared at the top level of
this module (the file has top-level imports), so they were module-local
and never augmented the global types. Move ImportMetaEnv into the existing
declare global block so it merges with vite's global interface, and declare
the env vars actually read in the renderer (RENDERER_VITE_AIHUBMIX_SECRET,
RENDERER_VITE_PPIO_APP_SECRET) instead of the unused VITE_RENDERER_INTEGRATED_MODEL.
Drop window.store: v1 Redux residue with zero references after Redux removal.
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
Subdirectories under the pages/ bucket are domain modules and must be
camelCase per naming-conventions.md section 4.5; the kebab-case
mini-apps was the only divergent one. Rename to pages/miniApps and
update the two route files and the test mock paths that referenced the
old path. Route URLs (/app/mini-app/...) are unchanged.
Reorganize src/renderer/config per renderer-architecture §8 so it holds only
app-global constants (constant.ts, env.ts).
- Delete v1 dead code: provider catalog, model defaults, embeddings/translate/
webSearch presets, the mini-app catalog, and unused agent configs.
- Relocate live config to its owning domain: PROVIDER_URLS -> ProviderSettings,
builtin MCP servers -> McpSettings, code providers -> code page, OCR ->
FileProcessingSettings, message menu bar -> chat message frame.
- Sink model predicates (with modelReconcile/modelSearch) into utils/model with
a curated named-export index; move tab/agent/sidebar helpers into utils.
- Split the sidebar icon map into the component layer (components/app/
sidebarIcons) to remove the reverse config->component dependency, and drop
the sidebar exports orphaned by #16413.
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.
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.
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.
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.
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
PR #16449 removed the last ConfigManager reads (GitBash + diagnose).
This deletes the now fully-orphaned ConfigManager service together with
its dead fallout: stale configManager comments in ipc.ts and
MainWindowService.ts, the obsolete ConfigManager test mock in
AppUpdaterService.test.ts, and the orphaned ZOOM_SHORTCUTS export.
electron-store is now used only by the v2 migration readers
(MigrationContext / MigrationEngine).
DevtoolsExtensionService was a lifecycle service in name only: it owned no long-lived resources and needed no cleanup, only running a one-shot dev-only side effect (installing React DevTools + the bundled DataApi DevTools) in onReady. Per the lifecycle decision guide that does not belong in lifecycle, and as business-agnostic dev tooling it does not belong under services/ either.
Move it to a pure function in core/devtools.ts (alongside core/diagnostics.ts, the existing dev-tooling precedent), gated by isDev, and invoke it from MainWindowService.onReady() before the main window opens. That matches Electron's contract (after app ready, before the first page loads), which the former Background phase did not guarantee.
Also switch the deprecated session.loadExtension to session.extensions.loadExtension, and lazy-import electron-devtools-installer (a devDependency whose module load calls app.getPath()) so it never reaches the production path.
The v1 Redux store was deleted, so @reduxjs/toolkit, react-redux, redux,
and redux-persist have no importers anywhere in the codebase. Drop them as
direct dependencies. redux/react-redux remain in the lockfile only as
transitive deps of @hello-pangea/dnd, which uses them internally.
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.
Decouple consumers from the deprecated `@renderer/databases` schema module
as a step toward removing `src/renderer/databases`.
- DexieExporter: open the legacy `CherryStudio` IndexedDB in Dexie dynamic
mode via a self-contained `new Dexie()` guarded by `Dexie.exists`, instead
of importing the shared `db`. The v2 migration gate (`versionPolicy.ts`)
only admits users from a final v1 release whose on-disk schema is already
at its last version, so no Dexie upgrade hooks need to run before export.
- Remove the five bare `import '@renderer/databases'` side-effect imports
(AppShell, MainApp, SubWindowApp, SubWindowAppShell, settings entryPoint);
the db singleton is still instantiated by its direct importers.
- Comment out (keep) the disabled Dexie write-back in redux-persist migrator
'34'; v2 never reads db.topics so the legacy store is no longer mutated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
With useCopilot removed in #16412, no renderer component reads the Redux store
via useSelector/useDispatch anymore, so the <Provider store={store}> wrappers in
the three window entry points (main / settings / subWindow) are dead. Remove
them along with their store and react-redux imports.
The store is no longer mounted in React. The only remaining renderer consumer is
ImportService, which dispatches to the store singleton directly (no Provider
needed); it is intentionally left untouched for now.
Stop renderer code outside src/renderer/store/ from importing the v1 Redux
store or any Redux tooling, so the store can later be deleted outright.
Migrate live consumers to v2:
- useSettings fields -> usePreference, then delete useSettings
- backup/nutstore sync status -> session-local, non-reactive holders inside
Backup/NutstoreService; Nutstore config now reads Preference, not Redux
Remove dead consumers:
- useAwsBedrock, useVertexAi (no callers)
- the legacy websearch sync bridge (no Redux reader)
- the always-empty paintings delete guards
- prompt.ts {{model_name}} fallback to llm.defaultModel
Other:
- repoint nanoid imports from @reduxjs/toolkit to the nanoid package
- move the built-in MCP server catalog from store/mcp.ts to
src/renderer/config (interim home; should move to the data layer in v2)
- drop all store/redux references from tests
The only remaining store consumers are tails marked @deprecated: useCopilot
(copilot auth state) and ImportService, plus the three window <Provider>
mounts they require.
FileAction was orphaned by the file-page rewrite in #15338 and is removed.