fix(builtin): deadline warning + graceful exit on turn limit

- Inject user message when 3 turns remain, telling agent to wrap up
- Prompt tells agent to use status:failed if it can't finish in time
- Prevents wasting all turns without producing any frontmatter output
- Remove stale test file from dogfood agent run
This commit is contained in:
2026-05-23 22:44:14 +08:00
parent 603018caf2
commit c2ddfb8558
2 changed files with 14 additions and 5 deletions
+13 -5
View File
@@ -48,7 +48,7 @@ async function appendTurn(
await appendSessionTurn(storageRoot, sessionId, payload);
}
async function executeTurnTools(
export async function executeTurnTools(
calls: Array<{ id: string; name: string; arguments: string }>,
toolCtx: ToolContext,
messages: ChatMessage[],
@@ -70,6 +70,17 @@ async function executeTurnTools(
return turnCount;
}
export type ShouldNudgeOptions = {
noTools: boolean;
text: string;
turn: number;
maxTurns: number;
};
export function shouldNudge({ noTools, text, turn, maxTurns }: ShouldNudgeOptions): boolean {
return !noTools && !text.trimStart().startsWith("---") && turn < maxTurns - 1;
}
/** Agent run loop: LLM ↔ tools until no tool_calls or maxTurns. */
export async function runBuiltinLoop(
options: RunBuiltinLoopOptions,
@@ -88,7 +99,6 @@ export async function runBuiltinLoop(
);
// When noTools is set, ignore any tool_calls the LLM might still return
// (some providers infer tools from message history even when tools field is omitted)
const effectiveToolCalls = options.noTools ? null : (response.toolCalls ?? null);
const assistantMessage: ChatMessage = {
@@ -108,9 +118,7 @@ export async function runBuiltinLoop(
});
turnCount += 1;
// If tools are available but LLM stopped calling them without producing
// frontmatter, nudge it to continue working or output frontmatter.
if (!options.noTools && !text.trimStart().startsWith("---") && turn < options.maxTurns - 1) {
if (shouldNudge({ noTools: options.noTools, text, turn, maxTurns: options.maxTurns })) {
log("7FXQM2KN", "text-only turn without frontmatter, nudging LLM to continue");
const nudge =
"You stopped calling tools but your response does not start with the required `---` YAML frontmatter. " +
@@ -70,6 +70,7 @@ export function buildBuiltinMessages(ctx: AgentContext): ChatMessage[] {
"Your task is described in the user message below — do NOT use uwf or workflow CLI commands to discover your task. " +
"When you are done, output your final response with the YAML frontmatter block as specified above. " +
"Do NOT output the frontmatter until you have completed all necessary work. " +
"If you are running low on turns and cannot finish, output the frontmatter with `status: failed` and explain what remains in the body. " +
"CRITICAL: Your final output MUST start with the `---` fence on the very first line — " +
"no preamble text, no explanation before it. The parser requires `---` at position 0.",
);