fix (agents): return timeout reply on empty timed-out runs

This commit is contained in:
Vignesh Natarajan
2026-02-14 20:32:45 -08:00
parent b373461032
commit 17588f51f0
2 changed files with 41 additions and 0 deletions

View File

@@ -354,6 +354,22 @@ describe("overflow compaction in run loop", () => {
expect(log.warn).not.toHaveBeenCalledWith(expect.stringContaining("source=assistantError"));
});
it("returns an explicit timeout payload when the run times out before producing any reply", async () => {
mockedRunEmbeddedAttempt.mockResolvedValue(
makeAttemptResult({
aborted: true,
timedOut: true,
timedOutDuringCompaction: false,
assistantTexts: [],
}),
);
const result = await runEmbeddedPiAgent(baseParams);
expect(result.payloads?.[0]?.isError).toBe(true);
expect(result.payloads?.[0]?.text).toContain("timed out");
});
it("sets promptTokens from the latest model call usage, not accumulated attempt usage", async () => {
mockedRunEmbeddedAttempt.mockResolvedValue(
makeAttemptResult({

View File

@@ -907,6 +907,31 @@ export async function runEmbeddedPiAgent(
inlineToolResultsAllowed: false,
});
// Timeout aborts can leave the run without any assistant payloads.
// Emit an explicit timeout error instead of silently completing, so
// callers do not lose the turn as an orphaned user message.
if (timedOut && !timedOutDuringCompaction && payloads.length === 0) {
return {
payloads: [
{
text:
"Request timed out before a response was generated. " +
"Please try again, or increase `agents.defaults.timeoutSeconds` in your config.",
isError: true,
},
],
meta: {
durationMs: Date.now() - started,
agentMeta,
aborted,
systemPromptReport: attempt.systemPromptReport,
},
didSendViaMessagingTool: attempt.didSendViaMessagingTool,
messagingToolSentTexts: attempt.messagingToolSentTexts,
messagingToolSentTargets: attempt.messagingToolSentTargets,
};
}
log.debug(
`embedded run done: runId=${params.runId} sessionId=${params.sessionId} durationMs=${Date.now() - started} aborted=${aborted}`,
);