File size: 3,291 Bytes
b996e23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"""Patch: agent_loop.py task detection + auto-approve for free models."""

import os
import ast

AGENT_LOOP = "/app/agent/core/agent_loop.py"
AGENT_FILE = "/app/backend/routes/agent.py"
SESSION_FILE = "/app/agent/core/session.py"

# ===== PATCH 1: agent_loop.py - detect model stopped mid-task =====
with open(AGENT_LOOP) as f:
    c = f.read()

# Add helper function before class Handlers
if "_unfinished_plan" not in c:
    fn = (
        "\n\ndef _unfinished_plan(s):\n"
        "    p = getattr(s, 'current_plan', None) or []\n"
        "    return [it for it in p if it.get('status') in ('pending', 'in_progress')]\n\n"
    )
    c = c.replace("class Handlers:", fn + "class Handlers:")
    print("OK: Added _unfinished_plan()")

# Add detection: if model produced no tool calls but content still exists,
# and plan items are still pending/in_progress, send session_update event
if "ac_plan" not in c:
    check = (
        "\n            # Auto-continue: detect model stopped mid-task\n"
        "            if not llm_result.tool_calls_acc and llm_result.content:\n"
        "                unfinished = _unfinished_plan(session)\n"
        "                if unfinished:\n"
        "                    await session.send_event(Event(event_type='session_update', data={\n"
        "                        'ac_plan': unfinished,\n"
        "                    }))\n"
    )
    c = c.replace("  # -- End of turn --", check + "  # -- End of turn --")
    print("OK: Added mid-task detection")

try:
    ast.parse(c)
    with open(AGENT_LOOP, "w") as f:
        f.write(c)
    print("OK: agent_loop.py patched")
except SyntaxError as e:
    print(f"FAIL: agent_loop.py syntax: {e}")

# ===== PATCH 2: Enable auto_approval for ALL sessions by default =====
# So free models don't block on user approval
with open(SESSION_FILE) as f:
    c = f.read()

if "AUTO_APPROVE" not in c:
    # Find where auto_approval is set on the session object
    # Patch: when creating a new session, set auto_approval.enabled = True
    auto_patch = (
        "\n        # === PATCH: Auto-approve for free models ===\n"
        "        self.auto_approval = {\n"
        '            "enabled": True,\n'
        '            "cost_cap_usd": None,\n'
        '            "estimated_spend_usd": 0.0,\n'
        '            "remaining_usd": None,\n'
        "        }\n"
    )
    
    # Find session init method
    init_match = "class Session:"
    if init_match in c:
        # Insert after the class definition, find __init__
        init_found = "def __init__"
        if init_found in c:
            # Find first line inside __init__ that's an assignment
            init_start = c.find(init_found)
            body_start = c.find("\n", init_start) + 1
            body_start = c.find("        ", body_start)  # first indented line
            c = c[:body_start] + auto_patch + c[body_start:]
            print("OK: Added auto_approve default")
    
    try:
        ast.parse(c)
        with open(SESSION_FILE, "w") as f:
            f.write(c)
        print("OK: session.py patched")
    except SyntaxError as e:
        print(f"FAIL: session.py syntax: {e}")
        # Don't block on this patch
else:
    print("OK: session.py already has auto_approve")

print("DONE: Backend patches applied")