From 0b969c86758d96fb7dbdda7f5af9381b03720bf0 Mon Sep 17 00:00:00 2001 From: vvzvlad Date: Sat, 20 Jun 2026 17:47:16 +0300 Subject: [PATCH] test(ai-chat): pin step-limit boundary + note AI SDK v7 system->instructions Port two refinements from the GLM variant onto the Claude base: - prepareAgentStep: add a comment note that AI SDK v7 renames the per-step `system` field to `instructions` (v6 ^6.0.134 still uses `system`), so it gets updated correctly on the next SDK bump. - ai-chat.service.spec: add an explicit off-by-one boundary test for prepareAgentStep, expressed via MAX_AGENT_STEPS instead of a hardcoded 18/19 so it tracks the constant if the cap changes. Co-Authored-By: Claude Opus 4.8 --- apps/server/src/core/ai-chat/ai-chat.service.spec.ts | 9 +++++++++ apps/server/src/core/ai-chat/ai-chat.service.ts | 3 +++ 2 files changed, 12 insertions(+) diff --git a/apps/server/src/core/ai-chat/ai-chat.service.spec.ts b/apps/server/src/core/ai-chat/ai-chat.service.spec.ts index d007c546..20650457 100644 --- a/apps/server/src/core/ai-chat/ai-chat.service.spec.ts +++ b/apps/server/src/core/ai-chat/ai-chat.service.spec.ts @@ -97,4 +97,13 @@ describe('prepareAgentStep', () => { // The synthesis instruction is appended. expect(result?.system).toContain(FINAL_STEP_INSTRUCTION); }); + + it('pins the off-by-one boundary (MAX-2 is not final, MAX-1 is)', () => { + // Boundary expressed via the constant, not a hardcoded 18/19, so the test + // tracks MAX_AGENT_STEPS if the cap ever changes. + expect(prepareAgentStep(MAX_AGENT_STEPS - 2, 'SYS')).toBeUndefined(); + const atBoundary = prepareAgentStep(MAX_AGENT_STEPS - 1, 'SYS'); + expect(atBoundary).toBeDefined(); + expect(atBoundary?.toolChoice).toBe('none'); + }); }); diff --git a/apps/server/src/core/ai-chat/ai-chat.service.ts b/apps/server/src/core/ai-chat/ai-chat.service.ts index 1b274238..cd62b5f6 100644 --- a/apps/server/src/core/ai-chat/ai-chat.service.ts +++ b/apps/server/src/core/ai-chat/ai-chat.service.ts @@ -38,6 +38,9 @@ const FINAL_STEP_INSTRUCTION = // `system` is the in-scope system prompt; we CONCATENATE so the original // persona/context is preserved — a bare `system` override would REPLACE the // whole system prompt for the step. +// +// NOTE: at AI SDK v7 the per-step `system` field is renamed to `instructions`. +// On v6 (`^6.0.134`) `system` is the correct field — adjust when bumping. export function prepareAgentStep( stepNumber: number, system: string,