Skip to content

Conversation

@zerob13
Copy link
Collaborator

@zerob13 zerob13 commented Nov 17, 2025

Summary by CodeRabbit

  • New Features

    • Cross-window sync for search preview, notifications, and floating button state.
    • Enhanced search engine management with persistent selection, testing, and refresh flows.
    • Backup/import controls with refresh and start-backup actions exposed.
  • Chores

    • Dependency updates and added integration tooling.
    • Added planning and integration documentation.
  • Refactor

    • Migrated many data flows to a centralized query/mutation/cache layer for more reliable updates and invalidation.
    • Store lifecycle and initialization flows reorganized for consistency.

Add @pinia/colada dependency and useIpcQuery composable for type-safe IPC queries. Refactor MCP store to use Pinia Colada's query system with automatic caching, loading states, and error handling for config, tools, clients, resources, and prompts.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 17, 2025

Walkthrough

Integrates Pinia Colada and IPC-backed query/mutation patterns across the renderer: adds type-safe composables (useIpcQuery/useIpcMutation), registers the Colada plugin, refactors multiple stores (mcp, prompts, sync, settings), adds a new searchEngine store, new events, docs/plans, and dependency updates.

Changes

Cohort / File(s) Summary
Documentation & Planning
\.cursor/plans/store-colada-b9fc060f.plan.md, docs/mcp-store-colada-integration.md
Added migration plan and comprehensive integration guide for Pinia Colada, covering Query/Mutation patterns, caching/GC strategies, usage examples, migration steps, and checklists.
Dependencies
package.json
Bumped @modelcontextprotocol/sdk to ^1.22.0; added @pinia/colada ^0.17.8 (devDependency); updated vue-renderer-markdown dev version.
Event Definitions
src/main/events.ts, src/renderer/src/events.ts
Added CONFIG_EVENTS keys: SEARCH_PREVIEW_CHANGED and NOTIFICATIONS_CHANGED for cross-window config propagation.
Renderer Core
src/renderer/src/main.ts
Registered @pinia/colada plugin with default queryOptions (staleTime 30s, gcTime 5m).
IPC Composables
src/renderer/src/composables/useIpcQuery.ts, src/renderer/src/composables/useIpcMutation.ts
New type-safe composables that bind presenter methods to Pinia Colada queries/mutations; support generics, runtime arg resolution, lifecycle hooks, and dynamic invalidateQueries handling.
Store - MCP
src/renderer/src/stores/mcp.ts
Replaced inline presenter calls with useIpcQuery/useIpcMutation; introduced queries (config/tools/clients/resources/prompts), mutation-driven operations with invalidateQueries, adjusted init/load APIs and callTool now returns Promise.
Store - Prompts
src/renderer/src/stores/prompts.ts
Switched to promptsQuery (useIpcQuery) and mutation wrappers for CRUD operations with centralized invalidation and refetch flows.
Store - Sync / Backups
src/renderer/src/stores/sync.ts
Added backupsQuery, refreshBackups, startBackup and importData mutations; backups now derived from query data; added sync settings listener and mutation-driven flows.
New Store - Search Engines
src/renderer/src/stores/searchEngineStore.ts
New useSearchEngineStore with IPC-backed queries for base/custom engines, active engine sync, setSearchEngine mutation (with retry), listeners, and testSearchEngine utility.
Store Integration & Settings
src/renderer/src/stores/settings.ts, src/renderer/src/stores/floatingButton.ts
settings.ts now delegates search engine responsibilities to searchEngineStore (exposes aliases); added listeners for SEARCH_PREVIEW_CHANGED and NOTIFICATIONS_CHANGED; floatingButton store registers IPC ENABLED_CHANGED listener with guard.
Presenter (main)
src/main/presenter/configPresenter/index.ts, src/main/presenter/mcpPresenter/mcpClient.ts
configPresenter now emits renderer notifications for search preview, floating button enabled and notifications toggles; mcpClient initialization removed some advertised capabilities (resources/tools/prompts).
Renderer Component
src/renderer/src/components/McpToolsList.vue
Removed onMounted auto-loading logic for tools/clients—data population now driven externally.

Sequence Diagram(s)

sequenceDiagram
    participant Component
    participant useIpcQuery
    participant usePresenter
    participant Presenter
    participant Colada as Pinia_Colada
    participant Cache

    Component->>useIpcQuery: call(useIpcQuery(opts))
    useIpcQuery->>usePresenter: getPresenter(name)
    usePresenter->>Presenter: resolve
    useIpcQuery->>Colada: useQuery(key, queryFn)

    alt Cache hit
        Colada->>Cache: read(key)
        Cache-->>Colada: cached data
        Colada-->>Component: return data
    else Cache miss
        Colada->>Presenter: invoke method(args)
        Presenter-->>Colada: result
        Colada->>Cache: store(key, result)
        Colada-->>Component: return data
    end
Loading
sequenceDiagram
    participant Component
    participant useIpcMutation
    participant usePresenter
    participant Presenter
    participant Colada as Pinia_Colada
    participant Cache

    Component->>useIpcMutation: mutation.mutateAsync(vars)
    useIpcMutation->>usePresenter: getPresenter(name)
    usePresenter->>Presenter: resolve
    useIpcMutation->>Presenter: call(vars)
    Presenter-->>useIpcMutation: result

    alt success
        useIpcMutation->>Colada: invalidateQueries(keys)
        Colada->>Cache: evict(keys)
        useIpcMutation-->>Component: onSuccess(result)
    else error
        useIpcMutation-->>Component: onError(err)
    end
    useIpcMutation-->>Component: onSettled(result, err)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay special attention to:
    • Type generics and inferred method arg/return typing in useIpcQuery / useIpcMutation.
    • invalidateQueries callbacks across mcp, prompts, sync to ensure correct query key targeting.
    • Initialization and listener cleanup paths in searchEngineStore, settings, and floatingButton.
    • Mutation retry/fallback logic and any changed event payload types (MCP tool call result).

Possibly related PRs

Suggested labels

codex

Poem

🐰 Hopping through queries, I dance on the keys,

Mutations and caches, a soft Colada breeze.
Types stitched together, events hum in tune,
I nibble at bugs and hum a small rune—
New stores sprout like clover beneath the moon. 🌙🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: introducing Pinia Colada for improved data loading and error handling across the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/colada-with-ipc

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 794d9e4 and 09dc72e.

📒 Files selected for processing (2)
  • package.json (3 hunks)
  • src/main/presenter/mcpPresenter/mcpClient.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • src/main/presenter/mcpPresenter/mcpClient.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-check (x64)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/renderer/src/stores/settings.ts (1)

334-361: initSettings now wires config/listeners comprehensively, but setupProviderListener is called twice

initSettings’ updated flow:

  • Loads core settings and providers.
  • Calls searchEngineStore.initialize().
  • Refreshes all models and initializes the search assistant model.
  • Sets up config‑related listeners (setupContentProtectionListener, setupCopyWithCotEnabledListener, setupTraceDebugEnabledListener, setupFontSizeListener, setupSearchPreviewListener, setupNotificationsListener).
  • Calls setupProviderListener().

Later, onMounted also does:

onMounted(async () => {
  await initSettings()
  await setupProviderListener()
})

Because setupProviderListener itself unconditionally registers multiple ipcRenderer.on handlers, calling it both inside initSettings and again in onMounted will register each listener twice. That can cause duplicated updates, duplicated model refreshes, and extra work on every provider/config change.

You likely only need to call setupProviderListener once. A simple fix is to remove the explicit call inside initSettings and keep the one in onMounted, or vice versa (and drop it from onMounted).

-      // 设置配置类事件监听器(确保实时同步状态)
-      setupContentProtectionListener()
-      setupCopyWithCotEnabledListener()
-      setupTraceDebugEnabledListener()
-      setupFontSizeListener()
-      setupSearchPreviewListener()
-      setupNotificationsListener()
-
-      // 设置 provider 相关事件监听
-      setupProviderListener()
+      // 设置配置类事件监听器(确保实时同步状态)
+      setupContentProtectionListener()
+      setupCopyWithCotEnabledListener()
+      setupTraceDebugEnabledListener()
+      setupFontSizeListener()
+      setupSearchPreviewListener()
+      setupNotificationsListener()

(or alternatively drop the await setupProviderListener() in onMounted).

Also applies to: 150-155

🧹 Nitpick comments (11)
src/renderer/src/stores/floatingButton.ts (2)

11-11: Consider moving the guard into store state.

While the module-level guard works for singleton stores, moving it into the store's reactive state would be clearer and handle edge cases like store disposal/recreation during development.

Apply this diff:

  const configP = usePresenter('configPresenter')

  // 悬浮按钮是否启用的状态
  const enabled = ref<boolean>(false)
- let listenerRegistered = false
+ const listenerRegistered = ref<boolean>(false)

And update the checks:

  const setupFloatingButtonListener = () => {
-   if (listenerRegistered) {
+   if (listenerRegistered.value) {
      return
    }

    if (!window?.electron?.ipcRenderer) {
      return
    }

-   listenerRegistered = true
+   listenerRegistered.value = true

66-68: Consider explicit initialization over onMounted.

Using onMounted in a Pinia store is unconventional and ties initialization to component lifecycle, which could cause issues if the store is accessed from non-component contexts. Consider explicit initialization (e.g., calling initializeState() from main.ts after app mount) for more predictable behavior.

.cursor/plans/store-colada-b9fc060f.plan.md (1)

1-192: Avoid hard-coding line numbers in long-lived plan docs

The plan references specific line numbers in files like mcp.ts and settings.ts. These are likely to drift as the code evolves, which can make the document misleading over time. Prefer pointing to functions/sections (e.g., “mcp.ts callTool method”) instead of raw line numbers so the plan stays accurate with fewer updates.

src/renderer/src/composables/useIpcQuery.ts (1)

1-47: Type-safe query wrapper looks good; consider narrowing method keys to functions

The abstraction around useQuery and presenters looks clean and matches Pinia Colada’s API (key + query, plus selected UseQueryOptions like staleTime/gcTime). (pinia-colada.esm.dev) The args?: MaybeRefOrGetter<Parameters<...>> design is also flexible for reactive arguments.

One small type-level improvement you could consider (not urgent):

  • PresenterMethod<TName> currently allows any key of IPresenter[TName], including non-function properties. You’re guarding at the type level via PresenterMethodFn, but you can avoid accidental property picks by restricting to function-valued keys:
-type PresenterName = keyof IPresenter
-type PresenterMethod<TName extends PresenterName> = keyof IPresenter[TName]
+type PresenterName = keyof IPresenter
+type PresenterFunctionKeys<T> = {
+  [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never
+}[keyof T]
+type PresenterMethod<TName extends PresenterName> = PresenterFunctionKeys<IPresenter[TName]>

You could then reuse these aliases in useIpcMutation.ts to avoid duplicating the presenter method typing logic.

Please confirm this still lines up with the current IPresenter definition and doesn’t exclude any presenter members you intentionally want to expose here.

docs/mcp-store-colada-integration.md (1)

35-35: Add a language hint to the fenced diagram block.

markdownlint (MD040) flags this code fence because it lacks a language tag. Please annotate the block as plain text (for example, text) to satisfy the lint rules.

-```
+```text
src/renderer/src/stores/sync.ts (3)

22-44: Backups query wiring and refresh behavior look consistent with Colada usage

backupQueryKey, backupsQuery, backups (sorted by createdAt), and refreshBackups are wired coherently: a stable key, IPC-backed query, derived sorted list, and an explicit refetch helper with error logging. Given that you already invalidate this key in the mutations below, this should keep the list fresh after local backup/import operations.

One behavioral gap to consider: backups created from other windows or background actions will only show up after TTL expiry or a manual refreshBackups() call. If you want immediate UI updates when those events fire, consider also calling refreshBackups() inside the SYNC_EVENTS.BACKUP_COMPLETED and SYNC_EVENTS.IMPORT_COMPLETED listeners in initialize.


45-101: Backup/import mutation flows are guarded well; minor subtlety around isBackingUp/events

The startBackup and importData helpers add good guardrails:

  • Short‑circuit when sync is disabled, already backing up/importing, or backupFile is empty.
  • Local isBackingUp / isImporting flags with try/finally reset.
  • Cache invalidation via invalidateQueries: () => [backupQueryKey()], plus an extra refreshBackups() on success and in the import finally block.

The only subtlety is that isBackingUp is now controlled both by this function and by IPC events (SYNC_EVENTS.BACKUP_STARTED/BACKUP_COMPLETED). If the presenter returns quickly while the backup still runs, startBackup’s finally may flip isBackingUp back to false before the completion event arrives. That likely only causes a brief UI mismatch but is worth being aware of; if it becomes an issue, you could rely solely on IPC events for the flag and let startBackup avoid toggling it directly.


172-186: Sync settings listener correctly refreshes on folder changes; small simplification possible

setupSyncSettingsListener keeps syncEnabled and syncFolderPath in sync with CONFIG_EVENTS.SYNC_SETTINGS_CHANGED, and triggers refreshBackups() only when the folder actually changes, which avoids redundant reloads.

The else if (typeof payload.folderPath === 'string') branch effectively reassigns the same value without refreshing. This is harmless but can be simplified by computing a hasFolderChanged boolean once and then updating/refreshing accordingly, if you want to trim conditionals.

You might also consider whether changes to enabled alone should trigger any cleanup (e.g., clearing backups or importResult) when sync is turned off, depending on UI expectations.

src/renderer/src/stores/mcp.ts (2)

62-85: Config query + watchers keep MCP config in sync; slight redundancy but acceptable

The configQuery (['mcp', 'config']) aggregates servers, defaults, and enabled state in one shot and normalizes nullish values, which is good. syncConfigFromQuery and the watcher on configQuery.data.value (with { immediate: true }) ensure config.value is updated whenever the query data changes.

loadConfig also calls runQuery(configQuery, options) and then calls syncConfigFromQuery(state.data) again on success. That means for the initial load you effectively sync config twice to the same value; this isn’t harmful, just a bit redundant.

If you want to tighten things up, you could rely solely on the watcher for syncing (loadConfig would just await runQuery(configQuery, options) and then updateAllServerStatuses() when config.value.ready flips), but the current implementation is correct.

Also applies to: 203-215, 238-267


305-363: Mutation + invalidation design looks correct; small potential to rely more on query invalidation

The new mutations for server/config operations (addServer*, updateServer*, removeServer*, addDefaultServer*, resetToDefaultServers*, setMcpEnabledMutation) consistently:

  • Target mcpPresenter methods.
  • Invalidate the appropriate query keys (config/tools/clients/resources as needed).

In the higher‑level methods (addServer, updateServer, removeServer, toggleDefaultServer, resetToDefaultServers), you’re also calling runQuery(configQuery, { force: true }) after successful mutations. That ensures config is eagerly resynced, but it’s somewhat redundant with the invalidation, which will already cause queries to refetch on next use.

Not a correctness issue, but if you want to reduce duplicate network calls you could consider relying on invalidation alone and only forcing a configQuery refresh in flows that must synchronously see the updated config.

Also applies to: 430-506

src/renderer/src/stores/settings.ts (1)

1557-1571: Extended cleanup covers new listeners; consider whether it should own SEARCH_ENGINES_UPDATED cleanup

The cleanup function now removes listeners for:

  • CONTENT_PROTECTION_CHANGED
  • COPY_WITH_COT_CHANGED
  • TRACE_DEBUG_CHANGED
  • FONT_SIZE_CHANGED
  • SEARCH_PREVIEW_CHANGED
  • NOTIFICATIONS_CHANGED

which matches the new setup*Listener functions and helps avoid leaking IPC handlers.

One thing to re‑evaluate: cleanup still calls removeAllListeners(CONFIG_EVENTS.SEARCH_ENGINES_UPDATED), but the settings store no longer sets up that listener itself—it’s delegated to searchEngineStore.setupSearchEnginesListener(). If other parts of the app use useSearchEngineStore, this cleanup might unexpectedly remove their listeners. If cleanup is only called during global teardown this is harmless, but if it can be invoked earlier you may want to move SEARCH_ENGINES_UPDATED cleanup into the search engine store instead.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 28191df and 794d9e4.

📒 Files selected for processing (16)
  • .cursor/plans/store-colada-b9fc060f.plan.md (1 hunks)
  • docs/mcp-store-colada-integration.md (1 hunks)
  • package.json (2 hunks)
  • src/main/events.ts (1 hunks)
  • src/main/presenter/configPresenter/index.ts (3 hunks)
  • src/renderer/src/components/McpToolsList.vue (1 hunks)
  • src/renderer/src/composables/useIpcMutation.ts (1 hunks)
  • src/renderer/src/composables/useIpcQuery.ts (1 hunks)
  • src/renderer/src/events.ts (1 hunks)
  • src/renderer/src/main.ts (2 hunks)
  • src/renderer/src/stores/floatingButton.ts (2 hunks)
  • src/renderer/src/stores/mcp.ts (15 hunks)
  • src/renderer/src/stores/prompts.ts (1 hunks)
  • src/renderer/src/stores/searchEngineStore.ts (1 hunks)
  • src/renderer/src/stores/settings.ts (9 hunks)
  • src/renderer/src/stores/sync.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-12T00:58:06.513Z
Learnt from: zerob13
Repo: ThinkInAIXYZ/deepchat PR: 977
File: package.json:137-137
Timestamp: 2025-10-12T00:58:06.513Z
Learning: In this Electron project, renderer process dependencies (used only in src/renderer/) should be placed in devDependencies because they are bundled by electron-vite during the build process. Only main process dependencies (used in src/main/) need to be in the dependencies section.

Applied to files:

  • package.json
🧬 Code graph analysis (9)
src/renderer/src/composables/useIpcMutation.ts (3)
src/shared/types/presenters/legacy.presenters.d.ts (1)
  • IPresenter (353-373)
src/main/presenter/index.ts (1)
  • presenter (223-223)
src/renderer/src/composables/usePresenter.ts (1)
  • usePresenter (103-105)
src/renderer/src/stores/floatingButton.ts (2)
src/renderer/src/composables/usePresenter.ts (1)
  • usePresenter (103-105)
src/renderer/src/events.ts (1)
  • FLOATING_BUTTON_EVENTS (152-157)
src/renderer/src/stores/prompts.ts (3)
src/renderer/src/composables/useIpcQuery.ts (1)
  • useIpcQuery (31-47)
src/shared/types/presenters/legacy.presenters.d.ts (1)
  • Prompt (58-74)
src/renderer/src/composables/useIpcMutation.ts (1)
  • useIpcMutation (40-89)
src/renderer/src/stores/searchEngineStore.ts (5)
src/renderer/src/composables/usePresenter.ts (1)
  • usePresenter (103-105)
src/renderer/src/composables/useIpcQuery.ts (1)
  • useIpcQuery (31-47)
src/renderer/src/composables/useIpcMutation.ts (1)
  • useIpcMutation (40-89)
src/main/presenter/threadPresenter/index.ts (2)
  • setSearchEngine (213-220)
  • testSearchEngine (204-206)
src/renderer/src/events.ts (1)
  • CONFIG_EVENTS (11-33)
src/main/presenter/configPresenter/index.ts (3)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/main/events.ts (2)
  • CONFIG_EVENTS (12-43)
  • FLOATING_BUTTON_EVENTS (198-207)
src/renderer/src/events.ts (2)
  • CONFIG_EVENTS (11-33)
  • FLOATING_BUTTON_EVENTS (152-157)
src/renderer/src/stores/sync.ts (5)
src/renderer/src/composables/usePresenter.ts (1)
  • usePresenter (103-105)
src/renderer/src/composables/useIpcQuery.ts (1)
  • useIpcQuery (31-47)
src/shared/types/presenters/legacy.presenters.d.ts (1)
  • SyncBackupInfo (1379-1383)
src/renderer/src/composables/useIpcMutation.ts (1)
  • useIpcMutation (40-89)
src/renderer/src/events.ts (1)
  • CONFIG_EVENTS (11-33)
src/renderer/src/stores/mcp.ts (6)
src/shared/types/presenters/legacy.presenters.d.ts (5)
  • MCPConfig (1144-1149)
  • ResourceListEntry (121-128)
  • PromptListEntry (84-97)
  • Prompt (58-74)
  • MCPServerConfig (1128-1142)
src/renderer/src/composables/useIpcQuery.ts (1)
  • useIpcQuery (31-47)
src/main/presenter/mcpPresenter/mcpClient.ts (1)
  • callTool (1160-1200)
src/renderer/src/composables/useIpcMutation.ts (1)
  • useIpcMutation (40-89)
src/main/presenter/mcpPresenter/index.ts (1)
  • callTool (543-587)
src/main/presenter/mcpPresenter/toolManager.ts (1)
  • callTool (304-453)
src/renderer/src/composables/useIpcQuery.ts (2)
src/shared/types/presenters/legacy.presenters.d.ts (1)
  • IPresenter (353-373)
src/renderer/src/composables/usePresenter.ts (1)
  • usePresenter (103-105)
src/renderer/src/stores/settings.ts (2)
src/renderer/src/stores/searchEngineStore.ts (1)
  • useSearchEngineStore (10-148)
src/renderer/src/events.ts (1)
  • CONFIG_EVENTS (11-33)
🪛 LanguageTool
docs/mcp-store-colada-integration.md

[uncategorized] ~1094-~1094: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:便捷"地"访问
Context: ... 或 useQuery 定义查询 4. 添加计算属性:为组件提供便捷的访问接口 5. 添加缓存失效:在相关的 Mutation 中配置缓存失效...

(wb4)


[uncategorized] ~1257-~1257: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:友好"地"调用
Context: ...s` 中列出需要失效的查询 5. 包装 Store 方法:为组件提供友好的调用接口 6. 错误处理:添加适当的错误处理和用户反馈 #### 代码...

(wb4)

🪛 markdownlint-cli2 (0.18.1)
docs/mcp-store-colada-integration.md

35-35: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (14)
src/renderer/src/stores/floatingButton.ts (2)

4-4: LGTM!

The import is necessary for the new IPC event listener and is correctly used.


40-40: LGTM!

The listener setup is correctly placed after state initialization.

package.json (2)

107-107: @pinia/colada correctly scoped as a renderer devDependency

Using @pinia/colada only from renderer stores/composables and registering it in src/renderer/src/main.ts makes devDependencies the right place in this Electron setup, since renderer code is bundled by electron-vite. This matches the existing convention of keeping renderer-only libraries out of dependencies. Based on learnings

Please double-check there is no main-process (src/main/) usage of Pinia Colada so we don’t accidentally require it at runtime outside the bundle.


169-169: Confirm vue-renderer-markdown 0.0.62-beta.1 compatibility

The minor/beta bump for vue-renderer-markdown looks reasonable, but renderer Markdown rendering is a user-facing path, so it’s worth a quick regression check (e.g., headings, lists, code blocks) to ensure there are no breaking changes or styling regressions.

src/renderer/src/main.ts (1)

6-35: Pinia Colada plugin wiring and global query options look correct

Registering PiniaColada after createPinia() and using queryOptions for global defaults matches the library’s recommended setup. (github.com) The chosen staleTime (30s) and gcTime (5min) also align with the plan’s intent to keep IPC-backed renderer data warm while avoiding overly long retention.

Just make sure these global values work well for all current queries (MCP, prompts, sync, search engines); if any resource needs different staleness, you can still override staleTime/gcTime per-query via useIpcQuery.

src/renderer/src/stores/mcp.ts (6)

55-61: runQuery helper integrates well with Colada; be mindful of when you want refetch vs refresh

The QueryExecuteOptions + runQuery helper cleanly abstracts choosing between queryReturn.refetch (for force: true) and queryReturn.refresh (default). Your uses in loadConfig, loadClients, loadTools, loadPrompts, and loadResources are consistent and check state.status === 'success' when they need the returned data.

Two things to verify:

  • That the UseQueryReturn from @pinia/colada indeed exposes both refresh and refetch with the same return type (QueryState<T>), matching your usage.
  • That callers are clear on the semantics: force: true will bypass staleness checks via refetch, while the default refresh respects staleness.

Functionally this looks solid and gives you a straightforward way to control cache behavior per call site.

Also applies to: 366-379, 542-589


87-110: IPC-backed tools/clients/resources/prompts queries and derived computed state look correct

  • toolsQuery, clientsQuery, and resourcesQuery all use useIpcQuery with:
    • Stable keys under the 'mcp' namespace.
    • enabled: () => config.value.ready && config.value.mcpEnabled so they only run once config has loaded and MCP is enabled.
  • promptsQuery merges custom prompts from config with MCP prompts when enabled, and falls back to only custom prompts otherwise.
  • Computed tools, clients, resources, and prompts correctly gate on mcpEnabled and default to empty arrays when data is absent.
  • toolsLoading, toolsError, and toolsErrorMessage wrap toolsQuery’s reactive state into simple consumable flags/messages.

This wiring is consistent and should integrate well with the mutation invalidation patterns defined later.

Also applies to: 154-163, 188-202


111-153: Prompt loading separation between MCP and config presenters is clear and resilient

Splitting prompt loading into loadMcpPrompts (via mcpPresenter) and loadCustomPrompts (via configPresenter and PromptPromptListEntry mapping) gives a clear source separation and allows custom prompts to work even when MCP is disabled.

The mapping preserves fields (name, description, parametersarguments, files, and a synthetic client identity), and both loaders log and return [] on failure, which is a reasonable fallback.

This is a solid improvement for prompt robustness around MCP availability.


164-187: Tool call mutation and helper are coherent; ensure event-based and mutation-based flows stay aligned

The call stack for tool invocation is nicely factored:

  • CallToolRequest/Result/MutationVars reuse the actual presenter types, keeping everything type-aligned.
  • callToolMutation uses useIpcMutation with:
    • onSuccess updating toolResults[toolName] from result.content.
    • onError logging a localized error and populating toolResults[toolName] with a user-friendly message.
  • callTool builds a request from toolInputs, applies search_files defaults, and calls mutateAsync([request]) while toggling toolLoadingStates[toolName] in a try/finally.

Assuming mcpPresenter.callTool returns exactly the { content: string; rawData: MCPToolResponse } (or similar) that your CallToolResult alias expects, this path should be reliable. Just keep the earlier MCP_EVENTS.TOOL_CALL_RESULT event payload in sync so that tool results updated from background events match the same structure.

Also applies to: 600-632


216-236: Tool snapshot initialization and config-driven cleanup behave as expected

applyToolsSnapshot initializes toolInputs lazily per tool, with special defaults for the search_files tool. The watcher on toolsQuery.data.value:

  • Bails out when MCP is disabled.
  • Applies snapshots immediately and on subsequent updates when tool definitions change.

The watcher on config.value.mcpEnabled resets both toolInputs and toolResults to {} when MCP is disabled, which is a good cleanup step to avoid stale UI.

All of this is consistent with the rest of the state management in the store.

Also applies to: 244-267


542-555: Client and resource loaders chain dependent queries in a sensible order

loadClients’ early return when MCP is disabled prevents unnecessary work. When it does run, you:

  • Refresh clientsQuery (respecting force), then
  • On success, call loadPrompts(options) and loadResources(options).

This ensures prompts/resources are refreshed only once clients have been (re)loaded. Similarly, loadResources bails out when MCP is disabled and otherwise just refreshes resourcesQuery. Error handling is localized and logs appropriately.

This sequencing looks correct and is a nice improvement over ad‑hoc presenter calls.

Also applies to: 579-589

src/renderer/src/stores/settings.ts (3)

1-2: Search engine store integration centralizes search state cleanly

Switching to useSearchEngineStore plus storeToRefs and exposing searchEngines/activeSearchEngine from there is a solid refactor. It removes duplicated search engine state from settings and delegates:

  • Initialization (searchEngineStore.initialize()),
  • Active engine selection,
  • CRUD/test behaviors

to the dedicated store, which matches the PR’s goal of centralizing data loading.

The return aliases (setSearchEngine, refreshSearchEngines, testSearchEngine, setupSearchEnginesListener) at the bottom are a nice way to preserve the existing public surface while routing through the new implementation.

Also applies to: 18-19, 24-32


1680-1697: New search preview & notifications listeners align with config events

setupSearchPreviewListener and setupNotificationsListener mirror the existing pattern for other config flags:

  • They listen to CONFIG_EVENTS.SEARCH_PREVIEW_CHANGED and CONFIG_EVENTS.NOTIFICATIONS_CHANGED.
  • They update the local searchPreviewEnabled and notificationsEnabled refs directly.

This keeps UI state in sync with external changes and matches how other toggles (content protection, copy-with-CoT, trace debug, font size) are handled. Combined with the additions to cleanup, this is a straightforward and correct extension.


1896-1951: Public API aliases to search engine store maintain backward compatibility

At the return block, the additions:

  • searchEngines,
  • activeSearchEngine,
  • setSearchEngine: searchEngineStore.setSearchEngine,
  • testSearchEngine: searchEngineStore.testSearchEngine,
  • refreshSearchEngines: searchEngineStore.refreshSearchEngines,
  • setupSearchEnginesListener: searchEngineStore.setupSearchEnginesListener,

ensure existing callers of useSettingsStore continue to work without being aware of the new useSearchEngineStore. This is an appropriate compatibility layer for a refactor of this scope.

No functional issues here; the aliasing looks correct.

@zerob13 zerob13 merged commit 9ddbbfa into dev Nov 17, 2025
2 checks passed
@zerob13 zerob13 deleted the refactor/colada-with-ipc branch November 23, 2025 13:52
@coderabbitai coderabbitai bot mentioned this pull request Nov 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants