Skip to content

feat: adiciona provider Codex via SDK Python oficial - #111

Open
bdcdo wants to merge 9 commits into
mainfrom
feature/codex-provider
Open

feat: adiciona provider Codex via SDK Python oficial#111
bdcdo wants to merge 9 commits into
mainfrom
feature/codex-provider

Conversation

@bdcdo

@bdcdo bdcdo commented Jul 15, 2026

Copy link
Copy Markdown
Owner

O que mudou

  • adiciona provider="codex" usando o SDK Python oficial, fora do caminho LangChain;
  • mantém Codex opcional e fora do extra all; dataframeit[codex] fixa openai-codex==0.1.0b3, que por sua vez fixa o runtime compatível openai-codex-cli-bin==0.137.0a4;
  • usa sempre o runtime empacotado pelo SDK; o CLI externo serve apenas para criar o auth.json file-backed;
  • mantém um codex app-server por execução do DataFrame e cria uma thread efêmera por linha, inclusive com parallel_requests;
  • usa structured output nativo, converte o schema gerado pelo Pydantic v2 para o subconjunto estrito aceito e valida a resposta novamente com model_validate_json;
  • expõe as mesmas métricas de tokens dos demais providers, inclusive _cached_input_tokens, e preserva respostas válidas quando o SDK não fornece telemetria.

Simplificações e correções

O backend é selecionado e vinculado uma única vez antes do processamento. O loop por linha recebe apenas invoke(text): não há novo despacho entre Codex, Claude Code, LangChain ou os três modos de busca, nem cache multimodelo, prepare() ou lookup de schema por linha.

O preflight de dependência, configuração, schema e autenticação termina antes de _setup_columns, portanto uma falha não deixa o DataFrame parcialmente modificado. DataFrames vazios criam as colunas esperadas; checkpoints concluídos retornam sem importar o SDK, exigir login ou iniciar o app-server.

Ao retomar um checkpoint, cada linha marcada como processada é validada contra o modelo Pydantic atual antes de qualquer mutação ou abertura do provider. Campos obrigatórios ausentes, nulos ou inválidos precisam ser cobertos por reprocess_columns; campos opcionais e defaults continuam válidos, e defaults ausentes são materializados depois do preflight. A validação usa a posição da linha — portanto aceita índices duplicados — e lê o nome canônico salvo no checkpoint mesmo quando o modelo aceita somente um alias na entrada.

O conversor de schema remove defaults, torna objetos estritos, converte somente uniões compatíveis e rejeita cedo estruturas fora do subconjunto aceito. Falhas do próprio Pydantic ao gerar JSON Schema são classificadas como erro de configuração do provider, com a causa original preservada.

A autenticação file-backed tem uma única instrução canônica e o runtime fixa explicitamente cli_auth_credentials_store="file". Cada execução cria o runtime temporário no mesmo filesystem da credencial e compartilha auth.json por hard link, preservando refresh sem exigir privilégio de symlink no Windows; falhas de diretório, link e exclusão têm diagnósticos distintos e cleanup explícito.

O runtime pinado salva a credencial com truncate + write e coordena refresh apenas dentro do próprio processo. Para impedir que dois app-servers do DataFrameIt corrompam ou sobrescrevam a mesma credencial, o extra codex usa um lock interprocessual por auth.json, adquirido antes do runtime e liberado somente depois de client.close() e do cleanup. A aquisição é fail-fast: uma segunda execução com a mesma credencial falha antes de iniciar o cliente ou alterar o DataFrame; credenciais distintas não contendem e parallel_requests continua concorrente dentro da execução ativa.

Erros de provider usam uma taxonomia compartilhada. HTTP 429 e serverOverloaded recebem retry e reduzem o paralelismo; erros internos, rollback e falhas transitórias de conexão recebem retry sem serem confundidos com rate limit; demais 4xx permanecem definitivos. A classificação usa o erro tipado registrado no turno pelo SDK, em vez de procurar texto em mensagens.

A telemetria LangChain agora preserva input_token_details.cache_read tanto em metadados dict quanto objeto, nos caminhos normal e com busca. Uma única estrutura inicializa os acumuladores de tokens, eliminando quatro cópias divergentes e preservando também reasoning_tokens nas agregações por campo, grupo, lista e modelo aninhado. cache_creation não entra em _cached_input_tokens, pois representa consumo de entrada ainda não lido do cache.

O pin exato do runtime deixou de ser declarado duas vezes: openai-codex é a única fonte da versão exata; o extra mantém somente um limite inferior com marcador pré-release para que checkouts limpos do uv resolvam sem --prerelease=allow. A descrição das colunas de tokens também tem uma única referência canônica por idioma.

Isolamento

Cada execução usa CODEX_HOME, CODEX_SQLITE_HOME e workspace temporários. auth.json é o único arquivo do estado persistente do Codex vinculado ao runtime; como todo subprocesso, o app-server ainda herda as variáveis de ambiente do processo. Busca web, shell, execução unificada e servidores MCP ficam desativados, aprovações são negadas e o sandbox somente leitura bloqueia escrita.

O lock coordena apenas instâncias do DataFrameIt. Codex CLI, login/logout e outros programas não respeitam esse sidecar; por isso, não devem usar a mesma credencial enquanto um processamento estiver ativo. A gravação upstream por truncamento também continua sujeita a falha se o processo morrer exatamente durante o save — a correção integral desses dois limites pertence ao runtime upstream.

Testes e CI

  • Python 3.13, ambiente local e ambiente isolado [dev,codex]: 440 passed, 5 skipped em cada execução;
  • Python 3.10, ambiente isolado [dev] sem o SDK Codex: 408 passed, 37 skipped;
  • compatibilidade específica do checkpoint verificada também com Pydantic 2.0.3;
  • uv build e twine check aprovam wheel e sdist;
  • MkDocs gera a documentação PT/EN pelo mesmo comando do CI;
  • job dedicado no Windows agora inicia o runtime empacotado, além de validar hard link, propagação de refresh, exclusão multiprocesso fail-fast, ausência de symlink e cleanup;
  • três revisões independentes cobriram contratos do provider, lifecycle/autenticação, checkpoints, telemetria, testes e empacotamento; os bloqueios encontrados foram corrigidos e revistos.

Não há bump de versão; a mudança está registrada em [Unreleased].

@bdcdo
bdcdo marked this pull request as ready for review July 15, 2026 19:56
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