Skip to content

Commit 07a93c2

Browse files
committed
test: cover safety-buffering stream metadata
1 parent 421ceb7 commit 07a93c2

5 files changed

Lines changed: 134 additions & 0 deletions

File tree

docs-site/src/content/docs/reference/runtime-routes.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ account helpers, analytics posting, thread-goal helpers, memory summaries,
211211
search helpers, realtime helper calls, safety helper calls, identity JWKS, or
212212
reset-credit consume operations. Configure Codex clients by pointing
213213
`model_providers.*.base_url` at `/backend-api/codex`.
214+
Supported Responses stream event metadata is relayed on model-provider streams as upstream sends it. Codex Pooler does not synthesize app-server notifications such as `turn/safetyBuffering/updated`.
214215

215216
## Backend bridge and usage routes
216217

test/codex_pooler/gateway/request_compression/token_counter_test.exs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@ defmodule CodexPooler.Gateway.RequestCompression.TokenCounterTest do
3131
assert {:ok, 51, %{encoding: "cl100k_base"}} = TokenCounter.count("gpt-4-turbo", output)
3232
end
3333

34+
test "counts literal special-token-looking strings as ordinary text" do
35+
content = """
36+
tool output can contain <|endoftext|>
37+
diff markers can contain <|fim_prefix|>, <|fim_middle|>, and <|fim_suffix|>
38+
"""
39+
40+
assert {:ok, o200k_count, %{encoding: "o200k_base"}} =
41+
TokenCounter.count("gpt-4o", content)
42+
43+
assert o200k_count > 0
44+
45+
assert {:ok, cl100k_count, %{encoding: "cl100k_base"}} =
46+
TokenCounter.count("gpt-4-turbo", content)
47+
48+
assert cl100k_count > 0
49+
end
50+
3451
test "matches oracle counts for unicode and diff-like content" do
3552
unicode = "unicode sample: ciao mondo, こんにちは, Привет, مرحبا, 😀"
3653

test/codex_pooler/gateway/transports/stream_protocol_test.exs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,35 @@ defmodule CodexPooler.Gateway.Transports.Streaming.StreamProtocolTest do
9393
|> StreamProtocol.decode_sse_data()
9494
end
9595

96+
test "preserves safety-buffering metadata on public Responses stream events" do
97+
state = StreamProtocol.public_openai_responses_stream_state()
98+
99+
event =
100+
sse_event("response.output_text.delta", %{
101+
"type" => "response.output_text.delta",
102+
"delta" => "visible synthetic safety-buffered text",
103+
"safety_buffering" => %{
104+
"model" => "safety-buffering-model-sentinel",
105+
"use_cases" => ["cyber"],
106+
"reasons" => ["user-risk-sentinel"]
107+
}
108+
})
109+
110+
assert {chunk, _state} =
111+
StreamProtocol.normalize_public_openai_responses_sse_data(event, state)
112+
113+
assert [%{"event" => "response.output_text.delta", "data" => data}] =
114+
public_sse_events(chunk)
115+
116+
assert data["delta"] == "visible synthetic safety-buffered text"
117+
118+
assert data["safety_buffering"] == %{
119+
"model" => "safety-buffering-model-sentinel",
120+
"use_cases" => ["cyber"],
121+
"reasons" => ["user-risk-sentinel"]
122+
}
123+
end
124+
96125
test "synthesizes missing reasoning and message output item ids" do
97126
state = StreamProtocol.public_openai_responses_stream_state()
98127

test/codex_pooler/gateway/transports/websocket_codec_test.exs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,37 @@ defmodule CodexPooler.Gateway.Transports.Streaming.WebsocketCodecTest do
141141
refute Process.get({:websocket_sse_buffer, request_id})
142142
end
143143

144+
test "preserves safety-buffering metadata from upstream SSE frames" do
145+
request_id = "websocket-safety-buffering"
146+
147+
sse =
148+
"event: response.output_text.delta\n" <>
149+
"data: " <>
150+
Jason.encode!(%{
151+
"type" => "response.output_text.delta",
152+
"delta" => "visible synthetic safety-buffered text",
153+
"safety_buffering" => %{
154+
"model" => "safety-buffering-model-sentinel",
155+
"use_cases" => ["cyber"],
156+
"reasons" => ["user-risk-sentinel"]
157+
}
158+
}) <>
159+
"\n\n"
160+
161+
assert {[message], ""} = WebsocketCodec.stream_messages(request_id, sse, "")
162+
163+
assert %{
164+
"type" => "response.output_text.delta",
165+
"safety_buffering" => safety_buffering
166+
} = Jason.decode!(message)
167+
168+
assert safety_buffering == %{
169+
"model" => "safety-buffering-model-sentinel",
170+
"use_cases" => ["cyber"],
171+
"reasons" => ["user-risk-sentinel"]
172+
}
173+
end
174+
144175
test "drops oversized incomplete SSE buffers instead of retaining them" do
145176
attach_stream_buffer_telemetry()
146177
request_id = "websocket-buffer-oversized"

test/codex_pooler_web/controllers/runtime/backend_codex_controller_test.exs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6615,6 +6615,62 @@ defmodule CodexPoolerWeb.Runtime.BackendCodexControllerTest do
66156615
assert_turn_state_not_persisted!(setup, response_turn_state)
66166616
end
66176617

6618+
test "POST /backend-api/codex/responses relays stream safety-buffering metadata without persisting it",
6619+
%{conn: conn} do
6620+
safety_buffering = %{
6621+
"model" => "safety-buffering-model-sentinel",
6622+
"use_cases" => ["cyber"],
6623+
"reasons" => ["user-risk-sentinel"]
6624+
}
6625+
6626+
upstream =
6627+
start_upstream(
6628+
FakeUpstream.sse_stream([
6629+
{"response.output_text.delta",
6630+
%{
6631+
"type" => "response.output_text.delta",
6632+
"delta" => "visible synthetic safety-buffered text",
6633+
"safety_buffering" => safety_buffering
6634+
}},
6635+
{"response.completed",
6636+
%{
6637+
"type" => "response.completed",
6638+
"response" => %{
6639+
"id" => "resp_backend_stream_safety_buffering",
6640+
"usage" => %{"input_tokens" => 4, "output_tokens" => 3, "total_tokens" => 7}
6641+
}
6642+
}}
6643+
])
6644+
)
6645+
6646+
setup = gateway_setup(upstream)
6647+
6648+
conn =
6649+
conn
6650+
|> auth(setup)
6651+
|> post("/backend-api/codex/responses", %{
6652+
"model" => setup.model.exposed_model_id,
6653+
"input" => "synthetic streaming safety-buffering relay request",
6654+
"stream" => true
6655+
})
6656+
6657+
assert conn.resp_body =~ "event: response.output_text.delta\n"
6658+
assert conn.resp_body =~ ~s("safety_buffering":)
6659+
assert conn.resp_body =~ "safety-buffering-model-sentinel"
6660+
assert conn.resp_body =~ "user-risk-sentinel"
6661+
assert conn.resp_body =~ "data: [DONE]\n\n"
6662+
6663+
assert [request] = Repo.all(from(r in Request, where: r.pool_id == ^setup.pool.id))
6664+
assert request.status == "succeeded"
6665+
6666+
assert [attempt] = Repo.all(from(a in Attempt, where: a.request_id == ^request.id))
6667+
assert attempt.status == "succeeded"
6668+
6669+
metadata_text = inspect({request.request_metadata, attempt.response_metadata})
6670+
refute metadata_text =~ "safety-buffering-model-sentinel"
6671+
refute metadata_text =~ "user-risk-sentinel"
6672+
end
6673+
66186674
test "POST /backend-api/codex/responses/compact keeps opencode continuity headers local without forwarding",
66196675
%{
66206676
conn: conn

0 commit comments

Comments
 (0)