





















@@ -4,14 +4,18 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js";
44import { clearAgentRunContext, registerAgentRunContext } from "../../infra/agent-events.js";
55import { formatErrorMessage } from "../../infra/errors.js";
66import { createSubsystemLogger } from "../../logging/subsystem.js";
7+import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
78import {
89completeTaskRunByRunId,
910createRunningTaskRun,
1011failTaskRunByRunId,
1112recordTaskRunProgressByRunId,
1213} from "../../tasks/detached-task-runtime.js";
13-import type { DeliveryContext } from "../../utils/delivery-context.js";
14-import { INTERNAL_MESSAGE_CHANNEL } from "../../utils/message-channel.js";
14+import { normalizeDeliveryContext, type DeliveryContext } from "../../utils/delivery-context.js";
15+import {
16+INTERNAL_MESSAGE_CHANNEL,
17+isDeliverableMessageChannel,
18+} from "../../utils/message-channel.js";
1519import {
1620mediaUrlsFromGeneratedAttachments,
1721type AgentGeneratedAttachment,
@@ -447,7 +451,22 @@ async function wakeMediaGenerationTaskCompletion(params: {
447451bestEffortDeliver: true,
448452directIdempotencyKey: announceId,
449453});
450-if (!delivery.delivered && delivery.error) {
454+if (delivery.delivered) {
455+return;
456+}
457+if (params.status === "error") {
458+const delivered = await tryDeliverMediaGenerationFailureDirect({
459+config: params.config,
460+handle: params.handle,
461+toolName: params.toolName,
462+completionLabel: params.completionLabel,
463+result: params.result,
464+});
465+if (delivered) {
466+return;
467+}
468+}
469+if (delivery.error) {
451470log.error("Media generation completion wake failed; requester session was not woken", {
452471taskId: params.handle.taskId,
453472runId: params.handle.runId,
@@ -457,6 +476,50 @@ async function wakeMediaGenerationTaskCompletion(params: {
457476}
458477}
459478479+async function tryDeliverMediaGenerationFailureDirect(params: {
480+config?: OpenClawConfig;
481+handle: MediaGenerationTaskHandle;
482+toolName: string;
483+completionLabel: string;
484+result: string;
485+}): Promise<boolean> {
486+const origin = normalizeDeliveryContext(params.handle.requesterOrigin);
487+if (!origin?.channel || !origin.to || !isDeliverableMessageChannel(origin.channel)) {
488+return false;
489+}
490+const label = `${params.completionLabel[0]?.toUpperCase() ?? "M"}${params.completionLabel.slice(1)}`;
491+const agentId = resolveAgentIdFromSessionKey(params.handle.requesterSessionKey);
492+const idempotencyKey = `${params.toolName}:${params.handle.taskId}:error:direct`;
493+try {
494+const { sendMessage } = await import("../../tasks/task-registry-delivery-runtime.js");
495+await sendMessage({
496+cfg: params.config,
497+channel: origin.channel,
498+to: origin.to,
499+accountId: origin.accountId,
500+threadId: origin.threadId,
501+content: `${label} generation failed: ${params.result}`,
502+requesterSessionKey: params.handle.requesterSessionKey,
503+ agentId,
504+ idempotencyKey,
505+mirror: {
506+sessionKey: params.handle.requesterSessionKey,
507+ agentId,
508+ idempotencyKey,
509+},
510+});
511+return true;
512+} catch (error) {
513+log.warn("Direct media generation failure delivery failed; falling back to agent wake", {
514+taskId: params.handle.taskId,
515+runId: params.handle.runId,
516+toolName: params.toolName,
517+ error,
518+});
519+return false;
520+}
521+}
522+460523export function createMediaGenerationTaskLifecycle(params: {
461524toolName: string;
462525taskKind: string;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。