From 9cb06b1a73e92af4a671da6d00b89679f94b095d Mon Sep 17 00:00:00 2001 From: ubeyidah Date: Sun, 9 Nov 2025 20:23:56 +0300 Subject: [PATCH] feat: hyprland app open tool created --- src/assistant.py | 5 ++++- src/config.py | 14 ++++++++---- src/tools.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 src/tools.py diff --git a/src/assistant.py b/src/assistant.py index c113e8f..4617479 100644 --- a/src/assistant.py +++ b/src/assistant.py @@ -5,6 +5,7 @@ from google import genai from google.genai import types from src.config import MEMORY_FILE +from src.tools import all_tools class ChatAssistant: @@ -42,7 +43,9 @@ def _initialize_client(self): def _create_chat_session(self): """creates a new chat session with the system prompt""" history = self._load_history() - gen_config = types.GenerateContentConfig(system_instruction=self.system_prompt) + gen_config = types.GenerateContentConfig( + system_instruction=self.system_prompt, tools=all_tools + ) print(f"Initializing chat with {self.model_name}...") return self.client.chats.create( model=self.model_name, config=gen_config, history=history diff --git a/src/config.py b/src/config.py index 6acabd2..1bb258e 100644 --- a/src/config.py +++ b/src/config.py @@ -3,9 +3,15 @@ USER_NAME = "Ubeyidah" EXIT_WORD_LIST = ["exit", "quit", "bye", "goodbye", "stop", "end", "quite"] SYSTEM_PROMPT = f""" - You are {ASSISTANT_NAME}, a helpful and friendly AI assistant. - You are speaking to your creator, {USER_NAME}. - Be calm, thoughtful, and slightly encouraging. - """ +You are {ASSISTANT_NAME}, a helpful AI assistant for your creator, {USER_NAME}. +You are running on Arch Linux with the Hyprland window manager. + +You have one tool: `tool_open_application(app_name)`. +Use this tool to open applications like 'kitty' or 'firefox' when asked. + +You MUST use this tool to fulfill any requests related to opening apps. +When the tool is used, you will get a JSON response. Relay the key information +(e.g., "OK, I've opened kitty") to {USER_NAME} in a natural, calm tone. +""" MEMORY_FILE = "vector_memory.json" diff --git a/src/tools.py b/src/tools.py new file mode 100644 index 0000000..b60cf17 --- /dev/null +++ b/src/tools.py @@ -0,0 +1,57 @@ +import subprocess +from google.genai import types + +ALLOWED_APPS = ["alacritty", "btop", "nvim", "yazi", "nautilus"] + + +def _run_safe_hyprctl(command_list: list): + """Run hyprctl command safely.""" + try: + full_command = ["hyprctl", "-j"] + command_list + result = subprocess.run( + full_command, + capture_output=True, + text=True, + check=True, + encoding="utf-8", + ) + print(f"[Tool Executed: hyprctl -j {' '.join(command_list)}]") + return {"status": "success", "output": result.stdout} + except Exception as e: + print(f"[Tool Error: {str(e)}]") + return {"status": "error", "message": str(e)} + + +def tool_open_applications(app_name: str): + """Open specified application if it is allowed.""" + app_name_lower = app_name.lower() + if app_name_lower in ALLOWED_APPS: + return _run_safe_hyprctl(["dispatch", "exec", app_name_lower]) + else: + print(f"[Tool Error: App '{app_name}' is not on allow-list]") + return { + "status": "error", + "message": f"Application '{app_name}' is not allowed.", + } + + +all_tools = [ + types.Tool( + function_declarations=[ + types.FunctionDeclaration( + name="tool_open_applications", + description=f"Opens an application on the user's computer, e.g. {', '.join(ALLOWED_APPS)}.", + parameters=types.Schema( + type=types.Type.OBJECT, + properties={ + "app_name": types.Schema( + type=types.Type.STRING, + description=f"The name of the app to open, e.g. {', '.join(ALLOWED_APPS)}", + ) + }, + required=["app_name"], + ), + ) + ] + ) +]