Skip to content

Commit a8442e4

Browse files
committed
fix: keep stalled session retry in accessor boundary
1 parent 1fed9d2 commit a8442e4

3 files changed

Lines changed: 12 additions & 32 deletions

File tree

src/auto-reply/reply/agent-runner-execution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ function isAbortLikeRunFailure(value: unknown): boolean {
344344
typeof value === "string"
345345
? value
346346
: value && typeof value === "object" && "message" in value
347-
? String((value as { message?: unknown }).message ?? "")
347+
? (readStringValue((value as { message?: unknown }).message) ?? "")
348348
: "";
349349
return /aborted/i.test(message);
350350
}

src/auto-reply/reply/agent-runner-session-reset.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ export async function resetReplyRunSession(params: {
4444
onActiveSessionEntry: (entry: SessionEntry) => void;
4545
onNewSession: (newSessionId: string, nextSessionFile: string) => void;
4646
}): Promise<boolean> {
47-
if (!params.sessionKey || !params.activeSessionStore || !params.storePath) {
47+
if (!params.sessionKey || !params.storePath) {
4848
return false;
4949
}
50-
const prevEntry = params.activeSessionStore[params.sessionKey] ?? params.activeSessionEntry;
50+
const prevEntry = params.activeSessionStore?.[params.sessionKey] ?? params.activeSessionEntry;
5151
if (!prevEntry) {
5252
return false;
5353
}
@@ -89,7 +89,9 @@ export async function resetReplyRunSession(params: {
8989
params.messageThreadId,
9090
);
9191
nextEntry.sessionFile = nextSessionFile;
92-
params.activeSessionStore[params.sessionKey] = nextEntry;
92+
if (params.activeSessionStore) {
93+
params.activeSessionStore[params.sessionKey] = nextEntry;
94+
}
9395
try {
9496
await deps.persistSessionResetLifecycle({
9597
agentId,

src/auto-reply/reply/agent-runner.ts

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { deriveContextPromptTokens, hasNonzeroUsage, normalizeUsage } from "../.
2323
import { enqueueCommitmentExtraction } from "../../commitments/runtime.js";
2424
import type { OpenClawConfig } from "../../config/config.js";
2525
import {
26-
loadSessionStore,
2726
resolveSessionPluginStatusLines,
2827
resolveSessionPluginTraceLines,
2928
type SessionEntry,
@@ -365,7 +364,6 @@ function shouldAutoResetRetryStalledDirectSession(params: {
365364
params.isHeartbeat ||
366365
!params.sessionKey ||
367366
!params.storePath ||
368-
!params.activeSessionStore ||
369367
!isDirectChatSession({
370368
sessionKey: params.sessionKey,
371369
sessionEntry: params.activeSessionEntry,
@@ -1330,7 +1328,7 @@ export async function runReplyAgent(params: {
13301328
} = params;
13311329

13321330
let activeSessionEntry = sessionEntry;
1333-
let activeSessionStore = sessionStore;
1331+
const activeSessionStore = sessionStore;
13341332
let activeIsNewSession = isNewSession;
13351333
const effectiveResetTriggered = resetTriggered === true;
13361334
const activeRunQueueMode = effectiveResetTriggered ? "interrupt" : resolvedQueue.mode;
@@ -1351,16 +1349,6 @@ export async function runReplyAgent(params: {
13511349
config: followupRun.run.config,
13521350
attributes: traceAttributes,
13531351
});
1354-
const ensureActiveSessionStore = (): Record<string, SessionEntry> | undefined => {
1355-
if (activeSessionStore || !storePath || !sessionKey) {
1356-
return activeSessionStore;
1357-
}
1358-
// Gateway direct turns can arrive with a session entry but no mutable store;
1359-
// reset/retry must still rotate the canonical persisted session.
1360-
activeSessionStore = loadSessionStore(storePath, { skipCache: true });
1361-
activeSessionEntry = activeSessionStore[sessionKey] ?? activeSessionEntry;
1362-
return activeSessionStore;
1363-
};
13641352
const effectiveShouldSteer = !isHeartbeat && !effectiveResetTriggered && shouldSteer;
13651353
const effectiveShouldFollowup = !effectiveResetTriggered && shouldFollowup;
13661354
const typingSignals = createTypingSignaler({
@@ -1875,23 +1863,18 @@ export async function runReplyAgent(params: {
18751863
toolProgressDetail,
18761864
replyMediaContext,
18771865
isRestartRecoveryArmed,
1878-
shouldDeferRunFailure: (outcome) => {
1879-
const resetRetrySessionStore =
1880-
!activeSessionStore && isReplayableStalledDirectSessionAbort(outcome.runResult.meta)
1881-
? ensureActiveSessionStore()
1882-
: activeSessionStore;
1883-
return shouldAutoResetRetryStalledDirectSession({
1866+
shouldDeferRunFailure: (outcome) =>
1867+
shouldAutoResetRetryStalledDirectSession({
18841868
isHeartbeat,
18851869
sessionKey,
18861870
storePath,
1887-
activeSessionStore: resetRetrySessionStore,
1871+
activeSessionStore,
18881872
activeSessionEntry,
18891873
sessionCtx,
18901874
runOutcome: outcome,
18911875
blockReplyPipeline,
18921876
pendingToolTasks,
1893-
});
1894-
},
1877+
}),
18951878
});
18961879
let runOutcome = await traceAgentPhase("reply.run_agent_turn", runAgentTurn);
18971880

@@ -1906,17 +1889,12 @@ export async function runReplyAgent(params: {
19061889
await blockReplyPipeline.flush({ force: true });
19071890
}
19081891

1909-
const resetRetryNeedsSessionStore =
1910-
!activeSessionStore && isReplayableStalledDirectSessionAbort(runOutcome.runResult.meta);
1911-
const resetRetrySessionStore = resetRetryNeedsSessionStore
1912-
? ensureActiveSessionStore()
1913-
: activeSessionStore;
19141892
if (
19151893
shouldAutoResetRetryStalledDirectSession({
19161894
isHeartbeat,
19171895
sessionKey,
19181896
storePath,
1919-
activeSessionStore: resetRetrySessionStore,
1897+
activeSessionStore,
19201898
activeSessionEntry,
19211899
sessionCtx,
19221900
runOutcome,

0 commit comments

Comments
 (0)