feat(ai-chat): step cap 8→20 + forced final text answer #9
Reference in New Issue
Block a user
Delete Branch "feat/ai-chat-step-limit"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements
docs/backlog/ai-chat-step-limit-and-forced-final-answer.md.What
Raises the AI agent's per-turn step cap from 8 to 20 and guarantees a non-empty answer: the final allowed step is forced to be text-only, so a tool-heavy research turn can no longer end with an empty assistant message.
How
Single file, server-only:
apps/server/src/core/ai-chat/ai-chat.service.ts.MAX_AGENT_STEPS = 20replaces the magicstepCountIs(8)instopWhen.prepareAgentStep(stepNumber, system)returnsundefinedfor normal steps, and on the final step (stepNumber >= MAX_AGENT_STEPS - 1) returns{ toolChoice: 'none', system: \${system}\n\n${FINAL_STEP_INSTRUCTION}` }`.prepareStep: ({ stepNumber }) => prepareAgentStep(stepNumber, system), placed next tostopWhen. The instruction is concatenated with the in-scope builtsystemprompt, never replacing the persona/safety layers (the AI SDK v6systemoverride is a full replacement, hence concat).Reasoning / decisions
streamTextloop is expensive to unit-test; extracting the per-step decision into a pure function (mirroring the existingcompactToolOutputpattern) makes the boundary behavior deterministically testable without the model.prepareStep.systemfully replaces the step's system message; replacing would drop persona + the non-removable safety framework. Confirmed againstai@6.0.207d.ts(per the plan).toolChoice:'none'makes the model emit text → loop ends asstop, not a truncated empty turn.prepareStep.systemis renamedinstructionsin AI SDK 7 — flagged in a code comment for the future bump.Review findings
Self-reviewed (small, localized change); no separate review-subagent pass given the size and the pure-function test coverage. No issues found; the in-scope prompt variable is confirmed to be
system.Verification
pnpm --filter server build— clean.pnpm --filter server test -- ai-chat.service— 9/9 pass (6 pre-existingcompactToolOutput+ 3 newprepareAgentStep: step 0 → undefined, step 18 → undefined, step 19 →toolChoice:'none'+ system starts with original prompt and contains the synthesis instruction).prepareStepreturnsundefinedfor normal steps and streaming is intact. No app errors.🤖 Generated with Claude Code
Ghost referenced this pull request2026-06-24 00:42:55 +03:00