-
Notifications
You must be signed in to change notification settings - Fork 614
feat: add support for acp plan and file #1156
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
- Add AcpCapabilities module for client capability declaration - Implement AcpFsHandler for read_text_file and write_text_file with workspace boundary validation - Implement AcpTerminalManager for PTY-based terminal execution with output buffering and lifecycle management - Update acpProcessManager to wire fs/terminal handlers and advertise capabilities during initialization - Register session workdirs for fs operation security checks
- Improve plan updates with structured PlanEntry type - Add status icons and formatted plan display - Handle current_mode_update notifications - Store plan entries and mode changes in MappedContent - Add extra metadata to reasoning blocks for UI access
…nt mapper - Add tests for buildClientCapabilities options - Add comprehensive tests for AcpFsHandler: - Path validation and workspace boundary checks - Read with line offset and limit parameters - Write with directory creation - Add tests for plan and mode update handling in content mapper: - Structured plan entries with status icons - Mode change notifications
WalkthroughAdds ACP protocol support: client capability builder, per-session filesystem and PTY-backed terminal manager, plan/mode handling and types, renderer plan & terminal UI with i18n, presenter APIs for session modes, tests, docs, and a minor version bump. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant SessionMgr as AcpSessionManager
participant ProcessMgr as AcpProcessManager
participant TerminalMgr as AcpTerminalManager
participant FsHandler as AcpFsHandler
participant Renderer
Client->>SessionMgr: initializeSession()/createSession()
SessionMgr->>ProcessMgr: registerSessionWorkdir(sessionId, workdir)
ProcessMgr->>FsHandler: create per-session FsHandler(workdir)
ProcessMgr->>TerminalMgr: ensure TerminalManager
Client->>ProcessMgr: openConnection(capabilities from buildClientCapabilities)
Client->>ProcessMgr: send tool_call / notifications
alt terminal tool
ProcessMgr->>TerminalMgr: createTerminal(request)
TerminalMgr-->>ProcessMgr: terminalId
TerminalMgr-->>ProcessMgr: terminalOutput events
ProcessMgr->>Renderer: emit terminal output block
else filesystem tool
ProcessMgr->>FsHandler: readTextFile / writeTextFile
FsHandler-->>ProcessMgr: response or ACP error
ProcessMgr->>Renderer: emit file-operation block
end
Client->>SessionMgr: mode change / plan update
SessionMgr->>ProcessMgr: persist currentModeId / planEntries
ProcessMgr->>Renderer: emit plan or reasoning block
Client->>ProcessMgr: clearSession / shutdown
ProcessMgr->>TerminalMgr: releaseSessionTerminals(sessionId)
ProcessMgr->>FsHandler: cleanup per-session handlers
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
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (1)
606-618: Resource leak:clearSessionsForAgentdoes not clean upsessionWorkdirsandfsHandlers.When an agent exits,
clearSessionsForAgentcleans session listeners and permission resolvers but leavessessionWorkdirsandfsHandlersentries orphaned for those sessions.private clearSessionsForAgent(agentId: string): void { for (const [sessionId, entry] of this.sessionListeners.entries()) { if (entry.agentId === agentId) { this.sessionListeners.delete(sessionId) + this.sessionWorkdirs.delete(sessionId) + this.fsHandlers.delete(sessionId) + void this.terminalManager.releaseSessionTerminals(sessionId) } } for (const [sessionId, entry] of this.permissionResolvers.entries()) { if (entry.agentId === agentId) { this.permissionResolvers.delete(sessionId) } } }
🟠 Major comments (16)
src/renderer/src/i18n/zh-HK/plan.json-2-3 (1)
2-3: Provide Hong Kong Chinese translations instead of English values.The plan.json file for zh-HK locale contains English text ("Task Plan", "completed") rather than Traditional Chinese translations. All user-facing strings must be localized to the target language.
Provide the Hong Kong Chinese translations for these keys:
{ - "title": "Task Plan", - "completed": "completed" + "title": "任務計劃", + "completed": "已完成" }src/renderer/src/i18n/zh-TW/plan.json-2-3 (1)
2-3: Provide Traditional Chinese translations instead of English values.The plan.json file for zh-TW locale contains English text ("Task Plan", "completed") rather than Traditional Chinese translations. Per coding guidelines and the i18n pattern across the codebase, user-facing strings must be localized to their target language.
Provide the Traditional Chinese translations for these keys:
{ - "title": "Task Plan", - "completed": "completed" + "title": "任務計劃", + "completed": "已完成" }src/renderer/src/i18n/ko-KR/plan.json-2-3 (1)
2-3: Provide Korean translations instead of English values.The plan.json file for ko-KR locale contains English text ("Task Plan", "completed") rather than Korean translations. All user-facing strings must be localized to the target language.
Provide the Korean translations for these keys:
{ - "title": "Task Plan", - "completed": "completed" + "title": "작업 계획", + "completed": "완료됨" }src/renderer/src/i18n/fr-FR/plan.json-2-3 (1)
2-3: Provide French translations instead of English values.The plan.json file for fr-FR locale contains English text ("Task Plan", "completed") rather than French translations. All user-facing strings must be localized to the target language per coding guidelines and i18n best practices.
Provide the French translations for these keys:
{ - "title": "Task Plan", - "completed": "completed" + "title": "Plan de Tâche", + "completed": "complété" }src/main/presenter/llmProviderPresenter/agent/acpFsHandler.ts-34-45 (1)
34-45: Fix workspace-relative path handling invalidatePathWhen
workspaceRootis set,validatePathcurrently resolves relative paths againstprocess.cwd()rather than the session workspace:
const resolved = path.resolve(filePath)resolves relative toprocess.cwd()path.relative(this.workspaceRoot, resolved)then checks if the resolved path escapes the workspaceThis causes two problems:
- Valid workspace-relative paths (sent by ACP agents) are rejected as "escapes workspace" when
process.cwd()differs fromworkspaceRoot- Relative paths resolve to unintended locations if the Electron process cwd differs from the session workspace
Fix by anchoring resolution to the workspace root when present:
private validatePath(filePath: string): string { - const resolved = path.resolve(filePath) + const baseDir = this.workspaceRoot ?? process.cwd() + const resolved = path.resolve(baseDir, filePath) if (this.workspaceRoot) { const relative = path.relative(this.workspaceRoot, resolved) if (relative.startsWith('..') || path.isAbsolute(relative)) { throw RequestError.invalidParams({ path: filePath }, `Path escapes workspace: ${filePath}`) } } return resolved }This preserves the security boundary check while ensuring relative paths resolve within the session workspace.
src/renderer/src/i18n/da-DK/plan.json-1-4 (1)
1-4: Translate English strings to Danish.Both translation values are in English instead of Danish. This will display English text in the plan UI for Danish-speaking users.
Apply proper Danish translations:
{ - "title": "Task Plan", - "completed": "completed" + "title": "Opgaveplan", + "completed": "fuldført" }src/renderer/src/i18n/ja-JP/chat.json-31-31 (1)
31-31: Translate English string to Japanese.The modeChanged value is in English instead of Japanese. This will display English text to Japanese-speaking users when the mode changes.
Apply proper Japanese translation:
- "modeChanged": "Mode changed to: {mode}" + "modeChanged": "モードが {mode} に変更されました"src/renderer/src/i18n/fa-IR/chat.json-31-31 (1)
31-31: Translate English string to Persian.The modeChanged value is in English instead of Persian. This will display English text to Persian-speaking users when the mode changes.
Apply proper Persian translation:
- "modeChanged": "Mode changed to: {mode}" + "modeChanged": "حالت به {mode} تغییر یافت"src/renderer/src/i18n/pt-BR/chat.json-31-31 (1)
31-31: Translate English string to Portuguese.The modeChanged value is in English instead of Portuguese. This will display English text to Brazilian Portuguese speakers when the mode changes.
Apply proper Portuguese translation:
- "modeChanged": "Mode changed to: {mode}" + "modeChanged": "Modo alterado para: {mode}"src/renderer/src/i18n/fr-FR/toolCall.json-12-18 (1)
12-18: Translate English strings to French.The new translation keys contain English text instead of French translations. This will display English text to French-speaking users in the terminal and file operation UI.
Apply proper French translations for these keys:
- "terminalOutput": "Terminal Output", - "fileOperation": "File Operation", - "fileRead": "Read File", - "fileWrite": "Write File", - "filePath": "File Path", - "success": "Success", - "failed": "Failed" + "terminalOutput": "Sortie du terminal", + "fileOperation": "Opération de fichier", + "fileRead": "Lire le fichier", + "fileWrite": "Écrire le fichier", + "filePath": "Chemin du fichier", + "success": "Succès", + "failed": "Échec"src/renderer/src/i18n/da-DK/toolCall.json-12-18 (1)
12-18: Translate English strings to Danish.The new translation keys contain English text instead of Danish translations. This will display English text to users who have selected Danish as their language, breaking the localized user experience.
Apply proper Danish translations for these keys:
- "terminalOutput": "Terminal Output", - "fileOperation": "File Operation", - "fileRead": "Read File", - "fileWrite": "Write File", - "filePath": "File Path", - "success": "Success", - "failed": "Failed" + "terminalOutput": "Terminal Output", + "fileOperation": "Filhandling", + "fileRead": "Læs fil", + "fileWrite": "Skriv fil", + "filePath": "Filsti", + "success": "Succes", + "failed": "Mislykkedes"src/renderer/src/i18n/ja-JP/toolCall.json-12-18 (1)
12-18: Translate new keys to Japanese.The new translation keys (terminalOutput, fileOperation, fileRead, fileWrite, filePath, success, failed) contain English values in a Japanese locale file. All user-facing strings in ja-JP should be translated to Japanese to maintain consistency with existing translations.
Based on coding guidelines for i18n consistency across all language translation files.
src/renderer/src/i18n/pt-BR/toolCall.json-12-18 (1)
12-18: Translate new keys to Portuguese.The new translation keys (terminalOutput, fileOperation, fileRead, fileWrite, filePath, success, failed) contain English values in a Brazilian Portuguese locale file. All user-facing strings in pt-BR should be translated to Portuguese to maintain consistency with existing translations.
Based on coding guidelines for i18n consistency across all language translation files.
src/renderer/src/i18n/da-DK/chat.json-7-7 (1)
7-7: Translate new key to Danish.The modeChanged key contains an English value in a Danish locale file. This should be translated to Danish to maintain consistency with other translations in this file.
Based on coding guidelines for i18n consistency across all language translation files.
src/renderer/src/components/message/MessageBlockToolCall.vue-283-294 (1)
283-294: Terminal may be re-initialized on each watch trigger.The
watchcallback callsinitTerminal()on every change toisExpandedorresponse, butinitTerminal()creates a new terminal without checking if one already exists. This could cause multiple terminals to be created or memory leaks.const initTerminal = () => { if (!terminalContainer.value || !isTerminalTool.value) return + if (terminal) return // Already initialized terminal = new Terminal({Or add cleanup before re-initialization if you want to support re-rendering:
const initTerminal = () => { if (!terminalContainer.value || !isTerminalTool.value) return + + // Dispose existing terminal before creating new one + if (terminal) { + terminal.dispose() + } terminal = new Terminal({Committable suggestion skipped: line range outside the PR's diff.
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts-94-104 (1)
94-104: Security: Fallback to unrestricted file system handler is risky.Creating an unrestricted handler (
workspaceRoot: null) when no session is registered allows the agent to access any file on the system. This fallback should either throw an error or restrict access to a safe default directory.Consider failing fast instead of falling back to unrestricted access:
private getFsHandler(sessionId: string): AcpFsHandler { const handler = this.fsHandlers.get(sessionId) if (!handler) { - // Fallback: create handler with no workspace restriction - console.warn( - `[ACP] No fs handler registered for session ${sessionId}, using unrestricted handler` - ) - return new AcpFsHandler({ workspaceRoot: null }) + throw new Error( + `[ACP] No fs handler registered for session ${sessionId}. ` + + `Call registerSessionWorkdir before performing fs operations.` + ) } return handler }Alternatively, if a fallback is required, use a safe restricted directory like a temp folder.
🟡 Minor comments (1)
src/renderer/src/i18n/ru-RU/toolCall.json-12-18 (1)
12-18: Missing Russian translations for new keys.The new keys use English text instead of Russian translations. This breaks localization consistency for Russian users. Based on learnings, all language files should maintain consistent key-value structure with proper translations.
Suggested Russian translations:
- "terminalOutput": "Terminal Output", - "fileOperation": "File Operation", - "fileRead": "Read File", - "fileWrite": "Write File", - "filePath": "File Path", - "success": "Success", - "failed": "Failed" + "terminalOutput": "Вывод терминала", + "fileOperation": "Операция с файлом", + "fileRead": "Чтение файла", + "fileWrite": "Запись файла", + "filePath": "Путь к файлу", + "success": "Успешно", + "failed": "Ошибка"
🧹 Nitpick comments (16)
docs/ACP_PROTOCOL_GAP_ANALYSIS.md (1)
1-12: Wrap bare URLs in markdown link syntax and add language specifiers to code blocks.The markdown linter flags bare URLs (lines 4–11) and missing language specifiers on fenced code blocks throughout the document. While not blocking, these should be fixed for consistency with markdown best practices.
For bare URLs, wrap them in markdown link syntax:
-https://agentclientprotocol.com/protocol/prompt-turn +[Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)For fenced code blocks, add language specifiers (e.g.,
```typescriptinstead of```). This applies to lines 115, 146, 206, 644, 676, 722, 750, 839, 856, 875.src/renderer/src/i18n/zh-HK/toolCall.json (1)
11-18: Localize new tool-call labels for zh-HKThe newly added keys (
terminalOutput,fileOperation,fileRead,fileWrite,filePath,success,failed) are currently English in a Traditional Chinese (zh-HK) file, whereas the rest of the file is localized.Consider providing Traditional Chinese translations for these values (or confirming that English is intentional for this locale) to keep the user experience consistent across keys.
src/main/presenter/llmProviderPresenter/agent/acpTerminalManager.ts (2)
53-64: Revisit command construction and argument handling for terminalsThe non‑Windows branch runs:
shell = '/bin/bash' shellArgs = ['-c', [params.command, ...(params.args ?? [])].join(' ')]This effectively treats
command+argsas a single shell script string. That:
- Changes semantics from “command + argv” to “bash -c ''”
- Loses explicit argument boundaries (spaces, quoting, special characters in args may break or be interpreted by the shell)
- Potentially broadens what the agent can execute vs. a more direct
spawn(command, args, …)styleIf ACP’s
CreateTerminalRequestsemantics are intended to be “run this executable with these args”, you may want to:
- Either call
spawn(params.command, params.args ?? [], …)directly, or- Explicitly document that this manager provides a shell and that
command/argsare combined into one shell command, and ensure any callers match that contract.Clarifying this now will avoid subtle cross‑platform differences and quoting bugs later.
229-243:truncateAtCharBoundarylikely doesn’t enforce UTF‑8 boundaries as intendedThe helper currently does:
const buf = Buffer.from(str, 'utf-8') if (buf.length <= maxBytes) return str let truncated = buf.subarray(0, maxBytes) while (truncated.length > 0) { try { return truncated.toString('utf-8') } catch { truncated = truncated.subarray(0, truncated.length - 1) } }In Node,
Buffer.toString('utf8')decodes invalid sequences with replacement characters and does not throw, so thewhileloop will almost always return on the first iteration. That means:
- You may still end up cutting a multi‑byte character in the middle.
- The loop and try/catch add complexity but don’t change behavior.
If you do care about strict character boundaries, consider either:
- Using a dedicated UTF‑8 boundary calculation (e.g., scanning backward from
maxBytesuntil you hit a valid leading byte), or- Simplifying the function to just slice by bytes and accept that the last character may be replaced, updating the comment accordingly.
Right now the code works functionally, but the implementation doesn’t match the comment’s intent.
src/renderer/src/i18n/pt-BR/plan.json (1)
1-4: Consider localizing plan strings for pt-BRThis new
plan.jsonforpt-BRuses English values:
"title": "Task Plan""completed": "completed"For consistency with the rest of the pt-BR locale, consider translating these strings into Brazilian Portuguese (or explicitly confirming that English is acceptable as a temporary fallback).
src/renderer/src/i18n/ko-KR/chat.json (1)
30-31: Localizefeatures.modeChangedfor ko-KRThe new
modeChangedkey currently has an English value:"modeChanged": "Mode changed to: {mode}"Since the rest of the
featuressection is in Korean, consider translating this string to Korean to keep the KO locale consistent for end users.src/renderer/src/i18n/fr-FR/chat.json (1)
30-31: Localizefeatures.modeChangedfor fr-FRThe new
modeChangedkey is currently:"modeChanged": "Mode changed to: {mode}"In a French locale where surrounding strings are translated, this will stand out. Consider providing a French translation (e.g., along the lines of “Mode changé en : {mode}”) to keep the UX consistent.
src/renderer/src/i18n/fa-IR/plan.json (1)
1-4: Localize plan strings for fa-IRThe new
fa-IR/plan.jsondefines:"title": "Task Plan", "completed": "completed"For a Persian locale, these English values are functional but inconsistent with a fully localized UI. When translation resources are available, consider replacing them with Persian equivalents to align with other i18n files.
src/renderer/src/i18n/zh-HK/chat.json (1)
30-31: NewmodeChangedkey wiring is correct; consider localizing textThe
features.modeChangedkey aligns with the usage inMessageBlockThink.vue(t('chat.features.modeChanged', { mode })), and the placeholder{mode}is consistent.However, the value is English (
"Mode changed to: {mode}") in an otherwise Traditional Chinese zh-HK file. If you want fully localized UX here, consider providing a zh-HK translation instead of English.Also, please double‑check that all other locales define
chat.features.modeChangedso this header doesn’t fall back to a missing key in some languages, in line with the “consistent key structure across locales” guideline.src/renderer/src/i18n/ko-KR/toolCall.json (1)
11-18: ToolCall keys added correctly; consider localizing new Korean stringsThe additional keys for terminal/file operations (
terminalOutput,fileOperation,fileRead,fileWrite,filePath,success,failed) align with the expanded tool-call UI and follow the existing key structure.Right now, all of these values are English in the ko-KR locale. To provide a consistent localized experience, consider translating these into Korean, keeping the placeholders and semantics intact (e.g., keep
{}variables as-is).Also, ensure the same key set is present in other locales so tool-call UIs don’t hit missing translations. Based on learnings, consistent key structure across locales is expected.
src/renderer/src/i18n/ja-JP/plan.json (1)
1-4: ja-JP plan keys are correct; recommend localizing valuesThe
titleandcompletedkeys match other locales and will integrate fine witht('plan.title')/t('plan.completed').To align with the localization guidelines and the zh-CN variant, consider replacing the English values with Japanese translations while keeping the same keys, so ja-JP users don’t see English labels in the plan UI.
src/renderer/src/i18n/ru-RU/plan.json (1)
1-4: ru-RU plan keys are consistent; recommend Russian translationsThe ru-RU
plan.jsonuses the same keys (title,completed) as other locales, which is good for structural consistency.For better localization, consider providing Russian translations for these values instead of the current English strings, keeping the key structure unchanged to satisfy cross-locale consistency.
test/main/presenter/llmProviderPresenter/acpContentMapper.test.ts (1)
195-237: LGTM! Mode handling tests are well-structured.Tests verify
currentModeIdpopulation, reasoning event emission, and block extra data storage. Consider adding a test for missingcurrentModeId(empty/undefined) to match the empty plan entries test pattern.src/renderer/src/components/message/MessageBlockPlan.vue (1)
73-77: Consider using the shared PlanEntry type.A
PlanEntryinterface is also defined inacpContentMapper.ts. Consider importing the shared type to maintain consistency and avoid duplication.-interface PlanEntry { - content: string - priority?: string | null - status?: string | null -} +import type { PlanEntry } from '@/presenter/llmProviderPresenter/agent/acpContentMapper'Alternatively, if the type needs to be shared across renderer and main, consider moving it to
@shared/chat.d.ts.src/renderer/src/components/message/MessageBlockToolCall.vue (1)
204-212: Heuristic tool type detection may have false positives.The detection logic uses simple
includes()checks which could match unintended tool names. For example,isFileSystemToolwould match any tool containing "read" (like "readDatabase") andisTerminalToolwould match "executeQuery".Consider using more specific patterns or checking for known tool names:
const FILE_TOOLS = ['read_file', 'write_file', 'readTextFile', 'writeTextFile'] const TERMINAL_TOOLS = ['run_command', 'execute_terminal', 'terminal_exec'] const isFileSystemTool = computed(() => { const name = props.block.tool_call?.name || '' return FILE_TOOLS.some(t => name.includes(t)) })docs/ACP_UI_IMPLEMENTATION_SUMMARY.md (1)
115-123: Add language specifier to fenced code blocks for ASCII diagrams.Static analysis flags these ASCII diagrams as missing a language specifier. Using
textsilences the lint warning and indicates these are human-readable diagrams rather than executable code.-``` +```text Agent (ACP Process) ↓ AcpContentMapper (处理 plan/mode 更新) ↓ MessageBlock (plan 类型块) ↓ MessageBlockPlan.vue (UI 渲染)Apply the same fix to the diagram at lines 126-134. </blockquote></details> </blockquote></details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
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: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (27)
src/renderer/src/i18n/da-DK/chat.json(1 hunks)src/renderer/src/i18n/da-DK/plan.json(1 hunks)src/renderer/src/i18n/da-DK/toolCall.json(1 hunks)src/renderer/src/i18n/fa-IR/chat.json(1 hunks)src/renderer/src/i18n/fa-IR/plan.json(1 hunks)src/renderer/src/i18n/fa-IR/toolCall.json(1 hunks)src/renderer/src/i18n/fr-FR/chat.json(1 hunks)src/renderer/src/i18n/fr-FR/plan.json(1 hunks)src/renderer/src/i18n/fr-FR/toolCall.json(1 hunks)src/renderer/src/i18n/ja-JP/chat.json(1 hunks)src/renderer/src/i18n/ja-JP/plan.json(1 hunks)src/renderer/src/i18n/ja-JP/toolCall.json(1 hunks)src/renderer/src/i18n/ko-KR/chat.json(1 hunks)src/renderer/src/i18n/ko-KR/plan.json(1 hunks)src/renderer/src/i18n/ko-KR/toolCall.json(1 hunks)src/renderer/src/i18n/pt-BR/chat.json(1 hunks)src/renderer/src/i18n/pt-BR/plan.json(1 hunks)src/renderer/src/i18n/pt-BR/toolCall.json(1 hunks)src/renderer/src/i18n/ru-RU/chat.json(1 hunks)src/renderer/src/i18n/ru-RU/plan.json(1 hunks)src/renderer/src/i18n/ru-RU/toolCall.json(1 hunks)src/renderer/src/i18n/zh-HK/chat.json(1 hunks)src/renderer/src/i18n/zh-HK/plan.json(1 hunks)src/renderer/src/i18n/zh-HK/toolCall.json(1 hunks)src/renderer/src/i18n/zh-TW/chat.json(1 hunks)src/renderer/src/i18n/zh-TW/plan.json(1 hunks)src/renderer/src/i18n/zh-TW/toolCall.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (17)
- src/renderer/src/i18n/fa-IR/plan.json
- src/renderer/src/i18n/ru-RU/chat.json
- src/renderer/src/i18n/zh-HK/chat.json
- src/renderer/src/i18n/ja-JP/chat.json
- src/renderer/src/i18n/da-DK/plan.json
- src/renderer/src/i18n/ru-RU/plan.json
- src/renderer/src/i18n/ko-KR/plan.json
- src/renderer/src/i18n/zh-TW/chat.json
- src/renderer/src/i18n/ja-JP/plan.json
- src/renderer/src/i18n/fa-IR/chat.json
- src/renderer/src/i18n/zh-HK/plan.json
- src/renderer/src/i18n/da-DK/chat.json
- src/renderer/src/i18n/pt-BR/chat.json
- src/renderer/src/i18n/pt-BR/toolCall.json
- src/renderer/src/i18n/zh-TW/toolCall.json
- src/renderer/src/i18n/zh-TW/plan.json
- src/renderer/src/i18n/zh-HK/toolCall.json
🧰 Additional context used
📓 Path-based instructions (3)
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/pt-BR/plan.jsonsrc/renderer/src/i18n/da-DK/toolCall.jsonsrc/renderer/src/i18n/fr-FR/plan.jsonsrc/renderer/src/i18n/fr-FR/chat.jsonsrc/renderer/src/i18n/ko-KR/toolCall.jsonsrc/renderer/src/i18n/fr-FR/toolCall.jsonsrc/renderer/src/i18n/ja-JP/toolCall.jsonsrc/renderer/src/i18n/fa-IR/toolCall.jsonsrc/renderer/src/i18n/ko-KR/chat.jsonsrc/renderer/src/i18n/ru-RU/toolCall.json
src/**/*
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
New features should be developed in the
srcdirectory
Files:
src/renderer/src/i18n/pt-BR/plan.jsonsrc/renderer/src/i18n/da-DK/toolCall.jsonsrc/renderer/src/i18n/fr-FR/plan.jsonsrc/renderer/src/i18n/fr-FR/chat.jsonsrc/renderer/src/i18n/ko-KR/toolCall.jsonsrc/renderer/src/i18n/fr-FR/toolCall.jsonsrc/renderer/src/i18n/ja-JP/toolCall.jsonsrc/renderer/src/i18n/fa-IR/toolCall.jsonsrc/renderer/src/i18n/ko-KR/chat.jsonsrc/renderer/src/i18n/ru-RU/toolCall.json
src/renderer/**
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Use lowercase with dashes for directories (e.g., components/auth-wizard)
Files:
src/renderer/src/i18n/pt-BR/plan.jsonsrc/renderer/src/i18n/da-DK/toolCall.jsonsrc/renderer/src/i18n/fr-FR/plan.jsonsrc/renderer/src/i18n/fr-FR/chat.jsonsrc/renderer/src/i18n/ko-KR/toolCall.jsonsrc/renderer/src/i18n/fr-FR/toolCall.jsonsrc/renderer/src/i18n/ja-JP/toolCall.jsonsrc/renderer/src/i18n/fa-IR/toolCall.jsonsrc/renderer/src/i18n/ko-KR/chat.jsonsrc/renderer/src/i18n/ru-RU/toolCall.json
🧠 Learnings (7)
📚 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/pt-BR/plan.jsonsrc/renderer/src/i18n/da-DK/toolCall.jsonsrc/renderer/src/i18n/fr-FR/plan.jsonsrc/renderer/src/i18n/ko-KR/toolCall.jsonsrc/renderer/src/i18n/fr-FR/toolCall.jsonsrc/renderer/src/i18n/ja-JP/toolCall.jsonsrc/renderer/src/i18n/fa-IR/toolCall.jsonsrc/renderer/src/i18n/ko-KR/chat.jsonsrc/renderer/src/i18n/ru-RU/toolCall.json
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')
Applied to files:
src/renderer/src/i18n/da-DK/toolCall.jsonsrc/renderer/src/i18n/fa-IR/toolCall.jsonsrc/renderer/src/i18n/ru-RU/toolCall.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} : Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system
Applied to files:
src/renderer/src/i18n/fr-FR/plan.jsonsrc/renderer/src/i18n/fr-FR/toolCall.jsonsrc/renderer/src/i18n/fa-IR/toolCall.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/fa-IR/toolCall.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/fa-IR/toolCall.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/fa-IR/toolCall.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/fa-IR/toolCall.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-check (x64)
🔇 Additional comments (11)
src/renderer/src/i18n/ko-KR/chat.json (1)
30-31: No action needed. The newmodeChangedkey has been consistently added across all seven language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR), meeting the coding guidelines for consistent key-value structure. The syntax and placement in ko-KR/chat.json are correct.src/renderer/src/i18n/fa-IR/toolCall.json (2)
1-19: Translation coverage improved: Persian translations now provided for all keys.This resolves the previous critical issue where new keys contained untranslated English values. All 7 flagged keys (terminalOutput, fileOperation, fileRead, fileWrite, filePath, success, failed) now have Persian translations. The file maintains consistency with the flat key-value structure used across other locale files and follows the i18n conventions properly.
13-13: The "response" translation in fa-IR is semantically correct and consistent across all locale files. The Persian translation "در حال دویدن" (literally "in the process of running") aligns with translations in all other locales (en-US: "Running...", zh-CN: "运行中", fr-FR: "En cours d'exécution", etc.), confirming that the "response" key represents the in-progress status of a tool call response, not a literal response object. No changes needed.src/renderer/src/i18n/da-DK/toolCall.json (1)
1-19: Key consistency across all language files is maintained.All new keys (fileOperation, filePath, fileRead, fileWrite, terminalOutput, success, failed) are present and identically named in all 11 language translation files (da-DK, en-US, fa-IR, fr-FR, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW). Each file contains exactly 17 keys with consistent structure.
Note: The camelCase naming pattern (fileOperation vs file.operation) is consistent across the entire toolCall.json codebase and not introduced by this PR.
src/renderer/src/i18n/ru-RU/toolCall.json (1)
6-10: All 7 new translation keys (failed, fileOperation, filePath, fileRead, fileWrite, success, terminalOutput) have been consistently added to all language translation files in src/renderer/src/i18n, including zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR, and additional languages (da-DK, ja-JP, pt-BR, zh-TW). Consistent key-value structure is maintained across all language files.src/renderer/src/i18n/ko-KR/toolCall.json (2)
1-19: File structure and formatting look good.The JSON structure is valid, properly formatted, and consistent with existing translation file conventions. All keys maintain lowercase formatting appropriate for this i18n file.
6-18: No action required — key consistency verified across all language files.All new keys (failed, fileOperation, filePath, fileRead, fileWrite, params, responseData, success, terminalOutput) are consistently present in all language translation files (en-US, zh-CN, ru-RU, zh-HK, fr-FR, fa-IR). The i18n guideline for maintaining consistent key-value structure across locales is satisfied.
src/renderer/src/i18n/fr-FR/chat.json (1)
30-31: JSON syntax and key structure look good.The "modeChanged" key follows the existing camelCase naming convention and the parameterized value format is consistent with other entries in the file.
src/renderer/src/i18n/fr-FR/toolCall.json (1)
2-18: No action needed. The French translation uses appropriate sentence-case capitalization following French language conventions, not a deviation. Comparing en-US title-case values to localized sentence-case translations is not a valid concern—other locales (ru-RU, ko-KR) follow similar patterns where translated values use natural capitalization for their respective languages rather than mimicking English title case. All required keys are present across locales.src/renderer/src/i18n/ja-JP/toolCall.json (2)
1-19: Key consistency verification complete — all locales are properly aligned.All 11 supported locales (da-DK, en-US, fa-IR, fr-FR, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW) contain exactly 17 keys each in toolCall.json with no missing or extra keys. The new ACP-related keys (fileOperation, filePath, fileRead, fileWrite, terminalOutput) are present and properly translated across all locales.
2-2: Fix translation accuracy to match UI context and standard Japanese terminology.The Japanese translations contain semantic misalignments with their UI context:
- Line 2:
"calling": "電話をかける"literally means "making a phone call" and is inappropriate for tool invocation. Use"呼び出し中"or"実行中"to match English "Calling..." and Chinese "调用中".- Line 4:
"end": "仕上げる"(to polish/finish) is non-standard UI Japanese. Use"完了"or"終了"instead, consistent with standard UI terminology.- Line 5:
"error": "間違い"(mistake as noun) should be"エラー", the standard Japanese UI term for errors.⛔ Skipped due to learnings
Learnt from: CR Repo: ThinkInAIXYZ/deepchat PR: 0 File: .cursor/rules/i18n.mdc:0-0 Timestamp: 2025-11-25T05:26:43.510Z Learning: Applies to src/renderer/src/i18n/**/*.json : Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)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')
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: 2
♻️ Duplicate comments (1)
src/renderer/src/i18n/ru-RU/toolCall.json (1)
3-18: Rename new i18n keys to follow dot-separated, lowercase conventionLines 6–10 and 18 still introduce/keep camelCase keys like
fileOperation,filePath,fileRead,fileWrite,terminalOutput, which conflicts with the guideline to use dot-separated, lowercase hierarchical keys (e.g.,common.button.submit). This was already raised in a previous review and remains unresolved.Consider refactoring these keys (and matching them across all locales and usages in code) along the lines of:
- "fileOperation": "Операции с файлами", - "filePath": "путь к файлу", - "fileRead": "прочитать файл", - "fileWrite": "записать файл", - "terminalOutput": "Выходной терминал" + "file.operation": "Операции с файлами", + "file.path": "путь к файлу", + "file.read": "прочитать файл", + "file.write": "записать файл", + "terminal.output": "Вывод терминала"You’ll also need to update the corresponding keys in other locale files and any components that reference the old camelCase names to keep the i18n structure consistent.
Optionally, you might also polish a couple of labels for more natural Russian (e.g., Line 4
end: something like"Вызов завершен"/"Завершено"instead of"Заканчивать"), but that’s secondary compared to fixing the key naming.As per coding guidelines and previous review comments, and based on learnings, ...
🧹 Nitpick comments (1)
src/renderer/src/i18n/zh-TW/index.ts (1)
19-19: Plan namespace wiring is consistent and correctImporting
planfrom./plan.jsonand exposing it as a top‑level namespace in the default export follows the same pattern as the existing i18n modules (e.g.,promptSetting,toolCall). No issues from a TypeScript or i18n wiring perspective. Just ensureplan.jsonin zh-TW stays key‑aligned with the correspondingplan.jsonfiles in other locales to keep translations consistent.Also applies to: 53-53
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
src/renderer/src/i18n/fa-IR/index.ts(2 hunks)src/renderer/src/i18n/fr-FR/index.ts(2 hunks)src/renderer/src/i18n/fr-FR/plan.json(1 hunks)src/renderer/src/i18n/ja-JP/index.ts(2 hunks)src/renderer/src/i18n/ko-KR/index.ts(2 hunks)src/renderer/src/i18n/ko-KR/toolCall.json(1 hunks)src/renderer/src/i18n/pt-BR/index.ts(2 hunks)src/renderer/src/i18n/ru-RU/index.ts(2 hunks)src/renderer/src/i18n/ru-RU/toolCall.json(1 hunks)src/renderer/src/i18n/zh-HK/index.ts(2 hunks)src/renderer/src/i18n/zh-TW/index.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/renderer/src/i18n/fr-FR/plan.json
🧰 Additional context used
📓 Path-based instructions (20)
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Enable and maintain strict TypeScript type checking for all files
**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
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/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/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/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
Write logs and comments in English
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/renderer/src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)
src/renderer/src/**/*.{vue,ts,tsx}: All user-facing strings must use i18n keys with vue-i18n framework in the renderer
Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Use the dynamic locale.value property to switch languages at runtime
Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/**/*
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
New features should be developed in the
srcdirectory
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.jsonsrc/renderer/src/i18n/ko-KR/toolCall.json
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/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
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/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/renderer/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,tsx,vue}: Write concise, technical TypeScript code with accurate examples
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Avoid enums; use const objects instead
Use arrow functions for methods and computed properties
Avoid unnecessary curly braces in conditionals; use concise syntax for simple 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/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/renderer/**
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Use lowercase with dashes for directories (e.g., components/auth-wizard)
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.jsonsrc/renderer/src/i18n/ko-KR/toolCall.json
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/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/renderer/**/*.{ts,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching
Leverage ref, reactive, and computed for reactive state management
Use provide/inject for dependency injection when appropriate
Use Iconify/Vue for icon implementation
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
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/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/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/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use OxLint for linting JavaScript and TypeScript files
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use EventBus for inter-process communication events
Files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
src/renderer/src/i18n/**/*.json
📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)
src/renderer/src/i18n/**/*.json: Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')
Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)
Files:
src/renderer/src/i18n/ru-RU/toolCall.jsonsrc/renderer/src/i18n/ko-KR/toolCall.json
🧠 Learnings (10)
📚 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/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.jsonsrc/renderer/src/i18n/ko-KR/toolCall.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} : 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/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.json
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to **/*.{ts,tsx,js,jsx,vue} : Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)
Applied to files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.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/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fa-IR/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.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} : Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Applied to files:
src/renderer/src/i18n/zh-TW/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ja-JP/index.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/renderer/src/**/*.{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/index.tssrc/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/ru-RU/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.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} : Use the dynamic locale.value property to switch languages at runtime
Applied to files:
src/renderer/src/i18n/pt-BR/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ja-JP/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 : All user-facing strings must use i18n keys via vue-i18n for internationalization
Applied to files:
src/renderer/src/i18n/zh-HK/index.tssrc/renderer/src/i18n/fr-FR/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.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/ru-RU/index.tssrc/renderer/src/i18n/ko-KR/index.tssrc/renderer/src/i18n/ja-JP/index.tssrc/renderer/src/i18n/ru-RU/toolCall.json
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/**/*.{ts,tsx} : Use camelCase for variable and function names in TypeScript files
Applied to files:
src/renderer/src/i18n/ru-RU/toolCall.json
🔇 Additional comments (10)
src/renderer/src/i18n/fa-IR/index.ts (1)
19-19: Plan bundle wiring for fa-IR looks consistentImporting
planand adding it to the exported locale object matches the existing pattern for other namespaces (chat, toolCall, etc.) and keeps fa-IR aligned with the other locales. Just ensureplan.jsonfollows the same key structure as the other languages’planbundles so cross-locale lookups stay consistent.Based on learnings, maintain consistent key/value structure across all locale
plan.jsonfiles.Also applies to: 53-53
src/renderer/src/i18n/pt-BR/index.ts (1)
19-55: Plan namespace wiring for pt-BR looks consistentImporting
planand exposing it in the default export matches the pattern of other locales and cleanly plugs the new ACP plan translations into the i18n surface. No issues from a typing or structure perspective.
Based on learnings, this keeps i18n usage consistent across locales.src/renderer/src/i18n/ko-KR/index.ts (1)
19-19: LGTM! Plan translation namespace added correctly.The import and export of the
plantranslation namespace follow the established pattern perfectly and maintain consistency with other translation modules in the ko-KR locale.Based on learnings, this change maintains the consistent key-value structure across language translation files as confirmed by the PR's cross-locale implementation.
Also applies to: 54-54
src/renderer/src/i18n/zh-HK/index.ts (1)
18-18: ACPplannamespace is wired correctly for zh-HKThe new
planimport and its inclusion in the default export follow the existing locale pattern and keep zh-HK aligned with other locales and the shared plan.json structure; no issues from an i18n or typing perspective.
Based on learnings, this maintains consistent key structure across translation files.Also applies to: 53-53
src/renderer/src/i18n/fr-FR/index.ts (2)
19-19: LGTM! Import follows the established pattern.The import statement correctly follows the same pattern as other translation resource imports in this file.
54-54: Export integration is correct.The
plan,export on line 54 properly adds plan translations to the fr-FR locale bundle, maintaining the established pattern. The plan.json file exists with French translations ("plan.title": "planification des missions", "plan.completed": "Complété"), and all 11 locales consistently include the plan.json file.src/renderer/src/i18n/ja-JP/index.ts (1)
19-19: LGTM. The import and export of theplanmodule follows the established pattern and is consistent across all supported locales (da-DK, en-US, fa-IR, fr-FR, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW).src/renderer/src/i18n/ko-KR/toolCall.json (2)
5-5: Replace "error" translation from "실수" to "오류" for semantic accuracy.In Korean UI contexts, "실수" (mistake/oversight made by a person) is semantically incorrect for a system error message. The appropriate technical term is "오류" (system/technical error), which aligns with the English "Error" value. Additionally, line 6 "failed": "실패하다" uses an infinitive verb form and should be "실패" or "실패했음" (noun/past form) to match standard Korean UI conventions.
Likely an incorrect or invalid review comment.
6-18: Translation keys are consistent across all locale files.All 7 required locale files (en-US, zh-CN, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR) contain the identical 17-key structure for toolCall.json, including all newly added/modified keys (failed, fileOperation, filePath, fileRead, fileWrite, responseData, success, terminalOutput). Consistency is maintained across all locales.
src/renderer/src/i18n/ru-RU/index.ts (1)
18-18: Wire-up ofplannamespace for ru-RU looks correctImporting
planand adding it to the default export is consistent with the existing pattern for other namespaces; nothing else to change here.Also applies to: 52-52
| "title": "도구 호출", | ||
| "clickToView": "세부 정보를 보려면 클릭하세요", | ||
| "error": "실수", | ||
| "failed": "실패하다", |
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.
Fix infinitive verb form in Korean translation.
"실패하다" uses the infinitive marker "하다". For UI status terminology, use the noun form "실패" instead to match the English "failed" state indicator semantics.
- "failed": "실패하다",
+ "failed": "실패",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "failed": "실패하다", | |
| "failed": "실패", |
🤖 Prompt for AI Agents
In src/renderer/src/i18n/ko-KR/toolCall.json around line 6, the Korean
translation uses the infinitive verb form "실패하다" for the key "failed"; change it
to the noun/state form "실패" to match the English status semantics (replace
"실패하다" with "실패").
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: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts(3 hunks)src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts(8 hunks)src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts(4 hunks)src/main/presenter/llmProviderPresenter/index.ts(1 hunks)src/main/presenter/llmProviderPresenter/providers/acpProvider.ts(1 hunks)src/main/presenter/threadPresenter/index.ts(1 hunks)src/renderer/src/components/chat-input/ChatInput.vue(3 hunks)src/renderer/src/components/chat-input/composables/useAcpMode.ts(1 hunks)src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts(0 hunks)src/renderer/src/i18n/da-DK/chat.json(1 hunks)src/renderer/src/i18n/en-US/chat.json(1 hunks)src/renderer/src/i18n/fa-IR/chat.json(1 hunks)src/renderer/src/i18n/fr-FR/chat.json(1 hunks)src/renderer/src/i18n/fr-FR/plan.json(1 hunks)src/renderer/src/i18n/ja-JP/chat.json(1 hunks)src/renderer/src/i18n/ko-KR/chat.json(1 hunks)src/renderer/src/i18n/pt-BR/chat.json(1 hunks)src/renderer/src/i18n/ru-RU/chat.json(1 hunks)src/renderer/src/i18n/zh-CN/chat.json(1 hunks)src/renderer/src/i18n/zh-HK/chat.json(1 hunks)src/renderer/src/i18n/zh-TW/chat.json(1 hunks)src/shared/types/presenters/legacy.presenters.d.ts(2 hunks)src/shared/types/presenters/llmprovider.presenter.d.ts(1 hunks)src/shared/types/presenters/thread.presenter.d.ts(1 hunks)
💤 Files with no reviewable changes (1)
- src/renderer/src/components/chat-input/composables/useAcpWorkdir.ts
🚧 Files skipped from review as they are similar to previous changes (8)
- src/renderer/src/i18n/fr-FR/plan.json
- src/renderer/src/i18n/ko-KR/chat.json
- src/renderer/src/i18n/en-US/chat.json
- src/renderer/src/i18n/fr-FR/chat.json
- src/renderer/src/i18n/zh-HK/chat.json
- src/renderer/src/i18n/ja-JP/chat.json
- src/renderer/src/i18n/zh-TW/chat.json
- src/renderer/src/i18n/pt-BR/chat.json
🧰 Additional context used
📓 Path-based instructions (35)
**/*.{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/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/renderer/src/components/chat-input/ChatInput.vuesrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
Write logs and comments in English
Files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/llmprovider.presenter.d.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.ts
src/**/*
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
New features should be developed in the
srcdirectory
Files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/i18n/fa-IR/chat.jsonsrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/renderer/src/components/chat-input/ChatInput.vuesrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.tssrc/renderer/src/i18n/da-DK/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/zh-CN/chat.json
src/shared/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Shared type definitions and utilities between main and renderer processes should be placed in
src/shared
Files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.ts
src/shared/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Shared types and utilities should be placed in
src/shared/
Files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.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/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/renderer/src/components/chat-input/ChatInput.vuesrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use OxLint for linting JavaScript and TypeScript files
Files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use EventBus for inter-process communication events
Files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/threadPresenter/index.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/threadPresenter/index.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/threadPresenter/index.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/threadPresenter/index.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/main/presenter/llmProviderPresenter/index.ts
📄 CodeRabbit inference engine (.cursor/rules/llm-agent-loop.mdc)
src/main/presenter/llmProviderPresenter/index.ts: Insrc/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, maintainingconversationMessageshistory, callingprovider.coreStream()on each iteration, and controlling the loop usingneedContinueConversationandtoolCallCount(compared againstMAX_TOOL_CALLS)
Insrc/main/presenter/llmProviderPresenter/index.ts, listen for standardized events yielded bycoreStreamand handle them accordingly: buffer text content (currentContent), handletool_call_start/chunk/endevents by collecting tool details and callingpresenter.mcpPresenter.callTool, send frontend events viaeventBuswith tool call status, format tool results for the next LLM call, and setneedContinueConversation = true
Insrc/main/presenter/llmProviderPresenter/index.ts, handlereasoning,text,image_data, andusageevents by processing and forwarding them throughSTREAM_EVENTS.RESPONSEevents to the frontend
Insrc/main/presenter/llmProviderPresenter/index.ts, handlestopevents by checkingstop_reason: if'tool_use', add the buffered assistant message and prepare for the next loop iteration; otherwise, add the final assistant message and exit the loop
Files:
src/main/presenter/llmProviderPresenter/index.ts
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/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
**/*Provider**/index.ts
📄 CodeRabbit inference engine (.cursor/rules/provider-guidelines.mdc)
**/*Provider**/index.ts: Output only discriminated unionLLMCoreStreamEventin Provider implementations, do not use single interface with optional fields
Use factory methodscreateStreamEvent.*to construct events in Provider implementations, avoid direct field pollution
Text events: emit multipletextchunks in arrival order
Reasoning events:reasoningis optional; if provided, ensure it contains the complete chain
Tool call events: strictly follow sequencetool_call_start → tool_call_chunk* → tool_call_end, ensuretool_call_idis required and stable
Stop events: emitstopat stream end withstop_reasonvalue from {tool_use,max_tokens,stop_sequence,error,complete}
Usage events: sendusageonce before or at stream end withprompt_tokens,completion_tokens, andtotal_tokens
Rate limit events: sendrate_limitevent when reaching limit threshold with fields {providerId,qpsLimit,currentQps,queueLength,estimatedWaitTime?}, do not block event channel
Error handling: useerrorevent uniformly to carry error messages, avoid mixing errors into other event fields
Error termination: after fatal error occurs, emitstopevent as needed and terminate the stream
Image events:image_dataevent must providedata(Base64 encoded) andmimeTypefields; control single frame size and frequency to avoid blocking
Do not emitAssistantMessageBlockor any UI types from Provider implementations to UI layer
Do not introduce renderer dependencies inside Provider implementations
Every event construction in Provider implementations must use factory functions
Tool call IDs in Provider implementations must be globally unique and stable, with chunks arriving strictly in order
Error scenarios in Provider implementations must have correspondingstop_reasonanderrormessage
Provider implementations must emit at least oneusageevent if the provider has statistics capability
Providerate_limitevents in Provider implementations...
Files:
src/main/presenter/llmProviderPresenter/index.ts
src/renderer/src/i18n/**/*.json
📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)
src/renderer/src/i18n/**/*.json: Translation key naming convention: use dot-separated hierarchical structure with lowercase letters and descriptive names (e.g., 'common.button.submit')
Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)
Files:
src/renderer/src/i18n/fa-IR/chat.jsonsrc/renderer/src/i18n/da-DK/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/zh-CN/chat.json
src/renderer/**
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Use lowercase with dashes for directories (e.g., components/auth-wizard)
Files:
src/renderer/src/i18n/fa-IR/chat.jsonsrc/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vuesrc/renderer/src/i18n/da-DK/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/zh-CN/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/components/chat-input/composables/useAcpMode.ts
src/renderer/src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)
src/renderer/src/**/*.{vue,ts,tsx}: All user-facing strings must use i18n keys with vue-i18n framework in the renderer
Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Use the dynamic locale.value property to switch languages at runtime
Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system
Files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/*.{vue,js,ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Renderer process code should be placed in
src/renderer(Vue 3 application)
Files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability in Vue.js applications
Implement proper state management with Pinia in Vue.js applications
Utilize Vue Router for navigation and route management in Vue.js applications
Leverage Vue's built-in reactivity system for efficient data handling
Files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,tsx,vue}: Write concise, technical TypeScript code with accurate examples
Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError)
Avoid enums; use const objects instead
Use arrow functions for methods and computed properties
Avoid unnecessary curly braces in conditionals; use concise syntax for simple 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/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/composables/*.ts
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/composables/*.ts: Use camelCase for composables (e.g., useAuthState.ts)
Use VueUse for common composables and utility functions
Implement custom composables for reusable logic
Files:
src/renderer/src/components/chat-input/composables/useAcpMode.ts
src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
Use TypeScript for all code; prefer types over interfaces
Files:
src/renderer/src/components/chat-input/composables/useAcpMode.ts
src/renderer/**/*.{ts,vue}
📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)
src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching
Leverage ref, reactive, and computed for reactive state management
Use provide/inject for dependency injection when appropriate
Use Iconify/Vue for icon implementation
Files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/renderer/src/**/*.{ts,tsx,vue}: Use TypeScript with Vue 3 Composition API for the renderer application
All user-facing strings must use vue-i18n keys insrc/renderer/src/i18n
Files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
src/main/presenter/llmProviderPresenter/providers/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
src/main/presenter/llmProviderPresenter/providers/*.ts: Each LLM provider must implement thecoreStreammethod following the standardized event interface for tool calling and response streaming
Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation
src/main/presenter/llmProviderPresenter/providers/*.ts: In Provider implementations (src/main/presenter/llmProviderPresenter/providers/*.ts), thecoreStream(messages, modelId, temperature, maxTokens)method should perform a single-pass streaming API request for each conversation round without containing multi-turn tool call loop logic
In Provider implementations, handle native tool support by converting MCP tools to Provider format usingconvertToProviderToolsand including them in the API request; for Providers without native function call support, prepare messages usingprepareFunctionCallPromptbefore making the API call
In Provider implementations, parse Provider-specific data chunks from the streaming response andyieldstandardizedLLMCoreStreamEventobjects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data
In Provider implementations, include helper methods for Provider-specific operations such asformatMessages,convertToProviderTools,parseFunctionCalls, andprepareFunctionCallPrompt
Files:
src/main/presenter/llmProviderPresenter/providers/acpProvider.ts
**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.vue: Use Vue 3 Composition API for all components instead of Options API
Use Tailwind CSS with scoped styles for component styling
Files:
src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
src/renderer/**/*.vue: All user-facing strings must use i18n keys via vue-i18n for internationalization
Ensure proper error handling and loading states in all UI components
Implement responsive design using Tailwind CSS utilities for all UI components
src/renderer/**/*.vue: Use composition API and declarative programming patterns; avoid options API
Structure files: exported component, composables, helpers, static content, types
Use PascalCase for component names (e.g., AuthWizard.vue)
Use Vue 3 with TypeScript, leveraging defineComponent and PropType
Use template syntax for declarative rendering
Use Shadcn Vue, Radix Vue, and Tailwind for components and styling
Implement responsive design with Tailwind CSS; use a mobile-first approach
Use Suspense for asynchronous components
Use <script setup> syntax for concise component definitions
Prefer 'lucide:' icon family as the primary choice for Iconify icons
Import Icon component from '@iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'
Files:
src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/**/*.vue
📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)
Use scoped styles to prevent CSS conflicts between Vue components
Files:
src/renderer/src/components/chat-input/ChatInput.vue
src/renderer/src/components/**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
src/renderer/src/components/**/*.vue: Use Tailwind for styles in Vue components
Vue component files must use PascalCase naming (e.g.,ChatInput.vue)
Files:
src/renderer/src/components/chat-input/ChatInput.vue
🧠 Learnings (30)
📚 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/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, include helper methods for Provider-specific operations such as `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, and `prepareFunctionCallPrompt`
Applied to files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, 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/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, handle native tool support by converting MCP tools to Provider format using `convertToProviderTools` and including them in the API request; for Providers without native function call support, prepare messages using `prepareFunctionCallPrompt` before making the API call
Applied to files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts` (`startStreamCompletion`), implement the Agent loop that manages the overall conversation flow, including multiple rounds of LLM calls and tool usage, maintaining `conversationMessages` history, calling `provider.coreStream()` on each iteration, and controlling the loop using `needContinueConversation` and `toolCallCount` (compared against `MAX_TOOL_CALLS`)
Applied to files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Convert MCP tools to provider-specific formats and normalize streaming responses to standard events in each provider implementation
Applied to files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/**/*.ts : Define the standardized `LLMCoreStreamEvent` interface with fields: `type` (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), `content` (for text), `reasoning_content` (for reasoning), `tool_call_id`, `tool_call_name`, `tool_call_arguments_chunk` (for streaming), `tool_call_arguments_complete` (for complete arguments), `error_message`, `usage` object with token counts, `stop_reason` (tool_use | max_tokens | stop_sequence | error | complete), and `image_data` object with Base64-encoded data and mimeType
Applied to files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpSessionManager.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations (`src/main/presenter/llmProviderPresenter/providers/*.ts`), the `coreStream(messages, modelId, temperature, maxTokens)` method should perform a *single-pass* streaming API request for each conversation round without containing multi-turn tool call loop logic
Applied to files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/threadPresenter/index.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/providers/acpProvider.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Each LLM provider must implement the `coreStream` method following the standardized event interface for tool calling and response streaming
Applied to files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, parse Provider-specific data chunks from the streaming response and `yield` standardized `LLMCoreStreamEvent` objects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data
Applied to files:
src/shared/types/presenters/llmprovider.presenter.d.tssrc/main/presenter/llmProviderPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/threadPresenter/index.tssrc/shared/types/presenters/thread.presenter.d.tssrc/shared/types/presenters/legacy.presenters.d.tssrc/renderer/src/components/chat-input/composables/useAcpMode.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, handle `reasoning`, `text`, `image_data`, and `usage` events by processing and forwarding them through `STREAM_EVENTS.RESPONSE` events to the frontend
Applied to files:
src/main/presenter/threadPresenter/index.tssrc/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to {src/main/presenter/**/*.ts,src/renderer/**/*.ts} : Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs
Applied to files:
src/shared/types/presenters/thread.presenter.d.tssrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/main/**/*.ts : Use the Presenter pattern in the main process for UI coordination
Applied to files:
src/shared/types/presenters/thread.presenter.d.ts
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Maintain consistent key-value structure across all language translation files (zh-CN, en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR)
Applied to files:
src/renderer/src/i18n/fa-IR/chat.jsonsrc/renderer/src/i18n/ru-RU/chat.jsonsrc/renderer/src/i18n/zh-CN/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/**/composables/*.ts : Use VueUse for common composables and utility functions
Applied to files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/composables/*.ts : Use camelCase for composables (e.g., useAuthState.ts)
Applied to files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.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/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Applied to files:
src/renderer/src/components/chat-input/composables/useAcpMode.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/**/*.{ts,tsx,vue} : Use TypeScript with Vue 3 Composition API for the renderer application
Applied to files:
src/renderer/src/components/chat-input/composables/useAcpMode.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 : Implement custom composables for reusable logic
Applied to files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use composition API and declarative programming patterns; avoid options API
Applied to files:
src/renderer/src/components/chat-input/composables/useAcpMode.tssrc/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/(components|composables)/**/*.{ts,vue} : Utilize Nuxt's auto-imports feature for components and composables
Applied to files:
src/renderer/src/components/chat-input/composables/useAcpMode.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/(components|composables)/**/*.{ts,vue} : Use Nuxt's auto-imports for components and composables
Applied to files:
src/renderer/src/components/chat-input/composables/useAcpMode.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/mcpPresenter/**/*.ts : Register new MCP tools in `mcpPresenter/index.ts` after implementing them in `inMemoryServers/`
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/renderer/src/components/**/*.vue : Vue component files must use PascalCase naming (e.g., `ChatInput.vue`)
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.{ts,vue} : Use Iconify/Vue for icon implementation
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:27:39.200Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/provider-guidelines.mdc:0-0
Timestamp: 2025-11-25T05:27:39.200Z
Learning: Applies to **/*Provider**/index.ts : Output only discriminated union `LLMCoreStreamEvent` in Provider implementations, do not use single interface with optional fields
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/i18n/**/*.json : 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/ru-RU/chat.jsonsrc/renderer/src/i18n/zh-CN/chat.json
🧬 Code graph analysis (3)
src/renderer/src/components/chat-input/composables/useAcpMode.ts (1)
src/renderer/src/composables/usePresenter.ts (1)
usePresenter(103-105)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (3)
src/main/presenter/llmProviderPresenter/agent/acpTerminalManager.ts (1)
AcpTerminalManager(33-244)src/main/presenter/llmProviderPresenter/agent/acpFsHandler.ts (1)
AcpFsHandler(21-115)src/main/presenter/llmProviderPresenter/agent/acpCapabilities.ts (1)
buildClientCapabilities(14-31)
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (2)
src/shared/types/core/llm-events.ts (2)
LLMCoreStreamEvent(87-98)createStreamEvent(100-154)src/shared/chat.d.ts (1)
AssistantMessageBlock(84-147)
🪛 Biome (2.1.2)
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
[error] 68-68: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ 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 (23)
src/renderer/src/i18n/da-DK/chat.json (1)
6-7: Translation keys follow established patterns and are properly structured.The new keys (
modeChanged,acpMode,acpModeTooltip, etc.) are added under appropriate hierarchical sections and follow the existing camelCase naming convention used throughout the file. The placeholder syntax{mode}is consistent with other parameterized keys like{seconds}and{count}.Verify that these translation keys are consistently implemented across all supported locales (en-US, ko-KR, ru-RU, zh-HK, fr-FR, fa-IR, etc.) as mentioned in the PR summary. Also confirm that the new plan.json file is properly imported in the da-DK locale setup file.
Also applies to: 14-20
src/renderer/src/i18n/fa-IR/chat.json (1)
24-30: Verified: Persian translations for ACP mode and mode change keys are consistent.The new ACP mode-related keys (acpMode, acpModeTooltip, acpModeSwitched, acpModeDefault, acpModeAcceptEdits, acpModePlan, acpModeBypassPermissions) and the features.modeChanged key are properly translated to Persian, maintaining consistency with the rest of the file and aligning with the broader i18n additions across all locales mentioned in the PR.
Also applies to: 37-37
src/renderer/src/i18n/zh-CN/chat.json (2)
23-23: Naming conventions are consistent with existing translation structure.The new ACP-related translation keys (acpMode, acpModeTooltip, acpModeSwitched, etc.) follow the established camelCase naming pattern used throughout the file. Placeholder syntax using curly braces (e.g.,
{mode},{path}) aligns with existing patterns like{count}and{seconds}. JSON hierarchy structure is properly maintained.Also applies to: 24-30
24-30: No action needed. All new ACP translation keys (acpMode, acpModeTooltip, acpModeSwitched, acpModeDefault, acpModeAcceptEdits, acpModePlan, acpModeBypassPermissions, acpWorkdirCurrent, artifactThinking, modeChanged) have been properly added to all 11 language files (da-DK, en-US, fa-IR, fr-FR, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW). The consistent key-value structure requirement is satisfied.src/shared/types/presenters/llmprovider.presenter.d.ts (1)
230-234: LGTM! Well-defined ACP session mode API.The new public methods extend the ACP session mode management surface cleanly. The type definitions are precise and the nullable return type for
getAcpSessionModesproperly handles the case where no session exists.src/shared/types/presenters/thread.presenter.d.ts (1)
180-184: LGTM! Consistent API extension across presenter interfaces.The method signatures match those added to
ILlmProviderPresenter, maintaining consistency across the presenter layer and enabling ACP mode operations through the thread path.src/main/presenter/threadPresenter/index.ts (1)
763-772: LGTM! Clean delegation pattern.The implementations follow the established pattern of delegating to
llmProviderPresenterfor ACP operations, consistent with other ACP methods likegetAcpWorkdirandsetAcpWorkdir.src/main/presenter/llmProviderPresenter/providers/acpProvider.ts (1)
659-695: LGTM! Solid implementation of ACP session mode management.The methods properly:
- Validate session existence before operations
- Handle errors with appropriate logging and propagation
- Return null gracefully when no session exists (getSessionModes)
- Update local state after successful backend calls (setSessionMode)
src/main/presenter/llmProviderPresenter/index.ts (1)
482-499: LGTM! Consistent delegation to ACP provider.The implementations follow the established pattern:
setAcpSessionModethrows an error if the ACP provider is unavailable (appropriate for mutations)getAcpSessionModesreturns null if the ACP provider is unavailable (graceful for queries)- Clean delegation to the provider instance methods
src/renderer/src/components/chat-input/ChatInput.vue (1)
150-171: LGTM! Well-integrated ACP mode UI.The changes successfully replace the previous workdir button with ACP mode functionality:
- Appropriate icon choice (zap) for mode cycling
- Rich tooltip showing current mode name and description
- Clean integration with the new
useAcpModecomposable- Consistent with existing UI patterns
Also applies to: 392-392, 609-612
src/renderer/src/i18n/ru-RU/chat.json (1)
23-30: LGTM! Proper Russian translations for ACP mode keys.All new ACP mode keys are correctly translated to Russian:
- Mode names and tooltips properly localized
- Placeholders like
{mode}correctly preserved- Consistent with the translation patterns in the file
The previous issue with
modeChangedbeing in English has been resolved.Also applies to: 37-37
src/shared/types/presenters/legacy.presenters.d.ts (2)
874-878: LGTM! Consistent API extension for ACP session modes.The new
setAcpSessionModeandgetAcpSessionModesmethods follow the established patterns in this interface, with appropriate Promise-based return types and nullable responses.
1003-1007: LGTM! Consistent with ILlmProviderPresenter additions.The
IThreadPresenterinterface correctly mirrors the ACP session mode methods fromILlmProviderPresenter, maintaining API consistency between the presenter layers.src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (3)
5-17: LGTM! Well-structured interface additions.The
PlanEntryinterface andMappedContentextensions are clearly documented with optional fields. The nullable types (string | null) forpriorityandstatusalign with the ACP schema's optional nature.
185-206: Consider potential issue with empty reasoning event for plan blocks.The
createStreamEvent.reasoning('')at line 200 emits an empty reasoning event before the plan block. This seems intentional for signaling, but verify that downstream consumers (in the renderer) handle empty reasoning content gracefully without displaying empty UI elements.
208-226: LGTM! Mode update handling is correctly implemented.The
handleModeUpdatemethod properly stores the mode ID in the payload and emits both a reasoning event and a structured block with themode_changeextra data, enabling proper UI rendering of mode transitions.src/main/presenter/llmProviderPresenter/agent/acpSessionManager.ts (3)
24-31: LGTM! AcpSessionRecord properly extended with mode metadata.The new optional fields follow TypeScript conventions for optional interface properties and align with the ACP protocol's mode support.
159-160: Good placement of workdir registration.Registering the session workdir with the process manager before persisting session data ensures fs/terminal operations are available immediately when the session becomes active.
219-231: LGTM! Safe extraction of mode data from ACP response.The optional chaining (
modes?.availableModes?.map) correctly handles cases where the ACP agent doesn't support modes. The fallback to empty string for missing descriptions is a sensible default.src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (4)
146-156: LGTM! Comprehensive cleanup on shutdown.The shutdown sequence properly releases terminal manager resources, clears all per-session state maps, and handles the existing cleanup. The ordering ensures no resource leaks.
200-207: LGTM! Per-session resource cleanup is thorough.The
clearSessionmethod properly removes workdir mappings, FS handlers, and releases session terminals. The fire-and-forget pattern withvoidfor terminal release is appropriate since it's non-blocking cleanup.
229-232: LGTM! Proper capability negotiation with ACP agent.Using
buildClientCapabilitieswith explicitenableFsandenableTerminalflags clearly communicates the client's capabilities to the agent, enabling proper fs/terminal operation routing.
569-594: LGTM! Client proxy methods properly delegate to handlers.The fs and terminal operations are correctly routed to their respective handlers. Error handling is inherited from
AcpFsHandlerandAcpTerminalManager, which throwRequestErrorfor protocol-compliant error responses.
| default: | ||
| console.debug('[ACP] Unhandled session update', update.sessionUpdate) | ||
| // Handle any unrecognized session update types | ||
| const sessionUpdate = (update as { sessionUpdate?: string }).sessionUpdate | ||
| console.warn('[ACP] Unhandled session update type:', sessionUpdate) | ||
| console.debug('[ACP] Full update data:', JSON.stringify(update)) | ||
| break |
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.
Wrap switch case declaration in a block to fix correctness issue.
The const sessionUpdate declaration in the default case is accessible to other switch clauses, which can lead to subtle bugs. As flagged by static analysis, wrap the declaration in a block to restrict its scope.
default:
+ {
- // Handle any unrecognized session update types
- const sessionUpdate = (update as { sessionUpdate?: string }).sessionUpdate
- console.warn('[ACP] Unhandled session update type:', sessionUpdate)
- console.debug('[ACP] Full update data:', JSON.stringify(update))
+ // Handle any unrecognized session update types
+ const sessionUpdate = (update as { sessionUpdate?: string }).sessionUpdate
+ console.warn('[ACP] Unhandled session update type:', sessionUpdate)
+ console.debug('[ACP] Full update data:', JSON.stringify(update))
+ }
break🧰 Tools
🪛 Biome (2.1.2)
[error] 68-68: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🤖 Prompt for AI Agents
In src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts around
lines 66 to 71, the default switch case declares const sessionUpdate at function
scope which can leak into other cases; fix by wrapping the default case body in
its own block (add { ... } around the const and the console calls) so
sessionUpdate is block-scoped and cannot collide with other case declarations.
src/renderer/src/components/chat-input/composables/useAcpMode.ts
Outdated
Show resolved
Hide resolved
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: 3
♻️ Duplicate comments (1)
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (1)
67-72: Wrap switch case declaration in a block to fix correctness issue.The
const sessionUpdatedeclaration in the default case is accessible to other switch clauses, which can lead to subtle bugs. As flagged by static analysis, wrap the declaration in a block to restrict its scope.default: + { - // Handle any unrecognized session update types - const sessionUpdate = (update as { sessionUpdate?: string }).sessionUpdate - console.warn('[ACP] Unhandled session update type:', sessionUpdate) - console.debug('[ACP] Full update data:', JSON.stringify(update)) + // Handle any unrecognized session update types + const sessionUpdate = (update as { sessionUpdate?: string }).sessionUpdate + console.warn('[ACP] Unhandled session update type:', sessionUpdate) + console.debug('[ACP] Full update data:', JSON.stringify(update)) + } break
🧹 Nitpick comments (4)
src/renderer/src/components/chat-input/ChatInput.vue (1)
196-223: Well-structured ACP mode switcher with proper i18n and accessibility.The implementation follows existing patterns in the file (e.g., Model Selector) and correctly uses i18n for all user-facing strings. Minor suggestion: consider adding a guard for the description content to avoid rendering an empty paragraph.
- <p v-if="acpMode.currentModeInfo.value" class="text-xs text-muted-foreground mt-1"> + <p v-if="acpMode.currentModeInfo.value?.description" class="text-xs text-muted-foreground mt-1"> {{ acpMode.currentModeInfo.value.description }} </p>src/renderer/src/components/message/MessageBlockToolCall.vue (1)
194-226: Consider terminal resize handling for responsive layouts.The terminal is initialized with fixed dimensions derived from container size at mount time. If the container resizes (e.g., window resize), the terminal won't adapt. Consider using a
FitAddonfrom@xterm/addon-fitfor proper responsive behavior.src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (1)
191-212: Consider removing the empty reasoning event emission.Line 206 emits
createStreamEvent.reasoning('')with empty content, which may clutter the event stream without providing value. If this is a placeholder for plan events, consider using a dedicated event type or removing it entirely.// Create dedicated plan block - payload.events.push(createStreamEvent.reasoning('')) // Empty event for plan payload.blocks.push( this.createBlock('plan', '', { extra: { plan_entries: payload.planEntries } }) )src/renderer/src/components/artifacts/MermaidArtifact.vue (1)
133-142: Translate comment to English.The watch logic is correct. Minor issue: the comment on line 133 is in Chinese; per coding guidelines, new code should use English comments.
-// 监听内容变化和预览状态变化 +// Watch for content and preview state changes to trigger re-render watch(
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
package.json(1 hunks)src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts(6 hunks)src/renderer/src/components/artifacts/MermaidArtifact.vue(3 hunks)src/renderer/src/components/chat-input/ChatInput.vue(3 hunks)src/renderer/src/components/chat-input/composables/useAcpMode.ts(1 hunks)src/renderer/src/components/message/MessageBlockToolCall.vue(3 hunks)src/renderer/src/i18n/ko-KR/toolCall.json(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- package.json
🚧 Files skipped from review as they are similar to previous changes (2)
- src/renderer/src/i18n/ko-KR/toolCall.json
- src/renderer/src/components/chat-input/composables/useAcpMode.ts
🧰 Additional context used
📓 Path-based instructions (25)
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.tssrc/renderer/src/components/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.vue
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Enable and maintain strict TypeScript type checking for all files
**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/main/presenter/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Organize core business logic into dedicated Presenter classes, with one presenter per functional domain
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/main/**/*.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/llmProviderPresenter/agent/acpContentMapper.ts
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
Write logs and comments in English
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/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/acpContentMapper.ts
src/**/*
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
New features should be developed in the
srcdirectory
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.tssrc/renderer/src/components/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.vue
src/main/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Main process code for Electron should be placed in
src/main
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/**/*.{ts,tsx,vue,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Prettier with single quotes, no semicolons, and 100 character width
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.tssrc/renderer/src/components/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.vue
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use OxLint for linting JavaScript and TypeScript files
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use EventBus for inter-process communication events
Files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.vue
🧠 Learnings (28)
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, listen for standardized events yielded by `coreStream` and handle them accordingly: buffer text content (`currentContent`), handle `tool_call_start/chunk/end` events by collecting tool details and calling `presenter.mcpPresenter.callTool`, send frontend events via `eventBus` with tool call status, format tool results for the next LLM call, and set `needContinueConversation = true`
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/**/*.ts : Define the standardized `LLMCoreStreamEvent` interface with fields: `type` (text | reasoning | tool_call_start | tool_call_chunk | tool_call_end | error | usage | stop | image_data), `content` (for text), `reasoning_content` (for reasoning), `tool_call_id`, `tool_call_name`, `tool_call_arguments_chunk` (for streaming), `tool_call_arguments_complete` (for complete arguments), `error_message`, `usage` object with token counts, `stop_reason` (tool_use | max_tokens | stop_sequence | error | complete), and `image_data` object with Base64-encoded data and mimeType
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Implement separation of concerns where `src/main/presenter/llmProviderPresenter/index.ts` manages the Agent loop and conversation history, while Provider files handle LLM API interactions, Provider-specific request/response formatting, tool definition conversion, and native vs non-native tool call mechanisms
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 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/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/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/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, include helper methods for Provider-specific operations such as `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, and `prepareFunctionCallPrompt`
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, parse Provider-specific data chunks from the streaming response and `yield` standardized `LLMCoreStreamEvent` objects conforming to the standard stream event interface, including text, reasoning, tool calls, usage, errors, stop reasons, and image data
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : In Provider implementations, handle native tool support by converting MCP tools to Provider format using `convertToProviderTools` and including them in the API request; for Providers without native function call support, prepare messages using `prepareFunctionCallPrompt` before making the API call
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : In `src/main/presenter/llmProviderPresenter/index.ts`, handle `reasoning`, `text`, `image_data`, and `usage` events by processing and forwarding them through `STREAM_EVENTS.RESPONSE` events to the frontend
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:39.200Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/provider-guidelines.mdc:0-0
Timestamp: 2025-11-25T05:27:39.200Z
Learning: Applies to **/*Provider**/index.ts : Output only discriminated union `LLMCoreStreamEvent` in Provider implementations, do not use single interface with optional fields
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Each LLM provider must implement the `coreStream` method following the standardized event interface for tool calling and response streaming
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:27:39.200Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/provider-guidelines.mdc:0-0
Timestamp: 2025-11-25T05:27:39.200Z
Learning: Applies to **/*Provider**/index.ts : Tool call events: strictly follow sequence `tool_call_start → tool_call_chunk* → tool_call_end`, ensure `tool_call_id` is required and stable
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
📚 Learning: 2025-11-25T05:28:20.513Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T05:28:20.513Z
Learning: Applies to src/renderer/src/components/**/*.vue : Vue component files must use PascalCase naming (e.g., `ChatInput.vue`)
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:27: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/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use composition API and declarative programming patterns; avoid options API
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/chat-input/ChatInput.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/**/composables/*.ts : Use VueUse for common composables and utility functions
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vuesrc/renderer/src/components/artifacts/MermaidArtifact.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/**/composables/*.ts : Use camelCase for composables (e.g., useAuthState.ts)
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/composables/*.ts : Implement custom composables for reusable logic
Applied to files:
src/renderer/src/components/chat-input/ChatInput.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Import Icon component from 'iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'
Applied to files:
src/renderer/src/components/message/MessageBlockToolCall.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Applied to files:
src/renderer/src/components/message/MessageBlockToolCall.vuesrc/renderer/src/components/artifacts/MermaidArtifact.vue
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/renderer/**/*.vue : All user-facing strings must use i18n keys via vue-i18n for internationalization
Applied to files:
src/renderer/src/components/message/MessageBlockToolCall.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Prefer 'lucide:' icon family as the primary choice for Iconify icons
Applied to files:
src/renderer/src/components/message/MessageBlockToolCall.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use template syntax for declarative rendering
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.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} : Leverage ref, reactive, and computed for reactive state management
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use <script setup> syntax for concise component definitions
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.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/artifacts/MermaidArtifact.vue
🧬 Code graph analysis (1)
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (2)
src/shared/types/core/llm-events.ts (1)
createStreamEvent(100-154)src/shared/chat.d.ts (1)
AssistantMessageBlock(84-147)
🪛 Biome (2.1.2)
src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts
[error] 69-69: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ 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 (12)
src/renderer/src/components/chat-input/ChatInput.vue (2)
398-398: LGTM!The import follows the established pattern for composable imports in this file.
615-618: LGTM!The initialization follows the same pattern as
useAcpWorkdirand correctly uses the sharedactiveModelSourceandconversationIdcomputed refs, ensuring consistent reactive behavior across ACP features.src/renderer/src/components/message/MessageBlockToolCall.vue (4)
29-40: LGTM - Terminal output UI section.The terminal output section properly integrates with the template, using correct i18n translation via
t('toolCall.terminalOutput')and lucide icons per guidelines.
75-78: LGTM - Appropriate imports for terminal functionality.Imports for Vue lifecycle hooks and xterm.js are correctly added.
161-173: Improved parseJson with safer fallback handling.The function now properly handles non-object primitives by wrapping them in
{ raw: ... }, providing consistent output for the JsonObject component.
175-192: LGTM - Terminal detection and params computation.The
isTerminalToolcomputed property uses a reasonable heuristic for terminal-related tools. ThehasParamslogic correctly handles arrays, objects, and strings.src/main/presenter/llmProviderPresenter/agent/acpContentMapper.ts (4)
5-18: LGTM - Well-structured interfaces for plan and mode support.The
PlanEntryinterface and extendedMappedContentprovide clean typing for the new ACP plan/mode features.
176-184: LGTM - Improved tool call parameter handling.The logic correctly prioritizes
stringifyToolParamsoutput and usesparamsCapturedto prevent duplicate emissions. The fallback tocontentChunkwhen params haven't been captured maintains backward compatibility.
214-232: LGTM - Clean mode update handling.The method properly stores the mode ID and emits a reasoning block with mode change metadata for UI visibility.
389-418: LGTM - Robust parameter extraction with proper fallbacks.The method handles multiple input sources (
rawInput,raw_input,locations,title) with appropriate error handling via try-catch blocks. The use of(update as any)is acceptable given the schema's dynamic nature.src/renderer/src/components/artifacts/MermaidArtifact.vue (2)
3-7: Clean approach replacing iframe with direct DOM rendering.The switch from iframe-based rendering to a direct div container with proper Tailwind styling for SVG elements is a good improvement for maintainability and performance.
102-131: Good error handling and safe DOM manipulation.The rendering flow properly sanitizes content before setting it, uses safe
textContentinstead ofinnerHTML, and correctly leverages i18n for error messages. The error display is created safely using DOM APIs.
| /** | ||
| * 过滤 Mermaid 内容中的危险 HTML 标签和属性,防止 XSS 攻击 | ||
| * 参考 svgSanitizer.ts 和 deeplinkPresenter 的实现 | ||
| */ | ||
| const sanitizeMermaidContent = (content: string): string => { | ||
| if (!content || typeof content !== 'string') { | ||
| return '' | ||
| } | ||
| let sanitized = content | ||
| // 移除危险的 HTML 标签及其内容 | ||
| const dangerousTags = [ | ||
| // Script 标签 - 允许执行 JavaScript | ||
| /<script[^>]*>[\s\S]*?<\/script>/gi, | ||
| // Iframe 标签 - 可以嵌入恶意内容 | ||
| /<iframe[^>]*>[\s\S]*?<\/iframe>/gi, | ||
| // Object 和 Embed 标签 - 可以执行代码 | ||
| /<object[^>]*>[\s\S]*?<\/object>/gi, | ||
| /<embed[^>]*[^>]*>/gi, | ||
| // Form 标签 - 可能用于 CSRF | ||
| /<form[^>]*>[\s\S]*?<\/form>/gi, | ||
| // Link 标签 - 可能加载恶意样式或脚本 | ||
| /<link[^>]*>/gi, | ||
| // Style 标签 - 可能包含恶意 CSS | ||
| /<style[^>]*>[\s\S]*?<\/style>/gi, | ||
| // Meta 标签 - 可能用于重定向或执行 | ||
| /<meta[^>]*>/gi, | ||
| // Img 标签 - PoC 中使用的攻击向量,带事件处理器特别危险 | ||
| /<img[^>]*>/gi | ||
| ] | ||
| // 移除危险标签 | ||
| for (const pattern of dangerousTags) { | ||
| sanitized = sanitized.replace(pattern, '') | ||
| } | ||
| // 移除所有事件处理器属性 (on* 属性) | ||
| // 这包括 onerror, onclick, onload, onmouseover 等 | ||
| sanitized = sanitized.replace(/on\w+\s*=\s*["'][^"']*["']/gi, '') | ||
| // 移除危险的协议 | ||
| const dangerousProtocols = [/javascript\s*:/gi, /vbscript\s*:/gi, /data\s*:\s*text\/html/gi] | ||
| for (const pattern of dangerousProtocols) { | ||
| sanitized = sanitized.replace(pattern, '') | ||
| } | ||
| return sanitized | ||
| } |
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
Use English for comments in new code; improve event handler regex.
Per coding guidelines, new code should use English for comments instead of Chinese.
Additionally, the event handler regex on line 75 only catches quoted attribute values. Unquoted values like onerror=alert(1) (valid HTML5) would bypass this check.
-/**
- * 过滤 Mermaid 内容中的危险 HTML 标签和属性,防止 XSS 攻击
- * 参考 svgSanitizer.ts 和 deeplinkPresenter 的实现
- */
+/**
+ * Sanitize Mermaid content by removing dangerous HTML tags and attributes to prevent XSS attacks.
+ * References svgSanitizer.ts and deeplinkPresenter implementation.
+ */
const sanitizeMermaidContent = (content: string): string => {
// ... existing code ...
- // 移除危险的 HTML 标签及其内容
+ // Remove dangerous HTML tags and their content
const dangerousTags = [
- // Script 标签 - 允许执行 JavaScript
+ // Script tags - allow JavaScript execution
/<script[^>]*>[\s\S]*?<\/script>/gi,
- // Iframe 标签 - 可以嵌入恶意内容
+ // Iframe tags - can embed malicious content
// ... similarly translate other comments ...
]
- // 移除危险标签
+ // Remove dangerous tags
for (const pattern of dangerousTags) {
sanitized = sanitized.replace(pattern, '')
}
- // 移除所有事件处理器属性 (on* 属性)
- // 这包括 onerror, onclick, onload, onmouseover 等
- sanitized = sanitized.replace(/on\w+\s*=\s*["'][^"']*["']/gi, '')
+ // Remove all event handler attributes (on* attributes)
+ // This includes onerror, onclick, onload, onmouseover, etc.
+ // Handle both quoted and unquoted attribute values
+ sanitized = sanitized.replace(/\bon\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, '')
- // 移除危险的协议
+ // Remove dangerous protocols
const dangerousProtocols = [/javascript\s*:/gi, /vbscript\s*:/gi, /data\s*:\s*text\/html/gi]
// ...
}Based on learnings, use English for all new comments as per coding guidelines.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * 过滤 Mermaid 内容中的危险 HTML 标签和属性,防止 XSS 攻击 | |
| * 参考 svgSanitizer.ts 和 deeplinkPresenter 的实现 | |
| */ | |
| const sanitizeMermaidContent = (content: string): string => { | |
| if (!content || typeof content !== 'string') { | |
| return '' | |
| } | |
| let sanitized = content | |
| // 移除危险的 HTML 标签及其内容 | |
| const dangerousTags = [ | |
| // Script 标签 - 允许执行 JavaScript | |
| /<script[^>]*>[\s\S]*?<\/script>/gi, | |
| // Iframe 标签 - 可以嵌入恶意内容 | |
| /<iframe[^>]*>[\s\S]*?<\/iframe>/gi, | |
| // Object 和 Embed 标签 - 可以执行代码 | |
| /<object[^>]*>[\s\S]*?<\/object>/gi, | |
| /<embed[^>]*[^>]*>/gi, | |
| // Form 标签 - 可能用于 CSRF | |
| /<form[^>]*>[\s\S]*?<\/form>/gi, | |
| // Link 标签 - 可能加载恶意样式或脚本 | |
| /<link[^>]*>/gi, | |
| // Style 标签 - 可能包含恶意 CSS | |
| /<style[^>]*>[\s\S]*?<\/style>/gi, | |
| // Meta 标签 - 可能用于重定向或执行 | |
| /<meta[^>]*>/gi, | |
| // Img 标签 - PoC 中使用的攻击向量,带事件处理器特别危险 | |
| /<img[^>]*>/gi | |
| ] | |
| // 移除危险标签 | |
| for (const pattern of dangerousTags) { | |
| sanitized = sanitized.replace(pattern, '') | |
| } | |
| // 移除所有事件处理器属性 (on* 属性) | |
| // 这包括 onerror, onclick, onload, onmouseover 等 | |
| sanitized = sanitized.replace(/on\w+\s*=\s*["'][^"']*["']/gi, '') | |
| // 移除危险的协议 | |
| const dangerousProtocols = [/javascript\s*:/gi, /vbscript\s*:/gi, /data\s*:\s*text\/html/gi] | |
| for (const pattern of dangerousProtocols) { | |
| sanitized = sanitized.replace(pattern, '') | |
| } | |
| return sanitized | |
| } | |
| /** | |
| * Sanitize Mermaid content by removing dangerous HTML tags and attributes to prevent XSS attacks. | |
| * References svgSanitizer.ts and deeplinkPresenter implementation. | |
| */ | |
| const sanitizeMermaidContent = (content: string): string => { | |
| if (!content || typeof content !== 'string') { | |
| return '' | |
| } | |
| let sanitized = content | |
| // Remove dangerous HTML tags and their content | |
| const dangerousTags = [ | |
| // Script tags - allow JavaScript execution | |
| /<script[^>]*>[\s\S]*?<\/script>/gi, | |
| // Iframe tags - can embed malicious content | |
| /<iframe[^>]*>[\s\S]*?<\/iframe>/gi, | |
| // Object and Embed tags - can execute code | |
| /<object[^>]*>[\s\S]*?<\/object>/gi, | |
| /<embed[^>]*[^>]*>/gi, | |
| // Form tags - can be used for CSRF | |
| /<form[^>]*>[\s\S]*?<\/form>/gi, | |
| // Link tags - can load malicious styles or scripts | |
| /<link[^>]*>/gi, | |
| // Style tags - may contain malicious CSS | |
| /<style[^>]*>[\s\S]*?<\/style>/gi, | |
| // Meta tags - can be used for redirects or execution | |
| /<meta[^>]*>/gi, | |
| // Img tags - attack vectors used in PoC, especially dangerous with event handlers | |
| /<img[^>]*>/gi | |
| ] | |
| // Remove dangerous tags | |
| for (const pattern of dangerousTags) { | |
| sanitized = sanitized.replace(pattern, '') | |
| } | |
| // Remove all event handler attributes (on* attributes) | |
| // This includes onerror, onclick, onload, onmouseover, etc. | |
| // Handle both quoted and unquoted attribute values | |
| sanitized = sanitized.replace(/\bon\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, '') | |
| // Remove dangerous protocols | |
| const dangerousProtocols = [/javascript\s*:/gi, /vbscript\s*:/gi, /data\s*:\s*text\/html/gi] | |
| for (const pattern of dangerousProtocols) { | |
| sanitized = sanitized.replace(pattern, '') | |
| } | |
| return sanitized | |
| } |
| // 初始化 mermaid,使用更合适的配置 | ||
| onMounted(() => { | ||
| mermaid.initialize({ | ||
| startOnLoad: false, | ||
| theme: isDarkTheme.value ? 'dark' : 'default', | ||
| startOnLoad: true, | ||
| theme: document.documentElement.classList.contains('dark') ? 'dark' : 'default', | ||
| securityLevel: 'strict', | ||
| fontFamily: 'system-ui, -apple-system, sans-serif' | ||
| fontFamily: 'inherit' | ||
| }) | ||
| if (props.isPreview && props.block.content) { | ||
| renderDiagram() | ||
| // 初始渲染 | ||
| if (props.isPreview) { | ||
| nextTick(() => renderDiagram()) | ||
| } | ||
| }) |
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.
🧩 Analysis chain
🌐 Web query:
mermaid.js startOnLoad true vs manual mermaid.run() conflict
💡 Result:
Short answer
- startOnLoad: true makes Mermaid auto-run on DOMContentLoaded; calling mermaid.run()/mermaid.render() yourself while startOnLoad is true can produce duplicate/race behaviour in some versions. Disable the automatic run and initialize manually to avoid conflicts. [1][2][3]
Why
- startOnLoad triggers Mermaid to scan and render on page load. mermaid.run() also scans and renders (it marks processed elements with data-processed to avoid reprocessing). In practice this is safe if you only call run after load — but there have been race/duplicate-render bugs and differences between the public mermaid.render wrapper and mermaidAPI.render that caused "already registered" / duplicate-ID / parallel-render errors in some releases. [1][2][3]
Recommendation (concise)
- Use explicit initialization and manual runs:
- mermaid.initialize({ startOnLoad: false, ...config });
- call mermaid.run({ querySelector: '.mermaid' }) (or mermaid.render for single diagrams) when you need to render (e.g., after dynamic content is inserted).
- This avoids auto-run vs manual-run collisions and gives you control over timing (especially important for single-page apps, dynamic content, hidden containers, or parallel renders). [1][2][3]
If you need an example or have a specific Mermaid version/usage (CDN, ESM, SPA framework), tell me the version and environment and I’ll give a minimal snippet.
Sources
- Mermaid usage / initialize & startOnLoad docs. [1]
- mermaid.run / API docs (describes marking processed elements). [2]
- GitHub discussion about render concurrency / differences between render wrappers (duplicate registration / race issues). [3]
🏁 Script executed:
cat -n src/renderer/src/components/artifacts/MermaidArtifact.vueRepository: ThinkInAIXYZ/deepchat
Length of output: 4875
Fix Chinese comments and change startOnLoad to false to avoid conflicts with manual rendering.
The startOnLoad: true setting conflicts with the manual mermaid.run() calls in renderDiagram(), potentially causing race conditions or duplicate renders. Additionally, replace all Chinese comments with English and make theme detection reactive to support dark mode toggling.
-// 初始化 mermaid,使用更合适的配置
+// Initialize mermaid with appropriate configuration
onMounted(() => {
mermaid.initialize({
- startOnLoad: true,
+ startOnLoad: false,
theme: document.documentElement.classList.contains('dark') ? 'dark' : 'default',
securityLevel: 'strict',
fontFamily: 'inherit'
})
- // 初始渲染
+ // Initial render
if (props.isPreview) {
nextTick(() => renderDiagram())
}
})To support reactive theme changes, add a watcher that re-initializes mermaid and re-renders when the document's dark mode class changes.
🤖 Prompt for AI Agents
In src/renderer/src/components/artifacts/MermaidArtifact.vue around lines
87–100, replace the Chinese comments with English, set mermaid.initialize's
startOnLoad to false to avoid conflicts with manual rendering, and make theme
detection reactive: detect dark-mode changes (e.g., via a MutationObserver on
document.documentElement.classList or a reactive prefers-color-scheme listener),
and when the theme changes re-initialize mermaid with the new theme and call the
existing renderDiagram() to re-render diagrams; ensure the
MutationObserver/listener is cleaned up on unmounted.
| // Watch for expanded state and initialize terminal | ||
| watch( | ||
| [isExpanded, () => props.block.tool_call?.response], | ||
| () => { | ||
| if (isExpanded.value && isTerminalTool.value) { | ||
| nextTick(() => { | ||
| initTerminal() | ||
| }) | ||
| } | ||
| }, | ||
| { immediate: true } | ||
| ) | ||
| onBeforeUnmount(() => { | ||
| if (terminal) { | ||
| terminal.dispose() | ||
| terminal = null | ||
| } | ||
| }) |
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.
Terminal memory leak: dispose existing terminal before re-initialization.
When the response changes while the panel is expanded, initTerminal() creates a new Terminal instance without disposing the previous one. This leaks DOM nodes and event listeners.
// Watch for expanded state and initialize terminal
watch(
[isExpanded, () => props.block.tool_call?.response],
() => {
if (isExpanded.value && isTerminalTool.value) {
nextTick(() => {
+ // Dispose existing terminal before creating new one
+ if (terminal) {
+ terminal.dispose()
+ terminal = null
+ }
initTerminal()
})
+ } else if (terminal) {
+ // Clean up when collapsed
+ terminal.dispose()
+ terminal = null
}
},
{ immediate: true }
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Watch for expanded state and initialize terminal | |
| watch( | |
| [isExpanded, () => props.block.tool_call?.response], | |
| () => { | |
| if (isExpanded.value && isTerminalTool.value) { | |
| nextTick(() => { | |
| initTerminal() | |
| }) | |
| } | |
| }, | |
| { immediate: true } | |
| ) | |
| onBeforeUnmount(() => { | |
| if (terminal) { | |
| terminal.dispose() | |
| terminal = null | |
| } | |
| }) | |
| // Watch for expanded state and initialize terminal | |
| watch( | |
| [isExpanded, () => props.block.tool_call?.response], | |
| () => { | |
| if (isExpanded.value && isTerminalTool.value) { | |
| nextTick(() => { | |
| // Dispose existing terminal before creating new one | |
| if (terminal) { | |
| terminal.dispose() | |
| terminal = null | |
| } | |
| initTerminal() | |
| }) | |
| } else if (terminal) { | |
| // Clean up when collapsed | |
| terminal.dispose() | |
| terminal = null | |
| } | |
| }, | |
| { immediate: true } | |
| ) | |
| onBeforeUnmount(() => { | |
| if (terminal) { | |
| terminal.dispose() | |
| terminal = null | |
| } | |
| }) |
🤖 Prompt for AI Agents
In src/renderer/src/components/message/MessageBlockToolCall.vue around lines 228
to 246, the watcher calls initTerminal() when the response changes while
expanded but does not dispose the existing terminal, causing DOM/event-listener
leaks; before creating a new Terminal (either inside initTerminal() or right
before calling it in the watcher) check if a previous terminal exists and call
terminal.dispose(), remove any associated DOM nodes/listeners and set terminal =
null, then proceed to create and initialize the new Terminal instance so the old
instance is fully cleaned up.
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: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/presenter/configPresenter/acpInitHelper.ts (1)
599-625: PATH key inconsistency could cause runtime failures.After normalization sets
env[normalizedPath.key]at line 581, subsequent code uses hardcoded or platform-derived PATH keys:
- Line 611: Hardcodes
pathKey = 'Path'for Windows system install handling- Line 637: Derives
pathKeyfrom platform check- This creates multiple PATH-like variables if
normalizedPath.keydiffers from the hardcoded/derived keyImpact: Builtin runtime paths (UV, Node) may not be in the PATH actually used by the shell, causing agent initialization to fail when tools aren't found.
Apply this refactor to use
normalizedPath.keyconsistently:+ // Store normalized PATH key for consistent usage + const normalizedPathKey = normalizedPath.key + // Add registry environment variables if using builtin runtime if (useBuiltinRuntime) { // ... registry config ... // On Windows, if app is installed in system directory, set npm prefix to user directory // to avoid permission issues when installing global packages if (process.platform === 'win32' && this.runtimeHelper.isInstalledInSystemDirectory()) { const userNpmPrefix = this.runtimeHelper.getUserNpmPrefix() if (userNpmPrefix) { env.npm_config_prefix = userNpmPrefix env.NPM_CONFIG_PREFIX = userNpmPrefix console.log( '[ACP Init] Set NPM prefix to user directory (system install detected):', userNpmPrefix ) // Add user npm bin directory to PATH - const pathKey = 'Path' const separator = ';' - const existingPath = env[pathKey] || '' + const existingPath = env[normalizedPathKey] || '' const userNpmBinPath = userNpmPrefix // Ensure the user npm bin path is at the beginning of PATH if (existingPath) { - env[pathKey] = [userNpmBinPath, existingPath].filter(Boolean).join(separator) + env[normalizedPathKey] = [userNpmBinPath, existingPath].filter(Boolean).join(separator) } else { - env[pathKey] = userNpmBinPath + env[normalizedPathKey] = userNpmBinPath } console.log('[ACP Init] Added user npm bin directory to PATH:', userNpmBinPath) } } } // Add custom environment variables from profile if (profile.env) { const customEnvCount = Object.entries(profile.env).filter( ([, value]) => value !== undefined && value !== '' ).length Object.entries(profile.env).forEach(([key, value]) => { if (value !== undefined && value !== '') { if (['PATH', 'Path', 'path'].includes(key)) { // Merge PATH variables - const pathKey = process.platform === 'win32' ? 'Path' : 'PATH' const separator = process.platform === 'win32' ? ';' : ':' - const existingPath = env[pathKey] || env[normalizedPath.key] || '' - env[pathKey] = [value, existingPath].filter(Boolean).join(separator) + const existingPath = env[normalizedPathKey] || '' + env[normalizedPathKey] = [value, existingPath].filter(Boolean).join(separator) console.log('[ACP Init] Merged custom PATH from profile:', { customPath: value, - mergedPathLength: env[pathKey].length + mergedPathLength: env[normalizedPathKey].length }) } else { env[key] = valueAlso applies to: 635-644
🧹 Nitpick comments (1)
src/renderer/settings/components/AcpProfileManagerDialog.vue (1)
116-129: Env masking helper works but consider tightening masking + empty-value handlingThe new
maskValuehelper improves things by not dumping full env values into the UI, and the integration intoformatEnvlooks correct. Two small, non-blocking points to consider:
Amount of secret revealed
Exposing the first 10 characters of every value might still be more than you want for API keys/tokens. You could:
- Either fully mask (
'***') or- Only show a very short, fixed prefix (e.g. 3–4 chars) if you still need some visual differentiation.
Empty/undefined values semantics
if (!val) return ''means explicit empty-string envs render asKEY=with nothing else. If you want to make “intentionally empty” clearer, you might render a placeholder like<empty>or***instead.Example tweak (keeping the behavior very close but a bit stricter on masking and clearer on empties):
- const maskValue = (val: string | undefined | null) => { - if (!val) return '' - const str = String(val) - return str.length <= 10 ? str : `${str.slice(0, 10)}***` - } + const maskValue = (val: string | undefined | null) => { + if (val === '' || val === null || val === undefined) return '<empty>' + const str = String(val) + // Only show a short prefix for privacy; always indicate masking + const prefix = str.slice(0, 4) + return `${prefix}***` + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/main/presenter/configPresenter/acpInitHelper.ts(7 hunks)src/renderer/settings/components/AcpProfileManagerDialog.vue(1 hunks)
🧰 Additional context used
📓 Path-based instructions (20)
**/*.{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/configPresenter/acpInitHelper.tssrc/renderer/settings/components/AcpProfileManagerDialog.vue
**/*.{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/configPresenter/acpInitHelper.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/configPresenter/acpInitHelper.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/configPresenter/acpInitHelper.ts
src/main/presenter/configPresenter/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Store and retrieve custom prompts via
configPresenter.getCustomPrompts()for config-based data source management
Files:
src/main/presenter/configPresenter/acpInitHelper.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/configPresenter/acpInitHelper.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/configPresenter/acpInitHelper.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/configPresenter/acpInitHelper.ts
src/**/*
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
New features should be developed in the
srcdirectory
Files:
src/main/presenter/configPresenter/acpInitHelper.tssrc/renderer/settings/components/AcpProfileManagerDialog.vue
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/configPresenter/acpInitHelper.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/configPresenter/acpInitHelper.tssrc/renderer/settings/components/AcpProfileManagerDialog.vue
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use OxLint for linting JavaScript and TypeScript files
Files:
src/main/presenter/configPresenter/acpInitHelper.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/configPresenter/acpInitHelper.ts
src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use EventBus for inter-process communication events
Files:
src/main/presenter/configPresenter/acpInitHelper.ts
**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.vue: Use Vue 3 Composition API for all components instead of Options API
Use Tailwind CSS with scoped styles for component styling
Files:
src/renderer/settings/components/AcpProfileManagerDialog.vue
src/renderer/**/*.vue
📄 CodeRabbit inference engine (CLAUDE.md)
src/renderer/**/*.vue: All user-facing strings must use i18n keys via vue-i18n for internationalization
Ensure proper error handling and loading states in all UI components
Implement responsive design using Tailwind CSS utilities for all UI components
src/renderer/**/*.vue: Use composition API and declarative programming patterns; avoid options API
Structure files: exported component, composables, helpers, static content, types
Use PascalCase for component names (e.g., AuthWizard.vue)
Use Vue 3 with TypeScript, leveraging defineComponent and PropType
Use template syntax for declarative rendering
Use Shadcn Vue, Radix Vue, and Tailwind for components and styling
Implement responsive design with Tailwind CSS; use a mobile-first approach
Use Suspense for asynchronous components
Use <script setup> syntax for concise component definitions
Prefer 'lucide:' icon family as the primary choice for Iconify icons
Import Icon component from '@iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'
Files:
src/renderer/settings/components/AcpProfileManagerDialog.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/settings/components/AcpProfileManagerDialog.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/settings/components/AcpProfileManagerDialog.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/settings/components/AcpProfileManagerDialog.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/settings/components/AcpProfileManagerDialog.vue
🧠 Learnings (1)
📚 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/configPresenter/acpInitHelper.ts
🧬 Code graph analysis (1)
src/main/presenter/configPresenter/acpInitHelper.ts (1)
src/main/presenter/llmProviderPresenter/agent/shellEnvHelper.ts (1)
getShellEnvironment(160-240)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build-check (x64)
🔇 Additional comments (5)
src/main/presenter/configPresenter/acpInitHelper.ts (5)
10-10: LGTM: Import for shell environment integration.The import of
getShellEnvironmentis appropriate for the new shell environment merging functionality and aligns with the async changes tobuildEnvironmentVariables.
242-247: LGTM: Async/await usage is correct.Both call sites properly await
buildEnvironmentVariables, which is now async. The containing methods are already async, so the usage is correct.Also applies to: 274-279
493-498: LGTM: Async method signature.The method signature correctly changed to async with
Promise<Record<string, string>>return type, which is necessary for the shell environment fetching.
519-541: LGTM: Shell environment merging logic.The shell environment integration is well-implemented:
- Collects existing PATH-like keys to preserve them
- Merges non-PATH variables from shell environment
- Prepends shell PATH for proper precedence
- Includes appropriate error handling with warning
542-581: LGTM: PATH preparation and normalization.The PATH assembly and normalization logic is sound:
- Combines existing paths, shell paths, and default paths
- Prepends builtin runtime paths when configured
- Uses
runtimeHelper.normalizePathEnv()for platform-appropriate key handling
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
♻️ Duplicate comments (2)
src/renderer/src/components/artifacts/MermaidArtifact.vue (1)
36-85: Address previously flagged issues: translate comments to English and fix regex pattern.The Chinese comments and the event handler regex issue (line 75 only catches quoted attribute values, missing unquoted
onerror=alert(1)) were flagged in a previous review. Please apply the suggested fixes from that review.src/renderer/src/components/message/MessageBlockToolCall.vue (1)
194-205: Dispose terminal on collapse as well to fully avoid lingering instances
initTerminalnow correctly disposes any existing instance before re-creating, andonBeforeUnmountcleans up on component teardown. However, when the panel is collapsed, the watcher stops callinginitTerminal, so theterminalinstance remains alive (though only one per component) until unmount or the next expand.To eagerly free resources on collapse, you can extend the watcher to dispose when
isExpandedbecomesfalse:watch( [isExpanded, () => props.block.tool_call?.response], () => { - if (isExpanded.value && isTerminalTool.value) { - nextTick(() => { - initTerminal() - }) - } + if (isExpanded.value && isTerminalTool.value) { + nextTick(() => { + initTerminal() + }) + } else if (terminal) { + try { + terminal.dispose() + } catch (error) { + console.warn('[MessageBlockToolCall] Failed to dispose terminal on collapse:', error) + } + terminal = null + } }, { immediate: true } )Also applies to: 240-251
🧹 Nitpick comments (6)
src/renderer/src/components/artifacts/MermaidArtifact.vue (1)
164-173: Translate comment to English and await the async call.Line 164 has a Chinese comment that should be in English per coding guidelines. Additionally,
renderDiagram()returns a Promise but is not awaited, which could lead to unhandled promise rejections in edge cases.-// 监听内容变化和预览状态变化 +// Watch for content and preview state changes watch( [() => props.block.content, () => props.isPreview], async ([newContent, newIsPreview], [oldContent, oldIsPreview]) => { if (newIsPreview && (newContent !== oldContent || newIsPreview !== oldIsPreview)) { await nextTick() - renderDiagram() + await renderDiagram() } } )Based on learnings, use English for all new comments as per coding guidelines.
src/renderer/src/components/message/MessageBlockToolCall.vue (1)
55-56: Use English for new/updated comments to align with project guidelinesLines like the response/terminal comment and the
parseJsoncomment are (partially) in Chinese, while the current guidelines say new comments should be in English.This is minor but easy to fix by rephrasing:
- <!-- 响应 (hide for terminal tools as output is shown above) --> + <!-- Response (hidden for terminal tools as output is shown above) --> @@ -// 解析JSON为对象;解析失败时回退原文 +// Parse JSON into an object; fall back to raw text on parse failureBased on learnings, new comments in
*.ts/*.vuefiles should be written in English.Also applies to: 161-161
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (4)
81-89: Per-session FS handler and restricted fallback workspace look good; consider per-session fallback dirsThe new
registerSessionWorkdir,getFsHandler, andgetFallbackWorkdirflow correctly constrains ACP file access to a configured workspace, and the fallback now uses an app-scoped temp directory instead of an unrestricted root, which addresses the earlier security concern aboutworkspaceRoot: null.Two small improvements you might consider:
- Make the fallback workspace per-session (e.g., append
sessionIdunderdeepchat-acp/sessions) so sessions don’t share a single temp directory and to avoid cross-session collisions.- Given the JSDoc comment mentions “before any fs/terminal operations,” it might be worth either wiring the same
sessionWorkdirsinto terminalcwddefaults (see below) or relaxing the comment to “fs operations” so it reflects current behavior.Overall, the security posture of FS access is much better than the previous unrestricted fallback.
Also applies to: 91-107, 109-122
164-174: Ensure agent-level cleanup also releases FS handlers, workdirs, and terminals
shutdown()andclearSession()correctly clearsessionWorkdirs,fsHandlers, and per-session terminals, butclearSessionsForAgent()(used fromrelease()and the childexithandler) only removes listeners and permission resolvers. Any sessions associated with that agent will still have:
- Entries in
sessionWorkdirsandfsHandlers- Potentially active terminals tracked by
AcpTerminalManagerThis can lead to resource leaks if an agent process is killed or exits unexpectedly.
A simple way to align cleanup paths is to delegate through
clearSessionfor all affected sessionIds, e.g.:private clearSessionsForAgent(agentId: string): void { - for (const [sessionId, entry] of this.sessionListeners.entries()) { - if (entry.agentId === agentId) { - this.sessionListeners.delete(sessionId) - } - } - - for (const [sessionId, entry] of this.permissionResolvers.entries()) { - if (entry.agentId === agentId) { - this.permissionResolvers.delete(sessionId) - } - } + const sessionIds = new Set<string>() + + for (const [sessionId, entry] of this.sessionListeners.entries()) { + if (entry.agentId === agentId) { + sessionIds.add(sessionId) + } + } + + for (const [sessionId, entry] of this.permissionResolvers.entries()) { + if (entry.agentId === agentId) { + sessionIds.add(sessionId) + } + } + + for (const sessionId of sessionIds) { + this.clearSession(sessionId) + } }This keeps all session-scoped cleanup logic in one place and avoids leaking terminals or FS state when an agent goes away.
Also applies to: 218-225, 651-663
247-250: Init capabilities & logging are solid; consider typinginitResultinstead of castingWiring
buildClientCapabilities({ enableFs: true, enableTerminal: true })intoconnection.initializeand then logging session/models/modes from the init result gives good observability and matches the new FS/terminal features.The only minor concern is the
const resultData = initResult as unknown as { ... }cast; it bypasses type checking. If the SDK exposes a concrete type for the initialize response, using that here (or at least a narrower alias) would help catch drift if the protocol changes, while preserving the same runtime behavior.If such a type is not available, what you have is acceptable, especially since all accesses are optional and guarded.
Also applies to: 264-292
582-612: Client proxy FS/terminal wiring works; consider defaulting terminalcwdto session workdirThe new client proxy methods for
readTextFile/writeTextFileand terminal operations are wired correctly:
- FS calls go through
getFsHandler(params.sessionId)→AcpFsHandler, so they benefit from the workspace sandboxing you’ve added.- Terminal calls are delegated to
AcpTerminalManageras expected.One improvement to align terminal behavior with your session workdir model:
- Right now,
createTerminalforwardsparamsas-is, andAcpTerminalManagerdefaultscwdtoprocess.cwd()whenparams.cwdis absent.- Since you’re already tracking
sessionWorkdirs, you could default terminalcwdto the registered workdir (or the fallback workspace) when the caller does not explicitly specify acwd, keeping shell commands scoped similarly to file operations.For example:
// Terminal operations createTerminal: async (params) => { - return this.terminalManager.createTerminal(params) + const finalParams = { ...params } + if (!finalParams.cwd && finalParams.sessionId) { + const workdir = this.sessionWorkdirs.get(finalParams.sessionId) + if (workdir) { + finalParams.cwd = workdir + } + } + return this.terminalManager.createTerminal(finalParams) },This would make terminal execution semantics more predictable and better sandboxed per session without breaking callers that explicitly set
cwd.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts(8 hunks)src/renderer/src/components/artifacts/MermaidArtifact.vue(3 hunks)src/renderer/src/components/message/MessageBlockToolCall.vue(3 hunks)src/renderer/src/i18n/fa-IR/chat.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/renderer/src/i18n/fa-IR/chat.json
🧰 Additional context used
📓 Path-based instructions (25)
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use English for logs and comments (Chinese text exists in legacy code, but new code should use English)
Files:
src/renderer/src/components/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.vue
src/**/*
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
New features should be developed in the
srcdirectory
Files:
src/renderer/src/components/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/renderer/**/*.{vue,js,ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Renderer process code should be placed in
src/renderer(Vue 3 application)
Files:
src/renderer/src/components/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.vue
src/**/*.{ts,tsx,vue,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Prettier with single quotes, no semicolons, and 100 character width
Files:
src/renderer/src/components/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.vuesrc/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Enable and maintain strict TypeScript type checking for all files
**/*.{ts,tsx}: Always use try-catch to handle possible errors in TypeScript code
Provide meaningful error messages when catching errors
Log detailed error logs including error details, context, and stack traces
Distinguish and handle different error types (UserError, NetworkError, SystemError, BusinessError) with appropriate handlers in TypeScript
Use structured logging with logger.error(), logger.warn(), logger.info(), logger.debug() methods from logging utilities
Do not suppress errors (avoid empty catch blocks or silently ignoring errors)
Provide user-friendly error messages for user-facing errors in TypeScript components
Implement error retry mechanisms for transient failures in TypeScript
Avoid logging sensitive information (passwords, tokens, PII) in logs
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Organize core business logic into dedicated Presenter classes, with one presenter per functional domain
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use EventBus from
src/main/eventbus.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/llmProviderPresenter/agent/acpProcessManager.ts
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Do not include AI co-authoring information (e.g., 'Co-Authored-By: Claude') in git commits
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
**/*.{js,ts,jsx,tsx,mjs,cjs}
📄 CodeRabbit inference engine (.cursor/rules/development-setup.mdc)
Write logs and comments in English
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
{src/main/presenter/**/*.ts,src/renderer/**/*.ts}
📄 CodeRabbit inference engine (.cursor/rules/electron-best-practices.mdc)
Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/main/presenter/llmProviderPresenter/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/llm-agent-loop.mdc)
Define the standardized
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/main/**/*.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Main process code for Electron should be placed in
src/main
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use OxLint for linting JavaScript and TypeScript files
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Use camelCase for variable and function names in TypeScript files
Use PascalCase for type and class names in TypeScript
Use SCREAMING_SNAKE_CASE for constant names
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Use EventBus for inter-process communication events
Files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
🧠 Learnings (18)
📚 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/artifacts/MermaidArtifact.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/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use template syntax for declarative rendering
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.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/artifacts/MermaidArtifact.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 **/*.{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/components/artifacts/MermaidArtifact.vue
📚 Learning: 2025-11-25T05:26:15.929Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/development-setup.mdc:0-0
Timestamp: 2025-11-25T05:26:15.929Z
Learning: Applies to **/*.{js,ts,jsx,tsx,mjs,cjs} : Write logs and comments in English
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Import and use useI18n() composable with the t() function to access translations in Vue components and TypeScript files
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.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} : Leverage ref, reactive, and computed for reactive state management
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Use <script setup> syntax for concise component definitions
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.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/artifacts/MermaidArtifact.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/**/composables/*.ts : Use VueUse for common composables and utility functions
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.vue
📚 Learning: 2025-11-25T05:26:43.510Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-11-25T05:26:43.510Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Avoid hardcoding user-facing text and ensure all user-visible text uses the i18n translation system
Applied to files:
src/renderer/src/components/artifacts/MermaidArtifact.vuesrc/renderer/src/components/message/MessageBlockToolCall.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Import Icon component from 'iconify/vue' and use with lucide icons following pattern '{collection}:{icon-name}'
Applied to files:
src/renderer/src/components/message/MessageBlockToolCall.vue
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/renderer/**/*.vue : All user-facing strings must use i18n keys via vue-i18n for internationalization
Applied to files:
src/renderer/src/components/message/MessageBlockToolCall.vue
📚 Learning: 2025-11-25T05:28:04.454Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-11-25T05:28:04.454Z
Learning: Applies to src/renderer/**/*.vue : Prefer 'lucide:' icon family as the primary choice for Iconify icons
Applied to files:
src/renderer/src/components/message/MessageBlockToolCall.vue
📚 Learning: 2025-11-25T05:27:12.209Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-11-25T05:27:12.209Z
Learning: Implement separation of concerns where `src/main/presenter/llmProviderPresenter/index.ts` manages the Agent loop and conversation history, while Provider files handle LLM API interactions, Provider-specific request/response formatting, tool definition conversion, and native vs non-native tool call mechanisms
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:11.312Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T05:26:11.312Z
Learning: Applies to src/main/presenter/mcpPresenter/**/*.ts : Register new MCP tools in `mcpPresenter/index.ts` after implementing them in `inMemoryServers/`
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
📚 Learning: 2025-11-25T05:26:24.867Z
Learnt from: CR
Repo: ThinkInAIXYZ/deepchat PR: 0
File: .cursor/rules/electron-best-practices.mdc:0-0
Timestamp: 2025-11-25T05:26:24.867Z
Learning: Applies to {src/main/presenter/**/*.ts,src/renderer/**/*.ts} : Implement proper inter-process communication (IPC) patterns using Electron's ipcRenderer and ipcMain APIs
Applied to files:
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts
🧬 Code graph analysis (1)
src/main/presenter/llmProviderPresenter/agent/acpProcessManager.ts (3)
src/main/presenter/llmProviderPresenter/agent/acpTerminalManager.ts (1)
AcpTerminalManager(33-244)src/main/presenter/llmProviderPresenter/agent/acpFsHandler.ts (1)
AcpFsHandler(21-115)src/main/presenter/llmProviderPresenter/agent/acpCapabilities.ts (1)
buildClientCapabilities(14-31)
🔇 Additional comments (7)
src/renderer/src/components/artifacts/MermaidArtifact.vue (6)
1-14: LGTM!Template uses declarative rendering with proper conditional display for preview vs code modes. Tailwind CSS classes are well-structured for layout and overflow handling.
16-32: LGTM!Proper use of Vue 3 Composition API with
<script setup>, TypeScript props definition, and i18n integration viauseI18n()composable.
87-120: LGTM!Theme reactivity implementation is well done with
MutationObserverwatching for dark-mode class changes. ThestartOnLoad: falseconfiguration correctly avoids conflicts with manualmermaid.run()calls. Proper cleanup is handled inonBeforeUnmount.
122-131: LGTM!Proper initialization sequence with mermaid setup, theme watcher registration, and conditional initial render using
nextTickfor DOM readiness.
133-162: LGTM!Secure rendering pipeline with proper sanitization, defensive null checks, and safe error handling using
textContent(preventing XSS). User-facing error messages correctly use i18n viat()function.
175-180: LGTM!Proper cleanup of the
MutationObserverinonBeforeUnmountprevents memory leaks.src/renderer/src/components/message/MessageBlockToolCall.vue (1)
29-40: Terminal tool output block wiring looks solidThe dedicated terminal section, conditional response visibility for terminal tools, and use of
t('toolCall.terminalOutput')with lucide icons and Tailwind classes are all consistent with renderer/i18n/Iconify guidelines.Based on learnings, the i18n and Iconify usage here matches the expected patterns.
Also applies to: 53-56
Summary by CodeRabbit
New Features
Localization
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.