@miller-tech/uap 1.119.0 → 1.119.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "1.119.0",
3
+ "version": "1.119.1",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -4341,11 +4341,14 @@ def _maybe_inject_stuck_break(openai_body: dict, monitor: "SessionMonitor") -> N
4341
4341
  "operator the single blocking question in one sentence. Take a DIFFERENT "
4342
4342
  "action now."
4343
4343
  )
4344
- msgs = openai_body.get("messages") or []
4344
+ msgs = openai_body.get("messages")
4345
+ if not isinstance(msgs, list):
4346
+ msgs = []
4345
4347
  if msgs and msgs[0].get("role") == "system":
4346
4348
  msgs[0]["content"] = (msgs[0].get("content") or "") + directive
4347
4349
  else:
4348
4350
  msgs.insert(0, {"role": "system", "content": directive.strip()})
4351
+ openai_body["messages"] = msgs # reattach in case messages was empty/absent
4349
4352
  logger.warning("STUCK-BREAK: forced terminal turn (%s, fires=%d)", reason, monitor.stuck_break_fires)
4350
4353
 
4351
4354
 
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env python3
2
+ """Regression: the STUCK-BREAK injector built `msgs = openai_body.get("messages")
3
+ or []`, which returns a DETACHED empty list when messages is [], so the injected
4
+ directive never landed in the outbound request. Real requests always carry
5
+ messages, but the injector must be robust — it now reattaches the list.
6
+ Mirrors the fix already applied to _maybe_inject_deferral_break.
7
+ """
8
+
9
+ import importlib.util
10
+ import unittest
11
+ from pathlib import Path
12
+
13
+
14
+ def _load_proxy_module():
15
+ proxy_path = Path(__file__).resolve().parents[1] / "scripts" / "anthropic_proxy.py"
16
+ spec = importlib.util.spec_from_file_location("anthropic_proxy", proxy_path)
17
+ assert spec is not None and spec.loader is not None
18
+ module = importlib.util.module_from_spec(spec)
19
+ spec.loader.exec_module(module)
20
+ return module
21
+
22
+
23
+ proxy = _load_proxy_module()
24
+
25
+
26
+ def _firing_monitor():
27
+ mon = proxy.SessionMonitor()
28
+ # Trip the self-reported-stuck signal so the injector fires.
29
+ mon.self_stuck_streak = proxy.PROXY_STUCK_TEXT_THRESHOLD + 1
30
+ return mon
31
+
32
+
33
+ class TestStuckBreakReattach(unittest.TestCase):
34
+ def test_empty_messages_list_still_receives_directive(self):
35
+ mon = _firing_monitor()
36
+ body = {"tool_choice": "required", "messages": []}
37
+ proxy._maybe_inject_stuck_break(body, mon)
38
+ self.assertTrue(body["messages"], "directive must land in the request")
39
+ self.assertEqual(body["messages"][0]["role"], "system")
40
+ self.assertIn("STOP", body["messages"][0]["content"])
41
+ self.assertEqual(body["tool_choice"], "auto") # coercion released
42
+
43
+ def test_absent_messages_key_is_created(self):
44
+ mon = _firing_monitor()
45
+ body = {"tool_choice": "required"} # no "messages" key at all
46
+ proxy._maybe_inject_stuck_break(body, mon)
47
+ self.assertIn("messages", body)
48
+ self.assertIn("STOP", body["messages"][0]["content"])
49
+
50
+ def test_existing_system_message_is_appended(self):
51
+ mon = _firing_monitor()
52
+ body = {"messages": [{"role": "system", "content": "SYS"}]}
53
+ proxy._maybe_inject_stuck_break(body, mon)
54
+ self.assertEqual(len(body["messages"]), 1)
55
+ self.assertTrue(body["messages"][0]["content"].startswith("SYS"))
56
+ self.assertIn("STOP", body["messages"][0]["content"])
57
+
58
+ def test_does_not_fire_when_not_stuck(self):
59
+ mon = proxy.SessionMonitor() # no streak
60
+ body = {"tool_choice": "required", "messages": []}
61
+ proxy._maybe_inject_stuck_break(body, mon)
62
+ self.assertEqual(body["messages"], [])
63
+ self.assertEqual(body["tool_choice"], "required")
64
+
65
+
66
+ if __name__ == "__main__":
67
+ unittest.main()