fix(logging): record structured abort errors in turn logs (#572)
Co-authored-by: Letta Code <noreply@letta.com>
This commit is contained in:
@@ -1222,6 +1222,7 @@ export class LettaBot implements AgentSession {
|
||||
const maxRepeatedBashFailures = 3;
|
||||
let lastEventType: string | null = null;
|
||||
let abortedWithMessage = false;
|
||||
let turnError: string | undefined;
|
||||
|
||||
const parseAndHandleDirectives = async () => {
|
||||
if (!response.trim()) return;
|
||||
@@ -1346,6 +1347,7 @@ export class LettaBot implements AgentSession {
|
||||
log.error(`Agent stuck in tool loop (${msgTypeCounts['tool_call']} calls), aborting`);
|
||||
session?.abort().catch(() => {});
|
||||
response = '(Agent got stuck in a tool loop and was stopped. Try sending your message again.)';
|
||||
turnError = `tool loop abort after ${msgTypeCounts['tool_call'] || 0} tool calls`;
|
||||
abortedWithMessage = true;
|
||||
break;
|
||||
}
|
||||
@@ -1402,6 +1404,7 @@ export class LettaBot implements AgentSession {
|
||||
log.error(`Stopping run after repeated Bash command failures (${repeatedBashFailureCount}) for: ${bashCommand}`);
|
||||
session?.abort().catch(() => {});
|
||||
response = `(I stopped after repeated CLI command failures while running: ${bashCommand}. The command path appears mismatched. Please confirm Bluesky CLI commands are available, then resend your request.)`;
|
||||
turnError = `repeated Bash failure abort (${repeatedBashFailureCount}x): ${bashCommand}`;
|
||||
abortedWithMessage = true;
|
||||
break;
|
||||
}
|
||||
@@ -1652,7 +1655,7 @@ export class LettaBot implements AgentSession {
|
||||
events,
|
||||
output: output || response,
|
||||
durationMs: Math.round(performance.now() - t0),
|
||||
error: lastErrorDetail?.message,
|
||||
error: turnError ?? lastErrorDetail?.message,
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,8 @@ describe('result divergence guard', () => {
|
||||
allowedTools: [],
|
||||
maxToolCalls: 100,
|
||||
});
|
||||
const writeTurn = vi.fn(async () => {});
|
||||
(bot as any).turnLogger = { write: writeTurn };
|
||||
|
||||
const abort = vi.fn(async () => {});
|
||||
const adapter = {
|
||||
@@ -152,6 +154,10 @@ describe('result divergence guard', () => {
|
||||
expect(abort).toHaveBeenCalled();
|
||||
const sentTexts = adapter.sendMessage.mock.calls.map(([payload]) => payload.text as string);
|
||||
expect(sentTexts.some(text => text.includes('repeated CLI command failures'))).toBe(true);
|
||||
expect(writeTurn).toHaveBeenCalledTimes(1);
|
||||
expect(writeTurn).toHaveBeenCalledWith(expect.objectContaining({
|
||||
error: 'repeated Bash failure abort (3x): lettabot bluesky post --text "hi" --agent Bot',
|
||||
}));
|
||||
});
|
||||
|
||||
it('stops consuming stream and avoids retry after explicit tool-loop abort', async () => {
|
||||
@@ -160,6 +166,8 @@ describe('result divergence guard', () => {
|
||||
allowedTools: [],
|
||||
maxToolCalls: 1,
|
||||
});
|
||||
const writeTurn = vi.fn(async () => {});
|
||||
(bot as any).turnLogger = { write: writeTurn };
|
||||
|
||||
const adapter = {
|
||||
id: 'mock',
|
||||
@@ -207,6 +215,10 @@ describe('result divergence guard', () => {
|
||||
expect(runSession).toHaveBeenCalledTimes(1);
|
||||
const sentTexts = adapter.sendMessage.mock.calls.map(([payload]) => payload.text);
|
||||
expect(sentTexts).toEqual(['(Agent got stuck in a tool loop and was stopped. Try sending your message again.)']);
|
||||
expect(writeTurn).toHaveBeenCalledTimes(1);
|
||||
expect(writeTurn).toHaveBeenCalledWith(expect.objectContaining({
|
||||
error: 'tool loop abort after 1 tool calls',
|
||||
}));
|
||||
});
|
||||
|
||||
it('does not deliver reasoning text from error results as the response', async () => {
|
||||
|
||||
Reference in New Issue
Block a user