Skip to content

Conversation

@zerob13
Copy link
Collaborator

@zerob13 zerob13 commented Dec 4, 2025

Summary by CodeRabbit

  • New Features

    • ACP Workspace panel: files browser (lazy loading), plan tracker with progress, and terminal snippet viewer
    • Session mode discovery and mode controls; real-time plan and terminal updates pushed to UI
    • Workspace open button added to message actions; automatic file refresh on changes
  • Localization

    • Added workspace UI translations across multiple languages
  • Infrastructure

    • New workspace store and presenter integration enabling IPC-driven updates and workspace lifecycle management

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 4, 2025

Walkthrough

Adds ACP workspace support: new main-process presenter, directory readers, plan state manager, process/workdir updates, IPC workspace events, renderer components and store for files/plan/terminal, and i18n updates across locales.

Changes

Cohort / File(s) Summary
Events & Shared Types
src/main/events.ts, src/renderer/src/events.ts, src/shared/types/presenters/acp-workspace.d.ts, src/shared/types/presenters/index.d.ts, src/shared/types/index.d.ts, src/shared/types/presenters/legacy.presenters.d.ts
Adds ACP_WORKSPACE_EVENTS (PLAN_UPDATED, TERMINAL_OUTPUT, FILES_CHANGED, SESSION_MODES_READY). Introduces ACP workspace types and IAcpWorkspacePresenter interface; re-exports types in presenter barrels and shared index.
Workspace Presenter & Utils
src/main/presenter/acpWorkspacePresenter/index.ts, src/main/presenter/acpWorkspacePresenter/directoryReader.ts, src/main/presenter/acpWorkspacePresenter/planStateManager.ts
New AcpWorkspacePresenter with workdir registration, access checks, directory read/expand, plan entry lifecycle, terminal emission, and clearing. Adds readDirectoryShallow/readDirectoryTree utilities and PlanStateManager for deduplication, merging, and pruning.
Main Presenter Integration
src/main/presenter/index.ts
Presenter gains acpWorkspacePresenter field and initializes AcpWorkspacePresenter.
Process / FS / Session Changes
src/main/presenter/llmProviderPresenter/agent/acpFsHandler.ts, src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts, src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts
Adds optional onFileChange callback to FS handler (invoked after writes). Extends process manager to track workdir, accept workdir in getConnection/spawn, per-agent locks, and workdir-aware spawn/init logic. Session manager surfaces available modes/currentModeId and logs them.
Agent Loop & Provider
src/main/presenter/llmProviderPresenter/managers/agentLoopHandler.ts, src/main/presenter/llmProviderPresenter/providers/acpProvider.ts, src/main/presenter/threadPresenter/index.ts
ACP-specific tool_call handling (different completion path) and emits FILES_CHANGED on loop completion. AcpProvider adds getSessionModes and emits SESSION_MODES_READY. threadPresenter changes conversation update flow to promise chaining (removes prior await/guard).
Renderer Store & Events
src/renderer/src/stores/acpWorkspace.ts, src/renderer/src/events.ts
New Pinia useAcpWorkspaceStore managing isOpen/isLoading, planEntries, fileTree, terminalSnippets, IPC subscriptions to ACP events, file refresh debouncing, lazy child loading, and workspace lifecycle. Renderer events file exports ACP_WORKSPACE_EVENTS.
Renderer Components — Workspace
src/renderer/src/components/acp-workspace/AcpWorkspaceView.vue, .../AcpWorkspaceFiles.vue, .../AcpWorkspaceFileNode.vue, .../AcpWorkspacePlan.vue, .../AcpWorkspaceTerminal.vue
Adds ACP workspace UI: container view plus Files (tree with lazy load), FileNode (recursive), Plan (progress and entries), and Terminal (snippets) components with transitions and i18n.
Renderer Integration & UI Changes
src/renderer/src/components/ChatView.vue, src/renderer/src/components/message/MessageActionButtons.vue, src/renderer/src/components/message/MessageList.vue, src/renderer/src/components/chat-input/ChatInput.vue, src/renderer/src/components/chat-input/composables/useAcpMode.ts
Integrates workspace panel into ChatView; adds workspace button prop/event to message action controls; MessageList wires store to open workspace; ChatInput passes streaming state to ACP mode composable. useAcpMode extended for modes, IPC SESSION_MODES_READY, streaming-aware reload, and exposes hasAgentModes.
Message / Content Component Tweaks
src/renderer/src/components/message/MessageBlockPlan.vue, .../MessageBlockPermissionRequest.vue, src/renderer/src/components/think-content/ThinkContent.vue, src/renderer/src/components/message/MessageActionButtons.vue, src/renderer/src/components/message/MessageList.vue
Simplifies MessageBlockPlan rendering (removes per-entry list), truncates tool_call names in PermissionRequest (200 chars), strips <style> blocks in ThinkContent, and adds workspace open button wiring in message actions/list.
Localization
src/renderer/src/i18n/*/chat.json (en-US, da-DK, fr-FR, fa-IR, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW)
Removes several acpMode keys and adds a new acp.workspace (or acpWorkspace) structure with strings for workspace title, collapse, plan/files/terminal labels, empty/loading states and plan status values across locales.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Renderer as Renderer (ChatView / Components)
    participant Store as Pinia (acpWorkspace)
    participant Main as Main Process (AcpWorkspacePresenter)
    participant FS as FileSystem
    participant IPC as IPC Bus

    User->>Renderer: open workspace
    Renderer->>Store: setOpen(true)
    Store->>Main: readDirectory(workdir)
    Main->>FS: readDirectoryShallow(workdir)
    FS-->>Main: file nodes
    Main-->>IPC: emit PLAN_UPDATED / FILES_CHANGED (when applicable)
    IPC-->>Store: receive events
    Store->>Renderer: update plan/files/terminal UI

    User->>Renderer: expand directory
    Renderer->>Store: toggleFileNode(node)
    Store->>Main: expandDirectory(dirPath)
    Main->>FS: readDirectoryTree(dirPath)
    FS-->>Main: children nodes
    Main-->>Store: children loaded
    Store->>Renderer: render expanded node
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Review focus:
    • acpProcessManager: workdir matching, lock/inflight logic, process lifecycle and timeouts.
    • acpWorkspacePresenter: path access control (isPathAllowed) and IPC payload shapes.
    • PlanStateManager: hashing/deduplication and pruning correctness.
    • Renderer store: IPC subscriptions, debouncing, race conditions when conversation/workdir changes.
    • threadPresenter change to promise chaining (possible missing error handling / undefined title).

Possibly related PRs

  • #1156 — implements overlapping ACP workspace features (events, presenter, renderer components, types).
  • #1106 — modifies acpProcessManager spawn/handle logic (workdir/process fields) and thus intersects with new workdir changes.
  • #1112 — touches ACP process/agent initialization paths similar to acpProcessManager updates.

Suggested labels

codex

Suggested reviewers

  • deepinfect

Poem

🐰 I hopped through files and plans anew,

Terminals chattered, modes came through.
Trees expand with a gentle click,
Workspace ready — tidy and quick.
Hooray for code that helps us chew!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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 PR title 'feat: add workspace view to acp agents' clearly and accurately summarizes the main change: introducing a new workspace view feature for ACP agents.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ui/workspace-view

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

Caution

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

⚠️ Outside diff range comments (1)
src/renderer/src/i18n/ru-RU/chat.json (1)

20-22: Untranslated English strings in Russian locale.

The acpWorkdir, acpWorkdirTooltip, and acpWorkdirSelect keys contain English text instead of Russian translations. This breaks locale consistency.

-    "acpWorkdir": "ACP Workdir",
-    "acpWorkdirTooltip": "Set ACP working directory",
-    "acpWorkdirSelect": "Select a folder to use as the ACP workdir",
+    "acpWorkdir": "Рабочий каталог ACP",
+    "acpWorkdirTooltip": "Установить рабочий каталог ACP",
+    "acpWorkdirSelect": "Выберите папку для рабочего каталога ACP",
🧹 Nitpick comments (22)
src/renderer/src/components/message/MessageBlockPermissionRequest.vue (2)

13-19: Collapsed header now consistently uses truncatedName

Using truncatedName here keeps long tool names from breaking the collapsed layout and matches the expanded view header logic. Consider optionally exposing the full name via a title attribute or tooltip if you see UX complaints about discoverability, but this is fine as-is.


219-230: Status text strings should also use i18n instead of hardcoded literals

getStatusText still returns hardcoded 'Error' and 'Pending', while other status labels already use i18n keys. To keep all user-facing strings translatable and consistent with the rest of this component, consider moving these two into the i18n namespace as well, e.g.:

-    case 'error':
-      return 'Error'
-    default:
-      return 'Pending'
+    case 'error':
+      return t('components.messageBlockPermissionRequest.error')
+    default:
+      return t('components.messageBlockPermissionRequest.pending')

(Based on learnings, user-visible strings under src/renderer/src/**/* should use the i18n system.)

src/renderer/src/components/message/MessageBlockPlan.vue (1)

34-36: Consider stricter typing for planEntries.

The planEntries type was simplified to Array<{ status?: string | null }>, which is less strict than the previous PlanEntry interface. While this works for the current logic, consider using a more explicit type to maintain type safety and clarity:

-const planEntries = computed(() => {
-  return (props.block.extra?.plan_entries as Array<{ status?: string | null }>) || []
-})
+type PlanEntrySummary = { status?: string | null }
+
+const planEntries = computed(() => {
+  return (props.block.extra?.plan_entries as PlanEntrySummary[]) || []
+})

This makes the intent clearer and provides better type documentation.

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

125-126: Consider adding cleanup in destroy() lifecycle.

The acpWorkspacePresenter is initialized correctly, but there's no corresponding cleanup in the destroy() method (line 215). While the presenter doesn't require initialization, it maintains internal state (planStore in PlanStateManager) that should be cleaned up on application exit.

Consider adding cleanup in the destroy() method:

 destroy() {
   this.floatingButtonPresenter.destroy()
   this.tabPresenter.destroy()
   this.sqlitePresenter.close()
   this.shortcutPresenter.destroy()
   this.syncPresenter.destroy()
   this.notificationPresenter.clearAllNotifications()
   this.knowledgePresenter.destroy()
+  // Clear all ACP workspace data
+  // Note: Individual conversation cleanup is handled by clearWorkspaceData
   // 注意: trayPresenter.destroy() 在 main/index.ts 的 will-quit 事件中処理
   // 此処不销毁 trayPresenter,其生命周期由 main/index.ts 管理
 }
src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue (2)

3-21: Add accessibility attributes to toggle button.

The collapsible section button should include ARIA attributes to improve accessibility for screen readers.

Apply this diff:

 <button
   class="flex w-full items-center gap-2 px-4 py-2 text-left text-xs text-muted-foreground transition hover:bg-muted/40"
   type="button"
+  :aria-expanded="showFiles"
+  aria-controls="workspace-files-content"
   @click="showFiles = !showFiles"
 >

And add an ID to the collapsible content:

 <Transition name="workspace-collapse">
-  <div v-if="showFiles" class="space-y-0 overflow-hidden">
+  <div v-if="showFiles" id="workspace-files-content" class="space-y-0 overflow-hidden">

57-68: Consider whether directory nodes should be included in file count.

The countFiles function currently counts all nodes (both files and directories). This may not align with user expectations, as file counts typically refer only to files, not directories.

If only files should be counted, update the logic:

 const countFiles = (nodes: ACP_FILE_NODE[]): number => {
   let count = 0
   for (const node of nodes) {
-    count += 1
+    if (!node.isDirectory) {
+      count += 1
+    }
     if (node.children) {
       count += countFiles(node.children)
     }
   }
   return count
 }

If the current behavior (counting all nodes) is intentional, consider renaming to countNodes for clarity.

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

330-330: Consider using structured logging instead of commenting out logs.

Instead of commenting out debug logs, use a proper debug log level that can be enabled/disabled via configuration.

-                // console.log('[ACP] onSessionUpdate: notification:', JSON.stringify(notification))
+                logger.debug('[ACP] onSessionUpdate:', { notification })

As per coding guidelines: Use structured logging with logger.debug() for debug-level logs that can be toggled without code changes.


682-716: Consider preventing invalid mode changes at the presenter level.

The current implementation warns when a requested mode is not in availableModes but still attempts the mode change. This could lead to agent-level errors that might be confusing to users.

Consider blocking invalid mode changes upfront:

   // Warn if requested mode is not in available modes
   if (availableModeIds.length > 0 && !availableModeIds.includes(modeId)) {
-    console.warn(
-      `[ACP] Mode "${modeId}" is not in agent's available modes [${availableModeIds.join(', ')}]. ` +
-        `The agent may not support this mode.`
-    )
+    const errorMsg = 
+      `Mode "${modeId}" is not available. ` +
+      `Available modes: [${availableModeIds.join(', ')}]`
+    console.error(`[ACP] ${errorMsg}`)
+    throw new Error(errorMsg)
   }

This provides clearer feedback to the caller and prevents unnecessary IPC calls to the agent.

src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue (1)

3-21: Add accessibility attributes to toggle button.

Similar to the Files component, the plan section toggle should include ARIA attributes.

Apply this diff:

 <button
   class="flex w-full items-center gap-2 px-4 py-2 text-left text-xs text-muted-foreground transition hover:bg-muted/40"
   type="button"
+  :aria-expanded="showPlan"
+  aria-controls="workspace-plan-content"
   @click="showPlan = !showPlan"
 >

And add an ID to the collapsible content:

 <Transition name="workspace-collapse">
-  <div v-if="showPlan" class="space-y-0 overflow-hidden">
+  <div v-if="showPlan" id="workspace-plan-content" class="space-y-0 overflow-hidden">
src/renderer/src/components/acp-workspace/AcpWorkspaceTerminal.vue (2)

3-21: Add accessibility attributes to toggle button.

Consistent with the Files and Plan components, add ARIA attributes for accessibility.

Apply this diff:

 <button
   class="flex w-full items-center gap-2 px-4 py-2 text-left text-xs text-muted-foreground transition hover:bg-muted/40"
   type="button"
+  :aria-expanded="showTerminal"
+  aria-controls="workspace-terminal-content"
   @click="showTerminal = !showTerminal"
 >

And add an ID to the collapsible content:

 <Transition name="workspace-collapse">
-  <div v-if="showTerminal" class="space-y-0 overflow-hidden pb-1">
+  <div v-if="showTerminal" id="workspace-terminal-content" class="space-y-0 overflow-hidden pb-1">

43-50: Consider using break-words instead of break-all for terminal output.

The break-all utility will break words in the middle, which can make terminal output harder to read. The break-words utility tries to break at word boundaries first.

-            class="text-[10px] text-muted-foreground font-mono whitespace-pre-wrap break-all max-h-20 overflow-y-auto"
+            class="text-[10px] text-muted-foreground font-mono whitespace-pre-wrap break-words max-h-20 overflow-y-auto"
src/main/presenter/llmProviderPresenter/agent/acpFsHandler.ts (1)

11-12: Avoid callback exceptions turning successful writes into handler errors

Wiring onFileChange through options into writeTextFile looks clean, but invoking an arbitrary callback directly after fs.writeFile means any exception thrown in the callback will cause the whole writeTextFile request to fail even though the file is already persisted.

Consider either:

  • wrapping the callback in a small try/catch with structured logging so write semantics are not affected by observer failures, or
  • clearly documenting that onFileChange must be non-throwing and enforcing that via a guarded wrapper utility.

This makes the FS handler more robust against observer bugs while keeping the core behavior unchanged.

Also applies to: 26-32, 109-112

src/renderer/src/components/think-content/ThinkContent.vue (1)

31-35: Sanitizing content before NodeRenderer is a good hardening step

Switching to props plus a sanitizedContent computed that strips <style> tags, and then gating NodeRenderer on that value, effectively prevents injected styles from leaking into the app while keeping the rest of the rendering pipeline unchanged.

The current regex is a pragmatic balance; if you later see false positives (e.g., literal <style> in code samples), you can tighten it further, but this is a sensible default.

Also applies to: 50-53, 60-64

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

100-115: Consider returning new node data instead of mutating the argument.

The method directly mutates the node parameter. While Vue's reactivity will track these changes, mutating function arguments is harder to reason about. Also, setting expanded = true on error might mislead users into thinking the directory loaded successfully.

Consider either returning the updated node or passing an update callback:

 const loadDirectoryChildren = async (node: ACP_FILE_NODE): Promise<void> => {
   if (!node.isDirectory) return

   try {
     const children = (await acpWorkspacePresenter.expandDirectory(node.path)) ?? []
     node.children = children
     node.expanded = true
   } catch (error) {
     console.error('[AcpWorkspace] Failed to load directory children:', error)
     node.children = []
-    node.expanded = true
+    node.expanded = false
   }
 }

161-193: IPC listeners are registered without cleanup.

The event listeners are registered at store initialization but never removed. For a global Pinia store that lives for the application lifetime, this is acceptable. However, if the store could be destroyed and recreated (e.g., in tests or HMR), this could cause duplicate listeners.

Consider adding a cleanup method for testing scenarios:

const cleanupEventListeners = () => {
  window.electron.ipcRenderer.removeListener(ACP_WORKSPACE_EVENTS.PLAN_UPDATED, /* handler */)
  // ... other listeners
}

211-236: Potential duplicate file tree refresh on initialization.

Both the currentWorkdir watcher (line 212) and isAcpMode watcher (line 223) have { immediate: true } and both call refreshFileTree(). On initial store creation in ACP mode with a workdir set, this could trigger two concurrent refreshes.

Consider consolidating initialization logic or adding a guard:

 // Watch for workdir changes
 watch(
   currentWorkdir,
   (workdir) => {
-    if (isAcpMode.value && workdir) {
+    if (isAcpMode.value && workdir && lastSyncedConversationId.value) {
       refreshFileTree()
     }
   },
-  { immediate: true }
+  { immediate: false }
 )
src/main/presenter/acpWorkspacePresenter/directoryReader.ts (2)

69-71: Consider using structured logging instead of console.error.

Per coding guidelines, prefer structured logging with logger.error() methods from logging utilities. Also, the error context could include the error type for better debugging.

+import { logger } from '@/lib/logger' // or appropriate logger import
+
 // Inside catch block:
-    console.error(`[AcpWorkspace] Failed to read directory ${dirPath}:`, error)
+    logger.error(`[AcpWorkspace] Failed to read directory`, { dirPath, error })

75-89: Duplicate logic with readDirectoryShallow - consider extracting shared helpers.

Both functions share identical filtering logic (lines 95-104 vs 35-44) and sorting logic (lines 123-128 vs 63-68). Consider extracting these into private helper functions to reduce duplication and improve maintainability.

Also, use the standard @deprecated JSDoc tag for better tooling support:

 /**
- * Recursively read directory structure (deprecated, use readDirectoryShallow for lazy loading)
+ * Recursively read directory structure
+ * @deprecated Use readDirectoryShallow for lazy loading instead
  * @param dirPath Directory path
src/main/presenter/acpWorkspacePresenter/index.ts (2)

39-48: Potential case-sensitivity issue on Windows/macOS.

On case-insensitive file systems (Windows, macOS by default), /Users/Test/project and /users/test/project refer to the same directory, but this check would treat them as different paths. Consider normalizing case for comparison on these platforms.

  private isPathAllowed(targetPath: string): boolean {
-   const normalized = path.resolve(targetPath)
+   let normalized = path.resolve(targetPath)
+   // Normalize case on case-insensitive file systems
+   if (process.platform === 'win32' || process.platform === 'darwin') {
+     normalized = normalized.toLowerCase()
+   }
    for (const workdir of this.allowedWorkdirs) {
-     if (normalized === workdir || normalized.startsWith(workdir + path.sep)) {
+     let normalizedWorkdir = workdir
+     if (process.platform === 'win32' || process.platform === 'darwin') {
+       normalizedWorkdir = workdir.toLowerCase()
+     }
+     if (normalized === normalizedWorkdir || normalized.startsWith(normalizedWorkdir + path.sep)) {
        return true
      }
    }

Note: If you apply this, also update registerWorkdir and unregisterWorkdir to store normalized (lowercased) paths.


54-74: readDirectory and expandDirectory have identical implementations.

Both methods perform the same security check and delegate to readDirectoryShallow. If this is intentional for API clarity (semantic distinction between initial read vs lazy expand), consider adding a comment. Otherwise, one could delegate to the other.

  async expandDirectory(dirPath: string): Promise<ACP_FILE_NODE[]> {
-   // Security check: only allow reading within registered workdirs
-   if (!this.isPathAllowed(dirPath)) {
-     console.warn(`[AcpWorkspace] Blocked expand attempt for unauthorized path: ${dirPath}`)
-     return []
-   }
-   return readDirectoryShallow(dirPath)
+   // Semantically the same as readDirectory - both return shallow children
+   return this.readDirectory(dirPath)
  }
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (2)

172-180: Consider normalizing workdir path in resolveWorkdir.

The helper only trims whitespace but doesn't normalize the path (e.g., resolving relative paths, normalizing slashes). While spawnAgentProcess validates existence, the workdir stored in the handle might differ from the actual resolved path, causing unnecessary process recreation when the same logical directory is passed in different forms.

  private resolveWorkdir(workdir?: string): string {
    if (workdir && workdir.trim()) {
-     return workdir.trim()
+     return path.resolve(workdir.trim())
    }
    return this.getFallbackWorkdir()
  }

370-376: Consider removing commented-out code or using a debug flag.

Leaving commented-out code in production is generally discouraged. Consider either removing it entirely or using a debug configuration flag to enable verbose logging when needed.

-    // child.stdout?.on('data', (chunk: Buffer) => {
-    //   const output = chunk.toString().trim()
-    //   if (output) {
-    //     console.info(`[ACP] ${agent.id} stdout: ${output}`)
-    //   }
-    // })
+    // Enable stdout logging via environment variable for debugging
+    if (process.env.ACP_DEBUG_STDOUT) {
+      child.stdout?.on('data', (chunk: Buffer) => {
+        const output = chunk.toString().trim()
+        if (output) {
+          console.info(`[ACP] ${agent.id} stdout: ${output}`)
+        }
+      })
+    }

Comment on lines +178 to +184
this.summaryTitles(undefined, state.conversationId)
.then((title) => {
return this.renameConversation(state.conversationId, title)
})
.then(() => {
console.log('renameConversation success')
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Unhandled promise rejection in fire-and-forget chain.

The try/catch block on lines 185-190 will not catch errors from the promise chain since the promises are not awaited. Any rejection in summaryTitles or renameConversation will become an unhandled promise rejection.

Add a .catch() handler to properly log errors from the promise chain:

         this.summaryTitles(undefined, state.conversationId)
           .then((title) => {
             return this.renameConversation(state.conversationId, title)
           })
           .then(() => {
             console.log('renameConversation success')
           })
+          .catch((error) => {
+            console.error('[ThreadPresenter] Failed to summarize title', {
+              conversationId: state.conversationId,
+              err: error
+            })
+          })
-      } catch (error) {
-        console.error('[ThreadPresenter] Failed to summarize title', {
-          conversationId: state.conversationId,
-          err: error
-        })
       }

The surrounding try/catch can be removed since it serves no purpose for synchronous errors in this code path.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/presenter/threadPresenter/index.ts around lines 178 to 184, the
promise chain started with this.summaryTitles(...).then(...).then(...) is
fire-and-forget so the surrounding try/catch cannot catch rejections; add a
.catch(...) to the end of the chain to log or handle errors (e.g.,
processLogger.error or console.error with context and the error), and remove the
now-useless try/catch block that wraps this synchronous call path.

Comment on lines 92 to 109
"acpWorkspace": {
"title": "工作區",
"collapse": "收起",
"planSection": "計畫",
"planEmpty": "暫無任務",
"filesSection": "檔案",
"filesEmpty": "暫無檔案",
"filesLoading": "載入檔案中...",
"terminalSection": "終端機",
"terminalEmpty": "暫無輸出",
"planStatus": {
"pending": "待處理",
"in_progress": "進行中",
"completed": "已完成",
"failed": "失敗",
"skipped": "已略過"
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Translation key naming convention violations.

The new acpWorkspace translation group does not follow the documented naming convention. Per the coding guidelines, translation keys should use "dot-separated hierarchical structure with lowercase letters and descriptive names."

Current structure uses camelCase:

  • acpWorkspace → should be acp.workspace
  • planSection → should be plan.section
  • filesSection → should be files.section
  • terminalSection → should be terminal.section
  • planStatus.in_progress → mixed underscore/camelCase

While existing keys in the codebase also violate this convention, new features should adhere to the guidelines to prevent further technical debt.

Apply this diff to align with naming conventions:

-  "acpWorkspace": {
+  "acp": {
+    "workspace": {
-    "title": "工作區",
-    "collapse": "收起",
-    "planSection": "計畫",
-    "planEmpty": "暫無任務",
-    "filesSection": "檔案",
-    "filesEmpty": "暫無檔案",
-    "filesLoading": "載入檔案中...",
-    "terminalSection": "終端機",
-    "terminalEmpty": "暫無輸出",
-    "planStatus": {
-      "pending": "待處理",
-      "in_progress": "進行中",
-      "completed": "已完成",
-      "failed": "失敗",
-      "skipped": "已略過"
+      "title": "工作區",
+      "collapse": "收起",
+      "plan": {
+        "section": "計畫",
+        "empty": "暫無任務",
+        "status": {
+          "pending": "待處理",
+          "inprogress": "進行中",
+          "completed": "已完成",
+          "failed": "失敗",
+          "skipped": "已略過"
+        }
+      },
+      "files": {
+        "section": "檔案",
+        "empty": "暫無檔案",
+        "loading": "載入檔案中..."
+      },
+      "terminal": {
+        "section": "終端機",
+        "empty": "暫無輸出"
+      }
+    }
-    }
-  }
+  }

Note: This refactor will require updating all Vue component references to these translation keys.

Based on learnings, maintain consistent key-value structure across all language translation files.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/renderer/src/i18n/zh-TW/chat.json around lines 92-109, translation keys
use camelCase and underscores (e.g., acpWorkspace, planSection,
planStatus.in_progress) instead of the project's dot-separated, lowercase
hierarchical convention; rename keys to acp.workspace,
acp.workspace.plan.section, acp.workspace.plan.empty,
acp.workspace.files.section, acp.workspace.files.empty,
acp.workspace.files.loading, acp.workspace.terminal.section,
acp.workspace.terminal.empty and normalize plan status keys to
acp.workspace.plan.status.pending/in_progress/completed/failed/skipped (use
lowercase and dots, replace underscores with dots or camel parts as
appropriate), then update all Vue components and any code references to use the
new dot-separated keys to avoid runtime missing-translation errors.

Comment on lines 39 to 45
export type {
ACP_PLAN_STATUS,
ACP_PLAN_ENTRY,
ACP_FILE_NODE,
ACP_TERMINAL_SNIPPET,
ACP_RAW_PLAN_ENTRY,
IAcpWorkspacePresenter
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Type naming convention: prefer PascalCase over SCREAMING_SNAKE_CASE.

The coding guidelines specify "Use PascalCase for type and class names in TypeScript." The exported types use SCREAMING_SNAKE_CASE:

  • ACP_PLAN_STATUS → should be AcpPlanStatus
  • ACP_PLAN_ENTRY → should be AcpPlanEntry
  • ACP_FILE_NODE → should be AcpFileNode
  • ACP_TERMINAL_SNIPPET → should be AcpTerminalSnippet
  • ACP_RAW_PLAN_ENTRY → should be AcpRawPlanEntry

SCREAMING_SNAKE_CASE is conventionally reserved for constants, not type names.

If these types are defined in acp-workspace.d.ts, update both the definitions and re-exports to use PascalCase:

 // ACP Workspace types
 export type {
-  ACP_PLAN_STATUS,
-  ACP_PLAN_ENTRY,
-  ACP_FILE_NODE,
-  ACP_TERMINAL_SNIPPET,
-  ACP_RAW_PLAN_ENTRY,
+  AcpPlanStatus,
+  AcpPlanEntry,
+  AcpFileNode,
+  AcpTerminalSnippet,
+  AcpRawPlanEntry,
   IAcpWorkspacePresenter
 } from './acp-workspace'

Note: This change requires updating all references to these types throughout the codebase.

As per coding guidelines, use PascalCase for type and class names in TypeScript files.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/shared/types/presenters/index.d.ts around lines 39–45, exported type
names use SCREAMING_SNAKE_CASE; rename them to PascalCase (ACP_PLAN_STATUS →
AcpPlanStatus, ACP_PLAN_ENTRY → AcpPlanEntry, ACP_FILE_NODE → AcpFileNode,
ACP_TERMINAL_SNIPPET → AcpTerminalSnippet, ACP_RAW_PLAN_ENTRY → AcpRawPlanEntry)
and update the export list accordingly; also update the original definitions
(e.g., in acp-workspace.d.ts) to the new PascalCase names and run a project-wide
find-and-replace to update all imports/uses and any re-exports to the new names
so the codebase compiles with the PascalCase type names.

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

Caution

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

⚠️ Outside diff range comments (1)
src/renderer/src/i18n/pt-BR/chat.json (1)

20-23: Translate untranslated English strings to Portuguese.

Lines 20-23 contain English strings in a Portuguese (Brazil) translation file. These should be translated to maintain consistency with the rest of the file.

Apply this diff to translate these strings to Portuguese:

-    "acpWorkdir": "ACP Workdir",
-    "acpWorkdirTooltip": "Set ACP working directory",
-    "acpWorkdirSelect": "Select a folder to use as the ACP workdir",
-    "acpWorkdirCurrent": "Current workdir: {path}",
+    "acpWorkdir": "Diretório de Trabalho ACP",
+    "acpWorkdirTooltip": "Defina o diretório de trabalho ACP",
+    "acpWorkdirSelect": "Selecione uma pasta para usar como diretório de trabalho ACP",
+    "acpWorkdirCurrent": "Diretório de trabalho atual: {path}",
🧹 Nitpick comments (5)
src/renderer/src/i18n/pt-BR/chat.json (1)

92-117: Update coding guidelines to include all supported locales.

The ACP workspace translation structure in pt-BR/chat.json is consistent with all other language files (en-US, zh-CN, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR). All locales have identical key structures with proper dot-separated hierarchical naming. However, the coding guidelines list only 7 supported locales while the repository actually supports 11 locales (en-US, zh-CN, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR, pt-BR, da-DK, ja-JP, zh-TW). Update the guidelines to reflect the full set of supported locales.

src/main/presenter/acpWorkspacePresenter/planStateManager.ts (1)

74-94: Consider clarifying ordering and making status normalization more defensive

Two small, non-blocking improvements you might consider:

  • getEntries relies on Map insertion order; if the UI expects a specific ordering (e.g., by updatedAt), consider returning a sorted array to make ordering explicit.
  • normalizeStatus currently matches exact lowercase values. If upstream ever sends variants like "Completed" or "IN_PROGRESS", they’ll silently become 'pending'. Normalizing with status?.toLowerCase() before the switch (and maybe documenting accepted values) would make this more robust to small upstream changes.

Also applies to: 99-118

src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue (1)

70-72: Wrap handleToggle in try/catch to avoid unhandled rejections

handleToggle awaits store.toggleFileNode(node) without error handling. If the presenter throws (e.g. IPC failure), this will surface as an unhandled rejection in the UI.

You can defensively wrap it and log a concise error:

-const handleToggle = async (node: AcpFileNode) => {
-  await store.toggleFileNode(node)
-}
+const handleToggle = async (node: AcpFileNode) => {
+  try {
+    await store.toggleFileNode(node)
+  } catch (error) {
+    // Replace with shared logger if available
+    console.error('[AcpWorkspaceFiles] Failed to toggle file node', error)
+  }
+}
src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue (1)

3-36: Consider adding aria-expanded for directory buttons (a11y improvement)

The recursive tree rendering is correct, but directory rows don’t expose their expanded state to assistive tech.

You can add an aria-expanded binding only for directories:

-    <button
-      class="flex w-full items-center gap-1.5 px-4 py-1 text-left text-xs transition hover:bg-muted/40"
-      :style="{ paddingLeft: `${16 + depth * 12}px` }"
-      type="button"
-      @click="handleClick"
-    >
+    <button
+      class="flex w-full items-center gap-1.5 px-4 py-1 text-left text-xs transition hover:bg-muted/40"
+      :style="{ paddingLeft: `${16 + depth * 12}px` }"
+      type="button"
+      @click="handleClick"
+      :aria-expanded="node.isDirectory ? String(node.expanded) : undefined"
+    >

This keeps behavior unchanged while improving screen‑reader support.

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

127-188: Per-agent locking and workdir-aware spawning resolve the previous race condition

The new flow in getConnection plus agentLocks largely fixes the earlier concurrency issue around pendingHandles:

  • resolveWorkdir normalizes the target workdir (with a fallback to a constrained temp directory).
  • A fast path returns an existing alive handle with matching workdir.
  • The critical section is serialized per agent via acquireAgentLock, re-checking handles and pendingHandles under the lock before deciding to release or spawnProcess.
  • spawnProcess / spawnAgentProcess now track workdir on the handle and use it as cwd, with a safe fallback to HOME_DIR if the directory does not exist, and detailed logging around initialization.

This should prevent duplicate process spawns for the same agent and avoid the TOCTOU window that was called out previously.

A couple of non-blocking ideas you might consider (not required for this PR):

  • If you expect release(agentId) to be called concurrently with getConnection(agentId, ...), you could also route release through acquireAgentLock to guarantee consistent interaction with handles and pendingHandles.
  • If you have a shared logging utility in main, you may eventually want to migrate the newer console.info/warn/error calls in this block to that logger for consistency.

Overall, the new locking and workdir-aware spawning look correct and significantly more robust than the previous version.

Also applies to: 271-400, 402-406, 584-593, 722-739

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6036035 and 43fa963.

📒 Files selected for processing (25)
  • src/main/presenter/acpWorkspacePresenter/directoryReader.ts (1 hunks)
  • src/main/presenter/acpWorkspacePresenter/index.ts (1 hunks)
  • src/main/presenter/acpWorkspacePresenter/planStateManager.ts (1 hunks)
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (9 hunks)
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue (1 hunks)
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue (1 hunks)
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue (1 hunks)
  • src/renderer/src/components/acp-workspace/AcpWorkspaceTerminal.vue (1 hunks)
  • src/renderer/src/components/acp-workspace/AcpWorkspaceView.vue (1 hunks)
  • src/renderer/src/components/message/MessageActionButtons.vue (2 hunks)
  • src/renderer/src/components/message/MessageBlockPermissionRequest.vue (3 hunks)
  • src/renderer/src/i18n/da-DK/chat.json (1 hunks)
  • src/renderer/src/i18n/en-US/chat.json (2 hunks)
  • src/renderer/src/i18n/fa-IR/chat.json (2 hunks)
  • src/renderer/src/i18n/fr-FR/chat.json (2 hunks)
  • src/renderer/src/i18n/ja-JP/chat.json (2 hunks)
  • src/renderer/src/i18n/ko-KR/chat.json (2 hunks)
  • src/renderer/src/i18n/pt-BR/chat.json (2 hunks)
  • src/renderer/src/i18n/ru-RU/chat.json (2 hunks)
  • src/renderer/src/i18n/zh-CN/chat.json (2 hunks)
  • src/renderer/src/i18n/zh-HK/chat.json (2 hunks)
  • src/renderer/src/i18n/zh-TW/chat.json (2 hunks)
  • src/renderer/src/stores/acpWorkspace.ts (1 hunks)
  • src/shared/types/presenters/acp-workspace.d.ts (1 hunks)
  • src/shared/types/presenters/index.d.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/renderer/src/components/acp-workspace/AcpWorkspaceView.vue
  • src/renderer/src/i18n/fa-IR/chat.json
  • src/renderer/src/components/message/MessageBlockPermissionRequest.vue
  • src/renderer/src/i18n/da-DK/chat.json
  • src/main/presenter/acpWorkspacePresenter/directoryReader.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspaceTerminal.vue
  • src/renderer/src/i18n/ko-KR/chat.json
  • src/renderer/src/components/message/MessageActionButtons.vue
🧰 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/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/presenter/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.d.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/acpWorkspacePresenter/planStateManager.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/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/acpWorkspacePresenter/planStateManager.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/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/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/presenter/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.d.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/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
src/**/*

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

New features should be developed in the src directory

Files:

  • src/main/presenter/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue
  • src/renderer/src/i18n/ja-JP/chat.json
  • src/renderer/src/i18n/pt-BR/chat.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/renderer/src/i18n/zh-HK/chat.json
  • src/renderer/src/i18n/zh-CN/chat.json
  • src/renderer/src/i18n/en-US/chat.json
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/renderer/src/i18n/fr-FR/chat.json
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.d.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/acpWorkspacePresenter/planStateManager.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/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/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.d.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use OxLint for linting JavaScript and TypeScript files

Files:

  • src/main/presenter/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/presenter/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.d.ts
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use EventBus for inter-process communication events

Files:

  • src/main/presenter/acpWorkspacePresenter/planStateManager.ts
  • src/renderer/src/stores/acpWorkspace.ts
  • src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/stores/acpWorkspace.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/stores/acpWorkspace.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/stores/acpWorkspace.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/stores/acpWorkspace.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/i18n/ja-JP/chat.json
  • src/renderer/src/i18n/pt-BR/chat.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/stores/acpWorkspace.ts
  • src/renderer/src/i18n/zh-HK/chat.json
  • src/renderer/src/i18n/zh-CN/chat.json
  • src/renderer/src/i18n/en-US/chat.json
  • src/renderer/src/i18n/fr-FR/chat.json
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/stores/acpWorkspace.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/stores/acpWorkspace.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
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/ja-JP/chat.json
  • src/renderer/src/i18n/pt-BR/chat.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/i18n/zh-HK/chat.json
  • src/renderer/src/i18n/zh-CN/chat.json
  • src/renderer/src/i18n/en-US/chat.json
  • src/renderer/src/i18n/fr-FR/chat.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/stores/acpWorkspace.ts
src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx}

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

src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx}: Use modules to organize related state and actions in Pinia stores
Implement proper state persistence for maintaining data across sessions in Pinia stores
Use getters for computed state properties in Pinia stores
Utilize actions for side effects and asynchronous operations in Pinia stores
Keep Pinia stores focused on global state, not component-specific data

Files:

  • src/renderer/src/stores/acpWorkspace.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/stores/acpWorkspace.ts
src/renderer/**/stores/*.ts

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

Use Pinia for state management

Files:

  • src/renderer/src/stores/acpWorkspace.ts
src/renderer/src/stores/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use Pinia for state management

Files:

  • src/renderer/src/stores/acpWorkspace.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/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/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/acp-workspace.d.ts
  • src/shared/types/presenters/index.d.ts
🧠 Learnings (46)
📚 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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
📚 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/**/*.{ts,tsx,vue} : 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/`

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/acp-workspace/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
📚 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/acp-workspace/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vue
  • src/renderer/src/i18n/zh-TW/chat.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/renderer/src/**/*.{ts,tsx,vue} : Use TypeScript with Vue 3 Composition API for the renderer application

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.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} : Leverage Vue's built-in reactivity system for efficient data handling

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.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 **/*.vue : Use Vue 3 Composition API for all components instead of Options API

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.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/(components|composables)/**/*.{ts,vue} : Utilize Nuxt's auto-imports feature for components and composables

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vue
  • 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/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/ja-JP/chat.json
  • src/renderer/src/i18n/pt-BR/chat.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/i18n/zh-HK/chat.json
  • src/renderer/src/i18n/zh-CN/chat.json
  • src/renderer/src/i18n/en-US/chat.json
  • src/renderer/src/i18n/fr-FR/chat.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/ja-JP/chat.json
  • src/renderer/src/i18n/pt-BR/chat.json
  • src/renderer/src/i18n/ru-RU/chat.json
  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/i18n/zh-HK/chat.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/ja-JP/chat.json
  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/i18n/zh-HK/chat.json
  • src/shared/types/presenters/index.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 : Import Icon component from 'iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'

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/i18n/zh-TW/chat.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/renderer/src/**/*.{ts,tsx,vue} : All user-facing strings must use vue-i18n keys in `src/renderer/src/i18n`

Applied to files:

  • src/renderer/src/i18n/zh-TW/chat.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/**/*.{vue,ts,tsx} : All user-facing strings must use i18n keys with vue-i18n framework in the renderer

Applied to files:

  • src/renderer/src/i18n/zh-TW/chat.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 src/renderer/**/*.vue : All user-facing strings must use i18n keys via vue-i18n for internationalization

Applied to files:

  • src/renderer/src/i18n/zh-TW/chat.json
📚 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 PascalCase for component names (e.g., AuthWizard.vue)

Applied to files:

  • src/renderer/src/i18n/zh-TW/chat.json
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
  • src/shared/types/presenters/index.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/renderer/src/stores/**/*.ts : Use Pinia for state management

Applied to files:

  • src/renderer/src/stores/acpWorkspace.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/**/stores/*.ts : Use Pinia for state management

Applied to files:

  • src/renderer/src/stores/acpWorkspace.ts
📚 Learning: 2025-11-25T05:27:20.067Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/pinia-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:27:20.067Z
Learning: Applies to src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx} : Use modules to organize related state and actions in Pinia stores

Applied to files:

  • src/renderer/src/stores/acpWorkspace.ts
📚 Learning: 2025-11-25T05:27:20.067Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/pinia-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:27:20.067Z
Learning: Applies to src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx} : Implement proper state persistence for maintaining data across sessions in Pinia stores

Applied to files:

  • src/renderer/src/stores/acpWorkspace.ts
📚 Learning: 2025-11-25T05:27:20.067Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/pinia-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:27:20.067Z
Learning: Applies to src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx} : Keep Pinia stores focused on global state, not component-specific data

Applied to files:

  • src/renderer/src/stores/acpWorkspace.ts
📚 Learning: 2025-11-25T05:27:20.067Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/pinia-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:27:20.067Z
Learning: Applies to src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx} : Utilize actions for side effects and asynchronous operations in Pinia stores

Applied to files:

  • src/renderer/src/stores/acpWorkspace.ts
📚 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} : Implement proper state management with Pinia in Vue.js applications

Applied to files:

  • src/renderer/src/stores/acpWorkspace.ts
  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
📚 Learning: 2025-11-25T05:27:20.067Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/pinia-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:27:20.067Z
Learning: Applies to src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx} : Use getters for computed state properties in Pinia stores

Applied to files:

  • src/renderer/src/stores/acpWorkspace.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/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/agent/acpProcessManager.ts
  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.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/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: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/**/*.ts : Organize core business logic into dedicated Presenter classes, with one presenter per functional domain

Applied to files:

  • src/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/main/presenter/acpWorkspacePresenter/index.ts
  • src/shared/types/presenters/acp-workspace.d.ts
  • src/shared/types/presenters/index.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/main/presenter/acpWorkspacePresenter/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/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

Applied to files:

  • src/main/presenter/acpWorkspacePresenter/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/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/acpWorkspacePresenter/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/renderer/**/*.vue : Ensure proper error handling and loading states in all UI components

Applied to files:

  • src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue
📚 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,tsx} : Use SCREAMING_SNAKE_CASE for constant names

Applied to files:

  • src/shared/types/presenters/index.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/**/*.{ts,tsx} : Use PascalCase for type and class names in TypeScript

Applied to files:

  • src/shared/types/presenters/index.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/**/*.{ts,tsx} : Use camelCase for variable and function names in TypeScript files

Applied to files:

  • src/shared/types/presenters/index.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/**/composables/*.ts : Use camelCase for composables (e.g., useAuthState.ts)

Applied to files:

  • src/shared/types/presenters/index.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: Use conventional commits with format `type(scope): subject` ≤ 50 chars; types: `feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release`

Applied to files:

  • src/shared/types/presenters/index.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/**/*.{ts,tsx} : Use TypeScript for all code; prefer types over interfaces

Applied to files:

  • src/shared/types/presenters/index.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/shared/**/*.ts : Shared types and utilities should be placed in `src/shared/`

Applied to files:

  • src/shared/types/presenters/index.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/**/*.{ts,tsx,vue} : Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)

Applied to files:

  • src/shared/types/presenters/index.d.ts
🧬 Code graph analysis (4)
src/main/presenter/acpWorkspacePresenter/planStateManager.ts (1)
src/shared/types/presenters/acp-workspace.d.ts (3)
  • AcpPlanEntry (14-25)
  • AcpRawPlanEntry (66-70)
  • AcpPlanStatus (9-9)
src/renderer/src/stores/acpWorkspace.ts (4)
src/renderer/src/composables/usePresenter.ts (1)
  • usePresenter (103-105)
src/shared/types/presenters/acp-workspace.d.ts (3)
  • AcpPlanEntry (14-25)
  • AcpFileNode (30-41)
  • AcpTerminalSnippet (46-61)
src/main/events.ts (1)
  • ACP_WORKSPACE_EVENTS (235-240)
src/renderer/src/events.ts (1)
  • ACP_WORKSPACE_EVENTS (176-181)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (1)
src/shared/types/presenters/legacy.presenters.d.ts (1)
  • AcpAgentConfig (723-729)
src/shared/types/presenters/acp-workspace.d.ts (1)
src/shared/types/presenters/index.d.ts (6)
  • AcpPlanStatus (40-40)
  • AcpPlanEntry (41-41)
  • AcpFileNode (42-42)
  • AcpTerminalSnippet (43-43)
  • AcpRawPlanEntry (44-44)
  • IAcpWorkspacePresenter (45-45)
⏰ 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 (13)
src/renderer/src/i18n/zh-CN/chat.json (2)

92-117: Workspace i18n keys follow naming conventions and are properly structured.

The new acp.workspace object uses consistent dot-separated hierarchical naming (e.g., acp.workspace.plan.section), follows lowercase conventions, and is logically organized. All workspace sub-sections (plan with 5 status values, files, terminal) are present with appropriate Chinese translations.


92-117: All language locale files maintain consistent acp.workspace key-value structure.

Verification confirms that all 11 translation files (da-DK, en-US, fa-IR, fr-FR, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW) contain identical nested structures for acp.workspace:

  • Top level: collapse, files, plan, terminal, title
  • plan.status: completed, failed, in_progress, pending, skipped
  • files: empty, loading, section
  • terminal: empty, section

No inconsistencies found. The structure is properly maintained across all locales.

src/main/presenter/acpWorkspacePresenter/planStateManager.ts (1)

22-53: Incremental merge, dedupe, and pruning logic looks solid

The updateEntries flow correctly:

  • Initializes a per-conversation store
  • Deduplicates by normalized content hash
  • Upserts existing entries while preserving priority when not provided
  • Updates updatedAt on each change and prunes via pruneCompletedEntries
  • Returns the full per-conversation snapshot

This matches the shared types and should behave predictably for the renderer.

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

25-26: ACP workspace i18n structure is consistent and aligned with shared types

The new acp.workspace block (plan/files/terminal + status.*) mirrors the en-US structure and matches AcpPlanStatus values (pending, in_progress, completed, failed, skipped). Keeping acpModeTooltip while adding acp.workspace maintains backward compatibility for existing UI.

Based on learnings, this also respects the hierarchical key structure across locales.

Also applies to: 92-116

src/renderer/src/i18n/zh-HK/chat.json (1)

25-26: zh-HK ACP workspace keys mirror the canonical structure

acp.workspace (plan/files/terminal + plan.status entries) is structurally identical to the other locales, ensuring no missing-key issues at runtime. Status leaf key in_progress matches the shared AcpPlanStatus union.

Based on learnings, this keeps the i18n key structure consistent across locales.

Also applies to: 92-116

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

25-26: ja-JP workspace translations follow the shared ACP schema

The added acp.workspace plan/files/terminal sections and plan.status keys match the other locales’ structure and shared types, so consumers can rely on acp.workspace.* uniformly.

Based on learnings, this maintains the required key structure parity across locales.

Also applies to: 92-116

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

25-26: fr-FR workspace block is complete and aligned with other locales

acp.workspace includes all expected subsections (plan/files/terminal) and status keys, matching the en-US schema. This should prevent missing-translation issues when the ACP workspace UI renders in French.

Based on learnings, key/value structure is consistent with other language files.

Also applies to: 92-116

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

25-26: New acp.workspace schema is a good, extensible base for ACP UI

The en-US acp.workspace hierarchy (plan/files/terminal + plan.status.*) is clean, lowercased, and matches AcpPlanStatus values, giving a solid canonical shape for other locales and components (acp.workspace.plan.section, etc.). Keeping acpModeTooltip preserves compatibility with existing UI while shifting new workspace copy under acp.

Based on learnings, this aligns with the intended dot-separated hierarchical key pattern.

Also applies to: 81-116

src/shared/types/presenters/acp-workspace.d.ts (1)

9-128: Shared ACP workspace types are well-structured and consistent

The type surface (AcpPlanStatus, AcpPlanEntry, AcpFileNode, AcpTerminalSnippet, AcpRawPlanEntry, IAcpWorkspacePresenter) is clear, uses PascalCase, and matches usages elsewhere (plan state manager, i18n plan.status.*, directory reader, terminal snippets). The IAcpWorkspacePresenter interface cleanly separates workspace concerns from other presenters.

As per coding guidelines, this keeps shared types centralized under src/shared with proper naming conventions.

src/shared/types/presenters/index.d.ts (1)

38-46: Barrel now correctly exposes ACP workspace types with PascalCase names

Re-exporting AcpPlanStatus, AcpPlanEntry, AcpFileNode, AcpTerminalSnippet, AcpRawPlanEntry, and IAcpWorkspacePresenter from './acp-workspace' aligns with the naming guidelines and simplifies imports for consumers of the presenter types.

As per coding guidelines, types are PascalCase and centralized in the shared presenters index.

src/renderer/src/components/acp-workspace/AcpWorkspacePlan.vue (1)

2-55: Plan section wiring and progress rendering look solid

The component correctly gates on store.planEntries.length, uses the i18n key for the section label, and derives counts/progress from the store. Status icon/text-class helpers cover all AcpPlanStatus variants with sensible defaults.

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

14-74: Workspace presenter security and IPC usage look correct

allowedWorkdirs + isPathAllowed give a clear security boundary, and both readDirectory and expandDirectory enforce it before calling readDirectoryShallow. Plan and terminal updates are pushed via eventBus.sendToRenderer with the expected ACP_WORKSPACE_EVENTS payloads.

src/renderer/src/i18n/ru-RU/chat.json (1)

92-117: acp.workspace key structure is consistent across all locales

The new chat.acp.workspace.* hierarchy is present and identical across all 11 supported locale files (da-DK, en-US, fa-IR, fr-FR, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW). The keys follow the required dot-separated naming convention with lowercase and underscores. No missing or inconsistent keys detected.

@zerob13 zerob13 merged commit 7acb9fe into dev Dec 4, 2025
2 checks passed
zerob13 added a commit that referenced this pull request Dec 8, 2025
* feat: add workspaceview for acp agent

* feat: support workspace dirs

* fix: workspace file refresh

* fix: tool call status

* fix: review refactor
zerob13 added a commit that referenced this pull request Dec 8, 2025
* 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
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 ui/workspace-view 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