diff --git a/server/api/src/__tests__/agents/core/composeBackendValidation.test.ts b/server/api/src/__tests__/agents/core/composeBackendValidation.test.ts index 5595cbcc..73dee7c4 100644 --- a/server/api/src/__tests__/agents/core/composeBackendValidation.test.ts +++ b/server/api/src/__tests__/agents/core/composeBackendValidation.test.ts @@ -27,15 +27,31 @@ describe("assertComposeBackendReady", () => { expect(mockGetUserAiCredentialPlaintext).not.toHaveBeenCalled(); }); - it("allows BYOK backend without static env model provider mismatch (#972)", async () => { + it("rejects non-Google BYOK for wiki-compose-research (fixed Gemini model)", async () => { + await expect( + assertComposeBackendReady({ + backend: "user_openai", + graphId: "wiki-compose-research", + userId: "u1", + tier: "free", + db, + }), + ).rejects.toMatchObject({ + status: 400, + message: expect.stringContaining("user_google"), + }); + expect(mockGetUserAiCredentialPlaintext).not.toHaveBeenCalled(); + }); + + it("allows user_google BYOK for wiki-compose when credential exists", async () => { await assertComposeBackendReady({ - backend: "user_openai", - graphId: "wiki-compose-research", + backend: "user_google", + graphId: "wiki-compose", userId: "u1", tier: "free", db, }); - expect(mockGetUserAiCredentialPlaintext).toHaveBeenCalledWith("u1", "openai", db); + expect(mockGetUserAiCredentialPlaintext).toHaveBeenCalledWith("u1", "google", db); }); it("skips credential check for model-less graphs (wiki-maintenance)", async () => { @@ -53,7 +69,7 @@ describe("assertComposeBackendReady", () => { mockGetUserAiCredentialPlaintext.mockResolvedValue(null); await expect( assertComposeBackendReady({ - backend: "user_anthropic", + backend: "user_google", graphId: "wiki-compose-research", userId: "u1", tier: "free", diff --git a/server/api/src/__tests__/agents/core/llm/wikiComposeModelId.test.ts b/server/api/src/__tests__/agents/core/llm/wikiComposeModelId.test.ts new file mode 100644 index 00000000..f7434756 --- /dev/null +++ b/server/api/src/__tests__/agents/core/llm/wikiComposeModelId.test.ts @@ -0,0 +1,47 @@ +/** + * Tests for fixed Wiki Compose model id resolution. + * 固定 Wiki Compose モデル id 解決のテスト。 + */ +import { describe, expect, it, vi, beforeEach } from "vitest"; +import { + resolveWikiComposeModelId, + WIKI_COMPOSE_MODEL_ID, +} from "../../../../agents/core/llm/wikiComposeModelId.js"; + +const mockDb = { + select: vi.fn(), +}; + +function chainLimit(rows: unknown[]) { + const chain = { + from: vi.fn().mockReturnThis(), + where: vi.fn().mockReturnThis(), + limit: vi.fn().mockResolvedValue(rows), + }; + return chain; +} + +beforeEach(() => { + vi.clearAllMocks(); +}); + +describe("resolveWikiComposeModelId", () => { + it("returns the fixed id when the row is active and tier-accessible", async () => { + mockDb.select.mockReturnValueOnce(chainLimit([{ id: WIKI_COMPOSE_MODEL_ID }])); + const id = await resolveWikiComposeModelId("orchestrator", "free", mockDb as never); + expect(id).toBe(WIKI_COMPOSE_MODEL_ID); + }); + + it("returns the fixed id even when no DB row matches", async () => { + mockDb.select.mockReturnValueOnce(chainLimit([])); + const id = await resolveWikiComposeModelId("draft", "pro", mockDb as never); + expect(id).toBe("google:gemini-3.5-flash"); + }); + + it("uses the same id for orchestrator and draft roles", async () => { + mockDb.select.mockReturnValue(chainLimit([{ id: WIKI_COMPOSE_MODEL_ID }])); + const orchestrator = await resolveWikiComposeModelId("orchestrator", "free", mockDb as never); + const draft = await resolveWikiComposeModelId("draft", "free", mockDb as never); + expect(orchestrator).toBe(draft); + }); +}); diff --git a/server/api/src/__tests__/agents/subgraphs/research/nodes/planQueries.test.ts b/server/api/src/__tests__/agents/subgraphs/research/nodes/planQueries.test.ts index d923995e..afaa639a 100644 --- a/server/api/src/__tests__/agents/subgraphs/research/nodes/planQueries.test.ts +++ b/server/api/src/__tests__/agents/subgraphs/research/nodes/planQueries.test.ts @@ -8,6 +8,11 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const { createZediChatModel } = vi.hoisted(() => ({ createZediChatModel: vi.fn() })); +vi.mock("../../../../../agents/core/llm/wikiComposeModelId.js", () => ({ + WIKI_COMPOSE_MODEL_ID: "google:gemini-3.5-flash", + resolveWikiComposeModelId: vi.fn(async () => "google:gemini-3.5-flash"), +})); + vi.mock("../../../../../agents/core/llm/modelFactory.js", async () => { const actual = await vi.importActual< typeof import("../../../../../agents/core/llm/modelFactory.js") diff --git a/server/api/src/__tests__/agents/subgraphs/research/researchGraph.modelGuard.test.ts b/server/api/src/__tests__/agents/subgraphs/research/researchGraph.modelGuard.test.ts index 1c8f7c8b..edd3a053 100644 --- a/server/api/src/__tests__/agents/subgraphs/research/researchGraph.modelGuard.test.ts +++ b/server/api/src/__tests__/agents/subgraphs/research/researchGraph.modelGuard.test.ts @@ -15,6 +15,11 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const { createZediChatModel } = vi.hoisted(() => ({ createZediChatModel: vi.fn() })); +vi.mock("../../../../agents/core/llm/wikiComposeModelId.js", () => ({ + WIKI_COMPOSE_MODEL_ID: "google:gemini-3.5-flash", + resolveWikiComposeModelId: vi.fn(async () => "google:gemini-3.5-flash"), +})); + vi.mock("../../../../agents/core/llm/modelFactory.js", async () => { const actual = await vi.importActual< typeof import("../../../../agents/core/llm/modelFactory.js") diff --git a/server/api/src/agents/core/composeBackendValidation.ts b/server/api/src/agents/core/composeBackendValidation.ts index b2856532..ed77ad2e 100644 --- a/server/api/src/agents/core/composeBackendValidation.ts +++ b/server/api/src/agents/core/composeBackendValidation.ts @@ -2,17 +2,17 @@ * Pre-flight BYOK checks for Wiki Compose session creation (#951). * Wiki Compose セッション作成前の BYOK 事前チェック(#951)。 * - * Static env model ids are not validated here — provider matching is enforced at - * runtime via {@link resolveComposeModelId}. This function only verifies that - * the user has a stored credential when the graph will call an LLM. + * Wiki Compose uses a fixed Google model at runtime ({@link WIKI_COMPOSE_MODEL_ID}). + * Non-Google BYOK backends are rejected at session create to avoid runtime + * `BackendProviderMismatchError` in `createZediChatModel`. * - * 静的 env モデル id との provider 照合は行わない。実行時の - * `resolveComposeModelId` が provider 整合を担保する。本関数は LLM を呼ぶ - * グラフで credential が存在するかだけを確認する。 + * Wiki Compose は Google 固定モデルを使う。`user_anthropic` / `user_openai` など + * provider が合わない BYOK はセッション作成時に 400 で弾く。 */ import { HTTPException } from "hono/http-exception"; import type { Database, UserTier } from "../../types/index.js"; import { getComposeModelIdsForGraph } from "./composeModelConfig.js"; +import { isFixedWikiComposeModelGraph, WIKI_COMPOSE_MODEL_ID } from "./llm/wikiComposeModelId.js"; import { backendToCredentialProvider, isUserByokBackend, @@ -38,6 +38,12 @@ export async function assertComposeBackendReady(input: { // LLM を呼ばないグラフ(wiki-maintenance 等)は credential 不要。 if (modelIds.length === 0) return; + if (isFixedWikiComposeModelGraph(input.graphId) && input.backend !== "user_google") { + throw new HTTPException(400, { + message: `Wiki Compose requires zedi_managed or user_google backend (fixed model ${WIKI_COMPOSE_MODEL_ID})`, + }); + } + const expectedProvider = backendToCredentialProvider(input.backend); const key = await getUserAiCredentialPlaintext(input.userId, expectedProvider, input.db); if (!key?.trim()) { diff --git a/server/api/src/agents/core/composeModelConfig.ts b/server/api/src/agents/core/composeModelConfig.ts index e635bb1e..c996cfe3 100644 --- a/server/api/src/agents/core/composeModelConfig.ts +++ b/server/api/src/agents/core/composeModelConfig.ts @@ -7,13 +7,7 @@ import { WIKI_MAINTENANCE_GRAPH_ID } from "../graphs/wikiMaintenance/index.js"; import { getOrchestratorModelId } from "../subgraphs/research/nodes/planQueries.js"; import { RESEARCH_GRAPH_ID } from "../subgraphs/research/index.js"; import { INGEST_PLANNER_GRAPH_ID } from "../graphs/ingest/index.js"; - -const DRAFT_MODEL_ENV = "WIKI_COMPOSE_DRAFT_MODEL_ID"; -const DRAFT_MODEL_FALLBACK = "claude-3-5-sonnet"; - -function getDraftModelId(): string { - return process.env[DRAFT_MODEL_ENV]?.trim() || DRAFT_MODEL_FALLBACK; -} +import { WIKI_COMPOSE_MODEL_ID } from "./llm/wikiComposeModelId.js"; /** * Model row ids (`ai_models.id`) that a compose graph run will call via `createZediChatModel`. @@ -23,11 +17,12 @@ export function getComposeModelIdsForGraph(graphId: string): string[] { // Lint-only graph — no `createZediChatModel` calls; BYOK must not require orchestrator keys. if (graphId === WIKI_MAINTENANCE_GRAPH_ID) return []; if (graphId === WIKI_COMPOSE_GRAPH_ID) { - const orchestrator = getOrchestratorModelId(); - const draft = getDraftModelId(); - return orchestrator === draft ? [orchestrator] : [orchestrator, draft]; + return [WIKI_COMPOSE_MODEL_ID]; + } + if (graphId === RESEARCH_GRAPH_ID) { + return [WIKI_COMPOSE_MODEL_ID]; } - if (graphId === RESEARCH_GRAPH_ID || graphId === INGEST_PLANNER_GRAPH_ID) { + if (graphId === INGEST_PLANNER_GRAPH_ID) { return [getOrchestratorModelId()]; } return [getOrchestratorModelId()]; diff --git a/server/api/src/agents/core/llm/resolveComposeModelId.ts b/server/api/src/agents/core/llm/resolveComposeModelId.ts index 77ad8d2e..55ac9ba2 100644 --- a/server/api/src/agents/core/llm/resolveComposeModelId.ts +++ b/server/api/src/agents/core/llm/resolveComposeModelId.ts @@ -1,8 +1,8 @@ /** - * Resolve `ai_models.id` for Wiki Compose nodes so BYOK backends use a matching provider. + * Resolve `ai_models.id` for non–Wiki Compose graphs (e.g. ingest planner). + * Wiki Compose uses {@link resolveWikiComposeModelId} instead. * - * Wiki Compose の LLM ノード用 model id 解決。BYOK backend では provider が一致する - * active モデルを選び、`BackendProviderMismatchError` でセッション全体が落ちるのを防ぐ。 + * Wiki Compose 以外(ingest planner 等)向けの model id 解決。 */ import { and, asc, eq } from "drizzle-orm"; import { aiModels } from "../../../schema/index.js"; diff --git a/server/api/src/agents/core/llm/wikiComposeModelId.ts b/server/api/src/agents/core/llm/wikiComposeModelId.ts new file mode 100644 index 00000000..d72d241d --- /dev/null +++ b/server/api/src/agents/core/llm/wikiComposeModelId.ts @@ -0,0 +1,63 @@ +/** + * Fixed Wiki Compose model id (temporary until per-role / per-backend selection returns). + * Wiki Compose 用の固定モデル id(将来ロール別選択に戻すまでの暫定)。 + */ +import { and, eq } from "drizzle-orm"; +import { aiModels } from "../../../schema/index.js"; +import type { Database, UserTier } from "../../../types/index.js"; +import { WIKI_COMPOSE_GRAPH_ID } from "../../graphs/wikiCompose/index.js"; +import { RESEARCH_GRAPH_ID } from "../../subgraphs/research/index.js"; +import type { ComposeModelRole } from "./resolveComposeModelId.js"; + +/** + * `ai_models.id` used by every Wiki Compose LLM node and the `web_search` tool. + * すべての Wiki Compose LLM ノードと `web_search` ツールが使う `ai_models.id`。 + */ +export const WIKI_COMPOSE_MODEL_ID = "google:gemini-3.5-flash" as const; + +/** Graph ids that pin LLM calls to {@link WIKI_COMPOSE_MODEL_ID}. */ +export function isFixedWikiComposeModelGraph(graphId: string): boolean { + return graphId === WIKI_COMPOSE_GRAPH_ID || graphId === RESEARCH_GRAPH_ID; +} + +function tierFilter(tier: UserTier) { + if (tier === "pro") return undefined; + return eq(aiModels.tierRequired, "free"); +} + +/** + * Returns the fixed model row id when active and tier-accessible; otherwise `null`. + * `null` のとき呼び出し側はフォールバック(web_search の cheapest 探索など)へ進める。 + */ +export async function resolveActiveWikiComposeModelId( + db: Database, + tier: UserTier, +): Promise { + const tierClause = tierFilter(tier); + const [row] = await db + .select({ id: aiModels.id }) + .from(aiModels) + .where( + and( + eq(aiModels.id, WIKI_COMPOSE_MODEL_ID), + eq(aiModels.isActive, true), + ...(tierClause ? [tierClause] : []), + ), + ) + .limit(1); + return row?.id ?? null; +} + +/** + * Resolve the model row id for Wiki Compose orchestrator / draft / research nodes. + * `role` is accepted for API stability; all roles map to {@link WIKI_COMPOSE_MODEL_ID} for now. + * + * Wiki Compose の model id 解決。現時点では role に関わらず gemini-3.5-flash 固定。 + */ +export async function resolveWikiComposeModelId( + _role: ComposeModelRole, + _tier: UserTier, + db: Database, +): Promise { + return (await resolveActiveWikiComposeModelId(db, _tier)) ?? WIKI_COMPOSE_MODEL_ID; +} diff --git a/server/api/src/agents/core/tools/resolveWebSearchModel.ts b/server/api/src/agents/core/tools/resolveWebSearchModel.ts index f4ad2fe9..6709e1ad 100644 --- a/server/api/src/agents/core/tools/resolveWebSearchModel.ts +++ b/server/api/src/agents/core/tools/resolveWebSearchModel.ts @@ -5,13 +5,14 @@ * `useGoogleSearch` for Google) を呼ぶため、Anthropic-only な選択では成立しない。 * 本ヘルパは次の優先順で model を選ぶ: * - * 1. `process.env.WIKI_COMPOSE_WEB_SEARCH_MODEL_ID` (explicit override; `ai_models.id`) + * 1. {@link WIKI_COMPOSE_MODEL_ID} when active and tier-accessible + * 2. `process.env.WIKI_COMPOSE_WEB_SEARCH_MODEL_ID` (explicit override; `ai_models.id`) * — 必ず active かつ tier 通過することを DB 側で確認する(coderabbit review #956: * 不正な override で `createZediChatModel` が失敗してエラー envelope になる * のを防ぐ)。 - * 2. `ai_models` の active な OpenAI モデルで最安 (`input_cost_units` ASC, `output_cost_units` ASC) - * 3. `ai_models` の active な Google モデルで最安 - * 4. 何も無ければ `null` を返す(ツール側は empty result + note を返す)。 + * 3. `ai_models` の active な OpenAI モデルで最安 (`input_cost_units` ASC, `output_cost_units` ASC) + * 4. `ai_models` の active な Google モデルで最安 + * 5. 何も無ければ `null` を返す(ツール側は empty result + note を返す)。 * * Returns the `ai_models.id` so `createZediChatModel({ modelId })` can validate * tier access and resolve the API key uniformly. Centralising the choice in one @@ -25,6 +26,7 @@ import { and, asc, eq, inArray } from "drizzle-orm"; import { aiModels } from "../../../schema/index.js"; import type { Database, UserTier } from "../../../types/index.js"; +import { resolveActiveWikiComposeModelId } from "../llm/wikiComposeModelId.js"; const ENV_OVERRIDE = "WIKI_COMPOSE_WEB_SEARCH_MODEL_ID"; @@ -48,6 +50,9 @@ export async function resolveWebSearchModelId( db: Database, tier: UserTier, ): Promise { + const fixedId = await resolveActiveWikiComposeModelId(db, tier); + if (fixedId) return fixedId; + const override = process.env[ENV_OVERRIDE]?.trim(); if (override) { // Validate the override before returning: it must be active and diff --git a/server/api/src/agents/graphs/wikiCompose/nodes/briefDialogue.ts b/server/api/src/agents/graphs/wikiCompose/nodes/briefDialogue.ts index 263a25f6..dbd6fe14 100644 --- a/server/api/src/agents/graphs/wikiCompose/nodes/briefDialogue.ts +++ b/server/api/src/agents/graphs/wikiCompose/nodes/briefDialogue.ts @@ -16,7 +16,7 @@ import { randomUUID } from "node:crypto"; import { z } from "zod"; import { composeContentLocaleInstruction } from "../../../core/composeLocale.js"; import { createZediChatModel } from "../../../core/llm/modelFactory.js"; -import { resolveComposeModelId } from "../../../core/llm/resolveComposeModelId.js"; +import { resolveWikiComposeModelId } from "../../../core/llm/wikiComposeModelId.js"; import { getGraphContext } from "../../../subgraphs/research/nodes/shared/getGraphContext.js"; import { loadPageSnapshot } from "./shared/loadPageSnapshot.js"; import { dispatchComposePhase } from "./shared/dispatch.js"; @@ -117,7 +117,7 @@ export async function briefDialogue( // セッション開始時に 1 度だけ読み、以後は state を参照する。 const snapshot = state.pageSnapshot ?? (await loadPageSnapshot(ctx.db, ctx.pageId)); - const modelId = await resolveComposeModelId("orchestrator", ctx.backend, ctx.tier, ctx.db); + const modelId = await resolveWikiComposeModelId("orchestrator", ctx.tier, ctx.db); const model = await createZediChatModel({ modelId, userId: ctx.userId, diff --git a/server/api/src/agents/graphs/wikiCompose/nodes/draftSections.ts b/server/api/src/agents/graphs/wikiCompose/nodes/draftSections.ts index 5895cf80..212b0f54 100644 --- a/server/api/src/agents/graphs/wikiCompose/nodes/draftSections.ts +++ b/server/api/src/agents/graphs/wikiCompose/nodes/draftSections.ts @@ -15,7 +15,7 @@ import type { LangGraphRunnableConfig } from "@langchain/langgraph"; import { composeContentLocaleInstruction } from "../../../core/composeLocale.js"; import { createZediChatModel } from "../../../core/llm/modelFactory.js"; -import { resolveComposeModelId } from "../../../core/llm/resolveComposeModelId.js"; +import { resolveWikiComposeModelId } from "../../../core/llm/wikiComposeModelId.js"; import { getGraphContext } from "../../../subgraphs/research/nodes/shared/getGraphContext.js"; import { dispatchComposePhase, dispatchComposeSection } from "./shared/dispatch.js"; import type { WikiComposeStateType, WikiComposeStateUpdate } from "../state.js"; @@ -127,7 +127,7 @@ export async function draftSections( return { draftedSections: [], phase: "draft:completed" }; } - const modelId = await resolveComposeModelId("draft", ctx.backend, ctx.tier, ctx.db); + const modelId = await resolveWikiComposeModelId("draft", ctx.tier, ctx.db); const model = await createZediChatModel({ modelId, userId: ctx.userId, diff --git a/server/api/src/agents/graphs/wikiCompose/nodes/structureDialogue.ts b/server/api/src/agents/graphs/wikiCompose/nodes/structureDialogue.ts index e25af60d..24bc3225 100644 --- a/server/api/src/agents/graphs/wikiCompose/nodes/structureDialogue.ts +++ b/server/api/src/agents/graphs/wikiCompose/nodes/structureDialogue.ts @@ -19,7 +19,7 @@ import { structureDialogueFallbackOutline, } from "../../../core/composeLocale.js"; import { createZediChatModel } from "../../../core/llm/modelFactory.js"; -import { resolveComposeModelId } from "../../../core/llm/resolveComposeModelId.js"; +import { resolveWikiComposeModelId } from "../../../core/llm/wikiComposeModelId.js"; import { getGraphContext } from "../../../subgraphs/research/nodes/shared/getGraphContext.js"; import { dispatchComposePhase } from "./shared/dispatch.js"; import type { WikiComposeStateType, WikiComposeStateUpdate } from "../state.js"; @@ -83,7 +83,7 @@ export async function structureDialogue( await dispatchComposePhase({ phase: "structure", status: "entered" }, config); - const modelId = await resolveComposeModelId("orchestrator", ctx.backend, ctx.tier, ctx.db); + const modelId = await resolveWikiComposeModelId("orchestrator", ctx.tier, ctx.db); const model = await createZediChatModel({ modelId, userId: ctx.userId, diff --git a/server/api/src/agents/subgraphs/research/nodes/evaluateSufficiency.ts b/server/api/src/agents/subgraphs/research/nodes/evaluateSufficiency.ts index 536be2bb..aefb2cae 100644 --- a/server/api/src/agents/subgraphs/research/nodes/evaluateSufficiency.ts +++ b/server/api/src/agents/subgraphs/research/nodes/evaluateSufficiency.ts @@ -12,7 +12,7 @@ import type { LangGraphRunnableConfig } from "@langchain/langgraph"; import { z } from "zod"; import { composeContentLocaleInstruction } from "../../../core/composeLocale.js"; import { createZediChatModel } from "../../../core/llm/modelFactory.js"; -import { resolveComposeModelId } from "../../../core/llm/resolveComposeModelId.js"; +import { resolveWikiComposeModelId } from "../../../core/llm/wikiComposeModelId.js"; import { getGraphContext } from "./shared/getGraphContext.js"; import { dispatchResearchEvaluation } from "./shared/dispatchSseCustom.js"; import type { ResearchLoopStateType, ResearchLoopStateUpdate } from "../state.js"; @@ -72,7 +72,7 @@ export async function evaluateSufficiency( ): Promise { const ctx = getGraphContext(config); - const modelId = await resolveComposeModelId("orchestrator", ctx.backend, ctx.tier, ctx.db); + const modelId = await resolveWikiComposeModelId("orchestrator", ctx.tier, ctx.db); const model = await createZediChatModel({ modelId, userId: ctx.userId, diff --git a/server/api/src/agents/subgraphs/research/nodes/planQueries.ts b/server/api/src/agents/subgraphs/research/nodes/planQueries.ts index 33cba0d2..1e730584 100644 --- a/server/api/src/agents/subgraphs/research/nodes/planQueries.ts +++ b/server/api/src/agents/subgraphs/research/nodes/planQueries.ts @@ -16,14 +16,15 @@ import { randomUUID } from "node:crypto"; import { z } from "zod"; import { composeContentLocaleInstruction } from "../../../core/composeLocale.js"; import { createZediChatModel } from "../../../core/llm/modelFactory.js"; -import { resolveComposeModelId } from "../../../core/llm/resolveComposeModelId.js"; +import { resolveWikiComposeModelId } from "../../../core/llm/wikiComposeModelId.js"; import { getGraphContext } from "./shared/getGraphContext.js"; import { dispatchResearchIteration } from "./shared/dispatchSseCustom.js"; import type { ResearchLoopStateType, ResearchLoopStateUpdate } from "../state.js"; import type { PlannedQuery, Source } from "../types.js"; /** - * @deprecated Use {@link resolveComposeModelId} with graph context. Kept for tests importing the symbol. + * @deprecated Use {@link resolveWikiComposeModelId} for Wiki Compose graphs; kept for ingest planner BYOK preflight ({@link getComposeModelIdsForGraph}). + * Wiki Compose では {@link resolveWikiComposeModelId} を使う。ingest BYOK 事前検証用。 */ export function getOrchestratorModelId(): string { return process.env.WIKI_COMPOSE_ORCHESTRATOR_MODEL_ID?.trim() || "claude-3-5-haiku"; @@ -100,7 +101,7 @@ export async function planQueries( // maxIterations は既存 state を優先しつつ 1..5 にクランプ。 const maxIterations = clampMaxIterations(state.maxIterations ?? 3); - const modelId = await resolveComposeModelId("orchestrator", ctx.backend, ctx.tier, ctx.db); + const modelId = await resolveWikiComposeModelId("orchestrator", ctx.tier, ctx.db); const model = await createZediChatModel({ modelId, userId: ctx.userId, diff --git a/server/api/src/agents/subgraphs/research/nodes/refineQueries.ts b/server/api/src/agents/subgraphs/research/nodes/refineQueries.ts index 41fe7129..95738e13 100644 --- a/server/api/src/agents/subgraphs/research/nodes/refineQueries.ts +++ b/server/api/src/agents/subgraphs/research/nodes/refineQueries.ts @@ -10,7 +10,7 @@ import type { LangGraphRunnableConfig } from "@langchain/langgraph"; import { randomUUID } from "node:crypto"; import { composeContentLocaleInstruction } from "../../../core/composeLocale.js"; import { createZediChatModel } from "../../../core/llm/modelFactory.js"; -import { resolveComposeModelId } from "../../../core/llm/resolveComposeModelId.js"; +import { resolveWikiComposeModelId } from "../../../core/llm/wikiComposeModelId.js"; import { getGraphContext } from "./shared/getGraphContext.js"; import { dispatchResearchIteration } from "./shared/dispatchSseCustom.js"; import { planQueriesSchema } from "./planQueries.js"; @@ -62,7 +62,7 @@ export async function refineQueries( ): Promise { const ctx = getGraphContext(config); - const modelId = await resolveComposeModelId("orchestrator", ctx.backend, ctx.tier, ctx.db); + const modelId = await resolveWikiComposeModelId("orchestrator", ctx.tier, ctx.db); const model = await createZediChatModel({ modelId, userId: ctx.userId,