fix: improve error handling for headless (#187)
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { parseArgs } from "node:util";
|
||||
import { APIError } from "@letta-ai/letta-client/core/error";
|
||||
import type {
|
||||
AgentState,
|
||||
MessageCreate,
|
||||
@@ -19,6 +18,7 @@ import {
|
||||
markIncompleteToolsAsCancelled,
|
||||
toLines,
|
||||
} from "./cli/helpers/accumulator";
|
||||
import { formatErrorDetails } from "./cli/helpers/errorFormatter";
|
||||
import { safeJsonParseOr } from "./cli/helpers/safeJsonParse";
|
||||
import { drainStreamWithResume } from "./cli/helpers/stream";
|
||||
import { settingsManager } from "./settings-manager";
|
||||
@@ -846,20 +846,24 @@ export async function handleHeadlessCommand(
|
||||
? errorMessages.join("; ")
|
||||
: `Unexpected stop reason: ${stopReason}`;
|
||||
|
||||
// Fetch detailed error from run metadata if available
|
||||
// Fetch detailed error from run metadata if available (same as TUI mode)
|
||||
if (lastRunId && errorMessages.length === 0) {
|
||||
try {
|
||||
const run = await client.runs.retrieve(lastRunId);
|
||||
if (run.metadata?.error) {
|
||||
const error = run.metadata.error as {
|
||||
const errorData = run.metadata.error as {
|
||||
type?: string;
|
||||
message?: string;
|
||||
detail?: string;
|
||||
};
|
||||
const errorType = error.type ? `[${error.type}] ` : "";
|
||||
const errorMsg = error.message || "An error occurred";
|
||||
const errorDetail = error.detail ? `: ${error.detail}` : "";
|
||||
errorMessage = `${errorType}${errorMsg}${errorDetail}`;
|
||||
// Construct error object that formatErrorDetails can parse
|
||||
const errorObject = {
|
||||
error: {
|
||||
error: errorData,
|
||||
run_id: lastRunId,
|
||||
},
|
||||
};
|
||||
errorMessage = formatErrorDetails(errorObject, agent.id);
|
||||
}
|
||||
} catch (_e) {
|
||||
// If we can't fetch error details, append note to error message
|
||||
@@ -878,11 +882,7 @@ export async function handleHeadlessCommand(
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
// Include run_id and stop_reason for debugging
|
||||
const runInfoSuffix = lastRunId
|
||||
? ` (run_id: ${lastRunId}, stop_reason: ${stopReason})`
|
||||
: ` (stop_reason: ${stopReason})`;
|
||||
console.error(`${errorMessage}${runInfoSuffix}`);
|
||||
console.error(`Error: ${errorMessage}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -890,23 +890,19 @@ export async function handleHeadlessCommand(
|
||||
// Mark incomplete tool calls as cancelled
|
||||
markIncompleteToolsAsCancelled(buffers);
|
||||
|
||||
// Build run info suffix for debugging
|
||||
const runInfoSuffix = lastKnownRunId
|
||||
? ` (run_id: ${lastKnownRunId}, stop_reason: error)`
|
||||
: "";
|
||||
// Use comprehensive error formatting (same as TUI mode)
|
||||
const errorDetails = formatErrorDetails(error, agent.id);
|
||||
|
||||
// Handle APIError from streaming (event: error)
|
||||
if (error instanceof APIError && error.error?.error) {
|
||||
const { type, message, detail } = error.error.error;
|
||||
const errorType = type ? `[${type}] ` : "";
|
||||
const errorMessage = message || "An error occurred";
|
||||
const errorDetail = detail ? `: ${detail}` : "";
|
||||
console.error(
|
||||
`Error: ${errorType}${errorMessage}${errorDetail}${runInfoSuffix}`,
|
||||
if (outputFormat === "stream-json") {
|
||||
console.log(
|
||||
JSON.stringify({
|
||||
type: "error",
|
||||
message: errorDetails,
|
||||
run_id: lastKnownRunId,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
// Fallback for non-API errors
|
||||
console.error(`Error: ${error}${runInfoSuffix}`);
|
||||
console.error(`Error: ${errorDetails}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user