- {!resolvedSelectedModel && (
+ {!isModelConfigured && (
Configure `AI_GATEWAY_API_KEY` on the server to enable model access.
diff --git a/src/hooks/agent/persistent-selected-model-utils.ts b/src/hooks/agent/persistent-selected-model-utils.ts
deleted file mode 100644
index 7b8aa2e..0000000
--- a/src/hooks/agent/persistent-selected-model-utils.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import {
- isModelSelectorModel,
- isModelType,
- type ModelInfo,
- type ModelType,
-} from "@/lib/shared"
-
-const STORED_SELECTED_MODEL_VERSION = 1
-
-interface StoredSelectedModel {
- model: ModelType
- source: "user"
- version: typeof STORED_SELECTED_MODEL_VERSION
-}
-
-export function serializeStoredSelectedModel(
- model: ModelType
-): StoredSelectedModel {
- return {
- model,
- source: "user",
- version: STORED_SELECTED_MODEL_VERSION,
- }
-}
-
-export function parseStoredSelectedModel(value: unknown): ModelType | null {
- if (typeof value !== "string") {
- return null
- }
-
- if (isModelType(value) && isModelSelectorModel(value)) {
- return value
- }
-
- try {
- const parsed: unknown = JSON.parse(value)
-
- if (
- parsed &&
- typeof parsed === "object" &&
- "model" in parsed &&
- "source" in parsed &&
- "version" in parsed &&
- parsed.source === "user" &&
- parsed.version === STORED_SELECTED_MODEL_VERSION &&
- isModelType(parsed.model) &&
- isModelSelectorModel(parsed.model)
- ) {
- return parsed.model
- }
- } catch {
- return null
- }
-
- return null
-}
-
-export function resolvePersistedSelectedModel(params: {
- storedModel: ModelType | null
- currentModel: ModelType | null
- initialSelectedModel: ModelType | null | undefined
- availableModels: ModelInfo[]
-}): ModelType | null {
- const availableModelIds = new Set(
- params.availableModels
- .map((model) => model.id)
- .filter((modelId) => isModelSelectorModel(modelId))
- )
- const fallbackModel =
- params.initialSelectedModel &&
- availableModelIds.has(params.initialSelectedModel)
- ? params.initialSelectedModel
- : (params.availableModels.find((model) => availableModelIds.has(model.id))
- ?.id ?? null)
-
- if (params.storedModel && availableModelIds.has(params.storedModel)) {
- return params.storedModel
- }
-
- if (params.currentModel && availableModelIds.has(params.currentModel)) {
- return params.currentModel
- }
-
- return fallbackModel
-}
diff --git a/src/hooks/agent/use-persistent-selected-model.tsx b/src/hooks/agent/use-persistent-selected-model.tsx
deleted file mode 100644
index 28a55b1..0000000
--- a/src/hooks/agent/use-persistent-selected-model.tsx
+++ /dev/null
@@ -1,129 +0,0 @@
-"use client"
-
-import { useCallback, useEffect, useMemo, useState } from "react"
-
-import {
- MODEL_SELECTOR_STORAGE_KEY,
- MODEL_SELECTOR_UPDATED_EVENT,
-} from "@/lib/constants"
-import {
- isModelSelectorModel,
- type ModelInfo,
- type ModelType,
-} from "@/lib/shared"
-
-import {
- parseStoredSelectedModel,
- resolvePersistedSelectedModel,
- serializeStoredSelectedModel,
-} from "./persistent-selected-model-utils"
-
-function readStoredSelectedModel(): ModelType | null {
- if (typeof window === "undefined") {
- return null
- }
-
- const value = window.localStorage.getItem(MODEL_SELECTOR_STORAGE_KEY)
- return parseStoredSelectedModel(value)
-}
-
-function writeStoredSelectedModel(model: ModelType | null) {
- if (typeof window === "undefined") {
- return
- }
-
- if (model) {
- window.localStorage.setItem(
- MODEL_SELECTOR_STORAGE_KEY,
- JSON.stringify(serializeStoredSelectedModel(model))
- )
- } else {
- window.localStorage.removeItem(MODEL_SELECTOR_STORAGE_KEY)
- }
-
- window.dispatchEvent(new CustomEvent(MODEL_SELECTOR_UPDATED_EVENT))
-}
-
-export function usePersistentSelectedModel(
- initialSelectedModel: ModelType | null | undefined,
- availableModels: ModelInfo[]
-) {
- const availableModelIds = useMemo(
- () =>
- new Set(
- availableModels
- .map((model) => model.id)
- .filter((modelId) => isModelSelectorModel(modelId))
- ),
- [availableModels]
- )
-
- const fallbackModel = resolvePersistedSelectedModel({
- storedModel: null,
- currentModel: null,
- initialSelectedModel,
- availableModels,
- })
-
- const [selectedModel, setSelectedModel] = useState
(
- initialSelectedModel ?? null
- )
-
- useEffect(() => {
- const syncSelectedModel = () => {
- const storedModel = readStoredSelectedModel()
- const nextSelectedModel = resolvePersistedSelectedModel({
- storedModel,
- currentModel: selectedModel,
- initialSelectedModel,
- availableModels,
- })
-
- if (nextSelectedModel === selectedModel) {
- return
- }
-
- setSelectedModel(nextSelectedModel)
- }
-
- syncSelectedModel()
-
- const handleStorage = (event: StorageEvent) => {
- if (event.key && event.key !== MODEL_SELECTOR_STORAGE_KEY) {
- return
- }
-
- syncSelectedModel()
- }
-
- const handleModelUpdate = () => {
- syncSelectedModel()
- }
-
- window.addEventListener("storage", handleStorage)
- window.addEventListener(MODEL_SELECTOR_UPDATED_EVENT, handleModelUpdate)
-
- return () => {
- window.removeEventListener("storage", handleStorage)
- window.removeEventListener(
- MODEL_SELECTOR_UPDATED_EVENT,
- handleModelUpdate
- )
- }
- }, [availableModels, fallbackModel, initialSelectedModel, selectedModel])
-
- const persistSelectedModel = useCallback((model: ModelType | null) => {
- setSelectedModel(model)
- writeStoredSelectedModel(model)
- }, [])
-
- const resolvedSelectedModel =
- selectedModel && availableModelIds.has(selectedModel)
- ? selectedModel
- : fallbackModel
-
- return {
- selectedModel: resolvedSelectedModel,
- setSelectedModel: persistSelectedModel,
- }
-}
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 7395456..ac62a87 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -1,5 +1,2 @@
-export const MODEL_SELECTOR_STORAGE_KEY = "model-selector-state"
-export const MODEL_SELECTOR_UPDATED_EVENT = "model-selector-updated"
-
export const ASSISTANT_EMPTY_RESPONSE_FALLBACK =
"Sorry, I couldn't generate a response from that input. Please retry."
diff --git a/src/lib/server/agent-prompt-steering.ts b/src/lib/server/agent-prompt-steering.ts
index cbbfcc4..6411afb 100644
--- a/src/lib/server/agent-prompt-steering.ts
+++ b/src/lib/server/agent-prompt-steering.ts
@@ -1,6 +1,4 @@
-import type { ModelType } from "@/lib/shared"
-
-export type PromptProvider = "alibaba" | "moonshotai" | "zai"
+export type PromptProvider = "zai"
interface PromptSteeringBlock {
label: string
@@ -13,22 +11,6 @@ interface CreatePromptSteeringBlocksParams {
}
const PROVIDER_OVERLAYS: Record = {
- alibaba: `
-Use Qwen reasoning mode efficiently.
-- Take advantage of the long context window: skim and cite earlier turns before re-asking the user for information already present.
-- Prefer direct execution and verification over speculative narration.
-- On format-sensitive tasks, do a literal final-format check before finishing.
-- Treat hard word, line, and sentence caps as hard caps. Count the final output when close to the limit.
-- After tool use, synthesize the result and stop. Do not replay raw tool traces.
-`.trim(),
- moonshotai: `
-Use Kimi reasoning mode efficiently.
-- Take advantage of the long context window: skim and cite earlier turns before re-asking the user for information already present.
-- Prefer direct execution and verification over speculative narration.
-- On format-sensitive tasks, do a literal final-format check before finishing.
-- Treat hard word, line, and sentence caps as hard caps. Count the final output when close to the limit.
-- After tool use, synthesize the result and stop. Do not replay raw tool traces.
-`.trim(),
zai: `
Use GLM reasoning mode efficiently.
- Take advantage of the long context window: skim and cite earlier turns before re-asking the user for information already present.
@@ -39,20 +21,8 @@ Use GLM reasoning mode efficiently.
`.trim(),
}
-export function resolvePromptProvider(model: ModelType): PromptProvider {
- if (model.startsWith("alibaba/")) {
- return "alibaba"
- }
-
- if (model.startsWith("moonshotai/")) {
- return "moonshotai"
- }
-
- if (model.startsWith("zai/")) {
- return "zai"
- }
-
- throw new Error(`Unsupported model provider for model: ${model}`)
+export function resolvePromptProvider(): PromptProvider {
+ return "zai"
}
export function createPromptSteeringBlocks(
diff --git a/src/lib/server/agent-route.ts b/src/lib/server/agent-route.ts
index 5a84fa2..98065f0 100644
--- a/src/lib/server/agent-route.ts
+++ b/src/lib/server/agent-route.ts
@@ -9,10 +9,9 @@ import type { AgentFeatureFlags } from "@/lib/server/integration-flags"
import {
type AgentStreamEvent,
ALL_MODELS,
- MODEL_SELECTOR_MODELS,
+ DEFAULT_MODEL,
type ModelInfo,
type ModelType,
- resolveDefaultModelSelectorModel,
} from "@/lib/shared"
import {
@@ -238,7 +237,8 @@ function isAvailableModel(
models: readonly Pick[],
targetModel: ModelType
): boolean {
- return models.some((model) => model.id === targetModel)
+ const availableIds = new Set(models.map((model) => model.id))
+ return availableIds.has(targetModel)
}
function getTotalMessageChars(
@@ -314,14 +314,7 @@ export function parseAgentStreamRequest(
})
}
- const availableModelIds = new Set(
- params.availableModels.map((model) => model.id)
- )
- const chatModels = MODEL_SELECTOR_MODELS.flatMap((modelId) =>
- availableModelIds.has(modelId) ? [{ id: modelId }] : []
- )
- const selectedModelCandidate =
- parsed.data.model ?? resolveDefaultModelSelectorModel(chatModels)
+ const selectedModelCandidate = parsed.data.model ?? DEFAULT_MODEL
if (!isSupportedModel(selectedModelCandidate)) {
return createJsonErrorResponse({
@@ -332,7 +325,7 @@ export function parseAgentStreamRequest(
})
}
- if (!isAvailableModel(chatModels, selectedModelCandidate)) {
+ if (!isAvailableModel(params.availableModels, selectedModelCandidate)) {
return createJsonErrorResponse({
requestId: params.requestId,
error: "Unsupported model selected.",
diff --git a/src/lib/server/llm/agent-runtime-synthesis-gating.ts b/src/lib/server/llm/agent-runtime-synthesis-gating.ts
index bc53307..6ea25db 100644
--- a/src/lib/server/llm/agent-runtime-synthesis-gating.ts
+++ b/src/lib/server/llm/agent-runtime-synthesis-gating.ts
@@ -16,9 +16,9 @@ export function shouldNudgeMidBudgetSynthesis(
if (toolMaxSteps <= 3) {
return false
}
- // Kick in at one-third of budget. The failing 10-K tasks (e.g. Kimi K2.6)
- // tend to stop naturally with empty text after only 5-8 tool calls
- // (~steps 4-7 of 20); half-budget fires too late to reach them.
+ // Kick in at one-third of budget. The failing 10-K tasks tend to stop
+ // naturally with empty text after only 5-8 tool calls (~steps 4-7 of 20);
+ // half-budget fires too late to reach them.
const threshold = Math.max(2, Math.floor(toolMaxSteps / 3))
return stepNumber >= threshold && stepNumber < toolMaxSteps - 1
}
diff --git a/src/lib/shared/llm/models.ts b/src/lib/shared/llm/models.ts
index 7ca635c..30d5648 100644
--- a/src/lib/shared/llm/models.ts
+++ b/src/lib/shared/llm/models.ts
@@ -1,6 +1,4 @@
export const AvailableModels = {
- ALIBABA_QWEN3_7_MAX: "alibaba/qwen3.7-max",
- MOONSHOTAI_KIMI_K2_6: "moonshotai/kimi-k2.6",
ZAI_GLM_5_2: "zai/glm-5.2",
} as const
@@ -18,56 +16,14 @@ export interface ModelInfo {
name: string
}
-export const SUPPORTED_MODELS = [
- AvailableModels.ZAI_GLM_5_2,
- AvailableModels.ALIBABA_QWEN3_7_MAX,
- AvailableModels.MOONSHOTAI_KIMI_K2_6,
-] as const
+export const SUPPORTED_MODELS = [AvailableModels.ZAI_GLM_5_2] as const
export const ALL_MODELS = [...SUPPORTED_MODELS] as const
-export const MODEL_SELECTOR_MODELS = [
- AvailableModels.ZAI_GLM_5_2,
- AvailableModels.ALIBABA_QWEN3_7_MAX,
- AvailableModels.MOONSHOTAI_KIMI_K2_6,
-] as const
-
-const MODEL_SELECTOR_MODEL_SET: ReadonlySet = new Set(
- MODEL_SELECTOR_MODELS
-)
-
-export function isModelSelectorModel(value: unknown): value is ModelType {
- return (
- typeof value === "string" &&
- MODEL_SELECTOR_MODEL_SET.has(value as ModelType)
- )
-}
-
-export function getModelSelectorModels(
- models: readonly ModelInfo[]
-): ModelInfo[] {
- const modelById = new Map(models.map((model) => [model.id, model]))
- return MODEL_SELECTOR_MODELS.flatMap((modelId) => {
- const model = modelById.get(modelId)
- return model ? [model] : []
- })
-}
-
-export function resolveDefaultModelSelectorModel(
- models: readonly Pick[]
-): ModelType {
- return models[0]?.id ?? MODEL_SELECTOR_MODELS[0]
-}
+/** The single model the app runs on. */
+export const DEFAULT_MODEL: ModelType = AvailableModels.ZAI_GLM_5_2
export const ModelInfos: Record = {
- [AvailableModels.ALIBABA_QWEN3_7_MAX]: {
- id: AvailableModels.ALIBABA_QWEN3_7_MAX,
- name: "Qwen 3.7 Max",
- },
- [AvailableModels.MOONSHOTAI_KIMI_K2_6]: {
- id: AvailableModels.MOONSHOTAI_KIMI_K2_6,
- name: "Kimi K2.6",
- },
[AvailableModels.ZAI_GLM_5_2]: {
id: AvailableModels.ZAI_GLM_5_2,
name: "GLM 5.2",
diff --git a/tests/agent-context.test.mjs b/tests/agent-context.test.mjs
index 91bbf40..229a97c 100644
--- a/tests/agent-context.test.mjs
+++ b/tests/agent-context.test.mjs
@@ -103,13 +103,13 @@ test("system prompt never includes a deep research block", () => {
test("provider overlay respects its toggle", () => {
const withOverlay = buildAgentSystemInstruction(viewer, {
...baseContext,
- provider: "moonshotai",
+ provider: "zai",
})
- assert.ok(withOverlay.includes("PROVIDER OVERLAY: MOONSHOTAI"))
+ assert.ok(withOverlay.includes("PROVIDER OVERLAY: ZAI"))
const disabled = buildAgentSystemInstruction(
viewer,
- { ...baseContext, provider: "moonshotai" },
+ { ...baseContext, provider: "zai" },
{ providerOverlaysEnabled: false }
)
assert.ok(!disabled.includes("PROVIDER OVERLAY"))
diff --git a/tests/agent-follow-ups-route-behavior.test.mjs b/tests/agent-follow-ups-route-behavior.test.mjs
index 7cb26a3..5dd6278 100644
--- a/tests/agent-follow-ups-route-behavior.test.mjs
+++ b/tests/agent-follow-ups-route-behavior.test.mjs
@@ -37,7 +37,7 @@ function createRequest(overrides = {}) {
signal: AbortSignal.timeout(30_000),
json: async () => ({
assistantMessageId: "assistant-1",
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
threadId: "thread-1",
messages: [
{ role: "user", content: "Explain love" },
diff --git a/tests/agent-follow-ups.test.mjs b/tests/agent-follow-ups.test.mjs
index f89e9db..ef66dba 100644
--- a/tests/agent-follow-ups.test.mjs
+++ b/tests/agent-follow-ups.test.mjs
@@ -107,7 +107,7 @@ test("follow-up generation uses GPT-5.1 Instant and tags the source model", asyn
return {
output: {
questions: [
- "How does Kimi handle the repair-after-conflict point?",
+ "How does a couple handle the repair-after-conflict point?",
"What tradeoff matters most for commitment over time?",
"How would care over time change the recommendation?",
],
@@ -127,7 +127,7 @@ test("follow-up generation uses GPT-5.1 Instant and tags the source model", asyn
"Love includes intimacy, commitment, repair after conflict, and care over time.",
},
],
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
userId: "user-1",
})
@@ -135,7 +135,7 @@ test("follow-up generation uses GPT-5.1 Instant and tags the source model", asyn
assert.deepEqual(recordedParams?.providerOptions?.gateway?.tags, [
"feature:follow_up_questions",
"generation_model:openai/gpt-5.1-instant",
- "source_model:moonshotai/kimi-k2.6",
+ "source_model:zai/glm-5.2",
])
assert.equal(followUps.length, 3)
})
diff --git a/tests/agent-helper-behavior.test.mjs b/tests/agent-helper-behavior.test.mjs
index a85e467..ef6b026 100644
--- a/tests/agent-helper-behavior.test.mjs
+++ b/tests/agent-helper-behavior.test.mjs
@@ -122,35 +122,16 @@ test("agent helper validates total size, last-message role, and default model su
},
],
},
- availableModels: [{ id: "moonshotai/kimi-k2.6" }],
+ availableModels: [{ id: "zai/glm-5.2" }],
requestId: "request-default-mode",
})
assert(!(defaultModeResult instanceof Response))
- assert.equal(defaultModeResult.selectedModel, "moonshotai/kimi-k2.6")
-
- const defaultModeWithQwenResult = parseAgentStreamRequest({
- body: {
- messages: [
- {
- role: "user",
- content: "Use the default model.",
- },
- ],
- },
- availableModels: [
- { id: "alibaba/qwen3.7-max" },
- { id: "moonshotai/kimi-k2.6" },
- ],
- requestId: "request-default-mode-qwen",
- })
-
- assert(!(defaultModeWithQwenResult instanceof Response))
- assert.equal(defaultModeWithQwenResult.selectedModel, "alibaba/qwen3.7-max")
+ assert.equal(defaultModeResult.selectedModel, "zai/glm-5.2")
const unavailableModelResult = parseAgentStreamRequest({
body: {
- model: "alibaba/qwen3.7-max",
+ model: "zai/glm-5.2",
messages: [
{
role: "user",
@@ -158,7 +139,7 @@ test("agent helper validates total size, last-message role, and default model su
},
],
},
- availableModels: [{ id: "moonshotai/kimi-k2.6" }],
+ availableModels: [],
requestId: "request-unavailable-model",
})
@@ -180,7 +161,7 @@ test("agent helper validates total size, last-message role, and default model su
},
],
},
- availableModels: [{ id: "moonshotai/kimi-k2.6" }],
+ availableModels: [{ id: "zai/glm-5.2" }],
requestId: "request-unknown-field",
})
@@ -199,7 +180,7 @@ test("agent helper validates total size, last-message role, and default model su
content: "hello",
})),
},
- availableModels: [{ id: "moonshotai/kimi-k2.6" }],
+ availableModels: [{ id: "zai/glm-5.2" }],
requestId: "request-too-many",
})
@@ -220,7 +201,7 @@ test("agent helper validates total size, last-message role, and default model su
},
],
},
- availableModels: [{ id: "moonshotai/kimi-k2.6" }],
+ availableModels: [{ id: "zai/glm-5.2" }],
requestId: "request-message-too-large",
})
@@ -239,7 +220,7 @@ test("agent helper validates total size, last-message role, and default model su
content: `${String(index).padStart(2, "0")}${"x".repeat(10_998)}`,
})),
},
- availableModels: [{ id: "moonshotai/kimi-k2.6" }],
+ availableModels: [{ id: "zai/glm-5.2" }],
requestId: "request-1",
})
@@ -260,7 +241,7 @@ test("agent helper validates total size, last-message role, and default model su
},
],
},
- availableModels: [{ id: "moonshotai/kimi-k2.6" }],
+ availableModels: [{ id: "zai/glm-5.2" }],
requestId: "request-2",
})
@@ -308,7 +289,7 @@ test("agent helper streams fallback output when the model yields no content", as
request: createRequest(),
requestId: "request-1",
timeoutMs: 30_000,
- selectedModel: "moonshotai/kimi-k2.6",
+ selectedModel: "zai/glm-5.2",
aiGatewayApiKey: "ai-gateway-key",
tavilyApiKey: "tavily-key",
messages: [{ role: "user", content: "Hello" }],
@@ -358,7 +339,7 @@ test("agent helper marks tool-backed partial output incomplete when a tool call
request: createRequest(),
requestId: "request-unresolved-tool",
timeoutMs: 30_000,
- selectedModel: "moonshotai/kimi-k2.6",
+ selectedModel: "zai/glm-5.2",
aiGatewayApiKey: "ai-gateway-key",
tavilyApiKey: "tavily-key",
messages: [{ role: "user", content: "Search latest docs" }],
@@ -413,7 +394,7 @@ test("agent helper does not add an incomplete fallback when a meaningful answer
request: createRequest(),
requestId: "request-tool-error",
timeoutMs: 30_000,
- selectedModel: "moonshotai/kimi-k2.6",
+ selectedModel: "zai/glm-5.2",
aiGatewayApiKey: "ai-gateway-key",
tavilyApiKey: "tavily-key",
messages: [{ role: "user", content: "Search latest docs" }],
@@ -460,7 +441,7 @@ test("agent helper turns upstream body timeouts into visible timeout output", as
request: createRequest(),
requestId: "request-body-timeout",
timeoutMs: 30_000,
- selectedModel: "moonshotai/kimi-k2.6",
+ selectedModel: "zai/glm-5.2",
aiGatewayApiKey: "ai-gateway-key",
messages: [{ role: "user", content: "Latest AI news" }],
systemInstruction: "system",
@@ -506,7 +487,7 @@ test("agent helper returns an auth-key fallback when provider auth fails", async
request: createRequest(),
requestId: "request-2",
timeoutMs: 30_000,
- selectedModel: "moonshotai/kimi-k2.6",
+ selectedModel: "zai/glm-5.2",
aiGatewayApiKey: "ai-gateway-key",
messages: [{ role: "user", content: "Hello" }],
systemInstruction: "system",
diff --git a/tests/agent-route-behavior.test.mjs b/tests/agent-route-behavior.test.mjs
index 06d642c..1aa87d0 100644
--- a/tests/agent-route-behavior.test.mjs
+++ b/tests/agent-route-behavior.test.mjs
@@ -109,8 +109,8 @@ beforeEach(() => {
},
},
agentPromptSteering: {
- resolvePromptProvider(model) {
- return `provider:${model}`
+ resolvePromptProvider() {
+ return "zai"
},
},
agentRoute: {
@@ -126,7 +126,7 @@ beforeEach(() => {
parsedRequest: {
messages: body.messages,
},
- selectedModel: "moonshotai/kimi-k2.6",
+ selectedModel: "zai/glm-5.2",
}
},
createAgentStreamResponse(params) {
@@ -269,7 +269,7 @@ test("agent route passes the resolved prompt context into stream creation", asyn
context: {
now: recorded.buildInstructionCalls[0].context.now,
userTimeZone: "America/Chicago",
- provider: "provider:moonshotai/kimi-k2.6",
+ provider: "zai",
},
})
assert.deepEqual(recorded.streamCalls[0]?.messages, [
diff --git a/tests/agent-session-state.test.mjs b/tests/agent-session-state.test.mjs
index 5219318..c87fb76 100644
--- a/tests/agent-session-state.test.mjs
+++ b/tests/agent-session-state.test.mjs
@@ -70,7 +70,7 @@ test("assistant session state builds assistant messages from stream accumulators
id: "assistant-1",
createdAt: "2026-04-30T12:00:00.000Z",
accumulator,
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
isStreaming: true,
})
@@ -93,14 +93,14 @@ test("assistant session state omits empty structured fields and upserts by id",
id: "assistant-1",
createdAt: "2026-04-30T12:00:00.000Z",
accumulator: createAccumulator({ content: "Partial" }),
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
isStreaming: true,
})
const finalMessage = createAssistantMessageFromAccumulator({
id: "assistant-1",
createdAt: "2026-04-30T12:00:00.000Z",
accumulator: createAccumulator({ content: "Final" }),
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
isStreaming: false,
})
@@ -117,7 +117,7 @@ test("assistant session state attaches follow-up questions without changing cont
id: "assistant-1",
createdAt: "2026-04-30T12:00:00.000Z",
accumulator: createAccumulator({ content: "Final answer." }),
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
isStreaming: false,
})
const updatedMessages = attachFollowUpQuestionsToMessage(
@@ -148,7 +148,7 @@ test("assistant session state tracks pending follow-up questions", () => {
id: "assistant-1",
createdAt: "2026-04-30T12:00:00.000Z",
accumulator: createAccumulator({ content: "Final answer." }),
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
isStreaming: false,
})
diff --git a/tests/agent-system-prompt.test.mjs b/tests/agent-system-prompt.test.mjs
index d16d591..7326f37 100644
--- a/tests/agent-system-prompt.test.mjs
+++ b/tests/agent-system-prompt.test.mjs
@@ -50,15 +50,13 @@ test("agent system prompt composes trusted blocks in priority order", () => {
{
now: new Date("2026-05-03T12:34:56.000Z"),
userTimeZone: "America/Chicago",
- provider: "alibaba",
+ provider: "zai",
}
)
const operatingIndex = prompt.indexOf("--- BEGIN OPERATING INSTRUCTIONS ---")
const dateIndex = prompt.indexOf("--- BEGIN RUNTIME DATE CONTEXT ---")
- const providerIndex = prompt.indexOf(
- "--- BEGIN PROVIDER OVERLAY: ALIBABA ---"
- )
+ const providerIndex = prompt.indexOf("--- BEGIN PROVIDER OVERLAY: ZAI ---")
const identityIndex = prompt.indexOf(
"--- BEGIN IDENTITY AND TONE CONTEXT ---"
)
@@ -89,7 +87,7 @@ test("agent system prompt composes trusted blocks in priority order", () => {
assert.match(prompt, /Current UTC timestamp: 2026-05-03T12:34:56.000Z/)
assert.match(prompt, /User time zone: America\/Chicago/)
- assert.match(prompt, /Use Qwen reasoning mode efficiently/)
+ assert.match(prompt, /Use GLM reasoning mode efficiently/)
assert.match(prompt, /Email: user@example.com/)
assert(prompt.includes(DEFAULT_SOUL_FALLBACK_INSTRUCTION))
assert.equal(prompt.includes("SOUL.md"), false)
@@ -104,14 +102,12 @@ test("agent system prompt places the identity block after provider steering", ()
},
{
now: new Date("2026-05-03T12:34:56.000Z"),
- provider: "moonshotai",
+ provider: "zai",
}
)
const operatingIndex = prompt.indexOf("--- BEGIN OPERATING INSTRUCTIONS ---")
- const providerIndex = prompt.indexOf(
- "--- BEGIN PROVIDER OVERLAY: MOONSHOTAI ---"
- )
+ const providerIndex = prompt.indexOf("--- BEGIN PROVIDER OVERLAY: ZAI ---")
const identityIndex = prompt.indexOf(
"--- BEGIN IDENTITY AND TONE CONTEXT ---"
)
diff --git a/tests/assistant-activity-timeline.test.mjs b/tests/assistant-activity-timeline.test.mjs
index ac4d540..4faf906 100644
--- a/tests/assistant-activity-timeline.test.mjs
+++ b/tests/assistant-activity-timeline.test.mjs
@@ -45,7 +45,7 @@ test("normalizeAssistantActivityTimeline preserves streamed event order", () =>
id: "assistant-1",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
activityTimeline: [
@@ -112,7 +112,7 @@ test("normalizeAssistantActivityTimeline repairs legacy reasoning spacing from a
id: "assistant-legacy-spacing",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
reasoning:
@@ -162,7 +162,7 @@ test("normalizeAssistantActivityTimeline repairs spacing around non-BMP characte
id: "assistant-legacy-non-bmp",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
reasoning: `Review ${rocket}financial data for MSFT.`,
@@ -187,7 +187,7 @@ test("normalizeAssistantActivityTimeline skips redacted entries before aggregate
id: "assistant-redacted-repair",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
reasoning: "Visible repaired text for MSFT.",
@@ -220,7 +220,7 @@ test("normalizeAssistantActivityTimeline sanitizes private prompt terminology",
id: "assistant-private-prompt",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
activityTimeline: [
@@ -247,7 +247,7 @@ test("normalizeAssistantActivityTimeline appends missing sources after legacy fa
id: "assistant-2",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
reasoning: "Look up results",
@@ -297,7 +297,7 @@ test("normalizeAssistantActivityTimeline hides tool errors superseded by a later
id: "assistant-recovered-tool",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
activityTimeline: [
@@ -341,7 +341,7 @@ test("normalizeAssistantActivityTimeline keeps tool errors with a different oper
id: "assistant-unresolved-tool",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
activityTimeline: [
@@ -383,7 +383,7 @@ test("normalizeAssistantActivityTimeline keeps tool errors for different input q
id: "assistant-distinct-tools",
role: "assistant",
content: "",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-20T12:00:00.000Z",
metadata: {
activityTimeline: [
diff --git a/tests/follow-up-questions.test.mjs b/tests/follow-up-questions.test.mjs
index ac0ff14..e10992e 100644
--- a/tests/follow-up-questions.test.mjs
+++ b/tests/follow-up-questions.test.mjs
@@ -25,7 +25,7 @@ const {
const { AvailableModels } = await import(modelsUrl)
const { ASSISTANT_EMPTY_RESPONSE_FALLBACK } = await import(constantsUrl)
-const MODEL = AvailableModels.MOONSHOTAI_KIMI_K2_6
+const MODEL = AvailableModels.ZAI_GLM_5_2
function assistantMessage(overrides = {}) {
const { metadata = {}, ...rest } = overrides
diff --git a/tests/gateway-search-tools.test.mjs b/tests/gateway-search-tools.test.mjs
index 3199be2..97fd50e 100644
--- a/tests/gateway-search-tools.test.mjs
+++ b/tests/gateway-search-tools.test.mjs
@@ -2,24 +2,13 @@ import assert from "node:assert/strict"
import { readFile } from "node:fs/promises"
import path from "node:path"
import test from "node:test"
-import { fileURLToPath, pathToFileURL } from "node:url"
-
-import "./register-ts-path-hooks.mjs"
+import { fileURLToPath } from "node:url"
const cwd = fileURLToPath(new URL("..", import.meta.url))
const tavilyToolsPath = path.join(
cwd,
"src/lib/server/llm/ai-sdk-tavily-tools.ts"
)
-const persistentSelectedModelUrl = pathToFileURL(
- path.join(cwd, "src/hooks/agent/persistent-selected-model-utils.ts")
-).href
-
-const {
- parseStoredSelectedModel,
- resolvePersistedSelectedModel,
- serializeStoredSelectedModel,
-} = await import(persistentSelectedModelUrl)
test("tavily search tool results derive source links", async () => {
const source = await readFile(tavilyToolsPath, "utf8")
@@ -50,36 +39,3 @@ test("inline citation instructions avoid separate sources sections", async () =>
"Expected source-backed answers to rely on inline citations and Activity instead of a footer."
)
})
-
-test("stale and fallback-only model ids fall back to GLM 5.2", () => {
- assert.equal(parseStoredSelectedModel("qwen/qwen3.6-plus"), null)
- assert.equal(
- parseStoredSelectedModel(
- JSON.stringify(serializeStoredSelectedModel("openai/gpt-5.5"))
- ),
- null
- )
-
- assert.equal(
- resolvePersistedSelectedModel({
- storedModel: null,
- currentModel: null,
- initialSelectedModel: null,
- availableModels: [
- {
- id: "zai/glm-5.2",
- name: "GLM 5.2",
- },
- {
- id: "alibaba/qwen3.7-max",
- name: "Qwen 3.7 Max",
- },
- {
- id: "moonshotai/kimi-k2.6",
- name: "Kimi K2.6",
- },
- ],
- }),
- "zai/glm-5.2"
- )
-})
diff --git a/tests/home-agent-utils.test.mjs b/tests/home-agent-utils.test.mjs
index d7da8d8..c4efc80 100644
--- a/tests/home-agent-utils.test.mjs
+++ b/tests/home-agent-utils.test.mjs
@@ -76,8 +76,8 @@ test("appended user messages record the selected model", () => {
const messages = appendUserMessage(
[],
"Research Apple supply chain risk.",
- "moonshotai/kimi-k2.6"
+ "zai/glm-5.2"
)
- assert.equal(messages[0]?.metadata?.selectedModel, "moonshotai/kimi-k2.6")
+ assert.equal(messages[0]?.metadata?.selectedModel, "zai/glm-5.2")
})
diff --git a/tests/model-registry.test.mjs b/tests/model-registry.test.mjs
index 060d3ee..3eed25f 100644
--- a/tests/model-registry.test.mjs
+++ b/tests/model-registry.test.mjs
@@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url"
const cwd = fileURLToPath(new URL("..", import.meta.url))
const modelsPath = path.join(cwd, "src/lib/shared/llm/models.ts")
-test("shared model registry includes the curated gateway models", async () => {
+test("shared model registry exposes GLM 5.2 as the only model", async () => {
const source = await readFile(modelsPath, "utf8")
assert.doesNotMatch(
@@ -18,20 +18,14 @@ test("shared model registry includes the curated gateway models", async () => {
assert.doesNotMatch(
source,
- /google\/gemini-3\.1-pro-preview|xiaomi\/mimo-v2\.5-pro|GOOGLE_GEMINI_3_1_PRO_PREVIEW|XIAOMI_MIMO_V2_5_PRO|Gemini 3\.1 Pro Preview|MiMo V2\.5 Pro/,
- "Expected Gemini 3.1 Pro Preview and MiMo V2.5 Pro to be fully removed from the shared model registry."
+ /alibaba\/qwen3\.7-max|moonshotai\/kimi-k2\.6|ALIBABA_QWEN3_7_MAX|MOONSHOTAI_KIMI_K2_6|Qwen 3\.7 Max|Kimi K2\.6/,
+ "Expected Qwen 3.7 Max and Kimi K2.6 to be fully removed from the shared model registry."
)
- assert.match(
- source,
- /ALIBABA_QWEN3_7_MAX:\s*"alibaba\/qwen3\.7-max"/,
- "Expected AvailableModels to include ALIBABA_QWEN3_7_MAX."
- )
-
- assert.match(
+ assert.doesNotMatch(
source,
- /MOONSHOTAI_KIMI_K2_6:\s*"moonshotai\/kimi-k2\.6"/,
- "Expected AvailableModels to include MOONSHOTAI_KIMI_K2_6."
+ /MODEL_SELECTOR_MODELS|isModelSelectorModel|getModelSelectorModels|resolveDefaultModelSelectorModel/,
+ "Expected all model-selector helpers to be removed now that GLM 5.2 is the only model."
)
assert.match(
@@ -42,26 +36,14 @@ test("shared model registry includes the curated gateway models", async () => {
assert.match(
source.replace(/\s+/g, " "),
- /SUPPORTED_MODELS = \[ AvailableModels\.ZAI_GLM_5_2, AvailableModels\.ALIBABA_QWEN3_7_MAX, AvailableModels\.MOONSHOTAI_KIMI_K2_6, \] as const/,
- "Expected SUPPORTED_MODELS to list GLM 5.2, Qwen 3.7 Max, and Kimi K2.6."
- )
-
- assert.match(
- source.replace(/\s+/g, " "),
- /MODEL_SELECTOR_MODELS = \[ AvailableModels\.ZAI_GLM_5_2, AvailableModels\.ALIBABA_QWEN3_7_MAX, AvailableModels\.MOONSHOTAI_KIMI_K2_6, \] as const/,
- "Expected the chat model selector to default to GLM 5.2, then Qwen 3.7 Max and Kimi K2.6."
- )
-
- assert.match(
- source,
- /\[AvailableModels\.ALIBABA_QWEN3_7_MAX\]:\s*\{[\s\S]*name:\s*"Qwen 3\.7 Max"/,
- "Expected ModelInfos to define display metadata for ALIBABA_QWEN3_7_MAX."
+ /SUPPORTED_MODELS = \[AvailableModels\.ZAI_GLM_5_2\] as const/,
+ "Expected SUPPORTED_MODELS to list only GLM 5.2."
)
assert.match(
source,
- /\[AvailableModels\.MOONSHOTAI_KIMI_K2_6\]:\s*\{[\s\S]*name:\s*"Kimi K2\.6"/,
- "Expected ModelInfos to define display metadata for MOONSHOTAI_KIMI_K2_6."
+ /DEFAULT_MODEL: ModelType = AvailableModels\.ZAI_GLM_5_2/,
+ "Expected DEFAULT_MODEL to be GLM 5.2."
)
assert.match(
diff --git a/tests/prompt-form-contract.test.mjs b/tests/prompt-form-contract.test.mjs
index 758f686..a34f9f0 100644
--- a/tests/prompt-form-contract.test.mjs
+++ b/tests/prompt-form-contract.test.mjs
@@ -10,7 +10,7 @@ const promptFormPath = path.join(
"src/components/agent/prompt-form/prompt-form.tsx"
)
-test("prompt form drops the tools popover and research mode controls", async () => {
+test("prompt form drops the tools popover, research mode, and model selector controls", async () => {
const source = await readFile(promptFormPath, "utf8")
assert.doesNotMatch(
@@ -18,9 +18,9 @@ test("prompt form drops the tools popover and research mode controls", async ()
/runMode|usePersistentRunMode|Research|Telescope|Popover|setIsToolsOpen/,
"Expected PromptForm to drop the Tools popover and Research mode controls."
)
- assert.match(
+ assert.doesNotMatch(
source,
- / {
const normalizedThread = prepareThreadForPersistence({
id: "thread-persist",
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
messages: [
createMessage({
createdAt: "2026-04-15T09:59:00.000Z",
diff --git a/tests/thread-payload-contract.test.mjs b/tests/thread-payload-contract.test.mjs
index 2b7a9a6..5a1e06d 100644
--- a/tests/thread-payload-contract.test.mjs
+++ b/tests/thread-payload-contract.test.mjs
@@ -37,7 +37,7 @@ test("thread payload sanitizes private prompt terminology in reasoning", () => {
id: "message-1",
role: "assistant",
content: "Done.",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-26T00:00:00.000Z",
metadata: {
reasoning: "Use SOUL.md and the system prompt.",
@@ -76,7 +76,7 @@ test("thread payload truncates sanitized activity reasoning to the schema limit"
id: "message-1",
role: "assistant",
content: "Done.",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-26T00:00:00.000Z",
metadata: {
activityTimeline: [
@@ -126,16 +126,16 @@ test("thread store delegates parsing and persistence shaping to the payload help
test("thread payload drops legacy run-mode metadata from stored threads", () => {
const parsed = parseThreadPayload({
id: "thread-1",
- model: "alibaba/qwen3.7-max",
+ model: "zai/glm-5.2",
messages: [
{
id: "message-1",
role: "user",
content: "Research this.",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-26T00:00:00.000Z",
metadata: {
- selectedModel: "moonshotai/kimi-k2.6",
+ selectedModel: "zai/glm-5.2",
runMode: "research",
},
},
@@ -144,9 +144,6 @@ test("thread payload drops legacy run-mode metadata from stored threads", () =>
updatedAt: "2026-04-26T00:00:01.000Z",
})
- assert.equal(
- parsed.messages[0]?.metadata?.selectedModel,
- "moonshotai/kimi-k2.6"
- )
+ assert.equal(parsed.messages[0]?.metadata?.selectedModel, "zai/glm-5.2")
assert.equal(parsed.messages[0]?.metadata?.runMode, undefined)
})
diff --git a/tests/threads-route-behavior.test.mjs b/tests/threads-route-behavior.test.mjs
index d5b555a..ae689ac 100644
--- a/tests/threads-route-behavior.test.mjs
+++ b/tests/threads-route-behavior.test.mjs
@@ -201,7 +201,7 @@ test("threads GET returns a full thread when an id is requested", async () => {
id: "message-1",
role: "user",
content: "Open the thread",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-15T10:00:00.000Z",
},
],
diff --git a/tests/threads-store-behavior.test.mjs b/tests/threads-store-behavior.test.mjs
index ceded72..fbfbaec 100644
--- a/tests/threads-store-behavior.test.mjs
+++ b/tests/threads-store-behavior.test.mjs
@@ -34,7 +34,7 @@ function createStoredMessage(overrides = {}) {
id: "message-1",
role: "user",
content: "Stored thread message",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-15T10:00:00.000Z",
...overrides,
}
@@ -43,7 +43,7 @@ function createStoredMessage(overrides = {}) {
function createStoredRow(overrides = {}) {
return {
id: "thread-1",
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
messages: [createStoredMessage()],
createdAt: "2026-04-15T10:00:00.000Z",
updatedAt: "2026-04-15T10:05:00.000Z",
@@ -140,7 +140,7 @@ test("listThreadSummariesForUser avoids selecting message payloads", async () =>
{
id: "summary-thread",
title: "Stored summary",
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
createdAt: "2026-04-15T10:00:00.000Z",
updatedAt: "2026-04-15T10:05:00.000Z",
},
@@ -156,7 +156,7 @@ test("listThreadSummariesForUser avoids selecting message payloads", async () =>
{
id: "summary-thread",
title: "Stored summary",
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
createdAt: "2026-04-15T10:00:00.000Z",
updatedAt: "2026-04-15T10:05:00.000Z",
},
@@ -177,7 +177,7 @@ test("listThreadSummariesForUser skips invalid summary rows", async () => {
{
id: "invalid-summary",
title: "Stored summary",
- model: "moonshotai/kimi-k2.6",
+ model: "zai/glm-5.2",
createdAt: "not-a-date",
updatedAt: "2026-04-15T10:05:00.000Z",
},
@@ -254,7 +254,7 @@ test("upsertThreadForUser normalizes the persisted thread and shapes SQL values"
id: "message-upsert",
role: "user",
content: " Derive my title from the first message ",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-15T09:59:00.000Z",
},
],
@@ -285,7 +285,7 @@ test("upsertThreadForUser normalizes the persisted thread and shapes SQL values"
id: "message-upsert",
role: "user",
content: " Derive my title from the first message ",
- llmModel: "moonshotai/kimi-k2.6",
+ llmModel: "zai/glm-5.2",
createdAt: "2026-04-15T09:59:00.000Z",
},
])