feat(webchat): add server-side dictation (#76021)

Summary:
- This PR adds WebChat server-side dictation through a new authenticated `chat.transcribeAudio` Gateway RPC, MediaRecorder composer controls, docs/changelog updates, and focused gateway/UI tests.
- Reproducibility: yes. Current main reproduces the missing feature by inspection: the Gateway method list, write scopes, docs, and WebChat voice-control test have no `chat.transcribeAudio` server-dictation path.

ClawSweeper fixups:
- Included follow-up commit: feat(webchat): add server-side dictation
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7602…

Validation:
- ClawSweeper review passed for head 850571380a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 850571380a
Review: https://github.com/openclaw/openclaw/pull/76021#issuecomment-4363514226

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
This commit is contained in:
Peter Steinberger
2026-05-03 00:09:23 +01:00
committed by GitHub
parent 15bbf4f2f3
commit 68359cacbf
23 changed files with 847 additions and 23 deletions

View File

@@ -427,16 +427,14 @@ function isNpmExecPath(value: string): boolean {
return /^npm(?:-cli)?(?:\.(?:c?js|cmd|exe))?$/.test(basename(value).toLowerCase());
}
export function resolveNpmCommandInvocation(
params: {
npmExecPath?: string;
nodeExecPath?: string;
platform?: NodeJS.Platform;
} = {},
): { command: string; args: string[] } {
const npmExecPath = params.npmExecPath ?? process.env.npm_execpath;
const nodeExecPath = params.nodeExecPath ?? process.execPath;
const npmCommand = (params.platform ?? process.platform) === "win32" ? "npm.cmd" : "npm";
export function resolveNpmCommandInvocation(params?: {
npmExecPath?: string;
nodeExecPath?: string;
platform?: NodeJS.Platform;
}): { command: string; args: string[] } {
const npmExecPath = params === undefined ? process.env.npm_execpath : params.npmExecPath;
const nodeExecPath = params?.nodeExecPath ?? process.execPath;
const npmCommand = (params?.platform ?? process.platform) === "win32" ? "npm.cmd" : "npm";
if (typeof npmExecPath === "string" && npmExecPath.length > 0 && isNpmExecPath(npmExecPath)) {
return { command: nodeExecPath, args: [npmExecPath] };