From cc8e3ef511895482aed3522a0af92323a4990a0a Mon Sep 17 00:00:00 2001 From: NaccOll Date: Tue, 12 Aug 2025 14:28:54 +0800 Subject: [PATCH] system notification like kilocode --- packages/types/src/global-settings.ts | 2 + src/core/webview/ClineProvider.ts | 3 + src/core/webview/webviewMessageHandler.ts | 15 +++ src/integrations/notifications/index.ts | 97 +++++++++++++++++++ src/shared/ExtensionMessage.ts | 2 + src/shared/WebviewMessage.ts | 7 ++ webview-ui/src/components/chat/ChatView.tsx | 9 ++ .../settings/NotificationSettings.tsx | 41 +++++++- .../src/components/settings/SettingsView.tsx | 4 + .../src/context/ExtensionStateContext.tsx | 3 + webview-ui/src/i18n/locales/ca/settings.json | 15 +++ webview-ui/src/i18n/locales/de/settings.json | 15 +++ webview-ui/src/i18n/locales/en/settings.json | 15 +++ webview-ui/src/i18n/locales/es/settings.json | 15 +++ webview-ui/src/i18n/locales/fr/settings.json | 15 +++ webview-ui/src/i18n/locales/hi/settings.json | 15 +++ webview-ui/src/i18n/locales/id/settings.json | 15 +++ webview-ui/src/i18n/locales/it/settings.json | 15 +++ webview-ui/src/i18n/locales/ja/settings.json | 15 +++ webview-ui/src/i18n/locales/ko/settings.json | 15 +++ webview-ui/src/i18n/locales/nl/settings.json | 15 +++ webview-ui/src/i18n/locales/pl/settings.json | 15 +++ .../src/i18n/locales/pt-BR/settings.json | 15 +++ webview-ui/src/i18n/locales/ru/settings.json | 15 +++ webview-ui/src/i18n/locales/tr/settings.json | 15 +++ webview-ui/src/i18n/locales/vi/settings.json | 15 +++ .../src/i18n/locales/zh-CN/settings.json | 15 +++ .../src/i18n/locales/zh-TW/settings.json | 15 +++ .../src/utils/showSystemNotification.ts | 11 +++ 29 files changed, 462 insertions(+), 2 deletions(-) create mode 100644 src/integrations/notifications/index.ts create mode 100644 webview-ui/src/utils/showSystemNotification.ts diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index dd72d72fe9..3566133a2d 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -97,6 +97,7 @@ export const globalSettingsSchema = z.object({ ttsSpeed: z.number().optional(), soundEnabled: z.boolean().optional(), soundVolume: z.number().optional(), + systemNotificationsEnabled: z.boolean().optional(), maxOpenTabsContext: z.number().optional(), maxWorkspaceFiles: z.number().optional(), @@ -261,6 +262,7 @@ export const EVALS_SETTINGS: RooCodeSettings = { ttsSpeed: 1, soundEnabled: false, soundVolume: 0.5, + systemNotificationsEnabled: false, terminalOutputLineLimit: 500, terminalOutputCharacterLimit: DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT, diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index b6c00ee379..7bd24855ab 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1698,6 +1698,7 @@ export class ClineProvider soundEnabled, ttsEnabled, ttsSpeed, + systemNotificationsEnabled, diffEnabled, enableCheckpoints, taskHistory, @@ -1804,6 +1805,7 @@ export class ClineProvider soundEnabled: soundEnabled ?? false, ttsEnabled: ttsEnabled ?? false, ttsSpeed: ttsSpeed ?? 1.0, + systemNotificationsEnabled: systemNotificationsEnabled ?? false, diffEnabled: diffEnabled ?? true, enableCheckpoints: enableCheckpoints ?? true, shouldShowAnnouncement: @@ -1999,6 +2001,7 @@ export class ClineProvider soundEnabled: stateValues.soundEnabled ?? false, ttsEnabled: stateValues.ttsEnabled ?? false, ttsSpeed: stateValues.ttsSpeed ?? 1.0, + systemNotificationsEnabled: stateValues.systemNotificationsEnabled ?? false, diffEnabled: stateValues.diffEnabled ?? true, enableCheckpoints: stateValues.enableCheckpoints ?? true, soundVolume: stateValues.soundVolume, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 8e42707a95..2c2a44625e 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -29,6 +29,7 @@ import { checkExistKey } from "../../shared/checkExistApiConfig" import { experimentDefault } from "../../shared/experiments" import { Terminal } from "../../integrations/terminal/Terminal" import { openFile } from "../../integrations/misc/open-file" +import { showSystemNotification } from "../../integrations/notifications" import { CodeIndexManager } from "../../services/code-index/manager" import { openImage, saveImage } from "../../integrations/misc/image-handler" import { selectImages } from "../../integrations/misc/process-images" @@ -975,6 +976,20 @@ export const webviewMessageHandler = async ( await updateGlobalState("soundVolume", soundVolume) await provider.postStateToWebview() break + case "showSystemNotification": + const isSystemNotificationsEnabled = getGlobalState("systemNotificationsEnabled") ?? false + if (!isSystemNotificationsEnabled) { + break + } + if (message.notificationOptions) { + showSystemNotification(message.notificationOptions) + } + break + case "systemNotificationsEnabled": + const systemNotificationsEnabled = message.bool ?? true + await updateGlobalState("systemNotificationsEnabled", systemNotificationsEnabled) + await provider.postStateToWebview() + break case "ttsEnabled": const ttsEnabled = message.bool ?? true await updateGlobalState("ttsEnabled", ttsEnabled) diff --git a/src/integrations/notifications/index.ts b/src/integrations/notifications/index.ts new file mode 100644 index 0000000000..8a26c1bf10 --- /dev/null +++ b/src/integrations/notifications/index.ts @@ -0,0 +1,97 @@ +import { execa } from "execa" +import { platform } from "os" + +interface NotificationOptions { + title?: string + subtitle?: string + message: string +} + +async function showMacOSNotification(options: NotificationOptions): Promise { + const { title, subtitle = "", message } = options + + const script = `display notification "${message}" with title "${title}" subtitle "${subtitle}" sound name "Tink"` + + try { + await execa("osascript", ["-e", script]) + } catch (error) { + throw new Error(`Failed to show macOS notification: ${error}`) + } +} + +async function showWindowsNotification(options: NotificationOptions): Promise { + const { subtitle, message } = options + + const script = ` + [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null + [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null + + $template = @" + + + + ${subtitle} + ${message} + + + +"@ + + $xml = New-Object Windows.Data.Xml.Dom.XmlDocument + $xml.LoadXml($template) + $toast = [Windows.UI.Notifications.ToastNotification]::new($xml) + [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Roo Code").Show($toast) + ` + + try { + await execa("powershell", ["-Command", script]) + } catch (error) { + throw new Error(`Failed to show Windows notification: ${error}`) + } +} + +async function showLinuxNotification(options: NotificationOptions): Promise { + const { title = "", subtitle = "", message } = options + + // Combine subtitle and message if subtitle exists + const fullMessage = subtitle ? `${subtitle}\n${message}` : message + + try { + await execa("notify-send", [title, fullMessage]) + } catch (error) { + throw new Error(`Failed to show Linux notification: ${error}`) + } +} + +export async function showSystemNotification(options: NotificationOptions): Promise { + try { + const { title = "Roo Code", message } = options + + if (!message) { + throw new Error("Message is required") + } + + const escapedOptions = { + ...options, + title: title.replace(/"/g, '\\"'), + message: message.replace(/"/g, '\\"'), + subtitle: options.subtitle?.replace(/"/g, '\\"') || "", + } + + switch (platform()) { + case "darwin": + await showMacOSNotification(escapedOptions) + break + case "win32": + await showWindowsNotification(escapedOptions) + break + case "linux": + await showLinuxNotification(escapedOptions) + break + default: + throw new Error("Unsupported platform") + } + } catch (error) { + console.error("Could not show system notification", error) + } +} diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index dccc1f2af0..5aaca89588 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -96,6 +96,7 @@ export interface ExtensionMessage { | "remoteBrowserEnabled" | "ttsStart" | "ttsStop" + | "showSystemNotification" | "maxReadFileLine" | "fileSearchResults" | "toggleApiConfigPin" @@ -233,6 +234,7 @@ export type ExtensionState = Pick< | "ttsSpeed" | "soundEnabled" | "soundVolume" + | "systemNotificationsEnabled" // | "maxOpenTabsContext" // Optional in GlobalSettings, required here. // | "maxWorkspaceFiles" // Optional in GlobalSettings, required here. // | "showRooIgnoredFiles" // Optional in GlobalSettings, required here. diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index d8b873e40a..eb6f4578f8 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -94,6 +94,8 @@ export interface WebviewMessage { | "ttsEnabled" | "ttsSpeed" | "soundVolume" + | "showSystemNotification" + | "systemNotificationsEnabled" | "diffEnabled" | "enableCheckpoints" | "browserViewportSize" @@ -274,6 +276,11 @@ export interface WebviewMessage { codebaseIndexGeminiApiKey?: string codebaseIndexMistralApiKey?: string } + notificationOptions?: { + title?: string + subtitle?: string + message: string + } } export const checkoutDiffPayloadSchema = z.object({ diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index d2a053b07f..69173e049b 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -57,6 +57,7 @@ import { CheckpointWarning } from "./CheckpointWarning" import QueuedMessages from "./QueuedMessages" import { getLatestTodo } from "@roo/todo" import { QueuedMessage } from "@roo-code/types" +import { showSystemNotification } from "@/utils/showSystemNotification" export interface ChatViewProps { isHidden: boolean @@ -276,6 +277,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction & { ttsEnabled?: boolean ttsSpeed?: number soundEnabled?: boolean soundVolume?: number - setCachedStateField: SetCachedStateField<"ttsEnabled" | "ttsSpeed" | "soundEnabled" | "soundVolume"> + systemNotificationsEnabled?: boolean + setCachedStateField: SetCachedStateField< + "ttsEnabled" | "ttsSpeed" | "soundEnabled" | "soundVolume" | "systemNotificationsEnabled" + > + isChangeDetected: boolean } export const NotificationSettings = ({ @@ -21,10 +26,22 @@ export const NotificationSettings = ({ ttsSpeed, soundEnabled, soundVolume, + systemNotificationsEnabled, + isChangeDetected, setCachedStateField, ...props }: NotificationSettingsProps) => { const { t } = useAppTranslation() + + const onTestNotificationClick = () => { + vscode.postMessage({ + type: "showSystemNotification", + notificationOptions: { + title: t("settings.notifications.system.testTitle"), + message: t("settings.notifications.system.testMessage"), + }, + }) + } return (
@@ -35,6 +52,26 @@ export const NotificationSettings = ({
+
+ setCachedStateField("systemNotificationsEnabled", e.target.checked)} + data-testid="system-notifications-enabled-checkbox"> + {t("settings:notifications.system.label")} + +
+ {t("settings:notifications.system.description")} +
+ {systemNotificationsEnabled && !isChangeDetected && ( + + {t("settings:notifications.system.testButton")} + + )} +
+
(({ onDone, t ttsEnabled, ttsSpeed, soundVolume, + systemNotificationsEnabled, telemetrySetting, terminalOutputLineLimit, terminalOutputCharacterLimit, @@ -300,6 +301,7 @@ const SettingsView = forwardRef(({ onDone, t vscode.postMessage({ type: "ttsEnabled", bool: ttsEnabled }) vscode.postMessage({ type: "ttsSpeed", value: ttsSpeed }) vscode.postMessage({ type: "soundVolume", value: soundVolume }) + vscode.postMessage({ type: "systemNotificationsEnabled", bool: systemNotificationsEnabled }) vscode.postMessage({ type: "diffEnabled", bool: diffEnabled }) vscode.postMessage({ type: "enableCheckpoints", bool: enableCheckpoints }) vscode.postMessage({ type: "browserViewportSize", text: browserViewportSize }) @@ -663,7 +665,9 @@ const SettingsView = forwardRef(({ onDone, t ttsSpeed={ttsSpeed} soundEnabled={soundEnabled} soundVolume={soundVolume} + systemNotificationsEnabled={systemNotificationsEnabled} setCachedStateField={setCachedStateField} + isChangeDetected={isChangeDetected} /> )} diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index e632b27a31..d3beb337f9 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -84,6 +84,7 @@ export interface ExtensionStateContextType extends ExtensionState { setTerminalZdotdir: (value: boolean) => void setTtsEnabled: (value: boolean) => void setTtsSpeed: (value: number) => void + setSystemNotificationsEnabled: (value: boolean) => void setDiffEnabled: (value: boolean) => void setEnableCheckpoints: (value: boolean) => void setBrowserViewportSize: (value: string) => void @@ -441,6 +442,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setSoundVolume: (value) => setState((prevState) => ({ ...prevState, soundVolume: value })), setTtsEnabled: (value) => setState((prevState) => ({ ...prevState, ttsEnabled: value })), setTtsSpeed: (value) => setState((prevState) => ({ ...prevState, ttsSpeed: value })), + setSystemNotificationsEnabled: (value) => + setState((prevState) => ({ ...prevState, systemNotificationsEnabled: value })), setDiffEnabled: (value) => setState((prevState) => ({ ...prevState, diffEnabled: value })), setEnableCheckpoints: (value) => setState((prevState) => ({ ...prevState, enableCheckpoints: value })), setBrowserViewportSize: (value: string) => diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 54d66c17c7..982307e5cd 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -509,6 +509,21 @@ "label": "Habilitar text a veu", "description": "Quan està habilitat, Roo llegirà en veu alta les seves respostes utilitzant text a veu.", "speedLabel": "Velocitat" + }, + "system": { + "label": "Habilitar notificacions del sistema", + "description": "Quan està habilitat, Roo mostrarà notificacions del sistema per a esdeveniments i missatges importants.", + "testButton": "Provar notificació del sistema", + "testTitle": "Roo Code", + "testMessage": "Les notificacions del sistema funcionen correctament!", + "apiReqFailed": "Error de sol·licitud d'API", + "mistakeLimitReached": "Límit d'errors assolit", + "followup": "Esperant la teva resposta de seguiment", + "toolRequest": "Sol·licitud d'eina esperant aprovació", + "browserAction": "Acció del navegador esperant aprovació", + "command": "Ordre esperant aprovació", + "useMcpServer": "Utilitzar servidor MCP per a l'aprovació", + "completionResult": "Tasca completada" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 402e57c8dc..386a31b1f3 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -509,6 +509,21 @@ "label": "Text-zu-Sprache aktivieren", "description": "Wenn aktiviert, liest Roo seine Antworten mit Text-zu-Sprache laut vor.", "speedLabel": "Geschwindigkeit" + }, + "system": { + "label": "Systembenachrichtigungen aktivieren", + "description": "Wenn aktiviert, zeigt Roo Systembenachrichtigungen für wichtige Ereignisse und Nachrichten an.", + "testButton": "Systembenachrichtigung testen", + "testTitle": "Roo Code", + "testMessage": "Systembenachrichtigungen funktionieren ordnungsgemäß!", + "apiReqFailed": "API-Anfragefehler", + "mistakeLimitReached": "Fehlerlimit erreicht", + "followup": "Warte auf deine Antwort", + "toolRequest": "Tool-Anfrage wartet auf Genehmigung", + "browserAction": "Browser-Aktion wartet auf Genehmigung", + "command": "Befehl wartet auf Genehmigung", + "useMcpServer": "MCP-Server für Genehmigung verwenden", + "completionResult": "Aufgabe abgeschlossen" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 63a9445924..f226a35490 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -508,6 +508,21 @@ "label": "Enable text-to-speech", "description": "When enabled, Roo will read aloud its responses using text-to-speech.", "speedLabel": "Speed" + }, + "system": { + "label": "Enable system notifications", + "description": "When enabled, Roo will show system notifications for important events and messages.", + "testButton": "Test System Notification", + "testTitle": "Roo Code", + "testMessage": "System notifications are working properly!", + "apiReqFailed": "API request error", + "mistakeLimitReached": "Mistake limit reached", + "followup": "Waiting for your follow-up reply", + "toolRequest": "Tool request waiting for approval", + "browserAction": "Browser action waiting for approval", + "command": "Command waiting for approval", + "useMcpServer": "Use MCP server for approval", + "completionResult": "Task Complete" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index a67e2520d0..f2f54e266a 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -509,6 +509,21 @@ "label": "Habilitar texto a voz", "description": "Cuando está habilitado, Roo leerá en voz alta sus respuestas usando texto a voz.", "speedLabel": "Velocidad" + }, + "system": { + "label": "Habilitar notificaciones del sistema", + "description": "Cuando está habilitado, Roo mostrará notificaciones del sistema para eventos y mensajes importantes.", + "testButton": "Probar notificación del sistema", + "testTitle": "Roo Code", + "testMessage": "¡Las notificaciones del sistema funcionan correctamente!", + "apiReqFailed": "Error de solicitud de API", + "mistakeLimitReached": "Límite de errores alcanzado", + "followup": "Esperando tu respuesta de seguimiento", + "toolRequest": "Solicitud de herramienta esperando aprobación", + "browserAction": "Acción del navegador esperando aprobación", + "command": "Comando esperando aprobación", + "useMcpServer": "Usar servidor MCP para aprobación", + "completionResult": "Tarea completada" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 36e4629c43..baaa3f584d 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -509,6 +509,21 @@ "label": "Activer la synthèse vocale", "description": "Lorsque cette option est activée, Roo lira ses réponses à haute voix en utilisant la synthèse vocale.", "speedLabel": "Vitesse" + }, + "system": { + "label": "Activer les notifications système", + "description": "Lorsque cette option est activée, Roo affichera des notifications système pour les événements et messages importants.", + "testButton": "Tester la notification système", + "testTitle": "Roo Code", + "testMessage": "Les notifications système fonctionnent correctement !", + "apiReqFailed": "Erreur de requête API", + "mistakeLimitReached": "Limite d'erreurs atteinte", + "followup": "En attente de ta réponse de suivi", + "toolRequest": "Demande d'outil en attente d'approbation", + "browserAction": "Action du navigateur en attente d'approbation", + "command": "Commande en attente d'approbation", + "useMcpServer": "Utiliser le serveur MCP pour l'approbation", + "completionResult": "Tâche terminée" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index a419e7a688..d73e1d5f9a 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -509,6 +509,21 @@ "label": "टेक्स्ट-टू-स्पीच सक्षम करें", "description": "जब सक्षम होता है, तो Roo टेक्स्ट-टू-स्पीच का उपयोग करके अपनी प्रतिक्रियाओं को बोलकर पढ़ेगा।", "speedLabel": "गति" + }, + "system": { + "label": "सिस्टम सूचनाएं सक्षम करें", + "description": "जब सक्षम होता है, तो Roo महत्वपूर्ण घटनाओं और संदेशों के लिए सिस्टम सूचनाएं दिखाएगा।", + "testButton": "सिस्टम सूचना परीक्षण करें", + "testTitle": "Roo Code", + "testMessage": "सिस्टम सूचनाएं ठीक से काम कर रही हैं!", + "apiReqFailed": "API अनुरोध त्रुटि", + "mistakeLimitReached": "त्रुटि सीमा पहुंच गई", + "followup": "आपके फॉलो-अप उत्तर की प्रतीक्षा कर रहे हैं", + "toolRequest": "टूल अनुरोध अनुमोदन की प्रतीक्षा में", + "browserAction": "ब्राउज़र कार्य अनुमोदन की प्रतीक्षा में", + "command": "कमांड अनुमोदन की प्रतीक्षा में", + "useMcpServer": "अनुमोदन के लिए MCP सर्वर का उपयोग करें", + "completionResult": "कार्य पूर्ण" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index fe16c7724a..7100285fef 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -513,6 +513,21 @@ "label": "Aktifkan text-to-speech", "description": "Ketika diaktifkan, Roo akan membacakan responnya menggunakan text-to-speech.", "speedLabel": "Kecepatan" + }, + "system": { + "label": "Aktifkan notifikasi sistem", + "description": "Ketika diaktifkan, Roo akan menampilkan notifikasi sistem untuk event dan pesan penting.", + "testButton": "Tes notifikasi sistem", + "testTitle": "Roo Code", + "testMessage": "Notifikasi sistem berfungsi dengan baik!", + "apiReqFailed": "Kesalahan permintaan API", + "mistakeLimitReached": "Batas kesalahan tercapai", + "followup": "Menunggu balasan lanjutan Anda", + "toolRequest": "Permintaan tool menunggu persetujuan", + "browserAction": "Aksi browser menunggu persetujuan", + "command": "Perintah menunggu persetujuan", + "useMcpServer": "Gunakan server MCP untuk persetujuan", + "completionResult": "Tugas selesai" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 89b900de98..4126483b54 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -509,6 +509,21 @@ "label": "Abilita sintesi vocale", "description": "Quando abilitato, Roo leggerà ad alta voce le sue risposte utilizzando la sintesi vocale.", "speedLabel": "Velocità" + }, + "system": { + "label": "Abilita notifiche di sistema", + "description": "Quando abilitato, Roo mostrerà notifiche di sistema per eventi e messaggi importanti.", + "testButton": "Testa notifica di sistema", + "testTitle": "Roo Code", + "testMessage": "Le notifiche di sistema funzionano correttamente!", + "apiReqFailed": "Errore richiesta API", + "mistakeLimitReached": "Limite errori raggiunto", + "followup": "In attesa della tua risposta di follow-up", + "toolRequest": "Richiesta strumento in attesa di approvazione", + "browserAction": "Azione del browser in attesa di approvazione", + "command": "Comando in attesa di approvazione", + "useMcpServer": "Usa server MCP per approvazione", + "completionResult": "Attività completata" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index d597f259d2..a843e8efa8 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -509,6 +509,21 @@ "label": "音声合成を有効化", "description": "有効にすると、Rooは音声合成を使用して応答を音声で読み上げます。", "speedLabel": "速度" + }, + "system": { + "label": "システム通知を有効化", + "description": "有効にすると、Rooは重要なイベントやメッセージのためにシステム通知を表示します。", + "testButton": "システム通知をテスト", + "testTitle": "Roo Code", + "testMessage": "システム通知が正常に動作しています!", + "apiReqFailed": "APIリクエストエラー", + "mistakeLimitReached": "エラー制限に達しました", + "followup": "フォローアップの返信をお待ちしています", + "toolRequest": "ツールリクエストが承認待ちです", + "browserAction": "ブラウザアクションが承認待ちです", + "command": "コマンドが承認待ちです", + "useMcpServer": "承認にMCPサーバーを使用", + "completionResult": "タスク完了" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 381622ad74..ca595a4d5f 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -509,6 +509,21 @@ "label": "음성 합성 활성화", "description": "활성화되면 Roo는 음성 합성을 사용하여 응답을 소리내어 읽습니다.", "speedLabel": "속도" + }, + "system": { + "label": "시스템 알림 활성화", + "description": "활성화되면 Roo는 중요한 이벤트와 메시지에 대한 시스템 알림을 표시합니다.", + "testButton": "시스템 알림 테스트", + "testTitle": "Roo Code", + "testMessage": "시스템 알림이 정상적으로 작동합니다!", + "apiReqFailed": "API 요청 오류", + "mistakeLimitReached": "오류 한도 도달", + "followup": "후속 답변을 기다리고 있습니다", + "toolRequest": "도구 요청이 승인 대기 중입니다", + "browserAction": "브라우저 작업이 승인 대기 중입니다", + "command": "명령이 승인 대기 중입니다", + "useMcpServer": "승인에 MCP 서버 사용", + "completionResult": "작업 완료" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 27811c0bca..fcb57c1544 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -509,6 +509,21 @@ "label": "Tekst-naar-spraak inschakelen", "description": "Indien ingeschakeld, leest Roo zijn antwoorden hardop voor via tekst-naar-spraak.", "speedLabel": "Snelheid" + }, + "system": { + "label": "Systeemmeldingen inschakelen", + "description": "Indien ingeschakeld, toont Roo systeemmeldingen voor belangrijke gebeurtenissen en berichten.", + "testButton": "Systeemmelding testen", + "testTitle": "Roo Code", + "testMessage": "Systeemmeldingen werken correct!", + "apiReqFailed": "API-verzoekfout", + "mistakeLimitReached": "Foutlimiet bereikt", + "followup": "Wachten op je vervolgantwoord", + "toolRequest": "Toolverzoek wacht op goedkeuring", + "browserAction": "Browseractie wacht op goedkeuring", + "command": "Opdracht wacht op goedkeuring", + "useMcpServer": "MCP-server gebruiken voor goedkeuring", + "completionResult": "Taak voltooid" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index b101a98b78..9b1c75342d 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -509,6 +509,21 @@ "label": "Włącz syntezę mowy", "description": "Gdy włączone, Roo będzie czytać na głos swoje odpowiedzi za pomocą syntezy mowy.", "speedLabel": "Szybkość" + }, + "system": { + "label": "Włącz powiadomienia systemowe", + "description": "Gdy włączone, Roo będzie wyświetlać powiadomienia systemowe dla ważnych zdarzeń i wiadomości.", + "testButton": "Testuj powiadomienie systemowe", + "testTitle": "Roo Code", + "testMessage": "Powiadomienia systemowe działają prawidłowo!", + "apiReqFailed": "Błąd żądania API", + "mistakeLimitReached": "Osiągnięto limit błędów", + "followup": "Oczekiwanie na twoją odpowiedź", + "toolRequest": "Żądanie narzędzia oczekuje na zatwierdzenie", + "browserAction": "Akcja przeglądarki oczekuje na zatwierdzenie", + "command": "Polecenie oczekuje na zatwierdzenie", + "useMcpServer": "Użyj serwera MCP do zatwierdzenia", + "completionResult": "Zadanie ukończone" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 20064675c8..380496e85a 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -509,6 +509,21 @@ "label": "Ativar texto para fala", "description": "Quando ativado, o Roo lerá em voz alta suas respostas usando texto para fala.", "speedLabel": "Velocidade" + }, + "system": { + "label": "Ativar notificações do sistema", + "description": "Quando ativado, o Roo mostrará notificações do sistema para eventos e mensagens importantes.", + "testButton": "Testar notificação do sistema", + "testTitle": "Roo Code", + "testMessage": "As notificações do sistema estão funcionando corretamente!", + "apiReqFailed": "Erro de solicitação da API", + "mistakeLimitReached": "Limite de erros alcançado", + "followup": "Aguardando sua resposta de acompanhamento", + "toolRequest": "Solicitação de ferramenta aguardando aprovação", + "browserAction": "Ação do navegador aguardando aprovação", + "command": "Comando aguardando aprovação", + "useMcpServer": "Usar servidor MCP para aprovação", + "completionResult": "Tarefa concluída" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 4143a331fc..57b89d5d57 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -509,6 +509,21 @@ "label": "Включить озвучивание", "description": "Если включено, Roo будет озвучивать свои ответы с помощью преобразования текста в речь.", "speedLabel": "Скорость" + }, + "system": { + "label": "Включить системные уведомления", + "description": "Если включено, Roo будет показывать системные уведомления для важных событий и сообщений.", + "testButton": "Тестировать системное уведомление", + "testTitle": "Roo Code", + "testMessage": "Системные уведомления работают правильно!", + "apiReqFailed": "Ошибка API-запроса", + "mistakeLimitReached": "Достигнут лимит ошибок", + "followup": "Ожидаем твой ответ", + "toolRequest": "Запрос инструмента ожидает одобрения", + "browserAction": "Действие браузера ожидает одобрения", + "command": "Команда ожидает одобрения", + "useMcpServer": "Использовать MCP-сервер для одобрения", + "completionResult": "Задача завершена" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 5de8363038..70311039c1 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -509,6 +509,21 @@ "label": "Metinden sese özelliğini etkinleştir", "description": "Etkinleştirildiğinde, Roo yanıtlarını metinden sese teknolojisi kullanarak sesli okuyacaktır.", "speedLabel": "Hız" + }, + "system": { + "label": "Sistem bildirimlerini etkinleştir", + "description": "Etkinleştirildiğinde, Roo önemli olaylar ve mesajlar için sistem bildirimleri gösterecektir.", + "testButton": "Sistem bildirimini test et", + "testTitle": "Roo Code", + "testMessage": "Sistem bildirimleri düzgün çalışıyor!", + "apiReqFailed": "API istek hatası", + "mistakeLimitReached": "Hata sınırına ulaşıldı", + "followup": "Takip yanıtını bekliyoruz", + "toolRequest": "Araç isteği onay bekliyor", + "browserAction": "Tarayıcı eylemi onay bekliyor", + "command": "Komut onay bekliyor", + "useMcpServer": "Onay için MCP sunucusu kullan", + "completionResult": "Görev tamamlandı" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 6fce8db6f4..ab5c95d021 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -509,6 +509,21 @@ "label": "Bật chuyển văn bản thành giọng nói", "description": "Khi được bật, Roo sẽ đọc to các phản hồi của nó bằng chức năng chuyển văn bản thành giọng nói.", "speedLabel": "Tốc độ" + }, + "system": { + "label": "Bật thông báo hệ thống", + "description": "Khi được bật, Roo sẽ hiển thị thông báo hệ thống cho các sự kiện và tin nhắn quan trọng.", + "testButton": "Kiểm tra thông báo hệ thống", + "testTitle": "Roo Code", + "testMessage": "Thông báo hệ thống hoạt động bình thường!", + "apiReqFailed": "Lỗi yêu cầu API", + "mistakeLimitReached": "Đã đạt giới hạn lỗi", + "followup": "Đang chờ phản hồi tiếp theo của bạn", + "toolRequest": "Yêu cầu công cụ đang chờ phê duyệt", + "browserAction": "Hành động trình duyệt đang chờ phê duyệt", + "command": "Lệnh đang chờ phê duyệt", + "useMcpServer": "Sử dụng máy chủ MCP để phê duyệt", + "completionResult": "Tác vụ hoàn thành" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 948693768c..5f138380ef 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -509,6 +509,21 @@ "label": "启用文本转语音", "description": "启用后,Roo 将使用文本转语音功能朗读其响应。", "speedLabel": "速度" + }, + "system": { + "label": "启用系统通知", + "description": "启用后 Roo 将为重要事件和消息显示系统通知。", + "testButton": "测试系统通知", + "testTitle": "Roo Code", + "testMessage": "系统通知运行正常!", + "apiReqFailed": "API 请求错误", + "mistakeLimitReached": "错误次数达到上限", + "followup": "等待你的后续回复", + "toolRequest": "工具请求等待批准", + "browserAction": "浏览器操作等待批准", + "command": "命令等待批准", + "useMcpServer": "使用 MCP 服务进行批准", + "completionResult": "任务完成" } }, "contextManagement": { diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 8dd76aee3f..c69795c0b2 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -509,6 +509,21 @@ "label": "啟用文字轉語音", "description": "啟用後,Roo 將使用文字轉語音功能朗讀其回應。", "speedLabel": "速度" + }, + "system": { + "label": "啟用系統通知", + "description": "啟用後,Roo 將為重要事件和訊息顯示系統通知。", + "testButton": "測試系統通知", + "testTitle": "Roo Code", + "testMessage": "系統通知運作正常!", + "apiReqFailed": "API 請求錯誤", + "mistakeLimitReached": "錯誤次數達到上限", + "followup": "等待你的後續回覆", + "toolRequest": "工具請求等待核准", + "browserAction": "瀏覽器動作等待核准", + "command": "指令等待核准", + "useMcpServer": "使用 MCP 伺服器進行核准", + "completionResult": "工作完成" } }, "contextManagement": { diff --git a/webview-ui/src/utils/showSystemNotification.ts b/webview-ui/src/utils/showSystemNotification.ts new file mode 100644 index 0000000000..4450553b96 --- /dev/null +++ b/webview-ui/src/utils/showSystemNotification.ts @@ -0,0 +1,11 @@ +import { vscode } from "../utils/vscode" +import debounce from "debounce" + +export const showSystemNotification = debounce((message: string) => { + vscode.postMessage({ + type: "showSystemNotification", + notificationOptions: { + message, + }, + }) +}, 100)