惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园_首页
量子位
V
Visual Studio Blog
博客园 - Franky
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 【当耐特】
罗磊的独立博客
小众软件
小众软件
V
V2EX
GbyAI
GbyAI
B
Blog RSS Feed
博客园 - 三生石上(FineUI控件)
大猫的无限游戏
大猫的无限游戏
有赞技术团队
有赞技术团队
月光博客
月光博客
Recent Announcements
Recent Announcements
雷峰网
雷峰网
F
Fortinet All Blogs
M
MIT News - Artificial intelligence

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix(webchat): forward trustedLocalMedia on accumulated bl...
leno23 · 2026-05-17 · via Recent Commits to openclaw:main

@@ -62,52 +62,62 @@ async function main() {

6262

},

6363

};

646465-

const blockText = "WebChat block replies should synthesize audio for auto TTS.";

65+

const accumulatedBlockText =

66+

"WebChat streams block text; dispatch synthesizes one TTS tail with kind final.";

6667

const blockResult = await maybeApplyTtsToPayload({

67-

payload: { text: blockText },

68+

payload: { text: accumulatedBlockText },

6869

cfg,

6970

channel: "webchat",

7071

kind: "block",

7172

});

7273

console.log("maybeApplyTtsToPayload(kind=block).mediaUrl =", blockResult.mediaUrl ?? "(none)");

73-

console.log(

74-

"maybeApplyTtsToPayload(kind=block).trustedLocalMedia =",

75-

blockResult.trustedLocalMedia ?? false,

76-

);

777478-

const toolResult = await maybeApplyTtsToPayload({

79-

payload: { text: "Intermediate tool output should not be spoken." },

75+

const tailResult = await maybeApplyTtsToPayload({

76+

payload: { text: accumulatedBlockText },

8077

cfg,

8178

channel: "webchat",

82-

kind: "tool",

79+

kind: "final",

8380

});

84-

console.log("maybeApplyTtsToPayload(kind=tool).mediaUrl =", toolResult.mediaUrl ?? "(none)");

81+

console.log("maybeApplyTtsToPayload(kind=final).mediaUrl =", tailResult.mediaUrl ?? "(none)");

82+

console.log(

83+

"maybeApplyTtsToPayload(kind=final).trustedLocalMedia =",

84+

tailResult.trustedLocalMedia ?? false,

85+

);

858686-

const mediaPath = blockResult.mediaUrl;

87+

const mediaPath = tailResult.mediaUrl;

8788

if (!mediaPath || !fs.existsSync(mediaPath)) {

88-

throw new Error("expected block TTS to write a local media file");

89+

throw new Error("expected final-mode tail TTS to write a local media file");

8990

}

90-

const localRoots = [path.dirname(mediaPath)];

91-

const trustedBlocks = await buildWebchatAudioContentBlocksFromReplyPayloads(

92-

[{ mediaUrl: mediaPath, trustedLocalMedia: true }],

93-

{ localRoots },

91+92+

const ttsOnlyPayload = {

93+

mediaUrl: tailResult.mediaUrl,

94+

audioAsVoice: tailResult.audioAsVoice,

95+

spokenText: accumulatedBlockText,

96+

trustedLocalMedia: tailResult.trustedLocalMedia,

97+

};

98+

console.log(

99+

"dispatch ttsOnlyPayload.trustedLocalMedia =",

100+

ttsOnlyPayload.trustedLocalMedia ?? false,

94101

);

102+103+

const localRoots = [path.dirname(mediaPath)];

104+

const trustedBlocks = await buildWebchatAudioContentBlocksFromReplyPayloads([ttsOnlyPayload], {

105+

localRoots,

106+

});

95107

const untrustedBlocks = await buildWebchatAudioContentBlocksFromReplyPayloads(

96108

[{ mediaUrl: mediaPath }],

97109

{ localRoots },

98110

);

99111

console.log(

100-

"buildWebchatAudioContentBlocksFromReplyPayloads(trustedLocalMedia=true).length =",

112+

"buildWebchatAudioContentBlocksFromReplyPayloads(ttsOnlyPayload).length =",

101113

trustedBlocks.length,

102114

);

103115

console.log(

104-

"buildWebchatAudioContentBlocksFromReplyPayloads(trustedLocalMedia missing).length =",

116+

"buildWebchatAudioContentBlocksFromReplyPayloads(untrusted).length =",

105117

untrustedBlocks.length,

106118

);

107119108-

if (blockResult.mediaUrl) {

109-

fs.rmSync(path.dirname(blockResult.mediaUrl), { recursive: true, force: true });

110-

}

120+

fs.rmSync(path.dirname(mediaPath), { recursive: true, force: true });

111121

try {

112122

fs.unlinkSync(prefsPath);

113123

} catch {