Skip to content

feat: support custom in welcome#1341

Merged
zerob13 merged 4 commits intodevfrom
feat/support-custom-in-welcome
Mar 10, 2026
Merged

feat: support custom in welcome#1341
zerob13 merged 4 commits intodevfrom
feat/support-custom-in-welcome

Conversation

@zerob13
Copy link
Copy Markdown
Collaborator

@zerob13 zerob13 commented Mar 10, 2026

#157

Summary by CodeRabbit

  • New Features

    • Redesigned welcome flow with guided provider and ACP setup and direct "open settings" navigation.
    • Multilingual welcome content added across many locales.
    • Developer override to force/clear the welcome startup flow (exposed to dev tools).
  • Bug Fixes

    • UI defers rendering until startup checks complete to prevent premature navigation.
    • Sessions gracefully skip unavailable agents and recover when active sessions change.
  • Refactor

    • Simplified page routing and startup sequencing for clearer navigation paths.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 10, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds a developer welcome override and new localized WelcomePage with settings-window navigation, emits SESSION_EVENTS.LIST_UPDATED when ACP agents change, makes session-building resilient to agent failures, removes legacy WelcomeView, and updates tests and i18n for the new welcome flow.

Changes

Cohort / File(s) Summary
Main presenters
src/main/presenter/configPresenter/index.ts, src/main/presenter/newAgentPresenter/index.ts
ConfigPresenter now notifies renderers via SESSION_EVENTS.LIST_UPDATED when ACP agents change. NewAgentPresenter builds sessions with guarded state resolution (tryBuildSessionWithState), skipping unavailable sessions and logging warnings.
Preload / Dev API
src/preload/index.d.ts, src/preload/index.ts
Adds an optional __deepchatDev API exposing goToWelcome() and clearWelcomeOverride() gated by a dev flag and a sessionStorage override key.
Renderer startup & routing
src/renderer/src/App.vue, src/renderer/src/router/index.ts, src/renderer/src/stores/ui/pageRouter.ts, src/renderer/src/stores/ui/session.ts, src/renderer/src/views/ChatTabView.vue
Introduces dev welcome override and startup readiness gating; swaps welcome route to the new WelcomePage.vue; simplifies pageRouter (removes legacy welcome path and config-driven logic); session store detects previous active session to trigger new-thread fallback; ChatTabView defers render until ready.
Welcome UI & navigation
src/renderer/src/pages/WelcomePage.vue, src/renderer/src/components/mock/MockWelcomePage.vue, src/renderer/src/views/WelcomeView.vue
Adds localized WelcomePage and mock variant with provider browse and ACP setup flows that open/focus settings windows and send NAVIGATE events; deletes legacy WelcomeView.vue (onboarding wizard removed).
i18n
src/renderer/src/i18n/*/welcome.json (en-US, da-DK, fa-IR, fr-FR, he-IL, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW)
Adds a new page section with welcome copy and provider name keys across language files.
Tests
test/renderer/components/App.startup.test.ts, test/renderer/components/WelcomePage.test.ts, test/renderer/stores/pageRouter.test.ts, test/renderer/stores/sessionStore.test.ts, test/main/presenter/newAgentPresenter/newAgentPresenter.test.ts
New/updated tests for app startup (dev override), WelcomePage navigation and settings-window interaction, simplified pageRouter tests, session store LIST_UPDATED handling, and newAgentPresenter expectations (initSession now receives agentId and skips unavailable sessions).
Settings UI tweaks
src/renderer/settings/components/ProviderModelList.vue
Replaced inline type checks with type-guard helpers and wrapped size-dependency call to getScrollerItemSizeDependencies.

Sequence Diagram(s)

sequenceDiagram
    participant WelcomePage
    participant PageRouter
    participant Router
    participant WindowPresenter
    participant SettingsWindow
    participant Renderer

    WelcomePage->>PageRouter: setSetting('init_complete', true) & goToNewThread()
    PageRouter->>Router: router.replace({ name: 'chat', sessionId })
    WelcomePage->>WindowPresenter: createSettingsWindow()
    WindowPresenter->>SettingsWindow: create/focus window (settings-provider | settings-acp)
    WelcomePage->>SettingsWindow: sendToWindow(SESSION_EVENTS.NAVIGATE, { route })
    SettingsWindow->>Renderer: navigate to route (settings-provider | settings-acp)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #1101: Modifies configPresenter and related event emission logic—overlaps with the new SESSION_EVENTS.LIST_UPDATED emission on ACP changes.
  • PR #996: Adds/changes settings-window APIs (create/get settings window) that the new WelcomePage navigation flow uses.
  • PR #1319: Introduces or evolves SESSION_EVENTS and LIST_UPDATED handling used by presenters and renderer event listeners.

Suggested reviewers

  • deepinfect

Poem

🐰 I hopped to welcome, new routes in sight,

Dev keys in hand to guide the flight,
Windows open, settings gleam so bright,
Sessions skipped softly when agents take flight,
Old view retires — hello new light! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: support custom in welcome' is vague and does not clearly summarize the main changes. It lacks specificity about what 'custom' feature is being added and in what context. Revise the title to be more specific and descriptive, such as 'feat: add welcome page flow for provider and ACP agent setup' or 'feat: refactor welcome onboarding with new agent setup flows'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/support-custom-in-welcome

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
Copy Markdown
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: 1

Caution

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

⚠️ Outside diff range comments (2)
src/main/presenter/configPresenter/index.ts (1)

1305-1308: ⚠️ Potential issue | 🟠 Major

Send LIST_UPDATED after ACP refresh finishes.

SESSION_EVENTS.LIST_UPDATED now makes the renderer call fetchSessions() immediately, but handleAcpAgentsMutated() still emits that event before refreshAcpProviderAgents(agentIds) completes. That means session reloads can race against acpProvider.refreshAgents() and observe stale ACP availability, with no follow-up event to correct the UI.

Suggested fix
-  private handleAcpAgentsMutated(agentIds?: string[]) {
+  private async handleAcpAgentsMutated(agentIds?: string[]): Promise<void> {
     this.clearProviderModelStatusCache('acp')
-    this.notifyAcpAgentsChanged()
-    this.refreshAcpProviderAgents(agentIds)
+    await this.refreshAcpProviderAgents(agentIds)
+    this.notifyAcpAgentsChanged()
   }

-  private refreshAcpProviderAgents(agentIds?: string[]): void {
+  private async refreshAcpProviderAgents(agentIds?: string[]): Promise<void> {
     try {
       const providerInstance = presenter?.llmproviderPresenter?.getProviderInstance?.('acp')
       if (!providerInstance) {
         return
       }

       const acpProvider = providerInstance as AcpProvider
       if (typeof acpProvider.refreshAgents !== 'function') {
         return
       }

-      void acpProvider.refreshAgents(agentIds)
+      await acpProvider.refreshAgents(agentIds)
     } catch (error) {
       console.warn('[ACP] Failed to refresh agent processes after config change:', error)
     }
   }

Also applies to: 1329-1332

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/presenter/configPresenter/index.ts` around lines 1305 - 1308, The
handler handleAcpAgentsMutated currently clears cache, emits
notifyAcpAgentsChanged (which causes SESSION_EVENTS.LIST_UPDATED) and then calls
refreshAcpProviderAgents, causing a race; change the flow so you clear the
cache, call refreshAcpProviderAgents(agentIds) and await its completion, then
call notifyAcpAgentsChanged (so SESSION_EVENTS.LIST_UPDATED is emitted only
after refresh finishes). Apply the same change to the analogous block that
follows (the other handler that calls notify... then refresh... around lines
referenced in the review).
src/main/presenter/newAgentPresenter/index.ts (1)

367-380: ⚠️ Potential issue | 🟠 Major

Don’t collapse state-load failures into “session missing”.

tryBuildSessionWithState() now catches every failure path, so getSession() returns null for transient getSessionState() errors as well as genuinely unavailable agents. That makes getActiveSession() clear a valid binding on a temporary runtime hiccup, and callers like src/main/presenter/mcpPresenter/toolManager.ts:426-432 will silently skip ACP agent propagation because they only see null. Please keep the skip-only behavior for permanently unavailable agents in list APIs, but let single-session lookups surface non-agent-resolution failures instead.

Suggested direction
 async getSession(sessionId: string): Promise<SessionWithState | null> {
   const record = this.sessionManager.get(sessionId)
   if (!record) return null
-  return await this.tryBuildSessionWithState(record)
+  return await this.buildSessionWithState(record)
 }

 private async tryBuildSessionWithState(record: SessionRecord): Promise<SessionWithState | null> {
   try {
     return await this.buildSessionWithState(record)
   } catch (error) {
+    if (!(error instanceof Error) || !error.message.startsWith('Agent not found:')) {
+      throw error
+    }
     console.warn(
       `[NewAgentPresenter] Skipping unavailable session id=${record.id} agent=${record.agentId}:`,
       error
     )
     return null
   }
 }

Also applies to: 545-552, 898-907

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/presenter/newAgentPresenter/index.ts` around lines 367 - 380,
getSession currently calls tryBuildSessionWithState(record) which swallows all
errors, causing transient state-load failures to be treated the same as missing
sessions; change getSession to call tryBuildSessionWithState(record) but
propagate non-agent-resolution errors instead of returning null: specifically,
keep the early null return for genuinely missing records from
sessionManager.get(sessionId), but when tryBuildSessionWithState throws or
returns an error indicating a transient getSessionState()/agent-resolution
failure, rethrow that error (or return it to the caller) so callers (e.g.,
getActiveSession and the toolManager consumer) can detect and handle transient
failures; update analogous call sites that rely on getSession (the other
occurrences around tryBuildSessionWithState) to preserve list APIs behavior
(filter out permanently unavailable agents) while surfacing non-resolution
errors for single-session lookups.
🧹 Nitpick comments (7)
test/renderer/stores/sessionStore.test.ts (1)

221-229: Consider using flushPromises for more reliable async handling.

The setTimeout(resolve, 0) pattern works but can be fragile if the async chain has multiple ticks. Consider using @vue/test-utils's flushPromises for consistency with other Vue tests.

♻️ Suggested improvement
+import { flushPromises } from '@vue/test-utils'
+
 it('reloads sessions when the session list update event fires', async () => {
     const { newAgentPresenter, emitIpc, SESSION_EVENTS } = await setupStore()

     emitIpc(SESSION_EVENTS.LIST_UPDATED)
-    await new Promise((resolve) => setTimeout(resolve, 0))
+    await flushPromises()

     expect(newAgentPresenter.getSessionList).toHaveBeenCalledTimes(1)
     expect(newAgentPresenter.getActiveSession).toHaveBeenCalledTimes(1)
   })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/renderer/stores/sessionStore.test.ts` around lines 221 - 229, Replace
the ad-hoc tick wait with Vue's flushPromises to make the async test robust:
import flushPromises from '@vue/test-utils' at the top, and in the test that
uses setupStore()/emitIpc(SESSION_EVENTS.LIST_UPDATED) replace the await new
Promise(resolve => setTimeout(resolve, 0)) with await flushPromises(); keep
assertions that newAgentPresenter.getSessionList and getActiveSession were
called once so the test still verifies those calls.
src/renderer/src/App.vue (2)

231-231: Potential silent error suppression with void operator.

If configPresenter.getSetting() or router operations fail, the error will be silently swallowed. Consider adding error handling to log failures while still allowing the UI to proceed.

♻️ Suggested improvement
-void ensureStartupWelcomeState()
+ensureStartupWelcomeState().catch((error) => {
+  console.error('Startup welcome state check failed:', error)
+})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/App.vue` at line 231, The call to ensureStartupWelcomeState
uses the void operator which can silently swallow rejections from async
operations like configPresenter.getSetting() and router navigation; update
ensureStartupWelcomeState (or the place that calls it) to await its result
inside a try/catch (or attach a .catch) and log any errors via the existing
logger, ensuring failures from configPresenter.getSetting() and
router.push/replace are surfaced while allowing the UI flow to continue.

29-29: Consider extracting the constant to a shared location.

DEV_WELCOME_OVERRIDE_KEY is duplicated between src/preload/index.ts and src/renderer/src/App.vue. While sharing between preload and renderer contexts can be complex, a shared constants file under src/shared/ would ensure consistency and prevent drift.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/App.vue` at line 29, DEV_WELCOME_OVERRIDE_KEY is duplicated;
extract it into a shared constants module (e.g., export const
DEV_WELCOME_OVERRIDE_KEY = '__deepchat_dev_force_welcome') and update both
locations to import that symbol instead of redefining it. Create the new module
under a shared directory (e.g., src/shared/) and ensure both preload code (where
DEV_WELCOME_OVERRIDE_KEY is used) and the renderer App.vue import from that
module (adjust build/import aliases if needed so preload and renderer can
resolve the shared file).
test/renderer/components/App.startup.test.ts (1)

197-207: Note: Test relies on implicit import.meta.env.DEV being true in Vitest.

The dev override test works because Vitest sets import.meta.env.DEV = true by default. Consider adding a comment or explicit mock to make this dependency clear, preventing silent failures if test configuration changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/renderer/components/App.startup.test.ts` around lines 197 - 207, The
test relies on import.meta.env.DEV being true (Vitest default), so explicitly
document or mock it to avoid silent failures: either add a one-line comment
above the test noting the dependency on import.meta.env.DEV for future
maintainers, or explicitly set the env for this test (e.g., use Vitest's
vi.stubEnv/fixture to ensure DEV=true) before calling mountApp; reference
DEV_WELCOME_OVERRIDE_KEY and the mountApp invocation so the change is applied to
this specific test case.
src/renderer/src/pages/WelcomePage.vue (1)

111-120: Race condition workaround with 250ms retry is fragile and may not be sufficient.

The settings window's Vue app mounts asynchronously after createSettingsWindow() completes. The immediate navigateToSettings() call may arrive before the SETTINGS_EVENTS.NAVIGATE listener is registered in the settings app (see src/renderer/settings/App.vue). Although the listener handler includes await router.isReady() for synchronization, this only protects navigation routing—the listener registration itself is asynchronous. The 250ms retry is an arbitrary delay that may not be sufficient on slow machines or systems under load.

Consider having the settings window emit a "ready" IPC event once fully initialized, or implementing a retry with confirmation that the message was received.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/pages/WelcomePage.vue` around lines 111 - 120, The retry
with a fixed 250ms delay is fragile; modify the flow so navigation waits for an
explicit "settings-ready" acknowledgement from the settings window instead of
sleeping: update createSettingsWindow / windowPresenter to either return a
promise that resolves when the settings window emits a ready IPC event (emitted
by the settings app after it registers the SETTINGS_EVENTS.NAVIGATE listener) or
add logic here to listen for that IPC "settings-ready" message (using
ipcRenderer.once) before calling navigateToSettings(settingsWindowId,
routeName); remove the setTimeout retry and ensure the settings app emits the
ready event after registering its SETTINGS_EVENTS.NAVIGATE handler (see settings
App.vue) so navigateToSettings is only called after the listener exists.
src/renderer/src/components/mock/MockWelcomePage.vue (1)

92-103: Prefer the createSettingsWindow() result over a second presenter lookup.

openSettings() already waits for window creation, then immediately depends on getSettingsWindowId() being up to date. If that cached id lags the promise resolution, both navigation sends are skipped even though the window exists.

Possible simplification
 const openSettings = async (routeName: SettingsRouteName) => {
   const windowId = window.api.getWindowId()
   if (windowId != null) {
-    await windowPresenter.createSettingsWindow()
-    const settingsWindowId = windowPresenter.getSettingsWindowId()
+    const settingsWindowId =
+      (await windowPresenter.createSettingsWindow()) ??
+      windowPresenter.getSettingsWindowId()
     if (settingsWindowId != null) {
       navigateToSettings(settingsWindowId, routeName)
       window.setTimeout(() => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/components/mock/MockWelcomePage.vue` around lines 92 - 103,
The openSettings function should use the created window id returned or captured
immediately after awaiting windowPresenter.createSettingsWindow() rather than
re-querying windowPresenter.getSettingsWindowId() later; update openSettings to
store the settingsWindowId right after the await (or change
createSettingsWindow() to return the new id) and use that stored
settingsWindowId for both the immediate navigateToSettings(settingsWindowId,
routeName) call and the setTimeout comparison, so you avoid a stale second
lookup via getSettingsWindowId().
test/renderer/components/WelcomePage.test.ts (1)

11-85: Extract the repeated WelcomePage bootstrap into a helper.

The three cases repeat the same mocks and mount scaffolding almost verbatim, so any presenter or router contract change has to be updated in three places. A small mountWelcomePage(...) helper would keep these tests easier to evolve.

Also applies to: 106-180, 201-274

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/renderer/components/WelcomePage.test.ts` around lines 11 - 85, Extract
the repeated test setup into a helper function (e.g., mountWelcomePage) that
centralizes the mock wiring and mounting of WelcomePage: move the
vi.resetModules/vi.useFakeTimers, the window.api stub, the vi.doMock calls for
usePresenter (returning configPresenter/windowPresenter), usePageRouterStore,
vue-router mocks (useRoute/useRouter), vue-i18n, icons and theme, and the
mount(WelcomePage, ...) call into this helper; have mountWelcomePage return the
mounted wrapper plus the mocked collaborators (router, pageRouter,
configPresenter, windowPresenter) so each test can call mountWelcomePage() and
assert behavior (e.g., calls to router.replace, pageRouter.goToNewThread,
configPresenter.setSetting, windowPresenter.createSettingsWindow) without
duplicating the scaffolding.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/renderer/src/stores/ui/pageRouter.ts`:
- Around line 16-31: The initialize() function leaves error.value set after a
failure so future successful retries still show the stale error; clear
error.value at the start of initialize() (or immediately on successful path) so
any prior error is removed before attempting to re-run. Update the initialize()
function to reset error.value = '' (or null) before calling
newAgentPresenter.getActiveSession(...) and/or set error.value = '' right after
you set route.value on success (e.g., when setting route to { name: 'chat',
sessionId: ... } or { name: 'newThread' }) to ensure the UI no longer displays
the old failure message.

---

Outside diff comments:
In `@src/main/presenter/configPresenter/index.ts`:
- Around line 1305-1308: The handler handleAcpAgentsMutated currently clears
cache, emits notifyAcpAgentsChanged (which causes SESSION_EVENTS.LIST_UPDATED)
and then calls refreshAcpProviderAgents, causing a race; change the flow so you
clear the cache, call refreshAcpProviderAgents(agentIds) and await its
completion, then call notifyAcpAgentsChanged (so SESSION_EVENTS.LIST_UPDATED is
emitted only after refresh finishes). Apply the same change to the analogous
block that follows (the other handler that calls notify... then refresh...
around lines referenced in the review).

In `@src/main/presenter/newAgentPresenter/index.ts`:
- Around line 367-380: getSession currently calls
tryBuildSessionWithState(record) which swallows all errors, causing transient
state-load failures to be treated the same as missing sessions; change
getSession to call tryBuildSessionWithState(record) but propagate
non-agent-resolution errors instead of returning null: specifically, keep the
early null return for genuinely missing records from
sessionManager.get(sessionId), but when tryBuildSessionWithState throws or
returns an error indicating a transient getSessionState()/agent-resolution
failure, rethrow that error (or return it to the caller) so callers (e.g.,
getActiveSession and the toolManager consumer) can detect and handle transient
failures; update analogous call sites that rely on getSession (the other
occurrences around tryBuildSessionWithState) to preserve list APIs behavior
(filter out permanently unavailable agents) while surfacing non-resolution
errors for single-session lookups.

---

Nitpick comments:
In `@src/renderer/src/App.vue`:
- Line 231: The call to ensureStartupWelcomeState uses the void operator which
can silently swallow rejections from async operations like
configPresenter.getSetting() and router navigation; update
ensureStartupWelcomeState (or the place that calls it) to await its result
inside a try/catch (or attach a .catch) and log any errors via the existing
logger, ensuring failures from configPresenter.getSetting() and
router.push/replace are surfaced while allowing the UI flow to continue.
- Line 29: DEV_WELCOME_OVERRIDE_KEY is duplicated; extract it into a shared
constants module (e.g., export const DEV_WELCOME_OVERRIDE_KEY =
'__deepchat_dev_force_welcome') and update both locations to import that symbol
instead of redefining it. Create the new module under a shared directory (e.g.,
src/shared/) and ensure both preload code (where DEV_WELCOME_OVERRIDE_KEY is
used) and the renderer App.vue import from that module (adjust build/import
aliases if needed so preload and renderer can resolve the shared file).

In `@src/renderer/src/components/mock/MockWelcomePage.vue`:
- Around line 92-103: The openSettings function should use the created window id
returned or captured immediately after awaiting
windowPresenter.createSettingsWindow() rather than re-querying
windowPresenter.getSettingsWindowId() later; update openSettings to store the
settingsWindowId right after the await (or change createSettingsWindow() to
return the new id) and use that stored settingsWindowId for both the immediate
navigateToSettings(settingsWindowId, routeName) call and the setTimeout
comparison, so you avoid a stale second lookup via getSettingsWindowId().

In `@src/renderer/src/pages/WelcomePage.vue`:
- Around line 111-120: The retry with a fixed 250ms delay is fragile; modify the
flow so navigation waits for an explicit "settings-ready" acknowledgement from
the settings window instead of sleeping: update createSettingsWindow /
windowPresenter to either return a promise that resolves when the settings
window emits a ready IPC event (emitted by the settings app after it registers
the SETTINGS_EVENTS.NAVIGATE listener) or add logic here to listen for that IPC
"settings-ready" message (using ipcRenderer.once) before calling
navigateToSettings(settingsWindowId, routeName); remove the setTimeout retry and
ensure the settings app emits the ready event after registering its
SETTINGS_EVENTS.NAVIGATE handler (see settings App.vue) so navigateToSettings is
only called after the listener exists.

In `@test/renderer/components/App.startup.test.ts`:
- Around line 197-207: The test relies on import.meta.env.DEV being true (Vitest
default), so explicitly document or mock it to avoid silent failures: either add
a one-line comment above the test noting the dependency on import.meta.env.DEV
for future maintainers, or explicitly set the env for this test (e.g., use
Vitest's vi.stubEnv/fixture to ensure DEV=true) before calling mountApp;
reference DEV_WELCOME_OVERRIDE_KEY and the mountApp invocation so the change is
applied to this specific test case.

In `@test/renderer/components/WelcomePage.test.ts`:
- Around line 11-85: Extract the repeated test setup into a helper function
(e.g., mountWelcomePage) that centralizes the mock wiring and mounting of
WelcomePage: move the vi.resetModules/vi.useFakeTimers, the window.api stub, the
vi.doMock calls for usePresenter (returning configPresenter/windowPresenter),
usePageRouterStore, vue-router mocks (useRoute/useRouter), vue-i18n, icons and
theme, and the mount(WelcomePage, ...) call into this helper; have
mountWelcomePage return the mounted wrapper plus the mocked collaborators
(router, pageRouter, configPresenter, windowPresenter) so each test can call
mountWelcomePage() and assert behavior (e.g., calls to router.replace,
pageRouter.goToNewThread, configPresenter.setSetting,
windowPresenter.createSettingsWindow) without duplicating the scaffolding.

In `@test/renderer/stores/sessionStore.test.ts`:
- Around line 221-229: Replace the ad-hoc tick wait with Vue's flushPromises to
make the async test robust: import flushPromises from '@vue/test-utils' at the
top, and in the test that uses setupStore()/emitIpc(SESSION_EVENTS.LIST_UPDATED)
replace the await new Promise(resolve => setTimeout(resolve, 0)) with await
flushPromises(); keep assertions that newAgentPresenter.getSessionList and
getActiveSession were called once so the test still verifies those calls.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46a0dfda-2a0a-4c7c-aafb-2aedae9aae89

📥 Commits

Reviewing files that changed from the base of the PR and between a44ead3 and 66c5fc8.

📒 Files selected for processing (29)
  • src/main/presenter/configPresenter/index.ts
  • src/main/presenter/newAgentPresenter/index.ts
  • src/preload/index.d.ts
  • src/preload/index.ts
  • src/renderer/src/App.vue
  • src/renderer/src/components/mock/MockWelcomePage.vue
  • src/renderer/src/i18n/da-DK/welcome.json
  • src/renderer/src/i18n/en-US/welcome.json
  • src/renderer/src/i18n/fa-IR/welcome.json
  • src/renderer/src/i18n/fr-FR/welcome.json
  • src/renderer/src/i18n/he-IL/welcome.json
  • src/renderer/src/i18n/ja-JP/welcome.json
  • src/renderer/src/i18n/ko-KR/welcome.json
  • src/renderer/src/i18n/pt-BR/welcome.json
  • src/renderer/src/i18n/ru-RU/welcome.json
  • src/renderer/src/i18n/zh-CN/welcome.json
  • src/renderer/src/i18n/zh-HK/welcome.json
  • src/renderer/src/i18n/zh-TW/welcome.json
  • src/renderer/src/pages/WelcomePage.vue
  • src/renderer/src/router/index.ts
  • src/renderer/src/stores/ui/pageRouter.ts
  • src/renderer/src/stores/ui/session.ts
  • src/renderer/src/views/ChatTabView.vue
  • src/renderer/src/views/WelcomeView.vue
  • test/main/presenter/newAgentPresenter/newAgentPresenter.test.ts
  • test/renderer/components/App.startup.test.ts
  • test/renderer/components/WelcomePage.test.ts
  • test/renderer/stores/pageRouter.test.ts
  • test/renderer/stores/sessionStore.test.ts
💤 Files with no reviewable changes (1)
  • src/renderer/src/views/WelcomeView.vue

@zerob13 zerob13 merged commit 72dc7e5 into dev Mar 10, 2026
1 of 2 checks passed
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.

1 participant