fix: disable HTTP caching on run log endpoints (#3724)

## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - Every run emits a streaming log that the web UI polls so humans can
watch what the agent is doing
> - Log responses go out without explicit cache directives, so Express
adds an ETag
> - If the first poll lands before any bytes have been written, the
browser caches the empty / partial snapshot and keeps getting `304 Not
Modified` on every subsequent poll
> - The transcript pane then stays stuck on "Waiting for transcript…"
even after the log has plenty of content
> - This pull request sets `Cache-Control: no-cache, no-store` on both
run-log endpoints so the conditional-request path is defeated

## What Changed

- `server/src/routes/agents.ts` — `GET /heartbeat-runs/:runId/log` now
sets `Cache-Control: no-cache, no-store` on the response.
- Same change applied to `GET /workspace-operations/:operationId/log`
(same structure, same bug).

## Verification

- Reproduction: start a long-running agent, watch the transcript pane.
Before the fix, open devtools and observe `304 Not Modified` on each
poll after the initial 200 with an empty body; the UI never updates.
After the fix, each poll is a 200 with fresh bytes.
- Existing tests pass.

## Risks

Low. Cache headers only affect whether the browser revalidates; the
response body is unchanged. No API surface change.

## Model Used

Claude Opus 4.6 (1M context), extended thinking mode.

## Checklist

- [x] Thinking path traces from project context to this change
- [x] Model used specified
- [x] Tests run locally and pass
- [x] CI green
- [x] Greptile review addressed
This commit is contained in:
Jannes Stubbemann 2026-04-15 16:53:25 +02:00 committed by GitHub
parent 3fa5d25de1
commit 7463479fc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2493,6 +2493,7 @@ export function agentRoutes(db: Db) {
limitBytes: Number.isFinite(limitBytes) ? limitBytes : 256000,
});
res.set("Cache-Control", "no-cache, no-store");
res.json(result);
});
@ -2527,6 +2528,7 @@ export function agentRoutes(db: Db) {
limitBytes: Number.isFinite(limitBytes) ? limitBytes : 256000,
});
res.set("Cache-Control", "no-cache, no-store");
res.json(result);
});