#!/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()