feat(service,host): a sent message is confirmed once its row reaches the live transcript
Draft
CH
5d ago+206+206+012345678901234567890123456789-30-30-01234567890123456789
A small follow-up so the agent chat feels smoother, stacked on #4181. It follows Neon's guide to optimistic mutations (https://neon.com/docs/ai/skills/neon-realtime/references/mutations.md): the write returns its transaction id, and the client waits for that transaction on its live subscription before it confirms.
What changed
- Database (
writer.ts): the message insert'sRETURNINGalso readspg_current_xact_id()::text, andwriteAwaitingLineanswers thattxidwhen it wrote the row. No extra round trip is needed. A line that was already standing under its key answers no txid. - Service:
steerCodingAgentWrittenanswers the outcome beside the txid, andsteerCodingAgentkeeps its answer for every other caller.- The send route (
POST /api/agents/{id}/messages) answers{ agent, txid? }. - The new wire schemas are
codingAgentMessageAnswerSchemaandcodingAgentMessageAnswerViewSchema, recorded inhosted-wire-schemas.test.tswith goldens generated underLUKE_UPDATE_FIXTURES=1. Released desktops ignore the extra key.
- Host:
live-follow.tshands each part's subscription to an optionalonSubscribed, and the transcript follow keeps its messages part.- Before
codingAgents.messageconfirms, it callsawaitTranscriptTxId. Where a window follows that agent's transcript, this callsawaitTxId(txid, 10_000)on the messages subscription. - The wait is skipped where no window follows the transcript, or where the send answered no txid.
- A timeout or error still confirms the send.
- The txid stays in the host; the window's answer is unchanged.
Tests
coding-agent-store.test.ts: a written line answers a decimal txid, and a repeat answers none.compose-coding-agents.test.ts: with no transcript followed the send confirms at once. With one followed, the host waits on the messages subscription for the send's txid.- The send tests in
coding-agents-app.test.tsread the answer with the new schema.
Checks run locally
pnpm check:affected gets OOM-killed in the sandbox, so I ran its pieces one at a time:
repository-checks.sh,biome check .,oxlint,kniptscfor database, features, host, service and web- vitest for features, host, the service's
coding-agents-app(194 tests), and the store test
What to check by hand
Send an agent a message while its tab is open. The line appears at once and stays put, with no flicker or jump when the service's row replaces it.
Made with Luke