Public: anyone can read this; the crew can change it.
GET /api/v1/conversation/turns carries an ETag and answers a repeat with 304 until a turn, a queued message or the running state changes #9287
Check · Review · Land · Live done — Landed and live in production.
`GET /api/v1/conversation/turns` now sends a weak ETag and answers a repeat with a bodiless 304. The type check is clean and the new tests pass, along with `test/conversation-talk.test.ts` and `test/talk-page.test.ts`. I did not run the whole suite.
shipped production is serving it deploy 4915f35
GET /api/v1/conversation/turns now sends a weak ETag and answers a repeat with a bodiless 304. The type check is clean and the new tests pass, along with test/conversation-talk.test.ts and test/talk-page.test.ts. I did not run the whole suite.
What changed
- The tag: it is computed from the exact JSON the route sends (
running,conversation,queued,turns), using the repo'sweakEtagandholdshelpers, as in the upstream route.before,limitand the conversation id change the body, so each gets its own tag. - Headers: a 304 carries
etag,Cache-Control: privateandVary: authorization, cookie, and the usual security-floor headers are on it too. The 401 and 404 paths return before any tag is made. - Code: the change is in
src/http/api/conversation_talk.ts.
What the tests check
They are in test/conversation-queue-api.test.ts, next to the other queue tests, because it already has a held-open fake run.
- A repeat gives 304.
- A run starting, a message being queued, a message being cancelled and the run ending each change the tag.
- Cancelling the queued message brings back the running tag.
limit=1gives a different tag from the default.- A tag from one person's read gets a 200 for another person.
- The 304 carries the security headers.
- Both new tests fail when the route change is stashed.
Not done
I did not add a case for a new turn changing the tag. The "run ending" step in the first test covers a turn being stored. scripts/gate.ts printed nothing when I ran it.
To try it
bun test test/conversation-queue-api.test.ts
🤖 Generated with Claude Code
I changed nothing and pushed nothing for this failure. The deploy log shows the app booted, / answered, and the log ended with done and ready at the preview URL. The only complaint is "no tests declared, none run".
forge.json is the same as on main. It has no test entry; its checks are check.fast, check.run and check.verify, and none of them is part of the preview deploy. Adding a test declaration would change how the repo's checks are configured, which is beyond this issue. The change is in commit 73d3090.
The tests for my change pass locally. The forge's check runs on the pull and decides whether it can land.
If that "no tests declared" message should block previews, a person needs to decide how forge.json should declare tests.
GET /api/v1/conversation/turns now sends an ETag and answers a repeat request with 304. It does this until a turn, a queued message or the running state changes.
The earlier check failed because no commit message had a "Try:" line. I added an empty commit whose message has one, since force pushes are refused and I couldn't amend the existing commit. No code changed, so I didn't rerun tsc or the tests. bun scripts/gate.ts printed nothing when I ran it, and the push went through. I haven't seen the forge's check result on the new push yet.
Try it: request /api/v1/conversation/turns on the preview (https://lab--9287--forge-trevato-apps.open-platform.sh) with authorization: Bearer $FORGE_TOKEN and note the ETag. Repeat the request with If-None-Match set to that value and expect a 304.
🤖 Generated with Claude Code
Clean and small: the tag is over the exact bytes sent after auth and access are settled, 304 carries etag, private cache-control and vary, the floor headers come from the shared response path, and the tests cover repeat, run start, queue, cancel, run end, limit. Non-blocking: the sibling /api/v1/conversations route salts the tag with user.id and uses private, no-cache; consider the same here. before and a stored new turn have no direct test (covered by construction since the body is what is tagged).
GET /api/v1/conversation/turnsnow sends a weak ETag and answers a repeat with a bodiless 304. The type check is clean and the new tests pass, along withtest/conversation-talk.test.tsandtest/talk-page.test.ts. I did not run the whole suite.What changed
running,conversation,queued,turns), using the repo'sweakEtagandholdshelpers, as in the upstream route.before,limitand the conversation id change the body, so each gets its own tag.etag,Cache-Control: privateandVary: authorization, cookie, and the usual security-floor headers are on it too. The 401 and 404 paths return before any tag is made.src/http/api/conversation_talk.ts.What the tests check They are in
test/conversation-queue-api.test.ts, next to the other queue tests, because it already has a held-open fake run.limit=1gives a different tag from the default.Not done I did not add a case for a new turn changing the tag. The "run ending" step in the first test covers a turn being stored.
scripts/gate.tsprinted nothing when I ran it.To try it
bun test test/conversation-queue-api.test.ts🤖 Generated with Claude Code
Closes #9278