From 5337f9243a1dbb33dc6fe8b5d5da808bd410af9c Mon Sep 17 00:00:00 2001 From: Rajeev91691 Date: Mon, 20 Jul 2026 21:20:25 +0530 Subject: [PATCH] fix(ai-chat): respect max_tokens parameter and model limit in MoonshotProvider Fixes #3408 by destructuring max_tokens from ICompleteArguments in MoonshotProvider.complete() and passing max_tokens || modelUsed.max_tokens || 1000 instead of hardcoding 1000. This ensures thinking models such as Kimi K3 have sufficient output token budget and do not hit early length truncation. --- .../moonshot/MoonshotProvider.test.ts | 23 +++++++++++++++---- .../providers/moonshot/MoonshotProvider.ts | 3 ++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/backend/drivers/ai-chat/providers/moonshot/MoonshotProvider.test.ts b/src/backend/drivers/ai-chat/providers/moonshot/MoonshotProvider.test.ts index 9ae61ace62..4f51b7744f 100644 --- a/src/backend/drivers/ai-chat/providers/moonshot/MoonshotProvider.test.ts +++ b/src/backend/drivers/ai-chat/providers/moonshot/MoonshotProvider.test.ts @@ -202,7 +202,7 @@ describe('MoonshotProvider.complete request shape', () => { usage: { prompt_tokens: 1, completion_tokens: 1 }, }; - it('forwards model + messages and locks max_tokens=1000', async () => { + it('forwards model + messages and passes max_tokens or falls back to model max_tokens', async () => { const { provider } = makeProvider(); createMock.mockResolvedValueOnce(baseCompletion); @@ -216,9 +216,24 @@ describe('MoonshotProvider.complete request shape', () => { const [args] = createMock.mock.calls[0]!; expect(args.model).toBe('kimi-k2.6'); expect(args.messages).toEqual([{ role: 'user', content: 'hello' }]); - // max_tokens is hardcoded by the provider — the call to Moonshot - // should always cap at 1000 tokens of completion. - expect(args.max_tokens).toBe(1000); + expect(args.max_tokens).toBe(262_144); + }); + + it('passes custom max_tokens when provided in arguments', async () => { + const { provider } = makeProvider(); + createMock.mockResolvedValueOnce(baseCompletion); + + await withTestActor(() => + provider.complete({ + model: 'kimi-k3', + messages: [{ role: 'user', content: 'hello' }], + max_tokens: 4096, + }), + ); + + const [args] = createMock.mock.calls[0]!; + expect(args.model).toBe('kimi-k3'); + expect(args.max_tokens).toBe(4096); }); it('omits the `tools` key entirely when no tools are supplied', async () => { diff --git a/src/backend/drivers/ai-chat/providers/moonshot/MoonshotProvider.ts b/src/backend/drivers/ai-chat/providers/moonshot/MoonshotProvider.ts index 079a74601f..e6de47db8a 100644 --- a/src/backend/drivers/ai-chat/providers/moonshot/MoonshotProvider.ts +++ b/src/backend/drivers/ai-chat/providers/moonshot/MoonshotProvider.ts @@ -68,6 +68,7 @@ export class MoonshotProvider implements IChatProvider { stream, model, tools, + max_tokens, }: ICompleteArguments): Promise { const actor = Context.get('actor'); const availableModels = this.models(); @@ -89,7 +90,7 @@ export class MoonshotProvider implements IChatProvider { messages, model: modelUsed.id, ...(tools ? { tools } : {}), - max_tokens: 1000, + max_tokens: max_tokens || modelUsed.max_tokens || 1000, stream, ...(stream ? {