Skip to content

Commit a8d7537

Browse files
committed
Enhance output handling: improve tool output processing and error message handling
1 parent 751aa84 commit a8d7537

File tree

1 file changed

+51
-15
lines changed

1 file changed

+51
-15
lines changed

src/agent/state.ts

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,33 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
306306
{ toolName: toolCall.toolName, args: toolCall.input },
307307
config,
308308
);
309-
const output =
310-
result === "" || result === null || result === undefined
311-
? "Tool executed successfully and produced no output."
312-
: result;
313-
logger.info("Tool executed successfully.", { toolCall, output });
309+
310+
let finalOutput: object;
311+
312+
if (result === "" || result === null || result === undefined) {
313+
finalOutput = {
314+
result: "Tool executed successfully and produced no output.",
315+
};
316+
} else if (typeof result === "string") {
317+
finalOutput = { result: result };
318+
} else if (
319+
typeof result === "object" &&
320+
Object.keys(result).length === 0
321+
) {
322+
// The AI SDK expects a non-empty object for the tool output.
323+
finalOutput = {
324+
result: "Tool executed successfully and produced an empty object.",
325+
};
326+
} else {
327+
// Assuming result is a non-empty object that fits the expected type
328+
finalOutput = result;
329+
}
330+
331+
logger.info("Tool executed successfully.", {
332+
toolCall,
333+
output: finalOutput,
334+
});
335+
314336
toolResults.push({
315337
id: crypto.randomUUID(),
316338
role: "tool",
@@ -319,8 +341,11 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
319341
type: "tool-result",
320342
toolCallId: toolCall.toolCallId,
321343
toolName: toolCall.toolName,
322-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
323-
output: output as any,
344+
// We use `as any` here because the exact type of the tool output
345+
// is not known at compile time and can vary between tools.
346+
// The logic above ensures that the output is always a non-empty
347+
// object, which satisfies the AI SDK's runtime validation.
348+
output: finalOutput as any,
324349
},
325350
],
326351
});
@@ -360,7 +385,18 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
360385
logger.info("No tool calls, agent is now idle.");
361386
}
362387
} catch (error) {
363-
if (error instanceof TransientError && retryCount < MAX_RETRIES) {
388+
let typedError = error;
389+
const errorMessage =
390+
typedError instanceof Error ? typedError.message : "An unknown error occurred.";
391+
392+
// This is a workaround for a generic error thrown by the AI SDK when the LLM
393+
// returns an empty response (no text, no tool calls). We treat it as a
394+
// transient error and retry.
395+
if (errorMessage.includes("No output generated")) {
396+
typedError = new TransientError(errorMessage);
397+
}
398+
399+
if (typedError instanceof TransientError && retryCount < MAX_RETRIES) {
364400
logger.warn(`Transient error caught, retrying... (${retryCount + 1})`);
365401
set({ status: "idle" });
366402
const backoff = INITIAL_BACKOFF_MS * 2 ** retryCount;
@@ -371,15 +407,15 @@ export const useStore = create<AppState & AppActions>((set, get) => ({
371407
return;
372408
}
373409

374-
const errorMessage =
375-
error instanceof Error ? error.message : "An unknown error occurred.";
410+
const finalErrorMessage =
411+
typedError instanceof Error ? typedError.message : "An unknown error occurred.";
376412

377-
if (error instanceof FatalError) {
378-
logger.error(`Fatal error: ${errorMessage}`);
379-
set({ error: errorMessage, status: "error" });
413+
if (typedError instanceof FatalError) {
414+
logger.error(`Fatal error: ${finalErrorMessage}`);
415+
set({ error: finalErrorMessage, status: "error" });
380416
} else {
381-
logger.error(`Unhandled error in agent logic: ${errorMessage}`);
382-
set({ error: errorMessage, status: "error" });
417+
logger.error(`Unhandled error in agent logic: ${finalErrorMessage}`);
418+
set({ error: finalErrorMessage, status: "error" });
383419
}
384420
}
385421
},

0 commit comments

Comments
 (0)