Skip to content

Conversation

@zerob13
Copy link
Collaborator

@zerob13 zerob13 commented Dec 10, 2025

  • ACP process pre-warming to significantly reduce the wait time before the first message responds.
  • Mode selection at creation time, allowing users to choose a mode when starting a new session.
  • Left-click improvements for workspace files: automatically inserts a reference into the input box.
  • Right-click enhancements for workspace files: quickly open files or locate them in the directory.
    finish [Feature] init process in NewThreadView #1168

Summary by CodeRabbit

  • New Features

    • Pre-warm ACP processes and query/set per-agent+workdir process modes; presenter APIs and UI hooks added.
    • ACP Debug dialog: interactive debug actions, live event feed, payload editor, and new "Debug" entry in settings.
  • Bug Fixes

    • Improved reasoning content timestamps to record clearer start/end timing during streaming.
  • Chores

    • Added ACP debug localization for many locales and minor UI placement/markup tweaks.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Walkthrough

Adds ACP process warmup/bind lifecycle and per-agent+workdir mode discovery/preference APIs, ACP debug run/event plumbing and UI, renderer workdir-aware mode warmup/selection, and small reasoning_content timestamp start/end initialization changes.

Changes

Cohort / File(s) Change Summary
ACP Process Lifecycle & State Management
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
Adds warmup vs bound handle states, boundConversationId, available/current modes, preferred-mode persistence, bind/unbind APIs, handle reuse/disposal, mode fetching/notification, spawn/env merging, timeouts and stronger error logging.
ACP Session Binding & Mode Sync
src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
Binds warmup handles to conversations on session create, unbinds on clear/failure, normalizes/persists availableModes/currentModeId from handle/response, and applies preferred modes with defensive error handling.
Provider & Presenter APIs / Delegation
src/main/presenter/llmProviderPresenter/providers/acpProvider.ts, src/main/presenter/llmProviderPresenter/index.ts, src/main/presenter/threadPresenter/index.ts
New presenter/provider methods: warmup/get modes/set preferred mode/run debug action; debug event tracing and SESSION_MODES_READY emissions; provider-availability guarding and delegation.
Reasoning Content & Event Timing
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts, src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
reasoning_content blocks now include explicit reasoning_time start/end timestamps; streaming logic initializes start times from current time or last block timestamp (removed state.reasoningStartTime fallback).
Renderer Mode & Workdir Composables
src/renderer/src/components/chat-input/composables/useAcpMode.ts, src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
useAcpMode gains optional workdir, tracks warmup/load and pendingPreferredMode, loads warmup modes for workdir-only contexts; useAcpWorkdir triggers deduplicated warmups and manages lastWarmupKey.
Chat Input / Workspace UI changes
src/renderer/src/components/chat-input/ChatInput.vue, src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
Moved addon-actions slot, made mode-switch tooltip eligible for "newThread", pass workdir into acpMode, and simplified ContextMenuContent positioning props.
ACP Debug UI & Settings
src/renderer/settings/components/AcpDebugDialog.vue, src/renderer/settings/components/AcpSettings.vue
New AcpDebugDialog component (method selector, Monaco JSON payload editor, live event feed, send/run flow) and settings integration with Debug button and dialog wiring.
Types / Public Interfaces
src/shared/types/presenters/legacy.presenters.d.ts, src/shared/types/presenters/llmprovider.presenter.d.ts, src/shared/types/presenters/thread.presenter.d.ts
Added ACP debug types (AcpDebugActionType, AcpDebugEventKind, AcpDebugRequest, AcpDebugEventEntry, AcpDebugRunResult) and new presenter methods for warmup, mode retrieval/setting, and debug actions.
Events
src/main/events.ts, src/renderer/src/events.ts
Added ACP_DEBUG_EVENTS namespace with EVENT: 'acp-debug:event'.
Internationalization
src/renderer/src/i18n/**/settings.json (da‑DK, en‑US, fa‑IR, fr‑FR, he‑IL, ja‑JP, ko‑KR, pt‑BR, ru‑RU, zh‑CN, zh‑HK, zh‑TW)
Added debug translation blocks for the ACP Debug UI across locales.
Misc / Config
.vscode/settings.json, package.json, src/renderer/src/components/markdown/MarkdownRenderer.vue
VS Code settings formatting, markstream-vue devDependency bump, and Mermaid blocks now render with isStrict=true.
sequenceDiagram
  autonumber
  participant UI as Renderer (AcpDebugDialog / ChatInput)
  participant Presenter as ThreadPresenter / LLMProviderPresenter
  participant Provider as AcpProvider
  participant Manager as AcpProcessManager
  participant Session as AcpSessionManager

  UI->>Presenter: warmupAcpProcess(agentId, workdir) / getAcpProcessModes / setAcpPreferredProcessMode
  Presenter->>Provider: forward API call
  Provider->>Manager: warmupProcess / getProcessModes / setPreferredProcessMode
  Manager-->>Provider: return handle / modes
  Provider-->>Presenter: modes / ack
  Presenter-->>UI: return modes / SESSION_MODES_READY

  Note over UI,Presenter: Debug run flow
  UI->>Presenter: runAcpDebugAction(request)
  Presenter->>Provider: runDebugAction(request)
  Provider->>Session: initialize/new/load/prompt/etc.
  Session->>Manager: bindProcess / applyMode (when needed)
  Manager-->>Session: confirmation
  Session-->>Provider: stream events/responses
  Provider-->>Presenter: emit ACP_DEBUG_EVENTS (request/response/error)
  Presenter-->>UI: deliver events to AcpDebugDialog
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts — state transitions, handle reuse/cleanup, mode application, spawn/env merging, timeouts.
    • src/renderer/src/components/chat-input/composables/useAcpMode.ts & useAcpWorkdir.ts — workdir vs conversation mode logic and pendingPreferredMode handling.
    • src/renderer/settings/components/AcpDebugDialog.vue — Monaco editor lifecycle, payload parsing/formatting, IPC listener management, and event deduplication.
    • Presenter → Provider → ProcessManager error propagation and SESSION_MODES_READY payload consistency.

Possibly related PRs

Suggested reviewers

  • deepinfect

"🐇
Warmup handles hop through night and day,
Bound to threads where modes hold sway.
Debug events sparkle, payloads take flight,
Timestamps stitch moments from dark into light.
A little rabbit cheers — systems align!"

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 'feat: acp init and process manage' accurately describes the primary change—introducing ACP process initialization and management features including pre-warming, mode selection, and related lifecycle updates across multiple components.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/acp-init-and-process-manage

📜 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 dd5dbb2 and 9c0bad8.

📒 Files selected for processing (2)
  • package.json (1 hunks)
  • src/renderer/src/components/markdown/MarkdownRenderer.vue (1 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.vue: Use Vue 3 Composition API for all components instead of Options API
Use Tailwind CSS with scoped styles for component styling

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

src/renderer/**/*.vue: All user-facing strings must use i18n keys via vue-i18n for internationalization
Ensure proper error handling and loading states in all UI components
Implement responsive design using Tailwind CSS utilities for all UI components

src/renderer/**/*.vue: Use composition API and declarative programming patterns; avoid options API
Structure files: exported component, composables, helpers, static content, types
Use PascalCase for component names (e.g., AuthWizard.vue)
Use Vue 3 with TypeScript, leveraging defineComponent and PropType
Use template syntax for declarative rendering
Use Shadcn Vue, Radix Vue, and Tailwind for components and styling
Implement responsive design with Tailwind CSS; use a mobile-first approach
Use Suspense for asynchronous components
Use <script setup> syntax for concise component definitions
Prefer 'lucide:' icon family as the primary choice for Iconify icons
Import Icon component from '@iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*.{vue,ts,tsx}: All user-facing strings must use i18n keys with vue-i18n framework in the renderer
Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Use the dynamic locale.value property to switch languages at runtime
Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/**/*

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

New features should be developed in the src directory

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.{vue,js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Renderer process code should be placed in src/renderer (Vue 3 application)

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability in Vue.js applications
Implement proper state management with Pinia in Vue.js applications
Utilize Vue Router for navigation and route management in Vue.js applications
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/**/*.vue

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

Use scoped styles to prevent CSS conflicts between Vue components

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Write concise, technical TypeScript code with accurate examples
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Avoid enums; use const objects instead
Use arrow functions for methods and computed properties
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements

Vue 3 app code in src/renderer/src should be organized into components/, stores/, views/, i18n/, lib/ directories with shell UI in src/renderer/shell/

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Use lowercase with dashes for directories (e.g., components/auth-wizard)

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/**/*.{ts,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching
Leverage ref, reactive, and computed for reactive state management
Use provide/inject for dependency injection when appropriate
Use Iconify/Vue for icon implementation

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use TypeScript with Vue 3 Composition API for the renderer application
All user-facing strings must use vue-i18n keys in src/renderer/src/i18n

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/renderer/src/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

src/renderer/src/components/**/*.vue: Use Tailwind for styles in Vue components
Vue component files must use PascalCase naming (e.g., ChatInput.vue)

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
src/**/*.{ts,tsx,vue,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with single quotes, no semicolons, and 100 character width

Files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
package.json

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

package.json: Node.js >= 22 required
pnpm >= 9 required

Files:

  • package.json
🧠 Learnings (5)
📚 Learning: 2025-08-28T08:07:05.182Z
Learnt from: neoragex2002
Repo: ThinkInAIXYZ/deepchat PR: 807
File: src/renderer/src/components/markdown/MarkdownRenderer.vue:58-58
Timestamp: 2025-08-28T08:07:05.182Z
Learning: In src/renderer/src/components/markdown/MarkdownRenderer.vue, the unscoped <style> tag is intentionally used for global prose styles and the anchor .markdown-renderer fix, as confirmed by user neoragex2002.

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use template syntax for declarative rendering

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Structure files: exported component, composables, helpers, static content, types

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-11-25T05:27:26.656Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T05:27:26.656Z
Learning: Applies to src/renderer/**/*.{vue,js,ts} : Renderer process code should be placed in `src/renderer` (Vue 3 application)

Applied to files:

  • src/renderer/src/components/markdown/MarkdownRenderer.vue
📚 Learning: 2025-11-25T05:26:15.929Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/development-setup.mdc:0-0
Timestamp: 2025-11-25T05:26:15.929Z
Learning: Applies to package.json : Node.js >= 22 required

Applied to files:

  • 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)
🔇 Additional comments (2)
src/renderer/src/components/markdown/MarkdownRenderer.vue (1)

107-108: Confirm behavior change from enabling strict mode on all Mermaid blocks

Setting isStrict: true on every MermaidBlockNode will enforce stricter parsing for all Mermaid diagrams; any previously tolerated but non‑strict diagrams may now fail to render. Please confirm this global behavior change is intended for both existing content and new ACP/debug flows, and consider making strict mode configurable (e.g. via a setting or prop) if you expect mixed content quality.

package.json (1)

150-150: Verify markstream-vue beta version stability with maintainers.

The dependency is pinned to a beta version (0.0.3-beta.2), which appears to be a private or internal package not available in public registries. Unable to assess production readiness or identify breaking changes through public sources. Confirm with the package maintainers that this version is stable and compatible with the ACP-related UI enhancements (AcpDebugDialog, AcpSettings) before merging.


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

🧹 Nitpick comments (3)
src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue (1)

29-43: Context menu placement/width change looks fine; just confirm UX and consider a minor Tailwind tweak

Switching to the default ContextMenuContent positioning with a fixed w-48 simplifies things and should be functionally safe, but it does slightly change layout behavior compared to explicit align / side / sideOffset:

  • Please sanity‑check that the menu still appears fully within the viewport for deeply nested items or near the right edge, especially on narrower windows.
  • If you start seeing truncated labels or unnecessary horizontal overflow, consider min-w-48 instead of w-48 so the menu can grow with content while keeping a sensible minimum width.

Otherwise the overall context menu structure, i18n usage, and click/select handlers look solid and consistent with the PR’s left/right‑click behavior objectives.

Based on learnings, this aligns with the Composition API + vue-i18n + Tailwind guidelines.

src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts (1)

59-90: Consider triggering warmup when workdir is loaded from backend.

When loadWorkdir successfully retrieves an existing workdir from the backend, warmup isn't triggered. This means the first message in an existing conversation may still experience warmup delay.

       workdir.value = result?.path ?? ''
       isCustom.value = Boolean(result?.isCustom)
       pendingWorkdir.value = null
       syncPreference(workdir.value || null)
+      await warmupProcess(workdir.value)
     } catch (error) {
src/renderer/src/components/chat-input/composables/useAcpMode.ts (1)

197-205: Potential null safety concern in pre-conversation mode cycling.

Line 199 uses non-null assertions (options.activeModel.value!.id!). While the outer isAcpModel check validates providerId === 'acp' && !!options.activeModel.value?.id, the assertion could fail if state changes between the check and execution.

Consider adding a defensive check:

       } else if (selectedWorkdir.value) {
+        const agentId = options.activeModel.value?.id
+        if (!agentId) return
         await threadPresenter.setAcpPreferredProcessMode(
-          options.activeModel.value!.id!,
+          agentId,
           selectedWorkdir.value,
           nextModeId
         )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0854134 and 9a79743.

📒 Files selected for processing (14)
  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (1 hunks)
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (11 hunks)
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts (5 hunks)
  • src/main/presenter/llmProviderPresenter/index.ts (1 hunks)
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (3 hunks)
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts (2 hunks)
  • src/main/presenter/threadPresenter/index.ts (1 hunks)
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue (1 hunks)
  • src/renderer/src/components/chat-input/ChatInput.vue (3 hunks)
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts (7 hunks)
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts (5 hunks)
  • src/shared/types/presenters/legacy.presenters.d.ts (2 hunks)
  • src/shared/types/presenters/llmprovider.presenter.d.ts (1 hunks)
  • src/shared/types/presenters/thread.presenter.d.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (34)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and maintain strict TypeScript type checking for all files

**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/main/presenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Organize core business logic into dedicated Presenter classes, with one presenter per functional domain

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/main/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use EventBus from src/main/eventbus.ts for main-to-renderer communication, broadcasting events via mainWindow.webContents.send()

src/main/**/*.ts: Use EventBus pattern for inter-process communication within the main process to decouple modules
Use Electron's built-in APIs for file system and native dialogs instead of Node.js or custom implementations

src/main/**/*.ts: Electron main process code belongs in src/main/ with presenters in presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider) and eventbus.ts for app events
Use the Presenter pattern in the main process for UI coordination

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/index.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

Write logs and comments in English

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/main/presenter/llmProviderPresenter/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/llm-agent-loop.mdc)

Define the standardized LLMCoreStreamEvent interface with fields: type (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), content (for text), reasoning_content (for reasoning), tool_call_id, tool_call_name, tool_call_arguments_chunk (for streaming), tool_call_arguments_complete (for complete arguments), error_message, usage object with token counts, stop_reason (tool_use | max_tokens | stop_sequence | error | complete), and image_data object with Base64-encoded data and mimeType

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/**/*

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

New features should be developed in the src directory

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/main/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Main process code for Electron should be placed in src/main

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/**/*.{ts,tsx,vue,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with single quotes, no semicolons, and 100 character width

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use OxLint for linting JavaScript and TypeScript files

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use EventBus for inter-process communication events

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
src/shared/**/*.d.ts

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Define type definitions in shared/*.d.ts files for objects exposed by the main process to the renderer process

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/shared/types/presenters/thread.presenter.d.ts
src/shared/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Shared type definitions and utilities between main and renderer processes should be placed in src/shared

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/shared/types/presenters/thread.presenter.d.ts
src/shared/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Shared types and utilities should be placed in src/shared/

Files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/shared/types/presenters/thread.presenter.d.ts
**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.vue: Use Vue 3 Composition API for all components instead of Options API
Use Tailwind CSS with scoped styles for component styling

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

src/renderer/**/*.vue: All user-facing strings must use i18n keys via vue-i18n for internationalization
Ensure proper error handling and loading states in all UI components
Implement responsive design using Tailwind CSS utilities for all UI components

src/renderer/**/*.vue: Use composition API and declarative programming patterns; avoid options API
Structure files: exported component, composables, helpers, static content, types
Use PascalCase for component names (e.g., AuthWizard.vue)
Use Vue 3 with TypeScript, leveraging defineComponent and PropType
Use template syntax for declarative rendering
Use Shadcn Vue, Radix Vue, and Tailwind for components and styling
Implement responsive design with Tailwind CSS; use a mobile-first approach
Use Suspense for asynchronous components
Use <script setup> syntax for concise component definitions
Prefer 'lucide:' icon family as the primary choice for Iconify icons
Import Icon component from '@iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*.{vue,ts,tsx}: All user-facing strings must use i18n keys with vue-i18n framework in the renderer
Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Use the dynamic locale.value property to switch languages at runtime
Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/*.{vue,js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Renderer process code should be placed in src/renderer (Vue 3 application)

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability in Vue.js applications
Implement proper state management with Pinia in Vue.js applications
Utilize Vue Router for navigation and route management in Vue.js applications
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/**/*.vue

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

Use scoped styles to prevent CSS conflicts between Vue components

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Write concise, technical TypeScript code with accurate examples
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Avoid enums; use const objects instead
Use arrow functions for methods and computed properties
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements

Vue 3 app code in src/renderer/src should be organized into components/, stores/, views/, i18n/, lib/ directories with shell UI in src/renderer/shell/

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Use lowercase with dashes for directories (e.g., components/auth-wizard)

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/*.{ts,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching
Leverage ref, reactive, and computed for reactive state management
Use provide/inject for dependency injection when appropriate
Use Iconify/Vue for icon implementation

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use TypeScript with Vue 3 Composition API for the renderer application
All user-facing strings must use vue-i18n keys in src/renderer/src/i18n

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

src/renderer/src/components/**/*.vue: Use Tailwind for styles in Vue components
Vue component files must use PascalCase naming (e.g., ChatInput.vue)

Files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use the usePresenter.ts composable for renderer-to-main IPC communication to call presenter methods directly

Files:

  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
src/renderer/**/composables/*.ts

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/composables/*.ts: Use camelCase for composables (e.g., useAuthState.ts)
Use VueUse for common composables and utility functions
Implement custom composables for reusable logic

Files:

  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Use TypeScript for all code; prefer types over interfaces

Files:

  • src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
  • src/renderer/src/components/chat-input/composables/useAcpMode.ts
src/main/presenter/llmProviderPresenter/providers/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/main/presenter/llmProviderPresenter/providers/*.ts: Each LLM provider must implement the coreStream method following the standardized event interface for tool calling and response streaming
Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation

src/main/presenter/llmProviderPresenter/providers/*.ts: In Provider implementations (src/main/presenter/llmProviderPresenter/providers/*.ts), the coreStream(messages, modelId, temperature, maxTokens) method should perform a single-pass streaming API request for each conversation round without containing multi-turn tool call loop logic
In Provider implementations, handle native tool support by converting MCP tools to Provider format using convertToProviderTools and including them in the API request; for Providers without native function call support, prepare messages using prepareFunctionCallPrompt before making the API call
In Provider implementations, parse Provider-specific data chunks from the streaming response and yield standardized LLMCoreStreamEvent objects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data
In Provider implementations, include helper methods for Provider-specific operations such as formatMessages, convertToProviderTools, parseFunctionCalls, and prepareFunctionCallPrompt

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
src/main/presenter/llmProviderPresenter/index.ts

📄 CodeRabbit inference engine (.cursor/rules/llm-agent-loop.mdc)

src/main/presenter/llmProviderPresenter/index.ts: In src/main/presenter/llmProviderPresenter/index.ts (startStreamCompletion), implement the Agent loop that manages the overall conversation flow, including multiple rounds of LLM calls and tool usage, maintaining conversationMessages history, calling provider.coreStream() on each iteration, and controlling the loop using needContinueConversation and toolCallCount (compared against MAX_TOOL_CALLS)
In src/main/presenter/llmProviderPresenter/index.ts, listen for standardized events yielded by coreStream and handle them accordingly: buffer text content (currentContent), handle tool_call_start/chunk/end events by collecting tool details and calling presenter.mcpPresenter.callTool, send frontend events via eventBus with tool call status, format tool results for the next LLM call, and set needContinueConversation = true
In src/main/presenter/llmProviderPresenter/index.ts, handle reasoning, text, image_data, and usage events by processing and forwarding them through STREAM_EVENTS.RESPONSE events to the frontend
In src/main/presenter/llmProviderPresenter/index.ts, handle stop events by checking stop_reason: if 'tool_use', add the buffered assistant message and prepare for the next loop iteration; otherwise, add the final assistant message and exit the loop

Files:

  • src/main/presenter/llmProviderPresenter/index.ts
**/*Provider**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/provider-guidelines.mdc)

**/*Provider**/index.ts: Output only discriminated union LLMCoreStreamEvent in Provider implementations, do not use single interface with optional fields
Use factory methods createStreamEvent.* to construct events in Provider implementations, avoid direct field pollution
Text events: emit multiple text chunks in arrival order
Reasoning events: reasoning is optional; if provided, ensure it contains the complete chain
Tool call events: strictly follow sequence tool_call_start → tool_call_chunk* → tool_call_end, ensure tool_call_id is required and stable
Stop events: emit stop at stream end with stop_reason value from {tool_use, max_tokens, stop_sequence, error, complete}
Usage events: send usage once before or at stream end with prompt_tokens, completion_tokens, and total_tokens
Rate limit events: send rate_limit event when reaching limit threshold with fields {providerId, qpsLimit, currentQps, queueLength, estimatedWaitTime?}, do not block event channel
Error handling: use error event uniformly to carry error messages, avoid mixing errors into other event fields
Error termination: after fatal error occurs, emit stop event as needed and terminate the stream
Image events: image_data event must provide data (Base64 encoded) and mimeType fields; control single frame size and frequency to avoid blocking
Do not emit AssistantMessageBlock or any UI types from Provider implementations to UI layer
Do not introduce renderer dependencies inside Provider implementations
Every event construction in Provider implementations must use factory functions
Tool call IDs in Provider implementations must be globally unique and stable, with chunks arriving strictly in order
Error scenarios in Provider implementations must have corresponding stop_reason and error message
Provider implementations must emit at least one usage event if the provider has statistics capability
Provide rate_limit events in Provider implementations...

Files:

  • src/main/presenter/llmProviderPresenter/index.ts
🧠 Learnings (26)
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, handle `reasoning`, `text`, `image_data`, and `usage` events by processing and forwarding them through `STREAM_EVENTS.RESPONSE` events to the frontend

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/**/*.ts : Define the standardized `LLMCoreStreamEvent` interface with fields: `type` (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), `content` (for text), `reasoning_content` (for reasoning), `tool_call_id`, `tool_call_name`, `tool_call_arguments_chunk` (for streaming), `tool_call_arguments_complete` (for complete arguments), `error_message`, `usage` object with token counts, `stop_reason` (tool_use | max_tokens | stop_sequence | error | complete), and `image_data` object with Base64-encoded data and mimeType

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:27:39.200Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/provider-guidelines.mdc:0-0
Timestamp: 2025-11-25T05:27:39.200Z
Learning: Applies to **/*Provider**/index.ts : Reasoning events: `reasoning` is optional; if provided, ensure it contains the complete chain

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, listen for standardized events yielded by `coreStream` and handle them accordingly: buffer text content (`currentContent`), handle `tool_call_start/chunk/end` events by collecting tool details and calling `presenter.mcpPresenter.callTool`, send frontend events via `eventBus` with tool call status, format tool results for the next LLM call, and set `needContinueConversation = true`

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, parse Provider-specific data chunks from the streaming response and `yield` standardized `LLMCoreStreamEvent` objects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Implement separation of concerns where `src/main/presenter/llmProviderPresenter/index.ts` manages the Agent loop and conversation history, while Provider files handle LLM API interactions, Provider-specific request/response formatting, tool definition conversion, and native vs non-native tool call mechanisms

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:27:39.200Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/provider-guidelines.mdc:0-0
Timestamp: 2025-11-25T05:27:39.200Z
Learning: Applies to **/*Provider**/index.ts : Text events: emit multiple `text` chunks in arrival order

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, include helper methods for Provider-specific operations such as `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, and `prepareFunctionCallPrompt`

Applied to files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation

Applied to files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, handle native tool support by converting MCP tools to Provider format using `convertToProviderTools` and including them in the API request; for Providers without native function call support, prepare messages using `prepareFunctionCallPrompt` before making the API call

Applied to files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to {src/main/presenter/**/*.ts,src/renderer/**/*.ts} : Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Applied to files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/shared/types/presenters/thread.presenter.d.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/main/**/*.ts : Use the Presenter pattern in the main process for UI coordination

Applied to files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/shared/types/presenters/thread.presenter.d.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/renderer/**/*.ts : Use the `usePresenter.ts` composable for renderer-to-main IPC communication to call presenter methods directly

Applied to files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/shared/types/presenters/thread.presenter.d.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts` (`startStreamCompletion`), implement the Agent loop that manages the overall conversation flow, including multiple rounds of LLM calls and tool usage, maintaining `conversationMessages` history, calling `provider.coreStream()` on each iteration, and controlling the loop using `needContinueConversation` and `toolCallCount` (compared against `MAX_TOOL_CALLS`)

Applied to files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/thread.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/mcpPresenter/**/*.ts : Register new MCP tools in `mcpPresenter/index.ts` after implementing them in `inMemoryServers/`

Applied to files:

  • src/shared/types/presenters/legacy.presenters.d.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/threadPresenter/index.ts
  • src/shared/types/presenters/thread.presenter.d.ts
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Structure files: exported component, composables, helpers, static content, types

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
📚 Learning: 2025-11-25T05:27:45.545Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:27:45.545Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx,js,jsx} : Use the Composition API for better code organization and reusability in Vue.js applications

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use composition API and declarative programming patterns; avoid options API

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.{ts,vue} : Use Iconify/Vue for icon implementation

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, handle `stop` events by checking `stop_reason`: if `'tool_use'`, add the buffered assistant message and prepare for the next loop iteration; otherwise, add the final assistant message and exit the loop

Applied to files:

  • src/main/presenter/threadPresenter/handlers/llmEventHandler.ts
  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Each LLM provider must implement the `coreStream` method following the standardized event interface for tool calling and response streaming

Applied to files:

  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/renderer/src/components/**/*.vue : Vue component files must use PascalCase naming (e.g., `ChatInput.vue`)

Applied to files:

  • src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations (`src/main/presenter/llmProviderPresenter/providers/*.ts`), the `coreStream(messages, modelId, temperature, maxTokens)` method should perform a *single-pass* streaming API request for each conversation round without containing multi-turn tool call loop logic

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/index.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/**/*.ts : Use EventBus for inter-process communication events

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to src/main/**/*.ts : Use EventBus pattern for inter-process communication within the main process to decouple modules

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
🧬 Code graph analysis (4)
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (2)
src/main/presenter/configPresenter/providerDbLoader.ts (1)
  • now (126-128)
src/shared/types/core/llm-events.ts (1)
  • createStreamEvent (100-154)
src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts (2)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (1)
  • warmupProcess (165-236)
src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (1)
  • warmupProcess (411-420)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (5)
src/shared/types/presenters/agent-provider.d.ts (1)
  • AgentProcessHandle (16-24)
src/shared/types/presenters/legacy.presenters.d.ts (1)
  • AcpAgentConfig (730-736)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/main/events.ts (1)
  • ACP_WORKSPACE_EVENTS (237-242)
src/renderer/src/events.ts (1)
  • ACP_WORKSPACE_EVENTS (178-183)
src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (3)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/main/events.ts (1)
  • ACP_WORKSPACE_EVENTS (237-242)
src/renderer/src/events.ts (1)
  • ACP_WORKSPACE_EVENTS (178-183)
⏰ 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)
🔇 Additional comments (28)
src/shared/types/presenters/legacy.presenters.d.ts (2)

883-894: LGTM - Well-structured ACP process management API additions.

The new methods are properly typed with appropriate return types. The getAcpProcessModes correctly returns undefined when no process exists, and the mode structure includes all necessary fields (id, name, description).


1024-1035: Consistent API mirroring in IThreadPresenter.

The ACP process management methods are correctly mirrored from ILlmProviderPresenter, maintaining API consistency across the presenter layer.

src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (6)

21-35: Well-designed state model for ACP process lifecycle.

The addition of state: 'warmup' | 'bound' with boundConversationId and mode tracking provides a clean separation between pre-warmed processes and conversation-bound ones. The optional mode fields allow graceful handling when modes aren't available.


140-152: Clean workdir resolution with sensible fallback.

The resolveWorkdir helper properly trims and validates the workdir, falling back to a safe temp directory when not provided.


164-236: Robust warmup process management with proper locking.

The warmup logic correctly:

  • Acquires per-agent locks to prevent race conditions
  • Reuses existing warmup handles when possible
  • Awaits in-flight warmup promises
  • Cleans up stale handles before spawning new ones

The fire-and-forget fetchProcessModes with .catch() is appropriate since mode fetching is non-critical.


319-363: Verify handle state before binding.

The bind logic has good defensive checks for state and liveliness. However, when multiple warmup handles exist for the same agent, the selection logic prioritizes matching workdir but falls back to any available warmup handle, which could bind a process with a different workdir than intended.

Consider adding a warning or stricter check when binding a handle whose workdir differs from the requested one:

     const handle =
       warmupHandles.find(([, candidate]) => candidate.workdir === resolvedWorkdir)?.[1] ??
       warmupHandles[0]?.[1]
     if (!handle) {
       console.warn(`[ACP] No warmup handle to bind for agent ${agentId}`)
       return
     }
+    if (handle.workdir !== resolvedWorkdir) {
+      console.warn(
+        `[ACP] Binding handle with different workdir: requested=${resolvedWorkdir}, actual=${handle.workdir}`
+      )
+    }

884-930: Mode fetching creates temporary session - verify cleanup.

The fetchProcessModes method creates a real session via newSession() to retrieve available modes, then cancels it. This is a reasonable approach, but ensure the agent implementation properly handles session cancellation without side effects.

The session is properly cleaned up on lines 916-926, but the try-catch for cancel only logs a warning. If cancellation fails, the session may remain active on the agent side. Consider tracking whether cleanup succeeded for debugging purposes.


1054-1058: Comprehensive process liveliness check.

Good addition of signalCode === null check alongside exitCode === null to ensure the process is truly alive.

src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (1)

126-139: Reasoning content now includes temporal boundaries.

Good addition of reasoning_time with start and end timestamps. Using the same timestamp for both is correct since each emitAsText call represents a point-in-time emission. The accumulated reasoning duration can be computed by the consumer from the first and last block timestamps.

src/main/presenter/threadPresenter/handlers/llmEventHandler.ts (1)

188-217: Improved reasoning block timing - per-block rather than global.

The changes make reasoning timing more accurate:

  • New blocks now use currentTime as their start time (the moment they're created)
  • Existing blocks without reasoning_time use their own timestamp as the start

This is more correct than using state.reasoningStartTime, which represents when reasoning first started globally. Each block should track its own timing.

src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts (3)

22-57: Good deduplication for warmup requests.

The lastWarmupKey pattern effectively prevents redundant warmup calls. The key format ${agentId}::${trimmed} correctly matches the backend's warmup key structure.


100-119: LGTM - Warmup correctly triggered after pending workdir sync.

The warmup is properly called after the workdir is successfully persisted, ensuring the process is ready before the user starts interacting.


127-133: Correct cache invalidation on agent change.

Clearing lastWarmupKey when the agent changes ensures that switching agents will allow a fresh warmup, even if the workdir is the same.

src/renderer/src/components/chat-input/ChatInput.vue (2)

196-200: Mode switcher now visible in 'newThread' variant.

This change extends the mode switcher visibility from only 'chat' to include 'newThread'. This aligns with the PR objective of allowing mode selection at session creation.


625-630: LGTM: Workdir wiring to acpMode composable.

Passing acpWorkdir.workdir to the useAcpMode composable correctly establishes the dependency flow needed for workdir-aware mode management.

src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts (4)

136-143: Defensive unbinding during session cleanup.

Good addition of try-catch around unbindProcess to prevent cleanup failures from blocking session teardown. The warning log provides observability without failing the operation.


166-171: Proper lifecycle binding with error recovery.

The binding is correctly placed after obtaining the connection handle, and the error path properly unbinds before re-throwing to prevent leaked bindings.


185-214: Mode preference application with fallback handling.

The logic correctly:

  1. Prefers handle.currentModeId (warmup preference) over session default
  2. Validates mode against available modes before applying
  3. Falls back gracefully on failure

One minor observation: Line 212 reassigns currentModeId on failure, but this doesn't update handle.currentModeId. This is acceptable since the returned session will have the correct currentModeId, but worth noting for consistency.


275-286: Mode normalization with multi-source fallback.

The logic properly handles mode derivation:

  1. Prefers handle.currentModeId (preferred mode from warmup)
  2. Falls back to response mode if preferred is invalid
  3. Further falls back to first available mode

The validation check on Line 280 ensures the preferred mode exists in available modes before using it.

src/main/presenter/llmProviderPresenter/index.ts (1)

482-511: New ACP process management methods with graceful degradation.

All three methods follow a consistent pattern:

  • Obtain ACP provider via getAcpProviderInstance()
  • Gracefully handle missing provider (return early or return undefined)
  • Delegate to provider methods

This pattern ensures the presenter remains usable even when ACP is unavailable.

src/shared/types/presenters/llmprovider.presenter.d.ts (1)

230-241: Interface declarations for ACP process management APIs.

The new method signatures are properly typed and align with the implementations in LLMProviderPresenter. The getAcpProcessModes return type correctly uses undefined rather than null to match the implementation.

src/shared/types/presenters/thread.presenter.d.ts (1)

180-191: ThreadPresenter interface extension for ACP process management.

The new method signatures correctly mirror those in ILlmProviderPresenter, maintaining consistency across the presenter layer. This enables renderer code to access ACP process management through ThreadPresenter.

src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (3)

350-355: Extended SESSION_MODES_READY payload for context matching.

Adding agentId and workdir to the event payload enables the renderer to match modes events in both conversation and pre-conversation (warmup) contexts. This supports the new workdir-scoped mode management.


411-446: New ACP process management methods.

Well-implemented methods with:

  • Proper agent validation before operations
  • Error handling with warning logs that don't propagate failures
  • getProcessModes returns synchronously which is appropriate for cached state

Note: getProcessModes returns undefined for both "no agent" and "no modes" cases. This is acceptable as callers should check for modes presence regardless.


745-755: Session mode synchronization to handle and renderer.

The logic correctly:

  1. Updates the process handle's currentModeId only when bound to the same conversation
  2. Emits SESSION_MODES_READY to notify renderer of mode changes

The conditional update on Lines 746-748 prevents mode leakage between conversations using the same agent process.

src/main/presenter/threadPresenter/index.ts (1)

765-784: ThreadPresenter forwarding methods for ACP process management.

Clean delegation to llmProviderPresenter following the established Presenter pattern. No additional logic is needed here as the underlying methods handle validation and errors appropriately.

src/renderer/src/components/chat-input/composables/useAcpMode.ts (2)

73-97: Warmup modes loading with deduplication.

Good implementation:

  • Uses lastWarmupModesKey to prevent redundant API calls for same agent/workdir
  • Early returns protect against unnecessary loads
  • Proper try-catch with warning log

132-159: Extended mode readiness handler with context matching.

The matching logic handles both scenarios:

  1. Direct conversation match (existing session)
  2. Agent + workdir match (warmup context)

The pendingPreferredMode application on Lines 156-158 ensures the user's pre-selected mode persists through session creation.

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: 0

🧹 Nitpick comments (1)
.cursor/plans/acp-debug-dialog_71231f69.plan.md (1)

22-63: Consider adding implementation details for concurrency, error resilience, and history management.

The plan covers the core UI structure and feature set well. A few areas could benefit from more specificity to guide implementation:

  1. Concurrency & Serialization (section 4): The mention of "queue" to avoid races is good, but consider documenting whether requests are serialized per ACP process instance or globally, and how pending requests are tracked/cancelled if the dialog closes.

  2. Error Recovery (section 4): What happens if the stdio pipe breaks during a request or while streaming a response? Should the UI retry, timeout, or just display an error?

  3. Response History (section 3): No mention of size limits, pagination, or auto-cleanup strategy. For long debug sessions, history could grow unbounded. Consider specifying a max-entries policy or session-based retention.

  4. Testing Coverage: The test section (lines 62–63) lists scenarios but is brief. Consider adding edge cases (e.g., malformed JSON, timeout, process crash, rapid send/cancel).

Would you like me to generate expanded detail sections for concurrency guarantees, error handling, and test cases?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a79743 and 4edc042.

📒 Files selected for processing (1)
  • .cursor/plans/acp-debug-dialog_71231f69.plan.md (1 hunks)
⏰ 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)
🔇 Additional comments (1)
.cursor/plans/acp-debug-dialog_71231f69.plan.md (1)

1-20: Well‑structured planning with clear task definitions.

The frontmatter provides actionable todos with distinct IDs and pending status tracking, which is excellent for tracking implementation progress. The task decomposition (entry-overlay, methods-json, response-view, state-guard, manual-test) is granular enough to guide development.

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: 6

🧹 Nitpick comments (5)
src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (1)

592-593: Unchecked type assertion for mcpServers.

The cast payloadOverrides.mcpServers as schema.McpServer[] doesn't validate that array elements conform to the schema. Malformed payloads could cause runtime errors downstream.

Consider adding validation or using a safer approach:

-            if (Array.isArray(payloadOverrides.mcpServers)) {
-              body.mcpServers = payloadOverrides.mcpServers as schema.McpServer[]
-            }
+            if (Array.isArray(payloadOverrides.mcpServers)) {
+              // Trust user-provided debug payload; downstream validation expected
+              body.mcpServers = payloadOverrides.mcpServers as schema.McpServer[]
+            }

At minimum, add a comment clarifying that this is debug-only functionality where the user takes responsibility for payload correctness.

src/renderer/settings/components/AcpDebugDialog.vue (4)

211-212: Potential memory leak: seenIds Set is not cleared on agent change.

The seenIds Set is declared at module scope and only cleared when clearEvents() is called or when the dialog opens/closes. If the same dialog instance is reused with a different agentId, stale IDs could cause event deduplication issues.

Consider watching for agentId changes:

watch(
  () => props.agentId,
  () => {
    clearEvents()
    processReady.value = false
    debugSessionId.value = createDebugSessionId()
  }
)

393-395: Silent catch in syncWorkdirIntoPayload may hide payload issues.

While the comment explains the intention, silently swallowing JSON parse errors could make debugging difficult for users if they accidentally corrupt their payload.

Consider logging in development mode or showing a subtle indicator:

} catch (e) {
  // JSON parse errors during auto-sync are expected during editing
  console.debug('[AcpDebugDialog] syncWorkdirIntoPayload: parse error (expected during editing)')
}

440-443: Uncaught JSON parse error could throw.

The parsePayload function can throw on invalid JSON, but only handleSend catches it. If parsePayload is called elsewhere in the future without a try-catch, it could cause unhandled exceptions.

Consider returning a result tuple or using a try-catch internally:

const parsePayload = (): { ok: true; data: Record<string, unknown> | undefined } | { ok: false; error: Error } => {
  if (!payloadText.value.trim()) return { ok: true, data: undefined }
  try {
    return { ok: true, data: JSON.parse(payloadText.value) }
  } catch (error) {
    return { ok: false, error: error instanceof Error ? error : new Error(String(error)) }
  }
}

44-57: Keyboard accessibility: method buttons lack focus indicators.

The method selection buttons use <button> elements which is good for accessibility, but the focus states are not clearly defined in the styling. Users navigating with keyboard may not see which button is focused.

Add focus-visible styling:

 :class="
   selectedMethod === method.value
     ? 'border-primary bg-primary/5'
-    : 'border-border hover:border-primary/60'
+    : 'border-border hover:border-primary/60 focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2'
 "
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4edc042 and ff6b1d3.

📒 Files selected for processing (21)
  • .vscode/settings.json (1 hunks)
  • src/main/events.ts (1 hunks)
  • src/main/presenter/llmProviderPresenter/index.ts (3 hunks)
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (5 hunks)
  • src/renderer/settings/components/AcpDebugDialog.vue (1 hunks)
  • src/renderer/settings/components/AcpSettings.vue (6 hunks)
  • src/renderer/src/events.ts (1 hunks)
  • src/renderer/src/i18n/da-DK/settings.json (1 hunks)
  • src/renderer/src/i18n/en-US/settings.json (1 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (1 hunks)
  • src/renderer/src/i18n/fr-FR/settings.json (1 hunks)
  • src/renderer/src/i18n/he-IL/settings.json (1 hunks)
  • src/renderer/src/i18n/ja-JP/settings.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/settings.json (1 hunks)
  • src/renderer/src/i18n/pt-BR/settings.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-CN/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-HK/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-TW/settings.json (1 hunks)
  • src/shared/types/presenters/legacy.presenters.d.ts (3 hunks)
  • src/shared/types/presenters/llmprovider.presenter.d.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .vscode/settings.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/presenter/llmProviderPresenter/index.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
🧰 Additional context used
📓 Path-based instructions (30)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Files:

  • src/main/events.ts
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
  • src/shared/types/presenters/llmprovider.presenter.d.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and maintain strict TypeScript type checking for all files

**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs

Files:

  • src/main/events.ts
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
src/main/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use EventBus from src/main/eventbus.ts for main-to-renderer communication, broadcasting events via mainWindow.webContents.send()

src/main/**/*.ts: Use EventBus pattern for inter-process communication within the main process to decouple modules
Use Electron's built-in APIs for file system and native dialogs instead of Node.js or custom implementations

src/main/**/*.ts: Electron main process code belongs in src/main/ with presenters in presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider) and eventbus.ts for app events
Use the Presenter pattern in the main process for UI coordination

Files:

  • src/main/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits

Files:

  • src/main/events.ts
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

Write logs and comments in English

Files:

  • src/main/events.ts
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
src/**/*

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

New features should be developed in the src directory

Files:

  • src/main/events.ts
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/shared/types/presenters/llmprovider.presenter.d.ts
  • src/renderer/src/i18n/zh-CN/settings.json
src/main/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Main process code for Electron should be placed in src/main

Files:

  • src/main/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
src/**/*.{ts,tsx,vue,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with single quotes, no semicolons, and 100 character width

Files:

  • src/main/events.ts
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
  • src/shared/types/presenters/llmprovider.presenter.d.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use OxLint for linting JavaScript and TypeScript files

Files:

  • src/main/events.ts
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names

Files:

  • src/main/events.ts
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use EventBus for inter-process communication events

Files:

  • src/main/events.ts
  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
src/renderer/src/i18n/**/*.json

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/i18n/**/*.json: Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')
Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)

Files:

  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
src/renderer/**

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Use lowercase with dashes for directories (e.g., components/auth-wizard)

Files:

  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/events.ts
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
src/renderer/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use the usePresenter.ts composable for renderer-to-main IPC communication to call presenter methods directly

Files:

  • src/renderer/src/events.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Files:

  • src/renderer/src/events.ts
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
src/renderer/src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*.{vue,ts,tsx}: All user-facing strings must use i18n keys with vue-i18n framework in the renderer
Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Use the dynamic locale.value property to switch languages at runtime
Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system

Files:

  • src/renderer/src/events.ts
src/renderer/**/*.{vue,js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Renderer process code should be placed in src/renderer (Vue 3 application)

Files:

  • src/renderer/src/events.ts
  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability in Vue.js applications
Implement proper state management with Pinia in Vue.js applications
Utilize Vue Router for navigation and route management in Vue.js applications
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/events.ts
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Write concise, technical TypeScript code with accurate examples
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Avoid enums; use const objects instead
Use arrow functions for methods and computed properties
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements

Vue 3 app code in src/renderer/src should be organized into components/, stores/, views/, i18n/, lib/ directories with shell UI in src/renderer/shell/

Files:

  • src/renderer/src/events.ts
  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Use TypeScript for all code; prefer types over interfaces

Files:

  • src/renderer/src/events.ts
src/renderer/**/*.{ts,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching
Leverage ref, reactive, and computed for reactive state management
Use provide/inject for dependency injection when appropriate
Use Iconify/Vue for icon implementation

Files:

  • src/renderer/src/events.ts
  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use TypeScript with Vue 3 Composition API for the renderer application
All user-facing strings must use vue-i18n keys in src/renderer/src/i18n

Files:

  • src/renderer/src/events.ts
src/main/presenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Organize core business logic into dedicated Presenter classes, with one presenter per functional domain

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
src/main/presenter/llmProviderPresenter/providers/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/main/presenter/llmProviderPresenter/providers/*.ts: Each LLM provider must implement the coreStream method following the standardized event interface for tool calling and response streaming
Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation

src/main/presenter/llmProviderPresenter/providers/*.ts: In Provider implementations (src/main/presenter/llmProviderPresenter/providers/*.ts), the coreStream(messages, modelId, temperature, maxTokens) method should perform a single-pass streaming API request for each conversation round without containing multi-turn tool call loop logic
In Provider implementations, handle native tool support by converting MCP tools to Provider format using convertToProviderTools and including them in the API request; for Providers without native function call support, prepare messages using prepareFunctionCallPrompt before making the API call
In Provider implementations, parse Provider-specific data chunks from the streaming response and yield standardized LLMCoreStreamEvent objects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data
In Provider implementations, include helper methods for Provider-specific operations such as formatMessages, convertToProviderTools, parseFunctionCalls, and prepareFunctionCallPrompt

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
src/main/presenter/llmProviderPresenter/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/llm-agent-loop.mdc)

Define the standardized LLMCoreStreamEvent interface with fields: type (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), content (for text), reasoning_content (for reasoning), tool_call_id, tool_call_name, tool_call_arguments_chunk (for streaming), tool_call_arguments_complete (for complete arguments), error_message, usage object with token counts, stop_reason (tool_use | max_tokens | stop_sequence | error | complete), and image_data object with Base64-encoded data and mimeType

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.vue: Use Vue 3 Composition API for all components instead of Options API
Use Tailwind CSS with scoped styles for component styling

Files:

  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

src/renderer/**/*.vue: All user-facing strings must use i18n keys via vue-i18n for internationalization
Ensure proper error handling and loading states in all UI components
Implement responsive design using Tailwind CSS utilities for all UI components

src/renderer/**/*.vue: Use composition API and declarative programming patterns; avoid options API
Structure files: exported component, composables, helpers, static content, types
Use PascalCase for component names (e.g., AuthWizard.vue)
Use Vue 3 with TypeScript, leveraging defineComponent and PropType
Use template syntax for declarative rendering
Use Shadcn Vue, Radix Vue, and Tailwind for components and styling
Implement responsive design with Tailwind CSS; use a mobile-first approach
Use Suspense for asynchronous components
Use <script setup> syntax for concise component definitions
Prefer 'lucide:' icon family as the primary choice for Iconify icons
Import Icon component from '@iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'

Files:

  • src/renderer/settings/components/AcpDebugDialog.vue
  • src/renderer/settings/components/AcpSettings.vue
src/shared/**/*.d.ts

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Define type definitions in shared/*.d.ts files for objects exposed by the main process to the renderer process

Files:

  • src/shared/types/presenters/llmprovider.presenter.d.ts
src/shared/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Shared type definitions and utilities between main and renderer processes should be placed in src/shared

Files:

  • src/shared/types/presenters/llmprovider.presenter.d.ts
src/shared/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Shared types and utilities should be placed in src/shared/

Files:

  • src/shared/types/presenters/llmprovider.presenter.d.ts
🧠 Learnings (21)
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)

Applied to files:

  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')

Applied to files:

  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/he-IL/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/ru-RU/settings.json
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to **/*.{ts,tsx,js,jsx,vue} : Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Applied to files:

  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/zh-CN/settings.json
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/**/*.ts : Use EventBus for inter-process communication events

Applied to files:

  • src/renderer/src/events.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Implement separation of concerns where `src/main/presenter/llmProviderPresenter/index.ts` manages the Agent loop and conversation history, while Provider files handle LLM API interactions, Provider-specific request/response formatting, tool definition conversion, and native vs non-native tool call mechanisms

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, include helper methods for Provider-specific operations such as `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, and `prepareFunctionCallPrompt`

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, handle native tool support by converting MCP tools to Provider format using `convertToProviderTools` and including them in the API request; for Providers without native function call support, prepare messages using `prepareFunctionCallPrompt` before making the API call

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, listen for standardized events yielded by `coreStream` and handle them accordingly: buffer text content (`currentContent`), handle `tool_call_start/chunk/end` events by collecting tool details and calling `presenter.mcpPresenter.callTool`, send frontend events via `eventBus` with tool call status, format tool results for the next LLM call, and set `needContinueConversation = true`

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts` (`startStreamCompletion`), implement the Agent loop that manages the overall conversation flow, including multiple rounds of LLM calls and tool usage, maintaining `conversationMessages` history, calling `provider.coreStream()` on each iteration, and controlling the loop using `needContinueConversation` and `toolCallCount` (compared against `MAX_TOOL_CALLS`)

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, parse Provider-specific data chunks from the streaming response and `yield` standardized `LLMCoreStreamEvent` objects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/mcpPresenter/**/*.ts : Register new MCP tools in `mcpPresenter/index.ts` after implementing them in `inMemoryServers/`

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to {src/main/presenter/**/*.ts,src/renderer/**/*.ts} : Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/**/*.ts : Define the standardized `LLMCoreStreamEvent` interface with fields: `type` (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), `content` (for text), `reasoning_content` (for reasoning), `tool_call_id`, `tool_call_name`, `tool_call_arguments_chunk` (for streaming), `tool_call_arguments_complete` (for complete arguments), `error_message`, `usage` object with token counts, `stop_reason` (tool_use | max_tokens | stop_sequence | error | complete), and `image_data` object with Base64-encoded data and mimeType

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Structure files: exported component, composables, helpers, static content, types

Applied to files:

  • src/renderer/settings/components/AcpDebugDialog.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use <script setup> syntax for concise component definitions

Applied to files:

  • src/renderer/settings/components/AcpDebugDialog.vue
📚 Learning: 2025-11-25T05:27:45.545Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:27:45.545Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx,js,jsx} : Use the Composition API for better code organization and reusability in Vue.js applications

Applied to files:

  • src/renderer/settings/components/AcpDebugDialog.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system

Applied to files:

  • src/renderer/settings/components/AcpSettings.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files

Applied to files:

  • src/renderer/settings/components/AcpSettings.vue
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Each LLM provider must implement the `coreStream` method following the standardized event interface for tool calling and response streaming

Applied to files:

  • src/shared/types/presenters/llmprovider.presenter.d.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, handle `reasoning`, `text`, `image_data`, and `usage` events by processing and forwarding them through `STREAM_EVENTS.RESPONSE` events to the frontend

Applied to files:

  • src/shared/types/presenters/llmprovider.presenter.d.ts
🧬 Code graph analysis (3)
src/main/events.ts (1)
src/renderer/src/events.ts (1)
  • ACP_DEBUG_EVENTS (185-187)
src/renderer/src/events.ts (1)
src/main/events.ts (1)
  • ACP_DEBUG_EVENTS (244-246)
src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (6)
src/shared/types/presenters/legacy.presenters.d.ts (3)
  • AcpDebugRequest (709-717)
  • AcpDebugRunResult (730-735)
  • AcpDebugEventEntry (719-728)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/main/events.ts (2)
  • ACP_DEBUG_EVENTS (244-246)
  • ACP_WORKSPACE_EVENTS (237-242)
src/main/presenter/llmProviderPresenter/agent/acpCapabilities.ts (1)
  • buildClientCapabilities (14-31)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (1)
  • resolveWorkdir (147-152)
src/main/presenter/llmProviderPresenter/agent/acpSessionPersistence.ts (1)
  • resolveWorkdir (74-79)
⏰ 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). (5)
  • GitHub Check: build-linux (x64)
  • GitHub Check: build-mac (arm64)
  • GitHub Check: build-mac (x64)
  • GitHub Check: build-windows (x64)
  • GitHub Check: build-check (x64)
🔇 Additional comments (22)
src/renderer/src/i18n/zh-HK/settings.json (1)

974-1015: LGTM.

Key set matches en-US; wording and placeholders look good for zh-HK.

src/renderer/src/i18n/zh-TW/settings.json (1)

974-1015: LGTM.

acp.debug keys and translations look consistent and clear for zh-TW.

src/renderer/src/i18n/en-US/settings.json (1)

948-989: Fix pt-BR eventCount placeholder: change {contar} to {count} for consistency.

The en-US acp.debug baseline is complete and correct. All 12 locales have identical key structures across all 37 keys (verified). However, pt-BR has a critical bug: the eventCount value uses {contar} instead of {count}, breaking template interpolation. All other 11 locales correctly preserve the {count} placeholder. Fix pt-BR's eventCount in src/renderer/src/i18n/pt-BR/settings.json from "{contar} itens" to "{count} itens".

⛔ Skipped due to learnings
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)
src/renderer/src/events.ts (1)

185-187: ACP debug event namespace mirrors main side correctly

ACP_DEBUG_EVENTS.EVENT follows the existing naming convention and matches the main process event, so the renderer can cleanly share this channel. No further changes needed.

src/renderer/src/i18n/he-IL/settings.json (1)

947-989: ACP debug i18n block structure looks consistent

The new settings.acp.debug.* keys mirror the structure used in other locales and keep placeholders ({name}, {count}) consistent. No issues found.

src/main/events.ts (1)

244-246: Main-process ACP debug event added correctly

ACP_DEBUG_EVENTS.EVENT follows the existing event naming pattern and matches the renderer-side constant, providing a clean channel for ACP debug IPC.

src/renderer/src/i18n/ja-JP/settings.json (1)

973-1015: Japanese ACP debug translations added with correct key structure

The settings.acp.debug.* block matches other locales structurally and uses placeholders ({name}, {count}) correctly. Looks good.

src/renderer/settings/components/AcpSettings.vue (1)

121-140: ACP debug dialog integration is clean and consistent

The new debug entry buttons, debugDialogState reactive state, openDebugDialog helper, and <AcpDebugDialog> wiring are all consistent with the existing patterns in this component and correctly use the new settings.acp.debug.entry i18n key. No issues spotted.

Also applies to: 175-230, 275-280, 317-317, 355-359, 579-583

src/renderer/src/i18n/fr-FR/settings.json (1)

973-1015: French ACP debug i18n block matches global structure

The newly added settings.acp.debug.* keys align with other locales and use placeholders ({name}, {count}) correctly. No functional or structural issues found.

src/renderer/src/i18n/zh-CN/settings.json (1)

939-989: zh-CN ACP debug translations provide complete, well-structured key set

The settings.acp.debug.* additions (title, methods, eventKinds, status text, etc.) form a coherent block that other locales mirror, and placeholders are consistent. No issues detected.

src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (7)

417-426: LGTM - warmupProcess method is well implemented.

The method properly validates the agent exists before attempting warmup and handles errors gracefully with a warning log. The early return on missing agent prevents unnecessary process manager calls.


428-438: LGTM - getProcessModes method looks good.

Clean synchronous accessor that properly delegates to processManager and handles the undefined case with nullish coalescing.


440-452: LGTM - setPreferredProcessMode properly handles errors.

Good error handling with informative warning message including agent ID, workdir, and mode ID for debugging.


454-491: Agent lookup and process connection acquisition look correct.

The method properly validates agent existence before proceeding. The isPlainObject helper is well-defined for type narrowing. The pushEvent helper correctly constructs and emits debug events.


749-764: Good error handling in runDebugAction.

The catch block properly extracts error messages, logs the error event with stack trace information, and returns a structured error result. The finally block ensures listener cleanup.


1068-1078: Good addition to sync process handle mode with session mode.

The update to setSessionMode properly synchronizes the mode change to both the process handle (when the conversation is bound) and emits a SESSION_MODES_READY event to notify the renderer. This ensures consistent state across components.


536-552: Remove sessionId extraction from initialize response—InitializeResponse doesn't include this field.

The ACP SDK's InitializeResponse structure does not contain a sessionId field. Session IDs are returned by session/new (NewSessionResponse), not by initialize. The type assertion on line 542 attempts to access a non-existent field, making the conditional check unreachable. Delete lines 542–544 and rely on session/new to populate activeSessionId.

Likely an incorrect or invalid review comment.

src/shared/types/presenters/llmprovider.presenter.d.ts (1)

230-247: LGTM - Interface additions are well-defined and consistent.

The new method signatures properly match the implementation in acpProvider.ts. The Promise<...> return types are appropriate for async operations, and the undefined union type in getAcpProcessModes correctly handles the case where no process exists.

src/renderer/settings/components/AcpDebugDialog.vue (4)

1-40: LGTM - Header section with status indicator and controls.

Good use of conditional styling for the process ready indicator, and the header layout is clean with appropriate spacing. The close button properly emits the update:open event.


88-116: Missing key in v-for loop when combined with v-if.

When v-if and v-for are on sibling elements, ensure the v-for element has a unique key. The current implementation looks correct with :key="event.id", but note that combining v-if on line 83 as a separate element is the right pattern.


547-566: Good lifecycle management for dialog open/close state.

The watcher properly cleans up the editor and events when the dialog closes, and reinitializes state when it opens. The use of nextTick before ensureEditor ensures the DOM is ready.


568-584: LGTM - Proper IPC listener cleanup.

The component correctly registers the IPC listener on mount and removes it on unmount, preventing memory leaks. The editor is also properly disposed.

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: 5

♻️ Duplicate comments (1)
src/renderer/src/i18n/da-DK/settings.json (1)

948-977: Do not localize methods values; keep canonical ACP method paths.

In acp.debug.methods, the values like "session/aflys", "ext/metode", "session/belastning" etc. look localized. These strings are method identifiers, not user-facing labels, and must remain the canonical paths (session/cancel, ext/method, session/load, etc.) to match the debug wiring and other locales.

Suggested fix:

       "methods": {
-        "cancel": "session/aflys",
-        "extMethod": "ext/metode",
-        "extNotification": "ext/meddelelse",
-        "initialize": "initialisere",
-        "loadSession": "session/belastning",
-        "newSession": "session/nyt",
-        "prompt": "session/prompt",
-        "setSessionMode": "session/setMode",
-        "setSessionModel": "session/sætModel"
+        "cancel": "session/cancel",
+        "extMethod": "ext/method",
+        "extNotification": "ext/notification",
+        "initialize": "initialize",
+        "loadSession": "session/load",
+        "newSession": "session/new",
+        "prompt": "session/prompt",
+        "setSessionMode": "session/setMode",
+        "setSessionModel": "session/setModel"
       },

Based on learnings, method identifier values should stay consistent across locales.

🧹 Nitpick comments (5)
src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (2)

417-452: Warmup and process-mode helpers are straightforward and side‑effect safe.

warmupProcess, getProcessModes, and setPreferredProcessMode correctly delegate to AcpProcessManager, guard on missing agents, and log (rather than throw) on failures, which is reasonable for best-effort prewarm/mode hints.

If you want slightly stricter hygiene later, you could normalize workdir (e.g. trim and treat empty string as null/undefined) before passing into the process manager to align with how updateAcpWorkdir resolves directories.


454-777: runDebugAction implementation is solid; consider catching connection errors for structured failures.

The debug runner cleanly:

  • Resolves the agent and process connection.
  • Normalizes payloads per action (initialize, newSession, loadSession, prompt, cancel, setSessionMode, setSessionModel, extMethod, extNotification).
  • Attaches and disposes per‑session notification/permission listeners, emitting AcpDebugEventEntry records and forwarding them over ACP_DEBUG_EVENTS.EVENT.
  • Returns a structured AcpDebugRunResult with status, sessionId, and full events, including an error event on exceptions.

Two small robustness tweaks you might consider:

  1. Wrap getConnection in the same try/catch:

Right now, failures in processManager.getConnection(agent, request.workdir) will throw before the try block, so callers get an exception instead of an AcpDebugRunResult with status: 'error'.

A minimal adjustment:

-    const handle = await this.processManager.getConnection(agent, request.workdir)
-    const connection = handle.connection
-    const events: AcpDebugEventEntry[] = []
+    const events: AcpDebugEventEntry[] = []
+    let handle: Awaited<ReturnType<AcpProcessManager['getConnection']>>
+    try {
+      handle = await this.processManager.getConnection(agent, request.workdir)
+    } catch (error) {
+      const message =
+        error instanceof Error ? error.message : typeof error === 'string' ? error : 'Unknown error'
+      // Optionally push an error event here if you want it visible in the UI
+      return { status: 'error', events, error: message }
+    }
+    const connection = handle.connection
  1. (Optional) Capture initialize/newSession notifications:

If ACP servers ever emit notifications during initialize/newSession, you might want to call attachSession immediately after inferring/receiving a sessionId in those branches, so debug views see the entire lifecycle; today you only attach for loadSession/prompt/cancel/mode setters.

Neither issue is blocking; the current behavior is functionally correct for the debug UI.

src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (3)

255-266: Clarify handle selection precedence.

The method returns the first handle found, which could be either a warmup or bound handle. If both exist for the same agent, the behavior depends on map iteration order. Consider documenting the expected behavior or prioritizing bound handles over warmup handles for more predictable results.


372-392: Consider thread-safety for getProcessModes.

While this is a read-only operation, it could return inconsistent data if called during concurrent handle modifications (warmup, bind, dispose). Consider documenting that callers should handle undefined/stale mode data, or acquiring a read lock if consistency is critical.


884-930: Consider caching modes to avoid repeated session creation.

The method creates a temporary session just to fetch modes, which could be expensive if called frequently. Consider:

  1. Caching modes per agent/workdir after first fetch
  2. Fetching modes during initial connection setup instead of a separate session
  3. Documenting the cost and expected frequency of this operation
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff6b1d3 and e1fafd6.

📒 Files selected for processing (7)
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (10 hunks)
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (5 hunks)
  • src/renderer/src/i18n/da-DK/settings.json (1 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/settings.json (1 hunks)
  • src/renderer/src/i18n/pt-BR/settings.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/settings.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/src/i18n/ru-RU/settings.json
🧰 Additional context used
📓 Path-based instructions (17)
src/renderer/src/i18n/**/*.json

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/i18n/**/*.json: Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')
Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
src/**/*

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

New features should be developed in the src directory

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/renderer/**

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Use lowercase with dashes for directories (e.g., components/auth-wizard)

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and maintain strict TypeScript type checking for all files

**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Organize core business logic into dedicated Presenter classes, with one presenter per functional domain

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/llmProviderPresenter/providers/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/main/presenter/llmProviderPresenter/providers/*.ts: Each LLM provider must implement the coreStream method following the standardized event interface for tool calling and response streaming
Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation

src/main/presenter/llmProviderPresenter/providers/*.ts: In Provider implementations (src/main/presenter/llmProviderPresenter/providers/*.ts), the coreStream(messages, modelId, temperature, maxTokens) method should perform a single-pass streaming API request for each conversation round without containing multi-turn tool call loop logic
In Provider implementations, handle native tool support by converting MCP tools to Provider format using convertToProviderTools and including them in the API request; for Providers without native function call support, prepare messages using prepareFunctionCallPrompt before making the API call
In Provider implementations, parse Provider-specific data chunks from the streaming response and yield standardized LLMCoreStreamEvent objects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data
In Provider implementations, include helper methods for Provider-specific operations such as formatMessages, convertToProviderTools, parseFunctionCalls, and prepareFunctionCallPrompt

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
src/main/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use EventBus from src/main/eventbus.ts for main-to-renderer communication, broadcasting events via mainWindow.webContents.send()

src/main/**/*.ts: Use EventBus pattern for inter-process communication within the main process to decouple modules
Use Electron's built-in APIs for file system and native dialogs instead of Node.js or custom implementations

src/main/**/*.ts: Electron main process code belongs in src/main/ with presenters in presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider) and eventbus.ts for app events
Use the Presenter pattern in the main process for UI coordination

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

Write logs and comments in English

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/llmProviderPresenter/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/llm-agent-loop.mdc)

Define the standardized LLMCoreStreamEvent interface with fields: type (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), content (for text), reasoning_content (for reasoning), tool_call_id, tool_call_name, tool_call_arguments_chunk (for streaming), tool_call_arguments_complete (for complete arguments), error_message, usage object with token counts, stop_reason (tool_use | max_tokens | stop_sequence | error | complete), and image_data object with Base64-encoded data and mimeType

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Main process code for Electron should be placed in src/main

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx,vue,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with single quotes, no semicolons, and 100 character width

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use OxLint for linting JavaScript and TypeScript files

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use EventBus for inter-process communication events

Files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
🧠 Learnings (14)
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)

Applied to files:

  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/pt-BR/settings.json
  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')

Applied to files:

  • src/renderer/src/i18n/da-DK/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Implement separation of concerns where `src/main/presenter/llmProviderPresenter/index.ts` manages the Agent loop and conversation history, while Provider files handle LLM API interactions, Provider-specific request/response formatting, tool definition conversion, and native vs non-native tool call mechanisms

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, include helper methods for Provider-specific operations such as `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, and `prepareFunctionCallPrompt`

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, handle native tool support by converting MCP tools to Provider format using `convertToProviderTools` and including them in the API request; for Providers without native function call support, prepare messages using `prepareFunctionCallPrompt` before making the API call

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, listen for standardized events yielded by `coreStream` and handle them accordingly: buffer text content (`currentContent`), handle `tool_call_start/chunk/end` events by collecting tool details and calling `presenter.mcpPresenter.callTool`, send frontend events via `eventBus` with tool call status, format tool results for the next LLM call, and set `needContinueConversation = true`

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, parse Provider-specific data chunks from the streaming response and `yield` standardized `LLMCoreStreamEvent` objects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to {src/main/presenter/**/*.ts,src/renderer/**/*.ts} : Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/**/*.ts : Define the standardized `LLMCoreStreamEvent` interface with fields: `type` (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), `content` (for text), `reasoning_content` (for reasoning), `tool_call_id`, `tool_call_name`, `tool_call_arguments_chunk` (for streaming), `tool_call_arguments_complete` (for complete arguments), `error_message`, `usage` object with token counts, `stop_reason` (tool_use | max_tokens | stop_sequence | error | complete), and `image_data` object with Base64-encoded data and mimeType

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts` (`startStreamCompletion`), implement the Agent loop that manages the overall conversation flow, including multiple rounds of LLM calls and tool usage, maintaining `conversationMessages` history, calling `provider.coreStream()` on each iteration, and controlling the loop using `needContinueConversation` and `toolCallCount` (compared against `MAX_TOOL_CALLS`)

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations (`src/main/presenter/llmProviderPresenter/providers/*.ts`), the `coreStream(messages, modelId, temperature, maxTokens)` method should perform a *single-pass* streaming API request for each conversation round without containing multi-turn tool call loop logic

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/**/*.ts : Use EventBus for inter-process communication events

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to src/main/**/*.ts : Use EventBus pattern for inter-process communication within the main process to decouple modules

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
🧬 Code graph analysis (2)
src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (5)
src/shared/types/presenters/legacy.presenters.d.ts (3)
  • AcpDebugRequest (709-717)
  • AcpDebugRunResult (730-735)
  • AcpDebugEventEntry (719-728)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/renderer/src/events.ts (2)
  • ACP_DEBUG_EVENTS (185-187)
  • ACP_WORKSPACE_EVENTS (178-183)
src/main/events.ts (2)
  • ACP_DEBUG_EVENTS (244-246)
  • ACP_WORKSPACE_EVENTS (237-242)
src/main/presenter/llmProviderPresenter/agent/acpCapabilities.ts (1)
  • buildClientCapabilities (14-31)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (3)
src/main/presenter/llmProviderPresenter/agent/types.ts (1)
  • AgentProcessHandle (9-9)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/main/events.ts (1)
  • ACP_WORKSPACE_EVENTS (237-242)
⏰ 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)
🔇 Additional comments (16)
src/renderer/src/i18n/ko-KR/settings.json (1)

974-1014: ACP debug block looks consistent and technically safe.

Keys match other locales, placeholders (e.g. {count}) are correct, and methods keep canonical English paths, so the debug UI should interoperate correctly across languages.

Based on learnings, the key structure is consistent across locales.

src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (1)

350-360: SESSION_MODES_READY payload enrichment looks correct.

Including agentId and workdir in ACP_WORKSPACE_EVENTS.SESSION_MODES_READY (both from coreStream and setSessionMode) matches the renderer-side event shape and gives the workspace enough context to present and persist per-agent/per-workdir modes.

Based on learnings, this keeps IPC event contracts coherent between main and renderer.

Also applies to: 1077-1087

src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (14)

21-22: LGTM!

The EventBus imports are correctly added to support the new mode notification feature.


24-35: LGTM!

The interface extensions properly capture the new warmup/bound lifecycle states and mode data. The field types are well-defined and appropriately optional.


74-74: LGTM!

The new maps for tracking bound handles and preferred modes are correctly initialized and support the enhanced lifecycle management.

Also applies to: 83-83


140-142: LGTM!

The simplified delegation to warmupProcess maintains backward compatibility while supporting the new lifecycle model.


147-159: LGTM!

Both helper methods are well-scoped with clear responsibilities. The workdir resolution properly handles edge cases.


268-287: LGTM!

The deduplication logic correctly handles potential overlaps between warmup and bound handles.


289-300: LGTM!

The release logic properly acquires locks, disposes all agent handles, and uses Promise.allSettled to ensure all disposal attempts complete.


302-317: LGTM!

The shutdown logic comprehensively cleans up all resources including the new boundHandles map and ensures all agents are released.


445-586: LGTM!

The spawn process enhancements properly handle mode initialization, timeout extension for slow agents, and cleanup on exit. The mode parsing includes appropriate fallbacks for missing name/description fields.


932-942: LGTM!

The EventBus integration follows coding guidelines and properly broadcasts mode availability to all renderer windows.

Based on coding guidelines.


944-997: LGTM!

All helper methods are well-implemented with clear responsibilities and appropriate error handling.


999-1017: LGTM!

The bound handles cleanup is correctly integrated into the session cleanup logic.


1048-1052: LGTM!

The formatting change improves readability without altering the logic.


319-363: Critical: Missing lock protection in bindProcess.

The method modifies both handles and boundHandles maps without acquiring the agent lock. This could cause race conditions if bindProcess is called concurrently with warmupProcess, release, or another bindProcess call. The handle could be disposed or reused while being bound.

Minor: Unawaited async disposal.

Line 343 calls disposeHandle without awaiting, which could result in incomplete cleanup before the method returns. Consider using await or void to make the fire-and-forget intent explicit.

Apply this diff to add lock protection:

-  bindProcess(agentId: string, conversationId: string, workdir?: string): void {
+  async bindProcess(agentId: string, conversationId: string, workdir?: string): Promise<void> {
     const resolvedWorkdir = this.resolveWorkdir(workdir)
+    const releaseLock = await this.acquireAgentLock(agentId)
+    try {
       // Prefer warmup handle matching requested workdir if provided
       const warmupHandles = Array.from(this.handles.entries()).filter(
         ([, handle]) =>
           handle.agentId === agentId &&
           handle.state === 'warmup' &&
           (!workdir || !handle.workdir || handle.workdir === resolvedWorkdir)
       )
       const handle =
         warmupHandles.find(([, candidate]) => candidate.workdir === resolvedWorkdir)?.[1] ??
         warmupHandles[0]?.[1]
       if (!handle) {
         console.warn(`[ACP] No warmup handle to bind for agent ${agentId}`)
         return
       }
       // ... rest of validation and binding logic ...
+    } finally {
+      releaseLock()
+    }
   }

Likely an incorrect or invalid review comment.

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: 2

♻️ Duplicate comments (1)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (1)

238-253: Preferred mode update works; optional: align with locking pattern to avoid subtle ordering issues.

setPreferredMode writes preferredModes and updates any existing warmup handle, while warmupProcess reads from preferredModes and calls applyPreferredMode. This is functionally fine in Node’s single‑threaded model, but it’s the only place where shared agent state is updated without going through acquireAgentLock, which may lead to surprising ordering (e.g., a long‑running warmup re‑applying an older preference after a newer setPreferredMode call).

If you want fully serialized agent‑level state transitions (matching warmupProcess, release, and unbindProcess), consider wrapping setPreferredMode in the same lock:

-  async setPreferredMode(agent: AcpAgentConfig, workdir: string, modeId: string): Promise<void> {
-    const resolvedWorkdir = this.resolveWorkdir(workdir)
-    const warmupKey = this.getWarmupKey(agent.id, resolvedWorkdir)
-    this.preferredModes.set(warmupKey, modeId)
-
-    // Apply to existing warmup handle if available
-    const existingWarmup = this.findReusableHandle(agent.id, resolvedWorkdir)
-    if (existingWarmup && this.isHandleAlive(existingWarmup)) {
-      existingWarmup.currentModeId = modeId
-      this.notifyModesReady(existingWarmup)
-    }
-  }
+  async setPreferredMode(agent: AcpAgentConfig, workdir: string, modeId: string): Promise<void> {
+    const resolvedWorkdir = this.resolveWorkdir(workdir)
+    const warmupKey = this.getWarmupKey(agent.id, resolvedWorkdir)
+
+    const releaseLock = await this.acquireAgentLock(agent.id)
+    try {
+      this.preferredModes.set(warmupKey, modeId)
+
+      const existingWarmup = this.findReusableHandle(agent.id, resolvedWorkdir)
+      if (existingWarmup && this.isHandleAlive(existingWarmup)) {
+        existingWarmup.currentModeId = modeId
+        this.notifyModesReady(existingWarmup)
+      }
+    } finally {
+      releaseLock()
+    }
+  }

Not strictly required, but it would make the concurrency story more uniform across this manager.

Also applies to: 998-1002

🧹 Nitpick comments (1)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (1)

161-236: Warmup flow looks solid; consider tightening stats and simplifying inflight handling.

The warmup lifecycle and locking pattern are generally correct. Two small cleanups to simplify behavior and logging:

  • warmupCount at Line 172 currently counts all alive handles for the agent (including bound ones) even though the log labels it as warmups. If you care specifically about warmup processes, filter on handle.state === 'warmup' to avoid misleading debug output.
  • With the per‑agent lock in warmupProcess, the pendingHandles / “inflight” path is effectively never hit for the same agentId + workdir (subsequent calls will await the previous lock and see a settled pendingHandles entry). You could either:
    • Document that pendingHandles is intended for future callers that don’t use the lock, or
    • Remove/simplify the inflight branch to reduce complexity.

Example tweak for the warmup count:

-      const warmupCount = this.getHandlesByAgent(agent.id).filter((handle) =>
-        this.isHandleAlive(handle)
-      ).length
+      const warmupCount = this.getHandlesByAgent(agent.id).filter(
+        (handle) => handle.state === 'warmup' && this.isHandleAlive(handle)
+      ).length

Also applies to: 950-1002

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1fafd6 and 711d783.

📒 Files selected for processing (3)
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (10 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (1 hunks)
  • src/renderer/src/i18n/pt-BR/settings.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/src/i18n/pt-BR/settings.json
🧰 Additional context used
📓 Path-based instructions (16)
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and maintain strict TypeScript type checking for all files

**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Organize core business logic into dedicated Presenter classes, with one presenter per functional domain

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use EventBus from src/main/eventbus.ts for main-to-renderer communication, broadcasting events via mainWindow.webContents.send()

src/main/**/*.ts: Use EventBus pattern for inter-process communication within the main process to decouple modules
Use Electron's built-in APIs for file system and native dialogs instead of Node.js or custom implementations

src/main/**/*.ts: Electron main process code belongs in src/main/ with presenters in presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider) and eventbus.ts for app events
Use the Presenter pattern in the main process for UI coordination

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

Write logs and comments in English

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/llmProviderPresenter/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/llm-agent-loop.mdc)

Define the standardized LLMCoreStreamEvent interface with fields: type (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), content (for text), reasoning_content (for reasoning), tool_call_id, tool_call_name, tool_call_arguments_chunk (for streaming), tool_call_arguments_complete (for complete arguments), error_message, usage object with token counts, stop_reason (tool_use | max_tokens | stop_sequence | error | complete), and image_data object with Base64-encoded data and mimeType

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

New features should be developed in the src directory

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/renderer/src/i18n/fa-IR/settings.json
src/main/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Main process code for Electron should be placed in src/main

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx,vue,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with single quotes, no semicolons, and 100 character width

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use OxLint for linting JavaScript and TypeScript files

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use EventBus for inter-process communication events

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/renderer/src/i18n/**/*.json

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/i18n/**/*.json: Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')
Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
src/renderer/**

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Use lowercase with dashes for directories (e.g., components/auth-wizard)

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
🧠 Learnings (8)
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Implement separation of concerns where `src/main/presenter/llmProviderPresenter/index.ts` manages the Agent loop and conversation history, while Provider files handle LLM API interactions, Provider-specific request/response formatting, tool definition conversion, and native vs non-native tool call mechanisms

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts` (`startStreamCompletion`), implement the Agent loop that manages the overall conversation flow, including multiple rounds of LLM calls and tool usage, maintaining `conversationMessages` history, calling `provider.coreStream()` on each iteration, and controlling the loop using `needContinueConversation` and `toolCallCount` (compared against `MAX_TOOL_CALLS`)

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, listen for standardized events yielded by `coreStream` and handle them accordingly: buffer text content (`currentContent`), handle `tool_call_start/chunk/end` events by collecting tool details and calling `presenter.mcpPresenter.callTool`, send frontend events via `eventBus` with tool call status, format tool results for the next LLM call, and set `needContinueConversation = true`

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/**/*.ts : Use EventBus for inter-process communication events

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to src/main/**/*.ts : Use EventBus pattern for inter-process communication within the main process to decouple modules

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to {src/main/presenter/**/*.ts,src/renderer/**/*.ts} : Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)

Applied to files:

  • src/renderer/src/i18n/fa-IR/settings.json
🧬 Code graph analysis (1)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (5)
src/main/presenter/llmProviderPresenter/agent/types.ts (1)
  • AgentProcessHandle (9-9)
src/shared/types/presenters/legacy.presenters.d.ts (1)
  • AcpAgentConfig (771-777)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/renderer/src/events.ts (1)
  • ACP_WORKSPACE_EVENTS (178-183)
src/main/events.ts (1)
  • ACP_WORKSPACE_EVENTS (237-242)
⏰ 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)
🔇 Additional comments (5)
src/renderer/src/i18n/fa-IR/settings.json (1)

974-1015: Excellent—major issues from past review are resolved.

The debug section correctly restores canonical ACP protocol identifiers in the methods object (lines 993–1003) and improves key term translations:

  • clearHistory: "پاک کردن تاریخچه" ✓
  • close: "بستن" ✓
  • eventKinds.notification: "اعلان" ✓
  • eventKinds.request: "درخواست" ✓

The hierarchical structure with lowercase dot-separated keys aligns with coding guidelines. JSON formatting and locale consistency are sound.

src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (4)

889-947: SESSION_MODES_READY payload can have undefined conversationId for warmup; confirm renderer handles this.

notifyModesReady sends:

eventBus.sendToRenderer(ACP_WORKSPACE_EVENTS.SESSION_MODES_READY, SendTarget.ALL_WINDOWS, {
  conversationId: conversationId ?? handle.boundConversationId,
  agentId: handle.agentId,
  workdir: handle.workdir,
  current: handle.currentModeId ?? 'default',
  available: handle.availableModes
})

For pure warmup flows (no bound conversation yet), both conversationId and handle.boundConversationId can be undefined, so renderers will receive a SESSION_MODES_READY event without a conversation id. That may be intentional for workspace‑level mode pickers, but it’s worth double‑checking that all consumers tolerate conversationId being missing (e.g., they key only on agentId + workdir and don’t assume a non‑empty string).

If any renderer code assumes a string conversationId, you may want to:

  • Explicitly document that conversationId can be undefined for pre‑session mode discovery, or
  • Use a dedicated field (e.g., sessionId or a flag like isWarmup) to disambiguate warmup vs bound notifications.

542-559: Restart count logic and handle construction look consistent.

Using getRestartCount(agent.id) + 1 to compute restarts and centralizing the counting in getHandlesByAgent is a clean approach, and seeding availableModes / currentModeId from the initialization result into the final handle is consistent with the later warmup/mode probing flow.

No changes needed here.

Also applies to: 964-969


565-583: Handle cleanup and process exit handling are coherent and idempotent.

removeHandleReferences, disposeHandle, killChild, and the child.on('exit') handler form a consistent cleanup story:

  • disposeHandle calls removeHandleReferences then killChild, and is used by warmupProcess, release, and unbindProcess.
  • The exit handler also calls removeHandleReferences and clearSessionsForAgent, which is safe even if disposeHandle ran first.
  • clearSessionsForAgent now also cleans out any remaining boundHandles entries for the agent.

This makes disposal idempotent and avoids stale handle references. No action required.

Also applies to: 971-988, 1004-1022


1053-1057: isHandleAlive condition is reasonable.

Checking !child.killed && exitCode === null && signalCode === null is a sensible proxy for liveness for these spawned ACP processes, and aligns with how Node’s ChildProcess reports termination.

No modifications needed.

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: 2

♻️ Duplicate comments (2)
src/renderer/src/i18n/fa-IR/settings.json (1)

991-991: Use plural form for "events" key.

Line 991 still uses the singular form "رویداد" but should use the plural "رویدادها" to match the label's semantic meaning and the pattern suggested in previous review feedback. This was flagged before but appears not to have been addressed.

-      "events": "رویداد",
+      "events": "رویدادها",
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (1)

322-367: Bind/unbind should participate in the per‑agent lock to avoid races on handle maps

warmupProcess, release, and unbindProcess use acquireAgentLock(agentId) to serialize mutations of handles/boundHandles for a given agent, but bindProcess still:

  • Selects a warmup handle from this.handles
  • Mutates handle.state/boundConversationId
  • Moves the handle from handles to boundHandles

all without taking the lock.

Because bindProcess is synchronous and doesn’t await, it can run while another operation (e.g. release or warmupProcess) is between awaits inside its critical section. That opens up interleavings such as:

  • release(agentId) computing targets and acquiring the lock just as bindProcess binds a handle that is about to be disposed.
  • warmupProcess/clearSessionsForAgent concurrently adding/removing entries while bindProcess is iterating this.handles.entries().

Recommend making bindProcess follow the same pattern as unbindProcess so that all handle map mutations are serialized per agent. One possible refactor (requires updating call sites to await):

-  bindProcess(agentId: string, conversationId: string, workdir?: string): void {
-    const resolvedWorkdir = this.resolveWorkdir(workdir)
-    // Prefer warmup handle matching requested workdir if provided
-    const warmupHandles = Array.from(this.handles.entries()).filter(
-      ([, handle]) =>
-        handle.agentId === agentId &&
-        handle.state === 'warmup' &&
-        (!workdir || !handle.workdir || handle.workdir === resolvedWorkdir)
-    )
-    const handle =
-      warmupHandles.find(([, candidate]) => candidate.workdir === resolvedWorkdir)?.[1] ??
-      warmupHandles[0]?.[1]
-    if (!handle) {
-      console.warn(`[ACP] No warmup handle to bind for agent ${agentId}`)
-      return
-    }
+  async bindProcess(agentId: string, conversationId: string, workdir?: string): Promise<void> {
+    const resolvedWorkdir = this.resolveWorkdir(workdir)
+    const releaseLock = await this.acquireAgentLock(agentId)
+    try {
+      // Prefer warmup handle matching requested workdir if provided
+      const warmupHandles = Array.from(this.handles.entries()).filter(
+        ([, handle]) =>
+          handle.agentId === agentId &&
+          handle.state === 'warmup' &&
+          (!workdir || !handle.workdir || handle.workdir === resolvedWorkdir)
+      )
+      const handle =
+        warmupHandles.find(([, candidate]) => candidate.workdir === resolvedWorkdir)?.[1] ??
+        warmupHandles[0]?.[1]
+      if (!handle) {
+        console.warn(`[ACP] No warmup handle to bind for agent ${agentId}`)
+        return
+      }
@@
-    this.boundHandles.set(conversationId, handle)
-
-    // Immediately notify renderer if modes are already known
-    this.notifyModesReady(handle, conversationId)
-    console.info(
-      `[ACP] Bound process for agent ${agentId} to conversation ${conversationId} (pid=${handle.pid}, workdir=${handle.workdir})`
-    )
-  }
+      this.boundHandles.set(conversationId, handle)
+
+      // Immediately notify renderer if modes are already known
+      this.notifyModesReady(handle, conversationId)
+      console.info(
+        `[ACP] Bound process for agent ${agentId} to conversation ${conversationId} (pid=${handle.pid}, workdir=${handle.workdir})`
+      )
+    } finally {
+      releaseLock()
+    }
+  }

If you prefer to keep a synchronous signature, you could instead wrap the locking logic in a void (async () => { ... })() fire‑and‑forget, but then callers must tolerate binding finishing slightly later.

This aligns bind/unbind/release on the same locking model and removes subtle lifecycle races.

You can quickly see all call sites impacted by changing the signature with:

#!/bin/bash
rg -n "bindProcess\\(" src -S -C3

Also applies to: 368-378

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 711d783 and dd5dbb2.

📒 Files selected for processing (2)
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (10 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (16)
src/renderer/src/i18n/**/*.json

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/i18n/**/*.json: Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')
Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
src/**/*

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

New features should be developed in the src directory

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/renderer/**

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Use lowercase with dashes for directories (e.g., components/auth-wizard)

Files:

  • src/renderer/src/i18n/fa-IR/settings.json
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enable and maintain strict TypeScript type checking for all files

**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Organize core business logic into dedicated Presenter classes, with one presenter per functional domain

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use EventBus from src/main/eventbus.ts for main-to-renderer communication, broadcasting events via mainWindow.webContents.send()

src/main/**/*.ts: Use EventBus pattern for inter-process communication within the main process to decouple modules
Use Electron's built-in APIs for file system and native dialogs instead of Node.js or custom implementations

src/main/**/*.ts: Electron main process code belongs in src/main/ with presenters in presenter/ (Window/Tab/Thread/Mcp/Config/LLMProvider) and eventbus.ts for app events
Use the Presenter pattern in the main process for UI coordination

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)

Write logs and comments in English

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}

📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)

Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/llmProviderPresenter/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/llm-agent-loop.mdc)

Define the standardized LLMCoreStreamEvent interface with fields: type (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), content (for text), reasoning_content (for reasoning), tool_call_id, tool_call_name, tool_call_arguments_chunk (for streaming), tool_call_arguments_complete (for complete arguments), error_message, usage object with token counts, stop_reason (tool_use | max_tokens | stop_sequence | error | complete), and image_data object with Base64-encoded data and mimeType

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Main process code for Electron should be placed in src/main

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx,vue,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with single quotes, no semicolons, and 100 character width

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use OxLint for linting JavaScript and TypeScript files

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use EventBus for inter-process communication events

Files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
🧠 Learnings (8)
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)

Applied to files:

  • src/renderer/src/i18n/fa-IR/settings.json
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Implement separation of concerns where `src/main/presenter/llmProviderPresenter/index.ts` manages the Agent loop and conversation history, while Provider files handle LLM API interactions, Provider-specific request/response formatting, tool definition conversion, and native vs non-native tool call mechanisms

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts` (`startStreamCompletion`), implement the Agent loop that manages the overall conversation flow, including multiple rounds of LLM calls and tool usage, maintaining `conversationMessages` history, calling `provider.coreStream()` on each iteration, and controlling the loop using `needContinueConversation` and `toolCallCount` (compared against `MAX_TOOL_CALLS`)

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, listen for standardized events yielded by `coreStream` and handle them accordingly: buffer text content (`currentContent`), handle `tool_call_start/chunk/end` events by collecting tool details and calling `presenter.mcpPresenter.callTool`, send frontend events via `eventBus` with tool call status, format tool results for the next LLM call, and set `needContinueConversation = true`

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/**/*.ts : Use EventBus for inter-process communication events

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to src/main/**/*.ts : Use EventBus pattern for inter-process communication within the main process to decouple modules

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to {src/main/presenter/**/*.ts,src/renderer/**/*.ts} : Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs

Applied to files:

  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
🧬 Code graph analysis (1)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (6)
src/main/presenter/llmProviderPresenter/agent/types.ts (1)
  • AgentProcessHandle (9-9)
src/shared/types/presenters/agent-provider.d.ts (1)
  • AgentProcessHandle (16-24)
src/shared/types/presenters/legacy.presenters.d.ts (1)
  • AcpAgentConfig (771-777)
src/main/eventbus.ts (1)
  • eventBus (151-151)
src/main/events.ts (1)
  • ACP_WORKSPACE_EVENTS (237-242)
src/renderer/src/events.ts (1)
  • ACP_WORKSPACE_EVENTS (178-183)
⏰ 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)
🔇 Additional comments (3)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (3)

21-35: EventBus wiring and extended handle shape look solid

Using the shared eventBus/ACP_WORKSPACE_EVENTS for mode notifications and extending AcpProcessHandle with state, boundConversationId, workdir, and mode fields cleanly models the new lifecycle without breaking AgentProcessHandle assumptions. Types and field usage look consistent across the file.

As per coding guidelines and learnings, this keeps IPC and process state centralized in the presenter.


140-160: Warmup lifecycle, mode discovery, and liveness checks are well-structured

The combination of resolveWorkdir/getWarmupKey, warmupProcess, pendingHandles, findReusableHandle, fetchProcessModes, notifyModesReady, applyPreferredMode, and isHandleAlive gives you:

  • Serialized warmups per agent via acquireAgentLock
  • Reuse of still-alive warmup processes by (agentId, workdir)
  • Safe handling of inflight warmups and failures (with cleanup via disposeHandle and pendingHandles.delete)
  • Asynchronous mode discovery that notifies the renderer once availableModes are known

Overall this flow looks robust and matches the intended “pre-warm + later bind” design.

Based on learnings, this keeps ACP process IO and lifecycle concerns inside the provider/manager while leaving the agent loop to the main presenter.

Also applies to: 165-236, 892-938, 940-951, 993-1005, 1056-1060


453-562: Spawn and initialization flow looks correct, including mode extraction

The spawn/initialize path now:

  • Validates and expands the agent command/args and swaps in the builtin runtime when configured.
  • Builds a merged environment with shell env, existing PATH, default runtime paths, and agent env, plus optional registry variables.
  • Falls back from a missing workdir to HOME_DIR for cwd (with clear logging).
  • Wraps connection.initialize in a 5‑minute timeout, tears down the child on failure, and logs initialization details.
  • Normalizes ACP modes into availableModes/currentModeId on the handle and logs them for debugging.
  • Hooks process exit/error events to cleanup handle references and sessions.

All of this looks coherent and defensive; I don’t see correctness issues here.

Also applies to: 579-591

@zerob13 zerob13 merged commit ee66082 into dev Dec 11, 2025
2 checks passed
zerob13 added a commit that referenced this pull request Dec 12, 2025
* fix: Multiple Issues Affecting Conversation Flow and Model Settings (#1166)

* fix: #1164 support maxtoken 2

* fix: mcp tool panel close btn #1163

* fix: #1162 file content in converation

* fix(search-assistant): exclude acp models

* fix: #1072 thinkcontent respects the global font size set

* feat: Hebrew (he-IL) Translation (#1157)

* feat: Hebrew (he-IL) Translation

* feat: add workspace view to acp agents (#1158)

* feat: add workspaceview for acp agent

* feat: support workspace dirs

* fix: workspace file refresh

* fix: tool call status

* fix: review refactor

* chore: update readme

* fix: add file context actions (#1160)

* fix: keep last file list

* feat(acp-workspace): add file context actions

* fix(acp-workspace): move path helpers to preload

* fix(preload): allow empty relative path

* fix(preload): escape quotes when formatting paths

* chore: update docs

* fix: Multiple Issues Affecting Conversation Flow and Model Settings (#1166)

* fix: #1164 support maxtoken 2

* fix: mcp tool panel close btn #1163

* fix: #1162 file content in converation

* fix(search-assistant): exclude acp models

* fix: #1072 thinkcontent respects the global font size set

* feat: add new i18n translation

* feat: add custom font setting (#1167)

* feat(settings): add font customization controls

* feat: change font with monaco

* chore: remove log and remove unuse key

* fix: linux font parse

* feat: use font-list to get font

* fix: font setting not work on settings page (#1169)

* style: unify scroll bar style (#1173)

* feat: acp init and process manage (#1171)

* feat: init acp process on select

* feat: warm up acp process on new thread

* fix: reuse warmup process

* fix: vue warning

* chore: add plan for acp debug panel

* feat: add debugview for acp

* feat: add i18n for debug

* fix: code review

* fix: ai review

* fix: Shutdown may skip releasing warmup‑only processes due to using warmupKey instead of agentId.

* chore: update markdown renderer

* chore: update mermaid node

* Merge commit from fork

* chore: update markstream-vue to version 0.0.3-beta.3
fix link renderer
feat html_inline render

* fix: increase button size for web content limit adjustment

* fix: close app kill all acp processes (#1175)

* fix: close app kill all acp processes

* fix: disable tool call merge

* fix: handle uncatch error

* fix: remove redundant type

* feat: add  shell to powerpack (#1178)

* chore(powerpack): randomize shell workdir

* feat: exclusive inmem server in terminal display

* fix: add sandbox in shell script

---------

Co-authored-by: xiaomo <wegi866@gmail.com>
Co-authored-by: Simon He <674949287@qq.com>
Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>
@zerob13 zerob13 deleted the feat/acp-init-and-process-manage branch December 13, 2025 06:59
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