Conversation
* feat: settings auto scroll toggle * feat: i18n support
📝 WalkthroughWalkthroughThis PR introduces a built-in "question" tool feature enabling the assistant to ask users for input and manage pending questions through resolution or rejection. The implementation spans tool definition, event handling, session state management, UI rendering, and internationalization across multiple languages. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant LLM as LLM Agent
participant ToolProcessor as Tool Processor
participant SessionManager as Session Manager
participant Renderer as Renderer
LLM->>ToolProcessor: emit tool_call<br/>(tool_name: 'question', args: {...})
activate ToolProcessor
ToolProcessor->>ToolProcessor: validate standalone<br/>parse args
ToolProcessor->>LLM: emit question_required<br/>event
deactivate ToolProcessor
LLM->>SessionManager: record pendingQuestion<br/>(messageId, toolCallId)
SessionManager->>SessionManager: set status to<br/>waiting_question
SessionManager->>Renderer: update session<br/>status & pendingQuestion
Renderer->>Renderer: render MessageBlockQuestionRequest<br/>with options
Renderer->>User: display question & selectable options
User->>Renderer: select option & submit
Renderer->>SessionManager: resolveQuestion<br/>(messageId, toolCallId, answerText)
activate SessionManager
SessionManager->>SessionManager: update question block<br/>resolution status
SessionManager->>SessionManager: clear pendingQuestion<br/>set status to idle
deactivate SessionManager
SessionManager->>Renderer: update message block
Renderer->>User: display answered state
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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.
Actionable comments posted: 5
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🤖 Fix all issues with AI agents
In `@src/renderer/src/i18n/fa-IR/components.json`:
- Around line 61-69: Translate the English values in the
messageBlockQuestionRequest localization object to Persian: replace
messageBlockQuestionRequest.title, .send, .reject, .selected, .rejected,
.customPlaceholder, and .answerLabel with appropriate Farsi strings (e.g.,
"سؤال", "ارسال", "رد کردن", "انتخاب شد", "رد شد", "پاسخ خود را بنویسید...",
"پاسخ") ensuring key names remain unchanged and consistent with other locale
files; verify translations with a native Persian speaker.
In `@src/renderer/src/i18n/he-IL/components.json`:
- Around line 61-69: Replace the English values under the
messageBlockQuestionRequest object with Hebrew translations: update "title",
"send", "reject", "selected", "rejected", "customPlaceholder", and "answerLabel"
to their Hebrew equivalents (e.g., "שאלה", "שלח", "דחה", "נבחר", "נדחה", "הקלד
את תגובתך...", "תשובה" or other approved translations), ensuring the keys
(messageBlockQuestionRequest.*) remain unchanged and the file stays valid UTF-8
JSON.
In `@src/renderer/src/i18n/ru-RU/common.json`:
- Around line 41-42: The localization entries for the key
"invalidQuestionRequest" are left in English in multiple non‑English locale
JSONs (e.g., ru‑RU, da‑DK, fa‑IR, fr‑FR, he‑IL, ja‑JP, ko‑KR, pt‑BR); update
each locale's JSON to replace "Invalid question request" with an appropriate
native translation (for ru‑RU use "Неверный запрос вопроса"), keeping the exact
key name "invalidQuestionRequest", preserving valid JSON syntax and punctuation,
and ensure all other locale files that currently contain the English string are
similarly updated.
In `@src/renderer/src/i18n/zh-TW/components.json`:
- Around line 61-69: The translations under the messageBlockQuestionRequest
object use Simplified Chinese; update each key value to Traditional Chinese:
replace "问题"→"問題" for title, "发送"→"發送" for send, "拒绝"→"拒絕" for reject,
"已选择"→"已選擇" for selected, "已拒绝"→"已拒絕" for rejected, and "输入你的回答..."→"輸入你的回答..."
for customPlaceholder while keeping answerLabel unchanged; ensure only the
string values are modified in messageBlockQuestionRequest.
In `@src/renderer/src/stores/chat.ts`:
- Around line 1038-1046: The renderer currently pushes raw msg.question_error
strings (in the block that calls finalizeAssistantMessageBlocks and pushes an
'error' message into assistantMsg.content) which causes untranslated
external-agent errors to show; update llmEventHandler (preferred) or the
renderer path before assistantMsg.content.push so that incoming
msg.question_error values are mapped to the existing i18n key
'common.error.invalidQuestionRequest' (or other appropriate keys) by calling the
app's i18n translate function (e.g., t or i18n.t) or by mapping known external
error strings to i18n keys; ensure the converted/translated string is what is
pushed into assistantMsg.content to match toolCallProcessor behavior.
🟡 Minor comments (20)
src/renderer/src/i18n/zh-TW/chat.json-151-160 (1)
151-160:⚠️ Potential issue | 🟡 MinorAlign new keys with the dot‑separated naming convention.
The new
audioandcallkeys are nested objects rather than dot‑separated keys. If the i18n layer expects dot‑separated keys, consider flattening these entries (e.g.,audio.play,call.title) and updating references accordingly.As per coding guidelines: Use dot-separated hierarchical structure for translation key naming with lowercase letters and descriptive names grouped by feature/context.
src/renderer/src/components/icons/ModelIcon.vue-71-74 (1)
71-74:⚠️ Potential issue | 🟡 MinorTranslate the nearby comment to English.
The comment at Line 73 is non-English. Please translate it for consistency.
Suggested change
-// 导入所有图标 +// Import all iconsAs per coding guidelines: Ensure all code comments are in English and all log messages are in English, with no non-English text in code comments or console statements.
src/renderer/src/i18n/fa-IR/settings.json-11-11 (1)
11-11:⚠️ Potential issue | 🟡 MinorRename
autoScrollEnabledto a lowercase dot‑separated key.
This key violates the required naming convention and should be updated (and referenced paths adjusted) to match the lowercase dot‑separated structure.Proposed update (also update call sites + other locales)
- "autoScrollEnabled": "پیمایش خودکار هنگام تولید", + "auto": { + "scroll": { + "enabled": "پیمایش خودکار هنگام تولید" + } + },As per coding guidelines: Use dot-separated hierarchical structure for translation key naming with lowercase letters and descriptive names grouped by feature/context (e.g., common.button.submit, chat.send.placeholder).
src/renderer/src/i18n/ru-RU/components.json-61-69 (1)
61-69:⚠️ Potential issue | 🟡 MinorRussian locale file contains untranslated English strings.
The
messageBlockQuestionRequestblock has English values instead of Russian translations. Russian users will see English text for the question request UI.🌐 Suggested Russian translations
"messageBlockQuestionRequest": { - "title": "Question", - "send": "Send", - "reject": "Reject", - "selected": "Selected", - "rejected": "Rejected", - "customPlaceholder": "Type your answer...", - "answerLabel": "Answer" + "title": "Вопрос", + "send": "Отправить", + "reject": "Отклонить", + "selected": "Выбрано", + "rejected": "Отклонено", + "customPlaceholder": "Введите ответ...", + "answerLabel": "Ответ" }src/renderer/src/i18n/zh-HK/common.json-44-45 (1)
44-45:⚠️ Potential issue | 🟡 MinorUse Traditional Chinese characters for zh-HK locale.
The value
"问题请求无效"uses Simplified Chinese characters, but this is the zh-HK (Hong Kong) locale which should use Traditional Chinese. The rest of the file consistently uses Traditional Chinese.🔤 Proposed fix
- "invalidQuestionRequest": "问题请求无效" + "invalidQuestionRequest": "問題請求無效"src/renderer/src/i18n/fa-IR/common.json-45-46 (1)
45-46:⚠️ Potential issue | 🟡 MinorTranslate to Persian for fa-IR locale.
The value
"Invalid question request"is in English, but this is the Persian (fa-IR) locale. All other error messages in this file are properly translated to Persian.🌍 Proposed fix
- "invalidQuestionRequest": "Invalid question request" + "invalidQuestionRequest": "درخواست سؤال نامعتبر"src/renderer/src/i18n/zh-TW/common.json-41-42 (1)
41-42:⚠️ Potential issue | 🟡 MinorUse Traditional Chinese for zh‑TW.
The new value is in Simplified Chinese; it should be Traditional for this locale.✅ Suggested Traditional Chinese value
- "invalidQuestionRequest": "问题请求无效" + "invalidQuestionRequest": "問題請求無效"src/renderer/src/i18n/he-IL/common.json-45-46 (1)
45-46:⚠️ Potential issue | 🟡 MinorLocalize
invalidQuestionRequestfor he‑IL.
The value is still English, which will show mixed-language errors in Hebrew UI.✅ Suggested translation (please verify with locale reviewer)
- "invalidQuestionRequest": "Invalid question request" + "invalidQuestionRequest": "בקשת שאלה לא תקינה"src/renderer/src/i18n/ja-JP/common.json-45-46 (1)
45-46:⚠️ Potential issue | 🟡 MinorLocalize
invalidQuestionRequestfor ja-JP.
The value is still English, which will surface mixed-language errors in Japanese UI.✅ Suggested translation (please verify with locale reviewer)
- "invalidQuestionRequest": "Invalid question request" + "invalidQuestionRequest": "無効な質問リクエスト"src/renderer/src/i18n/fr-FR/common.json-45-46 (1)
45-46:⚠️ Potential issue | 🟡 MinorLocalize
invalidQuestionRequestfor fr-FR.The new key is still in English, which will surface mixed-language UI in the French locale.
🌍 Suggested translation
- "invalidQuestionRequest": "Invalid question request" + "invalidQuestionRequest": "Demande de question invalide"Based on learnings: Add new translations to ALL language files (da-DK, en-US, fa-IR, fr-FR, he-IL, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW) with consistent key names across all locales.
src/renderer/src/i18n/pt-BR/components.json-61-68 (1)
61-68:⚠️ Potential issue | 🟡 MinorTranslate
messageBlockQuestionRequestfor pt-BR.The new block is still in English, which breaks locale consistency.
🌍 Suggested translation
- "messageBlockQuestionRequest": { - "title": "Question", - "send": "Send", - "reject": "Reject", - "selected": "Selected", - "rejected": "Rejected", - "customPlaceholder": "Type your answer...", - "answerLabel": "Answer" - } + "messageBlockQuestionRequest": { + "title": "Pergunta", + "send": "Enviar", + "reject": "Rejeitar", + "selected": "Selecionado", + "rejected": "Rejeitado", + "customPlaceholder": "Digite sua resposta...", + "answerLabel": "Resposta" + }Based on learnings: Use English (en-US) as the reference for translation accuracy when adding new keys.
src/renderer/src/i18n/ko-KR/common.json-46-47 (1)
46-47:⚠️ Potential issue | 🟡 MinorLocalize
invalidQuestionRequestfor ko-KR.The new error string is still English in the Korean locale.
🌍 Suggested translation
- "invalidQuestionRequest": "Invalid question request" + "invalidQuestionRequest": "잘못된 질문 요청"Based on learnings: Add new translations to ALL language files (da-DK, en-US, fa-IR, fr-FR, he-IL, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW) with consistent key names across all locales.
src/renderer/src/i18n/ja-JP/components.json-61-69 (1)
61-69:⚠️ Potential issue | 🟡 MinorMissing Japanese translations for
messageBlockQuestionRequestblock.All values in this block are in English instead of Japanese. This locale file should contain Japanese translations for these UI strings to provide a proper localized experience for Japanese users.
Expected translations (example):
"title": "質問"instead of"Question""send": "送信"instead of"Send""reject": "拒否"instead of"Reject""selected": "選択済み"instead of"Selected""rejected": "拒否済み"instead of"Rejected""customPlaceholder": "回答を入力..."instead of"Type your answer...""answerLabel": "回答"instead of"Answer"Based on learnings: "Add new translations to ALL language files (da-DK, en-US, fa-IR, fr-FR, he-IL, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW) with consistent key names across all locales."
src/renderer/src/i18n/da-DK/common.json-48-48 (1)
48-48:⚠️ Potential issue | 🟡 MinorMissing Danish translation for
invalidQuestionRequest.The value is in English instead of Danish. This should be translated to Danish for consistency with the rest of the locale file.
Suggested translation:
"invalidQuestionRequest": "Ugyldig spørgsmålsanmodning"Based on learnings: "Add new translations to ALL language files with consistent key names across all locales."
src/renderer/src/i18n/da-DK/components.json-61-69 (1)
61-69:⚠️ Potential issue | 🟡 MinorMissing Danish translations for
messageBlockQuestionRequestblock.All values in this block are in English instead of Danish. This locale file should contain Danish translations for these UI strings.
Expected translations (example):
"title": "Spørgsmål"instead of"Question""send": "Send"(same in Danish)"reject": "Afvis"instead of"Reject""selected": "Valgt"instead of"Selected""rejected": "Afvist"instead of"Rejected""customPlaceholder": "Skriv dit svar..."instead of"Type your answer...""answerLabel": "Svar"instead of"Answer"Based on learnings: "Add new translations to ALL language files (da-DK, en-US, fa-IR, fr-FR, he-IL, ja-JP, ko-KR, pt-BR, ru-RU, zh-CN, zh-HK, zh-TW) with consistent key names across all locales."
src/renderer/src/i18n/pt-BR/common.json-46-46 (1)
46-46:⚠️ Potential issue | 🟡 MinorTranslation not localized to Portuguese.
The value
"Invalid question request"is in English but this is the pt-BR (Portuguese-Brazil) locale file. All other error messages in this file are properly translated to Portuguese.Suggested translation:
- "invalidQuestionRequest": "Invalid question request" + "invalidQuestionRequest": "Solicitação de pergunta inválida"src/renderer/src/i18n/ko-KR/components.json-61-69 (1)
61-69:⚠️ Potential issue | 🟡 MinorTranslation not localized to Korean.
All values in the
messageBlockQuestionRequestblock are in English, but this is the ko-KR (Korean) locale file. Other entries in this file have proper Korean translations.Suggested Korean translations:
"messageBlockQuestionRequest": { - "title": "Question", - "send": "Send", - "reject": "Reject", - "selected": "Selected", - "rejected": "Rejected", - "customPlaceholder": "Type your answer...", - "answerLabel": "Answer" + "title": "질문", + "send": "보내기", + "reject": "거부", + "selected": "선택됨", + "rejected": "거부됨", + "customPlaceholder": "답변을 입력하세요...", + "answerLabel": "답변" }src/renderer/src/i18n/zh-HK/components.json-61-68 (1)
61-68:⚠️ Potential issue | 🟡 MinorUse Traditional Chinese for zh-HK question-request strings.
The new values are Simplified Chinese; zh-HK should be Traditional.
Suggested translation
"messageBlockQuestionRequest": { - "title": "问题", - "send": "发送", - "reject": "拒绝", - "selected": "已选择", - "rejected": "已拒绝", - "customPlaceholder": "输入你的回答...", - "answerLabel": "回答" + "title": "問題", + "send": "發送", + "reject": "拒絕", + "selected": "已選擇", + "rejected": "已拒絕", + "customPlaceholder": "輸入你的回答...", + "answerLabel": "回答" }src/renderer/src/i18n/fr-FR/components.json-61-68 (1)
61-68:⚠️ Potential issue | 🟡 MinorLocalize the new question-request strings to French.
The added values are still in English, which will surface mixed-language UI in fr-FR.
Suggested translation
"messageBlockQuestionRequest": { "title": "Question", - "send": "Send", - "reject": "Reject", - "selected": "Selected", - "rejected": "Rejected", - "customPlaceholder": "Type your answer...", - "answerLabel": "Answer" + "send": "Envoyer", + "reject": "Refuser", + "selected": "Sélectionné", + "rejected": "Refusé", + "customPlaceholder": "Saisissez votre réponse...", + "answerLabel": "Réponse" }src/main/presenter/agentPresenter/index.ts-402-405 (1)
402-405:⚠️ Potential issue | 🟡 MinorUse the injected SessionManager instead of the global presenter.
handleQuestionResolutionshould clear pending questions on the instance passed intoAgentPresenter, otherwise tests or alternate presenter setups can end up with stale session state.🛠️ Suggested fix
- presenter.sessionManager.clearPendingQuestion(message.conversationId) - presenter.sessionManager.setStatus(message.conversationId, 'idle') + this.sessionManager.clearPendingQuestion(message.conversationId) + this.sessionManager.setStatus(message.conversationId, 'idle')
🧹 Nitpick comments (13)
src/renderer/src/i18n/zh-TW/chat.json (1)
156-158: Prefer ‘智能體’ for Agent terminology in zh‑TW.Line 157 uses “語音代理”. To align with the Chinese locale guidance for “Agents”, consider “語音智能體” (keeping “Voice.ai” as a proper noun).
As per coding guidelines: For Chinese translations, consider using '智能体' for 'Agents' instead of the English term.✏️ Suggested tweak
- "description": "點擊連接 Voice.ai 語音代理,通話接通後即可說話。", + "description": "點擊連接 Voice.ai 語音智能體,通話接通後即可說話。",test/renderer/message/messageBlockSnapshot.test.ts (1)
5-8: Comments should be in English per coding guidelines.The comment block is in Chinese. As per the coding guidelines for
**/*.{js,ts,tsx,jsx,vue,mjs,cjs}, all logs and comments must be in English.🔧 Suggested fix
-/** - * 消息块数据结构快照测试 - * 确保事件到UI块的映射结构保持一致 - */ +/** + * Message Block Data Structure Snapshot Tests + * Ensures event-to-UI-block mapping structures remain consistent + */src/renderer/src/components/chat-input/VoiceCallWidget.vue (1)
49-74: Align props/emits typing and Shadcn import alias with project conventions.
- Please switch the inline props/emits types to named interfaces for consistency across components.
- Also confirm Shadcn imports should use the
@/shadcn/...alias per renderer conventions (this file currently uses@shadcn/...).♻️ Suggested refactor for props/emits typing
+interface VoiceCallWidgetProps { + variant: 'chat' | 'newThread' + activeProviderId?: string | null + isStreaming?: boolean +} + +interface VoiceCallWidgetEmits { + (event: 'active-change', value: boolean): void +} + const props = withDefaults( - defineProps<{ - variant: 'chat' | 'newThread' - activeProviderId?: string | null - isStreaming?: boolean - }>(), + defineProps<VoiceCallWidgetProps>(), { activeProviderId: null, isStreaming: false } ) -const emit = defineEmits<{ - (event: 'active-change', value: boolean): void -}>() +const emit = defineEmits<VoiceCallWidgetEmits>()As per coding guidelines: Define props and emits explicitly in Vue components using
definePropsanddefineEmitswith TypeScript interfaces; Import Shadcn Vue components from@/shadcn/components/ui/path alias.src/main/presenter/sessionPresenter/types.ts (1)
1-7: ConsolidateSessionStatustype to single source of truth in@shared/types.
SessionStatusis defined identically in three locations:src/main/presenter/sessionPresenter/types.ts,src/main/presenter/agentPresenter/session/sessionContext.ts, andsrc/shared/types/presenters/session.presenter.d.ts. To reduce duplication and prevent type drift, import fromsrc/shared/types/presenters/session.presenter.d.tsin the two main process files instead of defining locally.src/main/presenter/agentPresenter/session/sessionContext.ts (1)
37-41: Consider whetherpendingQuestionInitializedis necessary.The
pendingQuestionstructure follows the existingpendingPermissionpattern, which is good for consistency. However,pendingQuestionInitializedseems redundant if the presence ofpendingQuestionalready indicates an active question flow.Could this flag be derived from
pendingQuestion !== undefinedinstead? If there's a specific use case where a question exists but isn't "initialized," it would be helpful to document that distinction.src/renderer/settings/components/OllamaProviderSettingsDetail.vue (1)
302-307: Align the Tooltip import with the shadcn alias.The new tooltip import uses
@shadcn/..., but the project guideline prefers@/shadcn/.... Consider updating this import (and optionally the other shadcn imports in this file) for consistency.Based on learnings: Applies to src/renderer/src/**/*.{vue,ts,tsx} : Import Shadcn Vue components from `@/shadcn/components/ui/` path aliasSuggested update
-import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger -} from '@shadcn/components/ui/tooltip' +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger +} from '@/shadcn/components/ui/tooltip'src/renderer/settings/components/VoiceAIProviderConfig.vue (1)
236-248: Consider consolidating slider handlers.Both
onTemperatureChangeandonTopPChangefollow identical patterns. A minor refactor could reduce duplication.♻️ Optional: Consolidate slider handlers
+const createSliderHandler = ( + ref: Ref<number>, + key: keyof VoiceAIConfigUpdates +) => (value: number[] | undefined) => { + if (!value || value[0] === undefined) return + ref.value = value[0] + if (isHydrating.value) return + void persistUpdates({ [key]: value[0] }) +} + +const onTemperatureChange = createSliderHandler(temperature, 'temperature') +const onTopPChange = createSliderHandler(topP, 'topP') -const onTemperatureChange = (value: number[] | undefined) => { - if (!value || value[0] === undefined) return - temperature.value = value[0] - if (isHydrating.value) return - void persistUpdates({ temperature: value[0] }) -} - -const onTopPChange = (value: number[] | undefined) => { - if (!value || value[0] === undefined) return - topP.value = value[0] - if (isHydrating.value) return - void persistUpdates({ topP: value[0] }) -}src/renderer/src/components/message/MessageBlockQuestionRequest.vue (1)
52-56: Unused propsmessageIdandconversationId.The props
messageIdandconversationIdare defined but never used within the component. If these are intended for future use or passed by parent convention, consider adding a comment. Otherwise, remove them to keep the interface clean.src/renderer/settings/components/AnthropicProviderSettingsDetail.vue (1)
428-429:hasDefaultBaseUrlis alwaystrue.Since
defaultBaseUrlis a hardcoded non-empty string,hasDefaultBaseUrlwill always betrue. This is fine if the intent is to always show the tooltip for Anthropic. However, if consistency with other providers (likeProviderApiConfig.vuewhich derives it from props) is desired, consider making this computed from a configurable source.src/renderer/src/stores/providerStore.ts (1)
353-386: Consider adding error handling for Voice AI config operations.Both
getVoiceAIConfigandupdateVoiceAIConfigmake multiple async calls toconfigP.getSetting/setSettingwithout try-catch blocks. If the config presenter throws, the error will propagate unhandled. Consider wrapping in try-catch for resilience, consistent with patterns likeloadProviderOrder.Example error handling pattern
const getVoiceAIConfig = async (): Promise<VoiceAIConfig> => { + try { const config = { audioFormat: (await configP.getSetting<string>('voiceAI_audioFormat')) || 'mp3', // ... rest of config } voiceAIConfig.value = config return config + } catch (error) { + console.error('Failed to load Voice AI config:', error) + const defaultConfig: VoiceAIConfig = { + audioFormat: 'mp3', + model: 'voiceai-tts-v1-latest', + language: 'en', + temperature: 1, + topP: 0.8, + agentId: '' + } + voiceAIConfig.value = defaultConfig + return defaultConfig + } }src/renderer/src/components/message/MessageBlockAudio.vue (1)
53-57: Define a props interface for this component.A named props type keeps the component aligned with the Vue typing guideline and improves reuse.
♻️ Suggested refactor
-const props = defineProps<{ - block: AssistantMessageBlock - messageId?: string - threadId?: string -}>() +type MessageBlockAudioProps = { + block: AssistantMessageBlock + messageId?: string + threadId?: string +} + +const props = defineProps<MessageBlockAudioProps>()Based on learnings: Define TypeScript interfaces for Vue component props and data structures.
src/main/presenter/agentPresenter/streaming/llmEventHandler.ts (1)
403-410: Consider consolidating status assignment for clarity.The current flow always sets
waiting_permissionfirst, then conditionally overwrites withwaiting_question. While functionally correct, inverting the condition would make the intent clearer.♻️ Optional refactor for clarity
- presenter.sessionManager.setStatus(state.conversationId, 'waiting_permission') - if (!hasPendingPermissions) { - presenter.sessionManager.setStatus(state.conversationId, 'waiting_question') - } + presenter.sessionManager.setStatus( + state.conversationId, + hasPendingPermissions ? 'waiting_permission' : 'waiting_question' + )src/main/presenter/agentPresenter/tools/questionTool.ts (1)
22-40: Redundant trimming and boolean conversion.The schema already applies
.trim()transforms (lines 8, 9, 13, 14), so manual trimming in the normalization function is unnecessary. Additionally,Boolean(input.multiple)is redundant since zod with.default(false)already ensures a boolean, andinput.custom !== falsecould simply beinput.custom.♻️ Optional simplification
const normalizeQuestionInfo = (input: QuestionToolInput): QuestionInfo => { - const header = input.header?.trim() - const question = input.question.trim() - const options = input.options.map((option) => { - const description = option.description?.trim() - return { - label: option.label.trim(), - ...(description ? { description } : {}) - } - }) + const header = input.header + const options = input.options.map((option) => ({ + label: option.label, + ...(option.description ? { description: option.description } : {}) + })) return { ...(header ? { header } : {}), - question, + question: input.question, options, - multiple: Boolean(input.multiple), - custom: input.custom !== false + multiple: input.multiple, + custom: input.custom } }
* chore: typecheck with tsgo (#1278) * feat: image left align * feat: app settings skills (#1283) * docs: add spec for app-settings * feat: implement chat-driven settings control with skill gating Add a safe, validated API for modifying DeepChat application settings via natural language. Settings changes are controlled by a dedicated 'deepchat-settings' skill to ensure tools are only available when contextually relevant. Key features: - Skill-gated tool injection: settings tools only appear when deepchat-settings skill is active - Safe settings apply API with Zod validation and strict allowlist - Support for toggles (sound, copy COT, chat mode) and enums (language, theme, font size) - Defense-in-depth: runtime skill verification before applying changes - Deep-linked settings navigation for unsupported/complex settings - Comprehensive test coverage for validation, mapping, and skill gating Changes: - Add ChatSettingsToolHandler with validated apply/open methods - Integrate with AgentToolManager for tool definition gating - Create deepchat-settings built-in skill with clear activation rules - Add shared types for requests/responses (chatSettings.ts) - Implement settings window navigation with SECTION_ALIASES - Add unit tests for handler and integration tests for tool gating - Translate spec documents (plan.md, spec.md, tasks.md) to Chinese - Fix type errors in getCurrentValue and OPEN_SECTION_VALUES * refactor: remove chatMode from settings control and add permission service Remove chatMode setting from the allowlist as it requires conversation-scoped updates that are better handled separately. Add permission checking for settings window opening to provide user control over settings navigation. Key changes: - Remove setChatMode tool and related schemas from ChatSettingsToolHandler - Add SettingsPermissionService for managing tool approvals (one-time and session) - Add permission check for deepchat_settings_open tool - Update PermissionHandler to handle settings permission grants - Add rememberable flag to permission request structure - Update AgentToolManager to consume approvals before opening settings - Add settingsPermissionService to main presenter index - Clear settings approvals when conversation ends - Update spec documents to reflect removed chatMode feature - Remove chatMode-related tests and types This ensures settings window opening requires explicit user approval and provides a cleaner separation of concerns for chat mode management. * docs: translate to en * chore: yo browser less context (#1284) * docs: add specs for yo browesr context manager * feat(yo-browser): improve skill description and add yo_browser_cdp_send to offload whitelist * refactor(yobrowser): remove skill gating and make CDP tools always available in agent mode * refactor(yobrowser): add CDP method schema validation with strict enums - Add enum-based validation for cdp_send method (11 common CDP methods) - Add detailed union schemas for each method's parameters with examples - Add normalizeCdpParams method to handle both object and JSON string inputs - Prevent method typos and provide better type safety for CDP interactions * fix(yobrowser): add strict tab ID validation in CDP send handler * chore: update deps * refactor: agent provider simplification (#1286) * docs: add spec for agent provider * refactor(agent): remove BaseAgentProvider layer and simplify provider hierarchy * feat(mcp): implement real Apple Maps search using URL scheme (#1289) * feat: support voice.ai (#1291) * feat: remove custome tiptap (#1295) * feat: settings auto scroll toggle (#1293) * feat: settings auto scroll toggle * feat: i18n support * fix(renderer): remove specific event listeners instead of all * feat: add tooltip for filling default API URL in settings (#1296) * fix: fix model list refresh failed (#1297) * feat: add question tools (#1298) * feat(agent): add question tool flow * feat(mcp): implement real Apple Maps search using URL scheme (#1289) * feat: support voice.ai (#1291) * feat: remove custome tiptap (#1295) * feat: settings auto scroll toggle (#1293) * feat: settings auto scroll toggle * feat: i18n support * fix(renderer): remove specific event listeners instead of all * feat: add tooltip for filling default API URL in settings (#1296) * refactor(question): simplify question request UI to single-choice interface * fix(chat): restore pending question state * fix: review issues --------- Co-authored-by: Qi Jin <jin.qi1@northeastern.edu> Co-authored-by: xiaomo <wegi866@gmail.com> * chore: integrated vue-tsgo (#1299) * chore: integrated vue-tsgo * chore: update recommendation exteion * chore: update * feat: add prompt for ask tool * chore: version to 0.5.7 --------- Co-authored-by: xiaomo <wegi866@gmail.com> Co-authored-by: wanna <wanna.w@binarywalk.com> Co-authored-by: Qi Jin <jin.qi1@northeastern.edu>
Summary by CodeRabbit
Release Notes
New Features
User Interface