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:
@@ -48,7 +48,7 @@ async function appendTurn(
|
|||||||
await appendSessionTurn(storageRoot, sessionId, payload);
|
await appendSessionTurn(storageRoot, sessionId, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function executeTurnTools(
|
export async function executeTurnTools(
|
||||||
calls: Array<{ id: string; name: string; arguments: string }>,
|
calls: Array<{ id: string; name: string; arguments: string }>,
|
||||||
toolCtx: ToolContext,
|
toolCtx: ToolContext,
|
||||||
messages: ChatMessage[],
|
messages: ChatMessage[],
|
||||||
@@ -70,6 +70,17 @@ async function executeTurnTools(
|
|||||||
return turnCount;
|
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. */
|
/** Agent run loop: LLM ↔ tools until no tool_calls or maxTurns. */
|
||||||
export async function runBuiltinLoop(
|
export async function runBuiltinLoop(
|
||||||
options: RunBuiltinLoopOptions,
|
options: RunBuiltinLoopOptions,
|
||||||
@@ -88,7 +99,6 @@ export async function runBuiltinLoop(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// When noTools is set, ignore any tool_calls the LLM might still return
|
// 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 effectiveToolCalls = options.noTools ? null : (response.toolCalls ?? null);
|
||||||
|
|
||||||
const assistantMessage: ChatMessage = {
|
const assistantMessage: ChatMessage = {
|
||||||
@@ -108,9 +118,7 @@ export async function runBuiltinLoop(
|
|||||||
});
|
});
|
||||||
turnCount += 1;
|
turnCount += 1;
|
||||||
|
|
||||||
// If tools are available but LLM stopped calling them without producing
|
if (shouldNudge({ noTools: options.noTools, text, turn, maxTurns: options.maxTurns })) {
|
||||||
// frontmatter, nudge it to continue working or output frontmatter.
|
|
||||||
if (!options.noTools && !text.trimStart().startsWith("---") && turn < options.maxTurns - 1) {
|
|
||||||
log("7FXQM2KN", "text-only turn without frontmatter, nudging LLM to continue");
|
log("7FXQM2KN", "text-only turn without frontmatter, nudging LLM to continue");
|
||||||
const nudge =
|
const nudge =
|
||||||
"You stopped calling tools but your response does not start with the required `---` YAML frontmatter. " +
|
"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. " +
|
"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. " +
|
"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. " +
|
"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 — " +
|
"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.",
|
"no preamble text, no explanation before it. The parser requires `---` at position 0.",
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user