fix(extensions): clear Twilio playback on interrupt#1343
Conversation
🦋 Changeset detectedLatest commit: 2a871c9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7568368975
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // finished streaming and the base transport has reset its audio state. | ||
| // Always clear Twilio playback first, then let the base transport truncate | ||
| // the OpenAI conversation item if it still has one to truncate. | ||
| this.#clearTwilioAudio(); |
There was a problem hiding this comment.
Skip clear until streamSid is initialized
interrupt() now unconditionally calls #clearTwilioAudio(), but #streamSid starts as null and is only populated after a Twilio start message. If an app calls interrupt() before that event (for example during early connection lifecycle), this sends {"event":"clear","streamSid":null}, which is not a valid stream target and can produce a no-op/protocol error instead of a safe interrupt. Please guard the clear path on a non-null stream SID.
Useful? React with 👍 / 👎.
Guard #clearTwilioAudio when interrupt runs before the Twilio start event. Add regression test for early interrupt lifecycle. Addresses Codex review on openai#1343. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Thanks @chatgpt-codex-connector — addressed in 7568368+:
CI was already green; pushed to |
|
Note To use Codex here, create an environment for this repo. |
|
@chatgpt-codex-connector Addressed in latest push (guard `#clearTwilioAudio` until `streamSid` is set + regression test). Note: upstream CI workflow is `action_required` on fork PRs (run 26269351443) — needs a maintainer to approve the workflow run. Changeset check is green. |
|
Note To use Codex here, create an environment for this repo. |
|
@openai-maintainers Friendly heads-up: CI workflow run needs approval on fork PRs (run 26269351443 — Latest push addresses Codex P2 (guard |
|
@codex feedback addressed (streamSid guard + test). Fork workflow may need maintainer approval to run full CI — happy to rebase if anything else comes up. |
|
Note You have reached your Codex usage limits. You can see your limits in the Codex usage dashboard. |
|
@seratch @dkundel-openai Twilio interrupt fix (#1173): guard |
b37e5a9 to
ae05b31
Compare
Guard Twilio clear when streamSid is not set yet (interrupt before start). Add regression test for early interrupt lifecycle.
ae05b31 to
2a871c9
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2a871c99e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // finished streaming and the base transport has reset its audio state. | ||
| // Always clear Twilio playback first, then let the base transport truncate | ||
| // the OpenAI conversation item if it still has one to truncate. | ||
| this.#clearTwilioAudio(); |
There was a problem hiding this comment.
Preserve conversation state when clearing buffered audio
When interrupt() is called after OpenAI has emitted response.output_audio.done but Twilio is still playing buffered audio—the scenario this override targets—#clearTwilioAudio() stops playback, but super.interrupt() immediately returns because the websocket transport reset #currentItemId/_firstAudioTimestamp in _afterAudioDoneEvent(). That means no conversation.item.truncate is sent, so the model keeps the full assistant response in history even though the caller did not hear the cleared tail; subsequent turns can then rely on unheard content. The clear needs to be paired with a way to truncate using the last Twilio mark/item state, or skipped when truncation is no longer possible.
Useful? React with 👍 / 👎.
Summary
TwilioRealtimeTransportLayer.interrupt()path before delegating to the base transport._interrupt()responsible for OpenAI item truncation while avoiding duplicate Twilioclearevents when the base interrupt path dispatches to it.Test Plan
CI=1 PATH=/tmp/corepack-pnpm-shim:$PATH bash .agents/skills/code-change-verification/scripts/run.shPATH=/tmp/corepack-pnpm-shim:$PATH pnpm exec vitest run --project @openai/agents-extensions test/TwilioRealtimeTransport.test.tsPATH=/tmp/corepack-pnpm-shim:$PATH pnpm -F @openai/agents-extensions build-checkCI=1 PATH=/tmp/corepack-pnpm-shim:$PATH pnpm changeset:validate-result -- /tmp/changeset-validation-result.jsonCI=1 PATH=/tmp/corepack-pnpm-shim:$PATH pnpm changeset:validate-lite -- --base origin/main --head HEADCloses #1173