(self)
| 100 | logger.debug("OpenSpace instance created") |
| 101 | |
| 102 | async def initialize(self) -> None: |
| 103 | if self._initialized: |
| 104 | logger.warning("OpenSpace already initialized") |
| 105 | return |
| 106 | |
| 107 | logger.info("Initializing OpenSpace...") |
| 108 | try: |
| 109 | self._llm_client = LLMClient( |
| 110 | model=self.config.llm_model, |
| 111 | enable_thinking=self.config.llm_enable_thinking, |
| 112 | rate_limit_delay=self.config.llm_rate_limit_delay, |
| 113 | max_retries=self.config.llm_max_retries, |
| 114 | timeout=self.config.llm_timeout, |
| 115 | **self.config.llm_kwargs |
| 116 | ) |
| 117 | logger.info(f"✓ LLM Client: {self.config.llm_model}") |
| 118 | |
| 119 | # Load grounding config |
| 120 | # If custom config is provided, merge it with default configs |
| 121 | # load_config supports multiple files and deep merges them (later files override earlier ones) |
| 122 | if self.config.grounding_config_path: |
| 123 | from openspace.config.loader import CONFIG_DIR |
| 124 | from openspace.config.constants import CONFIG_GROUNDING, CONFIG_SECURITY |
| 125 | # Load default configs + custom config (custom values will override defaults) |
| 126 | grounding_config = load_config( |
| 127 | CONFIG_DIR / CONFIG_GROUNDING, |
| 128 | CONFIG_DIR / CONFIG_SECURITY, |
| 129 | self.config.grounding_config_path |
| 130 | ) |
| 131 | logger.info(f"Merged custom grounding config: {self.config.grounding_config_path}") |
| 132 | else: |
| 133 | # Load default configs only |
| 134 | grounding_config = get_config() |
| 135 | |
| 136 | # Optional: enable ClawWork productivity tools for fair benchmark comparison |
| 137 | if getattr(self.config, "use_clawwork_productivity", False): |
| 138 | shell_cfg = grounding_config.shell.model_copy( |
| 139 | update={ |
| 140 | "use_clawwork_productivity": True, |
| 141 | "working_dir": self.config.workspace_dir or grounding_config.shell.working_dir, |
| 142 | } |
| 143 | ) |
| 144 | grounding_config = grounding_config.model_copy(update={"shell": shell_cfg}) |
| 145 | logger.info("ClawWork productivity tools enabled (shell.working_dir used as sandbox root)") |
| 146 | |
| 147 | # Resolve backend_scope early so we can skip initializing |
| 148 | # providers that are not in scope (e.g. web when only shell is needed). |
| 149 | agent_config = get_agent_config("GroundingAgent") |
| 150 | _cli_max_iter = self.config.grounding_max_iterations |
| 151 | _default_max_iter = OpenSpaceConfig().grounding_max_iterations # dataclass default (20) |
| 152 | if agent_config: |
| 153 | cfg_max_iter = agent_config.get("max_iterations", _default_max_iter) |
| 154 | if _cli_max_iter != _default_max_iter: |
| 155 | max_iterations = _cli_max_iter |
| 156 | else: |
| 157 | max_iterations = cfg_max_iter |
| 158 | backend_scope = self.config.backend_scope or agent_config.get("backend_scope") or ["gui", "shell", "mcp", "web", "system"] |
| 159 | visual_analysis_timeout = agent_config.get("visual_analysis_timeout", 30.0) |
no test coverage detected