Skip to content

Mecanismo de Transformação de Requisições: Compatibilidade Multi-Protocolo

O Que Você Vai Aprender

  • Entender como o plugin transforma formatos de requisição entre OpenCode e Antigravity API
  • Dominar as diferenças de protocolo e regras de transformação entre modelos Claude e Gemini
  • Diagnosticar erros 400 causados por incompatibilidade de Schema
  • Otimizar configurações de Thinking para melhor desempenho

Seu Problema Atual

Você pode estar enfrentando estes problemas:

  • ❌ Servidor MCP retorna erro 400 Unknown name 'parameters'
  • ❌ Ao usar modelos Gemini, aparece 400 Unknown name 'const'
  • ❌ Blocos de pensamento do modelo Thinking exibidos incorretamente
  • ❌ Chamadas de ferramentas falham com erro de validação de assinatura
  • ❌ Não entende por que o plugin suporta Claude e Gemini simultaneamente

Quando Usar Esta Técnica

Quando você precisa:

CenárioPor Que Entender o Mecanismo de Transformação
Desenvolver servidor MCP personalizadoGarantir que o Schema da ferramenta seja compatível com Antigravity API
Diagnosticar erros 400/500Determinar se é problema de Schema ou lógica de transformação
Otimizar desempenho do ThinkingEntender assinaturas de blocos de pensamento e mecanismo de cache
Depurar falhas em chamadas de ferramentasVerificar atribuição de ID de ferramenta e assinaturas de parâmetros

Verificação Prévia

Antes de iniciar este tutorial, certifique-se de que você:

  • ✅ Instalou o plugin opencode-antigravity-auth
  • ✅ Conhece os modelos disponíveis e suas variantes
  • ✅ Entende os conceitos básicos dos modelos Thinking

Tutorial de Lista de Modelos | Tutorial de Modelos Thinking

Conceito Central

A transformação de requisições é o mecanismo central do plugin, realizando três tarefas:

  1. Interceptar requisições do OpenCode — Intercepta chamadas fetch(generativeLanguage.googleapis.com)
  2. Aplicar transformação de modelo — Transforma o formato de acordo com o tipo de modelo (Claude/Gemini)
  3. Empacotar e enviar — Empacota no formato Antigravity e chama a API
  4. Transformar resposta — Converte a resposta de volta para formato reconhecível pelo OpenCode

Diagrama do Fluxo de Transformação:

mermaid
graph TD
    A[Requisição OpenCode] --> B{Detectar Tipo de Modelo}
    B -->|Claude| C[Aplicar Transformação Claude]
    B -->|Gemini| D[Aplicar Transformação Gemini]
    C --> E[Limpar Schema]
    D --> E
    E --> F[Injetar Configuração Thinking]
    F --> G[Processar Assinatura do Bloco de Pensamento]
    G --> H[Empacotar no Formato Antigravity]
    H --> I[Enviar para API]
    I --> J[Transformar Stream de Resposta]
    J --> K[Retornar ao OpenCode]

Pontos-Chave de Transformação:

Tipo de TransformaçãoObjetivoLocalização no Código
Limpeza de SchemaRemover campos não suportados pela Antigravity APIsrc/plugin/request-helpers.ts
Configuração ThinkingInjetar configuração de pensamento correta por família de modelosrc/plugin/transform/claude.ts, src/plugin/transform/gemini.ts
Processamento de Bloco de PensamentoRemover blocos de pensamento históricos e injetar assinaturassrc/plugin/request.ts
Transformação de Stream de RespostaConverter eventos SSE para formato OpenCodesrc/plugin/core/streaming.ts

Passo a Passo

Passo 1: Entender as Regras de Transformação Claude

Por Quê Modelos Claude usam formato de protocolo diferente (snake_case, modo VALIDATED), exigindo tratamento especial.

Regras-Chave de Transformação

Formato OriginalFormato TransformadoDescrição
toolConfig.functionCallingConfig.mode"VALIDATED"Força validação de chamada de ferramenta
thinkingConfig.includeThoughtsinclude_thoughtsFormato snake_case
thinkingConfig.thinkingBudgetthinking_budgetFormato snake_case
maxOutputTokensAjustado automaticamente para 64.000Modelos Thinking precisam de mais espaço de saída

Localização no Código: src/plugin/transform/claude.ts:43-56

Exemplo

typescript
// Antes da transformação (formato OpenCode)
{
  "toolConfig": {
    "functionCallingConfig": {
      "mode": "AUTO"
    }
  },
  "thinkingConfig": {
    "includeThoughts": true,
    "thinkingBudget": 32000
  }
}

// Após transformação (formato Antigravity)
{
  "toolConfig": {
    "functionCallingConfig": {
      "mode": "VALIDATED"  // Forçado VALIDATED
    }
  },
  "thinkingConfig": {
    "include_thoughts": true,  // snake_case
    "thinking_budget": 32000   // snake_case
  },
  "generationConfig": {
    "maxOutputTokens": 64000   // Ajuste automático para modelos Thinking
  }
}

O Que Você Deve Ver:

  • Todas as transformações de modelos Claude seguem nomenclatura snake_case
  • maxOutputTokens é automaticamente ajustado para um valor suficientemente grande (CLAUDE_THINKING_MAX_OUTPUT_TOKENS = 64.000)

Passo 2: Entender as Regras de Transformação Gemini

Por Quê Modelos Gemini usam formato camelCase e têm requisitos rigorosos para JSON Schema (tipos em maiúsculas).

Regras-Chave de Transformação

Formato OriginalFormato TransformadoDescrição
JSON Schema type: "object"type: "OBJECT"Tipo deve ser maiúsculo
additionalProperties: falseRemovidoGemini API não suporta
$ref: "#/$defs/Foo"Convertido para description: "See: Foo"Referência convertida em descrição
const: "foo"enum: ["foo"]const convertido para enum
enum: ["a", "b"]Adiciona dica na descrição (Allowed: a, b)Enums de 2-10 itens recebem dica automática

Localização no Código: src/plugin/transform/gemini.ts:52-124

Exemplo

json
// Antes da transformação (formato OpenCode)
{
  "parameters": {
    "type": "object",
    "properties": {
      "status": {
        "type": "string",
        "const": "active",
        "enum": ["active", "inactive"]
      }
    }
  }
}

// Após transformação (formato Gemini)
{
  "parameters": {
    "type": "OBJECT",  // Maiúsculo
    "properties": {
      "status": {
        "type": "STRING",  // Maiúsculo
        "enum": ["active", "inactive"],  // const removido
        "description": "(Allowed: active, inactive)"  // Dica adicionada automaticamente
      }
    }
  }
}

O Que Você Deve Ver:

  • Todos os tipos no Schema Gemini são convertidos para maiúsculas (STRING, OBJECT, ARRAY)
  • Campo const é removido e convertido para enum
  • Campos não suportados ($ref, additionalProperties) são removidos

Passo 3: Entender o Fluxo de Limpeza de Schema

Por Quê A Antigravity API usa validação rigorosa baseada em protobuf e não suporta todos os campos do JSON Schema padrão.

Fluxo de Limpeza em Quatro Fases

  1. Fase 1a: Converter $ref para descrição

    • $ref: "#/$defs/Foo"{ description: "See: Foo" }
  2. Fase 1b: Converter const para enum

    • const: "foo"enum: ["foo"]
  3. Fase 1c: Adicionar dicas de enum

    • enum: ["a", "b"] → Adiciona (Allowed: a, b) à descrição
  4. Fase 1d: Remover campos não suportados

    • Remove: $schema, $defs, additionalProperties, pattern, minLength, maxLength, etc.

Localização no Código: src/plugin/request-helpers.ts:20-280

Lista de Campos Não Suportados:

CampoPor Que Não é SuportadoAlternativa
$refReferências não permitidasConverter para dica na descrição
constConstantes não permitidasUsar enum
additionalPropertiesPropriedades extras não validadasMencionar na descrição
$schema, $defsJSON Draft não usadoRemover
pattern, minLength, maxLengthRestrições de string tratadas pelo servidorRemover
minItems, maxItemsRestrições de array tratadas pelo servidorRemover

O Que Você Deve Ver:

  • Schema do servidor MCP é limpo para formato compatível com Antigravity
  • Erros 400 reduzidos, mensagens de erro mais claras

Passo 4: Entender o Mecanismo de Processamento de Blocos de Pensamento

Por Quê Modelos Claude e Gemini 3 precisam de assinaturas estáveis para blocos de pensamento, caso contrário ocorrem erros de validação de assinatura.

Fluxo de Processamento em Três Passos

  1. Remover blocos de pensamento históricos

    • Remove recursivamente todos os blocos thinking históricos (evita conflitos de assinatura)
    • Usa cache para validar validade da assinatura
  2. Injetar nova assinatura de pensamento

    • Gera assinatura estável para novos blocos de pensamento
    • Armazena assinatura em cache para conversas multi-turno
  3. Garantir ordem dos blocos de pensamento

    • Claude: thinking deve vir antes de tool_use
    • Gemini: thinking pode aparecer em qualquer posição

Localização no Código:

Exemplo de Assinatura de Bloco de Pensamento:

typescript
// Formato de bloco Thinking do Claude
{
  "type": "thinking",
  "text": "Preciso analisar as necessidades do usuário...",
  "signature": "sig-abc123",  // Assinatura injetada pelo plugin
  "cache_control": { "type": "ephemeral" }  // Controle de cache
}

// Bloco de pensamento histórico (removido)
{
  "type": "thinking",
  "text": "Análise antiga...",  // Removido
  "signature": "sig-old456"  // Assinatura inválida
}

O Que Você Deve Ver:

  • Em conversas multi-turno, blocos de pensamento históricos não são exibidos repetidamente
  • Novos blocos de pensamento têm assinatura correta
  • Processo de pensamento completo antes das chamadas de ferramentas

Passo 5: Entender a Transformação de Stream de Resposta

Por Quê A Antigravity API retorna stream SSE (Server-Sent Events), que precisa ser convertido para formato reconhecível pelo OpenCode.

Regras-Chave de Transformação

Formato OriginalFormato TransformadoDescrição
thought: truetype: "reasoning"Conversão de formato de bloco de pensamento
textMantidoConteúdo de texto
tool_useMantidoChamada de ferramenta
tool_resultMantidoResultado de ferramenta

Localização no Código: src/plugin/core/streaming.ts

Exemplo de Evento SSE:

// Retorno da Antigravity API
data: {"type": "thinking", "text": "Analisando...", "thought": true}

// Após transformação
data: {"type": "reasoning", "text": "Analisando..."}

// Evento de texto
data: {"type": "text", "text": "Olá"}

// Evento de chamada de ferramenta
data: {"type": "tool_use", "id": "tool-123", "name": "my_function"}

O Que Você Deve Ver:

  • Blocos de pensamento exibidos corretamente na interface como tipo reasoning
  • Resposta em streaming sem atraso, conversão linha por linha
  • Formato correto de eventos de chamada de ferramenta

Checkpoint ✅

Após completar os passos acima, você deve ser capaz de responder estas perguntas:

  • [ ] Para qual valor o toolConfig.mode do modelo Claude é definido?
  • [ ] Para o que type: "string" do Schema Gemini é convertido?
  • [ ] Por que blocos de pensamento históricos são removidos?
  • [ ] Para qual formato o campo const é convertido?
  • [ ] Qual é a função da assinatura do bloco de pensamento?

Armadilhas Comuns

Armadilha 1: Schema MCP contém $ref causando erro 400

Mensagem de Erro: 400 Unknown name 'parameters'

Causa: Servidor MCP usa referência $ref do JSON Schema, que a Antigravity API não suporta.

Solução:

  • Verificar definição de Schema do servidor MCP
  • Remover $ref, expandir estrutura do objeto diretamente
  • Ou modificar código do servidor MCP

Exemplo:

json
// ❌ Errado: usando $ref
{
  "properties": {
    "data": { "$ref": "#/$defs/DataModel" }
  },
  "$defs": {
    "DataModel": { "type": "string" }
  }
}

// ✅ Correto: expandido diretamente
{
  "properties": {
    "data": { "type": "string" }
  }
}

Armadilha 2: Campo const causa erro 400 no modelo Gemini

Mensagem de Erro: 400 Unknown name 'const'

Causa: Endpoint Gemini da Antigravity API não suporta campo const.

Solução:

  • Converter manualmente const para enum
  • Ou confiar na conversão automática do plugin (já implementada)

Exemplo:

json
// ❌ Errado: usando const
{
  "properties": {
    "status": { "type": "string", "const": "active" }
  }
}

// ✅ Correto: usando enum
{
  "properties": {
    "status": { "type": "string", "enum": ["active"] }
  }
}

Armadilha 3: Modelo Thinking exibe caracteres ilegíveis

Mensagem de Erro: Bloco de pensamento exibido como [object Object] ou formato incorreto

Causa: Bug na lógica de transformação de resposta, ou cache de assinatura inválido.

Solução:

  1. Verificar logs de depuração: opencode --debug
  2. Limpar cache de assinatura: deletar campo de cache em ~/.config/opencode/antigravity-accounts.json
  3. Reiniciar OpenCode

Armadilha 4: Chamada de ferramenta falha com erro de assinatura

Mensagem de Erro: tool_result_missing ou falha na validação de assinatura

Causa:

  • Ordem incorreta dos blocos de pensamento (thinking deve vir antes de tool_use)
  • Cache de assinatura inconsistente
  • Atribuição incorreta de ID de ferramenta

Solução:

  • Plugin tentará novamente automaticamente (mecanismo de recuperação de sessão)
  • Ativar modo de depuração para ver erros detalhados
  • Verificar se definição da ferramenta está correta

Resumo da Lição

Pontos-chave do mecanismo de transformação de requisições:

  1. Família do modelo determina regras de transformação — Claude (snake_case, VALIDATED) vs Gemini (camelCase, Schema maiúsculo)
  2. Limpeza de Schema é obrigatória — Remover campos não suportados como $ref, const, additionalProperties
  3. Assinatura do bloco de pensamento é crucial — Assinaturas estáveis garantem consistência em conversas multi-turno
  4. Transformação de stream de resposta — Converte eventos SSE em tempo real para formato OpenCode

Localizações-Chave no Código:

Prévia da Próxima Lição

Na próxima lição, aprenderemos sobre Mecanismo de Recuperação de Sessão.

Você aprenderá:

  • Como funciona a recuperação de sessão
  • Como tratar automaticamente falhas em chamadas de ferramentas
  • Como corrigir ordem corrompida de blocos de pensamento

Apêndice: Referência do Código-Fonte

Clique para expandir e ver localizações no código-fonte

Atualizado em: 2026-01-23

FuncionalidadeCaminho do ArquivoLinhas
Entrada principal de transformação de requisiçãosrc/plugin/request.ts585-1443
Entrada de transformação de respostasrc/plugin/request.ts1445-1663
Detecção de modelo Claudesrc/plugin/transform/claude.ts27-29
Configuração Thinking do Claudesrc/plugin/transform/claude.ts62-72
Configuração de Tool do Claudesrc/plugin/transform/claude.ts43-57
Detecção de modelo Geminisrc/plugin/transform/gemini.ts129-132
Configuração Thinking do Gemini 3src/plugin/transform/gemini.tsProcurar buildGemini3ThinkingConfig
Transformação de Schema Geminisrc/plugin/transform/gemini.ts52-124
---------
---------
---------
Remoção de bloco de pensamentosrc/plugin/request-helpers.tsProcurar deepFilterThinkingBlocks
Injeção de assinatura de bloco de pensamentosrc/plugin/request.ts715-720
Transformação de resposta em streamingsrc/plugin/core/streaming.tsArquivo completo

Constantes-Chave:

Funções-Chave: