diff --git a/.changeset/sound-notifications.md b/.changeset/sound-notifications.md new file mode 100644 index 00000000000..0a900520798 --- /dev/null +++ b/.changeset/sound-notifications.md @@ -0,0 +1,5 @@ +--- +"kilo-code": minor +--- + +Add sound playback for notification events in the VS Code extension. Users can select from 45+ notification sounds or use the system default sound. A test button allows previewing sounds before committing to a selection. Sounds play on agent completion, permission requests, questions, and errors. diff --git a/packages/kilo-vscode/.vscodeignore b/packages/kilo-vscode/.vscodeignore index a1779eec27d..dbc1de5e2a5 100644 --- a/packages/kilo-vscode/.vscodeignore +++ b/packages/kilo-vscode/.vscodeignore @@ -25,3 +25,6 @@ AGENTS.md # Include bin/ directory for CLI binary (production) !bin/** + +# Include audio files for sound notifications +!audio-wav/** diff --git a/packages/kilo-vscode/audio-wav/alert-01.wav b/packages/kilo-vscode/audio-wav/alert-01.wav new file mode 100644 index 00000000000..061fdb53c3a Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-01.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-02.wav b/packages/kilo-vscode/audio-wav/alert-02.wav new file mode 100644 index 00000000000..b73daff94a8 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-02.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-03.wav b/packages/kilo-vscode/audio-wav/alert-03.wav new file mode 100644 index 00000000000..7ad929468c1 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-03.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-04.wav b/packages/kilo-vscode/audio-wav/alert-04.wav new file mode 100644 index 00000000000..b99b52738a4 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-04.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-05.wav b/packages/kilo-vscode/audio-wav/alert-05.wav new file mode 100644 index 00000000000..5580a3f3ed1 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-05.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-06.wav b/packages/kilo-vscode/audio-wav/alert-06.wav new file mode 100644 index 00000000000..48dbd0dc870 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-06.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-07.wav b/packages/kilo-vscode/audio-wav/alert-07.wav new file mode 100644 index 00000000000..ed04924bec9 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-07.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-08.wav b/packages/kilo-vscode/audio-wav/alert-08.wav new file mode 100644 index 00000000000..f9de3611dd4 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-08.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-09.wav b/packages/kilo-vscode/audio-wav/alert-09.wav new file mode 100644 index 00000000000..842417b962a Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-09.wav differ diff --git a/packages/kilo-vscode/audio-wav/alert-10.wav b/packages/kilo-vscode/audio-wav/alert-10.wav new file mode 100644 index 00000000000..f9a80aaddb3 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/alert-10.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-01.wav b/packages/kilo-vscode/audio-wav/bip-bop-01.wav new file mode 100644 index 00000000000..eb259650ce1 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-01.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-02.wav b/packages/kilo-vscode/audio-wav/bip-bop-02.wav new file mode 100644 index 00000000000..44c5ea0d5c5 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-02.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-03.wav b/packages/kilo-vscode/audio-wav/bip-bop-03.wav new file mode 100644 index 00000000000..88899675b73 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-03.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-04.wav b/packages/kilo-vscode/audio-wav/bip-bop-04.wav new file mode 100644 index 00000000000..319ab26d71f Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-04.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-05.wav b/packages/kilo-vscode/audio-wav/bip-bop-05.wav new file mode 100644 index 00000000000..f9db904297d Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-05.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-06.wav b/packages/kilo-vscode/audio-wav/bip-bop-06.wav new file mode 100644 index 00000000000..dd561c3e14d Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-06.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-07.wav b/packages/kilo-vscode/audio-wav/bip-bop-07.wav new file mode 100644 index 00000000000..9ccf4984680 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-07.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-08.wav b/packages/kilo-vscode/audio-wav/bip-bop-08.wav new file mode 100644 index 00000000000..ec87ee8ce17 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-08.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-09.wav b/packages/kilo-vscode/audio-wav/bip-bop-09.wav new file mode 100644 index 00000000000..1a11d73ecc9 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-09.wav differ diff --git a/packages/kilo-vscode/audio-wav/bip-bop-10.wav b/packages/kilo-vscode/audio-wav/bip-bop-10.wav new file mode 100644 index 00000000000..b4d5e705a0c Binary files /dev/null and b/packages/kilo-vscode/audio-wav/bip-bop-10.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-01.wav b/packages/kilo-vscode/audio-wav/nope-01.wav new file mode 100644 index 00000000000..3fa989aaaa2 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-01.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-02.wav b/packages/kilo-vscode/audio-wav/nope-02.wav new file mode 100644 index 00000000000..10948cf9667 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-02.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-03.wav b/packages/kilo-vscode/audio-wav/nope-03.wav new file mode 100644 index 00000000000..dbfb6eeb6e5 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-03.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-04.wav b/packages/kilo-vscode/audio-wav/nope-04.wav new file mode 100644 index 00000000000..dd1893e4b2a Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-04.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-05.wav b/packages/kilo-vscode/audio-wav/nope-05.wav new file mode 100644 index 00000000000..562e49f9576 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-05.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-06.wav b/packages/kilo-vscode/audio-wav/nope-06.wav new file mode 100644 index 00000000000..7192f7a31c8 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-06.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-07.wav b/packages/kilo-vscode/audio-wav/nope-07.wav new file mode 100644 index 00000000000..f7d760c2a61 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-07.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-08.wav b/packages/kilo-vscode/audio-wav/nope-08.wav new file mode 100644 index 00000000000..7ee5c72b48a Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-08.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-09.wav b/packages/kilo-vscode/audio-wav/nope-09.wav new file mode 100644 index 00000000000..254a083320a Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-09.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-10.wav b/packages/kilo-vscode/audio-wav/nope-10.wav new file mode 100644 index 00000000000..9c43e5765ed Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-10.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-11.wav b/packages/kilo-vscode/audio-wav/nope-11.wav new file mode 100644 index 00000000000..934bdd42e9a Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-11.wav differ diff --git a/packages/kilo-vscode/audio-wav/nope-12.wav b/packages/kilo-vscode/audio-wav/nope-12.wav new file mode 100644 index 00000000000..ed0b49189a3 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/nope-12.wav differ diff --git a/packages/kilo-vscode/audio-wav/staplebops-01.wav b/packages/kilo-vscode/audio-wav/staplebops-01.wav new file mode 100644 index 00000000000..4c429b74612 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/staplebops-01.wav differ diff --git a/packages/kilo-vscode/audio-wav/staplebops-02.wav b/packages/kilo-vscode/audio-wav/staplebops-02.wav new file mode 100644 index 00000000000..6ccc3f4f469 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/staplebops-02.wav differ diff --git a/packages/kilo-vscode/audio-wav/staplebops-03.wav b/packages/kilo-vscode/audio-wav/staplebops-03.wav new file mode 100644 index 00000000000..e9ce09bb54c Binary files /dev/null and b/packages/kilo-vscode/audio-wav/staplebops-03.wav differ diff --git a/packages/kilo-vscode/audio-wav/staplebops-04.wav b/packages/kilo-vscode/audio-wav/staplebops-04.wav new file mode 100644 index 00000000000..042e3f93e97 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/staplebops-04.wav differ diff --git a/packages/kilo-vscode/audio-wav/staplebops-05.wav b/packages/kilo-vscode/audio-wav/staplebops-05.wav new file mode 100644 index 00000000000..194f85d02c6 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/staplebops-05.wav differ diff --git a/packages/kilo-vscode/audio-wav/staplebops-06.wav b/packages/kilo-vscode/audio-wav/staplebops-06.wav new file mode 100644 index 00000000000..0a7bca02a4b Binary files /dev/null and b/packages/kilo-vscode/audio-wav/staplebops-06.wav differ diff --git a/packages/kilo-vscode/audio-wav/staplebops-07.wav b/packages/kilo-vscode/audio-wav/staplebops-07.wav new file mode 100644 index 00000000000..3fc74be97a4 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/staplebops-07.wav differ diff --git a/packages/kilo-vscode/audio-wav/yup-01.wav b/packages/kilo-vscode/audio-wav/yup-01.wav new file mode 100644 index 00000000000..2361194deb2 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/yup-01.wav differ diff --git a/packages/kilo-vscode/audio-wav/yup-02.wav b/packages/kilo-vscode/audio-wav/yup-02.wav new file mode 100644 index 00000000000..acf914a6491 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/yup-02.wav differ diff --git a/packages/kilo-vscode/audio-wav/yup-03.wav b/packages/kilo-vscode/audio-wav/yup-03.wav new file mode 100644 index 00000000000..58865b47fc3 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/yup-03.wav differ diff --git a/packages/kilo-vscode/audio-wav/yup-04.wav b/packages/kilo-vscode/audio-wav/yup-04.wav new file mode 100644 index 00000000000..08f474cc771 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/yup-04.wav differ diff --git a/packages/kilo-vscode/audio-wav/yup-05.wav b/packages/kilo-vscode/audio-wav/yup-05.wav new file mode 100644 index 00000000000..8837d4040a8 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/yup-05.wav differ diff --git a/packages/kilo-vscode/audio-wav/yup-06.wav b/packages/kilo-vscode/audio-wav/yup-06.wav new file mode 100644 index 00000000000..4c65ec82a51 Binary files /dev/null and b/packages/kilo-vscode/audio-wav/yup-06.wav differ diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index e0475c4e79f..1ccd0c7b006 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -952,30 +952,173 @@ "default": true, "description": "Show notification on errors" }, + "kilo-code.new.notifications.playWhenFocused": { + "type": "boolean", + "default": false, + "description": "Play sounds even when VS Code is focused" + }, "kilo-code.new.sounds.agent": { "type": "string", - "default": "default", + "default": "system", "enum": [ "default", - "none" + "none", + "system", + "alert-01", + "alert-02", + "alert-03", + "alert-04", + "alert-05", + "alert-06", + "alert-07", + "alert-08", + "alert-09", + "alert-10", + "bip-bop-01", + "bip-bop-02", + "bip-bop-03", + "bip-bop-04", + "bip-bop-05", + "bip-bop-06", + "bip-bop-07", + "bip-bop-08", + "bip-bop-09", + "bip-bop-10", + "staplebops-01", + "staplebops-02", + "staplebops-03", + "staplebops-04", + "staplebops-05", + "staplebops-06", + "staplebops-07", + "nope-01", + "nope-02", + "nope-03", + "nope-04", + "nope-05", + "nope-06", + "nope-07", + "nope-08", + "nope-09", + "nope-10", + "nope-11", + "nope-12", + "yup-01", + "yup-02", + "yup-03", + "yup-04", + "yup-05", + "yup-06" ], "description": "Sound to play when agent completes" }, "kilo-code.new.sounds.permissions": { "type": "string", - "default": "default", + "default": "system", "enum": [ "default", - "none" + "none", + "system", + "alert-01", + "alert-02", + "alert-03", + "alert-04", + "alert-05", + "alert-06", + "alert-07", + "alert-08", + "alert-09", + "alert-10", + "bip-bop-01", + "bip-bop-02", + "bip-bop-03", + "bip-bop-04", + "bip-bop-05", + "bip-bop-06", + "bip-bop-07", + "bip-bop-08", + "bip-bop-09", + "bip-bop-10", + "staplebops-01", + "staplebops-02", + "staplebops-03", + "staplebops-04", + "staplebops-05", + "staplebops-06", + "staplebops-07", + "nope-01", + "nope-02", + "nope-03", + "nope-04", + "nope-05", + "nope-06", + "nope-07", + "nope-08", + "nope-09", + "nope-10", + "nope-11", + "nope-12", + "yup-01", + "yup-02", + "yup-03", + "yup-04", + "yup-05", + "yup-06" ], "description": "Sound to play on permission requests" }, "kilo-code.new.sounds.errors": { "type": "string", - "default": "default", + "default": "system", "enum": [ "default", - "none" + "none", + "system", + "alert-01", + "alert-02", + "alert-03", + "alert-04", + "alert-05", + "alert-06", + "alert-07", + "alert-08", + "alert-09", + "alert-10", + "bip-bop-01", + "bip-bop-02", + "bip-bop-03", + "bip-bop-04", + "bip-bop-05", + "bip-bop-06", + "bip-bop-07", + "bip-bop-08", + "bip-bop-09", + "bip-bop-10", + "staplebops-01", + "staplebops-02", + "staplebops-03", + "staplebops-04", + "staplebops-05", + "staplebops-06", + "staplebops-07", + "nope-01", + "nope-02", + "nope-03", + "nope-04", + "nope-05", + "nope-06", + "nope-07", + "nope-08", + "nope-09", + "nope-10", + "nope-11", + "nope-12", + "yup-01", + "yup-02", + "yup-03", + "yup-04", + "yup-05", + "yup-06" ], "description": "Sound to play on errors" }, diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 8657c062cf2..1e4dd3fe2a5 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -68,6 +68,7 @@ import { watchFontSizeConfig } from "./kilo-provider/font-size" import { getTerminalContents } from "./services/terminal/context" import { disposeGitChangesTarget } from "./kilo-provider/git-changes-target" import { interceptMessage } from "./kilo-provider/git-changes-request" +import { SoundNotificationService } from "./util/sound-notification" import { matchFollowup, recordFollowup, type Followup } from "./kilo-provider/followup-session" import { clearCommandsCache, loadCommands } from "./kilo-provider/commands" import { fetchMessagePage, MESSAGE_PAGE_LIMIT } from "./kilo-provider/message-page" @@ -160,7 +161,6 @@ const mapAgent = (a: Agent) => ({ model: a.model, }) -// message.part.* events are always session-scoped; drop them when the session is unknown. const SESSION_SCOPED_PART_EVENTS = new Set(["message.part.updated", "message.part.delta", "message.part.removed"]) const isSessionScopedPartEvent = (type: string) => SESSION_SCOPED_PART_EVENTS.has(type) @@ -244,7 +244,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper private chatAutocomplete: ChatTextAreaAutocomplete | null = null private projectDirectory: string | null | undefined private slimEditMetadata = true - private pendingFollowup: Followup | null = null private followupListeners: Array<(session: Session, directory: string) => void> = [] private statsPoller: GitStatsPoller | null = null @@ -263,6 +262,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper private diffVirtualProvider: import("./DiffVirtualProvider").DiffVirtualProvider | undefined private remoteService: RemoteStatusService | null = null private unsubscribeRemote: (() => void) | null = null + private soundService: SoundNotificationService constructor( private readonly extensionUri: vscode.Uri, @@ -272,7 +272,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper ) { this.projectDirectory = opts.projectDirectory this.slimEditMetadata = opts.slimEditMetadata ?? true - + this.soundService = new SoundNotificationService(connectionService) + this.soundService.setupFocusTracking() TelemetryProxy.getInstance().setProvider(this) } @@ -443,7 +444,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper } // legacy-migration end } - public resolveWebviewView( webviewView: vscode.WebviewView, _context: vscode.WebviewViewResolveContext, @@ -972,6 +972,9 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper case "requestNotificationSettings": this.sendNotificationSettings() break + case "testNotification": + this.soundService.handleTestNotification(message.settingType) + break case "requestTimelineSetting": this.sendTimelineSetting() break @@ -1104,17 +1107,13 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper await this.handleFetchMarketplaceData() break } - case "filterMarketplaceItems": { - // Client-side filtering — no server action needed + case "filterMarketplaceItems": break - } case "installMarketplaceItem": { const workspace = this.getProjectDirectory(this.currentSession?.id) const scope = message.mpInstallOptions?.target ?? "project" const result = await this.getMarketplace().install(message.mpItem, message.mpInstallOptions, workspace) - if (result.success) { - await this.invalidateAfterMarketplaceChange(scope) - } + if (result.success) await this.invalidateAfterMarketplaceChange(scope) this.postMessage({ type: "marketplaceInstallResult", success: result.success, @@ -1296,7 +1295,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper // Get current state and push to webview const serverInfo = this.connectionService.getServerInfo() this.connectionState = this.connectionService.getConnectionState() - if (serverInfo) { const langConfig = vscode.workspace.getConfiguration("kilo-code.new") this.postMessage({ @@ -2387,9 +2385,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper notifyAgent: notifications.get("agent", true), notifyPermissions: notifications.get("permissions", true), notifyErrors: notifications.get("errors", true), - soundAgent: sounds.get("agent", "default"), - soundPermissions: sounds.get("permissions", "default"), - soundErrors: sounds.get("errors", "default"), + playWhenFocused: notifications.get("playWhenFocused", false), + soundAgent: sounds.get("agent", "system"), + soundPermissions: sounds.get("permissions", "system"), + soundErrors: sounds.get("errors", "system"), }, }) } @@ -2401,7 +2400,6 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper visible: config.get("showTaskTimeline", true), }) } - /** Returns the number of sessions currently in "busy" state. */ private getBusySessionCount(): number { return getBusySessionCount(this.sessionStatusMap) @@ -3178,6 +3176,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.streams.flush(sid) this.postMessage(msg) } + this.soundService.playSoundForEvent(event, sid, this.trackedSessionIds) return } @@ -3254,7 +3253,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper if (event.type === "indexing.status" && directory) { if (!sameDirectory(directory, this.getWorkspaceDirectory(this.currentSession?.id))) return } - + this.soundService.playSoundForEvent(event, sessionID, this.trackedSessionIds) const msg = mapSSEEventToWebviewMessage(event, sessionID) if (!msg) return if (msg.type === "partUpdated") { @@ -3587,6 +3586,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper this.telemetryStateDisposable?.dispose() this.autoApproveBridge?.dispose() this.visibleTaskStreams.clear() + this.soundService.dispose() this.streams.dispose() this.isWebviewReady = false this.promptRecoveryQueued = false diff --git a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts index 768f6bb6c78..0f193154176 100644 --- a/packages/kilo-vscode/src/services/cli-backend/connection-service.ts +++ b/packages/kilo-vscode/src/services/cli-backend/connection-service.ts @@ -68,6 +68,7 @@ export class KiloConnectionService { private connectPromise: Promise | null = null private healthPollTimer: ReturnType | null = null private remoteService: import("../RemoteStatusService").RemoteStatusService | null = null + private disposed = false private readonly eventListeners: Set = new Set() private readonly stateListeners: Set = new Set() @@ -84,6 +85,8 @@ export class KiloConnectionService { * Used primarily for message.part.updated where only messageID may be present. */ private readonly messageSessionIdsByMessageId: Map = new Map() + private readonly notifiedEvents: Set = new Set() + private readonly notifiedEventTimers: Map = new Map() /** Provider key → single focused session ID. */ private readonly focused: Map = new Map() @@ -302,6 +305,29 @@ export class KiloConnectionService { } } + /** + * Check-and-mark deduplication for OS notifications. + * Returns true the first time a given sessionID + eventType (+ optional requestID) combination is seen, + * and false for all subsequent calls until the entry expires (TTL). + * This prevents multiple KiloProvider instances from emitting duplicate + * OS notifications for the same backend event. + * When requestID is provided, distinct requests in the same session are not suppressed. + */ + shouldNotify(sessionID: string, eventType: string, requestID?: string): boolean { + if (this.disposed) return false + const key = requestID ? `${sessionID}:${eventType}:${requestID}` : `${sessionID}:${eventType}` + if (this.notifiedEvents.has(key)) return false + this.notifiedEvents.add(key) + const existing = this.notifiedEventTimers.get(key) + if (existing) clearTimeout(existing) + const timer = setTimeout(() => { + this.notifiedEvents.delete(key) + this.notifiedEventTimers.delete(key) + }, 5_000) + this.notifiedEventTimers.set(key, timer) + return true + } + /** * Subscribe to migration-complete events broadcast from any KiloProvider. Returns unsubscribe function. */ @@ -478,6 +504,7 @@ export class KiloConnectionService { * Clean up everything: kill server, close SSE, clear listeners. */ dispose(): void { + this.disposed = true this.stopHealthPoll() this.sseClient?.dispose() this.serverManager.dispose() @@ -490,6 +517,11 @@ export class KiloConnectionService { this.clearPendingPromptsListeners.clear() this.directoryProviders.clear() this.messageSessionIdsByMessageId.clear() + this.notifiedEvents.clear() + for (const timer of this.notifiedEventTimers.values()) { + clearTimeout(timer) + } + this.notifiedEventTimers.clear() this.focused.clear() this.opened.clear() if (this.debounceTimer) { diff --git a/packages/kilo-vscode/src/util/sound-notification.ts b/packages/kilo-vscode/src/util/sound-notification.ts new file mode 100644 index 00000000000..0891b33ad5f --- /dev/null +++ b/packages/kilo-vscode/src/util/sound-notification.ts @@ -0,0 +1,147 @@ +import * as vscode from "vscode" +import type { Event } from "@kilocode/sdk/v2/client" +import type { KiloConnectionService } from "../services/cli-backend/connection-service" +import { playSound, resolveSoundId } from "./sound" + +const COOLDOWN_MS = 700 +const COOLDOWN_TTL_MS = COOLDOWN_MS * 10 +const MAX_COOLDOWNS = 200 + +export class SoundNotificationService { + private readonly cooldowns = new Map() + private readonly busySessions = new Map() + private readonly cleanupTimer: NodeJS.Timeout + private focused: boolean | undefined = undefined + private unsubscribeFocus: vscode.Disposable | null = null + + constructor(private readonly connectionService: KiloConnectionService) { + this.cleanupTimer = setInterval(() => { + const now = Date.now() + for (const [key, timestamp] of this.cooldowns) { + if (now - timestamp > COOLDOWN_TTL_MS) { + this.cooldowns.delete(key) + } + } + if (this.cooldowns.size > MAX_COOLDOWNS) { + const sorted = [...this.cooldowns.entries()].sort((a, b) => a[1] - b[1]) + const removeCount = this.cooldowns.size - MAX_COOLDOWNS + for (let i = 0; i < removeCount; i++) { + this.cooldowns.delete(sorted[i][0]) + } + } + this.pruneStaleBusySessions() + }, COOLDOWN_MS * 2) + } + + /** + * Set up window focus tracking. + * Sounds should only play when VS Code is not focused. + */ + setupFocusTracking(): void { + if (vscode.window.onDidChangeWindowState) { + this.unsubscribeFocus = vscode.window.onDidChangeWindowState((state) => { + this.focused = state.focused + }) + this.focused = vscode.window.state.focused + } + } + + private pruneStaleBusySessions(): void { + const now = Date.now() + for (const [sid, startTime] of this.busySessions) { + if (now - startTime > COOLDOWN_TTL_MS * 2) { + this.busySessions.delete(sid) + } + } + } + + playSoundForEvent(event: Event, sessionID: string | undefined, trackedSessionIds: Set): void { + this.pruneStaleBusySessions() + const now = Date.now() + const eventType = event.type + + if (eventType === "session.status") { + const sid = event.properties.sessionID + const status = event.properties.status.type + + if (status === "busy") { + this.busySessions.set(sid, now) + return + } + + if (status === "idle" && this.busySessions.has(sid) && trackedSessionIds.has(sid)) { + this.busySessions.delete(sid) + if (this.connectionService.shouldNotify(sid, "session.status:idle")) { + this.playWithCooldown("agent", now, sid, eventType) + } + } + return + } + + if (eventType === "permission.asked" && sessionID && trackedSessionIds.has(sessionID)) { + if (this.connectionService.shouldNotify(sessionID, "permission.asked", event.properties.id)) { + this.playWithCooldown("permissions", now, sessionID, eventType) + } + return + } + + if (eventType === "question.asked" && sessionID && trackedSessionIds.has(sessionID)) { + if (this.connectionService.shouldNotify(sessionID, "question.asked", event.properties.id)) { + this.playWithCooldown("permissions", now, sessionID, eventType) + } + return + } + + if (eventType === "session.error" && sessionID && trackedSessionIds.has(sessionID)) { + if (this.connectionService.shouldNotify(sessionID, "session.error")) { + this.playWithCooldown("errors", now, sessionID, eventType) + } + } + } + + private playWithCooldown( + setting: "agent" | "permissions" | "errors", + now: number, + sessionID?: string, + eventType?: string, + ): void { + // Don't play sounds when VS Code is focused unless playWhenFocused is true + const notifyConfig = vscode.workspace.getConfiguration("kilo-code.new.notifications") + const playWhenFocused = notifyConfig.get("playWhenFocused", false) + if (this.focused === true && !playWhenFocused) return + + const sessionKey = `${setting}:${eventType}:${sessionID}` + const cooldownKey = sessionID ? sessionKey : setting + const last = this.cooldowns.get(cooldownKey) ?? 0 + if (now - last < COOLDOWN_MS) return + this.cooldowns.set(cooldownKey, now) + + if (!notifyConfig.get(setting, true)) return + + const soundConfig = vscode.workspace.getConfiguration("kilo-code.new.sounds") + const soundSetting = soundConfig.get(setting, "system") + const soundId = resolveSoundId(soundSetting, setting) + if (soundId) { + void playSound(soundId) + } + } + + handleTestNotification(settingType: "agent" | "permissions" | "errors"): void { + const sounds = vscode.workspace.getConfiguration("kilo-code.new.sounds") + const soundSetting = sounds.get(settingType, "system") + const soundId = resolveSoundId(soundSetting, settingType) + if (soundId) { + void playSound(soundId) + } + } + + dispose(): void { + clearInterval(this.cleanupTimer) + this.cooldowns.clear() + this.busySessions.clear() + if (this.unsubscribeFocus) { + this.unsubscribeFocus.dispose() + } + this.unsubscribeFocus = null + } +} diff --git a/packages/kilo-vscode/src/util/sound.ts b/packages/kilo-vscode/src/util/sound.ts new file mode 100644 index 00000000000..21624821978 --- /dev/null +++ b/packages/kilo-vscode/src/util/sound.ts @@ -0,0 +1,220 @@ +import { exec } from "../util/process" +import * as path from "path" +import * as fs from "fs" + +const SOUND_DIR = path.join(__dirname, "../audio-wav") + +export type SoundID = + | "system" + | "alert-01" + | "alert-02" + | "alert-03" + | "alert-04" + | "alert-05" + | "alert-06" + | "alert-07" + | "alert-08" + | "alert-09" + | "alert-10" + | "bip-bop-01" + | "bip-bop-02" + | "bip-bop-03" + | "bip-bop-04" + | "bip-bop-05" + | "bip-bop-06" + | "bip-bop-07" + | "bip-bop-08" + | "bip-bop-09" + | "bip-bop-10" + | "staplebops-01" + | "staplebops-02" + | "staplebops-03" + | "staplebops-04" + | "staplebops-05" + | "staplebops-06" + | "staplebops-07" + | "nope-01" + | "nope-02" + | "nope-03" + | "nope-04" + | "nope-05" + | "nope-06" + | "nope-07" + | "nope-08" + | "nope-09" + | "nope-10" + | "nope-11" + | "nope-12" + | "yup-01" + | "yup-02" + | "yup-03" + | "yup-04" + | "yup-05" + | "yup-06" + +const SOUND_MAP: Record = { + system: "", + "alert-01": "alert-01.wav", + "alert-02": "alert-02.wav", + "alert-03": "alert-03.wav", + "alert-04": "alert-04.wav", + "alert-05": "alert-05.wav", + "alert-06": "alert-06.wav", + "alert-07": "alert-07.wav", + "alert-08": "alert-08.wav", + "alert-09": "alert-09.wav", + "alert-10": "alert-10.wav", + "bip-bop-01": "bip-bop-01.wav", + "bip-bop-02": "bip-bop-02.wav", + "bip-bop-03": "bip-bop-03.wav", + "bip-bop-04": "bip-bop-04.wav", + "bip-bop-05": "bip-bop-05.wav", + "bip-bop-06": "bip-bop-06.wav", + "bip-bop-07": "bip-bop-07.wav", + "bip-bop-08": "bip-bop-08.wav", + "bip-bop-09": "bip-bop-09.wav", + "bip-bop-10": "bip-bop-10.wav", + "staplebops-01": "staplebops-01.wav", + "staplebops-02": "staplebops-02.wav", + "staplebops-03": "staplebops-03.wav", + "staplebops-04": "staplebops-04.wav", + "staplebops-05": "staplebops-05.wav", + "staplebops-06": "staplebops-06.wav", + "staplebops-07": "staplebops-07.wav", + "nope-01": "nope-01.wav", + "nope-02": "nope-02.wav", + "nope-03": "nope-03.wav", + "nope-04": "nope-04.wav", + "nope-05": "nope-05.wav", + "nope-06": "nope-06.wav", + "nope-07": "nope-07.wav", + "nope-08": "nope-08.wav", + "nope-09": "nope-09.wav", + "nope-10": "nope-10.wav", + "nope-11": "nope-11.wav", + "nope-12": "nope-12.wav", + "yup-01": "yup-01.wav", + "yup-02": "yup-02.wav", + "yup-03": "yup-03.wav", + "yup-04": "yup-04.wav", + "yup-05": "yup-05.wav", + "yup-06": "yup-06.wav", +} + +const DEFAULT_SOUNDS: Record = { + agent: "alert-01", + permissions: "bip-bop-01", + errors: "nope-01", +} + +export function resolveSoundId( + settingValue: string | undefined, + settingType: "agent" | "permissions" | "errors", +): SoundID | undefined { + if (!settingValue || settingValue === "none") return undefined + if (settingValue === "system") return "system" + + if (settingValue === "default") { + return DEFAULT_SOUNDS[settingType] + } + + if (settingValue in SOUND_MAP) { + return settingValue as SoundID + } + + return undefined +} + +let chain = Promise.resolve() +let queued = 0 + +const MAX_QUEUED = 3 + +async function playSystem(): Promise { + switch (process.platform) { + case "darwin": + await exec("osascript", ["-e", "beep"]).catch((err) => { + console.log("[Kilo New] macOS system sound failed:", err) + }) + return + case "linux": + await exec("canberra-gtk-play", ["-i", "message-new-instant"]).catch(async (err) => { + console.log("[Kilo New] canberra-gtk-play failed, trying paplay:", err) + await exec("paplay", ["/usr/share/sounds/freedesktop/stereo/message.oga"]).catch((err2) => { + console.log("[Kilo New] Linux system sound failed:", err2) + }) + }) + return + case "win32": + await exec("powershell", [ + "-NonInteractive", + "-Command", + "[System.Media.SystemSounds]::Exclamation.Play()", + ]).catch((err) => { + console.log("[Kilo New] Windows system sound failed:", err) + }) + return + } +} + +async function playFile(soundId: Exclude): Promise { + const file = SOUND_MAP[soundId] + if (!file) return + + const filePath = path.join(SOUND_DIR, file) + if (!fs.existsSync(filePath)) return + if (!filePath.match(/^[^\x00-\x1F\x7F]+$/)) return + + switch (process.platform) { + case "darwin": + await exec("afplay", [filePath]).catch(async (err) => { + console.log("[Kilo New] afplay failed, trying play:", err) + await exec("play", [filePath]).catch((err2) => { + console.log("[Kilo New] Sound playback failed:", err2) + }) + }) + return + case "linux": + await exec("/usr/bin/aplay", ["-f", "CD", filePath]).catch(async (err) => { + console.log("[Kilo New] aplay failed, trying paplay:", err) + await exec("paplay", [filePath]).catch(async (err2) => { + console.log("[Kilo New] paplay failed, trying play:", err2) + await exec("play", [filePath]).catch((err3) => { + console.log("[Kilo New] Sound playback failed:", err3) + }) + }) + }) + return + case "win32": { + await exec("powershell", [ + "-NonInteractive", + "-Command", + `Add-Type -AssemblyName System.Media; [System.Media.SoundPlayer]::new('${filePath.replace(/'/g, "''")}').PlaySync()`, + ]).catch((err) => { + console.log("[Kilo New] Windows sound playback failed:", err) + }) + return + } + } +} + +export async function playSound(soundId: SoundID): Promise { + if (queued >= MAX_QUEUED) return + + const myChain = chain + queued++ + chain = myChain + .catch(() => {}) + .then(async () => { + if (soundId === "system") { + await playSystem() + return + } + await playFile(soundId) + }) + .finally(() => { + queued-- + }) + + await chain +} diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/NotificationsTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/NotificationsTab.tsx index e77f10e42a4..ea46ac3655a 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/NotificationsTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/NotificationsTab.tsx @@ -1,4 +1,5 @@ import { Component, createSignal, onCleanup } from "solid-js" +import { Button } from "@kilocode/kilo-ui/button" import { Switch } from "@kilocode/kilo-ui/switch" import { Select } from "@kilocode/kilo-ui/select" import { Card } from "@kilocode/kilo-ui/card" @@ -15,6 +16,52 @@ interface SoundOption { const SOUND_OPTIONS: SoundOption[] = [ { value: "default", labelKey: "settings.notifications.sound.default" }, { value: "none", labelKey: "settings.notifications.sound.none" }, + { value: "system", labelKey: "settings.notifications.sound.system" }, + { value: "alert-01", labelKey: "sound.option.alert01" }, + { value: "alert-02", labelKey: "sound.option.alert02" }, + { value: "alert-03", labelKey: "sound.option.alert03" }, + { value: "alert-04", labelKey: "sound.option.alert04" }, + { value: "alert-05", labelKey: "sound.option.alert05" }, + { value: "alert-06", labelKey: "sound.option.alert06" }, + { value: "alert-07", labelKey: "sound.option.alert07" }, + { value: "alert-08", labelKey: "sound.option.alert08" }, + { value: "alert-09", labelKey: "sound.option.alert09" }, + { value: "alert-10", labelKey: "sound.option.alert10" }, + { value: "bip-bop-01", labelKey: "sound.option.bipbop01" }, + { value: "bip-bop-02", labelKey: "sound.option.bipbop02" }, + { value: "bip-bop-03", labelKey: "sound.option.bipbop03" }, + { value: "bip-bop-04", labelKey: "sound.option.bipbop04" }, + { value: "bip-bop-05", labelKey: "sound.option.bipbop05" }, + { value: "bip-bop-06", labelKey: "sound.option.bipbop06" }, + { value: "bip-bop-07", labelKey: "sound.option.bipbop07" }, + { value: "bip-bop-08", labelKey: "sound.option.bipbop08" }, + { value: "bip-bop-09", labelKey: "sound.option.bipbop09" }, + { value: "bip-bop-10", labelKey: "sound.option.bipbop10" }, + { value: "staplebops-01", labelKey: "sound.option.staplebops01" }, + { value: "staplebops-02", labelKey: "sound.option.staplebops02" }, + { value: "staplebops-03", labelKey: "sound.option.staplebops03" }, + { value: "staplebops-04", labelKey: "sound.option.staplebops04" }, + { value: "staplebops-05", labelKey: "sound.option.staplebops05" }, + { value: "staplebops-06", labelKey: "sound.option.staplebops06" }, + { value: "staplebops-07", labelKey: "sound.option.staplebops07" }, + { value: "nope-01", labelKey: "sound.option.nope01" }, + { value: "nope-02", labelKey: "sound.option.nope02" }, + { value: "nope-03", labelKey: "sound.option.nope03" }, + { value: "nope-04", labelKey: "sound.option.nope04" }, + { value: "nope-05", labelKey: "sound.option.nope05" }, + { value: "nope-06", labelKey: "sound.option.nope06" }, + { value: "nope-07", labelKey: "sound.option.nope07" }, + { value: "nope-08", labelKey: "sound.option.nope08" }, + { value: "nope-09", labelKey: "sound.option.nope09" }, + { value: "nope-10", labelKey: "sound.option.nope10" }, + { value: "nope-11", labelKey: "sound.option.nope11" }, + { value: "nope-12", labelKey: "sound.option.nope12" }, + { value: "yup-01", labelKey: "sound.option.yup01" }, + { value: "yup-02", labelKey: "sound.option.yup02" }, + { value: "yup-03", labelKey: "sound.option.yup03" }, + { value: "yup-04", labelKey: "sound.option.yup04" }, + { value: "yup-05", labelKey: "sound.option.yup05" }, + { value: "yup-06", labelKey: "sound.option.yup06" }, ] const NotificationsTab: Component = () => { @@ -24,9 +71,10 @@ const NotificationsTab: Component = () => { const [agentNotify, setAgentNotify] = createSignal(true) const [permNotify, setPermNotify] = createSignal(true) const [errorNotify, setErrorNotify] = createSignal(true) - const [agentSound, setAgentSound] = createSignal("default") - const [permSound, setPermSound] = createSignal("default") - const [errorSound, setErrorSound] = createSignal("default") + const [playWhenFocused, setPlayWhenFocused] = createSignal(false) + const [agentSound, setAgentSound] = createSignal("system") + const [permSound, setPermSound] = createSignal("system") + const [errorSound, setErrorSound] = createSignal("system") const unsubscribe = vscode.onMessage((message: ExtensionMessage) => { if (message.type !== "notificationSettingsLoaded") { @@ -36,6 +84,7 @@ const NotificationsTab: Component = () => { setAgentNotify(s.notifyAgent) setPermNotify(s.notifyPermissions) setErrorNotify(s.notifyErrors) + setPlayWhenFocused(s.playWhenFocused) setAgentSound(s.soundAgent) setPermSound(s.soundPermissions) setErrorSound(s.soundErrors) @@ -48,6 +97,10 @@ const NotificationsTab: Component = () => { vscode.postMessage({ type: "updateSetting", key, value }) } + const test = (settingType: "agent" | "permissions" | "errors") => { + vscode.postMessage({ type: "testNotification", settingType }) + } + return (
@@ -84,7 +137,6 @@ const NotificationsTab: Component = () => { { {language.t("settings.notifications.errors.title")} + + { + setPlayWhenFocused(checked) + save("notifications.playWhenFocused", checked) + }} + hideLabel + > + {language.t("settings.notifications.playWhenFocused.title")} + +

{language.t("settings.notifications.sounds")}

@@ -105,62 +173,77 @@ const NotificationsTab: Component = () => { title={language.t("settings.notifications.agentSound.title")} description={language.t("settings.notifications.agentSound.description")} > - o.value === agentSound())} + value={(o) => o.value} + label={(o) => language.t(o.labelKey)} + onSelect={(o) => { + if (o) { + setAgentSound(o.value) + save("sounds.agent", o.value) + } + }} + variant="secondary" + size="small" + triggerVariant="settings" + /> + +
- o.value === permSound())} + value={(o) => o.value} + label={(o) => language.t(o.labelKey)} + onSelect={(o) => { + if (o) { + setPermSound(o.value) + save("sounds.permissions", o.value) + } + }} + variant="secondary" + size="small" + triggerVariant="settings" + /> + + - o.value === errorSound())} + value={(o) => o.value} + label={(o) => language.t(o.labelKey)} + onSelect={(o) => { + if (o) { + setErrorSound(o.value) + save("sounds.errors", o.value) + } + }} + variant="secondary" + size="small" + triggerVariant="settings" + /> + + diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 8afe59af40a..367b52c5bbf 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1212,6 +1212,8 @@ export const dict = { "settings.notifications.permissions.description": "إظهار إشعار عند طلبات الأذونات", "settings.notifications.errors.title": "أخطاء", "settings.notifications.errors.description": "إظهار إشعار عند الأخطاء", + "settings.notifications.playWhenFocused.title": "تشغيل الأصوات عند التركيز", + "settings.notifications.playWhenFocused.description": "السماح بأصوات الإشعار حتى عندما تكون نافذة VS Code مُركَزة", "settings.notifications.sounds": "أصوات", "settings.notifications.agentSound.title": "صوت إكمال الوكيل", "settings.notifications.agentSound.description": "الصوت عند إكمال الوكيل", @@ -1221,6 +1223,8 @@ export const dict = { "settings.notifications.errorSound.description": "الصوت عند الأخطاء", "settings.notifications.sound.default": "افتراضي", "settings.notifications.sound.none": "بدون", + "settings.notifications.sound.system": "النظام", + "settings.notifications.testSound": "اختبار", "settings.experimental.share.title": "وضع المشاركة", "settings.experimental.share.description": "سلوك مشاركة الجلسة", "settings.experimental.share.manual": "يدوي", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 4ed3ec97abe..b6643adc257 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1240,6 +1240,9 @@ export const dict = { "settings.notifications.permissions.description": "Mostrar notificação em solicitações de permissão", "settings.notifications.errors.title": "Erros", "settings.notifications.errors.description": "Mostrar notificação em erros", + "settings.notifications.playWhenFocused.title": "Reproduzir sons quando focado", + "settings.notifications.playWhenFocused.description": + "Permitir notificações sonoras mesmo quando a janela do VS Code estiver focada", "settings.notifications.sounds": "Sons", "settings.notifications.agentSound.title": "Som de conclusão do agente", "settings.notifications.agentSound.description": "Som ao concluir o agente", @@ -1249,6 +1252,8 @@ export const dict = { "settings.notifications.errorSound.description": "Som em erros", "settings.notifications.sound.default": "Padrão", "settings.notifications.sound.none": "Nenhum", + "settings.notifications.sound.system": "Sistema", + "settings.notifications.testSound": "Teste", "settings.experimental.share.title": "Modo de compartilhamento", "settings.experimental.share.description": "Comportamento do compartilhamento de sessão", "settings.experimental.share.manual": "Manual", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 66990e3da96..b760f0bc3d2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1241,6 +1241,9 @@ export const dict = { "settings.notifications.permissions.description": "Prikaži obavijest pri zahtjevima za dozvolu", "settings.notifications.errors.title": "Greške", "settings.notifications.errors.description": "Prikaži obavijest pri greškama", + "settings.notifications.playWhenFocused.title": "Reproduciraj zvukove prilikom fokusa", + "settings.notifications.playWhenFocused.description": + "Omogući zvučne obavijesti čak i kad je VS Code prozor fokusiran", "settings.notifications.sounds": "Zvukovi", "settings.notifications.agentSound.title": "Zvuk završetka agenta", "settings.notifications.agentSound.description": "Zvuk pri završetku agenta", @@ -1250,6 +1253,8 @@ export const dict = { "settings.notifications.errorSound.description": "Zvuk pri greškama", "settings.notifications.sound.default": "Zadano", "settings.notifications.sound.none": "Ništa", + "settings.notifications.sound.system": "Sistem", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Način dijeljenja", "settings.experimental.share.description": "Ponašanje dijeljenja sesije", "settings.experimental.share.manual": "Ručno", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index e377a75863e..a7827148826 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1234,6 +1234,8 @@ export const dict = { "settings.notifications.permissions.description": "Vis notifikation ved tilladelsesanmodninger", "settings.notifications.errors.title": "Fejl", "settings.notifications.errors.description": "Vis notifikation ved fejl", + "settings.notifications.playWhenFocused.title": "Afspil lyde ved fokus", + "settings.notifications.playWhenFocused.description": "Tillad lydnotifikationer, selvom VS Code-vinduet er i fokus", "settings.notifications.sounds": "Lyde", "settings.notifications.agentSound.title": "Agentafslutningslyd", "settings.notifications.agentSound.description": "Lyd ved agentafslutning", @@ -1243,6 +1245,8 @@ export const dict = { "settings.notifications.errorSound.description": "Lyd ved fejl", "settings.notifications.sound.default": "Standard", "settings.notifications.sound.none": "Ingen", + "settings.notifications.sound.system": "System", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Delingstilstand", "settings.experimental.share.description": "Adfærd for sessionsdeling", "settings.experimental.share.manual": "Manuel", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 346bf456ba7..5da4e268dfa 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1255,6 +1255,9 @@ export const dict = { "settings.notifications.permissions.description": "Benachrichtigung bei Berechtigungsanfragen anzeigen", "settings.notifications.errors.title": "Fehler", "settings.notifications.errors.description": "Benachrichtigung bei Fehlern anzeigen", + "settings.notifications.playWhenFocused.title": "Sounds bei Fokus abspielen", + "settings.notifications.playWhenFocused.description": + "Sound-Benachrichtigungen abspielen, auch wenn das VS Code-Fenster fokussiert ist", "settings.notifications.sounds": "Töne", "settings.notifications.agentSound.title": "Agent-Abschlusston", "settings.notifications.agentSound.description": "Ton bei Agent-Abschluss abspielen", @@ -1264,6 +1267,8 @@ export const dict = { "settings.notifications.errorSound.description": "Ton bei Fehlern abspielen", "settings.notifications.sound.default": "Standard", "settings.notifications.sound.none": "Kein", + "settings.notifications.sound.system": "System", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Freigabemodus", "settings.experimental.share.description": "Verhalten der Sitzungsfreigabe", "settings.experimental.share.manual": "Manuell", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 159e3634d83..ee1b8c3001a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1220,6 +1220,9 @@ export const dict = { "settings.notifications.permissions.description": "Show notification on permission requests", "settings.notifications.errors.title": "Errors", "settings.notifications.errors.description": "Show notification on errors", + "settings.notifications.playWhenFocused.title": "Play Sounds When Focused", + "settings.notifications.playWhenFocused.description": + "Allow sound notifications to play even when VS Code window is focused", "settings.notifications.sounds": "Sounds", "settings.notifications.agentSound.title": "Agent Completion Sound", "settings.notifications.agentSound.description": "Sound to play when agent completes", @@ -1229,6 +1232,8 @@ export const dict = { "settings.notifications.errorSound.description": "Sound to play on errors", "settings.notifications.sound.default": "Default", "settings.notifications.sound.none": "None", + "settings.notifications.sound.system": "System", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Share Mode", "settings.experimental.share.description": "How session sharing behaves", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 6d339c64938..e1fb8fa6e35 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1247,6 +1247,9 @@ export const dict = { "settings.notifications.permissions.description": "Mostrar notificación en solicitudes de permiso", "settings.notifications.errors.title": "Errores", "settings.notifications.errors.description": "Mostrar notificación en errores", + "settings.notifications.playWhenFocused.title": "Reproducir sonidos cuando está enfocado", + "settings.notifications.playWhenFocused.description": + "Permitir notificaciones de sonido aun cuando la ventana de VS Code esté enfocada", "settings.notifications.sounds": "Sonidos", "settings.notifications.agentSound.title": "Sonido de finalización del agente", "settings.notifications.agentSound.description": "Sonido a reproducir cuando el agente finaliza", @@ -1256,6 +1259,8 @@ export const dict = { "settings.notifications.errorSound.description": "Sonido a reproducir en errores", "settings.notifications.sound.default": "Predeterminado", "settings.notifications.sound.none": "Ninguno", + "settings.notifications.sound.system": "Sistema", + "settings.notifications.testSound": "Prueba", "settings.experimental.share.title": "Modo de compartir", "settings.experimental.share.description": "Comportamiento de compartir sesión", "settings.experimental.share.manual": "Manual", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index bfc477ed721..9591c9d8333 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1259,6 +1259,9 @@ export const dict = { "settings.notifications.permissions.description": "Afficher une notification lors des demandes d'autorisation", "settings.notifications.errors.title": "Erreurs", "settings.notifications.errors.description": "Afficher une notification en cas d'erreur", + "settings.notifications.playWhenFocused.title": "Jouer les sons quand VS Code est focusé", + "settings.notifications.playWhenFocused.description": + "Permettre les notifications sonores même quand la fenêtre VS Code est focusée", "settings.notifications.sounds": "Sons", "settings.notifications.agentSound.title": "Son d'achèvement de l'agent", "settings.notifications.agentSound.description": "Son à jouer lorsque l'agent termine", @@ -1268,6 +1271,8 @@ export const dict = { "settings.notifications.errorSound.description": "Son à jouer en cas d'erreur", "settings.notifications.sound.default": "Par défaut", "settings.notifications.sound.none": "Aucun", + "settings.notifications.sound.system": "Système", + "settings.notifications.testSound": "Tester", "settings.experimental.share.title": "Mode de partage", "settings.experimental.share.description": "Comportement du partage de session", "settings.experimental.share.manual": "Manuel", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/it.ts b/packages/kilo-vscode/webview-ui/src/i18n/it.ts index 3ce53bc55d3..873aa4ac64f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/it.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/it.ts @@ -1087,8 +1087,13 @@ export const dict = { "settings.notifications.permSound.description": "Suono da riprodurre per le richieste di autorizzazione", "settings.notifications.errorSound.title": "Suono errore", "settings.notifications.errorSound.description": "Suono da riprodurre per gli errori", + "settings.notifications.playWhenFocused.title": "Riproduci suoni quando è in focus", + "settings.notifications.playWhenFocused.description": + "Consenti notifiche audio anche quando la finestra di VS Code è in primo piano", "settings.notifications.sound.default": "Predefinito", "settings.notifications.sound.none": "Nessuno", + "settings.notifications.sound.system": "Sistema", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Modalità condivisione", "settings.experimental.share.description": "Come si comporta la condivisione sessione", "settings.experimental.share.manual": "Manuale", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index 3d451e9901b..4c4e47f5bb7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1229,6 +1229,9 @@ export const dict = { "settings.notifications.permissions.description": "権限リクエスト時に通知を表示", "settings.notifications.errors.title": "エラー", "settings.notifications.errors.description": "エラー発生時に通知を表示", + "settings.notifications.playWhenFocused.title": "フォーカス時にサウンドを再生", + "settings.notifications.playWhenFocused.description": + "VS Codeウィンドウにフォーカスがある場合でもサウンド通知を再生できるようにする", "settings.notifications.sounds": "サウンド", "settings.notifications.agentSound.title": "エージェント完了サウンド", "settings.notifications.agentSound.description": "エージェント完了時に再生するサウンド", @@ -1238,6 +1241,8 @@ export const dict = { "settings.notifications.errorSound.description": "エラー発生時に再生するサウンド", "settings.notifications.sound.default": "デフォルト", "settings.notifications.sound.none": "なし", + "settings.notifications.sound.system": "システム", + "settings.notifications.testSound": "テスト", "settings.experimental.share.title": "共有モード", "settings.experimental.share.description": "セッション共有の動作", "settings.experimental.share.manual": "手動", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 4dacfcf2725..8fff5c80870 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1223,6 +1223,8 @@ export const dict = { "settings.notifications.permissions.description": "권한 요청 시 알림 표시", "settings.notifications.errors.title": "오류", "settings.notifications.errors.description": "오류 발생 시 알림 표시", + "settings.notifications.playWhenFocused.title": "포커스 시 소리 재생", + "settings.notifications.playWhenFocused.description": "VS Code 창이 포커스되어 있어도 소리 알림 재생", "settings.notifications.sounds": "소리", "settings.notifications.agentSound.title": "에이전트 완료 소리", "settings.notifications.agentSound.description": "에이전트 완료 시 재생할 소리", @@ -1232,6 +1234,8 @@ export const dict = { "settings.notifications.errorSound.description": "오류 발생 시 재생할 소리", "settings.notifications.sound.default": "기본값", "settings.notifications.sound.none": "없음", + "settings.notifications.sound.system": "시스템", + "settings.notifications.testSound": "테스트 소리", "settings.experimental.share.title": "공유 모드", "settings.experimental.share.description": "세션 공유 동작 방식", "settings.experimental.share.manual": "수동", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 0123096dde9..c5a20f6b0f3 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1235,6 +1235,9 @@ export const dict = { "settings.notifications.permissions.description": "Toon melding bij toestemmingsverzoeken", "settings.notifications.errors.title": "Fouten", "settings.notifications.errors.description": "Toon melding bij fouten", + "settings.notifications.playWhenFocused.title": "Speel geluid bij focus", + "settings.notifications.playWhenFocused.description": + "Sta geluidsmeldingen toe zelfs als VS Code-venster focus heeft", "settings.notifications.sounds": "Geluiden", "settings.notifications.agentSound.title": "Agent Voltooiingsgeluid", "settings.notifications.agentSound.description": "Geluid om af te spelen wanneer agent voltooit", @@ -1244,6 +1247,8 @@ export const dict = { "settings.notifications.errorSound.description": "Geluid om af te spelen bij fouten", "settings.notifications.sound.default": "Standaard", "settings.notifications.sound.none": "Geen", + "settings.notifications.sound.system": "Systeem", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Deelmodus", "settings.experimental.share.description": "Hoe sessiedelen zich gedraagt", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index b6d40dff990..ae5a9ce64f6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1200,6 +1200,8 @@ export const dict = { "settings.notifications.permissions.description": "Vis varsling ved tillatelsesforespørsler", "settings.notifications.errors.title": "Feil", "settings.notifications.errors.description": "Vis varsling ved feil", + "settings.notifications.playWhenFocused.title": "Spill lyd ved fokus", + "settings.notifications.playWhenFocused.description": "Tillat lydvarsler selv om VS Code-vinduet er i fokus", "settings.notifications.sounds": "Lyder", "settings.notifications.agentSound.title": "Agentfullføringslyd", "settings.notifications.agentSound.description": "Lyd ved agentfullføring", @@ -1209,6 +1211,8 @@ export const dict = { "settings.notifications.errorSound.description": "Lyd ved feil", "settings.notifications.sound.default": "Standard", "settings.notifications.sound.none": "Ingen", + "settings.notifications.sound.system": "System", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Delingsmodus", "settings.experimental.share.description": "Oppførsel for sesjonsdeling", "settings.experimental.share.manual": "Manuell", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 0baa8fd6897..d1cf6eeba5c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1199,6 +1199,9 @@ export const dict = { "settings.notifications.permissions.description": "Pokaż powiadomienie przy żądaniach uprawnień", "settings.notifications.errors.title": "Błędy", "settings.notifications.errors.description": "Pokaż powiadomienie przy błędach", + "settings.notifications.playWhenFocused.title": "Odtwarzaj dźwięki przy fokusu", + "settings.notifications.playWhenFocused.description": + "Pozwól na dźwięki powiadomień, nawet gdy okno VS Code jest w fokusu", "settings.notifications.sounds": "Dźwięki", "settings.notifications.agentSound.title": "Dźwięk zakończenia agenta", "settings.notifications.agentSound.description": "Dźwięk odtwarzany po zakończeniu agenta", @@ -1208,6 +1211,8 @@ export const dict = { "settings.notifications.errorSound.description": "Dźwięk odtwarzany przy błędach", "settings.notifications.sound.default": "Domyślny", "settings.notifications.sound.none": "Brak", + "settings.notifications.sound.system": "System", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Tryb udostępniania", "settings.experimental.share.description": "Zachowanie udostępniania sesji", "settings.experimental.share.manual": "Ręczny", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 26f857dc8f3..8d4ffb239d6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1237,6 +1237,9 @@ export const dict = { "settings.notifications.permissions.description": "Показать уведомление при запросах разрешений", "settings.notifications.errors.title": "Ошибки", "settings.notifications.errors.description": "Показать уведомление при ошибках", + "settings.notifications.playWhenFocused.title": "Воспроизводить звуки при фокусе", + "settings.notifications.playWhenFocused.description": + "Разрешить звуковые уведомления, даже когда окно VS Code находится в фокусе", "settings.notifications.sounds": "Звуки", "settings.notifications.agentSound.title": "Звук завершения агента", "settings.notifications.agentSound.description": "Звук при завершении агента", @@ -1246,6 +1249,8 @@ export const dict = { "settings.notifications.errorSound.description": "Звук при ошибках", "settings.notifications.sound.default": "По умолчанию", "settings.notifications.sound.none": "Нет", + "settings.notifications.sound.system": "Система", + "settings.notifications.testSound": "Тест", "settings.experimental.share.title": "Режим обмена", "settings.experimental.share.description": "Поведение обмена сессиями", "settings.experimental.share.manual": "Вручную", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 919515ba1d0..697119f2d87 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1220,6 +1220,8 @@ export const dict = { "settings.notifications.permissions.description": "แสดงการแจ้งเตือนเมื่อมีคำขออนุญาต", "settings.notifications.errors.title": "ข้อผิดพลาด", "settings.notifications.errors.description": "แสดงการแจ้งเตือนเมื่อเกิดข้อผิดพลาด", + "settings.notifications.playWhenFocused.title": "เล่นเสียงเมื่อโฟกัส", + "settings.notifications.playWhenFocused.description": "อนุญาตให้แจ้งเตือนด้วยเสียงแม้ว่าหน้าต่าง VS Code อยู่ในโฟกัส", "settings.notifications.sounds": "เสียง", "settings.notifications.agentSound.title": "เสียงเอเจนต์เสร็จสิ้น", "settings.notifications.agentSound.description": "เสียงเมื่อเอเจนต์ทำงานเสร็จ", @@ -1229,6 +1231,8 @@ export const dict = { "settings.notifications.errorSound.description": "เสียงเมื่อเกิดข้อผิดพลาด", "settings.notifications.sound.default": "ค่าเริ่มต้น", "settings.notifications.sound.none": "ไม่มี", + "settings.notifications.sound.system": "ระบบ", + "settings.notifications.testSound": "ทดสอบ", "settings.experimental.share.title": "โหมดแชร์", "settings.experimental.share.description": "พฤติกรรมการแชร์เซสชัน", "settings.experimental.share.manual": "ด้วยตนเอง", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 30b79a52176..236db1d19a3 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1228,6 +1228,8 @@ export const dict = { "settings.notifications.permissions.description": "İzin isteklerinde bildirim göster", "settings.notifications.errors.title": "Hatalar", "settings.notifications.errors.description": "Hata oluştuğunda bildirim göster", + "settings.notifications.playWhenFocused.title": "Odaklandığında Sesleri Çal", + "settings.notifications.playWhenFocused.description": "VS Code penceresi odaklıyken bile ses bildirimlerine izin ver", "settings.notifications.sounds": "Sesler", "settings.notifications.agentSound.title": "Ajan Tamamlanma Sesi", "settings.notifications.agentSound.description": "Ajan tamamlandığında çalınacak ses", @@ -1237,6 +1239,8 @@ export const dict = { "settings.notifications.errorSound.description": "Hata oluştuğunda çalınacak ses", "settings.notifications.sound.default": "Varsayılan", "settings.notifications.sound.none": "Yok", + "settings.notifications.sound.system": "Sistem", + "settings.notifications.testSound": "Test", "settings.experimental.share.title": "Paylaşım Modu", "settings.experimental.share.description": "Oturum paylaşımının nasıl davranacağı", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts index 1e22d8a327b..a93ebefb4ba 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts @@ -1228,6 +1228,9 @@ export const dict = { "settings.notifications.permissions.description": "Показувати сповіщення при запитах дозволів", "settings.notifications.errors.title": "Помилки", "settings.notifications.errors.description": "Показувати сповіщення при виникненні помилок", + "settings.notifications.playWhenFocused.title": "Відтворювати звуки при фокусі", + "settings.notifications.playWhenFocused.description": + "Дозволяти звукові сповіщення, навіть коли вікно VS Code знаходиться на фокусі", "settings.notifications.sounds": "Звуки", "settings.notifications.agentSound.title": "Звук завершення агента", "settings.notifications.agentSound.description": "Звук, що відтворюється після завершення агента", @@ -1237,6 +1240,8 @@ export const dict = { "settings.notifications.errorSound.description": "Звук, що відтворюється при виникненні помилок", "settings.notifications.sound.default": "За замовчуванням", "settings.notifications.sound.none": "Немає", + "settings.notifications.sound.system": "Система", + "settings.notifications.testSound": "Тест", "settings.experimental.share.title": "Режим публікації", "settings.experimental.share.description": "Як поводиться публікація сесій", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 92c94ed9e0f..5c56abc3c30 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1202,6 +1202,8 @@ export const dict = { "settings.notifications.permissions.description": "权限请求时显示通知", "settings.notifications.errors.title": "错误", "settings.notifications.errors.description": "发生错误时显示通知", + "settings.notifications.playWhenFocused.title": "聚焦时播放声音", + "settings.notifications.playWhenFocused.description": "即使 VS Code 窗口处于焦点状态也播放声音通知", "settings.notifications.sounds": "声音", "settings.notifications.agentSound.title": "智能体完成提示音", "settings.notifications.agentSound.description": "智能体完成时播放的声音", @@ -1211,6 +1213,8 @@ export const dict = { "settings.notifications.errorSound.description": "发生错误时播放的声音", "settings.notifications.sound.default": "默认", "settings.notifications.sound.none": "无", + "settings.notifications.sound.system": "系统", + "settings.notifications.testSound": "测试", "settings.experimental.share.title": "分享模式", "settings.experimental.share.description": "会话分享行为", "settings.experimental.share.manual": "手动", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 5214459dd9f..136162a9bfe 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1170,6 +1170,8 @@ export const dict = { "settings.notifications.permissions.description": "權限請求時顯示通知", "settings.notifications.errors.title": "錯誤", "settings.notifications.errors.description": "發生錯誤時顯示通知", + "settings.notifications.playWhenFocused.title": "聚焦時播放聲音", + "settings.notifications.playWhenFocused.description": "即使 VS Code 視窗聚焦也播放聲音通知", "settings.notifications.sounds": "聲音", "settings.notifications.agentSound.title": "Agent 完成提示音", "settings.notifications.agentSound.description": "Agent 完成時播放的聲音", @@ -1179,6 +1181,8 @@ export const dict = { "settings.notifications.errorSound.description": "發生錯誤時播放的聲音", "settings.notifications.sound.default": "預設", "settings.notifications.sound.none": "無", + "settings.notifications.sound.system": "系統", + "settings.notifications.testSound": "測試", "settings.experimental.share.title": "分享模式", "settings.experimental.share.description": "工作階段分享行為", "settings.experimental.share.manual": "手動", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts index 6d4b5d9a0b4..de19a34a015 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts @@ -482,6 +482,7 @@ export interface NotificationSettingsLoadedMessage { notifyAgent: boolean notifyPermissions: boolean notifyErrors: boolean + playWhenFocused: boolean soundAgent: string soundPermissions: string soundErrors: string diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts index f0c0f315c0a..e7c9d2648e5 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts @@ -433,6 +433,11 @@ export interface RequestNotificationSettingsMessage { type: "requestNotificationSettings" } +export interface TestNotificationMessage { + type: "testNotification" + settingType: "agent" | "permissions" | "errors" +} + export interface ResetAllSettingsRequest { type: "resetAllSettings" } @@ -1133,6 +1138,7 @@ export type WebviewMessage = | UpdateConfigMessage | OpenSettingsTabRequest | RequestNotificationSettingsMessage + | TestNotificationMessage | ResetAllSettingsRequest | SettingsTabChangedMessage | SyncSessionRequest