APIs, streaming, mensagens
Você implementará uma máquina de estados para respostas progressivas antes de conectar qualquer serviço. Essa ordem permite testar a falha mais traiçoeira: uma frase aparentemente completa recebida por uma operação que terminou com erro. O contrato local torna o comportamento observável.
Prepare um arquivo .mjs e uma pequena coleção de eventos. Nenhuma credencial é necessária nesta etapa. A conexão real será feita por adaptadores separados, documentando versão instalada e endpoint escolhido. A conclusão do laboratório local demonstra tratamento de estados; não demonstra compatibilidade externa.
JavaScriptOpenAIAPIsAo terminar esta aula
- HTTP comunica resultados; validação decide adequação.
- Cada provedor exige tradução própria.
- Streaming precisa de estados e término explícitos.
Antes de continuar: Leitura: APIs, streaming, mensagens
Desenhar o contrato interno
FundamentosEscreva primeiro os estados que o produto precisa distinguir: aguardando, recebendo, concluído, falhou e cancelado. Defina quando o resumo pode ser salvo. Tente resolver o caso em que a frase parece completa, mas não chega evento final. A regra deve depender da operação, não da aparência do texto. Retome a separação entre HTTP e negócio: status de transporte, conclusão da geração e aprovação do resumo são verificações diferentes. Crie um objeto de entrada com pedido e instrução da aplicação separados. Esse objeto será traduzido por adaptadores, sem fingir que todos os provedores usam os mesmos campos ou roles.
Implementar montagem de eventos
FundamentosExecute a sequência nominal e observe cada transição, não apenas o objeto final. Acrescente uma função que receba estado anterior e evento e devolva estado novo. Isso permite testar fragmentos vazios, erro antes do primeiro texto e conclusão sem conteúdo. Associe um identificador de execução para impedir que fragmentos de duas requisições usem o mesmo acumulador. Quando uma nova chamada substituir outra, defina cancelamento e descarte de eventos antigos. Esses detalhes importam porque uma interface pode parecer correta em teste sequencial e misturar respostas quando o usuário envia dois pedidos rapidamente. Mantenha a tradução de eventos reais fora dessa função.
Traduzir provedores com documentação
FundamentosPrepare uma tabela do adaptador com autenticação, endpoint, instrução de aplicação, entrada, resposta e eventos relevantes. Consulte a documentação da versão usada antes de escrever código externo. Na Anthropic, confira system separado; no Gemini, o formato escolhido para contents e configuração; na OpenAI, a interface Responses selecionada. Não converta nomes mecanicamente. Para cada adaptador, indique capacidades não suportadas pelo contrato atual. Fixe versão de SDK quando optar por ele e registre defaults de timeout e retry. A etapa documental é revisável mesmo sem credenciais, mas compatibilidade real só pode ser afirmada depois de executar a integração autorizada.
↗ Create a Message↗ Gemini text generation↗ Responses API overview
Testar falha parcial e salvamento
FundamentosRemova a conclusão da sequência e confirme que a aplicação não salva o resumo. Depois acrescente erro após dois fragmentos e preserve o texto apenas como parcial. Tente uma sequência de outra execução para verificar isolamento. A rubrica exige estado correto, conteúdo sem mistura e salvamento apenas após validação. Compare streaming com resposta completa: o primeiro melhora percepção de progresso, mas exige mais estados; o segundo simplifica montagem, mas mantém espera. Documente essa escolha conforme a jornada. No relatório, cite testes locais e integrações reais separadamente, evitando transformar o sucesso do simulador em prova de um SDK.
Completar o cliente reutilizável
FundamentosPara concluir a entrega semanal, exponha uma função resumir que receba entrada, configuração e sinal de cancelamento, e devolva resultado com texto, status, uso quando disponível e identificador da requisição. Implemente um adaptador local para testar o contrato e um adaptador externo quando houver acesso autorizado. O cliente HTTP deve verificar status antes de consumir conteúdo e proteger credenciais no servidor. Os três provedores ficam em módulos separados; a interface do produto usa o contrato comum. Faça testes de tradução com corpos esperados segundo a documentação, sem usar o simulador como prova de integração. A rubrica final inclui autenticação inválida, timeout, stream interrompido e conclusão válida. Compare SDK e HTTP direto: o SDK pode reduzir código, enquanto HTTP explícito facilita inspecionar a fronteira; ambos exigem versão, contrato e limites claros.
Execução, inspeção e diagnóstico
FundamentosExecute o exemplo e confira o status final. Depois remova o evento concluido, acrescente um erro entre fragmentos e teste uma sequência vazia. Anote a diferença entre texto existente e operação concluída. Acrescente uma função podeSalvar que devolva true apenas para status concluido e conteúdo aprovado pela rubrica. O programa deve negar salvamento em todas as outras situações.
const eventos = [
{tipo:"fragmento",texto:"Pagamento "},
{tipo:"fragmento",texto:"aguarda confirmação."},
{tipo:"concluido"}
];
let estado = {status:"aguardando",texto:""};
for (const evento of eventos) {
if (evento.tipo === "fragmento") {
estado = {status:"recebendo",texto:estado.texto+evento.texto};
} else if (evento.tipo === "concluido") {
estado = {...estado,status:"concluido"};
} else if (evento.tipo === "erro") {
estado = {...estado,status:"falhou"};
}
}
console.log(estado);Se a interface salva um texto parcial, procure o ponto em que texto não vazio foi confundido com sucesso. Se duas chamadas misturam fragmentos, falta um identificador de execução ou cancelamento correto. Se um provedor ignora instruções, compare o corpo realmente serializado com o formato documentado. Não altere o prompt antes de conferir a tradução do adaptador.
Exercício aplicado
Crie um adaptador local de streaming com sucesso, erro, ausência de conclusão e duas execuções independentes.
- Execute a sequência nominal e inspecione o objeto final.
- Teste interrupção e erro com texto parcial.
- Implemente a condição de salvamento e um identificador por execução.
- Documente a tradução necessária para OpenAI, Anthropic e Gemini sem copiar roles entre formatos.
Abrir resolução comentada
A solução separa apresentação e confirmação. A interface pode mostrar texto parcial com indicação de progresso. O armazenamento definitivo só ocorre depois de término bem-sucedido e validação de negócio. Cancelamento também precisa de estado próprio no produto real.
Para três provedores, mantenha testes do contrato interno e testes de integração específicos de cada adaptador. Os primeiros usam eventos locais e são rápidos. Os segundos verificam autenticação, formatos e tipos reais; exigem credenciais e devem ser declarados como não executados quando não houver acesso.
A referência utiliza eventos internos para isolar a lógica. Na integração real, mapeie texto, conclusão e erro segundo a versão da API. Armazene a versão do adaptador e o identificador da requisição para rastrear regressões após mudanças.
A resolução mantém acumuladores por execução, condição de salvamento e cancelamento. Os asserts exercitam sucesso, erro parcial, frase sem término e eventos tardios após cancelamento. A tabela final documenta fronteiras de tradução; não é um cliente externo executado. Para integração real, o adaptador mapeia eventos documentados para os eventos internos e preserva a versão do endpoint e do SDK.
import assert from "node:assert/strict";
const execucoes=new Map();const salvos=new Map();
function iniciar(id){if(execucoes.has(id))throw new Error("ID_REPETIDO");
execucoes.set(id,{id,status:"aguardando",texto:""});}
function receber(id,eventos){
const estado=execucoes.get(id);if(!estado)throw new Error("EXECUCAO_AUSENTE");
for(const evento of eventos){
if(["concluido","falhou","cancelado"].includes(estado.status))break;
if(evento.tipo==="fragmento"){estado.status="recebendo";estado.texto+=evento.texto;}
else if(evento.tipo==="concluido")estado.status="concluido";
else if(evento.tipo==="erro")estado.status="falhou";
else if(evento.tipo==="cancelar")estado.status="cancelado";
}
return {...estado};
}
function salvar(id,aprovado){
const estado=execucoes.get(id);
if(estado.status!=="concluido"||!estado.texto.trim()||!aprovado)throw new Error("NAO_SALVAVEL");
salvos.set(id,estado.texto);return estado.texto;
}
iniciar("e1");iniciar("e2");iniciar("e3");iniciar("e4");
receber("e1",[{tipo:"fragmento",texto:"Pagamento "}]);
receber("e2",[{tipo:"fragmento",texto:"Outra execução."},{tipo:"erro"}]);
receber("e1",[{tipo:"fragmento",texto:"aguarda consulta."},{tipo:"concluido"}]);
assert.equal(salvar("e1",true),"Pagamento aguarda consulta.");
assert.equal(execucoes.get("e2").texto,"Outra execução.");
assert.throws(()=>salvar("e2",true),/NAO_SALVAVEL/);
receber("e3",[{tipo:"fragmento",texto:"Frase parece completa."}]);
assert.throws(()=>salvar("e3",true),/NAO_SALVAVEL/);
receber("e4",[{tipo:"cancelar"},{tipo:"fragmento",texto:"Evento tardio"}]);
assert.equal(execucoes.get("e4").texto,"");assert.equal(salvos.size,1);
assert.throws(()=>salvar("e1",false),/NAO_SALVAVEL/);
const contratos={
openai:{interface:"Responses",instrucao:"instructions ou mensagens no nível documentado",entrada:"input"},
anthropic:{interface:"Messages",instrucao:"system separado",entrada:"messages com user/assistant"},
gemini:{interface:"generateContent",instrucao:"system_instruction no formato do endpoint",entrada:"contents"}
};
console.log({status:"aprovado",salvos:salvos.size,contratos,integracoesExternas:"não executadas"});Como conferir seu resultado
- Texto parcial não é salvo como resumo definitivo.
- Execuções não compartilham acumulador.
- O documento diferencia teste local de integração real.
Aplique em um problema novo
Primeiro resolva sem consultar a resposta. Explique suas decisões e guarde a evidência. A conclusão de leitura é independente desta autoavaliação.
Confira seus pré-requisitos
- Interpretar status HTTP e corpo.
- Manter estado por identificador.
Eventos: U: 'Olá', V: 'Erro', U: concluído, V: erro. U recebeu aprovação de negócio. W é cancelado antes de fragmento tardio. Uma execução U2 concluiu transporte, mas teve aprovação recusada. Determine texto, estado e salvamento.
Conferir raciocínio e critérios de domínio
U preserva 'Olá' e V preserva 'Erro', sem misturar acumuladores. W permanece cancelado e ignora o fragmento tardio.
Somente U é salvo. V falhou, W foi cancelado e U2 não teve aprovação de negócio; conclusão de transporte não resolve essa recusa.
Asserções esperadas: um salvamento, textos separados e nenhum evento tardio revertendo o estado de W. Fixtures demonstram esse contrato interno; compatibilidade de SDK externo ainda exige seu runtime.
Evidências para autoavaliação ou revisão por pares
- Isolamento dos streams: U preserva 'Olá' e V preserva 'Erro', sem misturar acumuladores. W permanece cancelado e ignora o fragmento tardio.
- Condições de salvamento: Somente U é salvo. V falhou, W foi cancelado e U2 não teve aprovação de negócio; conclusão de transporte não resolve essa recusa.
- Asserts e alcance: Asserções esperadas: um salvamento, textos separados e nenhum evento tardio revertendo o estado de W. Fixtures demonstram esse contrato interno; compatibilidade de SDK externo ainda exige seu runtime.
Um erro frequente
Evento tardio pode reabrir cancelamento.
Cancelamento terminal impede fragmentos tardios de reabrirem o trabalho.
Teste sua compreensão
Responda com suas palavras antes de abrir o comentário. Saber explicar uma decisão é parte do domínio.
1. Todo provedor aceita system no array de mensagens?
Não.
A Anthropic documenta system separadamente; formatos devem ser traduzidos segundo cada API.
2. Uma frase completa prova que o stream terminou?
3. SDK elimina a necessidade de conhecer HTTP?
Não.
Status, autenticação, falhas de transporte e contratos continuam relevantes.
Seu progresso fica salvo neste navegador. Concluir a leitura não substitui demonstrar o domínio nos exercícios.
Referências e aprofundamento
Documentação oficial e trabalhos originais. As referências registram o escopo e as limitações para você conferir o que sustentam.
- OpenAI Python API library
OpenAI • consulta: 2026-10-06
PythonOpenAIAPIsCliente SDK, streaming, erros tipados, retries, timeout, logging e request IDs.
Limites: Defaults do SDK não substituem orçamento global de retries; pin de versão obrigatório.
- Claude API overview
Anthropic • consulta: 2026-10-06
APIsEndpoints HTTP, autenticação, SDKs e operação da API Claude.
Limites: Documentação dinâmica; fixar a versão usada no laboratório e conferir compatibilidade antes de executar.
- Gemini text generation
Google • consulta: 2026-10-06
FundamentosSDK e REST Gemini, instrução de sistema, configuração de geração, streaming e conversação.
Limites: Documentação atual inclui Interactions; conferir endpoint escolhido e formato de system_instruction/contents, sem presumir roles OpenAI.
- Responses API overview
OpenAI • consulta: 2026-10-06
OpenAIAPIsInterface HTTP Responses para geração, estado, ferramentas e multimodalidade.
Limites: Documentação dinâmica; fixar a versão usada no laboratório e conferir compatibilidade antes de executar.
- Prompt engineering
OpenAI • consulta: 2026-10-06
OpenAIHierarquia de mensagens OpenAI, instruções, exemplos few-shot, delimitadores, templates e versionamento.
Limites: Hierarquia específica do produto; não é controle de acesso. Exemplos negativos e decomposição precisam ser avaliados em casos de teste.
- Create a Message
Anthropic • consulta: 2026-10-06
FundamentosFormato Messages, mensagens user/assistant, campo system separado, parâmetros e resultados de tool use.
Limites: Não traduzir roles ou parâmetros OpenAI literalmente: Anthropic não usa system como role no array messages.
- Streaming API responses
OpenAI • consulta: 2026-10-06
OpenAIAPIsEventos de streaming e montagem progressiva de resposta.
Limites: Documentação dinâmica; fixar a versão usada no laboratório e conferir compatibilidade antes de executar.