@miller-tech/uap 1.220.6 → 1.220.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env python3
2
+ """Mid-stream degenerate-repetition guard.
3
+
4
+ Regression cover for the 2026-08-25 runaway: a rail running
5
+ --repeat-penalty 1.0 with DRY disabled emitted ONE sentence 640 times
6
+ (151,628 chars) until it hit the 32,768-token n-predict cap, ~11 minutes of
7
+ GPU for a turn that produced nothing. The post-hoc detector
8
+ (_detect_and_truncate_degenerate_repetition) only repairs NON-streaming
9
+ responses, so a streaming client like opencode was never protected.
10
+
11
+ The false-positive tests are the load-bearing half: a guard that aborts real
12
+ answers is worse than the runaway it prevents.
13
+ """
14
+
15
+ import asyncio
16
+ import importlib.util
17
+ import json
18
+ import unittest
19
+ from pathlib import Path
20
+
21
+
22
+ def _load_proxy_module():
23
+ proxy_path = Path(__file__).resolve().parents[1] / "scripts" / "anthropic_proxy.py"
24
+ spec = importlib.util.spec_from_file_location("anthropic_proxy", proxy_path)
25
+ assert spec is not None and spec.loader is not None
26
+ module = importlib.util.module_from_spec(spec)
27
+ spec.loader.exec_module(module)
28
+ return module
29
+
30
+
31
+ proxy = _load_proxy_module()
32
+
33
+ # The exact sentence captured from the live runaway.
34
+ RUNAWAY_LINE = (
35
+ "The Docker build fails because the workspace root `Cargo.toml` doesn't "
36
+ "include the `pg-server` bin target. Let me check the workspace structure:"
37
+ )
38
+
39
+
40
+ class TestDetectDegenerateRepeat(unittest.TestCase):
41
+ def test_detects_the_captured_runaway_shape(self):
42
+ """One sentence + blank line, over and over — the real failure."""
43
+ tail = (RUNAWAY_LINE + "\n\n") * 20
44
+ self.assertEqual(proxy._detect_degenerate_repeat(tail), RUNAWAY_LINE)
45
+
46
+ def test_detects_loop_with_no_newlines(self):
47
+ """Block mode: a loop inside one long line is invisible to line mode."""
48
+ unit = "and then the value is recomputed again, "
49
+ tail = "prefix text. " + unit * 12
50
+ found = proxy._detect_degenerate_repeat(tail)
51
+ self.assertIsNotNone(found)
52
+ # Whatever period it locks onto must itself be the repeating unit.
53
+ self.assertTrue(unit.strip(", ") in found or found in unit * 2)
54
+
55
+ def test_ignores_repetition_that_has_stopped(self):
56
+ """Anchored at the END: a repetitive passage the model moved on from
57
+ is not a runaway, and aborting there would truncate a real answer."""
58
+ tail = (RUNAWAY_LINE + "\n\n") * 20 + (
59
+ "\n\nRight — the bin target is missing from the workspace members "
60
+ "list. Adding it to Cargo.toml now, then rebuilding to confirm the "
61
+ "image picks up the new binary.\n"
62
+ )
63
+ self.assertIsNone(proxy._detect_degenerate_repeat(tail))
64
+
65
+ def test_ignores_short_and_punctuation_only_runs(self):
66
+ """Rules, fences and bracket runs legitimately repeat in real output."""
67
+ for tail in (
68
+ "----\n" * 30,
69
+ "```\n" * 30,
70
+ "}\n" * 30,
71
+ " \n" * 30,
72
+ ("ok\n") * 30, # non-blank but under MIN_UNIT
73
+ ):
74
+ with self.subTest(tail=tail[:12]):
75
+ self.assertIsNone(proxy._detect_degenerate_repeat(tail))
76
+
77
+ def test_ignores_similar_but_distinct_lines(self):
78
+ """Generated code repeats structure, not whole identical lines."""
79
+ tail = "".join(
80
+ f' assert_eq!(rows[{i}].get::<_, i64>("id"), {i} as i64);\n'
81
+ for i in range(30)
82
+ )
83
+ self.assertIsNone(proxy._detect_degenerate_repeat(tail))
84
+
85
+ def test_ignores_empty_input(self):
86
+ self.assertIsNone(proxy._detect_degenerate_repeat(""))
87
+
88
+
89
+ class _FakeUpstreamStream:
90
+ """Minimal streamed httpx.Response: yields OpenAI SSE lines."""
91
+
92
+ def __init__(self, contents, finish_reason="stop"):
93
+ self._contents = list(contents)
94
+ self._finish_reason = finish_reason
95
+ self.closed = False
96
+ self.lines_served = 0
97
+
98
+ async def aiter_lines(self):
99
+ for chunk in self._contents:
100
+ self.lines_served += 1
101
+ payload = {"choices": [{"delta": {"content": chunk}, "index": 0}]}
102
+ yield "data: " + json.dumps(payload)
103
+ final = {"choices": [{"delta": {}, "finish_reason": self._finish_reason}]}
104
+ yield "data: " + json.dumps(final)
105
+ yield "data: [DONE]"
106
+
107
+ async def aclose(self):
108
+ self.closed = True
109
+
110
+
111
+ def _drain(upstream):
112
+ monitor = proxy.SessionMonitor(context_window=131072)
113
+
114
+ async def run():
115
+ out = []
116
+ async for frame in proxy.stream_anthropic_response(
117
+ upstream, "test-model", monitor, {"messages": [], "tools": []}
118
+ ):
119
+ out.append(frame)
120
+ return out
121
+
122
+ return asyncio.run(run())
123
+
124
+
125
+ def _text_deltas(frames):
126
+ texts = []
127
+ for frame in frames:
128
+ for line in frame.splitlines():
129
+ if not line.startswith("data: "):
130
+ continue
131
+ try:
132
+ obj = json.loads(line[6:])
133
+ except json.JSONDecodeError:
134
+ continue
135
+ if obj.get("type") == "content_block_delta":
136
+ delta = obj.get("delta", {})
137
+ if delta.get("type") == "text_delta":
138
+ texts.append(delta["text"])
139
+ return texts
140
+
141
+
142
+ def _stop_reason(frames):
143
+ for frame in frames:
144
+ for line in frame.splitlines():
145
+ if not line.startswith("data: "):
146
+ continue
147
+ try:
148
+ obj = json.loads(line[6:])
149
+ except json.JSONDecodeError:
150
+ continue
151
+ if obj.get("type") == "message_delta":
152
+ return (obj.get("delta") or {}).get("stop_reason")
153
+ return None
154
+
155
+
156
+ class TestStreamRepeatGuard(unittest.TestCase):
157
+ def test_aborts_runaway_before_the_budget_is_spent(self):
158
+ """The whole point: stop generating, not just clean up afterwards."""
159
+ chunks = [RUNAWAY_LINE + "\n\n"] * 400
160
+ upstream = _FakeUpstreamStream(chunks)
161
+ frames = _drain(upstream)
162
+
163
+ served = upstream.lines_served
164
+ self.assertLess(
165
+ served, 100, f"guard did not abort early: {served}/400 chunks consumed"
166
+ )
167
+ self.assertEqual(
168
+ _stop_reason(frames),
169
+ "max_tokens",
170
+ "an aborted runaway must not be reported as a complete answer",
171
+ )
172
+
173
+ def test_normal_response_streams_through_untouched(self):
174
+ """No false abort, and every delta still reaches the client."""
175
+ chunks = [
176
+ "Checking the workspace layout.\n\n",
177
+ "The `pg-server` crate is present but not listed under "
178
+ "`[workspace] members`, so `cargo build --workspace` never "
179
+ "builds its binary.\n\n",
180
+ "Adding it to the members list and rebuilding.\n",
181
+ ]
182
+ upstream = _FakeUpstreamStream(chunks)
183
+ frames = _drain(upstream)
184
+
185
+ self.assertEqual(_text_deltas(frames), chunks)
186
+ self.assertEqual(_stop_reason(frames), "end_turn")
187
+
188
+ def test_long_legitimate_answer_is_not_aborted(self):
189
+ """Well past the guard's minimum length, with repeated structure."""
190
+ chunks = [
191
+ f"Step {i}: verify that migration {i:03d} applies cleanly and the "
192
+ f"resulting schema matches the fixture checked in at "
193
+ f"tests/fixtures/schema_{i:03d}.sql.\n\n"
194
+ for i in range(80)
195
+ ]
196
+ upstream = _FakeUpstreamStream(chunks)
197
+ frames = _drain(upstream)
198
+
199
+ self.assertEqual(len(_text_deltas(frames)), 80)
200
+ self.assertEqual(_stop_reason(frames), "end_turn")
201
+
202
+ def test_guard_can_be_disabled(self):
203
+ chunks = [RUNAWAY_LINE + "\n\n"] * 60
204
+ original = proxy.PROXY_REPEAT_GUARD
205
+ proxy.PROXY_REPEAT_GUARD = False
206
+ try:
207
+ upstream = _FakeUpstreamStream(chunks)
208
+ frames = _drain(upstream)
209
+ self.assertEqual(len(_text_deltas(frames)), 60)
210
+ self.assertEqual(_stop_reason(frames), "end_turn")
211
+ finally:
212
+ proxy.PROXY_REPEAT_GUARD = original
213
+
214
+
215
+ if __name__ == "__main__":
216
+ unittest.main()