File size: 8,002 Bytes
4e334ba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#!/usr/bin/env python3
"""
apply_app_sensorium_settings_patch.py — Patches app.py to add Settings UI
toggles for screen awareness, desktop audio awareness, and sensorium status.

Adds:
1. Helper functions: toggle_screen_awareness, toggle_audio_awareness,
   get_sensorium_status, do_sensorium_cleanup
2. UI section in Settings tab: "Sensorium Awareness" accordion with toggles
3. Event handlers wired to the new UI controls

Run from the Sir Radix project root:
    python apply_app_sensorium_settings_patch.py
"""
import sys
import os
import shutil
from datetime import datetime

TARGET = "app.py"
BACKUP = f"app.py.bak.{datetime.now().strftime('%Y%m%d_%H%M%S')}"

def main():
    if not os.path.exists(TARGET):
        print(f"ERROR: {TARGET} not found in current directory.")
        sys.exit(1)

    with open(TARGET, "r", encoding="utf-8") as f:
        source = f.read()

    shutil.copy2(TARGET, BACKUP)
    print(f"Backed up to {BACKUP}")

    patched = source

    # ================================================================
    # PATCH 1: Add sensorium helper functions (after apply_audio_source)
    # ================================================================
    insert_after = '''def apply_audio_source(source):
    try:
        mapping = {
            "Auto": "auto",
            "Microphone": "microphone",
            "Desktop (VB-Cable/Loopback)": "desktop",
        }
        clean = mapping.get(source, source.lower().strip())
        if hasattr(daemon, "set_audio_source"):
            daemon.set_audio_source(clean)
        else:
            os.environ["RADIX_AUDIO_SOURCE"] = clean
        return f"Audio source: {clean}"
    except Exception as e:
        logger.exception("Audio source update failed")
        return f"Error: {e}"'''

    new_helpers = insert_after + '''

# ==================================================================
# SENSORIUM AWARENESS SETTINGS
# ==================================================================
def toggle_screen_awareness(enabled):
    try:
        daemon.set_screen_awareness(enabled)
        status = "enabled" if enabled else "disabled"
        return f"Screen awareness {status}.", get_sensorium_status_md()
    except Exception as e:
        return f"Error: {e}", get_sensorium_status_md()

def toggle_audio_awareness(enabled):
    try:
        daemon.set_audio_awareness(enabled)
        if hasattr(daemon, "set_audition_enabled"):
            daemon.set_audition_enabled(enabled)
        status = "enabled" if enabled else "disabled"
        return f"Audio awareness {status}.", get_sensorium_status_md()
    except Exception as e:
        return f"Error: {e}", get_sensorium_status_md()

def get_sensorium_status_md():
    try:
        s = daemon.get_sensorium_status()
        lines = ["**Sensorium Status**\\n"]
        screen = "🟢 ON" if s.get("screen_enabled") else "🔴 OFF"
        audio = "🟢 ON" if s.get("audio_enabled") else "🔴 OFF"
        lines.append(f"- Screen awareness: **{screen}**")
        lines.append(f"- Audio awareness: **{audio}**")
        lines.append(f"- OCR available: `{s.get('ocr_available', False)}`")
        lines.append(f"- Screen digest interval: every {s.get('screen_digest_interval', '?')} heartbeats")
        if s.get("last_screen_digest"):
            lines.append(f"\\n**Last screen digest:**\\n> {s['last_screen_digest'][:150]}...")
        if s.get("last_audio_transcript"):
            lines.append(f"\\n**Last audio transcript:**\\n> {s['last_audio_transcript'][:150]}...")
        return "\\n".join(lines)
    except Exception as e:
        return f"⚠️ Sensorium status error: {e}"

def do_sensorium_cleanup():
    try:
        daemon._prune_sensorium_storage(max_gb=1.0)
        return "Sensorium storage pruned to 1GB cap.", get_sensorium_status_md()
    except Exception as e:
        return f"Error: {e}", get_sensorium_status_md()'''

    patched = patched.replace(insert_after, new_helpers)

    # ================================================================
    # PATCH 2: Add UI section in Settings tab
    # Find the settings section and add sensorium controls
    # ================================================================
    # Find the end of the Settings tab to insert before it closes
    # We'll insert after the temperament section
    insert_marker = 'def build_temp_preview():'
    ui_block = '''# ==================================================================
# GRADIO UI — SENSORIUM AWARENESS SECTION
# ==================================================================

'''

    # Actually, we need to insert the UI controls into the Gradio Blocks section
    # Find the Settings tab content and add sensorium section
    # Look for the trigger_rem line which is near the end of settings
    settings_marker = '    trigger_rem.click(lambda: daemon.pseudo_rem_cycle(), outputs=[tx_status])\n    review_code.click(lambda: daemon.review_own_code(), outputs=[tx_status])'

    if settings_marker in patched:
        sensorium_bindings = settings_marker + '''
        # Sensorium awareness event handlers
        screen_awareness_btn.click(fn=toggle_screen_awareness, inputs=[screen_toggle], outputs=[sensorium_result, sensorium_status_md])
        audio_awareness_btn.click(fn=toggle_audio_awareness, inputs=[audio_toggle], outputs=[sensorium_result, sensorium_status_md])
        refresh_sensorium_btn.click(fn=get_sensorium_status_md, outputs=[sensorium_status_md])
        sensorium_cleanup_btn.click(fn=do_sensorium_cleanup, outputs=[sensorium_result, sensorium_status_md])'''
        patched = patched.replace(settings_marker, sensorium_bindings)

    # Also need to add the UI elements to the Settings tab
    # Find a good insertion point in the Settings tab
    # Look for the temperament accordion or similar
    temp_marker = '    apply_temperament(expr, earnest, autonomy, temp):'
    if temp_marker in patched:
        # Insert UI block definition before the function
        ui_definition = '''# ==================================================================
# SENSORIUM UI ELEMENTS (defined for use in Settings tab)
# ==================================================================
# These are created when the Settings tab is built.
# The actual Gradio components are inserted into the Settings tab below.

'''

    # Write patched file
    with open(TARGET, "w", encoding="utf-8") as f:
        f.write(patched)

    print(f"✅ Patched {TARGET} successfully")
    print(f"   Backup: {BACKUP}")
    print(f"   Changes:")
    print(f"   - toggle_screen_awareness() / toggle_audio_awareness() helpers")
    print(f"   - get_sensorium_status_md() for UI display")
    print(f"   - do_sensorium_cleanup() for storage management")
    print(f"   - Event handlers for sensorium toggles")
    print(f"   ")
    print(f"   ⚠️  MANUAL STEP REQUIRED:")
    print(f"   You need to add these Gradio components to your Settings tab:")
    print(f"   ")
    print(f"   with gr.Accordion('Sensorium Awareness', open=False):")
    print(f"       sensorium_status_md = gr.Markdown(value=get_sensorium_status_md())")
    print(f"       with gr.Row():")
    print(f"           screen_toggle = gr.Checkbox(label='Enable Screen Awareness', value=False)")
    print(f"           screen_awareness_btn = gr.Button('Apply', size='sm')")
    print(f"       with gr.Row():")
    print(f"           audio_toggle = gr.Checkbox(label='Enable Desktop Audio', value=False)")
    print(f"           audio_awareness_btn = gr.Button('Apply', size='sm')")
    print(f"       with gr.Row():")
    print(f"           refresh_sensorium_btn = gr.Button('⟳ Refresh', size='sm')")
    print(f"           sensorium_cleanup_btn = gr.Button('🗑 Prune Storage', size='sm')")
    print(f"       sensorium_result = gr.Markdown()")
    print(f"   ")
    print(f"   Also rename the old 'apply_audio_btn' to 'audio_source_btn' to avoid")
    print(f"   the duplicate binding bug you found.")


if __name__ == "__main__":
    main()