import asyncio import threading from speech_to_text import record_voice from llm import get_llm_output from tts import edge_speak, stop_speaking from ui import JarvisUI import sys from pathlib import Path from actions.open_app import open_app from actions.web_search import web_search from actions.weather_report import weather_action from actions.send_message import send_message from memory.memory_manager import load_memory, update_memory from memory.temporary_memory import TemporaryMemory interrupt_commands = ["mute", "quit", "exit", "stop"] temp_memory = TemporaryMemory() def get_base_dir(): if getattr(sys, "frozen", False): return Path(sys.executable).parent return Path(__file__).resolve().parent BASE_DIR = get_base_dir() async def get_voice_input(): return await asyncio.to_thread(record_voice) async def ai_loop(ui: JarvisUI): while True: user_text = await get_voice_input() if not user_text: continue if any(cmd in user_text.lower() for cmd in interrupt_commands): stop_speaking() temp_memory.reset() continue ui.write_log(f"You: {user_text}") if temp_memory.get_current_question(): param = temp_memory.get_current_question() temp_memory.update_parameters({param: user_text}) temp_memory.clear_current_question() user_text = temp_memory.get_last_user_text() temp_memory.set_last_user_text(user_text) long_term_memory = load_memory() def minimal_memory_for_prompt(memory: dict) -> dict: result = {} identity = memory.get("identity", {}) preferences = memory.get("preferences", {}) relationships = memory.get("relationships", {}) emotional_state = memory.get("emotional_state", {}) if "name" in identity: result["user_name"] = identity["name"].get("value") for k in ["favorite_color", "favorite_food", "favorite_music"]: if k in preferences: val = preferences[k].get("value") if isinstance(val, dict) and "value" in val: val = val["value"] result[k] = val for rel, info in relationships.items(): if isinstance(info, dict) and "name" in info and "value" in info["name"]: result[f"{rel}_name"] = info["name"]["value"] for event, info in emotional_state.items(): if "value" in info: result[f"emotion_{event}"] = info["value"] return {k: v for k, v in result.items() if v} memory_for_prompt = minimal_memory_for_prompt(long_term_memory) history_lines = temp_memory.get_history_for_prompt() recent_history = "\n".join(history_lines.split("\n")[-5:]) if recent_history: memory_for_prompt["recent_conversation"] = recent_history if temp_memory.has_pending_intent(): memory_for_prompt["_pending_intent"] = temp_memory.pending_intent memory_for_prompt["_collected_params"] = str(temp_memory.get_parameters()) try: llm_output = get_llm_output( user_text=user_text, memory_block=memory_for_prompt ) except Exception as e: ui.write_log(f"AI ERROR: {e}") continue intent = llm_output.get("intent", "chat") parameters = llm_output.get("parameters", {}) response = llm_output.get("text") memory_update = llm_output.get("memory_update") if memory_update and isinstance(memory_update, dict): update_memory(memory_update) temp_memory.set_last_ai_response(response) if intent == "send_message": temp_memory.set_pending_intent("send_message") temp_memory.update_parameters(parameters) if all(temp_memory.get_parameter(p) for p in ["receiver", "message_text", "platform"]): threading.Thread( target=send_message, kwargs={ "parameters": temp_memory.get_parameters(), "player": ui, "session_memory": temp_memory }, daemon=True ).start() elif intent == "open_app": if parameters.get("app_name"): threading.Thread( target=open_app, kwargs={ "parameters": parameters, "response": response, "player": ui, "session_memory": temp_memory }, daemon=True ).start() elif intent == "weather_report": if parameters.get("city"): threading.Thread( target=weather_action, kwargs={ "parameters": parameters, "player": ui, "session_memory": temp_memory }, daemon=True ).start() elif intent == "search": if parameters.get("query"): threading.Thread( target=web_search, kwargs={ "parameters": parameters, "player": ui, "session_memory": temp_memory }, daemon=True ).start() else: if response: ui.write_log(f"AI: {response}") edge_speak(response, ui) await asyncio.sleep(0.01) def main(): ui = JarvisUI(BASE_DIR / "face.png", size=(900, 900)) def runner(): asyncio.run(ai_loop(ui)) threading.Thread(target=runner, daemon=True).start() ui.root.mainloop() if __name__ == "__main__": main()