import openai import subprocess import time import configparser import json import sys # === 1. Načtení konfigurace z config.ini === config = configparser.ConfigParser() config.read("config.ini") openai.api_key = config["OpenAI"]["api_key"] ASSISTANT_ID = config["OpenAI"]["assistant_id"] thread_id = None # === 2. Definice funkcí, které asistent může volat === FUNCTIONS = [ { "name": "execute_shell_command", "description": "Spustí shellový příkaz a vrátí jeho výstup.", "parameters": { "type": "object", "properties": { "command": { "type": "string", "description": "Shellový příkaz k vykonání." } }, "additionalProperties": False, "required": ["command"] } } ] # === 3. Pomocné funkce === def vytvor_nove_vlakno(): """Vytvoří nové vlákno pro zachování historie konverzace.""" thread = openai.beta.threads.create() return thread.id def spust_prikaz(prikaz): """Spustí shellový příkaz a vrátí jeho výstup.""" try: output = subprocess.check_output(prikaz, shell=True, stderr=subprocess.STDOUT, universal_newlines=True) return output.strip() except subprocess.CalledProcessError as e: return f"Chyba při vykonávání příkazu:\n{e.output}" def posli_dotaz_do_assistenta(prompt): """Odesílá dotaz v přirozeném jazyce do asistenta a vrací jeho odpověď.""" global thread_id if thread_id is None: thread_id = vytvor_nove_vlakno() openai.beta.threads.messages.create( thread_id=thread_id, role="user", content=prompt ) run = openai.beta.threads.runs.create( thread_id=thread_id, assistant_id=ASSISTANT_ID ) while True: run_status = openai.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id) if run_status.status == "completed": break time.sleep(1) messages = openai.beta.threads.messages.list(thread_id=thread_id) return messages.data[0].content[0].text.value def posli_prikaz_do_assistenta(command): """Odesílá schválený příkaz k vykonání asistentovi a vrací výstup příkazu.""" global thread_id if thread_id is None: thread_id = vytvor_nove_vlakno() run = openai.beta.threads.runs.create( thread_id=thread_id, assistant_id=ASSISTANT_ID, instructions=f"Prosím, spusť tento příkaz: {command}" ) while True: run_status = openai.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id) if run_status.status == "requires_action": tool_calls = run_status.required_action.submit_tool_outputs.tool_calls tool_outputs = [] for tool_call in tool_calls: tool_name = tool_call.function.name arguments = json.loads(tool_call.function.arguments) if tool_name == "execute_shell_command": vysledek = spust_prikaz(arguments["command"]) else: vysledek = "Neznámá funkce." tool_outputs.append({ "tool_call_id": tool_call.id, "output": vysledek }) openai.beta.threads.runs.submit_tool_outputs( thread_id=thread_id, run_id=run.id, tool_outputs=tool_outputs ) elif run_status.status == "completed": break time.sleep(1) messages = openai.beta.threads.messages.list(thread_id=thread_id) return messages.data[0].content[0].text.value def is_command_response(response): """Vrací True, pokud odpověď začíná prefixem indikujícím návrh příkazu.""" return response.strip().lower().startswith("navrhovaný příkaz:") def extract_command(response): """Odstraní prefix 'Navrhovaný příkaz:' a vrátí čistý shellový příkaz.""" prefix = "navrhovaný příkaz:" if response.strip().lower().startswith(prefix): return response.strip()[len(prefix):].strip() return response.strip() def provide_help(): """Vrací text s nápovědou o funkcích Robovojtíka.""" help_text = ( "Nápověda k Robovojtikovi – Linuxový Shell Asistent:\n\n" "Funkce:\n" " • Převádí dotazy v přirozeném jazyce na návrhy shellových příkazů.\n" " • Před spuštěním příkazu vždy čeká na potvrzení od uživatele.\n" " • Přímé příkazy zadejte s prefixem 'cmd:' (např. 'cmd: ls -la').\n" " • Pro ukončení Robovojtíka zadejte 'vypni' nebo 'exit'.\n\n" "Pokud potřebujete další pomoc, zeptejte se!" ) return help_text # === 4. Hlavní interaktivní smyčka === def main(): print("Linuxový shell s OpenAI Assistant v2 API a funkcemi.") print("Pro přímý příkaz použij prefix 'cmd:'") print("Pro ukončení Robovojtíka zadej 'vypni' nebo 'exit'.") print("Pro nápovědu zadej 'nápověda' nebo 'help'.") while True: user_input = input("\nZadej příkaz v přirozeném jazyce: ").strip() # Ukončení Robovojtíka if user_input.lower() in ["vypni", "exit"]: potvrzeni = input("Skutečně chceš ukončit Robovojtíka? (y/n): ").strip().lower() if potvrzeni == "y": print("Ukončuji Robovojtíka...") sys.exit(0) else: print("Ukončení zrušeno. Pokračuji.") continue # Zobrazení nápovědy if user_input.lower() in ["nápověda", "help"]: print("\n" + provide_help()) continue # Přímý příkaz bez asistenta if user_input.startswith("cmd:"): command = user_input[4:].strip() print(f"Rozpoznán přímý příkaz: {command}") potvrzeni = input("Spustit tento příkaz? (y/n): ").strip().lower() if potvrzeni == "y": vysledek = spust_prikaz(command) print("\nVýstup příkazu:") print(vysledek) else: print("Příkaz nebyl spuštěn.") continue # Dotaz pro asistenta – očekává návrh příkazu assistant_response = posli_dotaz_do_assistenta(user_input) # Pokud odpověď nevypadá jako návrh příkazu, zobrazíme ji jako informativní odpověď if not is_command_response(assistant_response): print("\nRobovojtík odpovídá:") print(assistant_response) continue # Pokud odpověď obsahuje navržený příkaz, vyzveme uživatele k potvrzení print("\nRobovojtík navrhuje příkaz:") print(assistant_response) potvrzeni = input("Spustit tento příkaz? (y/n): ").strip().lower() if potvrzeni == "y": command_to_execute = extract_command(assistant_response) execution_result = posli_prikaz_do_assistenta(command_to_execute) print("\nVýstup příkazu:") print(execution_result) else: print("Příkaz nebyl spuštěn. Čekám na další vstup.") if __name__ == "__main__": main(