-
Notifications
You must be signed in to change notification settings - Fork 614
feat: add workspace view to acp agents #1158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds 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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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, andacpWorkdirSelectkeys 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 truncatedNameUsing
truncatedNamehere keeps long tool names from breaking the collapsed layout and matches the expanded view header logic. Consider optionally exposing the full name via atitleattribute 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
getStatusTextstill 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
acpWorkspacePresenteris initialized correctly, but there's no corresponding cleanup in thedestroy()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
countFilesfunction 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
countNodesfor 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
availableModesbut 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 usingbreak-wordsinstead ofbreak-allfor terminal output.The
break-allutility will break words in the middle, which can make terminal output harder to read. Thebreak-wordsutility 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 errorsWiring
onFileChangethrough options intowriteTextFilelooks clean, but invoking an arbitrary callback directly afterfs.writeFilemeans any exception thrown in the callback will cause the wholewriteTextFilerequest to fail even though the file is already persisted.Consider either:
- wrapping the callback in a small
try/catchwith structured logging so write semantics are not affected by observer failures, or- clearly documenting that
onFileChangemust 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 stepSwitching to
propsplus asanitizedContentcomputed that strips<style>tags, and then gatingNodeRendereron 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
nodeparameter. While Vue's reactivity will track these changes, mutating function arguments is harder to reason about. Also, settingexpanded = trueon 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
currentWorkdirwatcher (line 212) andisAcpModewatcher (line 223) have{ immediate: true }and both callrefreshFileTree(). 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 withreadDirectoryShallow- 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
@deprecatedJSDoc 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 pathsrc/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/projectand/users/test/projectrefer 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
registerWorkdirandunregisterWorkdirto store normalized (lowercased) paths.
54-74:readDirectoryandexpandDirectoryhave 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 inresolveWorkdir.The helper only trims whitespace but doesn't normalize the path (e.g., resolving relative paths, normalizing slashes). While
spawnAgentProcessvalidates 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}`) + } + }) + }
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
Outdated
Show resolved
Hide resolved
| this.summaryTitles(undefined, state.conversationId) | ||
| .then((title) => { | ||
| return this.renameConversation(state.conversationId, title) | ||
| }) | ||
| .then(() => { | ||
| console.log('renameConversation success') | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| "acpWorkspace": { | ||
| "title": "工作區", | ||
| "collapse": "收起", | ||
| "planSection": "計畫", | ||
| "planEmpty": "暫無任務", | ||
| "filesSection": "檔案", | ||
| "filesEmpty": "暫無檔案", | ||
| "filesLoading": "載入檔案中...", | ||
| "terminalSection": "終端機", | ||
| "terminalEmpty": "暫無輸出", | ||
| "planStatus": { | ||
| "pending": "待處理", | ||
| "in_progress": "進行中", | ||
| "completed": "已完成", | ||
| "failed": "失敗", | ||
| "skipped": "已略過" | ||
| } | ||
| } |
There was a problem hiding this comment.
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 beacp.workspaceplanSection→ should beplan.sectionfilesSection→ should befiles.sectionterminalSection→ should beterminal.sectionplanStatus.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.
| export type { | ||
| ACP_PLAN_STATUS, | ||
| ACP_PLAN_ENTRY, | ||
| ACP_FILE_NODE, | ||
| ACP_TERMINAL_SNIPPET, | ||
| ACP_RAW_PLAN_ENTRY, | ||
| IAcpWorkspacePresenter |
There was a problem hiding this comment.
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 beAcpPlanStatusACP_PLAN_ENTRY→ should beAcpPlanEntryACP_FILE_NODE→ should beAcpFileNodeACP_TERMINAL_SNIPPET→ should beAcpTerminalSnippetACP_RAW_PLAN_ENTRY→ should beAcpRawPlanEntry
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.
There was a problem hiding this 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 defensiveTwo small, non-blocking improvements you might consider:
getEntriesrelies onMapinsertion order; if the UI expects a specific ordering (e.g., byupdatedAt), consider returning a sorted array to make ordering explicit.normalizeStatuscurrently matches exact lowercase values. If upstream ever sends variants like"Completed"or"IN_PROGRESS", they’ll silently become'pending'. Normalizing withstatus?.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: WraphandleTogglein try/catch to avoid unhandled rejections
handleToggleawaitsstore.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 addingaria-expandedfor 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-expandedbinding 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 conditionThe new flow in
getConnectionplusagentLockslargely fixes the earlier concurrency issue aroundpendingHandles:
resolveWorkdirnormalizes 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-checkinghandlesandpendingHandlesunder the lock before deciding toreleaseorspawnProcess.spawnProcess/spawnAgentProcessnow trackworkdiron the handle and use it ascwd, with a safe fallback toHOME_DIRif 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 withgetConnection(agentId, ...), you could also routereleasethroughacquireAgentLockto guarantee consistent interaction withhandlesandpendingHandles.- If you have a shared logging utility in main, you may eventually want to migrate the newer
console.info/warn/errorcalls 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
📒 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.tssrc/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/renderer/src/components/acp-workspace/AcpWorkspacePlan.vuesrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.ts
src/main/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use EventBus from
src/main/eventbus.tsfor main-to-renderer communication, broadcasting events viamainWindow.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 insrc/main/with presenters inpresenter/(Window/Tab/Thread/Mcp/Config/LLMProvider) andeventbus.tsfor app events
Use the Presenter pattern in the main process for UI coordination
Files:
src/main/presenter/acpWorkspacePresenter/planStateManager.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/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.tssrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.ts
src/**/*
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
New features should be developed in the
srcdirectory
Files:
src/main/presenter/acpWorkspacePresenter/planStateManager.tssrc/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vuesrc/renderer/src/i18n/ja-JP/chat.jsonsrc/renderer/src/i18n/pt-BR/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/i18n/zh-TW/chat.jsonsrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/renderer/src/i18n/zh-HK/chat.jsonsrc/renderer/src/i18n/zh-CN/chat.jsonsrc/renderer/src/i18n/en-US/chat.jsonsrc/main/presenter/acpWorkspacePresenter/index.tssrc/renderer/src/i18n/fr-FR/chat.jsonsrc/renderer/src/components/acp-workspace/AcpWorkspacePlan.vuesrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/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.tssrc/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/renderer/src/components/acp-workspace/AcpWorkspacePlan.vuesrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/renderer/src/stores/acpWorkspace.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/stores/acpWorkspace.tssrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/stores/acpWorkspace.tssrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/stores/acpWorkspace.tssrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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 statementsVue 3 app code in
src/renderer/srcshould be organized intocomponents/,stores/,views/,i18n/,lib/directories with shell UI insrc/renderer/shell/
Files:
src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/stores/acpWorkspace.tssrc/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.vuesrc/renderer/src/i18n/ja-JP/chat.jsonsrc/renderer/src/i18n/pt-BR/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/i18n/zh-TW/chat.jsonsrc/renderer/src/stores/acpWorkspace.tssrc/renderer/src/i18n/zh-HK/chat.jsonsrc/renderer/src/i18n/zh-CN/chat.jsonsrc/renderer/src/i18n/en-US/chat.jsonsrc/renderer/src/i18n/fr-FR/chat.jsonsrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/stores/acpWorkspace.tssrc/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 insrc/renderer/src/i18n
Files:
src/renderer/src/components/acp-workspace/AcpWorkspaceFiles.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/renderer/src/stores/acpWorkspace.tssrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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.jsonsrc/renderer/src/i18n/pt-BR/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/zh-TW/chat.jsonsrc/renderer/src/i18n/zh-HK/chat.jsonsrc/renderer/src/i18n/zh-CN/chat.jsonsrc/renderer/src/i18n/en-US/chat.jsonsrc/renderer/src/i18n/fr-FR/chat.json
src/renderer/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use the
usePresenter.tscomposable 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
LLMCoreStreamEventinterface 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,usageobject with token counts,stop_reason(tool_use | max_tokens | stop_sequence | error | complete), andimage_dataobject 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.tssrc/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.tssrc/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.tssrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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.vuesrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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.vuesrc/renderer/src/components/acp-workspace/AcpWorkspaceFileNode.vuesrc/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.vuesrc/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.vuesrc/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.jsonsrc/renderer/src/i18n/pt-BR/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/zh-TW/chat.jsonsrc/renderer/src/i18n/zh-HK/chat.jsonsrc/renderer/src/i18n/zh-CN/chat.jsonsrc/renderer/src/i18n/en-US/chat.jsonsrc/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.jsonsrc/renderer/src/i18n/pt-BR/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/zh-TW/chat.jsonsrc/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.jsonsrc/renderer/src/i18n/zh-TW/chat.jsonsrc/renderer/src/i18n/zh-HK/chat.jsonsrc/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.jsonsrc/renderer/src/components/acp-workspace/AcpWorkspacePlan.vuesrc/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.tssrc/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.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/main/presenter/acpWorkspacePresenter/index.tssrc/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.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.tssrc/shared/types/presenters/acp-workspace.d.tssrc/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.workspaceobject 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 consistentacp.workspacekey-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 solidThe
updateEntriesflow correctly:
- Initializes a per-conversation store
- Deduplicates by normalized content hash
- Upserts existing entries while preserving priority when not provided
- Updates
updatedAton each change and prunes viapruneCompletedEntries- 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 typesThe new
acp.workspaceblock (plan/files/terminal +status.*) mirrors the en-US structure and matchesAcpPlanStatusvalues (pending,in_progress,completed,failed,skipped). KeepingacpModeTooltipwhile addingacp.workspacemaintains 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.statusentries) is structurally identical to the other locales, ensuring no missing-key issues at runtime. Status leaf keyin_progressmatches the sharedAcpPlanStatusunion.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 schemaThe added
acp.workspaceplan/files/terminal sections andplan.statuskeys match the other locales’ structure and shared types, so consumers can rely onacp.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.workspaceincludes 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: Newacp.workspaceschema is a good, extensible base for ACP UIThe en-US
acp.workspacehierarchy (plan/files/terminal +plan.status.*) is clean, lowercased, and matchesAcpPlanStatusvalues, giving a solid canonical shape for other locales and components (acp.workspace.plan.section, etc.). KeepingacpModeTooltippreserves compatibility with existing UI while shifting new workspace copy underacp.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 consistentThe 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/sharedwith proper naming conventions.src/shared/types/presenters/index.d.ts (1)
38-46: Barrel now correctly exposes ACP workspace types with PascalCase namesRe-exporting
AcpPlanStatus,AcpPlanEntry,AcpFileNode,AcpTerminalSnippet,AcpRawPlanEntry, andIAcpWorkspacePresenterfrom'./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 solidThe 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 allAcpPlanStatusvariants with sensible defaults.src/main/presenter/acpWorkspacePresenter/index.ts (1)
14-74: Workspace presenter security and IPC usage look correct
allowedWorkdirs+isPathAllowedgive a clear security boundary, and bothreadDirectoryandexpandDirectoryenforce it before callingreadDirectoryShallow. Plan and terminal updates are pushed viaeventBus.sendToRendererwith the expectedACP_WORKSPACE_EVENTSpayloads.src/renderer/src/i18n/ru-RU/chat.json (1)
92-117: acp.workspace key structure is consistent across all localesThe 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.
* feat: add workspaceview for acp agent * feat: support workspace dirs * fix: workspace file refresh * fix: tool call status * fix: review refactor
* 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
* 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>
Summary by CodeRabbit
New Features
Localization
Infrastructure
✏️ Tip: You can customize this high-level summary in your review settings.