From ba443bd1280c102725b4525ffa53cbe3907f8c6b Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Fri, 11 Sep 2026 10:25:23 +0000 Subject: [PATCH 1/8] fix(web): remove StepFun from Auto Free Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- apps/web/src/lib/ai-gateway/models.test.ts | 2 -- apps/web/src/lib/ai-gateway/models.ts | 9 --------- 2 files changed, 11 deletions(-) diff --git a/apps/web/src/lib/ai-gateway/models.test.ts b/apps/web/src/lib/ai-gateway/models.test.ts index b5aa10dfed..c5ebcad600 100644 --- a/apps/web/src/lib/ai-gateway/models.test.ts +++ b/apps/web/src/lib/ai-gateway/models.test.ts @@ -231,7 +231,6 @@ describe('isFreeModel', () => { expect( Object.fromEntries(autoFreeModels.map(({ model, reasoning }) => [model, reasoning])) ).toEqual({ - 'stepfun/step-3.7-flash:free': { enabled: true, effort: 'high' }, 'poolside/laguna-s-2.1:free': { enabled: true, effort: 'high' }, 'nvidia/nemotron-3-ultra-550b-a55b:free': { enabled: true, effort: 'high' }, 'dots-studio/dots-3-note-preview:free': { enabled: true, effort: 'high' }, @@ -244,7 +243,6 @@ describe('isFreeModel', () => { autoFreeModels.map(({ model, weight }) => [model, weight]) ); expect(weights).toEqual({ - 'stepfun/step-3.7-flash:free': 1, 'poolside/laguna-s-2.1:free': 1, 'nvidia/nemotron-3-ultra-550b-a55b:free': 1, 'dots-studio/dots-3-note-preview:free': 1, diff --git a/apps/web/src/lib/ai-gateway/models.ts b/apps/web/src/lib/ai-gateway/models.ts index 1857b2774a..e8c18969c2 100644 --- a/apps/web/src/lib/ai-gateway/models.ts +++ b/apps/web/src/lib/ai-gateway/models.ts @@ -39,15 +39,6 @@ export type AutoFreeModel = { }; export const autoFreeModels: ReadonlyArray = [ - ...(stepfun_37_flash_free_model.status === 'public' - ? [ - { - model: stepfun_37_flash_free_model.public_id, - weight: 1, - reasoning: { enabled: true, effort: 'high' }, - } satisfies AutoFreeModel, - ] - : []), { model: 'poolside/laguna-s-2.1:free', weight: 1, From 9fe21eaf5c83a834fc0bbaf67578ae53fb17e722 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Fri, 11 Sep 2026 10:29:05 +0000 Subject: [PATCH 2/8] test(web): update Auto Free policy fixture Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- .../src/lib/ai-gateway/auto-model/resolution.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts index aea7b92e86..1b8bcc5496 100644 --- a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts +++ b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts @@ -1,7 +1,9 @@ import { describe, expect, it, jest } from '@jest/globals'; jest.mock('@/lib/ai-gateway/providers/gateway-models-cache', () => ({ - getOpenRouterModelsFromDatabase: jest.fn(async () => new Set()), + getOpenRouterModelsFromDatabase: jest.fn( + async () => new Set(['poolside/laguna-s-2.1:free']) + ), })); import { resolveAutoModel } from './resolution'; @@ -408,7 +410,7 @@ describe('resolveAutoModel — kilo-auto/efficient branch', () => { describe('resolveAutoModel — kilo-auto/free branch', () => { it('excludes candidates denied by the effective organization policy', async () => { const isAutoFreeCandidateAllowed = jest.fn( - async (modelId: string) => modelId === 'stepfun/step-3.7-flash:free' + async (modelId: string) => modelId === 'poolside/laguna-s-2.1:free' ); const result = await resolveAutoModel( @@ -425,11 +427,11 @@ describe('resolveAutoModel — kilo-auto/free branch', () => { expect(result).toEqual({ kind: 'ok', resolved: { - model: 'stepfun/step-3.7-flash:free', + model: 'poolside/laguna-s-2.1:free', reasoning: { enabled: true, effort: 'high' }, }, }); - expect(isAutoFreeCandidateAllowed).toHaveBeenCalledWith('stepfun/step-3.7-flash:free'); + expect(isAutoFreeCandidateAllowed).toHaveBeenCalledWith('poolside/laguna-s-2.1:free'); }); it('reports no free models when organization policy denies every candidate', async () => { From d0c2472b40f6b5a2f12be42b1d2bcd8629ecdfe5 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Fri, 11 Sep 2026 10:41:58 +0000 Subject: [PATCH 3/8] test(web): update remaining Auto Free fixtures Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- .../src/app/api/openrouter/[...path]/route.test.ts | 6 +++--- .../src/lib/ai-gateway/auto-model/resolution.test.ts | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/apps/web/src/app/api/openrouter/[...path]/route.test.ts b/apps/web/src/app/api/openrouter/[...path]/route.test.ts index a9b1235740..e713666ab3 100644 --- a/apps/web/src/app/api/openrouter/[...path]/route.test.ts +++ b/apps/web/src/app/api/openrouter/[...path]/route.test.ts @@ -498,7 +498,7 @@ describe('POST /api/openrouter/v1/chat/completions rules-engine actions', () => mockedClassifyAbuse.mockResolvedValue(classifyResult(null)); mockedRedisGet.mockResolvedValue(null); mockedRedisSet.mockResolvedValue('OK'); - mockedGetOpenRouterModels.mockResolvedValue(new Set(['stepfun/step-3.7-flash:free'])); + mockedGetOpenRouterModels.mockResolvedValue(new Set(['poolside/laguna-s-2.1:free'])); mockedIsValidOpenRouterModelId.mockResolvedValue(true); mockedUpstreamRequest.mockResolvedValue({ type: 'success', @@ -871,10 +871,10 @@ describe('POST /api/openrouter/v1/chat/completions rules-engine actions', () => expect(response.status).toBe(200); expect(mockedGetProvider).toHaveBeenCalledTimes(2); expect(mockedGetProvider.mock.calls[1]?.[0].requestedModel).toBe( - stepfun_37_flash_free_model.public_id + 'poolside/laguna-s-2.1:free' ); expect(mockedUpstreamRequest.mock.calls[0]?.[0].body.model).toBe( - stepfun_37_flash_free_model.internal_id + 'poolside/laguna-s-2.1:free' ); expect(mockedAccountForMicrodollarUsage.mock.calls[0]?.[1]).toMatchObject({ abuse_delay: 6000, diff --git a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts index 1b8bcc5496..144fe0c001 100644 --- a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts +++ b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts @@ -1,12 +1,11 @@ -import { describe, expect, it, jest } from '@jest/globals'; +import { beforeEach, describe, expect, it, jest } from '@jest/globals'; jest.mock('@/lib/ai-gateway/providers/gateway-models-cache', () => ({ - getOpenRouterModelsFromDatabase: jest.fn( - async () => new Set(['poolside/laguna-s-2.1:free']) - ), + getOpenRouterModelsFromDatabase: jest.fn(), })); import { resolveAutoModel } from './resolution'; +import { getOpenRouterModelsFromDatabase } from '@/lib/ai-gateway/providers/gateway-models-cache'; import { FRONTIER_MODE_TO_MODEL, KILO_AUTO_BALANCED_MODEL, @@ -29,6 +28,7 @@ const baseParams = { const nullUserPromise = Promise.resolve(null); const zeroBalancePromise = Promise.resolve(0); const primaryDefaultFallback = { model: PRIMARY_DEFAULT_MODEL }; +const mockedGetOpenRouterModels = jest.mocked(getOpenRouterModelsFromDatabase); const sampleDecision: AutoRoutingDecision = { model: 'anthropic/claude-haiku-4', @@ -408,6 +408,10 @@ describe('resolveAutoModel — kilo-auto/efficient branch', () => { }); describe('resolveAutoModel — kilo-auto/free branch', () => { + beforeEach(() => { + mockedGetOpenRouterModels.mockResolvedValue(new Set(['poolside/laguna-s-2.1:free'])); + }); + it('excludes candidates denied by the effective organization policy', async () => { const isAutoFreeCandidateAllowed = jest.fn( async (modelId: string) => modelId === 'poolside/laguna-s-2.1:free' From 95b3c8a5606460633ec2e26cd413242705873803 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Fri, 11 Sep 2026 10:44:48 +0000 Subject: [PATCH 4/8] style(web): format Auto Free assertions Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- apps/web/src/app/api/openrouter/[...path]/route.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/web/src/app/api/openrouter/[...path]/route.test.ts b/apps/web/src/app/api/openrouter/[...path]/route.test.ts index e713666ab3..70e5a61990 100644 --- a/apps/web/src/app/api/openrouter/[...path]/route.test.ts +++ b/apps/web/src/app/api/openrouter/[...path]/route.test.ts @@ -870,12 +870,8 @@ describe('POST /api/openrouter/v1/chat/completions rules-engine actions', () => expect(response.status).toBe(200); expect(mockedGetProvider).toHaveBeenCalledTimes(2); - expect(mockedGetProvider.mock.calls[1]?.[0].requestedModel).toBe( - 'poolside/laguna-s-2.1:free' - ); - expect(mockedUpstreamRequest.mock.calls[0]?.[0].body.model).toBe( - 'poolside/laguna-s-2.1:free' - ); + expect(mockedGetProvider.mock.calls[1]?.[0].requestedModel).toBe('poolside/laguna-s-2.1:free'); + expect(mockedUpstreamRequest.mock.calls[0]?.[0].body.model).toBe('poolside/laguna-s-2.1:free'); expect(mockedAccountForMicrodollarUsage.mock.calls[0]?.[1]).toMatchObject({ abuse_delay: 6000, abuse_downgraded_from: 'openai/gpt-4o', From 1a9669ded57092f4c1dee5c731d0db4ab36154cf Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Fri, 11 Sep 2026 10:57:45 +0000 Subject: [PATCH 5/8] test(web): use Auto Free catalog mock Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts index 144fe0c001..2aee087873 100644 --- a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts +++ b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts @@ -5,7 +5,6 @@ jest.mock('@/lib/ai-gateway/providers/gateway-models-cache', () => ({ })); import { resolveAutoModel } from './resolution'; -import { getOpenRouterModelsFromDatabase } from '@/lib/ai-gateway/providers/gateway-models-cache'; import { FRONTIER_MODE_TO_MODEL, KILO_AUTO_BALANCED_MODEL, @@ -28,7 +27,9 @@ const baseParams = { const nullUserPromise = Promise.resolve(null); const zeroBalancePromise = Promise.resolve(0); const primaryDefaultFallback = { model: PRIMARY_DEFAULT_MODEL }; -const mockedGetOpenRouterModels = jest.mocked(getOpenRouterModelsFromDatabase); +const { getOpenRouterModelsFromDatabase: mockedGetOpenRouterModels } = jest.requireMock< + jest.Mocked +>('@/lib/ai-gateway/providers/gateway-models-cache'); const sampleDecision: AutoRoutingDecision = { model: 'anthropic/claude-haiku-4', From b1ad96a2932a9a00d8aa115dfcdab163cfe70598 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Fri, 11 Sep 2026 11:03:15 +0000 Subject: [PATCH 6/8] test(web): type Auto Free catalog mock Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts index 2aee087873..9855842495 100644 --- a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts +++ b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts @@ -14,6 +14,7 @@ import { } from '@/lib/ai-gateway/auto-model'; import type { AutoRoutingDecision } from '@kilocode/auto-routing-contracts'; import { PRIMARY_DEFAULT_MODEL } from '@/lib/ai-gateway/models'; +import type * as GatewayModelsCache from '@/lib/ai-gateway/providers/gateway-models-cache'; const baseParams = { model: KILO_AUTO_EFFICIENT_MODEL.id, @@ -28,7 +29,7 @@ const nullUserPromise = Promise.resolve(null); const zeroBalancePromise = Promise.resolve(0); const primaryDefaultFallback = { model: PRIMARY_DEFAULT_MODEL }; const { getOpenRouterModelsFromDatabase: mockedGetOpenRouterModels } = jest.requireMock< - jest.Mocked + jest.Mocked >('@/lib/ai-gateway/providers/gateway-models-cache'); const sampleDecision: AutoRoutingDecision = { From f7fa0418056b018458415d4a287ffd1ae113407a Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Fri, 11 Sep 2026 11:15:12 +0000 Subject: [PATCH 7/8] test(web): load resolver after catalog mock Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts index 9855842495..f29c7665d9 100644 --- a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts +++ b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts @@ -4,7 +4,7 @@ jest.mock('@/lib/ai-gateway/providers/gateway-models-cache', () => ({ getOpenRouterModelsFromDatabase: jest.fn(), })); -import { resolveAutoModel } from './resolution'; +import type * as AutoModelResolution from './resolution'; import { FRONTIER_MODE_TO_MODEL, KILO_AUTO_BALANCED_MODEL, @@ -16,6 +16,8 @@ import type { AutoRoutingDecision } from '@kilocode/auto-routing-contracts'; import { PRIMARY_DEFAULT_MODEL } from '@/lib/ai-gateway/models'; import type * as GatewayModelsCache from '@/lib/ai-gateway/providers/gateway-models-cache'; +const { resolveAutoModel } = jest.requireActual('./resolution'); + const baseParams = { model: KILO_AUTO_EFFICIENT_MODEL.id, modeHeader: null, From e48ba70a2832bde5adc6f5813e68adbd562b0147 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Fri, 11 Sep 2026 11:26:43 +0000 Subject: [PATCH 8/8] test(web): preserve cache module exports Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts index f29c7665d9..2045217e77 100644 --- a/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts +++ b/apps/web/src/lib/ai-gateway/auto-model/resolution.test.ts @@ -1,6 +1,10 @@ import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import type * as GatewayModelsCache from '@/lib/ai-gateway/providers/gateway-models-cache'; jest.mock('@/lib/ai-gateway/providers/gateway-models-cache', () => ({ + ...jest.requireActual( + '@/lib/ai-gateway/providers/gateway-models-cache' + ), getOpenRouterModelsFromDatabase: jest.fn(), })); @@ -14,7 +18,6 @@ import { } from '@/lib/ai-gateway/auto-model'; import type { AutoRoutingDecision } from '@kilocode/auto-routing-contracts'; import { PRIMARY_DEFAULT_MODEL } from '@/lib/ai-gateway/models'; -import type * as GatewayModelsCache from '@/lib/ai-gateway/providers/gateway-models-cache'; const { resolveAutoModel } = jest.requireActual('./resolution');