mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 15:11:32 +00:00
fix(agents): prevent cancelled prompts from spawning zombie runs (#115011)
This commit is contained in:
committed by
GitHub
parent
0d7fb8eb39
commit
fe19f8f54b
@@ -228,6 +228,25 @@ describe("prepareEmbeddedAttemptStreamRuntime", () => {
|
||||
expect(mocks.withOwnedSessionTranscriptWrites).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ label: "external cancellation", message: "run cancelled" },
|
||||
{ label: "run timeout", message: "run timed out" },
|
||||
])("does not start a prompt after $label", async ({ message }) => {
|
||||
const fixture = createFixture();
|
||||
const runtime = await prepareEmbeddedAttemptStreamRuntime(fixture.input);
|
||||
const reason = new Error(message);
|
||||
const abortError = new Error(message, { cause: reason });
|
||||
abortError.name = "AbortError";
|
||||
fixture.input.runAbortController.abort(reason);
|
||||
mocks.abortable.mockImplementationOnce((_signal, _promise) => Promise.reject(abortError));
|
||||
|
||||
await expect(runtime.promptActiveSession("must not start")).rejects.toBe(abortError);
|
||||
|
||||
expect(fixture.activeSession.prompt).not.toHaveBeenCalled();
|
||||
expect(fixture.trackPromptSettlePromise).not.toHaveBeenCalled();
|
||||
expect(mocks.abortable).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("flushes pending tool results and disposes the session when history preparation fails", async () => {
|
||||
const fixture = createFixture({ aborted: true });
|
||||
const failure = new Error("history failed");
|
||||
|
||||
@@ -137,9 +137,14 @@ export async function prepareEmbeddedAttemptStreamRuntime(input: {
|
||||
prompt: string,
|
||||
options?: Parameters<typeof activeSession.prompt>[1],
|
||||
): Promise<void> =>
|
||||
withOwnedSessionTranscriptWrites(input.ownedTranscriptWriteContext, async () =>
|
||||
abortable(input.trackPromptSettlePromise(activeSession.prompt(prompt, options))),
|
||||
);
|
||||
withOwnedSessionTranscriptWrites(input.ownedTranscriptWriteContext, async () => {
|
||||
// Prompting starts its own agent loop; reject before creating a loop that
|
||||
// an already-aborted attempt can no longer cancel.
|
||||
if (input.runAbortController.signal.aborted) {
|
||||
return abortable(Promise.resolve());
|
||||
}
|
||||
return abortable(input.trackPromptSettlePromise(activeSession.prompt(prompt, options)));
|
||||
});
|
||||
const onBlockReply = attempt.onBlockReply
|
||||
? bindOwnedSessionTranscriptWrites(input.ownedTranscriptWriteContext, attempt.onBlockReply)
|
||||
: undefined;
|
||||
|
||||
Reference in New Issue
Block a user