chat.headStart relay ends the first turn after one empty session.out long-poll window (SDK 4.7.7)

Aberta
#5,056 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

  • #5063 de @ghazy2001 — fechado sem integrar

Avaliação

Dificuldade
4/5
Tempo estimado
1-2 dias
Facilidade para iniciantes
72/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
node.js, typescript
Domínio
api, backend

Direção de pesquisa

Start by reading stitchHandoverStream in dist/esm/v3/chat-server.js and the stream timeout section in docs/ai-chat/client-protocol.mdx; compare its EOF handling with the browser transport's resumeAfterEof. Check how the relay tracks the last event ID and handles aborts. Done means an empty long-poll window does not close the first turn before turn-complete; verify the behavior with the 90-second sleeping-tool reproduction.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

chat.headStart relay ends the first turn after one empty session.out long-poll window

SDK: @trigger.dev/sdk 4.7.7 (also present in 0.0.0-rc-4-8-0-20261021151928 and 4.8.0-webhooks.20261020092920)

What happens

On a head-start first turn, stitchHandoverStream (dist/esm/v3/chat-server.js) reads the agent's session.out once with apiClient.subscribeToSessionStream. When a tool runs for more than ~60 s without writing a record, the long-poll window closes empty, the for await loop ends, the relay writes trigger:session-state and closes the response — without trigger:turn-complete. The browser transport's sendMessagesViaHandover then clears isStreaming, so the UI treats the turn as finished while the agent run keeps going and later completes normally.

Measured in a browser: the /api/chat body ended 59,994 ms and 60,003 ms after the last chunk, both times with trigger:session-state and no turn-complete.

Why it looks like a bug

docs/ai-chat/client-protocol.mdx § Stream timeout: "If nothing arrives by the deadline, the server sends data: [DONE] and closes. Reconnect with Last-Event-ID to continue." The browser transport does this (resumeAfterEof); the head-start relay does not.

Repro

  1. chat.headStart route + chat.agent with a tool that sleeps 90 s without writing to the stream.
  2. Send the first message of a new chat through the transport's headStart option.
  3. The response ends ~60 s into the tool; the run finishes the turn later.

Fix we are running (patch on 4.7.7)

Loop the session.out read until turn-complete or abort, resuming from the last seen record, with waitBeforeEofResubscribe between empty windows:

let emptyWindows = 0;
while (!turnComplete && !subscriptionSignal.aborted) {
  if (emptyWindows > 0) await waitBeforeEofResubscribe(emptyWindows, subscriptionSignal);
  let windowHadRecords = false;
  const resumeFrom = latestEventId ?? customerLastEventId;
  const agentStream = await apiClient.subscribeToSessionStream(chatId, "out", {
    ...(resumeFrom != null ? { lastEventId: resumeFrom } : {}),
    signal: subscriptionSignal,
    onPart: (part) => { windowHadRecords = true; if (part.id) latestEventId = part.id; },
    onControl,
  });
  // existing for-await / AbortError handling
  emptyWindows = windowHadRecords ? 0 : emptyWindows + 1;
}

Related: docs/ai-chat/fast-starts.mdx says the handler keeps the response open for the whole first turn, so the serverless maxDuration must cover it. It may be worth noting that a first turn longer than the platform maximum still ends the relay, and that the transport does not fall back to session.out when the head-start response ends or errors before turn-complete.

Linguagem predominante
TypeScript
Estrelas
16.5k
Forks
1.5k
Merge médio
1d 15h
PRs com merge (30d)
17

Preparar o ambiente

Este projeto não oferece contêiner de desenvolvimento, Dockerfile nem guia de contribuição, então a configuração fica por sua conta: comece pelo README e veja nosso guia da primeira contribuição para os passos gerais.

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de triggerdotdev/trigger.dev

Todas as issues de triggerdotdev/trigger.dev

Issues semelhantes

Mais issues de TypeScript

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.