bep40 commited on
Commit
b996e23
·
verified ·
1 Parent(s): 39a3de5

patches: agent_loop detection + auto-approve toggle

Browse files
Files changed (1) hide show
  1. patch_agent_backend.py +89 -0
patch_agent_backend.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Patch: agent_loop.py task detection + auto-approve for free models."""
2
+
3
+ import os
4
+ import ast
5
+
6
+ AGENT_LOOP = "/app/agent/core/agent_loop.py"
7
+ AGENT_FILE = "/app/backend/routes/agent.py"
8
+ SESSION_FILE = "/app/agent/core/session.py"
9
+
10
+ # ===== PATCH 1: agent_loop.py - detect model stopped mid-task =====
11
+ with open(AGENT_LOOP) as f:
12
+ c = f.read()
13
+
14
+ # Add helper function before class Handlers
15
+ if "_unfinished_plan" not in c:
16
+ fn = (
17
+ "\n\ndef _unfinished_plan(s):\n"
18
+ " p = getattr(s, 'current_plan', None) or []\n"
19
+ " return [it for it in p if it.get('status') in ('pending', 'in_progress')]\n\n"
20
+ )
21
+ c = c.replace("class Handlers:", fn + "class Handlers:")
22
+ print("OK: Added _unfinished_plan()")
23
+
24
+ # Add detection: if model produced no tool calls but content still exists,
25
+ # and plan items are still pending/in_progress, send session_update event
26
+ if "ac_plan" not in c:
27
+ check = (
28
+ "\n # Auto-continue: detect model stopped mid-task\n"
29
+ " if not llm_result.tool_calls_acc and llm_result.content:\n"
30
+ " unfinished = _unfinished_plan(session)\n"
31
+ " if unfinished:\n"
32
+ " await session.send_event(Event(event_type='session_update', data={\n"
33
+ " 'ac_plan': unfinished,\n"
34
+ " }))\n"
35
+ )
36
+ c = c.replace(" # -- End of turn --", check + " # -- End of turn --")
37
+ print("OK: Added mid-task detection")
38
+
39
+ try:
40
+ ast.parse(c)
41
+ with open(AGENT_LOOP, "w") as f:
42
+ f.write(c)
43
+ print("OK: agent_loop.py patched")
44
+ except SyntaxError as e:
45
+ print(f"FAIL: agent_loop.py syntax: {e}")
46
+
47
+ # ===== PATCH 2: Enable auto_approval for ALL sessions by default =====
48
+ # So free models don't block on user approval
49
+ with open(SESSION_FILE) as f:
50
+ c = f.read()
51
+
52
+ if "AUTO_APPROVE" not in c:
53
+ # Find where auto_approval is set on the session object
54
+ # Patch: when creating a new session, set auto_approval.enabled = True
55
+ auto_patch = (
56
+ "\n # === PATCH: Auto-approve for free models ===\n"
57
+ " self.auto_approval = {\n"
58
+ ' "enabled": True,\n'
59
+ ' "cost_cap_usd": None,\n'
60
+ ' "estimated_spend_usd": 0.0,\n'
61
+ ' "remaining_usd": None,\n'
62
+ " }\n"
63
+ )
64
+
65
+ # Find session init method
66
+ init_match = "class Session:"
67
+ if init_match in c:
68
+ # Insert after the class definition, find __init__
69
+ init_found = "def __init__"
70
+ if init_found in c:
71
+ # Find first line inside __init__ that's an assignment
72
+ init_start = c.find(init_found)
73
+ body_start = c.find("\n", init_start) + 1
74
+ body_start = c.find(" ", body_start) # first indented line
75
+ c = c[:body_start] + auto_patch + c[body_start:]
76
+ print("OK: Added auto_approve default")
77
+
78
+ try:
79
+ ast.parse(c)
80
+ with open(SESSION_FILE, "w") as f:
81
+ f.write(c)
82
+ print("OK: session.py patched")
83
+ except SyntaxError as e:
84
+ print(f"FAIL: session.py syntax: {e}")
85
+ # Don't block on this patch
86
+ else:
87
+ print("OK: session.py already has auto_approve")
88
+
89
+ print("DONE: Backend patches applied")