

















@@ -1,8 +1,10 @@
11import crypto from "node:crypto";
2+import { SILENT_REPLY_TOKEN } from "../../auto-reply/tokens.js";
23import type { OpenClawConfig } from "../../config/types.openclaw.js";
34import { clearAgentRunContext, registerAgentRunContext } from "../../infra/agent-events.js";
45import { formatErrorMessage } from "../../infra/errors.js";
56import { createSubsystemLogger } from "../../logging/subsystem.js";
7+import { deriveSessionChatTypeFromKey } from "../../sessions/session-chat-type-shared.js";
68import {
79completeTaskRunByRunId,
810createRunningTaskRun,
@@ -222,8 +224,18 @@ function failMediaGenerationTaskRun(params: {
222224function buildMediaGenerationReplyInstruction(params: {
223225status: "ok" | "error";
224226completionLabel: string;
227+requiresMessageToolDelivery: boolean;
225228}) {
226229if (params.status === "ok") {
230+if (params.requiresMessageToolDelivery) {
231+return [
232+`The ${params.completionLabel} is ready for the original channel/group chat.`,
233+"This route requires message-tool delivery: the user will NOT see your normal assistant final reply.",
234+'Call the message tool with action="send" to the original/current chat, put a short caption in the message, and attach the generated media paths from the result.',
235+`After the message tool succeeds, reply only ${SILENT_REPLY_TOKEN}.`,
236+"Do not put MEDIA: lines only in your final answer; that final answer is private in this chat.",
237+].join(" ");
238+}
227239return `Tell the user the ${params.completionLabel} is ready. If visible source delivery requires the message tool, send it there with the generated media attached.`;
228240}
229241return [
@@ -233,6 +245,39 @@ function buildMediaGenerationReplyInstruction(params: {
233245].join(" ");
234246}
235247248+function inferMediaGenerationCompletionChatType(
249+handle: MediaGenerationTaskHandle,
250+): "direct" | "group" | "channel" | "unknown" {
251+const sessionKeyChatType = deriveSessionChatTypeFromKey(handle.requesterSessionKey);
252+if (sessionKeyChatType !== "unknown") {
253+return sessionKeyChatType;
254+}
255+const to = handle.requesterOrigin?.to?.trim().toLowerCase();
256+if (to?.startsWith("group:")) {
257+return "group";
258+}
259+if (to?.startsWith("channel:")) {
260+return "channel";
261+}
262+if (to?.startsWith("dm:") || to?.startsWith("direct:")) {
263+return "direct";
264+}
265+return "unknown";
266+}
267+268+function mediaGenerationCompletionRequiresMessageToolDelivery(params: {
269+config?: OpenClawConfig;
270+handle: MediaGenerationTaskHandle;
271+}): boolean {
272+const chatType = inferMediaGenerationCompletionChatType(params.handle);
273+if (chatType === "group" || chatType === "channel") {
274+const configuredMode =
275+params.config?.messages?.groupChat?.visibleReplies ?? params.config?.messages?.visibleReplies;
276+return configuredMode !== "automatic";
277+}
278+return params.config?.messages?.visibleReplies === "message_tool";
279+}
280+236281async function wakeMediaGenerationTaskCompletion(params: {
237282config?: OpenClawConfig;
238283handle: MediaGenerationTaskHandle | null;
@@ -266,6 +311,10 @@ async function wakeMediaGenerationTaskCompletion(params: {
266311replyInstruction: buildMediaGenerationReplyInstruction({
267312status: params.status,
268313completionLabel: params.completionLabel,
314+requiresMessageToolDelivery: mediaGenerationCompletionRequiresMessageToolDelivery({
315+config: params.config,
316+handle: params.handle,
317+}),
269318}),
270319},
271320];
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。