Skip to content
This repository was archived by the owner on Mar 30, 2026. It is now read-only.
This repository was archived by the owner on Mar 30, 2026. It is now read-only.

Tool Error and model variant issue #524

@miracthis

Description

@miracthis

Pre-submission checklist

Model used

Other (specify in description)

Exact error message

Request contains an invalid argument.
[Debug Info]
Requested Model: antigravity-gemini-3.1-pro
Effective Model: gemini-3.1-pro-low
Project: rising-fact-p41fc
Endpoint: https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse
Status: 400
Request ID: N/A
Tool Debug Missing: 1
Tool Debug Summary: idx=0, hasCustom=true, customSchema=true, hasFunction=false, functionSchema=false
Tool Debug Payload: [{"functionDeclarations":[{"name":"bash","description":"Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.\n\nAll commands run in /Users/miracthis/Desktop/HumayLojistik/humay-lojistik by default. Use the `workdir` parameter if you need to run a command in a different directory. AVOID using `cd <directory> && <command>` patterns - use `workdir` instead.\n\nIMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.\n\nBefore executing the command, please follow these steps:\n\n1. Directory Verification:\n   - If the command will create new directories or files, first use `ls` to verify the parent directory exists and is the correct location\n   - For example, before running \"mkdir foo/bar\", first use `ls foo` to check that \"foo\" exists and is the intended parent directory\n\n2. Command Execution:\n   - Always quote file paths that contain spaces with double quotes (e.g., rm \"path with spaces/file.txt\")\n   - Examples of proper quoting:\n     - mkdir \"/Users/name/My Documents\" (correct)\n     - mkdir /Users/name/My Documents (incorrect - will fail)\n     - python \"/path/with spaces/script.py\" (correct)\n     - python /path/with spaces/script.py (incorrect - will fail)\n   - After ensuring proper quoting, execute the command.\n   - Capture the output of the command.\n\nUsage notes:\n  - The command argument is required.\n  - You can specify an optional timeout in milliseconds.

Bug description

Issue 1: Variant Routing Bug
Title: Gemini 3.1 Pro "high" variant falls back to "low" — resolveModelWithVariant ignores thinkingLevel
Body:

Bug

When using antigravity-gemini-3.1-pro with variant "high", the effective model becomes gemini-3.1-pro-low instead of gemini-3.1-pro-high.

Debug Output

Requested Model: antigravity-gemini-3.1-pro
Effective Model: gemini-3.1-pro-low

Root Cause

resolveModelWithVariant() in model-resolver.ts (line ~311) checks only for thinkingBudget and returns early if it's missing — completely ignoring thinkingLevel:

// model-resolver.ts — resolveModelWithVariant()
if (!variantConfig.thinkingBudget) {
    return base;  // ← BUG: thinkingLevel is never checked
}
When opencode.json defines a Gemini 3 variant with thinkingLevel (the correct format for Gemini 3):
high: {
  thinkingLevel: high
}
…the function exits early at line 311 because thinkingBudget is undefined, returning the base config which defaults to thinkingLevel: "low" (line 186).
Note: request.ts line ~664 has a separate path that correctly handles thinkingLevel for Gemini 3, but by that point the model NAME has already been resolved with the -low suffix by resolveModelWithVariant.
Expected Fix
Add thinkingLevel check before the thinkingBudget guard:
export function resolveModelWithVariant(requestedModel, variantConfig) {
    const base = resolveModelWithTier(requestedModel);
    if (!variantConfig) return base;
    if (variantConfig.googleSearch) { ... }
    // FIX: Handle thinkingLevel for Gemini 3 models
    if (variantConfig.thinkingLevel) {
        const isGemini3 = base.actualModel.toLowerCase().includes("gemini-3");
        if (isGemini3) {
            const level = variantConfig.thinkingLevel;
            const isAntigravityPro = base.quotaPreference === "antigravity" 
                && isGemini3ProModel(base.actualModel);
            let actualModel = base.actualModel;
            if (isAntigravityPro) {
                const baseModel = base.actualModel.replace(/-(low|medium|high)$/, "");
                actualModel = `${baseModel}-${level}`;
            }
            return { ...base, actualModel, thinkingLevel: level, configSource: "variant" };
        }
    }
    if (!variantConfig.thinkingBudget) return base;
    // ... rest unchanged
}
Environment
- opencode-antigravity-auth: 1.6.0 (@latest)
- opencode: 1.2.15
- Platform: macOS (darwin/arm64)
---
### Issue 2: Tool Schema 400 Error
**Title:** `normalizeGeminiTools deletes custom wrapper without creating function field — causes 400 on custom-only tools`
**Body:**
Bug
Gemini API returns 400 "Request contains an invalid argument" when a tool has only a custom field (no function field), which is the standard format for MCP tools.
Debug Output
Status: 400
Tool Debug Missing: 1
Tool Debug Summary: idx=0, hasCustom=true, customSchema=true, hasFunction=false, functionSchema=false
Root Cause
In normalizeGeminiTools() (gemini.ts), the logic handles three cases but misses one critical path:
// Case 1: function EXISTS → update its schema ✅
if (newTool.function && schema) {
    newTool.function.input_schema = schema;
}
// Case 2: function EXISTS, custom MISSING → create custom from function ✅
if (!newTool.custom && newTool.function) { ... }
// Case 3: BOTH missing → create custom ✅
if (!newTool.custom && !newTool.function) { ... }
// THEN: delete custom wrapper (Gemini only accepts function-style)
if (newTool.custom) {
    delete newTool.custom;  // ← custom DELETED
}
// ⛔ MISSING CASE: custom EXISTS, function MISSING
// → custom gets deleted, function never created
// → tool becomes empty → 400
When a tool arrives with ONLY custom (standard MCP format):
1. Case 1 skipped (no function) 
2. Case 2 skipped (custom exists)
3. Case 3 skipped (custom exists)
4. custom gets deleted
5. No function field was ever created  empty tool  API rejects
Expected Fix
Add a case for custom-only tools that creates the function field:
// After Case 2, add:
// Case 2b: custom EXISTS, function MISSING → create function from custom
if (newTool.custom && !newTool.function) {
    const c = newTool.custom;
    newTool.function = {
        name: c.name || nameCandidate,
        description: c.description,
        input_schema: schema,
    };
}
Environment
- opencode-antigravity-auth: 1.6.0 (@latest)
- opencode: 1.2.15
- Platform: macOS (darwin/arm64)
---

### Steps to reproduce

gemini 3.1 pro high variant issue sub agent call 

### Did this ever work?

Worked before, now broken (regression)

### Number of Google accounts configured

1

### Reproducibility

Always (100%)

### Plugin version

opencode-antigravity-auth: 1.6.0 (@latest)

### OpenCode version

opencode: 1.2.15

### Operating System

macOs

### Node.js version

latest

### Environment type

Standard (native terminal)

### MCP servers installed

_No response_

### Debug logs (REQUIRED)

```text
Request contains an invalid argument.
[Debug Info]
Requested Model: antigravity-gemini-3.1-pro
Effective Model: gemini-3.1-pro-low
Project: rising-fact-p41fc
Endpoint: https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse
Status: 400
Request ID: N/A
Tool Debug Missing: 1
Tool Debug Summary: idx=0, hasCustom=true, customSchema=true, hasFunction=false, functionSchema=false
Tool Debug Payload: [{"functionDeclarations":[{"name":"bash","description":"Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.\n\nAll commands run in /Users/miracthis/Desktop/HumayLojistik/humay-lojistik by default. Use the `workdir` parameter if you need to run a command in a different directory. AVOID using `cd <directory> && <command>` patterns - use `workdir` instead.\n\nIMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.\n\nBefore executing the command, please follow these steps:\n\n1. Directory Verification:\n   - If the command will create new directories or files, first use `ls` to verify the parent directory exists and is the correct location\n   - For example, before running \"mkdir foo/bar\", first use `ls foo` to check that \"foo\" exists and is the intended parent directory\n\n2. Command Execution:\n   - Always quote file paths that contain spaces with double quotes (e.g., rm \"path with spaces/file.txt\")\n   - Examples of proper quoting:\n     - mkdir \"/Users/name/My Documents\" (correct)\n     - mkdir /Users/name/My Documents (incorrect - will fail)\n     - python \"/path/with spaces/script.py\" (correct)\n     - python /path/with spaces/script.py (incorrect - will fail)\n   - After ensuring proper quoting, execute the command.\n   - Capture the output of the command.\n\nUsage notes:\n  - The command argument is required.\n  - You can specify an optional timeout in milliseconds.

Configuration (optional)

Compliance

  • I'm using this plugin for personal development only
  • This issue is not related to commercial use or TOS violations

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/compatCompatibility with OpenCode, DCPbugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions