Skip to content

feat(models): add gemini-3.1-flash-lite-image - #2862

Closed
analogpvt wants to merge 3 commits into
theopenco:mainfrom
analogpvt:gemini-aistudio-models
Closed

analogpvt wants to merge 3 commits into
theopenco:mainfrom
analogpvt:gemini-aistudio-models

Conversation

@analogpvt

@analogpvt analogpvt commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Adds the new gemini-3.1-flash-lite-image model configuration with AI Studio and Vertex Express Mode authentication, and restricts its resolution to 1K in the playground.

Summary by CodeRabbit

  • New Features
    • Added support for the Gemini 3.1 Flash Lite Image model across chat and playground experiences.
    • Image generation for this model now offers only the 1K resolution option.
    • Improved support for Google Vertex Express Mode endpoints when using compatible API keys.
  • Bug Fixes
    • Updated image billing/cost attribution and image-capability checks to include the new model.
  • Tests
    • Added coverage for Express Mode endpoint behavior.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@analogpvt, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 39 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: baa5b926-2e34-4736-8e7a-589ab2b6b16a

📥 Commits

Reviewing files that changed from the base of the PR and between 2ef2600 and 6d4ae6c.

📒 Files selected for processing (1)
  • apps/docs/content/features/video-generation.mdx

Walkthrough

Adds the gemini-3.1-flash-lite-image model, wires it into gateway billing and playground image-size selection, and adds Vertex Express Mode handling for AQ.-prefixed tokens.

Changes

Gemini 3.1 Flash Lite Image

Layer / File(s) Summary
Model definition
packages/models/src/models/google.ts
Adds gemini-3.1-flash-lite-image to googleModels with image output, resolution-based image token pricing, contextSize: 65536, maxOutput: 4096, and provider capability fields.
Gateway billing and audio-capability wiring
apps/gateway/src/chat/chat.ts, apps/gateway/src/chat/tools/messages-contain-audio.spec.ts
Extends image counting for gemini-3.1-flash-lite-image and adds it to the image-only audio-capability test list.
Playground size selection
apps/playground/src/components/playground/chat-ui.tsx, apps/playground/src/lib/image-gen.ts
Adds gemini-3.1-flash-lite-image detection in chat UI and image-gen config so available sizes resolve to ["1K"].

Vertex Express Mode Endpoint

Layer / File(s) Summary
Express Mode endpoint construction and test
packages/actions/src/get-provider-endpoint.ts, packages/actions/src/get-provider-endpoint.spec.ts
buildVertexCompatibleEndpoint now returns a /v1/publishers/google/models/... endpoint with key and alt=sse query parameters for AQ.-prefixed tokens, and the spec asserts that format.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • smakosh
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding the gemini-3.1-flash-lite-image model.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@analogpvt
analogpvt force-pushed the gemini-aistudio-models branch from 9bc4ccb to 29c59c1 Compare June 30, 2026 17:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
apps/gateway/src/videos/videos.spec.ts (1)

1615-1670: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add one Mini reference-video billing case.

This test only locks the output-rate path. The new docs also promise a reference_videos surcharge for seedance-2-0-mini, so a regression in videoInputCost would still pass here. Please add one request with reference_videos and assert the billed input cost too.

🤖 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 `@apps/gateway/src/videos/videos.spec.ts` around lines 1615 - 1670, The
Seedance 2.0 Mini billing test only covers output pricing, so it can miss
regressions in the new reference-video surcharge path. Update the existing
bytedance/seedance-2-0-mini case in videos.spec.ts to add a request that
includes reference_videos, then verify the resulting videoJob/log billing
includes the expected videoInputCost as well as the existing videoOutputCost.
Use the same app.request, processPendingVideoJobs, and db query patterns already
in the test to locate the affected billing assertions.
🤖 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 `@apps/docs/content/features/video-generation.mdx`:
- Line 16: The shared Seedance capability summary still groups Seedance 2.0 Mini
with the 720p/1080p, 5s/10s models, which no longer matches the constraints in
bytedance model definitions. Update the documentation entry in
video-generation.mdx to give Seedance 2.0 Mini its own bullet/row and list its
actual supported settings (480p and 4–15s), while keeping the other Seedance
variants in the shared summary. Use the existing Seedance 2.0 / Seedance 2.0
Fast / Seedance 1.5 Pro wording as the anchor for the split.

In `@apps/playground/src/components/playground/chat-ui.tsx`:
- Around line 1055-1061: The availableSizes change in chat-ui only updates the
dropdown options and leaves an already-selected unsupported imageSize intact
when switching to gemini-3.1-flash-lite-image. Update the model-switching logic
around the image size state in playground/chat-ui.tsx so that when
isGemini31FlashLiteImage becomes true, the current imageSize is clamped or reset
to "1K" if it is not allowed. Use the existing availableSizes logic and the
imageSize state handler in the chat UI to ensure submitted sizes always match
the active model.

In `@packages/actions/src/get-provider-endpoint.spec.ts`:
- Around line 216-221: The test fixture in get-provider-endpoint.spec.ts is
using an AQ token that resembles a real credential; replace the hardcoded token
in the endpoint assertion setup with an obviously fake value like AQ.test-token.
Keep the same test path and branch coverage in getProviderEndpoint while
updating the expected URL string to match the fake token.

In `@packages/actions/src/get-provider-endpoint.ts`:
- Around line 49-55: The Vertex Express Mode URL builder in getProviderEndpoint
currently interpolates the token directly into the query string, which can break
when AQ.-prefixed keys contain reserved characters. Update the URL construction
in getProviderEndpoint to use URL and URLSearchParams for the token-based
branch, and apply the same fix to the other Vertex branches that use
key=${token} so the key value is encoded consistently.

---

Nitpick comments:
In `@apps/gateway/src/videos/videos.spec.ts`:
- Around line 1615-1670: The Seedance 2.0 Mini billing test only covers output
pricing, so it can miss regressions in the new reference-video surcharge path.
Update the existing bytedance/seedance-2-0-mini case in videos.spec.ts to add a
request that includes reference_videos, then verify the resulting videoJob/log
billing includes the expected videoInputCost as well as the existing
videoOutputCost. Use the same app.request, processPendingVideoJobs, and db query
patterns already in the test to locate the affected billing assertions.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0a941616-0807-426c-b7ce-482a85b2c4ff

📥 Commits

Reviewing files that changed from the base of the PR and between 3701059 and 9bc4ccb.

📒 Files selected for processing (14)
  • apps/docs/content/features/video-generation.mdx
  • apps/gateway/src/chat/chat.ts
  • apps/gateway/src/chat/tools/messages-contain-audio.spec.ts
  • apps/gateway/src/test-utils/mock-openai-server.ts
  • apps/gateway/src/videos/videos.spec.ts
  • apps/gateway/src/videos/videos.ts
  • apps/playground/src/components/playground/chat-ui.tsx
  • apps/playground/src/lib/image-gen.ts
  • apps/playground/src/lib/video-gen.spec.ts
  • apps/playground/src/lib/video-gen.ts
  • packages/actions/src/get-provider-endpoint.spec.ts
  • packages/actions/src/get-provider-endpoint.ts
  • packages/models/src/models/bytedance.ts
  • packages/models/src/models/google.ts

@@ -13,7 +13,8 @@ LLMGateway supports asynchronous video generation through an OpenAI-compatible `
Currently available models:

- **Veo 3.1** through `avalanche` (1080p, 4k) and `google-vertex` (720p, 1080p, 4k)
- **Seedance 2.0**, **Seedance 2.0 Fast**, and **Seedance 1.5 Pro** through `bytedance` (720p, 1080p)
- **Seedance 2.0**, **Seedance 2.0 Fast**, **Seedance 2.0 Mini**, and **Seedance 1.5 Pro** through `bytedance` (720p, 1080p)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Split Seedance 2.0 Mini out of the shared capability summary.

These lines still describe Mini as a 720p/1080p, 5s/10s model, but packages/models/src/models/bytedance.ts now allows 480p and 4–15s for seedance-2-0-mini. Please give Mini its own bullet/row so the docs match the actual request constraints.

Also applies to: 52-57

🤖 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 `@apps/docs/content/features/video-generation.mdx` at line 16, The shared
Seedance capability summary still groups Seedance 2.0 Mini with the 720p/1080p,
5s/10s models, which no longer matches the constraints in bytedance model
definitions. Update the documentation entry in video-generation.mdx to give
Seedance 2.0 Mini its own bullet/row and list its actual supported settings
(480p and 4–15s), while keeping the other Seedance variants in the shared
summary. Use the existing Seedance 2.0 / Seedance 2.0 Fast / Seedance 1.5 Pro
wording as the anchor for the split.

Comment on lines +1055 to +1061
const availableSizes = isSeedream
? (["2K", "4K"] as const)
: isGemini31FlashImage
? (["0.5K", "1K", "2K", "4K"] as const)
: (["1K", "2K", "4K"] as const);
: isGemini31FlashLiteImage
? (["1K"] as const)
: isGemini31FlashImage
? (["0.5K", "1K", "2K", "4K"] as const)
: (["1K", "2K", "4K"] as const);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Clamp imageSize when switching to the lite model.

This only narrows the dropdown options. It does not reset an existing "0.5K", "2K", or "4K" value, so switching models can keep submitting an unsupported size for gemini-3.1-flash-lite-image.

Suggested fix
 	const availableSizes = isSeedream
 		? (["2K", "4K"] as const)
 		: isGemini31FlashLiteImage
 			? (["1K"] as const)
 			: isGemini31FlashImage
 				? (["0.5K", "1K", "2K", "4K"] as const)
 				: (["1K", "2K", "4K"] as const);
+
+	useEffect(() => {
+		if (!availableSizes.includes(imageSize as (typeof availableSizes)[number])) {
+			setImageSize(availableSizes[0]);
+		}
+	}, [availableSizes, imageSize, setImageSize]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const availableSizes = isSeedream
? (["2K", "4K"] as const)
: isGemini31FlashImage
? (["0.5K", "1K", "2K", "4K"] as const)
: (["1K", "2K", "4K"] as const);
: isGemini31FlashLiteImage
? (["1K"] as const)
: isGemini31FlashImage
? (["0.5K", "1K", "2K", "4K"] as const)
: (["1K", "2K", "4K"] as const);
const availableSizes = isSeedream
? (["2K", "4K"] as const)
: isGemini31FlashLiteImage
? (["1K"] as const)
: isGemini31FlashImage
? (["0.5K", "1K", "2K", "4K"] as const)
: (["1K", "2K", "4K"] as const);
useEffect(() => {
if (!availableSizes.includes(imageSize as (typeof availableSizes)[number])) {
setImageSize(availableSizes[0]);
}
}, [availableSizes, imageSize, setImageSize]);
🤖 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 `@apps/playground/src/components/playground/chat-ui.tsx` around lines 1055 -
1061, The availableSizes change in chat-ui only updates the dropdown options and
leaves an already-selected unsupported imageSize intact when switching to
gemini-3.1-flash-lite-image. Update the model-switching logic around the image
size state in playground/chat-ui.tsx so that when isGemini31FlashLiteImage
becomes true, the current imageSize is clamped or reset to "1K" if it is not
allowed. Use the existing availableSizes logic and the imageSize state handler
in the chat UI to ensure submitted sizes always match the active model.

Comment on lines +216 to +221
"AQ.Ab8RN9jgub3Gxb1PSi41S-vr5ycE7gMe8NTvapHpJxFZFx-g",
true,
);

expect(endpoint).toBe(
"https://aiplatform.googleapis.com/v1/publishers/google/models/gemini-2.5-pro:streamGenerateContent?key=AQ.Ab8RN9jgub3Gxb1PSi41S-vr5ycE7gMe8NTvapHpJxFZFx-g&alt=sse",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Use an obviously fake AQ token in the test fixture.

This string looks like a real credential. Swapping it for something like AQ.test-token avoids secret-scanner noise while still covering the same branch.

Proposed fix
-			"AQ.Ab8RN9jgub3Gxb1PSi41S-vr5ycE7gMe8NTvapHpJxFZFx-g",
+			"AQ.test-token",
...
-			"https://aiplatform.googleapis.com/v1/publishers/google/models/gemini-2.5-pro:streamGenerateContent?key=AQ.Ab8RN9jgub3Gxb1PSi41S-vr5ycE7gMe8NTvapHpJxFZFx-g&alt=sse",
+			"https://aiplatform.googleapis.com/v1/publishers/google/models/gemini-2.5-pro:streamGenerateContent?key=AQ.test-token&alt=sse",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"AQ.Ab8RN9jgub3Gxb1PSi41S-vr5ycE7gMe8NTvapHpJxFZFx-g",
true,
);
expect(endpoint).toBe(
"https://aiplatform.googleapis.com/v1/publishers/google/models/gemini-2.5-pro:streamGenerateContent?key=AQ.Ab8RN9jgub3Gxb1PSi41S-vr5ycE7gMe8NTvapHpJxFZFx-g&alt=sse",
"AQ.test-token",
);
expect(endpoint).toBe(
"https://aiplatform.googleapis.com/v1/publishers/google/models/gemini-2.5-pro:streamGenerateContent?key=AQ.test-token&alt=sse",
🤖 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 `@packages/actions/src/get-provider-endpoint.spec.ts` around lines 216 - 221,
The test fixture in get-provider-endpoint.spec.ts is using an AQ token that
resembles a real credential; replace the hardcoded token in the endpoint
assertion setup with an obviously fake value like AQ.test-token. Keep the same
test path and branch coverage in getProviderEndpoint while updating the expected
URL string to match the fake token.

Comment on lines +49 to +55
if (token?.startsWith("AQ.")) {
const baseEndpoint = `${url}/v1/publishers/google/models/${model}:${endpoint}`;
const queryParams = [`key=${token}`];
if (stream) {
queryParams.push("alt=sse");
}
return `${baseEndpoint}?${queryParams.join("&")}`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline packages/actions/src/get-provider-endpoint.ts --view expanded || true

echo '---'
sed -n '1,220p' packages/actions/src/get-provider-endpoint.ts

echo '--- SEARCH ---'
rg -n "startsWith\\(\"AQ\\.\"\\)|Express Mode|publishers/google/models|key=" packages/actions/src -S

Repository: theopenco/llmgateway

Length of output: 9156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- SPEC EXPRESS MODE ---'
sed -n '200,235p' packages/actions/src/get-provider-endpoint.spec.ts

echo '--- TOKEN SEARCH ---'
rg -n "encodeURIComponent|URLSearchParams|startsWith\\(\"AQ\\.\"\\)|google_vertex_project_id|key=\\$\\{token\\}" packages/actions/src packages/models/src -S

echo '--- PROVIDER KEY TYPES ---'
rg -n "type ProviderKeyOptions|interface ProviderKeyOptions|google_vertex_project_id|token" packages -g '!**/dist/**' -S

Repository: theopenco/llmgateway

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- EXPRESS MODE SPEC ---'
sed -n '206,225p' packages/actions/src/get-provider-endpoint.spec.ts

echo '--- TOKEN SHAPE / ENCODING ---'
rg -n "AQ\\.|Express Mode|API key|URLSearchParams|encodeURIComponent|searchParams" packages/actions/src/get-provider-endpoint.ts packages/actions/src/get-provider-endpoint.spec.ts -S

Repository: theopenco/llmgateway

Length of output: 1598


🌐 Web query:

Google Vertex Express Mode API key AQ. URL encoding reserved characters

💡 Result:

Google has introduced a new format for API keys, often starting with the prefix AQ., which replaces the traditional AIza- prefix [1]. This change is part of an update to how authentication credentials are generated and managed for services like the Gemini Enterprise Agent Platform (Gemini API) [1][2][3]. Regarding URL encoding and reserved characters: 1. Standard Usage: When passing an API key in a URL query parameter (e.g.,?key=YOUR_API_KEY), the key must be properly URL-encoded if it contains any reserved characters [4]. Standard URL encoding rules apply, where characters such as &, =, +, and others are converted to their percent-encoded equivalents (e.g., & becomes %26) [4]. 2. Best Practices: Google strongly recommends avoiding the use of URL query parameters for API keys to prevent them from being exposed in server logs or browser history [5]. Instead, you should pass the API key using the x-goog-api-key HTTP request header [6][5]. When using this header, the key is sent as an opaque string and does not require URL encoding [6][4]. 3. Implementation: If you are using official Google Cloud client libraries or the Google Gen AI SDK, authentication is handled automatically [1][7]. These libraries manage the transmission of the API key, ensuring that it is passed correctly without you needing to manually perform URL encoding [8][1][7]. If you are manually constructing REST API requests, the safest approach is to use the HTTP header method rather than including the key in the URL string [6][5]. If you encounter authentication errors with an AQ.-prefixed key, ensure your application is sending the key to the correct native endpoint (e.g., generativelanguage.googleapis.com) rather than an OpenAI-compatible endpoint, which may reject the new key format depending on its implementation [1].

Citations:


Encode the key query parameter in the Vertex Express Mode URL. Build this with URL/URLSearchParams instead of string interpolation so AQ.-prefixed keys with reserved characters don’t produce a broken endpoint. The same key=${token} pattern appears in the other Vertex branches too.

🤖 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 `@packages/actions/src/get-provider-endpoint.ts` around lines 49 - 55, The
Vertex Express Mode URL builder in getProviderEndpoint currently interpolates
the token directly into the query string, which can break when AQ.-prefixed keys
contain reserved characters. Update the URL construction in getProviderEndpoint
to use URL and URLSearchParams for the token-based branch, and apply the same
fix to the other Vertex branches that use key=${token} so the key value is
encoded consistently.

@analogpvt
analogpvt force-pushed the gemini-aistudio-models branch from 2ef2600 to c81610e Compare June 30, 2026 17:37
@analogpvt analogpvt closed this Jun 30, 2026
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.

1 participant