Repository navigation
feat(agent): sdk-core 0.3.5 com o canal provisorio do copilot enquanto a box sobe (#121) - #122
JoaoLuisQuirino wants to merge 3 commits into
Conversation
|
/gandalf |
|
Gandalf, análise 1 · commit Pega-rápido: Hoje, o Copilot espera a box iniciar e abrir o canal da task. Esta mudança permite usar um canal provisório durante o boot para aceitar e administrar mensagens enfileiradas. Insights: O mérito está sustentado: o problema e o usuário afetado estão descritos na issue #121. O fallback atual por Forma da implementação: Aprovada com ressalvas. Findings
Confiança: Alta no comportamento demonstrável pela SDK; a integração com o produtor novo não pôde ser confirmada porque o contrato correspondente não está disponível neste recorte. Testes e CI: O CI deste SHA terminou verde, com build, compatibilidade Node 18/22 e 729 testes em 16 arquivos. Ainda faltam provas de box → provisório → box, redial com 4409/aborto, recuperação após queda antes de Standards verificados: Discussions #5, #35 e #93; nenhuma divergência relevante identificada no recorte. Decisão: mergeável. Os achados são Aqui o meu check é obrigatório: depois de um push, comente |
|
/gandalf |
|
Gandalf, análise 1 · commit Pega-rápidoAntes, era preciso esperar a box do agente iniciar para interagir com a fila. O PR adiciona um canal provisório e reaproveita o protocolo de fila existente, para permitir essa interação durante o boot, conforme a issue #121. InsightsO problema está documentado: o fallback REST aceita mensagens, mas ações de fila exigem o canal direto. Reutilizar o protocolo existente tem valor técnico e evita criar outra API de sessão no Core. O mérito fica duvidoso porque a comparação com outra alternativa não foi registrada: a issue #541 do Copilot descreve fila fria por histórico e comandos, mas não foi verificado por que o stand-in oferece a experiência necessária em vez desse caminho. Qualidade pede os dois ajustes abaixo; não encontrei regressão de autenticação ou isolamento, e o diff não adiciona estado persistente ou varredura que cresça por tenant. Forma da implementaçãoAprovada com ressalvas. Separar HTTP, parser, tipo público e canal direto é coerente. A ressalva é a decisão de replay na transição entre uma box real e um canal provisório; a prova do Stop também não verifica o efeito na fila. Findings
Confiança, comentários e testesConfiança 8/10: li o diff, o fluxo da máquina de estados, os testes, a issue e o contrato atual do produtor; não localizei o produtor futuro nem seus frames reais. O CI terminou verde no SHA revisado: Condição de ativação: habilitar a experiência nos consumidores somente depois que o produtor compatível estiver implantado e os frames de admissão, Stop e handoff forem validados. Registre essa condição no PR do produtor. DecisãoNão aprovaria até os dois ajustes major serem corrigidos. As perguntas sobre produtor e publicação não são bloqueios de merge. O CI está verde; depois dos ajustes, peça nova análise para validar o commit atualizado. Sugestões para próximas revisões: comparar a matriz de transições de canal por origem e destino, incluindo box → provisório; e, nos testes de comandos de fila, afirmar estado final e evento de atualização com mais de um item. Aqui o meu check é obrigatório: depois de um push, comente |
gandalf-the-grey-bot
left a comment
There was a problem hiding this comment.
Sem achados novos no delta desde a análise 1.
|
Gandalf, análise 2 · commit Desde a análise 1: os dois pontos Decisão: mergeável por código; CI verde. Para o GitHub liberar o merge, as conversas ainda abertas também precisam ser resolvidas. Aqui o meu check é obrigatório: depois de um push, comente |
35ca714 to
bf57d17
Compare
|
/gandalf |
1 similar comment
|
/gandalf |
|
Gandalf, análise 3 · commit Desde a análise 2: os dois pontos A integração real ainda não está demonstrada: o produtor mantém frames antigos de admissão, Stop e handoff. Isso não bloqueia por si só o merge desta SDK, mas os consumidores devem esperar um produtor compatível e a validação de integração antes do bump. O CI do SHA revisado terminou verde. Decisão: não aprovaria até os dois ajustes Aqui o meu check é obrigatório: depois de um push, comente |
|
/gandalf |
gandalf-the-grey-bot
left a comment
There was a problem hiding this comment.
Sem findings novos nesta rodada; as duas majors da análise anterior foram corrigidas.
|
Gandalf, análise 4 · commit Desde a análise 3: 2 pontos corrigidos; nenhum ponto anterior segue aberto; nada novo. Decisão: mergeável quando o CI terminar verde. Aqui o meu check é obrigatório: depois de um push, comente |
a9c14a8 to
89a31d3
Compare
|
/gandalf |
gandalf-the-grey-bot
left a comment
There was a problem hiding this comment.
Sem achados novos para comentar em linha nesta rodada.
|
Gandalf, análise 5 · commit Desde a análise 4: nenhum ponto anterior segue aberto e nenhum finding novo. A implementação principal não teve regressão identificada; pacote, lockfile e corpus estão alinhados em Sugestão documental, fora deste PR: atualizar no body do Copilot #550 as referências à SDK de Decisão: mergeável; o CI obrigatório está verde. Aqui o meu check é obrigatório: depois de um push, comente |
89a31d3 to
7fe2067
Compare
|
/gandalf |
|
Gandalf, análise 6 · commit Desde a análise 5: nenhum ponto anterior segue aberto; novo: uma pergunta não bloqueante sobre se Decisão: mergeável quanto ao código. O ruleset exige resolver a conversa inline; CI e Aqui o meu check é obrigatório: depois de um push, comente |
|
/gandalf |
gandalf-the-grey-bot
left a comment
There was a problem hiding this comment.
Sem achados novos no delta desde a análise 6.
|
Gandalf, análise 7 · commit Desde a análise 6: a pergunta sobre a semântica de Decisão: mergeável; o CI está verde e não restam conversas de revisão abertas. Aqui o meu check é obrigatório: depois de um push, comente |
e22be9f to
97a51c0
Compare
|
/gandalf |
|
Gandalf, análise 8 · commit Desde a análise 7: não encontrei regressão nova no comportamento do canal provisório. O bump reintroduz o desalinhamento entre pacote e corpus, e a descrição ainda cita Decisão: não aprovaria até alinhar a versão publicada e o corpus. Aqui o meu check é obrigatório: depois de um push, comente |
…enquanto a box sobe (#121) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/gandalf |
97a51c0 to
c16a5c1
Compare
gandalf-the-grey-bot
left a comment
There was a problem hiding this comment.
Sem achados novos no delta desde a análise 8.
|
Gandalf, análise 9 · commit Desde a análise 8: o rebase não alinhou o pacote Decisão: não aprovaria até alinhar o pacote à versão/corpus preparado e atualizar a descrição. Aqui o meu check é obrigatório: depois de um push, comente |
…r e stop com socket caido da erro (#121) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/gandalf |
|
Gandalf, análise 10 · commit Desde a análise 9: segue aberto o major de alinhamento entre pacote, manifest/corpus e descrição (conversa); há um novo major porque os testes e as garantias de Decisão: não aprovaria até corrigir os dois majors. Aqui o meu check é obrigatório: depois de um push, comente |
|
/gandalf |
gandalf-the-grey-bot
left a comment
There was a problem hiding this comment.
Sem novos findings de linha nesta rodada; os pontos anteriores foram resolvidos.
|
Gandalf, análise 11 · commit Desde a análise 10: os dois pontos major foram resolvidos: a beta pessoal fica sem corpus/manifest, reservados à release oficial; o produtor do Copilot #550 implementa Decisão: mergeável para a SDK beta. Ativar os consumidores somente após implantar o produtor compatível (PR #550). Aqui o meu check é obrigatório: depois de um push, comente |
|
/gandalf |
963e36e to
18ec944
Compare
| if (!link.wire?.message({ ...input, clientMessageId: messageId }, admission)) { | ||
| admission.fail(notSent()) | ||
| } | ||
| }) |
There was a problem hiding this comment.
major holdForTheBox() inicia o prazo de admissão antes de enviar a mensagem e guarda uma closure na outbox. Se o prazo expirar, a promessa falha, mas a closure continua válida e replayComplete ainda pode executar wire.message(). Assim, a mensagem pode sair depois de o chamador receber falha; se ele reenviar, o efeito pode duplicar. Isso contraria a garantia local de agentSession.ts:1396-1398 e o prazo descrito em agentChannel.ts:25-29. Mantenha a admissão pendente até o envio efetivo e arme o prazo nesse momento, ou invalide/remova a entrada da fila em qualquer falha terminal. Teste uma mensagem retida por mais de 35 segundos e depois replay concluído, provando que não é enviada após a falha.
| if (sent) sent.then(resolve, reject) | ||
| else reject(notSent()) | ||
| }) | ||
| }) |
There was a problem hiding this comment.
major O resolve/reject dos comandos da outbox existe apenas dentro da closure. Fechar a sessão durante o handover aborta a conexão e falha as admissões de mensagem, mas não rejeita esse comando; o caminho de reconexão abortado também retorna sem liquidá-lo. Um session.cancel() pendente pode, portanto, ficar sem resolução indefinidamente. O contrato de send em agentChannel.ts:607 e a promessa documentada de cancel() no README exigem que a operação termine com erro quando o canal fecha antes da confirmação. Guarde cada operação como entrada rastreável e rejeite/remova toda a fila no fechamento, aborto ou falha terminal. Acrescente teste de fechamento durante handover com Stop pendente e confirme rejeição e ausência de frames posteriores.
| for (const pending of link.admissions) pending.rearm() | ||
| if (link.handingOver && nextProvisional) flushOutbox() | ||
| } | ||
| const onLost = (error: Error, code?: number) => { |
There was a problem hiding this comment.
major Quando link.handingOver é verdadeiro, onLost() entra no ramo de reabertura imediata e retorna antes de tratar SUPERSEDED_CLOSE_CODE (4409). Se outro socket substituir este durante replay incompleto, as operações retidas escapam do tratamento terminal previsto. A issue #121, S4 exige rediscagem do provisório, exceto em 4409 e aborto. Trate 4409 antes do ramo de handover, rejeitando admissões e operações da outbox; cubra o caso de box adotada, replay incompleto e fechamento 4409.
| const socket = await this.dial(channel.wsUrl, options) | ||
| return { | ||
| close: () => socket.close(), | ||
| ...(channel.provisional === true |
There was a problem hiding this comment.
minor O SDK envia { type: "handover" }, mas o produtor consultado em mitra-copilot#550, SHA e8877a3, ainda rejeita esse tipo com INVALID_MESSAGE (StandInWebSocketHandler.java:76-88). O merge da beta não ativa consumidores por si só, mas a ativação é incompatível até o produtor aceitar essa resposta. Só adote esta SDK no consumidor depois de implantar o parser compatível e validar a troca, ou inclua esse suporte no produtor antes da ativação.
|
Gandalf, análise 12 · commit Desde a análise 11: nenhum ponto anterior segue aberto. No SHA auditado, há 3 novos major: a mensagem pode sair depois de a admissão falhar, o Stop pode ficar pendente ao fechar a sessão e o handover ignora o fechamento terminal 4409. Há também um minor de ativação: o produtor consultado ainda rejeita a resposta Condição de ativação: não adote esta SDK no consumidor até o produtor aceitar a resposta Decisão: não aprovaria o SHA auditado até corrigir os 3 pontos major. O PR ainda aponta para Não encontrei run de CI associado ao SHA auditado; o veredito não considera os testes. Aqui o meu check é obrigatório: depois de um push, comente |
Fecha #121.
O que muda
Com a box fria, o Copilot atende o canal ele mesmo enquanto a box sobe (canal provisório), emitindo exatamente os frames da box viva, sem
sequence. Quando a box fica pronta, ele manda o avisohandovere fecha com 4100 só 15 s depois, como rede de segurança. A box então drena a lista e repete omessageQueuede ostepStartdo mesmo prompt, agora com asequencedo log dela. A SDK recebe só o mínimo de protocolo:Opt-in. No modo
websocket, oPOST /tasks/{id}/channelmanda{ "standIn": true }; no modohttpsegue sem corpo e o Copilot segura o pedido até a box subir, como hoje.agentTasks.channel(id, { standIn })eAgentTaskChannel.provisional?: boolean, lido noexpectAgentTaskChannel.Cursor pela identidade do log. Abrir o provisório não pede replay (ele não tem log). Na troca para a box, o cursor fica onde o histórico termina se o
boxLogda box é o esperado, vai a 0 se é outro, e ohelloainda zera se olastSequencedele é menor que o cursor. Provisório para provisório não pede replay.Sair do provisório não fecha o turno. Sem
lostTurnFramena troca para a box, e o provisório que cai sempre pede o canal de novo (menos 4409 e abort), com ou sem turno. Um turno que começou numa box antes de cair no provisório segue a regra do redial comum contra aquela box: a mesma box e thread seguem do cursor; outra fecha o turno como interrompido.Mesmo turno na box. O
messageQueuede ostepStartque a box repete para o mesmoclientMessageIdeturnIdnão abrem turno novo nem bolha duplicada. A sessão já fazia isso (ostepStartcom turno rodando não abre outro, e a pergunta é deduplicada peloclientMessageId); o PR prova com teste.Fila repetida na troca. Um
messageQueuedque repete um item da fila igual ao que a sessão já tem (mesmo texto, posição equeueHeld) não emitequeueChange. Visto na dev: a box que assume põe no log a fila segura que o provisório mostrou, e o replay emitia umqueueChangeidêntico, um evento a mais que a box viva. Teste: "announces a queued message once when the box takes over the queue the stand-in showed".Troca sem buraco (abrir antes de fechar). No aviso
handover, a sessão pede/channel, abre o socket da box com a mesma decisão de replay do redial e só então fecha o provisório; até lá tudo segue pelo provisório. O 4100 que vem depois é ignorado; um 4100 no meio da troca não abre um segundo socket; uma troca que ainda encontra o provisório deixa o 4100 fazer o redial.Stop com o socket caído dá erro. Com o canal direto aberto e o socket em redial, o Stop é recusado com erro em vez de ir ao Copilot pelo REST, como cancel e edit já eram. Sem canal direto, o Stop segue pelo REST.
A SDK não tem fila, admissão nem Stop próprios para o boot: isso tudo vem dos frames.
Mudança de comportamento
websocketo pedido do canal passa a levar corpo{ "standIn": true }. Copilot sem o canal provisório ignora o corpo e responde como hoje, então com ele tudo fica igual à 0.3.7 (fixturessession-paritysem mudança).Dependência e release
handover(mitralab-dev/mitra-copilot#550). Sem ele, nada muda.package.json, para a réplica pessoal de teste da fila; sem corpus nemcurrentno manifest, que entram quando a fila for para uma release oficial.contracts/igual ao da main.Testes
npm test: 763 de 763 (16 arquivos). EmagentChannel.test.ts, bloco do canal provisório com 18 testes:turnStart;boxLogpede replay do fim do histórico, outroboxLogpede 0,hellomenor que o cursor zera, provisório para provisório não pede replay;historye a mesmaqueue, fora asequenceque o provisório não tem: (a) enviar, enfileirar dois, editar, cancelar e promover para steer no boot; (b) Stop no boot com a fila segura (queueHeld) e nova mensagem que roda na box. Os frames seguem o contrato do sidecar (mitralab-dev/mitra-sandbox#767):turnIdé o id do prompt, o provisório mandaactivityIdeturnSequencenulos e a box os preenche;httpnão pedestandIn; módulo manda o corpo só quando pedido;channelReconnecting; mensagem durante a troca vai pelo provisório e depois pela box; 4100 no meio da troca não abre segundo socket; troca que ainda encontra o provisório deixa o 4100 fazer o redial; Stop com o socket caído dá erro, sem REST.Contra a
main, sem a mudança emagentChannel.ts, 6 desses testes falham (os dois de paridade incluídos).typecheck,lint,format:check,build,check:exports,check:contractsesmoke:packageverdes.🤖 Generated with Claude Code