1+ #!/usr/bin/env python
12# cli.py
23
34"""
1011
1112import fire
1213
13- # Import necessary components from the project
14- from omnimcp .agent_executor import AgentExecutor
15- from omnimcp .config import config
16- from omnimcp .core import plan_action_for_ui
17- from omnimcp .input import InputController , _pynput_error # Check pynput import status
18- from omnimcp .omniparser .client import OmniParserClient
19- from omnimcp .omnimcp import VisualState
20- from omnimcp .utils import (
21- logger ,
22- draw_bounding_boxes ,
23- draw_action_highlight ,
24- NSScreen , # Check for AppKit on macOS
25- )
26-
14+ from omnimcp .utils import logger
2715
2816# Default configuration
2917DEFAULT_OUTPUT_DIR = "runs"
@@ -35,6 +23,7 @@ def run(
3523 goal : str = DEFAULT_GOAL ,
3624 max_steps : int = DEFAULT_MAX_STEPS ,
3725 output_dir : str = DEFAULT_OUTPUT_DIR ,
26+ ci_mode : bool = False ,
3827):
3928 """
4029 Runs the OmniMCP agent to achieve a specified goal.
@@ -43,9 +32,34 @@ def run(
4332 goal: The natural language goal for the agent.
4433 max_steps: Maximum number of steps to attempt.
4534 output_dir: Base directory to save run artifacts (timestamped subdirs).
35+ ci_mode: Run in CI mode (skips API validation and actual execution).
4636 """
4737 # --- Initial Checks ---
4838 logger .info ("--- OmniMCP CLI ---" )
39+
40+ # Skip import-time checks if we're in CI mode
41+ if ci_mode :
42+ logger .info ("Running in CI mode - skipping credential checks and execution" )
43+ return 0
44+
45+ # Delay imports to avoid credential checks at import time
46+ try :
47+ # Import necessary components from the project
48+ from omnimcp .config import config
49+ from omnimcp .input import InputController , _pynput_error
50+ from omnimcp .agent_executor import AgentExecutor
51+ from omnimcp .core import plan_action_for_ui
52+ from omnimcp .omniparser .client import OmniParserClient
53+ from omnimcp .visual_state import VisualState
54+ from omnimcp .utils import (
55+ draw_bounding_boxes ,
56+ draw_action_highlight ,
57+ NSScreen , # Check for AppKit on macOS
58+ )
59+ except ImportError as e :
60+ logger .critical (f"Required dependency not found: { e } " )
61+ return 1
62+
4963 logger .info ("Performing initial checks..." )
5064 success = True
5165
@@ -84,7 +98,7 @@ def run(
8498
8599 if not success :
86100 logger .error ("Prerequisite checks failed. Exiting." )
87- sys . exit ( 1 )
101+ return 1
88102
89103 # --- Component Initialization ---
90104 logger .info ("\n Initializing components..." )
@@ -116,10 +130,10 @@ def run(
116130 logger .critical (
117131 " Ensure all requirements are installed (`uv pip install -e .`)"
118132 )
119- sys . exit ( 1 )
133+ return 1
120134 except Exception as e :
121135 logger .critical (f"❌ Component initialization failed: { e } " , exc_info = True )
122- sys . exit ( 1 )
136+ return 1
123137
124138 # --- Agent Executor Initialization ---
125139 logger .info ("\n Initializing Agent Executor..." )
@@ -134,7 +148,7 @@ def run(
134148 logger .success ("✅ Agent Executor initialized successfully." )
135149 except Exception as e :
136150 logger .critical (f"❌ Agent Executor initialization failed: { e } " , exc_info = True )
137- sys . exit ( 1 )
151+ return 1
138152
139153 # --- User Confirmation & Start ---
140154 print ("\n " + "=" * 60 )
@@ -159,13 +173,13 @@ def run(
159173 )
160174 except KeyboardInterrupt :
161175 logger .warning ("\n Execution interrupted by user (Ctrl+C)." )
162- sys . exit ( 1 )
176+ return 1
163177 except Exception as run_e :
164178 logger .critical (
165179 f"\n An unexpected error occurred during the agent run: { run_e } " ,
166180 exc_info = True ,
167181 )
168- sys . exit ( 1 )
182+ return 1
169183 finally :
170184 # Optional: Add cleanup here if needed (e.g., stopping parser server)
171185 logger .info (
@@ -176,13 +190,20 @@ def run(
176190 # --- Exit ---
177191 if overall_success :
178192 logger .success ("\n Agent run finished successfully (goal achieved)." )
179- sys . exit ( 0 )
193+ return 0
180194 else :
181195 logger .error (
182196 "\n Agent run finished unsuccessfully (goal not achieved or error occurred)."
183197 )
184- sys .exit (1 )
198+ return 1
199+
200+
201+ def main ():
202+ """Main entry point that handles Fire's return code conversion."""
203+ result = fire .Fire (run )
204+ if isinstance (result , int ):
205+ sys .exit (result )
185206
186207
187208if __name__ == "__main__" :
188- fire . Fire ( run )
209+ main ( )
0 commit comments