Repository navigation
HPB live feed + gap-fill poll + auto-enable captions - #4
Merged
Merged
Conversation
ikusteu
force-pushed
the
feat/d-830-live-ui-hpb-feed
branch
3 times, most recently
from
October 30, 2026 21:40
f10db6f to
e8ddfae
Compare
The panel no longer polls for the live feed. It takes finals from Talk's
signalling in near-real-time and polls /history only to fill gaps, deliver
joins and catch up — both sources sharing ONE seq space, so the merge is
exact (no content-matching, no duplicates, no drops).
- Server (0.10.0, no bump): send_transcript stamps each HPB final with its
buffer seq. Talk's filtered 'transcript' event drops extra fields, but the
raw signalling 'message' event keeps them — so the browser gets the seq.
- tap.js: subscribe to connection.on('message') (what Talk's own SimpleWebRTC
uses) for the raw payload incl. seq; emit finals (seq) and partials; still
sees own lines; re-attaches on rejoin.
- store.js: a reorder buffer over the shared seq — render at applied+1, hold
out-of-order live finals until the gap fills, dedup by seq, and step over
entries the server has evicted. Append-only rendering.
- session.js: poll is demoted to gap-fill/joins, asking since=<contiguous seq>
every ~3s; on a call start it enables captions for this session.
- captions.js: POST Talk's live-transcription endpoint on activation, so every
viewer is on the HPB feed (idempotent, best-effort).
Feasibility note (Ivan asked to flag blockers): the seq cannot ride the
filtered 'transcript' event, but it does ride the raw 'message' event — so the
design is clean, with no WebSocket monkey-patching and no fuzzy correlation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WEKiygi6s6G31srWmN5rnz
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WEKiygi6s6G31srWmN5rnz
ikusteu
force-pushed
the
feat/d-830-live-ui-hpb-feed
branch
from
October 30, 2026 21:53
e8ddfae to
e6114aa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #3 (base is
feat/d-830-live-ui, notmain) — review after it.What
A followup that changes how the transcript panel gets the live feed, and makes it self-activating:
/historyonly to fill gaps, deliver joins, and catch up. Both sources share one seq space, so the merge is exact — no duplicates, no drops, no content-matching.How the two streams share a seq
The worry was correlating a live stream and a polled stream without a shared id. Talk's filtered
SimpleWebRTC.on('transcript')event hardcodes four fields and drops aseq, but the rawconnection.on('message')event (what Talk's own SimpleWebRTC listens to) carries the full payload. So cassini-live stamps each HPB final with its bufferseq, the browser reads it off the raw message event, and the live feed and the poll key into the same timeline. No WebSocket monkey-patching, no fuzzy matching.send_transcript): each HPB final carries its bufferseq. Version unchanged (0.10.0).tap.js: subscribe toconnection.on('message'); emit finals (with seq) + partials; re-attach on rejoin.store.js: a reorder buffer over the shared seq — render atapplied+1, hold out-of-order live finals until the gap fills, dedup by seq, step over server-evicted entries. Append-only.session.js: poll demoted to gap-fill/joins,since=<contiguous seq>, ~3s; enables captions on call start.captions.js: POSTs Talk'slive-transcriptionendpoint (idempotent, best-effort).Validation
docs/transcript-panel-harness.png.Note
The live feed reads a Talk-internal
connection.on('message')event — stable (Talk routes its own messages through it), withwindow.signalingSocketas a raw fallback if a future Talk version changes signalling internals.🤖 Generated with Claude Code
https://claude.ai/code/session_01WEKiygi6s6G31srWmN5rnz