

























@@ -7,8 +7,9 @@ import {
77normalizeOptionalLowercaseString,
88normalizeOptionalString,
99} from "../../shared/string-coerce.js";
10+import { createTtsDirectiveTextStreamCleaner } from "../../tts/directives.js";
1011import { resolveStatusTtsSnapshot } from "../../tts/status-config.js";
11-import { resolveConfiguredTtsMode } from "../../tts/tts-config.js";
12+import { resolveConfiguredTtsMode, shouldCleanTtsDirectiveText } from "../../tts/tts-config.js";
1213import type { FinalizedMsgContext } from "../templating.js";
1314import type { ReplyPayload } from "../types.js";
1415import type { ReplyDispatchKind, ReplyDispatcher } from "./reply-dispatcher.types.js";
@@ -127,6 +128,9 @@ async function maybeApplyAcpTts(params: {
127128type AcpDispatchDeliveryState = {
128129startedReplyLifecycle: boolean;
129130accumulatedBlockText: string;
131+accumulatedVisibleBlockText: string;
132+accumulatedBlockTtsText: string;
133+cleanBlockTtsDirectiveText?: ReturnType<typeof createTtsDirectiveTextStreamCleaner>;
130134blockCount: number;
131135deliveredFinalReply: boolean;
132136deliveredVisibleText: boolean;
@@ -146,6 +150,8 @@ export type AcpDispatchDeliveryCoordinator = {
146150) => Promise<boolean>;
147151getBlockCount: () => number;
148152getAccumulatedBlockText: () => string;
153+getAccumulatedVisibleBlockText: () => string;
154+getAccumulatedBlockTtsText: () => string;
149155settleVisibleText: () => Promise<void>;
150156hasDeliveredFinalReply: () => boolean;
151157hasDeliveredVisibleText: () => boolean;
@@ -172,6 +178,15 @@ export function createAcpDispatchDeliveryCoordinator(params: {
172178const state: AcpDispatchDeliveryState = {
173179startedReplyLifecycle: false,
174180accumulatedBlockText: "",
181+accumulatedVisibleBlockText: "",
182+accumulatedBlockTtsText: "",
183+cleanBlockTtsDirectiveText: shouldCleanTtsDirectiveText({
184+cfg: params.cfg,
185+ttsAuto: params.sessionTtsAuto,
186+agentId: params.agentId,
187+})
188+ ? createTtsDirectiveTextStreamCleaner()
189+ : undefined,
175190blockCount: 0,
176191deliveredFinalReply: false,
177192deliveredVisibleText: false,
@@ -279,24 +294,45 @@ export function createAcpDispatchDeliveryCoordinator(params: {
279294payload: ReplyPayload,
280295meta?: AcpDispatchDeliveryMeta,
281296): Promise<boolean> => {
282-if (kind === "block" && normalizeOptionalString(payload.text)) {
297+let visiblePayload = payload;
298+const rawBlockText = kind === "block" ? normalizeOptionalString(payload.text) : undefined;
299+if (rawBlockText) {
300+const joinsBufferedTtsDirective =
301+state.cleanBlockTtsDirectiveText?.hasBufferedDirectiveText() === true;
283302if (state.accumulatedBlockText.length > 0) {
284303state.accumulatedBlockText += "\n";
285304}
286-state.accumulatedBlockText += payload.text;
305+state.accumulatedBlockText += rawBlockText;
306+if (state.accumulatedBlockTtsText.length > 0 && !joinsBufferedTtsDirective) {
307+state.accumulatedBlockTtsText += "\n";
308+}
309+state.accumulatedBlockTtsText += rawBlockText;
287310state.blockCount += 1;
311+312+if (state.cleanBlockTtsDirectiveText && !payload.isCompactionNotice) {
313+const text = state.cleanBlockTtsDirectiveText.push(rawBlockText);
314+visiblePayload = { ...payload, text: text.trim() ? text : undefined };
315+}
316+if (visiblePayload.text) {
317+if (state.accumulatedVisibleBlockText.length > 0) {
318+state.accumulatedVisibleBlockText += "\n";
319+}
320+state.accumulatedVisibleBlockText += visiblePayload.text;
321+}
288322}
289323290-if (hasOutboundReplyContent(payload, { trimText: true })) {
324+if (hasOutboundReplyContent(visiblePayload, { trimText: true })) {
291325await startReplyLifecycleOnce();
326+} else {
327+return false;
292328}
293329294330if (params.suppressUserDelivery) {
295331return false;
296332}
297333298334const ttsPayload = await maybeApplyAcpTts({
299- payload,
335+payload: visiblePayload,
300336cfg: params.cfg,
301337agentId: params.agentId,
302338channel: params.ttsChannel,
@@ -396,6 +432,8 @@ export function createAcpDispatchDeliveryCoordinator(params: {
396432 deliver,
397433getBlockCount: () => state.blockCount,
398434getAccumulatedBlockText: () => state.accumulatedBlockText,
435+getAccumulatedVisibleBlockText: () => state.accumulatedVisibleBlockText,
436+getAccumulatedBlockTtsText: () => state.accumulatedBlockTtsText,
399437settleVisibleText: settleDirectVisibleText,
400438hasDeliveredFinalReply: () => state.deliveredFinalReply,
401439hasDeliveredVisibleText: () => state.deliveredVisibleText,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。