





















@@ -116,12 +116,15 @@ function resolveMainSessionResumeBlockReason(messages: unknown[]): string | null
116116return null;
117117}
118118119-function buildResumeMessage(): string {
120-return (
119+function buildResumeMessage(pendingFinalDeliveryText?: string | null): string {
120+const base =
121121"[System] Your previous turn was interrupted by a gateway restart while " +
122122"OpenClaw was waiting on tool/model work. Continue from the existing " +
123-"transcript and finish the interrupted response."
124-);
123+"transcript and finish the interrupted response.";
124+if (pendingFinalDeliveryText) {
125+return `${base}\n\nNote: The interrupted final reply was captured: "${pendingFinalDeliveryText}"`;
126+}
127+return base;
125128}
126129127130async function markSessionFailed(params: {
@@ -140,6 +143,13 @@ async function markSessionFailed(params: {
140143entry.abortedLastRun = true;
141144entry.endedAt = Date.now();
142145entry.updatedAt = entry.endedAt;
146+entry.pendingFinalDelivery = undefined;
147+entry.pendingFinalDeliveryText = undefined;
148+entry.pendingFinalDeliveryCreatedAt = undefined;
149+entry.pendingFinalDeliveryLastAttemptAt = undefined;
150+entry.pendingFinalDeliveryAttemptCount = undefined;
151+entry.pendingFinalDeliveryLastError = undefined;
152+entry.pendingFinalDeliveryContext = undefined;
143153store[params.sessionKey] = entry;
144154},
145155{ skipMaintenance: true },
@@ -150,12 +160,13 @@ async function markSessionFailed(params: {
150160async function resumeMainSession(params: {
151161storePath: string;
152162sessionKey: string;
163+pendingFinalDeliveryText?: string | null;
153164}): Promise<boolean> {
154165try {
155166await callGateway<{ runId: string }>({
156167method: "agent",
157168params: {
158-message: buildResumeMessage(),
169+message: buildResumeMessage(params.pendingFinalDeliveryText),
159170sessionKey: params.sessionKey,
160171idempotencyKey: crypto.randomUUID(),
161172deliver: false,
@@ -170,13 +181,24 @@ async function resumeMainSession(params: {
170181if (!entry) {
171182return;
172183}
184+const now = Date.now();
173185entry.abortedLastRun = false;
174-entry.updatedAt = Date.now();
186+entry.updatedAt = now;
187+if (entry.pendingFinalDelivery || entry.pendingFinalDeliveryText) {
188+entry.pendingFinalDeliveryLastAttemptAt = now;
189+entry.pendingFinalDeliveryAttemptCount =
190+(entry.pendingFinalDeliveryAttemptCount ?? 0) + 1;
191+entry.pendingFinalDeliveryLastError = null;
192+}
175193store[params.sessionKey] = entry;
176194},
177195{ skipMaintenance: true },
178196);
179-log.info(`resumed interrupted main session: ${params.sessionKey}`);
197+log.info(
198+`resumed interrupted main session: ${params.sessionKey}${
199+ params.pendingFinalDeliveryText ? " (with pending payload)" : ""
200+ }`,
201+);
180202return true;
181203} catch (err) {
182204log.warn(`failed to resume interrupted main session ${params.sessionKey}: ${String(err)}`);
@@ -290,6 +312,7 @@ async function recoverStore(params: {
290312const resumed = await resumeMainSession({
291313storePath: params.storePath,
292314 sessionKey,
315+pendingFinalDeliveryText: entry.pendingFinalDeliveryText,
293316});
294317if (resumed) {
295318params.resumedSessionKeys.add(sessionKey);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。