Skip to content

Commit 7f45061

Browse files
committed
Loosen sandbox compaction model parsing
1 parent 67fb85a commit 7f45061

File tree

3 files changed

+87
-18
lines changed

3 files changed

+87
-18
lines changed

src/agents/sandbox/capabilities/compaction.py

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,21 @@
1010
from .capability import Capability
1111

1212
_DEFAULT_COMPACT_THRESHOLD = 240_000
13+
_MODEL_NAME_SEPARATOR_TRANSLATION = str.maketrans("", "", ".-")
1314

1415

15-
class CompactionModelInfo(BaseModel):
16-
context_window: int
16+
def _model_lookup_key(model: str) -> str:
17+
normalized_model = model.strip().lower().removeprefix("openai/")
18+
return normalized_model.translate(_MODEL_NAME_SEPARATOR_TRANSLATION)
1719

18-
@classmethod
19-
def for_model(cls, model: str) -> CompactionModelInfo:
20-
normalized_model = model.removeprefix("openai/")
2120

22-
if normalized_model in (
21+
def _model_context_windows(models: tuple[str, ...], context_window: int) -> dict[str, int]:
22+
return {_model_lookup_key(model): context_window for model in models}
23+
24+
25+
_MODEL_CONTEXT_WINDOWS: dict[str, int] = {
26+
**_model_context_windows(
27+
(
2328
"gpt-5.4",
2429
"gpt-5.4-2026-03-05",
2530
"gpt-5.4-pro",
@@ -30,9 +35,11 @@ def for_model(cls, model: str) -> CompactionModelInfo:
3035
"gpt-4.1-mini-2025-04-14",
3136
"gpt-4.1-nano",
3237
"gpt-4.1-nano-2025-04-14",
33-
):
34-
return cls(context_window=1_047_576)
35-
if normalized_model in (
38+
),
39+
1_047_576,
40+
),
41+
**_model_context_windows(
42+
(
3643
"gpt-5",
3744
"gpt-5-2025-08-07",
3845
"gpt-5-codex",
@@ -57,9 +64,11 @@ def for_model(cls, model: str) -> CompactionModelInfo:
5764
"gpt-5.4-mini-2026-03-17",
5865
"gpt-5.4-nano",
5966
"gpt-5.4-nano-2026-03-17",
60-
):
61-
return cls(context_window=400_000)
62-
if normalized_model in (
67+
),
68+
400_000,
69+
),
70+
**_model_context_windows(
71+
(
6372
"codex-mini-latest",
6473
"o1",
6574
"o1-2024-12-17",
@@ -77,9 +86,11 @@ def for_model(cls, model: str) -> CompactionModelInfo:
7786
"o4-mini-2025-04-16",
7887
"o4-mini-deep-research",
7988
"o4-mini-deep-research-2025-06-26",
80-
):
81-
return cls(context_window=200_000)
82-
if normalized_model in (
89+
),
90+
200_000,
91+
),
92+
**_model_context_windows(
93+
(
8394
"gpt-4o",
8495
"gpt-4o-2024-05-13",
8596
"gpt-4o-2024-08-06",
@@ -90,9 +101,27 @@ def for_model(cls, model: str) -> CompactionModelInfo:
90101
"gpt-5.1-chat-latest",
91102
"gpt-5.2-chat-latest",
92103
"gpt-5.3-chat-latest",
93-
):
94-
return cls(context_window=128_000)
104+
),
105+
128_000,
106+
),
107+
}
95108

109+
110+
class CompactionModelInfo(BaseModel):
111+
context_window: int
112+
113+
@classmethod
114+
def maybe_for_model(cls, model: str) -> CompactionModelInfo | None:
115+
context_window = _MODEL_CONTEXT_WINDOWS.get(_model_lookup_key(model))
116+
if context_window is None:
117+
return None
118+
return cls(context_window=context_window)
119+
120+
@classmethod
121+
def for_model(cls, model: str) -> CompactionModelInfo:
122+
model_info = cls.maybe_for_model(model)
123+
if model_info is not None:
124+
return model_info
96125
raise ValueError(f"Unknown context window for model: {model!r}")
97126

98127

@@ -153,7 +182,11 @@ def sampling_params(self, sampling_params: dict[str, Any]) -> dict[str, Any]:
153182
if policy is None:
154183
model = sampling_params.get("model")
155184
if isinstance(model, str) and model:
156-
policy = DynamicCompactionPolicy(model_info=CompactionModelInfo.for_model(model))
185+
model_info = CompactionModelInfo.maybe_for_model(model)
186+
if model_info is None:
187+
policy = StaticCompactionPolicy()
188+
else:
189+
policy = DynamicCompactionPolicy(model_info=model_info)
157190
else:
158191
policy = StaticCompactionPolicy()
159192

tests/sandbox/capabilities/test_compaction_capability.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,34 @@ def test_sampling_params_uses_static_threshold(self) -> None:
2626
}
2727
assert isinstance(capability.policy, StaticCompactionPolicy)
2828

29+
def test_sampling_params_infers_hyphenated_model_threshold(self) -> None:
30+
capability = Compaction()
31+
32+
sampling_params = capability.sampling_params({"model": "gpt-5-2"})
33+
34+
assert sampling_params == {
35+
"context_management": [
36+
{
37+
"type": "compaction",
38+
"compact_threshold": 360_000,
39+
}
40+
]
41+
}
42+
43+
def test_sampling_params_falls_back_for_unknown_model(self) -> None:
44+
capability = Compaction()
45+
46+
sampling_params = capability.sampling_params({"model": "azure-prod-deployment"})
47+
48+
assert sampling_params == {
49+
"context_management": [
50+
{
51+
"type": "compaction",
52+
"compact_threshold": 240_000,
53+
}
54+
]
55+
}
56+
2957
def test_process_context_keeps_items_from_last_compaction(self) -> None:
3058
"""Tests compaction truncates history to the last compaction item, inclusive."""
3159

tests/sandbox/test_compaction.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
("o3", 200_000),
1515
("gpt-4o", 128_000),
1616
("openai/gpt-5.4", 1_047_576),
17+
("gpt-5-2", 400_000),
18+
("gpt-5-4", 1_047_576),
19+
("openai/gpt-5-4-mini", 400_000),
20+
("gpt-4-1-mini", 1_047_576),
1721
],
1822
)
1923
def test_compaction_model_info_for_model_returns_context_window(
@@ -26,3 +30,7 @@ def test_compaction_model_info_for_model_returns_context_window(
2630
def test_compaction_model_info_for_model_rejects_unknown_model() -> None:
2731
with pytest.raises(ValueError, match="Unknown context window for model"):
2832
CompactionModelInfo.for_model("not-a-model")
33+
34+
35+
def test_compaction_model_info_maybe_for_model_returns_none_for_unknown_model() -> None:
36+
assert CompactionModelInfo.maybe_for_model("not-a-model") is None

0 commit comments

Comments
 (0)