






















@@ -1,6 +1,8 @@
11import { EmbeddedBlockChunker } from "openclaw/plugin-sdk/agent-runtime";
22import {
3+createChannelProgressDraftGate,
34formatChannelProgressDraftText,
5+isChannelProgressDraftWorkToolName,
46resolveChannelProgressDraftMaxLines,
57resolveChannelStreamingBlockEnabled,
68resolveChannelStreamingPreviewToolProgress,
@@ -70,7 +72,6 @@ export function createDiscordDraftPreviewController(params: {
7072let hasStreamedMessage = false;
7173let finalizedViaPreviewMessage = false;
7274let finalDeliveryHandled = false;
73-let progressDraftStarted = false;
7475const previewToolProgressEnabled =
7576Boolean(draftStream) && resolveChannelStreamingPreviewToolProgress(params.discordConfig);
7677const suppressDefaultToolProgressMessages =
@@ -83,6 +84,32 @@ export function createDiscordDraftPreviewController(params: {
8384let previewToolProgressLines: string[] = [];
8485const progressSeed = `${params.accountId}:${params.deliverChannelId}`;
858687+const renderProgressDraft = async (options?: { flush?: boolean }) => {
88+if (!draftStream || discordStreamMode !== "progress") {
89+return;
90+}
91+const previewText = formatChannelProgressDraftText({
92+entry: params.discordConfig,
93+lines: previewToolProgressLines,
94+seed: progressSeed,
95+});
96+if (!previewText || previewText === lastPartialText) {
97+return;
98+}
99+lastPartialText = previewText;
100+draftText = previewText;
101+hasStreamedMessage = true;
102+draftChunker?.reset();
103+draftStream.update(previewText);
104+if (options?.flush) {
105+await draftStream.flush();
106+}
107+};
108+109+const progressDraftGate = createChannelProgressDraftGate({
110+onStart: () => renderProgressDraft({ flush: true }),
111+});
112+86113const resetProgressState = () => {
87114lastPartialText = "";
88115draftText = "";
@@ -106,6 +133,9 @@ export function createDiscordDraftPreviewController(params: {
106133get isProgressMode() {
107134return discordStreamMode === "progress";
108135},
136+get hasProgressDraftStarted() {
137+return progressDraftGate.hasStarted;
138+},
109139get finalizedViaPreviewMessage() {
110140return finalizedViaPreviewMessage;
111141},
@@ -120,50 +150,55 @@ export function createDiscordDraftPreviewController(params: {
120150if (!draftStream || discordStreamMode !== "progress") {
121151return;
122152}
123-if (progressDraftStarted) {
124-return;
125-}
126-const previewText = formatChannelProgressDraftText({
127-entry: params.discordConfig,
128-lines: [],
129-seed: progressSeed,
130-});
131-if (!previewText || previewText === lastPartialText) {
153+await progressDraftGate.startNow();
154+},
155+async pushToolProgress(line?: string, options?: { toolName?: string }) {
156+if (!draftStream) {
132157return;
133158}
134-progressDraftStarted = true;
135-lastPartialText = previewText;
136-draftText = previewText;
137-hasStreamedMessage = true;
138-draftChunker?.reset();
139-draftStream.update(previewText);
140-await draftStream.flush();
141-},
142-pushToolProgress(line?: string) {
143-if (!draftStream || !previewToolProgressEnabled || previewToolProgressSuppressed) {
159+if (
160+options?.toolName !== undefined &&
161+!isChannelProgressDraftWorkToolName(options.toolName)
162+) {
144163return;
145164}
146165const normalized = line?.replace(/\s+/g, " ").trim();
147-if (!normalized) {
166+if (discordStreamMode !== "progress") {
167+if (!previewToolProgressEnabled || previewToolProgressSuppressed || !normalized) {
168+return;
169+}
170+const previous = previewToolProgressLines.at(-1);
171+if (previous === normalized) {
172+return;
173+}
174+previewToolProgressLines = [...previewToolProgressLines, normalized].slice(
175+-resolveChannelProgressDraftMaxLines(params.discordConfig),
176+);
177+const previewText = formatChannelProgressDraftText({
178+entry: params.discordConfig,
179+lines: previewToolProgressLines,
180+seed: progressSeed,
181+});
182+lastPartialText = previewText;
183+draftText = previewText;
184+hasStreamedMessage = true;
185+draftChunker?.reset();
186+draftStream.update(previewText);
148187return;
149188}
150-const previous = previewToolProgressLines.at(-1);
151-if (previous === normalized) {
152-return;
189+if (previewToolProgressEnabled && !previewToolProgressSuppressed && normalized) {
190+const previous = previewToolProgressLines.at(-1);
191+if (previous !== normalized) {
192+previewToolProgressLines = [...previewToolProgressLines, normalized].slice(
193+-resolveChannelProgressDraftMaxLines(params.discordConfig),
194+);
195+}
196+}
197+const alreadyStarted = progressDraftGate.hasStarted;
198+await progressDraftGate.noteWork();
199+if (alreadyStarted && progressDraftGate.hasStarted) {
200+await renderProgressDraft();
153201}
154-previewToolProgressLines = [...previewToolProgressLines, normalized].slice(
155--resolveChannelProgressDraftMaxLines(params.discordConfig),
156-);
157-const previewText = formatChannelProgressDraftText({
158-entry: params.discordConfig,
159-lines: previewToolProgressLines,
160-seed: progressSeed,
161-});
162-lastPartialText = previewText;
163-draftText = previewText;
164-hasStreamedMessage = true;
165-draftChunker?.reset();
166-draftStream.update(previewText);
167202},
168203resolvePreviewFinalText(text?: string) {
169204if (typeof text !== "string") {
@@ -281,6 +316,7 @@ export function createDiscordDraftPreviewController(params: {
281316},
282317async cleanup() {
283318try {
319+progressDraftGate.cancel();
284320if (!finalDeliveryHandled) {
285321await draftStream?.discardPending();
286322}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。