Skip to content

Commit 0a1abe7

Browse files
committed
docs(chat): describe the resume cursor accurately in the changeset and API docs
The changeset only mentioned the new mailbox helpers, and led with them. The change a user is most likely to care about is that a chat could silently lose a message, which affected the managed agent too, so the release note now leads with that and with the retried-send duplicate. `chat.writeTurnComplete()` also promised that `sessionInEventId` identified the exact input record the turn acknowledged. It does not: it is the cursor that is safe to resume from, held back behind any message still waiting to be handled, so a value below the record just handled is expected rather than a fault.
1 parent 839c046 commit 0a1abe7

2 files changed

Lines changed: 23 additions & 6 deletions

File tree

.changeset/tidy-mailboxes-wait.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@
33
"@trigger.dev/sdk": patch
44
---
55

6-
Custom agent loops can now inspect pending chat input without consuming it and consume one mailbox record at a time with `chat.messages.hasPending()` and `chat.messages.next()`. Mailbox records include stable identifiers for tracing and redelivery.
6+
Fixes a case where a chat could silently lose a message. If a message arrived while the agent was between turns and a stop arrived after it, the cursor the next boot resumed from could point past that message, so it was never answered and no error was raised. This affected `chat.agent`, not just custom agents.
77

8-
A control record that nothing on the run consumes is now discarded rather than left at the head of the `.in` channel, where it would have made every message queued behind it undeliverable. `chat.messages.next()` returning `undefined` means no message became consumable before the timeout.
8+
Also fixes a retried send being answered twice. When a send was retried and its idempotency claim was lost, the agent could consume the same message a second time.
9+
10+
Custom agent loops can now inspect pending chat input without consuming it, and consume one mailbox record at a time, with `chat.messages.hasPending()` and `chat.messages.next()`. Records carry stable identifiers so a redelivery is recognisable.
11+
12+
```ts
13+
if (await chat.messages.hasPending()) {
14+
const record = await chat.messages.next({ timeoutInSeconds: 0 });
15+
if (record) handle(record.payload);
16+
}
17+
```
18+
19+
A control record that nothing on the run consumes is now discarded rather than left at the head of the input channel, where it would have made every message queued behind it undeliverable. `chat.messages.next()` returning `undefined` means no message became consumable before the timeout.
20+
21+
`chat.writeTurnComplete()`'s `sessionInEventId` is the cursor that is safe to resume from, not the sequence of the record the turn answered. It is held back behind any message still waiting to be handled, so a value below the record you just handled is expected.

packages/trigger-sdk/src/v3/ai.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9131,10 +9131,14 @@ function createStopSignal(): {
91319131
* task instead of round-tripping them back from the client:
91329132
* - `lastEventId` — the turn-complete control record's seq_num on
91339133
* `session.out`; where the next turn's output stream resumes.
9134-
* - `sessionInEventId` — the committed-consume cursor on `session.in` as of
9135-
* this turn-complete, letting a raw loop correlate the boundary with the
9136-
* exact input record it acknowledged. Trigger owns input-cursor recovery,
9137-
* so this is for correlation / out-of-sync detection, not required.
9134+
* - `sessionInEventId` — the safe-to-resume-from cursor on `session.in` as of
9135+
* this turn-complete. It is the highest sequence that can be resumed past
9136+
* without skipping an unhandled message, so it is held back behind any
9137+
* message still buffered unconsumed and is NOT necessarily the sequence of
9138+
* the record this turn answered. Trigger owns input-cursor recovery, so this
9139+
* is for correlation / out-of-sync detection, not required. Treat it as a
9140+
* lower bound: a value below the record you just handled is expected, not a
9141+
* sign of a lost turn.
91389142
*
91399143
* Either is `undefined` when the corresponding cursor isn't available.
91409144
*

0 commit comments

Comments
 (0)