@miller-tech/uap 1.131.0 → 1.132.0
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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/deliver.js +20 -17
- package/dist/cli/deliver.js.map +1 -1
- package/dist/delivery/context-budget.d.ts +25 -3
- package/dist/delivery/context-budget.d.ts.map +1 -1
- package/dist/delivery/context-budget.js +74 -3
- package/dist/delivery/context-budget.js.map +1 -1
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +16 -2
- package/tools/agents/tests/test_prune_preserve_force_write.py +47 -0
|
@@ -158,5 +158,52 @@ class ContaminationBreakerPreservesStateTest(unittest.TestCase):
|
|
|
158
158
|
self.assertIn("step two", blob)
|
|
159
159
|
|
|
160
160
|
|
|
161
|
+
class PrunerStateCarryoverTest(unittest.TestCase):
|
|
162
|
+
"""#2 companion: the CONTEXT PRUNER (not just the contamination breaker)
|
|
163
|
+
must carry the plan + files-written across a drop, or a long build re-reads
|
|
164
|
+
its own output after every prune (observed live: `cat lib.rs` ×16)."""
|
|
165
|
+
|
|
166
|
+
def test_prune_marker_carries_written_files(self):
|
|
167
|
+
long = "x " * 800 # ~400 tok each — large middle, small head/tail
|
|
168
|
+
messages = [{"role": "user", "content": "build the org-model crate"}]
|
|
169
|
+
# a WRITE in the middle (will be dropped) — the breadcrumb never
|
|
170
|
+
# captures write actions, only tool_result reads.
|
|
171
|
+
messages.append({"role": "assistant", "content": [
|
|
172
|
+
{"type": "tool_use", "name": "Write",
|
|
173
|
+
"input": {"file_path": "org-model/src/person.rs"}}]})
|
|
174
|
+
for _ in range(6): # large read results fill the middle
|
|
175
|
+
messages.append({"role": "user", "content": [
|
|
176
|
+
{"type": "tool_result", "content": "read " + long}]})
|
|
177
|
+
for t in ["a", "b", "c", "d"]: # small recent tail (protected, fits)
|
|
178
|
+
messages.append({"role": "user", "content": t})
|
|
179
|
+
|
|
180
|
+
body = {"messages": messages}
|
|
181
|
+
m = ap.SessionMonitor(context_window=4000)
|
|
182
|
+
out = ap.prune_conversation(body, context_window=4000, monitor=m,
|
|
183
|
+
target_fraction=0.4, keep_last=4)
|
|
184
|
+
blob = "\n".join(
|
|
185
|
+
b if isinstance(b, str) else str(b)
|
|
186
|
+
for msg in out["messages"] for b in [msg.get("content", "")]
|
|
187
|
+
)
|
|
188
|
+
# the dropped Write action survives as a carryover manifest entry
|
|
189
|
+
self.assertIn("STATE CARRYOVER", blob)
|
|
190
|
+
self.assertIn("org-model/src/person.rs", blob)
|
|
191
|
+
|
|
192
|
+
def test_no_carryover_on_fresh_prune_still_prunes(self):
|
|
193
|
+
"""A prune with no plan/writes to carry still works (breadcrumb only)."""
|
|
194
|
+
long = "y " * 800
|
|
195
|
+
messages = [{"role": "user", "content": "explore"}]
|
|
196
|
+
for _ in range(6):
|
|
197
|
+
messages.append({"role": "user", "content": [
|
|
198
|
+
{"type": "tool_result", "content": "read " + long}]})
|
|
199
|
+
for t in ["a", "b", "c", "d"]:
|
|
200
|
+
messages.append({"role": "user", "content": t})
|
|
201
|
+
m = ap.SessionMonitor(context_window=4000)
|
|
202
|
+
out = ap.prune_conversation({"messages": messages}, context_window=4000,
|
|
203
|
+
monitor=m, target_fraction=0.4, keep_last=4)
|
|
204
|
+
# no crash, and it did drop (fewer messages than input)
|
|
205
|
+
self.assertLess(len(out["messages"]), len(messages))
|
|
206
|
+
|
|
207
|
+
|
|
161
208
|
if __name__ == "__main__":
|
|
162
209
|
unittest.main()
|