Repository navigation
ThinkWatch v3.9.1
Images
ghcr.io/thinkwatchproject/think-watch-server:3.9.1ghcr.io/thinkwatchproject/think-watch-web:3.9.1
Helm
helm install think-watch ./think-watch-3.9.1.tgz \
--namespace thinkwatch --create-namespaceA conversation whose history a provider encrypted, such as a Codex
conversation over OpenAI's Responses API, now stays with that provider
instead of failing on every turn once it moves, and a provider that
cannot read such history says why. The thinkwatch-core crates move from
v0.77.0 to v0.81.0.
No setting, schema or API route changes.
Fixed
- A conversation whose history a provider encrypted goes back to that
provider. OpenAI's Responses API withstore: false(Codex always
sends it) hands the client encrypted state that comes back every turn:
reasoning, remote compactions, Codex's messages between agents,
encrypted tool output. Only the account that encrypted it can read it,
so a conversation that moved to another provider — after five idle
minutes, a tripped breaker or a failover — was refused on every turn
from then on withinvalid_encrypted_content. The gateway now
remembers, for 30 days and whatever the affinity settings say, the
provider that last answered each conversation (the authenticated user
and the request'sx-session-id, or else the session header the client
sends by itself, such as Codex'ssession_id; over HTTP and over the
WebSocket). The log row'ssession_idstill comes fromx-session-id
only. A
Responses request carrying encrypted content that cannot be left out
goes only to that provider: no strategy pick, no failover, and its open
breaker does not stop it. When that provider has no route for the model
any more, the request is refused up front with 409, naming the provider
and saying to start a new conversation. A request carrying only
encrypted reasoning goes to that provider first and still fails over.
Requests that name no conversation are routed as before. The request's log
row records"pinned_by": "encrypted_history"when the provider was
picked this way. - A provider that cannot read a conversation's encrypted history says
so. Its refusal, as a 4xx answer or as the error event of a stream
that opened with 200, now reaches the caller and the log as
SealedHistoryRefused: the provider cannot read this conversation's
encrypted history because another provider encrypted it; route the
conversation back to that provider or start a new conversation. The
upstream's own words follow. It no longer counts against the route's
breaker.