-
Notifications
You must be signed in to change notification settings - Fork 0
feat: hyprland app open tool created #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: hyprland app open tool created #2
Conversation
WalkthroughThis PR introduces tool support to the AI assistant by implementing a controlled application-launching capability. It adds a tools module with safe subprocess-based hyprctl execution, updates the system prompt to document the new tool, and integrates tool metadata into the assistant's chat configuration. Changes
Sequence DiagramsequenceDiagram
participant User
participant Assistant
participant ToolSystem
participant Hyprctl
User->>Assistant: Request to open app (e.g., "open kitty")
activate Assistant
Assistant->>ToolSystem: Invoke tool_open_applications("kitty")
activate ToolSystem
ToolSystem->>ToolSystem: Validate against ALLOWED_APPS
alt App Allowed
ToolSystem->>Hyprctl: _run_safe_hyprctl(["dispatch", "exec", "kitty"])
activate Hyprctl
Hyprctl-->>ToolSystem: {status: "success", output: "..."}
deactivate Hyprctl
ToolSystem-->>Assistant: {status: "success", output: "..."}
else App Blocked
ToolSystem-->>Assistant: {status: "error", error: "App not allowed"}
end
deactivate ToolSystem
Assistant->>User: Relay result in calm tone
deactivate Assistant
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/assistant.py (1)
28-28: Fix the parameter typo.Line 28 has
slefinstead ofself, which will cause anAttributeErrorwhen this method is called during initialization.Apply this diff:
- def _load_api_key(slef): + def _load_api_key(self): """Loads the api key from .env"""
🧹 Nitpick comments (1)
src/tools.py (1)
7-22: Consider parsing the JSON output and validating inputs.The function uses the
-jflag but returns rawstdoutwithout parsing. Consider returning parsed JSON for structured access. Additionally, validate thatcommand_listis non-empty before constructing the command to prevent silent failures.Example refactor:
def _run_safe_hyprctl(command_list: list): """Run hyprctl command safely.""" + if not command_list: + return {"status": "error", "message": "command_list cannot be empty"} + 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} + try: + import json + parsed_output = json.loads(result.stdout) + return {"status": "success", "output": parsed_output} + except json.JSONDecodeError: + return {"status": "success", "output": result.stdout} except Exception as e: print(f"[Tool Error: {str(e)}]") return {"status": "error", "message": str(e)}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/assistant.py(2 hunks)src/config.py(1 hunks)src/tools.py(1 hunks)
🔇 Additional comments (2)
src/tools.py (1)
1-4: Imports and allow-list look good.The imports are appropriate, and the ALLOWED_APPS constant provides a security boundary. However, note that the examples in SYSTEM_PROMPT ('kitty', 'firefox') don't match this list—see the comment on src/config.py.
src/assistant.py (1)
8-8: LGTM!The import correctly brings in the tool definitions for integration with the chat session.
| gen_config = types.GenerateContentConfig( | ||
| system_instruction=self.system_prompt, tools=all_tools | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tool execution logic is missing.
While the tools parameter is correctly added to the config, the code doesn't handle tool calls from the model. When Gemini decides to use tool_open_applications, it will return a FunctionCall in the response, which needs to be:
- Detected in the response
- Executed by calling the actual Python function
- Sent back to the model with
send_messagecontaining the tool result
The current send_message_stream method only handles text responses.
Do you want me to generate the tool execution logic or open an issue to track this implementation?
| 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. | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix function name and update examples to match ALLOWED_APPS.
Two critical issues in the SYSTEM_PROMPT:
-
Function name mismatch: Line 9 references
tool_open_application(singular), but the actual function in src/tools.py istool_open_applications(plural). -
Example apps not in allow-list: Line 10 mentions 'kitty' and 'firefox' as examples, but these are NOT in the ALLOWED_APPS list. The actual allowed apps are: alacritty, btop, nvim, yazi, nautilus. This will confuse the model and cause failures when it tries to use the examples.
Apply this diff:
SYSTEM_PROMPT = f"""
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 have one tool: `tool_open_applications(app_name)`.
+Use this tool to open applications like 'alacritty', 'btop', 'nvim', 'yazi', or 'nautilus' 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.
+(e.g., "OK, I've opened alacritty") to {USER_NAME} in a natural, calm tone.
"""📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 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. | |
| """ | |
| SYSTEM_PROMPT = f""" | |
| 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_applications(app_name)`. | |
| Use this tool to open applications like 'alacritty', 'btop', 'nvim', 'yazi', or 'nautilus' 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 alacritty") to {USER_NAME} in a natural, calm tone. | |
| """ |
🤖 Prompt for AI Agents
In src/config.py around lines 5 to 15, update the SYSTEM_PROMPT to reference the
correct tool function name and use allowed app examples: change any occurrence
of "tool_open_application" to "tool_open_applications" and replace example apps
('kitty', 'firefox') with apps from ALLOWED_APPS (e.g., 'alacritty', 'btop',
'nvim', 'yazi', 'nautilus') so the prompt matches the actual function and
approved app list.
| 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.", | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add input validation for the app_name parameter.
The function doesn't validate that app_name is a non-empty string. This could lead to unexpected behavior if called with None, empty string, or non-string types.
Apply this diff:
def tool_open_applications(app_name: str):
"""Open specified application if it is allowed."""
+ if not app_name or not isinstance(app_name, str):
+ return {
+ "status": "error",
+ "message": "app_name must be a non-empty string."
+ }
+
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.",
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 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.", | |
| } | |
| def tool_open_applications(app_name: str): | |
| """Open specified application if it is allowed.""" | |
| if not app_name or not isinstance(app_name, str): | |
| return { | |
| "status": "error", | |
| "message": "app_name must be a non-empty string." | |
| } | |
| 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.", | |
| } |
🤖 Prompt for AI Agents
In src/tools.py around lines 25 to 35, the function tool_open_applications lacks
input validation for app_name; add checks that app_name is an instance of str
and that app_name.strip() is non-empty before proceeding, returning the same
error dict (status: "error", message: ...) for invalid input; after validation,
normalize with app_name_lower = app_name.strip().lower() and then check
membership in ALLOWED_APPS and call _run_safe_hyprctl as before, ensuring
non-string or empty inputs don't cause unexpected behavior.
| 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"], | ||
| ), | ||
| ) | ||
| ] | ||
| ) | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function name mismatch with SYSTEM_PROMPT.
The tool is named tool_open_applications (plural), but src/config.py line 9 references tool_open_application (singular). This will prevent the model from using the tool correctly.
Ensure the function name matches across all references. Either update the SYSTEM_PROMPT or rename the function.
🤖 Prompt for AI Agents
In src/tools.py around lines 38 to 57 the declared function name is
"tool_open_applications" (plural) but src/config.py line 9 references
"tool_open_application" (singular), causing a mismatch; rename the
FunctionDeclaration's name value to "tool_open_application" so it matches the
SYSTEM_PROMPT, and search the repo for any other references to
"tool_open_applications" to update them accordingly (or conversely update the
SYSTEM_PROMPT if you prefer the plural form) ensuring both places use the exact
same function name.
Tools
Summary by CodeRabbit