Merge c328f668a4 into 09be5d45d5
This commit is contained in:
commit
0ebbe59ef5
12
src/agents/subagent-announce.error-formatting.test.ts
Normal file
12
src/agents/subagent-announce.error-formatting.test.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
// We need to import the functions we want to test, but they're not exported
|
||||
// For now, let's just test integration by checking that the module loads
|
||||
describe("subagent-announce error formatting", () => {
|
||||
it("module loads without errors", async () => {
|
||||
const module = await import("./subagent-announce.js");
|
||||
expect(module).toBeDefined();
|
||||
expect(module.buildSubagentSystemPrompt).toBeDefined();
|
||||
expect(module.runSubagentAnnounceFlow).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -20,6 +20,13 @@ import {
|
||||
} from "../utils/delivery-context.js";
|
||||
import { isEmbeddedPiRunActive, queueEmbeddedPiMessage } from "./pi-embedded.js";
|
||||
import { type AnnounceQueueItem, enqueueAnnounce } from "./subagent-announce-queue.js";
|
||||
import {
|
||||
isAuthErrorMessage,
|
||||
isBillingErrorMessage,
|
||||
isContextOverflowError,
|
||||
isRateLimitErrorMessage,
|
||||
isTimeoutErrorMessage,
|
||||
} from "./pi-embedded-helpers/errors.js";
|
||||
import { readLatestAssistantReply } from "./tools/agent-step.js";
|
||||
|
||||
function formatDurationShort(valueMs?: number) {
|
||||
@ -244,6 +251,73 @@ async function buildSubagentStatsLine(params: {
|
||||
return `Stats: ${parts.join(" \u2022 ")}`;
|
||||
}
|
||||
|
||||
function formatSubagentErrorMessage(outcome: SubagentRunOutcome): string {
|
||||
const rawError = outcome.error ?? "";
|
||||
|
||||
// Classify error types and provide actionable guidance
|
||||
if (isRateLimitErrorMessage(rawError)) {
|
||||
return "temporarily overloaded (rate limit). Try again in a moment.";
|
||||
}
|
||||
|
||||
if (isAuthErrorMessage(rawError)) {
|
||||
return "authentication failed. Check API credentials or re-authenticate.";
|
||||
}
|
||||
|
||||
if (isBillingErrorMessage(rawError)) {
|
||||
return "billing issue (insufficient credits or quota exceeded). Check account status.";
|
||||
}
|
||||
|
||||
if (isContextOverflowError(rawError)) {
|
||||
return "input too large for model. Try reducing input size or using a model with larger context window.";
|
||||
}
|
||||
|
||||
if (isTimeoutErrorMessage(rawError)) {
|
||||
return "request timed out. Try again or increase runTimeoutSeconds.";
|
||||
}
|
||||
|
||||
// Return sanitized error for unclassified errors
|
||||
if (rawError.length > 200) {
|
||||
// Truncate very long errors to keep announcement readable
|
||||
return `${rawError.slice(0, 200)}…`;
|
||||
}
|
||||
|
||||
return rawError || "unknown error";
|
||||
}
|
||||
|
||||
function buildSubagentStatusLabel(
|
||||
outcome: SubagentRunOutcome,
|
||||
runtimeMs?: number,
|
||||
timeoutMs?: number,
|
||||
): string {
|
||||
if (outcome.status === "ok") {
|
||||
return "completed successfully";
|
||||
}
|
||||
|
||||
if (outcome.status === "timeout") {
|
||||
const runtime = formatDurationShort(runtimeMs);
|
||||
const limit = formatDurationShort(timeoutMs);
|
||||
if (runtime && limit) {
|
||||
return `timed out after ${runtime} (limit: ${limit})`;
|
||||
}
|
||||
if (runtime) {
|
||||
return `timed out after ${runtime}`;
|
||||
}
|
||||
return "timed out (consider increasing runTimeoutSeconds)";
|
||||
}
|
||||
|
||||
if (outcome.status === "error") {
|
||||
const errorMsg = formatSubagentErrorMessage(outcome);
|
||||
return `failed: ${errorMsg}`;
|
||||
}
|
||||
|
||||
// Unknown status
|
||||
const runtime = formatDurationShort(runtimeMs);
|
||||
if (runtime) {
|
||||
return `finished with unknown status (runtime: ${runtime})`;
|
||||
}
|
||||
return "finished with unknown status";
|
||||
}
|
||||
|
||||
export function buildSubagentSystemPrompt(params: {
|
||||
requesterSessionKey?: string;
|
||||
requesterOrigin?: DeliveryContext;
|
||||
@ -366,6 +440,12 @@ export async function runSubagentAnnounceFlow(params: {
|
||||
|
||||
if (!outcome) outcome = { status: "unknown" };
|
||||
|
||||
// Calculate runtime for context
|
||||
const runtimeMs =
|
||||
typeof params.startedAt === "number" && typeof params.endedAt === "number"
|
||||
? Math.max(0, params.endedAt - params.startedAt)
|
||||
: undefined;
|
||||
|
||||
// Build stats
|
||||
const statsLine = await buildSubagentStatsLine({
|
||||
sessionKey: params.childSessionKey,
|
||||
@ -373,15 +453,8 @@ export async function runSubagentAnnounceFlow(params: {
|
||||
endedAt: params.endedAt,
|
||||
});
|
||||
|
||||
// Build status label
|
||||
const statusLabel =
|
||||
outcome.status === "ok"
|
||||
? "completed successfully"
|
||||
: outcome.status === "timeout"
|
||||
? "timed out"
|
||||
: outcome.status === "error"
|
||||
? `failed: ${outcome.error || "unknown error"}`
|
||||
: "finished with unknown status";
|
||||
// Build status label with improved error messages
|
||||
const statusLabel = buildSubagentStatusLabel(outcome, runtimeMs, params.timeoutMs);
|
||||
|
||||
// Build instructional message for main agent
|
||||
const taskLabel = params.label || params.task || "background task";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user