33import os
44import stat
55from pathlib import Path
6- from typing import Dict
76
8- from cubbi_init import ToolPlugin , cubbi_config
7+ from cubbi_init import ToolPlugin , cubbi_config , set_ownership
98
109
1110class AiderPlugin (ToolPlugin ):
1211 @property
1312 def tool_name (self ) -> str :
1413 return "aider"
1514
16- def _get_user_ids (self ) -> tuple [int , int ]:
17- return cubbi_config .user .uid , cubbi_config .user .gid
18-
19- def _set_ownership (self , path : Path ) -> None :
20- user_id , group_id = self ._get_user_ids ()
21- try :
22- os .chown (path , user_id , group_id )
23- except OSError as e :
24- self .status .log (f"Failed to set ownership for { path } : { e } " , "WARNING" )
25-
2615 def _get_aider_config_dir (self ) -> Path :
2716 return Path ("/home/cubbi/.aider" )
2817
@@ -33,28 +22,23 @@ def _ensure_aider_dirs(self) -> tuple[Path, Path]:
3322 config_dir = self ._get_aider_config_dir ()
3423 cache_dir = self ._get_aider_cache_dir ()
3524
36- # Create directories
37- for directory in [config_dir , cache_dir ]:
38- try :
39- directory .mkdir (mode = 0o755 , parents = True , exist_ok = True )
40- self ._set_ownership (directory )
41- except OSError as e :
42- self .status .log (
43- f"Failed to create Aider directory { directory } : { e } " , "ERROR"
44- )
25+ self .create_directory_with_ownership (config_dir )
26+ self .create_directory_with_ownership (cache_dir )
4527
4628 return config_dir , cache_dir
4729
48- def initialize (self ) -> bool :
30+ def is_already_configured (self ) -> bool :
31+ config_dir = self ._get_aider_config_dir ()
32+ env_file = config_dir / ".env"
33+ return env_file .exists ()
34+
35+ def configure (self ) -> bool :
4936 self .status .log ("Setting up Aider configuration..." )
5037
51- # Ensure Aider directories exist
5238 config_dir , cache_dir = self ._ensure_aider_dirs ()
5339
54- # Set up environment variables for the session
5540 env_vars = self ._create_environment_config ()
5641
57- # Create .env file if we have API keys
5842 if env_vars :
5943 env_file = config_dir / ".env"
6044 success = self ._write_env_file (env_file , env_vars )
@@ -71,22 +55,26 @@ def initialize(self) -> bool:
7155 "INFO" ,
7256 )
7357
74- # Always return True to allow container to start
58+ if not cubbi_config .mcps :
59+ self .status .log ("No MCP servers to integrate" )
60+ return True
61+
62+ self .status .log (
63+ f"Found { len (cubbi_config .mcps )} MCP server(s) - no direct integration available for Aider"
64+ )
65+
7566 return True
7667
77- def _create_environment_config (self ) -> Dict [str , str ]:
68+ def _create_environment_config (self ) -> dict [str , str ]:
7869 env_vars = {}
7970
80- # Configure Aider with the default model from cubbi config
8171 provider_config = cubbi_config .get_provider_for_default_model ()
8272 if provider_config and cubbi_config .defaults .model :
8373 _ , model_name = cubbi_config .defaults .model .split ("/" , 1 )
8474
85- # Set the model for Aider
8675 env_vars ["AIDER_MODEL" ] = model_name
8776 self .status .log (f"Set Aider model to { model_name } " )
8877
89- # Set provider-specific API key and configuration
9078 if provider_config .type == "anthropic" :
9179 env_vars ["AIDER_ANTHROPIC_API_KEY" ] = provider_config .api_key
9280 self .status .log ("Configured Anthropic API key for Aider" )
@@ -100,10 +88,7 @@ def _create_environment_config(self) -> Dict[str, str]:
10088 )
10189 self .status .log ("Configured OpenAI API key for Aider" )
10290
103- # Note: Aider uses different environment variable names for some providers
104- # We map cubbi provider types to Aider's expected variable names
10591 elif provider_config .type == "google" :
106- # Aider may expect GEMINI_API_KEY for Google models
10792 env_vars ["GEMINI_API_KEY" ] = provider_config .api_key
10893 self .status .log ("Configured Google/Gemini API key for Aider" )
10994
@@ -122,7 +107,6 @@ def _create_environment_config(self) -> Dict[str, str]:
122107 "WARNING" ,
123108 )
124109
125- # Fallback to legacy environment variable checking for backward compatibility
126110 api_key_mappings = {
127111 "OPENAI_API_KEY" : "AIDER_OPENAI_API_KEY" ,
128112 "ANTHROPIC_API_KEY" : "AIDER_ANTHROPIC_API_KEY" ,
@@ -138,25 +122,21 @@ def _create_environment_config(self) -> Dict[str, str]:
138122 provider = env_var .replace ("_API_KEY" , "" ).lower ()
139123 self .status .log (f"Added { provider } API key from environment" )
140124
141- # Check for OpenAI API base URL from legacy environment
142125 openai_url = os .environ .get ("OPENAI_URL" )
143126 if openai_url :
144127 env_vars ["AIDER_OPENAI_API_BASE" ] = openai_url
145128 self .status .log (
146129 f"Set OpenAI API base URL to { openai_url } from environment"
147130 )
148131
149- # Legacy model configuration
150132 model = os .environ .get ("AIDER_MODEL" )
151133 if model :
152134 env_vars ["AIDER_MODEL" ] = model
153135 self .status .log (f"Set model to { model } from environment" )
154136
155- # Handle additional API keys from AIDER_API_KEYS
156137 additional_keys = os .environ .get ("AIDER_API_KEYS" )
157138 if additional_keys :
158139 try :
159- # Parse format: "provider1=key1,provider2=key2"
160140 for pair in additional_keys .split ("," ):
161141 if "=" in pair :
162142 provider , key = pair .strip ().split ("=" , 1 )
@@ -166,17 +146,14 @@ def _create_environment_config(self) -> Dict[str, str]:
166146 except Exception as e :
167147 self .status .log (f"Failed to parse AIDER_API_KEYS: { e } " , "WARNING" )
168148
169- # Add git configuration
170149 auto_commits = os .environ .get ("AIDER_AUTO_COMMITS" , "true" )
171150 if auto_commits .lower () in ["true" , "false" ]:
172151 env_vars ["AIDER_AUTO_COMMITS" ] = auto_commits
173152
174- # Add dark mode setting
175153 dark_mode = os .environ .get ("AIDER_DARK_MODE" , "false" )
176154 if dark_mode .lower () in ["true" , "false" ]:
177155 env_vars ["AIDER_DARK_MODE" ] = dark_mode
178156
179- # Add proxy settings
180157 for proxy_var in ["HTTP_PROXY" , "HTTPS_PROXY" ]:
181158 value = os .environ .get (proxy_var )
182159 if value :
@@ -185,16 +162,15 @@ def _create_environment_config(self) -> Dict[str, str]:
185162
186163 return env_vars
187164
188- def _write_env_file (self , env_file : Path , env_vars : Dict [str , str ]) -> bool :
165+ def _write_env_file (self , env_file : Path , env_vars : dict [str , str ]) -> bool :
189166 try :
190167 content = "\n " .join (f"{ key } ={ value } " for key , value in env_vars .items ())
191168
192169 with open (env_file , "w" ) as f :
193170 f .write (content )
194171 f .write ("\n " )
195172
196- # Set ownership and secure file permissions (read/write for owner only)
197- self ._set_ownership (env_file )
173+ set_ownership (env_file )
198174 os .chmod (env_file , stat .S_IRUSR | stat .S_IWUSR )
199175
200176 self .status .log (f"Created Aider environment file at { env_file } " )
@@ -203,18 +179,5 @@ def _write_env_file(self, env_file: Path, env_vars: Dict[str, str]) -> bool:
203179 self .status .log (f"Failed to write Aider environment file: { e } " , "ERROR" )
204180 return False
205181
206- def setup_tool_configuration (self ) -> bool :
207- # Additional tool configuration can be added here if needed
208- return True
209-
210- def integrate_mcp_servers (self ) -> bool :
211- if not cubbi_config .mcps :
212- self .status .log ("No MCP servers to integrate" )
213- return True
214182
215- # Aider doesn't have native MCP support like Claude Code,
216- # but we could potentially add custom integrations here
217- self .status .log (
218- f"Found { len (cubbi_config .mcps )} MCP server(s) - no direct integration available for Aider"
219- )
220- return True
183+ PLUGIN_CLASS = AiderPlugin
0 commit comments