@@ -72,54 +72,35 @@ variable "experiment_report_tasks" {
7272 default = true
7373}
7474
75- variable "experiment_task_conventions " {
75+ variable "system_prompt " {
7676 type = string
77- description = " Custom conventions for task reporting to be written to CONVENTIONS.md "
77+ description = " System prompt for instructing Aider on task reporting and behavior "
7878 default = <<- EOT
79- # Aider Coding Conventions
80-
81- ## Task Reporting Requirements
82-
83- As you work on tasks, you MUST follow these task reporting conventions:
84-
85- 1. ALWAYS report the status of each task to Coder before and after your steps.
86- 2. Use the following format for reporting tasks:
87- ```
88- TASK: [brief description of what you're doing]
89- STATUS: [one of: "started", "in progress", "done", "failed"]
90- ```
91-
92- 3. Send a task report in these specific situations:
93- - When you BEGIN working on a task
94- - When you make SIGNIFICANT PROGRESS on a task
95- - When you COMPLETE a task successfully
96- - When you ENCOUNTER AN ERROR or cannot complete a task
97-
98- 4. Example sequence of task reporting:
99- ```
100- TASK: Setting up project structure
101- STATUS: started
102-
103- [Your work and discussion here]
104-
105- TASK: Setting up project structure
106- STATUS: in progress
107-
108- [More work and discussion]
109-
110- TASK: Setting up project structure
111- STATUS: done
112-
113- TASK: Implementing feature X
114- STATUS: started
115- ```
116-
117- 5. Always include a brief but descriptive task name that clearly identifies what you're working on.
118-
119- These conventions ensure that Coder can properly track task status in the UI.
79+ You are a helpful Coding assistant. Aim to autonomously investigate
80+ and solve issues the user gives you and test your work, whenever possible.
81+ Avoid shortcuts like mocking tests. When you get stuck, you can ask the user
82+ but opt for autonomy.
83+ YOU MUST REPORT ALL TASKS TO CODER.
84+ When reporting tasks, you MUST follow these EXACT instructions:
85+ - IMMEDIATELY report status after receiving ANY user message.
86+ - Be granular. If you are investigating with multiple steps, report each step to coder.
87+ Task state MUST be one of the following:
88+ - Use "state": "working" when actively processing WITHOUT needing additional user input.
89+ - Use "state": "complete" only when finished with a task.
90+ - Use "state": "failure" when you need ANY user input, lack sufficient details, or encounter blockers.
91+ Task summaries MUST:
92+ - Include specifics about what you're doing.
93+ - Include clear and actionable steps for the user.
94+ - Be less than 160 characters in length.
12095EOT
12196}
12297
98+ variable "task_prompt" {
99+ type = string
100+ description = " Task prompt to use with Aider"
101+ default = " "
102+ }
103+
123104variable "experiment_pre_install_script" {
124105 type = string
125106 description = " Custom script to run before installing Aider."
@@ -138,6 +119,35 @@ variable "experiment_additional_extensions" {
138119 default = null
139120}
140121
122+ variable "ai_provider" {
123+ type = string
124+ description = " AI provider to use with Aider (openai, anthropic, azure, google, etc.)"
125+ default = " anthropic"
126+ validation {
127+ condition = contains ([" openai" , " anthropic" , " azure" , " google" , " cohere" , " mistral" , " ollama" , " custom" ], var. ai_provider )
128+ error_message = " ai_provider must be one of: openai, anthropic, azure, google, cohere, mistral, ollama, custom"
129+ }
130+ }
131+
132+ variable "ai_model" {
133+ type = string
134+ description = " AI model to use with Aider. Can use Aider's built-in aliases like '4o' (gpt-4o), 'sonnet' (claude-3-7-sonnet), 'opus' (claude-3-opus), etc."
135+ default = " sonnet"
136+ }
137+
138+ variable "ai_api_key" {
139+ type = string
140+ description = " API key for the selected AI provider. This will be set as the appropriate environment variable based on the provider."
141+ default = " "
142+ sensitive = true
143+ }
144+
145+ variable "custom_env_var_name" {
146+ type = string
147+ description = " Custom environment variable name when using custom provider"
148+ default = " "
149+ }
150+
141151locals {
142152 base_extensions = <<- EOT
143153coder:
171181
172182 encoded_pre_install_script = var. experiment_pre_install_script != null ? base64encode (var. experiment_pre_install_script ) : " "
173183 encoded_post_install_script = var. experiment_post_install_script != null ? base64encode (var. experiment_post_install_script ) : " "
184+
185+ # Combine system prompt and task prompt for aider
186+ combined_prompt = trimspace (<<- EOT
187+ SYSTEM PROMPT:
188+ ${ var . system_prompt }
189+
190+ This is your current task: ${ var . task_prompt }
191+ EOT
192+ )
193+
194+ # Map providers to their environment variable names
195+ provider_env_vars = {
196+ openai = " OPENAI_API_KEY"
197+ anthropic = " ANTHROPIC_API_KEY"
198+ azure = " AZURE_OPENAI_API_KEY"
199+ google = " GOOGLE_API_KEY"
200+ cohere = " COHERE_API_KEY"
201+ mistral = " MISTRAL_API_KEY"
202+ ollama = " OLLAMA_HOST"
203+ custom = var.custom_env_var_name
204+ }
205+
206+ # Get the environment variable name for selected provider
207+ env_var_name = local. provider_env_vars [var . ai_provider ]
208+
209+ # Model flag for aider command
210+ model_flag = var. ai_provider == " ollama" ? " --ollama-model" : " --model"
174211}
175212
176213# Install and Initialize Aider
@@ -202,12 +239,21 @@ resource "coder_script" "aider" {
202239 if ! command_exists tmux; then
203240 echo "Installing tmux for persistent sessions..."
204241 if command -v apt-get >/dev/null 2>&1; then
205- sudo apt-get update -qq
206- sudo apt-get install -y -qq tmux
242+ if command -v sudo >/dev/null 2>&1; then
243+ sudo apt-get update -qq
244+ sudo apt-get install -y -qq tmux
245+ else
246+ apt-get update -qq || echo "Warning: Cannot update package lists without sudo privileges"
247+ apt-get install -y -qq tmux || echo "Warning: Cannot install tmux without sudo privileges"
248+ fi
207249 elif command -v dnf >/dev/null 2>&1; then
208- sudo dnf install -y -q tmux
250+ if command -v sudo >/dev/null 2>&1; then
251+ sudo dnf install -y -q tmux
252+ else
253+ dnf install -y -q tmux || echo "Warning: Cannot install tmux without sudo privileges"
254+ fi
209255 else
210- echo "Warning: Unable to install tmux on this system."
256+ echo "Warning: Unable to install tmux on this system. Neither apt-get nor dnf found. "
211257 fi
212258 else
213259 echo "tmux is already installed, skipping installation."
@@ -216,12 +262,21 @@ resource "coder_script" "aider" {
216262 if ! command_exists screen; then
217263 echo "Installing screen for persistent sessions..."
218264 if command -v apt-get >/dev/null 2>&1; then
219- sudo apt-get update -qq
220- sudo apt-get install -y -qq screen
265+ if command -v sudo >/dev/null 2>&1; then
266+ sudo apt-get update -qq
267+ sudo apt-get install -y -qq screen
268+ else
269+ apt-get update -qq || echo "Warning: Cannot update package lists without sudo privileges"
270+ apt-get install -y -qq screen || echo "Warning: Cannot install screen without sudo privileges"
271+ fi
221272 elif command -v dnf >/dev/null 2>&1; then
222- sudo dnf install -y -q screen
273+ if command -v sudo >/dev/null 2>&1; then
274+ sudo dnf install -y -q screen
275+ else
276+ dnf install -y -q screen || echo "Warning: Cannot install screen without sudo privileges"
277+ fi
223278 else
224- echo "Warning: Unable to install screen on this system."
279+ echo "Warning: Unable to install screen on this system. Neither apt-get nor dnf found. "
225280 fi
226281 else
227282 echo "screen is already installed, skipping installation."
@@ -245,12 +300,21 @@ resource "coder_script" "aider" {
245300 if ! command_exists python3 || ! command_exists pip3; then
246301 echo "Installing Python dependencies required for Aider..."
247302 if command -v apt-get >/dev/null 2>&1; then
248- sudo apt-get update -qq
249- sudo apt-get install -y -qq python3-pip python3-venv
303+ if command -v sudo >/dev/null 2>&1; then
304+ sudo apt-get update -qq
305+ sudo apt-get install -y -qq python3-pip python3-venv
306+ else
307+ apt-get update -qq || echo "Warning: Cannot update package lists without sudo privileges"
308+ apt-get install -y -qq python3-pip python3-venv || echo "Warning: Cannot install Python packages without sudo privileges"
309+ fi
250310 elif command -v dnf >/dev/null 2>&1; then
251- sudo dnf install -y -q python3-pip python3-virtualenv
311+ if command -v sudo >/dev/null 2>&1; then
312+ sudo dnf install -y -q python3-pip python3-virtualenv
313+ else
314+ dnf install -y -q python3-pip python3-virtualenv || echo "Warning: Cannot install Python packages without sudo privileges"
315+ fi
252316 else
253- echo "Warning: Unable to install Python on this system."
317+ echo "Warning: Unable to install Python on this system. Neither apt-get nor dnf found. "
254318 fi
255319 else
256320 echo "Python is already installed, skipping installation."
@@ -290,12 +354,6 @@ resource "coder_script" "aider" {
290354${ trimspace (local. combined_extensions )}
291355EOL
292356 echo "Added Coder MCP extension to Aider config.yml"
293-
294- mkdir -p "${ var . folder } "
295- cat > "${ var . folder } /CONVENTIONS.md" << 'CONVENTIONS_EOF'
296- ${ var . experiment_task_conventions }
297- CONVENTIONS_EOF
298- echo "Created CONVENTIONS.md file with task reporting instructions"
299357 fi
300358
301359 echo "Starting persistent Aider session..."
@@ -308,16 +366,41 @@ CONVENTIONS_EOF
308366 export PATH="$HOME/bin:$PATH"
309367
310368 if [ "${ var . use_tmux } " = "true" ]; then
311- if [ -n "$CODER_MCP_AIDER_TASK_PROMPT " ]; then
369+ if [ -n "${ var . task_prompt } " ]; then
312370 echo "Running Aider with message in tmux session..."
313- tmux new-session -d -s ${ var . session_name } -c ${ var . folder } "echo \"Starting Aider with app status slug: aider\"; export ANTHROPIC_API_KEY=\"$ANTHROPIC_API_KEY\"; export CODER_MCP_APP_STATUS_SLUG=\"aider\"; aider --architect --yes-always --read CONVENTIONS.md --message \"Report each step to Coder. Your task: $CODER_MCP_AIDER_TASK_PROMPT\""
371+
372+ # Configure tmux for shared sessions
373+ if [ ! -f "$HOME/.tmux.conf" ]; then
374+ echo "Creating ~/.tmux.conf with shared session settings..."
375+ echo "set -g mouse on" > "$HOME/.tmux.conf"
376+ fi
377+
378+ if ! grep -q "^set -g mouse on$" "$HOME/.tmux.conf"; then
379+ echo "Adding 'set -g mouse on' to ~/.tmux.conf..."
380+ echo "set -g mouse on" >> "$HOME/.tmux.conf"
381+ fi
382+
383+ echo "Starting Aider using ${ var . ai_provider } provider and model: ${ var . ai_model } "
384+ tmux new-session -d -s ${ var . session_name } -c ${ var . folder } "export ${ local . env_var_name } =\"${ var . ai_api_key } \"; aider --architect --yes-always ${ local . model_flag } ${ var . ai_model } --message \"${ local . combined_prompt } \""
314385 echo "Aider task started in tmux session '${ var . session_name } '. Check the UI for progress."
315386 else
316- tmux new-session -d -s ${ var . session_name } -c ${ var . folder } "echo \"Starting Aider with app status slug: aider\"; export ANTHROPIC_API_KEY=\"$ANTHROPIC_API_KEY\"; export CODER_MCP_APP_STATUS_SLUG=\"aider\"; aider --read CONVENTIONS.md"
387+ # Configure tmux for shared sessions
388+ if [ ! -f "$HOME/.tmux.conf" ]; then
389+ echo "Creating ~/.tmux.conf with shared session settings..."
390+ echo "set -g mouse on" > "$HOME/.tmux.conf"
391+ fi
392+
393+ if ! grep -q "^set -g mouse on$" "$HOME/.tmux.conf"; then
394+ echo "Adding 'set -g mouse on' to ~/.tmux.conf..."
395+ echo "set -g mouse on" >> "$HOME/.tmux.conf"
396+ fi
397+
398+ echo "Starting Aider using ${ var . ai_provider } provider and model: ${ var . ai_model } "
399+ tmux new-session -d -s ${ var . session_name } -c ${ var . folder } "export ${ local . env_var_name } =\"${ var . ai_api_key } \"; aider --architect --yes-always ${ local . model_flag } ${ var . ai_model } --message \"${ var . system_prompt } \""
317400 echo "Tmux session '${ var . session_name } ' started. Access it by clicking the Aider button."
318401 fi
319402 else
320- if [ -n "$CODER_MCP_AIDER_TASK_PROMPT " ]; then
403+ if [ -n "${ var . task_prompt } " ]; then
321404 echo "Running Aider with message in screen session..."
322405
323406 if [ ! -f "$HOME/.screenrc" ]; then
@@ -335,13 +418,12 @@ CONVENTIONS_EOF
335418 echo "acladd $(whoami)" >> "$HOME/.screenrc"
336419 fi
337420
421+ echo "Starting Aider using ${ var . ai_provider } provider and model: ${ var . ai_model } "
338422 screen -U -dmS ${ var . session_name } bash -c "
339423 cd ${ var . folder }
340424 export PATH=\"$HOME/bin:$HOME/.local/bin:$PATH\"
341- export ANTHROPIC_API_KEY=\"$ANTHROPIC_API_KEY\"
342- export CODER_MCP_APP_STATUS_SLUG=\"aider\"
343- echo \"Starting Aider with app status slug: aider\"
344- aider --architect --yes-always --read CONVENTIONS.md --message \"Report each step to Coder. Your task: $CODER_MCP_AIDER_TASK_PROMPT\"
425+ export ${ local . env_var_name } =\"${ var . ai_api_key } \"
426+ aider --architect --yes-always ${ local . model_flag } ${ var . ai_model } --message \"${ local . combined_prompt } \"
345427 /bin/bash
346428 "
347429
@@ -363,13 +445,12 @@ CONVENTIONS_EOF
363445 echo "acladd $(whoami)" >> "$HOME/.screenrc"
364446 fi
365447
448+ echo "Starting Aider using ${ var . ai_provider } provider and model: ${ var . ai_model } "
366449 screen -U -dmS ${ var . session_name } bash -c "
367450 cd ${ var . folder }
368451 export PATH=\"$HOME/bin:$HOME/.local/bin:$PATH\"
369- export ANTHROPIC_API_KEY=\"$ANTHROPIC_API_KEY\"
370- export CODER_MCP_APP_STATUS_SLUG=\"aider\"
371- echo \"Starting Aider with app status slug: aider\"
372- aider --read CONVENTIONS.md
452+ export ${ local . env_var_name } =\"${ var . ai_api_key } \"
453+ aider --architect --yes-always ${ local . model_flag } ${ var . ai_model } --message \"${ local . combined_prompt } \"
373454 /bin/bash
374455 "
375456 echo "Screen session '${ var . session_name } ' started. Access it by clicking the Aider button."
@@ -393,32 +474,28 @@ resource "coder_app" "aider_cli" {
393474
394475 export PATH="$HOME/bin:$HOME/.local/bin:$PATH"
395476
396- export CODER_MCP_APP_STATUS_SLUG="aider"
397-
398477 export LANG=en_US.UTF-8
399478 export LC_ALL=en_US.UTF-8
400479
401480 if [ "${ var . use_tmux } " = "true" ]; then
402481 if tmux has-session -t ${ var . session_name } 2>/dev/null; then
403482 echo "Attaching to existing Aider tmux session..."
404- tmux setenv -t ${ var . session_name } CODER_MCP_APP_STATUS_SLUG "aider"
405483 tmux attach-session -t ${ var . session_name }
406484 else
407485 echo "Starting new Aider tmux session..."
408- tmux new-session -s ${ var . session_name } -c ${ var . folder } "export ANTHROPIC_API_KEY =\"$ANTHROPIC_API_KEY \"; export CODER_MCP_APP_STATUS_SLUG=\" aider\"; aider --read CONVENTIONS.md ; exec bash"
486+ tmux new-session -s ${ var . session_name } -c ${ var . folder } "export ${ local . env_var_name } =\"${ var . ai_api_key } \"; aider ${ local . model_flag } ${ var . ai_model } --message \" ${ local . combined_prompt } \" ; exec bash"
409487 fi
410488 elif [ "${ var . use_screen } " = "true" ]; then
411489 if ! screen -list | grep -q "${ var . session_name } "; then
412490 echo "Error: No existing Aider session found. Please wait for the script to start it."
413491 exit 1
414492 fi
415- export CODER_MCP_APP_STATUS_SLUG="aider"
416493 screen -xRR ${ var . session_name }
417494 else
418495 cd "${ var . folder } "
419496 echo "Starting Aider directly..."
420- export CODER_MCP_APP_STATUS_SLUG="aider "
421- aider --read CONVENTIONS.md
497+ export ${ local . env_var_name } =" ${ var . ai_api_key } "
498+ aider ${ local . model_flag } ${ var . ai_model } --message " ${ local . combined_prompt } "
422499 fi
423500 EOT
424501 order = var. order
0 commit comments