Skip to content

fix(api): pin Wiki Compose LLM to google:gemini-3.5-flash#990

Merged
otomatty merged 3 commits into
developfrom
cursor/wiki-compose-gemini-model-0d93
May 27, 2026
Merged

fix(api): pin Wiki Compose LLM to google:gemini-3.5-flash#990
otomatty merged 3 commits into
developfrom
cursor/wiki-compose-gemini-model-0d93

Conversation

@otomatty

@otomatty otomatty commented May 26, 2026

Copy link
Copy Markdown
Owner

Summary

Wiki Compose のすべての LLM 呼び出し(Brief / 調査 / 構成 / 執筆)と web_search ツールが、固定の ai_models.id google:gemini-3.5-flash を使うように変更しました。ロール(orchestrator / draft)や実行 backend によるモデル切り替えは現時点では行いません。

Changes

  • 新規 wikiComposeModelId.ts: WIKI_COMPOSE_MODEL_IDresolveWikiComposeModelId()
  • Wiki Compose 各ノード・調査サブグラフを resolveWikiComposeModelId に切り替え
  • web_search は固定モデルを最優先で解決
  • composeModelConfig の wiki-compose / wiki-compose-research は単一モデル id のみ返す
  • ingest planner は従来どおり resolveComposeModelId(変更なし)

Ops note

本番・開発 DB の ai_modelsgoogle:gemini-3.5-flashis_active = true で登録されている必要があります。未登録の場合は従来どおり Model not found or inactive になります。管理画面のモデル同期、または GOOGLE_MODEL_IDSgemini-3.5-flash を含めて sync:ai-models を実行してください。

Testing

  • server/api: wikiComposeModelId.test.ts, wiki compose / research 関連 Vitest(42 tests)
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Wiki Compose and related research flows now consistently use a single fixed model at runtime.
    • Session validation now rejects non-Google BYOK backends for Wiki Compose graphs.
  • Removed

    • Draft-model environment override for Wiki Compose selection.
  • Behavior Changes

    • Web-search model selection now prioritizes the fixed Wiki Compose model when available.
  • Tests

    • Added tests for model resolution, BYOK validation, and routing across compose/research flows.
  • Documentation

    • Updated docs to describe the fixed model behavior and BYOK pre-flight checks.

Review Change Stack

Wiki Compose orchestrator, research, draft, and web_search now resolve
a single fixed ai_models.id (google:gemini-3.5-flash) instead of
provider-specific fallbacks. Ingest planner keeps resolveComposeModelId.

Co-authored-by: Akimasa Sugai <otomatty@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8db73c8e-ba33-4b86-9dee-521ea3fe8652

📥 Commits

Reviewing files that changed from the base of the PR and between 0d86d53 and c1a6d53.

📒 Files selected for processing (1)
  • server/api/src/agents/core/tools/resolveWebSearchModel.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/api/src/agents/core/tools/resolveWebSearchModel.ts

📝 Walkthrough

Walkthrough

Adds a fixed Wiki Compose model id and resolver with tier-aware DB lookup, migrates wiki and research nodes to use the wiki resolver, prioritizes the fixed model for web-search selection, and enforces BYOK runtime checks with new tests.

Changes

Wiki Compose Fixed Model ID Resolution

Layer / File(s) Summary
Wiki Compose model ID resolver and tests
server/api/src/agents/core/llm/wikiComposeModelId.ts, server/api/src/__tests__/agents/core/llm/wikiComposeModelId.test.ts
New WIKI_COMPOSE_MODEL_ID constant and resolver that queries ai_models for active, tier-accessible rows and falls back to the fixed model id; includes tier filtering and tests validating lookup, fallback, and role consistency.
Model configuration and documentation updates
server/api/src/agents/core/composeModelConfig.ts, server/api/src/agents/core/llm/resolveComposeModelId.ts
Import of WIKI_COMPOSE_MODEL_ID, removal of the draft-model env override and helper, and updated JSDoc to clarify non-Wiki compose resolver scope.
BYOK runtime validation and tests
server/api/src/agents/core/composeBackendValidation.ts, server/api/src/__tests__/agents/core/composeBackendValidation.test.ts
Docs updated and runtime check added to reject non-user_google BYOK for fixed Wiki Compose graphs; tests added/adjusted to cover rejection and allowed credential lookup behavior.
Web search model prioritization
server/api/src/agents/core/tools/resolveWebSearchModel.ts
resolveWebSearchModelId now checks for an active/tier-accessible WIKI_COMPOSE_MODEL_ID first, then validates env override, then falls back to cheapest OpenAI/Google model; tier predicate is reused.
Wiki Compose graph nodes migration
server/api/src/agents/graphs/wikiCompose/nodes/briefDialogue.ts, server/api/src/agents/graphs/wikiCompose/nodes/draftSections.ts, server/api/src/agents/graphs/wikiCompose/nodes/structureDialogue.ts
Nodes switch to resolveWikiComposeModelId and update calls to (role, ctx.tier, ctx.db) enabling fixed-model resolution with tier access checks.
Research subgraph nodes migration and test mocks
server/api/src/agents/subgraphs/research/nodes/evaluateSufficiency.ts, server/api/src/agents/subgraphs/research/nodes/planQueries.ts, server/api/src/agents/subgraphs/research/nodes/refineQueries.ts, server/api/src/__tests__/agents/subgraphs/research/nodes/planQueries.test.ts, server/api/src/__tests__/agents/subgraphs/research/researchGraph.modelGuard.test.ts
Research nodes switch to resolveWikiComposeModelId with updated arguments; tests add Vitest mocks for deterministic wiki-compose model id resolution during test runs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • otomatty/zedi#956: Overlaps on web-search model resolution and precedence logic.
  • otomatty/zedi#974: Related BYOK/session and model-selection changes touching compose backend validation and web-search resolver.

Poem

🐰 A fixed model shines so bright,
Tier checks steady through the night,
DB peeks then falls back kind,
One resolver clears the mind—
Drafts and tests now hop in light.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: pinning Wiki Compose LLM calls to a fixed Google Gemini model instead of dynamic resolution.
Docstring Coverage ✅ Passed Docstring coverage is 84.62% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/wiki-compose-gemini-model-0d93

Comment @coderabbitai help to get the list of available commands and usage tips.

@otomatty otomatty marked this pull request as ready for review May 26, 2026 23:50
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request pins the Wiki Compose model to a fixed Google model (google:gemini-3.5-flash) across various graphs and nodes, including orchestrator, draft, research, and web search tools. The feedback recommends updating the BYOK pre-flight validation to reject non-Google BYOK backends early, preventing runtime crashes due to provider mismatches. Additionally, it is suggested to extract the duplicated database query logic for resolving the active and accessible fixed model ID into a shared helper function to improve maintainability.

Comment on lines +5 to +10
* Wiki Compose uses a fixed Google model at runtime ({@link WIKI_COMPOSE_MODEL_ID}).
* BYOK sessions still need a stored credential when the graph calls an LLM; provider
* alignment with the fixed model is the caller's responsibility for now.
*
* 静的 env モデル id との provider 照合は行わない。実行時の
* `resolveComposeModelId` が provider 整合を担保する。本関数は LLM を呼ぶ
* グラフで credential が存在するかだけを確認する。
* Wiki Compose は実行時に Google 固定モデルを使う。BYOK 時は LLM 呼び出し前に
* credential の有無だけをここで確認する。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Since Wiki Compose is now pinned to google:gemini-3.5-flash (via WIKI_COMPOSE_MODEL_ID), any BYOK backend other than google_byok (e.g., anthropic_byok or openai_byok) will pass this pre-flight check but fail at runtime with a BackendProviderMismatchError when createZediChatModel is called.

To prevent runtime crashes and provide a clear error message, we should update assertComposeBackendReady to reject non-Google BYOK backends when the graph uses WIKI_COMPOSE_MODEL_ID:

export async function assertComposeBackendReady(input: {
  backend: ExecutionBackend;
  graphId: string;
  userId: string;
  tier: UserTier;
  db: Database;
}): Promise<void> {
  if (!isUserByokBackend(input.backend)) return;

  const modelIds = getComposeModelIdsForGraph(input.graphId);
  if (modelIds.length === 0) return;

  const expectedProvider = backendToCredentialProvider(input.backend);

  // Reject non-Google BYOK backends early for Wiki Compose
  if (modelIds.includes(WIKI_COMPOSE_MODEL_ID) && expectedProvider !== "google") {
    throw new HTTPException(400, {
      message: `Wiki Compose is currently pinned to Google models. Backend "${input.backend}" is incompatible.`,
    });
  }

  const key = await getUserAiCredentialPlaintext(input.userId, expectedProvider, input.db);
  if (!key?.trim()) {
    throw new HTTPException(400, {
      message: `No API credential configured for backend "${input.backend}"`,
    });
  }
}

Comment on lines +26 to +40
async function fixedModelIdIfAccessible(db: Database, tier: UserTier): Promise<string> {
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 ?? WIKI_COMPOSE_MODEL_ID;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The database query to resolve the active and accessible fixed model ID is duplicated in resolveWebSearchModel.ts. We can extract this query into a shared helper function resolveActiveWikiComposeModelId to improve maintainability and reuse it across both files.

export async function resolveActiveWikiComposeModelId(
  db: Database,
  tier: UserTier,
): Promise<string | null> {
  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;
}

async function fixedModelIdIfAccessible(db: Database, tier: UserTier): Promise<string> {
  return (await resolveActiveWikiComposeModelId(db, tier)) ?? WIKI_COMPOSE_MODEL_ID;
}

import { and, asc, eq, inArray } from "drizzle-orm";
import { aiModels } from "../../../schema/index.js";
import type { Database, UserTier } from "../../../types/index.js";
import { WIKI_COMPOSE_MODEL_ID } from "../llm/wikiComposeModelId.js";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Import the newly extracted resolveActiveWikiComposeModelId helper from wikiComposeModelId.ts.

Suggested change
import { WIKI_COMPOSE_MODEL_ID } from "../llm/wikiComposeModelId.js";
import { WIKI_COMPOSE_MODEL_ID, resolveActiveWikiComposeModelId } from "../llm/wikiComposeModelId.js";

Comment on lines +53 to +65
const tierClause = tierFilter(tier);
const [fixedRow] = 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);
if (fixedRow) return fixedRow.id;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Reuse the extracted resolveActiveWikiComposeModelId helper to avoid duplicating the database query logic.

  const fixedId = await resolveActiveWikiComposeModelId(db, tier);
  if (fixedId) return fixedId;

  const tierClause = tierFilter(tier);

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fc279f36b4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +48 to +53
export async function resolveWikiComposeModelId(
_role: ComposeModelRole,
_tier: UserTier,
db: Database,
): Promise<string> {
return fixedModelIdIfAccessible(db, _tier);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject incompatible BYOK backends before pinning model

resolveWikiComposeModelId now always resolves to google:gemini-3.5-flash regardless of the session backend, so user_openai / user_anthropic sessions can still be created but will fail at runtime when createZediChatModel enforces provider/backend matching (BackendProviderMismatchError). This is a regression from the previous backend-aware resolution path and will break valid BYOK users unless backend compatibility is checked up front or model resolution is backend-aware again.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/api/src/__tests__/agents/core/llm/wikiComposeModelId.test.ts`:
- Around line 1-3: The file header comment currently only contains English;
update the top-of-file comment block in wikiComposeModelId.test.ts to include a
concise Japanese equivalent (e.g., translate "Tests for fixed Wiki Compose model
id resolution" into Japanese) so the header is bilingual; ensure the Japanese
text appears alongside the existing English in the same comment block at the
very top of the file.

In `@server/api/src/agents/subgraphs/research/nodes/planQueries.ts`:
- Around line 26-27: The JSDoc deprecation comment for the function referencing
resolveWikiComposeModelId and getComposeModelIdsForGraph is English-only; add a
Japanese translation immediately below the English sentence within the same
JSDoc block so both languages appear (e.g., duplicate the deprecation sentence
in Japanese after “@deprecated Use {`@link` resolveWikiComposeModelId} for Wiki
Compose graphs. Kept for ingest planner BYOK preflight ({`@link`
getComposeModelIdsForGraph}).”), keeping the same tags and formatting and
ensuring the Japanese text clearly conveys the same deprecation and usage
guidance.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6d5494fa-0989-49c0-acff-d3c121204e97

📥 Commits

Reviewing files that changed from the base of the PR and between 502c0b8 and fc279f3.

📒 Files selected for processing (14)
  • server/api/src/__tests__/agents/core/llm/wikiComposeModelId.test.ts
  • server/api/src/__tests__/agents/subgraphs/research/nodes/planQueries.test.ts
  • server/api/src/__tests__/agents/subgraphs/research/researchGraph.modelGuard.test.ts
  • server/api/src/agents/core/composeBackendValidation.ts
  • server/api/src/agents/core/composeModelConfig.ts
  • server/api/src/agents/core/llm/resolveComposeModelId.ts
  • server/api/src/agents/core/llm/wikiComposeModelId.ts
  • server/api/src/agents/core/tools/resolveWebSearchModel.ts
  • server/api/src/agents/graphs/wikiCompose/nodes/briefDialogue.ts
  • server/api/src/agents/graphs/wikiCompose/nodes/draftSections.ts
  • server/api/src/agents/graphs/wikiCompose/nodes/structureDialogue.ts
  • server/api/src/agents/subgraphs/research/nodes/evaluateSufficiency.ts
  • server/api/src/agents/subgraphs/research/nodes/planQueries.ts
  • server/api/src/agents/subgraphs/research/nodes/refineQueries.ts

Comment thread server/api/src/__tests__/agents/core/llm/wikiComposeModelId.test.ts
Comment thread server/api/src/agents/subgraphs/research/nodes/planQueries.ts Outdated
- assertComposeBackendReady: only zedi_managed or user_google for wiki-compose graphs
- Export resolveActiveWikiComposeModelId; reuse in web_search resolver
- Address review: bilingual JSDoc, BYOK preflight tests

Co-authored-by: Akimasa Sugai <otomatty@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/api/src/agents/core/llm/wikiComposeModelId.ts`:
- Around line 18-21: The JSDoc for isFixedWikiComposeModelGraph is English-only;
update the exported JSDoc comment above the function to include a concise
Japanese translation alongside the existing English text (matching the file's
bilingual style). Keep the same description and reference to
WIKI_COMPOSE_MODEL_ID, and ensure the Japanese sentence clearly states the same
purpose (that the function checks graph ids pinned to WIKI_COMPOSE_MODEL_ID);
leave the function and constants (WIKI_COMPOSE_GRAPH_ID, RESEARCH_GRAPH_ID)
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5afa5656-7cb0-4654-8f97-40e13712a7df

📥 Commits

Reviewing files that changed from the base of the PR and between fc279f3 and 0d86d53.

📒 Files selected for processing (6)
  • server/api/src/__tests__/agents/core/composeBackendValidation.test.ts
  • server/api/src/__tests__/agents/core/llm/wikiComposeModelId.test.ts
  • server/api/src/agents/core/composeBackendValidation.ts
  • server/api/src/agents/core/llm/wikiComposeModelId.ts
  • server/api/src/agents/core/tools/resolveWebSearchModel.ts
  • server/api/src/agents/subgraphs/research/nodes/planQueries.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • server/api/src/agents/subgraphs/research/nodes/planQueries.ts
  • server/api/src/tests/agents/core/llm/wikiComposeModelId.test.ts
  • server/api/src/agents/core/tools/resolveWebSearchModel.ts

Comment on lines +18 to +21
/** 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;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add Japanese text to this exported JSDoc block for guideline compliance.

Line 18 currently has English-only documentation while this file otherwise follows bilingual EN/JA comments.

Proposed fix
-/** Graph ids that pin LLM calls to {`@link` WIKI_COMPOSE_MODEL_ID}. */
+/**
+ * Graph ids that pin LLM calls to {`@link` WIKI_COMPOSE_MODEL_ID}.
+ * LLM 呼び出しを {`@link` WIKI_COMPOSE_MODEL_ID} に固定する graph id。
+ */
 export function isFixedWikiComposeModelGraph(graphId: string): boolean {
   return graphId === WIKI_COMPOSE_GRAPH_ID || graphId === RESEARCH_GRAPH_ID;
 }

As per coding guidelines "Include both Japanese and English comments/documentation in code and documentation files to maintain project tone consistency".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/api/src/agents/core/llm/wikiComposeModelId.ts` around lines 18 - 21,
The JSDoc for isFixedWikiComposeModelGraph is English-only; update the exported
JSDoc comment above the function to include a concise Japanese translation
alongside the existing English text (matching the file's bilingual style). Keep
the same description and reference to WIKI_COMPOSE_MODEL_ID, and ensure the
Japanese sentence clearly states the same purpose (that the function checks
graph ids pinned to WIKI_COMPOSE_MODEL_ID); leave the function and constants
(WIKI_COMPOSE_GRAPH_ID, RESEARCH_GRAPH_ID) unchanged.

Co-authored-by: Akimasa Sugai <otomatty@users.noreply.github.com>
@otomatty otomatty merged commit 5d28c99 into develop May 27, 2026
18 checks passed
@otomatty otomatty deleted the cursor/wiki-compose-gemini-model-0d93 branch May 27, 2026 04:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants