Skip to content

Commit 765d8a7

Browse files
committed
feat(gateway): expand request compression coverage
- add lossless JSON object compression and broader diagnostic log detection - keep request-log compression badges token-only and suppress zero savings
1 parent 689a73f commit 765d8a7

20 files changed

Lines changed: 380 additions & 38 deletions

File tree

README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,11 +1345,7 @@ admin, MCP, usage, and control-plane requests are not eligible; public
13451345
dispatch.
13461346

13471347
Request compression is request-side only. Codex Pooler does not store raw tool
1348-
outputs, does not store raw response bodies, and does not implement
1349-
CCR/retrieval. Request logs may show `payload_compression` metadata with safe
1350-
aggregate savings only, preferring saved token count and percent when local
1351-
token counts are available and falling back to byte savings when token counts
1352-
are unavailable.
1348+
outputs or raw response bodies.
13531349

13541350
## Operator MCP Service
13551351

lib/codex_pooler/accounting/metadata.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ defmodule CodexPooler.Accounting.Metadata do
5454
@payload_compression_strategy_names ~w(
5555
diff
5656
json_array_lossless
57+
json_document_lossless
5758
log_output
5859
search_results
5960
)

lib/codex_pooler/accounting/request_logs.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,9 @@ defmodule CodexPooler.Accounting.RequestLogs do
576576
end
577577

578578
defp payload_compression_metric_available?(saved, percent, original, compressed) do
579-
is_integer(saved) and is_number(percent) and is_integer(original) and is_integer(compressed) and
580-
original > 0
579+
is_integer(saved) and saved > 0 and is_number(percent) and percent > 0 and
580+
is_integer(original) and original > 0 and is_integer(compressed) and compressed >= 0 and
581+
compressed < original
581582
end
582583

583584
defp maybe_put_saved_count(metadata, original_key, compressed_key, saved_key) do

lib/codex_pooler/gateway/payloads/request_options.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ defmodule CodexPooler.Gateway.Payloads.RequestOptions do
103103
search_results
104104
diff
105105
json_array_lossless
106+
json_document_lossless
106107
)
107108
@safe_payload_compression_value ~r/\A[a-zA-Z0-9_.:-]+\z/
108109

lib/codex_pooler/gateway/request_compression.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ defmodule CodexPooler.Gateway.RequestCompression do
1313
@strategy_modules %{
1414
diff: Strategies.Diff,
1515
json_array_lossless: Strategies.JsonArrayLossless,
16+
json_document_lossless: Strategies.JsonDocumentLossless,
1617
log_output: Strategies.LogOutput,
1718
search_results: Strategies.SearchResults
1819
}

lib/codex_pooler/gateway/request_compression/content_detector.ex

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
defmodule CodexPooler.Gateway.RequestCompression.ContentDetector do
22
@moduledoc false
33

4-
@type kind :: :json_array | :diff | :html | :search | :build | :source_code | :text
5-
@type strategy :: :json_array_lossless | :diff | :search_results | :log_output
4+
@type kind ::
5+
:json_array | :json_document | :diff | :html | :search | :build | :source_code | :text
6+
@type strategy ::
7+
:json_array_lossless | :json_document_lossless | :diff | :search_results | :log_output
68
@type decision :: %{
79
required(:kind) => kind(),
810
required(:confidence) => float(),
@@ -12,6 +14,7 @@ defmodule CodexPooler.Gateway.RequestCompression.ContentDetector do
1214

1315
@strategies %{
1416
json_array: :json_array_lossless,
17+
json_document: :json_document_lossless,
1518
diff: :diff,
1619
search: :search_results,
1720
build: :log_output
@@ -39,6 +42,9 @@ defmodule CodexPooler.Gateway.RequestCompression.ContentDetector do
3942
@build_term_regex ~r/\b(?:build|building|compile|compiling|compiled|test|tests|failed|failure|running|finished|warning|error|npm|yarn|pnpm|mix|make|cargo|gradle|maven|pytest|rspec|exunit)\b/i
4043
@build_prefix_regex ~r/^\s*(?:\$ |==>|-->|Compiling|Running|Finished|warning:|error:|\[\w+\])/mi
4144
@stack_line_regex ~r/(?:^\s+at\s+\S+|^\s*File\s+"[^"]+",\s+line\s+\d+|^\s*\S+:\d+:\d+:)/m
45+
@diagnostic_path_regex ~r/^\s*\S+\.(?:c|cc|cpp|cs|css|ex|exs|go|h|hpp|html|java|js|jsx|json|kt|m|md|mjs|mm|php|py|rb|rs|scss|svelte|swift|toml|ts|tsx|vue|xml|ya?ml)(?:\(\d+,\d+\)|:\d+(?::\d+)?)[:\s].+/im
46+
@diagnostic_summary_regex ~r/^\s*(?:Build\s+(?:FAILED|succeeded)|BUILD\s+(?:FAILED|SUCCESSFUL)|\*\*\s+BUILD\s+(?:FAILED|SUCCEEDED)\s+\*\*|Failed!\s+-\s+Failed:|Passed!\s+-\s+Failed:|Test summary:|Found\s+\d+\s+(?:errors?|warnings?)|Executed\s+\d+\s+tests?,\s+with\s+\d+|\d+\s+(?:Warning|Error)\(s\)|\d+\s+(?:tests?|examples?)\s+(?:completed|run|passed|failed)|\d+\s+actionable tasks?:)/im
47+
@lint_rule_regex ~r/\b(?:lint|style|correctness|suspicious|complexity|nursery|performance|security)\/[a-z0-9_\/-]+\b/i
4248

4349
@source_keyword_regex ~r/^\s*(?:defmodule|defp?\s+\w+|class\s+\w+|function\s+\w+|import\s+|export\s+|const\s+\w+|let\s+\w+|var\s+\w+|pub\s+fn\s+\w+|fn\s+\w+|impl\s+\w+|module\s+\w+|alias\s+)/m
4450
@source_punctuation_regex ~r/[{}();]/
@@ -58,6 +64,9 @@ defmodule CodexPooler.Gateway.RequestCompression.ContentDetector do
5864
json_array?(trimmed) ->
5965
decision(:json_array, 100)
6066

67+
json_document?(trimmed) ->
68+
decision(:json_document, 100)
69+
6170
(points = diff_points(content)) >= 70 ->
6271
decision(:diff, points)
6372

@@ -100,6 +109,13 @@ defmodule CodexPooler.Gateway.RequestCompression.ContentDetector do
100109
end
101110
end
102111

112+
defp json_document?(content) do
113+
case Jason.decode(content) do
114+
{:ok, value} when is_map(value) -> true
115+
_other -> false
116+
end
117+
end
118+
103119
defp diff_points(content) do
104120
[
105121
score(regex_match?(@diff_git_regex, content), 25),
@@ -151,9 +167,14 @@ defmodule CodexPooler.Gateway.RequestCompression.ContentDetector do
151167
defp build_points(content) do
152168
lines = lines(content)
153169
severities = scan_count(@severity_regex, content)
170+
diagnostic_paths = scan_count(@diagnostic_path_regex, content)
171+
diagnostic_summaries = scan_count(@diagnostic_summary_regex, content)
154172

155173
[
156174
cond_score(severities, [{2, 30}, {1, 20}]),
175+
cond_score(diagnostic_paths, [{2, 35}, {1, 25}]),
176+
cond_score(diagnostic_summaries, [{2, 25}, {1, 15}]),
177+
score(regex_match?(@lint_rule_regex, content), 15),
157178
score(regex_match?(@build_term_regex, content), 20),
158179
score(regex_match?(@build_prefix_regex, content), 20),
159180
score(regex_match?(@stack_line_regex, content), 25),
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
defmodule CodexPooler.Gateway.RequestCompression.Strategies.JsonDocumentLossless do
2+
@moduledoc """
3+
Conservative JSON-object request compression.
4+
5+
This strategy only minifies valid top-level JSON object text and returns a
6+
rewrite when local token counting proves a strict reduction. Arrays keep using
7+
the existing array strategy so row-oriented metadata stays stable.
8+
"""
9+
10+
alias CodexPooler.Gateway.RequestCompression.Strategies
11+
12+
@strategy :json_document_lossless
13+
14+
@spec compress(term(), Strategies.opts()) :: Strategies.result()
15+
def compress(content, opts \\ [])
16+
17+
def compress(content, opts) when is_binary(content) do
18+
with {:ok, %Jason.OrderedObject{} = document} <-
19+
Jason.decode(content, objects: :ordered_objects),
20+
{:ok, compressed} <- Jason.encode(document) do
21+
Strategies.finalize(
22+
@strategy,
23+
content,
24+
compressed,
25+
%{top_level_key_count: top_level_key_count(document)},
26+
opts
27+
)
28+
else
29+
{:error, :tokenizer_input_limit} -> {:skip, :tokenizer_input_limit}
30+
_skip -> :skip
31+
end
32+
end
33+
34+
def compress(_content, _opts), do: :skip
35+
36+
defp top_level_key_count(%Jason.OrderedObject{values: values}), do: length(values)
37+
end

lib/codex_pooler/gateway/request_compression/strategies/log_output.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ defmodule CodexPooler.Gateway.RequestCompression.Strategies.LogOutput do
1111
@default_context_lines 2
1212
@default_max_important_lines 12
1313

14-
@important_line_regex ~r/(?:^|\b)(?:error|warning|warn|failed|failure|fatal|panic|exception|traceback|assertion|exit\s+code|caused\s+by)(?:\b|:)/i
14+
@important_line_regex ~r/(?:^|\b)(?:error|warning|warn|failed|failure|fatal|panic|exception|traceback|assertion|exit\s+code|caused\s+by)(?:\b|:)|^\s*(?:Build\s+(?:FAILED|succeeded)|BUILD\s+(?:FAILED|SUCCESSFUL)|\*\*\s+BUILD\s+(?:FAILED|SUCCEEDED)\s+\*\*|Failed!\s+-\s+Failed:|Passed!\s+-\s+Failed:|Test summary:|Found\s+\d+\s+(?:errors?|warnings?)|Executed\s+\d+\s+tests?,\s+with\s+\d+|\d+\s+(?:Warning|Error)\(s\)|\d+\s+(?:tests?|examples?)\s+(?:completed|run|passed|failed)|\d+\s+actionable tasks?:)/i
1515

1616
@spec compress(term(), Strategies.opts()) :: Strategies.result()
1717
def compress(content, opts \\ [])

lib/codex_pooler_web/live/admin/components/pages/pools/wizard_components.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ defmodule CodexPoolerWeb.Admin.PoolWizardComponents do
254254
label="Request compression"
255255
/>
256256
<p class="routing-option-help">
257-
Compress upstream-bound Responses tool outputs before dispatch.
257+
Shrinks eligible Responses tool outputs before upstream dispatch.
258258
</p>
259259
</div>
260260
</div>

lib/codex_pooler_web/live/admin/components/pages/request_logs/display.ex

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,12 @@ defmodule CodexPoolerWeb.Admin.RequestLogsDisplay do
162162

163163
def compression_savings_line(%{payload_compression: compression})
164164
when is_map(compression) do
165-
with unit when unit in ["tokens", "bytes"] <- Map.get(compression, :unit),
165+
with "tokens" <- Map.get(compression, :unit),
166166
saved when is_integer(saved) <- Map.get(compression, :saved_count),
167167
percent when is_number(percent) <- Map.get(compression, :savings_percent),
168-
ratio when is_number(ratio) <- Map.get(compression, :compression_ratio) do
169-
"compression saved #{format_compression_count(saved, unit)} (#{format_percent(percent)}) · #{format_compression_ratio(ratio, unit)}"
168+
ratio when is_number(ratio) <- Map.get(compression, :compression_ratio),
169+
true <- saved > 0 and ratio < 1 do
170+
"#{format_compression_count(saved)} (#{format_percent(percent)})"
170171
else
171172
_value -> nil
172173
end
@@ -185,7 +186,8 @@ defmodule CodexPoolerWeb.Admin.RequestLogsDisplay do
185186
compression_count_title_part(
186187
"tokenizer input skipped",
187188
Map.get(compression, :tokenizer_input_skipped_count)
188-
)
189+
),
190+
"percent is measured against rewritten tool-output candidates, not total request tokens"
189191
]
190192
|> Enum.reject(&is_nil/1)
191193
|> case do
@@ -470,11 +472,7 @@ defmodule CodexPoolerWeb.Admin.RequestLogsDisplay do
470472

471473
defp compact_cached_input_cost(_usd), do: nil
472474

473-
defp format_compression_count(saved, "tokens"), do: "#{Format.token_count(saved)} tokens"
474-
defp format_compression_count(saved, "bytes"), do: "#{Format.integer(saved)} bytes"
475-
476-
defp format_compression_ratio(ratio, "bytes"), do: "byte ratio #{format_decimal(ratio)}x"
477-
defp format_compression_ratio(ratio, _unit), do: "ratio #{format_decimal(ratio)}x"
475+
defp format_compression_count(saved), do: Format.token_count(saved)
478476

479477
defp format_percent(percent), do: "#{format_decimal(percent)}%"
480478

0 commit comments

Comments
 (0)