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

Offen
#5,056 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

Dieses Issue hat noch niemand übernommen.

  • #5063 von @ghazy2001 — ohne Merge geschlossen

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
1-2 Tage
Anfängerfreundlichkeit
72/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
node.js, typescript
Bereich
api, backend

Rechercherichtung

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.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

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.

Vorherrschende Sprache
TypeScript
Sterne
16.5k
Forks
1.5k
Ø Merge
1 T. 15 Std.
Gemergte PRs (30 T.)
17

Entwicklungsumgebung

Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus triggerdotdev/trigger.dev

Alle Issues in triggerdotdev/trigger.dev

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.