Skip to content

fix(windows): use -EncodedCommand so PowerShell playback args never contain spaces - #101

Merged
mohak34 merged 1 commit into
mohak34:mainfrom
liaoxiaoxuan:fix/windows-sound-encodedcommand
Sep 16, 2026
Merged

mohak34 merged 1 commit into
mohak34:mainfrom
liaoxiaoxuan:fix/windows-sound-encodedcommand

Conversation

@liaoxiaoxuan

Copy link
Copy Markdown
Contributor

Problem

On Windows, sounds never play — desktop notifications appear fine, but audio silently fails. Affected versions: 0.2.8 (npm latest) and current main.

Note: this repository restricts issue creation for non-contributors, so I'm reporting via this PR.

Root cause

playOnWindows() passes two arguments containing spaces to powershell -Command via child_process.spawn():

const script = `& { (New-Object Media.SoundPlayer $args[0]).PlaySync() }`
await runCommand("powershell", ["-NoProfile", "-NonInteractive", "-Command", script, soundPath])

After Windows command-line conversion, the quoting is lost. powershell.exe -Command concatenates everything after it into one script string, producing:

(New-Object Media.SoundPlayer $args[0]).PlaySync() D:\opencode-sounds\complete.wav
Unexpected token 'D:\opencode-sounds\complete.wav' in expression or statement.
    + CategoryInfo          : ParserError

The child exits 1, runCommand() rejects, and playSound()'s catch block swallows the error — so notifications show but nothing is ever heard.

Minimal repro (fails identically under Bun 1.4.0 and Node.js):

import { spawnSync } from "child_process";
const r = spawnSync("powershell", [
  "-NoProfile", "-NonInteractive", "-Command",
  "(New-Object Media.SoundPlayer $args[0]).PlaySync()",
  "D:/opencode-sounds/complete.wav",
], { encoding: "utf8" });
console.log(r.status); // 1 — ParserError above in r.stderr

Running the same command manually from an interactive shell works (the outer shell quotes args correctly), which is why this only breaks when spawned programmatically.

Fix

Use -EncodedCommand so every argument handed to spawn() is space-free:

const script = `(New-Object Media.SoundPlayer '${soundPath.replace(/'/g, "''")}').PlaySync()`
const encoded = Buffer.from(script, "utf16le").toString("base64")
await runCommand("powershell", ["-NoProfile", "-NonInteractive", "-EncodedCommand", encoded])
  • -EncodedCommand expects UTF-16LE base64 per PowerShell spec
  • Single quotes in the path are escaped PowerShell-style ('')
  • Keeps -NoProfile / -NonInteractive

Verification

Environment: Windows 11, OpenCode 1.18.21 (Bun runtime), valid PCM WAV files.

  • Before: spawn repro exits 1 with the ParserError shown above; no sound
  • After: same repro exits 0 with audible playback (tested under both Bun 1.4.0 and Node.js)
  • Locally patched dist/index.js with this change: notifications + sounds both work
  • bun run typecheck
  • bun test: 90 pass, 0 fail ✓

Secondary suggestion: consider logging a warning instead of silently swallowing errors in playSound()'s catch — this failure mode was hard to diagnose precisely because it was silent.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The fix is small, well-scoped to Windows playback, and the new PowerShell invocation correctly avoids the spawn-time -Command parsing failure described in the PR.

Pull request overview

This PR fixes Windows sound playback by changing the PowerShell invocation to use -EncodedCommand, avoiding argument/quoting issues that occur when spawning powershell -Command programmatically from Node.js/Bun. The change is localized to the Windows sound path in src/sound.ts and aligns with the root-cause described in the PR metadata.

Changes:

  • Build a PowerShell script that inlines the WAV path as a single-quoted string (escaping ' as '').
  • Base64-encode the script as UTF-16LE and execute it via powershell -EncodedCommand to ensure spawned args contain no spaces.
File summaries
File Description
src/sound.ts Updates Windows sound playback to run PowerShell via UTF-16LE base64 -EncodedCommand to prevent quoting/argument concatenation failures.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@mohak34
mohak34 merged commit 595d6f7 into mohak34:main Sep 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants