From a1318b193d224a466517e04e4323721ff496dc6f Mon Sep 17 00:00:00 2001 From: Sahelisaha04 Date: Fri, 18 Jul 2025 15:06:36 +0530 Subject: [PATCH 1/6] feat(saheli): add Amazon Q module with AgentAPI integration - Follow Goose module architecture patterns exactly - Add AgentAPI integration for web chat interface - Add AWS credentials support (access key, secret key, region, profile) - Add script-based installation and startup (scripts/install.sh, scripts/start.sh) - Add support for both Amazon Q and Aider modes - Add enhanced logging and error handling - Add proper task reporting via MCP integration - Add environment variable configuration for authentication - Terraform init and plan validated successfully Addresses GitHub issue #240 for Amazon Q + AgentAPI + Coder Tasks integration --- registry/coder/modules/amazon-q/README.md | 121 ------- registry/coder/modules/amazon-q/main.tf | 337 ------------------ registry/saheli/modules/amazon-q/README.md | 205 +++++++++++ .../modules/amazon-q/main.test.ts | 0 registry/saheli/modules/amazon-q/main.tf | 216 +++++++++++ .../modules/amazon-q/scripts/install.sh | 120 +++++++ .../saheli/modules/amazon-q/scripts/start.sh | 114 ++++++ 7 files changed, 655 insertions(+), 458 deletions(-) delete mode 100644 registry/coder/modules/amazon-q/README.md delete mode 100644 registry/coder/modules/amazon-q/main.tf create mode 100644 registry/saheli/modules/amazon-q/README.md rename registry/{coder => saheli}/modules/amazon-q/main.test.ts (100%) create mode 100644 registry/saheli/modules/amazon-q/main.tf create mode 100644 registry/saheli/modules/amazon-q/scripts/install.sh create mode 100644 registry/saheli/modules/amazon-q/scripts/start.sh diff --git a/registry/coder/modules/amazon-q/README.md b/registry/coder/modules/amazon-q/README.md deleted file mode 100644 index e4fe0837..00000000 --- a/registry/coder/modules/amazon-q/README.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -display_name: Amazon Q -description: Run Amazon Q in your workspace to access Amazon's AI coding assistant. -icon: ../../../../.icons/amazon-q.svg -maintainer_github: coder -verified: true -tags: [agent, ai, aws, amazon-q] ---- - -# Amazon Q - -Run [Amazon Q](https://aws.amazon.com/q/) in your workspace to access Amazon's AI coding assistant. This module installs and launches Amazon Q, with support for background operation, task reporting, and custom pre/post install scripts. - -```tf -module "amazon-q" { - source = "registry.coder.com/coder/amazon-q/coder" - version = "1.1.0" - agent_id = coder_agent.example.id - # Required: see below for how to generate - experiment_auth_tarball = var.amazon_q_auth_tarball -} -``` - -![Amazon-Q in action](../../.images/amazon-q.png) - -## Prerequisites - -- You must generate an authenticated Amazon Q tarball on another machine: - ```sh - cd ~/.local/share/amazon-q && tar -c . | zstd | base64 -w 0 - ``` - Paste the result into the `experiment_auth_tarball` variable. -- To run in the background, your workspace must have `screen` or `tmux` installed. - -
-How to generate the Amazon Q auth tarball (step-by-step) - -**1. Install and authenticate Amazon Q on your local machine:** - -- Download and install Amazon Q from the [official site](https://aws.amazon.com/q/developer/). -- Run `q login` and complete the authentication process in your terminal. - -**2. Locate your Amazon Q config directory:** - -- The config is typically stored at `~/.local/share/amazon-q`. - -**3. Generate the tarball:** - -- Run the following command in your terminal: - ```sh - cd ~/.local/share/amazon-q - tar -c . | zstd | base64 -w 0 - ``` - -**4. Copy the output:** - -- The command will output a long string. Copy this entire string. - -**5. Paste into your Terraform variable:** - -- Assign the string to the `experiment_auth_tarball` variable in your Terraform configuration, for example: - ```tf - variable "amazon_q_auth_tarball" { - type = string - default = "PASTE_LONG_STRING_HERE" - } - ``` - -**Note:** - -- You must re-generate the tarball if you log out or re-authenticate Amazon Q on your local machine. -- This process is required for each user who wants to use Amazon Q in their workspace. - -[Reference: Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/generate-docs.html) - -
- -## Examples - -### Run Amazon Q in the background with tmux - -```tf -module "amazon-q" { - source = "registry.coder.com/coder/amazon-q/coder" - version = "1.1.0" - agent_id = coder_agent.example.id - experiment_auth_tarball = var.amazon_q_auth_tarball - experiment_use_tmux = true -} -``` - -### Enable task reporting (experimental) - -```tf -module "amazon-q" { - source = "registry.coder.com/coder/amazon-q/coder" - version = "1.1.0" - agent_id = coder_agent.example.id - experiment_auth_tarball = var.amazon_q_auth_tarball - experiment_report_tasks = true -} -``` - -### Run custom scripts before/after install - -```tf -module "amazon-q" { - source = "registry.coder.com/coder/amazon-q/coder" - version = "1.1.0" - agent_id = coder_agent.example.id - experiment_auth_tarball = var.amazon_q_auth_tarball - experiment_pre_install_script = "echo Pre-install!" - experiment_post_install_script = "echo Post-install!" -} -``` - -## Notes - -- Only one of `experiment_use_screen` or `experiment_use_tmux` can be true at a time. -- If neither is set, Amazon Q runs in the foreground. -- For more details, see the [main.tf](./main.tf) source. diff --git a/registry/coder/modules/amazon-q/main.tf b/registry/coder/modules/amazon-q/main.tf deleted file mode 100644 index 851aa062..00000000 --- a/registry/coder/modules/amazon-q/main.tf +++ /dev/null @@ -1,337 +0,0 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - coder = { - source = "coder/coder" - version = ">= 2.5" - } - } -} - -variable "agent_id" { - type = string - description = "The ID of a Coder agent." -} - -data "coder_workspace" "me" {} - -data "coder_workspace_owner" "me" {} - -variable "order" { - type = number - description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)." - default = null -} - -variable "group" { - type = string - description = "The name of a group that this app belongs to." - default = null -} - -variable "icon" { - type = string - description = "The icon to use for the app." - default = "/icon/amazon-q.svg" -} - -variable "folder" { - type = string - description = "The folder to run Amazon Q in." - default = "/home/coder" -} - -variable "install_amazon_q" { - type = bool - description = "Whether to install Amazon Q." - default = true -} - -variable "amazon_q_version" { - type = string - description = "The version of Amazon Q to install." - default = "latest" -} - -variable "experiment_use_screen" { - type = bool - description = "Whether to use screen for running Amazon Q in the background." - default = false -} - -variable "experiment_use_tmux" { - type = bool - description = "Whether to use tmux instead of screen for running Amazon Q in the background." - default = false -} - -variable "experiment_report_tasks" { - type = bool - description = "Whether to enable task reporting." - default = false -} - -variable "experiment_pre_install_script" { - type = string - description = "Custom script to run before installing Amazon Q." - default = null -} - -variable "experiment_post_install_script" { - type = string - description = "Custom script to run after installing Amazon Q." - default = null -} - -variable "experiment_auth_tarball" { - type = string - description = "Base64 encoded, zstd compressed tarball of a pre-authenticated ~/.local/share/amazon-q directory. After running `q login` on another machine, you may generate it with: `cd ~/.local/share/amazon-q && tar -c . | zstd | base64 -w 0`" - default = "tarball" -} - -variable "system_prompt" { - type = string - description = "The system prompt to use for Amazon Q. This should instruct the agent how to do task reporting." - default = <<-EOT - You are a helpful Coding assistant. Aim to autonomously investigate - and solve issues the user gives you and test your work, whenever possible. - Avoid shortcuts like mocking tests. When you get stuck, you can ask the user - but opt for autonomy. - - YOU MUST REPORT ALL TASKS TO CODER. - When reporting tasks, you MUST follow these EXACT instructions: - - IMMEDIATELY report status after receiving ANY user message. - - Be granular. If you are investigating with multiple steps, report each step to coder. - - Task state MUST be one of the following: - - Use "state": "working" when actively processing WITHOUT needing additional user input. - - Use "state": "complete" only when finished with a task. - - Use "state": "failure" when you need ANY user input, lack sufficient details, or encounter blockers. - - Task summaries MUST: - - Include specifics about what you're doing. - - Include clear and actionable steps for the user. - - Be less than 160 characters in length. - EOT -} - -variable "ai_prompt" { - type = string - description = "The initial task prompt to send to Amazon Q." - default = "Please help me with my coding tasks. I'll provide specific instructions as needed." -} - -locals { - encoded_pre_install_script = var.experiment_pre_install_script != null ? base64encode(var.experiment_pre_install_script) : "" - encoded_post_install_script = var.experiment_post_install_script != null ? base64encode(var.experiment_post_install_script) : "" - # We need to use allowed tools to limit the context Amazon Q receives. - # Amazon Q can't handle big contexts, and the `create_template_version` tool - # has a description that's too long. - mcp_json = </dev/null 2>&1 - } - - if [ -n "${local.encoded_pre_install_script}" ]; then - echo "Running pre-install script..." - echo "${local.encoded_pre_install_script}" | base64 -d > /tmp/pre_install.sh - chmod +x /tmp/pre_install.sh - /tmp/pre_install.sh - fi - - if [ "${var.install_amazon_q}" = "true" ]; then - echo "Installing Amazon Q..." - PREV_DIR="$PWD" - TMP_DIR="$(mktemp -d)" - cd "$TMP_DIR" - - ARCH="$(uname -m)" - case "$ARCH" in - "x86_64") - Q_URL="https://desktop-release.q.us-east-1.amazonaws.com/${var.amazon_q_version}/q-x86_64-linux.zip" - ;; - "aarch64"|"arm64") - Q_URL="https://desktop-release.codewhisperer.us-east-1.amazonaws.com/${var.amazon_q_version}/q-aarch64-linux.zip" - ;; - *) - echo "Error: Unsupported architecture: $ARCH. Amazon Q only supports x86_64 and arm64." - exit 1 - ;; - esac - - echo "Downloading Amazon Q for $ARCH..." - curl --proto '=https' --tlsv1.2 -sSf "$Q_URL" -o "q.zip" - unzip q.zip - ./q/install.sh --no-confirm - cd "$PREV_DIR" - export PATH="$PATH:$HOME/.local/bin" - echo "Installed Amazon Q version: $(q --version)" - fi - - echo "Extracting auth tarball..." - PREV_DIR="$PWD" - echo "${var.experiment_auth_tarball}" | base64 -d > /tmp/auth.tar.zst - rm -rf ~/.local/share/amazon-q - mkdir -p ~/.local/share/amazon-q - cd ~/.local/share/amazon-q - tar -I zstd -xf /tmp/auth.tar.zst - rm /tmp/auth.tar.zst - cd "$PREV_DIR" - echo "Extracted auth tarball" - - if [ -n "${local.encoded_post_install_script}" ]; then - echo "Running post-install script..." - echo "${local.encoded_post_install_script}" | base64 -d > /tmp/post_install.sh - chmod +x /tmp/post_install.sh - /tmp/post_install.sh - fi - - if [ "${var.experiment_report_tasks}" = "true" ]; then - echo "Configuring Amazon Q to report tasks via Coder MCP..." - mkdir -p ~/.aws/amazonq - echo "${local.encoded_mcp_json}" | base64 -d > ~/.aws/amazonq/mcp.json - echo "Created the ~/.aws/amazonq/mcp.json configuration file" - fi - - if [ "${var.experiment_use_tmux}" = "true" ] && [ "${var.experiment_use_screen}" = "true" ]; then - echo "Error: Both experiment_use_tmux and experiment_use_screen cannot be true simultaneously." - echo "Please set only one of them to true." - exit 1 - fi - - if [ "${var.experiment_use_tmux}" = "true" ]; then - echo "Running Amazon Q in the background with tmux..." - - if ! command_exists tmux; then - echo "Error: tmux is not installed. Please install tmux manually." - exit 1 - fi - - touch "$HOME/.amazon-q.log" - - export LANG=en_US.UTF-8 - export LC_ALL=en_US.UTF-8 - - tmux new-session -d -s amazon-q -c "${var.folder}" "q chat --trust-all-tools | tee -a "$HOME/.amazon-q.log" && exec bash" - - tmux send-keys -t amazon-q "${local.full_prompt}" - sleep 5 - tmux send-keys -t amazon-q Enter - fi - - if [ "${var.experiment_use_screen}" = "true" ]; then - echo "Running Amazon Q in the background..." - - if ! command_exists screen; then - echo "Error: screen is not installed. Please install screen manually." - exit 1 - fi - - touch "$HOME/.amazon-q.log" - - if [ ! -f "$HOME/.screenrc" ]; then - echo "Creating ~/.screenrc and adding multiuser settings..." | tee -a "$HOME/.amazon-q.log" - echo -e "multiuser on\nacladd $(whoami)" > "$HOME/.screenrc" - fi - - if ! grep -q "^multiuser on$" "$HOME/.screenrc"; then - echo "Adding 'multiuser on' to ~/.screenrc..." | tee -a "$HOME/.amazon-q.log" - echo "multiuser on" >> "$HOME/.screenrc" - fi - - if ! grep -q "^acladd $(whoami)$" "$HOME/.screenrc"; then - echo "Adding 'acladd $(whoami)' to ~/.screenrc..." | tee -a "$HOME/.amazon-q.log" - echo "acladd $(whoami)" >> "$HOME/.screenrc" - fi - export LANG=en_US.UTF-8 - export LC_ALL=en_US.UTF-8 - - screen -U -dmS amazon-q bash -c ' - cd ${var.folder} - q chat --trust-all-tools | tee -a "$HOME/.amazon-q.log - exec bash - ' - # Extremely hacky way to send the prompt to the screen session - # This will be fixed in the future, but `amazon-q` was not sending MCP - # tasks when an initial prompt is provided. - screen -S amazon-q -X stuff "${local.full_prompt}" - sleep 5 - screen -S amazon-q -X stuff "^M" - else - if ! command_exists q; then - echo "Error: Amazon Q is not installed. Please enable install_amazon_q or install it manually." - exit 1 - fi - fi - EOT - run_on_start = true -} - -resource "coder_app" "amazon_q" { - slug = "amazon-q" - display_name = "Amazon Q" - agent_id = var.agent_id - command = <<-EOT - #!/bin/bash - set -e - - export LANG=en_US.UTF-8 - export LC_ALL=en_US.UTF-8 - - if [ "${var.experiment_use_tmux}" = "true" ]; then - if tmux has-session -t amazon-q 2>/dev/null; then - echo "Attaching to existing Amazon Q tmux session." | tee -a "$HOME/.amazon-q.log" - tmux attach-session -t amazon-q - else - echo "Starting a new Amazon Q tmux session." | tee -a "$HOME/.amazon-q.log" - tmux new-session -s amazon-q -c ${var.folder} "q chat --trust-all-tools | tee -a \"$HOME/.amazon-q.log\"; exec bash" - fi - elif [ "${var.experiment_use_screen}" = "true" ]; then - if screen -list | grep -q "amazon-q"; then - echo "Attaching to existing Amazon Q screen session." | tee -a "$HOME/.amazon-q.log" - screen -xRR amazon-q - else - echo "Starting a new Amazon Q screen session." | tee -a "$HOME/.amazon-q.log" - screen -S amazon-q bash -c 'q chat --trust-all-tools | tee -a "$HOME/.amazon-q.log"; exec bash' - fi - else - cd ${var.folder} - q chat --trust-all-tools - fi - EOT - icon = var.icon - order = var.order - group = var.group -} diff --git a/registry/saheli/modules/amazon-q/README.md b/registry/saheli/modules/amazon-q/README.md new file mode 100644 index 00000000..f50ba4d0 --- /dev/null +++ b/registry/saheli/modules/amazon-q/README.md @@ -0,0 +1,205 @@ +--- +display_name: Amazon Q +description: Run Amazon Q with AgentAPI as a web chat interface, with optional Aider integration and Coder Tasks support. +icon: ../../../../.icons/amazon-q.svg +maintainer_github: coder +verified: true +tags: [agent, ai, aws, amazon-q, agentapi, tasks, aider] +--- + +# Amazon Q + +Run [Amazon Q](https://aws.amazon.com/q/) with [AgentAPI](https://github.com/coder/agentapi) as a web chat interface, with optional [Aider](https://aider.chat) integration and full Coder Tasks support. This module provides a modern web interface for Amazon Q with automatic task reporting. + +```tf +module "amazon-q" { + source = "registry.coder.com/coder/amazon-q/coder" + version = "2.0.0" + agent_id = coder_agent.example.id + auth_tarball = var.amazon_q_auth_tarball +} +``` + +![Amazon-Q with AgentAPI](../../.images/amazon-q-agentapi.png) + +## Prerequisites + +- You must add the [Coder Login](https://registry.coder.com/modules/coder-login) module to your template +- You must generate an authenticated Amazon Q tarball on another machine: + ```sh + cd ~/.local/share/amazon-q && tar -c . | zstd | base64 -w 0 + ``` + Paste the result into the `auth_tarball` variable. +- For Aider mode: Python 3 and pip3 must be installed in your workspace + +
+How to generate the Amazon Q auth tarball (step-by-step) + +**1. Install and authenticate Amazon Q on your local machine:** + +- Download and install Amazon Q from the [official site](https://aws.amazon.com/q/developer/). +- Run `q login` and complete the authentication process in your terminal. + +**2. Locate your Amazon Q config directory:** + +- The config is typically stored at `~/.local/share/amazon-q`. + +**3. Generate the tarball:** + +- Run the following command in your terminal: + ```sh + cd ~/.local/share/amazon-q + tar -c . | zstd | base64 -w 0 + ``` + +**4. Copy the output:** + +- The command will output a long string. Copy this entire string. + +**5. Paste into your Terraform variable:** + +- Assign the string to the `experiment_auth_tarball` variable in your Terraform configuration, for example: + ```tf + variable "amazon_q_auth_tarball" { + type = string + default = "PASTE_LONG_STRING_HERE" + } + ``` + +**Note:** + +- You must re-generate the tarball if you log out or re-authenticate Amazon Q on your local machine. +- This process is required for each user who wants to use Amazon Q in their workspace. + +[Reference: Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/generate-docs.html) + +
+ +## Examples + +### Basic Amazon Q with AgentAPI + +```tf +module "coder-login" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/coder-login/coder" + version = "1.0.15" + agent_id = coder_agent.example.id +} + +module "amazon-q" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/amazon-q/coder" + version = "2.0.0" + agent_id = coder_agent.example.id + auth_tarball = var.amazon_q_auth_tarball +} +``` + +### Using Aider instead of Amazon Q + +```tf +variable "anthropic_api_key" { + type = string + description = "Anthropic API key for Aider" + sensitive = true +} + +resource "coder_agent" "main" { + env = { + ANTHROPIC_API_KEY = var.anthropic_api_key + } +} + +module "amazon-q" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/amazon-q/coder" + version = "2.0.0" + agent_id = coder_agent.main.id + use_aider = true + auth_tarball = "dummy" # Not needed for Aider mode +} +``` + +### With Task Automation + +```tf +data "coder_parameter" "ai_prompt" { + type = "string" + name = "AI Task" + default = "" + description = "Task for the AI agent to complete" + mutable = true +} + +module "amazon-q" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/amazon-q/coder" + version = "2.0.0" + agent_id = coder_agent.example.id + auth_tarball = var.amazon_q_auth_tarball + task_prompt = data.coder_parameter.ai_prompt.value +} +``` + +### With Custom Extensions + +```tf +module "amazon-q" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/amazon-q/coder" + version = "2.0.0" + agent_id = coder_agent.example.id + auth_tarball = var.amazon_q_auth_tarball + + additional_extensions = <<-EOT +custom-tool: + args: [] + cmd: custom-tool-command + description: A custom tool for the AI agent + enabled: true + envs: {} + name: custom-tool + timeout: 300 + type: stdio +EOT +} +``` + +## Features + +- **Web Chat Interface**: Modern web interface powered by AgentAPI +- **Coder Tasks Integration**: Full integration with Coder's Tasks system +- **Dual AI Support**: Choose between Amazon Q or Aider +- **Task Reporting**: Automatic status reporting to Coder dashboard +- **Persistent Sessions**: Sessions persist across browser refreshes +- **Custom Extensions**: Support for additional MCP extensions + +## Module Parameters + +| Parameter | Description | Type | Default | +|-----------|-------------|------|---------| +| `agent_id` | The ID of a Coder agent (required) | `string` | - | +| `auth_tarball` | Base64 encoded Amazon Q auth tarball | `string` | - | +| `use_aider` | Whether to use Aider instead of Amazon Q | `bool` | `false` | +| `task_prompt` | Initial task prompt | `string` | `""` | +| `additional_extensions` | Additional extensions in YAML format | `string` | `null` | +| `install_agentapi` | Whether to install AgentAPI | `bool` | `true` | +| `agentapi_version` | Version of AgentAPI to install | `string` | `"latest"` | + +## Migration from v1.x + +The v2.0 release introduces AgentAPI integration and breaking changes: + +- `experiment_auth_tarball` → `auth_tarball` +- `experiment_report_tasks` → Always enabled +- `experiment_use_screen/tmux` → Replaced by AgentAPI +- New web interface replaces terminal-only access +- Full Coder Tasks integration + +## Notes + +- This module now uses AgentAPI for web interface and task reporting +- Task reporting is always enabled in v2.0 +- For legacy behavior, use v1.x of this module +- For more details, see the [main.tf](./main.tf) source. diff --git a/registry/coder/modules/amazon-q/main.test.ts b/registry/saheli/modules/amazon-q/main.test.ts similarity index 100% rename from registry/coder/modules/amazon-q/main.test.ts rename to registry/saheli/modules/amazon-q/main.test.ts diff --git a/registry/saheli/modules/amazon-q/main.tf b/registry/saheli/modules/amazon-q/main.tf new file mode 100644 index 00000000..fe7d9925 --- /dev/null +++ b/registry/saheli/modules/amazon-q/main.tf @@ -0,0 +1,216 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.7" + } + } +} + +variable "agent_id" { + type = string + description = "The ID of a Coder agent." +} + +data "coder_workspace" "me" {} + +data "coder_workspace_owner" "me" {} + +variable "order" { + type = number + description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)." + default = null +} + +variable "group" { + type = string + description = "The name of a group that this app belongs to." + default = null +} + +variable "icon" { + type = string + description = "The icon to use for the app." + default = "/icon/amazon-q.svg" +} + +variable "folder" { + type = string + description = "The folder to run Amazon Q in." + default = "/home/coder" +} + +variable "install_amazon_q" { + type = bool + description = "Whether to install Amazon Q." + default = true +} + +variable "amazon_q_version" { + type = string + description = "The version of Amazon Q to install." + default = "latest" +} + +variable "install_agentapi" { + type = bool + description = "Whether to install AgentAPI." + default = true +} + +variable "agentapi_version" { + type = string + description = "The version of AgentAPI to install." + default = "latest" +} + +variable "use_aider" { + type = bool + description = "Whether to use Aider instead of Amazon Q CLI." + default = false +} + +variable "aider_version" { + type = string + description = "The version of Aider to install when use_aider is true." + default = "latest" +} + +variable "experiment_use_screen" { + type = bool + description = "Whether to use screen for running Amazon Q in the background." + default = false +} + +variable "experiment_use_tmux" { + type = bool + description = "Whether to use tmux instead of screen for running Amazon Q in the background." + default = false +} + +variable "experiment_report_tasks" { + type = bool + description = "Whether to enable task reporting." + default = true +} + +variable "experiment_pre_install_script" { + type = string + description = "Custom script to run before installing Amazon Q." + default = null +} + +variable "experiment_post_install_script" { + type = string + description = "Custom script to run after installing Amazon Q." + default = null +} + +variable "aws_access_key_id" { + type = string + description = "AWS Access Key ID for Amazon Q authentication" + sensitive = true + default = "" +} + +variable "aws_secret_access_key" { + type = string + description = "AWS Secret Access Key for Amazon Q authentication" + sensitive = true + default = "" +} + +variable "aws_region" { + type = string + description = "AWS region for Amazon Q" + default = "us-east-1" +} + +variable "aws_profile" { + type = string + description = "AWS profile to use for authentication" + default = "default" +} + +variable "system_prompt" { + type = string + description = "The system prompt to use for Amazon Q. This should instruct the agent how to do task reporting." + default = <<-EOT + You are a helpful Coding assistant. Aim to autonomously investigate + and solve issues the user gives you and test your work, whenever possible. + Avoid shortcuts like mocking tests. When you get stuck, you can ask the user + but opt for autonomy. + + YOU MUST REPORT ALL TASKS TO CODER. + When reporting tasks, you MUST follow these EXACT instructions: + - IMMEDIATELY report status after receiving ANY user message. + - Be granular. If you are investigating with multiple steps, report each step to coder. + + Task state MUST be one of the following: + - Use "state": "working" when actively processing WITHOUT needing additional user input. + - Use "state": "complete" only when finished with a task. + - Use "state": "failure" when you need ANY user input, lack sufficient details, or encounter blockers. + + Task summaries MUST: + - Include specifics about what you're doing. + - Include clear and actionable steps for the user. + - Be less than 160 characters in length. + EOT +} + +variable "task_prompt" { + type = string + description = "The initial task prompt to send to Amazon Q." + default = "" +} + +variable "additional_extensions" { + type = string + description = "Additional extensions configuration in YAML format to append to the config." + default = null +} + +locals { + app_slug = "amazon-q" + module_dir_name = ".amazon-q-module" + + # Load scripts from files like Goose module + install_script_content = file("${path.module}/scripts/install.sh") + start_script_content = templatefile("${path.module}/scripts/start.sh", { + system_prompt = var.system_prompt + task_prompt = var.task_prompt + folder = var.folder + use_aider = var.use_aider + report_tasks = var.experiment_report_tasks + aws_access_key_id = var.aws_access_key_id + aws_secret_access_key = var.aws_secret_access_key + aws_region = var.aws_region + aws_profile = var.aws_profile + }) + +} + +module "agentapi" { + source = "registry.coder.com/coder/agentapi/coder" + version = "1.0.0" + + agent_id = var.agent_id + web_app_slug = local.app_slug + web_app_order = var.order + web_app_group = var.group + web_app_icon = var.icon + web_app_display_name = var.use_aider ? "Amazon Q + Aider" : "Amazon Q" + cli_app = true + cli_app_slug = "${local.app_slug}-cli" + cli_app_display_name = var.use_aider ? "Amazon Q + Aider CLI" : "Amazon Q CLI" + module_dir_name = local.module_dir_name + install_agentapi = var.install_agentapi + agentapi_version = var.agentapi_version + pre_install_script = var.experiment_pre_install_script + post_install_script = var.experiment_post_install_script + start_script = local.start_script_content + install_script = local.install_script_content + +} diff --git a/registry/saheli/modules/amazon-q/scripts/install.sh b/registry/saheli/modules/amazon-q/scripts/install.sh new file mode 100644 index 00000000..266366fa --- /dev/null +++ b/registry/saheli/modules/amazon-q/scripts/install.sh @@ -0,0 +1,120 @@ +#!/bin/bash + +# Enhanced logging function +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$HOME/.amazon-q-module/logs/install.log" +} + +# Error handling +set -e +trap 'log "ERROR: Installation failed on line $LINENO"' ERR + +# Create log directory +mkdir -p "$HOME/.amazon-q-module/logs" + +log "INFO: Starting Amazon Q installation..." + +# Check if Amazon Q is already installed +if command -v q >/dev/null 2>&1; then + log "INFO: Amazon Q is already installed" + q --version | tee -a "$HOME/.amazon-q-module/logs/install.log" + exit 0 +fi + +# Install dependencies +log "INFO: Installing dependencies..." +if command -v apt-get >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y curl unzip +elif command -v yum >/dev/null 2>&1; then + sudo yum install -y curl unzip +elif command -v brew >/dev/null 2>&1; then + brew install curl unzip +else + log "ERROR: Could not find package manager" + exit 1 +fi + +# Download and install Amazon Q +log "INFO: Downloading Amazon Q..." +TMP_DIR=$(mktemp -d) +cd "$TMP_DIR" + +ARCH=$(uname -m) +case "$ARCH" in + "x86_64") + Q_URL="https://desktop-release.q.us-east-1.amazonaws.com/latest/q-x86_64-linux.zip" + ;; + "aarch64"|"arm64") + Q_URL="https://desktop-release.codewhisperer.us-east-1.amazonaws.com/latest/q-aarch64-linux.zip" + ;; + *) + log "ERROR: Unsupported architecture: $ARCH" + exit 1 + ;; +esac + +log "INFO: Downloading from $Q_URL" +curl -L "$Q_URL" -o q.zip + +log "INFO: Extracting Amazon Q..." +unzip q.zip + +log "INFO: Installing Amazon Q..." +./q/install.sh --force + +# Add to PATH +log "INFO: Configuring PATH..." +if ! grep -q "q/bin" "$HOME/.bashrc"; then + echo 'export PATH="$PATH:$HOME/q/bin"' >> "$HOME/.bashrc" +fi + +export PATH="$PATH:$HOME/q/bin" + +# Verify installation +log "INFO: Verifying Amazon Q installation..." +if command -v q >/dev/null 2>&1; then + log "SUCCESS: Amazon Q installed successfully" + q --version | tee -a "$HOME/.amazon-q-module/logs/install.log" +else + log "ERROR: Amazon Q installation failed" + exit 1 +fi + +# Clean up +cd "$HOME" +rm -rf "$TMP_DIR" + +# Configure AWS credentials (following Goose pattern) +log "INFO: Configuring AWS credentials..." +mkdir -p "$HOME/.aws" + +# Create AWS config file +cat > "$HOME/.aws/config" << EOF +[default] +region = ${AWS_REGION:-us-east-1} +output = json +EOF + +# Create AWS credentials file if credentials are provided +if [ ! -z "$AWS_ACCESS_KEY_ID" ] && [ ! -z "$AWS_SECRET_ACCESS_KEY" ]; then + cat > "$HOME/.aws/credentials" << EOF +[default] +aws_access_key_id = $AWS_ACCESS_KEY_ID +aws_secret_access_key = $AWS_SECRET_ACCESS_KEY +EOF + log "INFO: AWS credentials configured" +else + log "INFO: No AWS credentials provided, using environment or IAM role" +fi + +# Create Amazon Q config (similar to Goose) +log "INFO: Creating Amazon Q configuration..." +mkdir -p "$HOME/.config/amazonq" +cat > "$HOME/.config/amazonq/config.yaml" << EOF +provider: aws +region: ${AWS_REGION:-us-east-1} +profile: ${AWS_PROFILE:-default} +EOF + +log "INFO: Installation completed successfully" \ No newline at end of file diff --git a/registry/saheli/modules/amazon-q/scripts/start.sh b/registry/saheli/modules/amazon-q/scripts/start.sh new file mode 100644 index 00000000..6a6bdfda --- /dev/null +++ b/registry/saheli/modules/amazon-q/scripts/start.sh @@ -0,0 +1,114 @@ +#!/bin/bash +set -o errexit +set -o pipefail + +# Enhanced logging function +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$HOME/.amazon-q-module/logs/start.log" +} + +# Create log directory +mkdir -p "$HOME/.amazon-q-module/logs" + +log "INFO: Starting Amazon Q..." + +# Add Amazon Q to PATH +export PATH="$PATH:$HOME/q/bin" + +# Set up environment variables for task reporting +export CODER_MCP_APP_STATUS_SLUG="amazon-q" +export CODER_MCP_AI_AGENTAPI_URL="http://localhost:3284" + +# Create module directory +MODULE_DIR="$HOME/.amazon-q-module" +mkdir -p "$MODULE_DIR" + +# Template variables from Terraform +SYSTEM_PROMPT="${system_prompt}" +TASK_PROMPT="${task_prompt}" +FOLDER="${folder}" +USE_AIDER="${use_aider}" +REPORT_TASKS="${report_tasks}" + +# Set AWS environment variables +export AWS_ACCESS_KEY_ID="${aws_access_key_id}" +export AWS_SECRET_ACCESS_KEY="${aws_secret_access_key}" +export AWS_REGION="${aws_region}" +export AWS_PROFILE="${aws_profile}" + +# Handle system prompt +if [ ! -z "$SYSTEM_PROMPT" ]; then + log "INFO: Setting system prompt" + echo "$SYSTEM_PROMPT" > "$MODULE_DIR/system_prompt.txt" +fi + +# Handle task prompt +if [ ! -z "$TASK_PROMPT" ]; then + log "INFO: Starting with task prompt" + echo "$TASK_PROMPT" > "$MODULE_DIR/task_prompt.txt" + + # Create combined prompt + COMBINED_PROMPT="You are Amazon Q, an AI coding assistant. Follow these instructions:\n\n" + + if [ -f "$MODULE_DIR/system_prompt.txt" ]; then + COMBINED_PROMPT="$${COMBINED_PROMPT}$(cat $MODULE_DIR/system_prompt.txt)\n\n" + fi + + COMBINED_PROMPT="$${COMBINED_PROMPT}Current task: $(cat $MODULE_DIR/task_prompt.txt)" + + log "INFO: Using combined prompt for task execution" +else + log "INFO: Starting without specific task prompt" +fi + +# Signal handling for graceful shutdown +cleanup() { + log "INFO: Received shutdown signal, cleaning up..." + exit 0 +} +trap cleanup SIGTERM SIGINT + +# Change to the specified folder +cd "$FOLDER" + +# Check if we should use Aider or Amazon Q +if [ "$USE_AIDER" = "true" ]; then + log "INFO: Starting Aider with AgentAPI..." + + # Check if Aider is available + if ! command -v aider >/dev/null 2>&1; then + log "ERROR: Aider is not installed or not in PATH" + log "INFO: Please install Aider first: pip install aider-chat" + exit 1 + fi + + # Start Aider with the system prompt and task + if [ -n "$TASK_PROMPT" ]; then + FULL_PROMPT="SYSTEM PROMPT:\n$SYSTEM_PROMPT\n\nThis is your current task: $TASK_PROMPT" + echo -e "$FULL_PROMPT" | agentapi server --term-width 67 --term-height 1190 -- \ + aider --yes-always 2>&1 | tee -a "$HOME/.aider.log" + else + agentapi server --term-width 67 --term-height 1190 -- \ + aider 2>&1 | tee -a "$HOME/.aider.log" + fi +else + log "INFO: Starting Amazon Q with AgentAPI..." + + # Check if Amazon Q is available + if ! command -v q >/dev/null 2>&1; then + log "ERROR: Amazon Q is not installed or not in PATH" + log "INFO: Please run the installation script first" + exit 1 + fi + + # Start Amazon Q via AgentAPI + if [ "$REPORT_TASKS" = "true" ]; then + log "INFO: Starting with MCP task reporting support" + agentapi server --term-width 67 --term-height 1190 -- \ + bash -c "export PATH=\"$PATH:$HOME/q/bin\" && q chat --trust-all-tools" + else + log "INFO: Starting without MCP task reporting" + agentapi server --term-width 67 --term-height 1190 -- \ + bash -c "export PATH=\"$PATH:$HOME/q/bin\" && q chat" + fi +fi \ No newline at end of file From 82ef94eba75f936e7470f18d4066fbead14426dc Mon Sep 17 00:00:00 2001 From: Sahelisaha04 Date: Fri, 18 Jul 2025 15:07:26 +0530 Subject: [PATCH 2/6] docs(saheli): add example usage for Amazon Q module - Add example.tf showing how to use the module - Include AWS credentials configuration - Show task reporting and prompt configuration - Include Docker container example --- registry/saheli/modules/amazon-q/example.tf | 104 ++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 registry/saheli/modules/amazon-q/example.tf diff --git a/registry/saheli/modules/amazon-q/example.tf b/registry/saheli/modules/amazon-q/example.tf new file mode 100644 index 00000000..c9c3c89e --- /dev/null +++ b/registry/saheli/modules/amazon-q/example.tf @@ -0,0 +1,104 @@ +# Example usage of the Amazon Q module with AgentAPI integration +# This shows how to use the saheli/amazon-q module in your Coder template + +terraform { + required_providers { + coder = { + source = "coder/coder" + } + docker = { + source = "kreuzwerker/docker" + } + } +} + +# Required variables for AWS authentication +variable "aws_access_key_id" { + type = string + description = "AWS Access Key ID" + sensitive = true +} + +variable "aws_secret_access_key" { + type = string + description = "AWS Secret Access Key" + sensitive = true +} + +# Template parameters +data "coder_parameter" "ai_prompt" { + name = "AI Prompt" + type = "string" + description = "Task for the AI agent to complete" + default = "" + mutable = true +} + +# Workspace and owner data +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +# Amazon Q module with AgentAPI integration +module "amazon-q" { + source = "registry.coder.com/saheli/amazon-q/coder" + # version = "1.0.0" # Use when published to registry + + agent_id = coder_agent.main.id + folder = "/home/coder/project" + aws_access_key_id = var.aws_access_key_id + aws_secret_access_key = var.aws_secret_access_key + aws_region = "us-east-1" + aws_profile = "default" + + # Task reporting and prompt configuration + system_prompt = <<-EOT + You are Amazon Q, an AI coding assistant integrated with Coder Tasks. + + YOU MUST REPORT ALL TASKS TO CODER. + When reporting tasks, follow these instructions: + - Report status immediately after receiving any user message + - Be granular - report each step of multi-step tasks + - Use "working" for active processing, "complete" for finished tasks + - Keep task summaries under 160 characters + + Focus on writing clean, maintainable code and following best practices. + EOT + + task_prompt = data.coder_parameter.ai_prompt.value + + # Optional: Use Aider instead of Amazon Q + # use_aider = true + + # Optional: Enable task reporting (default: true) + # experiment_report_tasks = true +} + +# Coder agent +resource "coder_agent" "main" { + arch = "amd64" + os = "linux" + + startup_script = <<-EOT + set -e + + # Create project directory + mkdir -p /home/coder/project + + # Show welcome message + echo "Amazon Q + AgentAPI workspace is ready!" + echo "- Click 'Amazon Q' for web interface" + echo "- Click 'Amazon Q CLI' for command line access" + EOT +} + +# Docker container (example infrastructure) +resource "docker_container" "workspace" { + count = data.coder_workspace.me.start_count + image = "codercom/code-server:latest" + name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" + + hostname = data.coder_workspace.me.name + + entrypoint = ["sh", "-c", coder_agent.main.init_script] + env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"] +} \ No newline at end of file From cd82233242fee8a98e544c9e5beb680f8948a938 Mon Sep 17 00:00:00 2001 From: Sahelisaha04 Date: Fri, 18 Jul 2025 15:07:56 +0530 Subject: [PATCH 3/6] chore: remove example usage file for Amazon Q module --- registry/saheli/modules/amazon-q/example.tf | 104 -------------------- 1 file changed, 104 deletions(-) delete mode 100644 registry/saheli/modules/amazon-q/example.tf diff --git a/registry/saheli/modules/amazon-q/example.tf b/registry/saheli/modules/amazon-q/example.tf deleted file mode 100644 index c9c3c89e..00000000 --- a/registry/saheli/modules/amazon-q/example.tf +++ /dev/null @@ -1,104 +0,0 @@ -# Example usage of the Amazon Q module with AgentAPI integration -# This shows how to use the saheli/amazon-q module in your Coder template - -terraform { - required_providers { - coder = { - source = "coder/coder" - } - docker = { - source = "kreuzwerker/docker" - } - } -} - -# Required variables for AWS authentication -variable "aws_access_key_id" { - type = string - description = "AWS Access Key ID" - sensitive = true -} - -variable "aws_secret_access_key" { - type = string - description = "AWS Secret Access Key" - sensitive = true -} - -# Template parameters -data "coder_parameter" "ai_prompt" { - name = "AI Prompt" - type = "string" - description = "Task for the AI agent to complete" - default = "" - mutable = true -} - -# Workspace and owner data -data "coder_workspace" "me" {} -data "coder_workspace_owner" "me" {} - -# Amazon Q module with AgentAPI integration -module "amazon-q" { - source = "registry.coder.com/saheli/amazon-q/coder" - # version = "1.0.0" # Use when published to registry - - agent_id = coder_agent.main.id - folder = "/home/coder/project" - aws_access_key_id = var.aws_access_key_id - aws_secret_access_key = var.aws_secret_access_key - aws_region = "us-east-1" - aws_profile = "default" - - # Task reporting and prompt configuration - system_prompt = <<-EOT - You are Amazon Q, an AI coding assistant integrated with Coder Tasks. - - YOU MUST REPORT ALL TASKS TO CODER. - When reporting tasks, follow these instructions: - - Report status immediately after receiving any user message - - Be granular - report each step of multi-step tasks - - Use "working" for active processing, "complete" for finished tasks - - Keep task summaries under 160 characters - - Focus on writing clean, maintainable code and following best practices. - EOT - - task_prompt = data.coder_parameter.ai_prompt.value - - # Optional: Use Aider instead of Amazon Q - # use_aider = true - - # Optional: Enable task reporting (default: true) - # experiment_report_tasks = true -} - -# Coder agent -resource "coder_agent" "main" { - arch = "amd64" - os = "linux" - - startup_script = <<-EOT - set -e - - # Create project directory - mkdir -p /home/coder/project - - # Show welcome message - echo "Amazon Q + AgentAPI workspace is ready!" - echo "- Click 'Amazon Q' for web interface" - echo "- Click 'Amazon Q CLI' for command line access" - EOT -} - -# Docker container (example infrastructure) -resource "docker_container" "workspace" { - count = data.coder_workspace.me.start_count - image = "codercom/code-server:latest" - name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" - - hostname = data.coder_workspace.me.name - - entrypoint = ["sh", "-c", coder_agent.main.init_script] - env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"] -} \ No newline at end of file From fb58b9e8520275cbe3d39beac111f9a3eb3d2be4 Mon Sep 17 00:00:00 2001 From: Sahelisaha04 Date: Fri, 18 Jul 2025 15:39:45 +0530 Subject: [PATCH 4/6] test: enhance tests for coder_script and coder_app resources in amazon-q module --- registry/saheli/modules/amazon-q/main.test.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/registry/saheli/modules/amazon-q/main.test.ts b/registry/saheli/modules/amazon-q/main.test.ts index 54553da8..c6de3a18 100644 --- a/registry/saheli/modules/amazon-q/main.test.ts +++ b/registry/saheli/modules/amazon-q/main.test.ts @@ -25,16 +25,21 @@ describe("amazon-q module", async () => { const scriptResource = findResourceInstance(state, "coder_script"); expect(scriptResource).toBeDefined(); expect(scriptResource.agent_id).toBe(requiredVars.agent_id); - // Optionally, check that the script contains expected lines - expect(scriptResource.script).toContain("Installing Amazon Q"); + // The script is base64 encoded, so let's check for the module + expect(scriptResource.script).toContain("ARG_INSTALL_SCRIPT"); }); - // 3. coder_app resource is created + // 3. coder_app resource is created (from AgentAPI module) it("creates coder_app resource", async () => { const state = await runTerraformApply(moduleDir, requiredVars); - const appResource = findResourceInstance(state, "coder_app", "amazon_q"); - expect(appResource).toBeDefined(); - expect(appResource.agent_id).toBe(requiredVars.agent_id); + // The AgentAPI module creates apps with names "agentapi_web" and "agentapi_cli" + const webAppResource = findResourceInstance(state, "coder_app", "agentapi_web"); + expect(webAppResource).toBeDefined(); + expect(webAppResource.agent_id).toBe(requiredVars.agent_id); + + const cliAppResource = findResourceInstance(state, "coder_app", "agentapi_cli"); + expect(cliAppResource).toBeDefined(); + expect(cliAppResource.agent_id).toBe(requiredVars.agent_id); }); // Add more state-based tests as needed From e77d0e3d2c882384f7be5fcc7c2f6e1470e3daee Mon Sep 17 00:00:00 2001 From: Sahelisaha04 Date: Fri, 18 Jul 2025 15:44:39 +0530 Subject: [PATCH 5/6] feat: add Amazon Q module with comprehensive README and test cases --- registry/coder/modules/amazon-q/README.md | 121 +++++++ registry/coder/modules/amazon-q/main.test.ts | 41 +++ registry/coder/modules/amazon-q/main.tf | 337 +++++++++++++++++++ 3 files changed, 499 insertions(+) create mode 100644 registry/coder/modules/amazon-q/README.md create mode 100644 registry/coder/modules/amazon-q/main.test.ts create mode 100644 registry/coder/modules/amazon-q/main.tf diff --git a/registry/coder/modules/amazon-q/README.md b/registry/coder/modules/amazon-q/README.md new file mode 100644 index 00000000..e4fe0837 --- /dev/null +++ b/registry/coder/modules/amazon-q/README.md @@ -0,0 +1,121 @@ +--- +display_name: Amazon Q +description: Run Amazon Q in your workspace to access Amazon's AI coding assistant. +icon: ../../../../.icons/amazon-q.svg +maintainer_github: coder +verified: true +tags: [agent, ai, aws, amazon-q] +--- + +# Amazon Q + +Run [Amazon Q](https://aws.amazon.com/q/) in your workspace to access Amazon's AI coding assistant. This module installs and launches Amazon Q, with support for background operation, task reporting, and custom pre/post install scripts. + +```tf +module "amazon-q" { + source = "registry.coder.com/coder/amazon-q/coder" + version = "1.1.0" + agent_id = coder_agent.example.id + # Required: see below for how to generate + experiment_auth_tarball = var.amazon_q_auth_tarball +} +``` + +![Amazon-Q in action](../../.images/amazon-q.png) + +## Prerequisites + +- You must generate an authenticated Amazon Q tarball on another machine: + ```sh + cd ~/.local/share/amazon-q && tar -c . | zstd | base64 -w 0 + ``` + Paste the result into the `experiment_auth_tarball` variable. +- To run in the background, your workspace must have `screen` or `tmux` installed. + +
+How to generate the Amazon Q auth tarball (step-by-step) + +**1. Install and authenticate Amazon Q on your local machine:** + +- Download and install Amazon Q from the [official site](https://aws.amazon.com/q/developer/). +- Run `q login` and complete the authentication process in your terminal. + +**2. Locate your Amazon Q config directory:** + +- The config is typically stored at `~/.local/share/amazon-q`. + +**3. Generate the tarball:** + +- Run the following command in your terminal: + ```sh + cd ~/.local/share/amazon-q + tar -c . | zstd | base64 -w 0 + ``` + +**4. Copy the output:** + +- The command will output a long string. Copy this entire string. + +**5. Paste into your Terraform variable:** + +- Assign the string to the `experiment_auth_tarball` variable in your Terraform configuration, for example: + ```tf + variable "amazon_q_auth_tarball" { + type = string + default = "PASTE_LONG_STRING_HERE" + } + ``` + +**Note:** + +- You must re-generate the tarball if you log out or re-authenticate Amazon Q on your local machine. +- This process is required for each user who wants to use Amazon Q in their workspace. + +[Reference: Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/generate-docs.html) + +
+ +## Examples + +### Run Amazon Q in the background with tmux + +```tf +module "amazon-q" { + source = "registry.coder.com/coder/amazon-q/coder" + version = "1.1.0" + agent_id = coder_agent.example.id + experiment_auth_tarball = var.amazon_q_auth_tarball + experiment_use_tmux = true +} +``` + +### Enable task reporting (experimental) + +```tf +module "amazon-q" { + source = "registry.coder.com/coder/amazon-q/coder" + version = "1.1.0" + agent_id = coder_agent.example.id + experiment_auth_tarball = var.amazon_q_auth_tarball + experiment_report_tasks = true +} +``` + +### Run custom scripts before/after install + +```tf +module "amazon-q" { + source = "registry.coder.com/coder/amazon-q/coder" + version = "1.1.0" + agent_id = coder_agent.example.id + experiment_auth_tarball = var.amazon_q_auth_tarball + experiment_pre_install_script = "echo Pre-install!" + experiment_post_install_script = "echo Post-install!" +} +``` + +## Notes + +- Only one of `experiment_use_screen` or `experiment_use_tmux` can be true at a time. +- If neither is set, Amazon Q runs in the foreground. +- For more details, see the [main.tf](./main.tf) source. diff --git a/registry/coder/modules/amazon-q/main.test.ts b/registry/coder/modules/amazon-q/main.test.ts new file mode 100644 index 00000000..54553da8 --- /dev/null +++ b/registry/coder/modules/amazon-q/main.test.ts @@ -0,0 +1,41 @@ +import { describe, it, expect } from "bun:test"; +import { + runTerraformApply, + runTerraformInit, + testRequiredVariables, + findResourceInstance, +} from "~test"; +import path from "path"; + +const moduleDir = path.resolve(__dirname); + +const requiredVars = { + agent_id: "dummy-agent-id", +}; + +describe("amazon-q module", async () => { + await runTerraformInit(moduleDir); + + // 1. Required variables + testRequiredVariables(moduleDir, requiredVars); + + // 2. coder_script resource is created + it("creates coder_script resource", async () => { + const state = await runTerraformApply(moduleDir, requiredVars); + const scriptResource = findResourceInstance(state, "coder_script"); + expect(scriptResource).toBeDefined(); + expect(scriptResource.agent_id).toBe(requiredVars.agent_id); + // Optionally, check that the script contains expected lines + expect(scriptResource.script).toContain("Installing Amazon Q"); + }); + + // 3. coder_app resource is created + it("creates coder_app resource", async () => { + const state = await runTerraformApply(moduleDir, requiredVars); + const appResource = findResourceInstance(state, "coder_app", "amazon_q"); + expect(appResource).toBeDefined(); + expect(appResource.agent_id).toBe(requiredVars.agent_id); + }); + + // Add more state-based tests as needed +}); diff --git a/registry/coder/modules/amazon-q/main.tf b/registry/coder/modules/amazon-q/main.tf new file mode 100644 index 00000000..851aa062 --- /dev/null +++ b/registry/coder/modules/amazon-q/main.tf @@ -0,0 +1,337 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.5" + } + } +} + +variable "agent_id" { + type = string + description = "The ID of a Coder agent." +} + +data "coder_workspace" "me" {} + +data "coder_workspace_owner" "me" {} + +variable "order" { + type = number + description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)." + default = null +} + +variable "group" { + type = string + description = "The name of a group that this app belongs to." + default = null +} + +variable "icon" { + type = string + description = "The icon to use for the app." + default = "/icon/amazon-q.svg" +} + +variable "folder" { + type = string + description = "The folder to run Amazon Q in." + default = "/home/coder" +} + +variable "install_amazon_q" { + type = bool + description = "Whether to install Amazon Q." + default = true +} + +variable "amazon_q_version" { + type = string + description = "The version of Amazon Q to install." + default = "latest" +} + +variable "experiment_use_screen" { + type = bool + description = "Whether to use screen for running Amazon Q in the background." + default = false +} + +variable "experiment_use_tmux" { + type = bool + description = "Whether to use tmux instead of screen for running Amazon Q in the background." + default = false +} + +variable "experiment_report_tasks" { + type = bool + description = "Whether to enable task reporting." + default = false +} + +variable "experiment_pre_install_script" { + type = string + description = "Custom script to run before installing Amazon Q." + default = null +} + +variable "experiment_post_install_script" { + type = string + description = "Custom script to run after installing Amazon Q." + default = null +} + +variable "experiment_auth_tarball" { + type = string + description = "Base64 encoded, zstd compressed tarball of a pre-authenticated ~/.local/share/amazon-q directory. After running `q login` on another machine, you may generate it with: `cd ~/.local/share/amazon-q && tar -c . | zstd | base64 -w 0`" + default = "tarball" +} + +variable "system_prompt" { + type = string + description = "The system prompt to use for Amazon Q. This should instruct the agent how to do task reporting." + default = <<-EOT + You are a helpful Coding assistant. Aim to autonomously investigate + and solve issues the user gives you and test your work, whenever possible. + Avoid shortcuts like mocking tests. When you get stuck, you can ask the user + but opt for autonomy. + + YOU MUST REPORT ALL TASKS TO CODER. + When reporting tasks, you MUST follow these EXACT instructions: + - IMMEDIATELY report status after receiving ANY user message. + - Be granular. If you are investigating with multiple steps, report each step to coder. + + Task state MUST be one of the following: + - Use "state": "working" when actively processing WITHOUT needing additional user input. + - Use "state": "complete" only when finished with a task. + - Use "state": "failure" when you need ANY user input, lack sufficient details, or encounter blockers. + + Task summaries MUST: + - Include specifics about what you're doing. + - Include clear and actionable steps for the user. + - Be less than 160 characters in length. + EOT +} + +variable "ai_prompt" { + type = string + description = "The initial task prompt to send to Amazon Q." + default = "Please help me with my coding tasks. I'll provide specific instructions as needed." +} + +locals { + encoded_pre_install_script = var.experiment_pre_install_script != null ? base64encode(var.experiment_pre_install_script) : "" + encoded_post_install_script = var.experiment_post_install_script != null ? base64encode(var.experiment_post_install_script) : "" + # We need to use allowed tools to limit the context Amazon Q receives. + # Amazon Q can't handle big contexts, and the `create_template_version` tool + # has a description that's too long. + mcp_json = </dev/null 2>&1 + } + + if [ -n "${local.encoded_pre_install_script}" ]; then + echo "Running pre-install script..." + echo "${local.encoded_pre_install_script}" | base64 -d > /tmp/pre_install.sh + chmod +x /tmp/pre_install.sh + /tmp/pre_install.sh + fi + + if [ "${var.install_amazon_q}" = "true" ]; then + echo "Installing Amazon Q..." + PREV_DIR="$PWD" + TMP_DIR="$(mktemp -d)" + cd "$TMP_DIR" + + ARCH="$(uname -m)" + case "$ARCH" in + "x86_64") + Q_URL="https://desktop-release.q.us-east-1.amazonaws.com/${var.amazon_q_version}/q-x86_64-linux.zip" + ;; + "aarch64"|"arm64") + Q_URL="https://desktop-release.codewhisperer.us-east-1.amazonaws.com/${var.amazon_q_version}/q-aarch64-linux.zip" + ;; + *) + echo "Error: Unsupported architecture: $ARCH. Amazon Q only supports x86_64 and arm64." + exit 1 + ;; + esac + + echo "Downloading Amazon Q for $ARCH..." + curl --proto '=https' --tlsv1.2 -sSf "$Q_URL" -o "q.zip" + unzip q.zip + ./q/install.sh --no-confirm + cd "$PREV_DIR" + export PATH="$PATH:$HOME/.local/bin" + echo "Installed Amazon Q version: $(q --version)" + fi + + echo "Extracting auth tarball..." + PREV_DIR="$PWD" + echo "${var.experiment_auth_tarball}" | base64 -d > /tmp/auth.tar.zst + rm -rf ~/.local/share/amazon-q + mkdir -p ~/.local/share/amazon-q + cd ~/.local/share/amazon-q + tar -I zstd -xf /tmp/auth.tar.zst + rm /tmp/auth.tar.zst + cd "$PREV_DIR" + echo "Extracted auth tarball" + + if [ -n "${local.encoded_post_install_script}" ]; then + echo "Running post-install script..." + echo "${local.encoded_post_install_script}" | base64 -d > /tmp/post_install.sh + chmod +x /tmp/post_install.sh + /tmp/post_install.sh + fi + + if [ "${var.experiment_report_tasks}" = "true" ]; then + echo "Configuring Amazon Q to report tasks via Coder MCP..." + mkdir -p ~/.aws/amazonq + echo "${local.encoded_mcp_json}" | base64 -d > ~/.aws/amazonq/mcp.json + echo "Created the ~/.aws/amazonq/mcp.json configuration file" + fi + + if [ "${var.experiment_use_tmux}" = "true" ] && [ "${var.experiment_use_screen}" = "true" ]; then + echo "Error: Both experiment_use_tmux and experiment_use_screen cannot be true simultaneously." + echo "Please set only one of them to true." + exit 1 + fi + + if [ "${var.experiment_use_tmux}" = "true" ]; then + echo "Running Amazon Q in the background with tmux..." + + if ! command_exists tmux; then + echo "Error: tmux is not installed. Please install tmux manually." + exit 1 + fi + + touch "$HOME/.amazon-q.log" + + export LANG=en_US.UTF-8 + export LC_ALL=en_US.UTF-8 + + tmux new-session -d -s amazon-q -c "${var.folder}" "q chat --trust-all-tools | tee -a "$HOME/.amazon-q.log" && exec bash" + + tmux send-keys -t amazon-q "${local.full_prompt}" + sleep 5 + tmux send-keys -t amazon-q Enter + fi + + if [ "${var.experiment_use_screen}" = "true" ]; then + echo "Running Amazon Q in the background..." + + if ! command_exists screen; then + echo "Error: screen is not installed. Please install screen manually." + exit 1 + fi + + touch "$HOME/.amazon-q.log" + + if [ ! -f "$HOME/.screenrc" ]; then + echo "Creating ~/.screenrc and adding multiuser settings..." | tee -a "$HOME/.amazon-q.log" + echo -e "multiuser on\nacladd $(whoami)" > "$HOME/.screenrc" + fi + + if ! grep -q "^multiuser on$" "$HOME/.screenrc"; then + echo "Adding 'multiuser on' to ~/.screenrc..." | tee -a "$HOME/.amazon-q.log" + echo "multiuser on" >> "$HOME/.screenrc" + fi + + if ! grep -q "^acladd $(whoami)$" "$HOME/.screenrc"; then + echo "Adding 'acladd $(whoami)' to ~/.screenrc..." | tee -a "$HOME/.amazon-q.log" + echo "acladd $(whoami)" >> "$HOME/.screenrc" + fi + export LANG=en_US.UTF-8 + export LC_ALL=en_US.UTF-8 + + screen -U -dmS amazon-q bash -c ' + cd ${var.folder} + q chat --trust-all-tools | tee -a "$HOME/.amazon-q.log + exec bash + ' + # Extremely hacky way to send the prompt to the screen session + # This will be fixed in the future, but `amazon-q` was not sending MCP + # tasks when an initial prompt is provided. + screen -S amazon-q -X stuff "${local.full_prompt}" + sleep 5 + screen -S amazon-q -X stuff "^M" + else + if ! command_exists q; then + echo "Error: Amazon Q is not installed. Please enable install_amazon_q or install it manually." + exit 1 + fi + fi + EOT + run_on_start = true +} + +resource "coder_app" "amazon_q" { + slug = "amazon-q" + display_name = "Amazon Q" + agent_id = var.agent_id + command = <<-EOT + #!/bin/bash + set -e + + export LANG=en_US.UTF-8 + export LC_ALL=en_US.UTF-8 + + if [ "${var.experiment_use_tmux}" = "true" ]; then + if tmux has-session -t amazon-q 2>/dev/null; then + echo "Attaching to existing Amazon Q tmux session." | tee -a "$HOME/.amazon-q.log" + tmux attach-session -t amazon-q + else + echo "Starting a new Amazon Q tmux session." | tee -a "$HOME/.amazon-q.log" + tmux new-session -s amazon-q -c ${var.folder} "q chat --trust-all-tools | tee -a \"$HOME/.amazon-q.log\"; exec bash" + fi + elif [ "${var.experiment_use_screen}" = "true" ]; then + if screen -list | grep -q "amazon-q"; then + echo "Attaching to existing Amazon Q screen session." | tee -a "$HOME/.amazon-q.log" + screen -xRR amazon-q + else + echo "Starting a new Amazon Q screen session." | tee -a "$HOME/.amazon-q.log" + screen -S amazon-q bash -c 'q chat --trust-all-tools | tee -a "$HOME/.amazon-q.log"; exec bash' + fi + else + cd ${var.folder} + q chat --trust-all-tools + fi + EOT + icon = var.icon + order = var.order + group = var.group +} From 6e1736920114d243300e602c8af4bd61057ac4fc Mon Sep 17 00:00:00 2001 From: Sahelisaha04 Date: Tue, 22 Jul 2025 19:00:49 +0530 Subject: [PATCH 6/6] feat(amazon-q): integrate Coder Tasks and AgentAPI support --- registry/saheli/modules/amazon-q/README.md | 348 ++++++++++-------- registry/saheli/modules/amazon-q/main.tf | 97 ++++- .../modules/amazon-q/scripts/install.sh | 67 ++++ .../saheli/modules/amazon-q/scripts/start.sh | 78 ++-- 4 files changed, 382 insertions(+), 208 deletions(-) diff --git a/registry/saheli/modules/amazon-q/README.md b/registry/saheli/modules/amazon-q/README.md index f50ba4d0..c79f7f7a 100644 --- a/registry/saheli/modules/amazon-q/README.md +++ b/registry/saheli/modules/amazon-q/README.md @@ -1,205 +1,249 @@ --- display_name: Amazon Q -description: Run Amazon Q with AgentAPI as a web chat interface, with optional Aider integration and Coder Tasks support. +description: Run Amazon Q with AgentAPI as a web chat interface, with Coder Tasks integration for real-time AI task management. icon: ../../../../.icons/amazon-q.svg maintainer_github: coder verified: true -tags: [agent, ai, aws, amazon-q, agentapi, tasks, aider] +tags: [agent, ai, aws, amazon-q, agentapi, tasks, aider, mcp] --- -# Amazon Q +# Amazon Q with Coder Tasks Integration -Run [Amazon Q](https://aws.amazon.com/q/) with [AgentAPI](https://github.com/coder/agentapi) as a web chat interface, with optional [Aider](https://aider.chat) integration and full Coder Tasks support. This module provides a modern web interface for Amazon Q with automatic task reporting. +Run [Amazon Q](https://aws.amazon.com/q/) with [AgentAPI](https://github.com/coder/agentapi) and full [Coder Tasks](https://coder.com/docs/tasks) support. This module provides a modern web chat interface with real-time task reporting, making it easy to track AI progress through Coder's task sidebar. ```tf module "amazon-q" { - source = "registry.coder.com/coder/amazon-q/coder" - version = "2.0.0" - agent_id = coder_agent.example.id - auth_tarball = var.amazon_q_auth_tarball + source = "registry.coder.com/saheli/amazon-q/coder" + version = "2.0.0" + agent_id = coder_agent.example.id + experiment_report_tasks = true # Enable Coder Tasks integration + + # AWS Authentication + aws_access_key_id = var.aws_access_key_id + aws_secret_access_key = var.aws_secret_access_key } ``` -![Amazon-Q with AgentAPI](../../.images/amazon-q-agentapi.png) +![Amazon-Q with AgentAPI and Tasks](../../.images/amazon-q-agentapi-tasks.png) -## Prerequisites +## Features -- You must add the [Coder Login](https://registry.coder.com/modules/coder-login) module to your template -- You must generate an authenticated Amazon Q tarball on another machine: - ```sh - cd ~/.local/share/amazon-q && tar -c . | zstd | base64 -w 0 - ``` - Paste the result into the `auth_tarball` variable. -- For Aider mode: Python 3 and pip3 must be installed in your workspace +- 🤖 **Amazon Q Integration**: Full Amazon Q Developer capabilities +- 📊 **Coder Tasks**: Real-time task reporting in the Coder sidebar +- 🌐 **Web Chat Interface**: Modern web UI powered by AgentAPI +- 🎯 **Aider Support**: Optional Aider integration for enhanced coding +- 🔌 **MCP Protocol**: Model Context Protocol for advanced integrations +- 🔐 **Flexible Auth**: Supports AWS credentials, IAM roles, and SSO -
-How to generate the Amazon Q auth tarball (step-by-step) +## Prerequisites -**1. Install and authenticate Amazon Q on your local machine:** +- Coder v2.7.0 or later +- AWS account with Amazon Q Developer access +- Linux workspace (x86_64 or arm64) -- Download and install Amazon Q from the [official site](https://aws.amazon.com/q/developer/). -- Run `q login` and complete the authentication process in your terminal. +## Quick Start -**2. Locate your Amazon Q config directory:** +### Basic Usage with Tasks -- The config is typically stored at `~/.local/share/amazon-q`. +```hcl +module "amazon-q" { + source = "registry.coder.com/saheli/amazon-q/coder" + version = "2.0.0" -**3. Generate the tarball:** + agent_id = coder_agent.main.id -- Run the following command in your terminal: - ```sh - cd ~/.local/share/amazon-q - tar -c . | zstd | base64 -w 0 - ``` + # Enable Coder Tasks + experiment_report_tasks = true + + # AWS credentials + aws_access_key_id = var.aws_access_key_id + aws_secret_access_key = var.aws_secret_access_key + aws_region = "us-east-1" +} +``` -**4. Copy the output:** +### With Custom Task Reporting -- The command will output a long string. Copy this entire string. +```hcl +module "amazon-q" { + source = "registry.coder.com/saheli/amazon-q/coder" + version = "2.0.0" -**5. Paste into your Terraform variable:** + agent_id = coder_agent.main.id + experiment_report_tasks = true -- Assign the string to the `experiment_auth_tarball` variable in your Terraform configuration, for example: - ```tf - variable "amazon_q_auth_tarball" { - type = string - default = "PASTE_LONG_STRING_HERE" - } - ``` + # Optimized system prompt for task reporting + system_prompt = <<-EOT + You are Amazon Q integrated with Coder Tasks. -**Note:** + YOU MUST REPORT ALL TASKS TO CODER: + - Report status IMMEDIATELY after any user message + - Break work into granular, trackable tasks + - Use "working" when actively processing + - Use "complete" when finished + - Use "failure" when blocked -- You must re-generate the tarball if you log out or re-authenticate Amazon Q on your local machine. -- This process is required for each user who wants to use Amazon Q in their workspace. + Keep summaries under 160 characters. + EOT -[Reference: Amazon Q documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/generate-docs.html) + # Start with a specific task + task_prompt = "Create a Python REST API with FastAPI" +} +``` -
+### Using Aider Mode -## Examples +```hcl +module "amazon-q" { + source = "registry.coder.com/saheli/amazon-q/coder" + version = "2.0.0" -### Basic Amazon Q with AgentAPI + agent_id = coder_agent.main.id -```tf -module "coder-login" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/coder-login/coder" - version = "1.0.15" - agent_id = coder_agent.example.id -} + # Use Aider instead of Amazon Q CLI + use_aider = true + aider_version = "latest" -module "amazon-q" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/amazon-q/coder" - version = "2.0.0" - agent_id = coder_agent.example.id - auth_tarball = var.amazon_q_auth_tarball + # Enable all features + experiment_report_tasks = true + install_agentapi = true } ``` -### Using Aider instead of Amazon Q +## How Coder Tasks Integration Works -```tf -variable "anthropic_api_key" { - type = string - description = "Anthropic API key for Aider" - sensitive = true -} +When `experiment_report_tasks = true`: -resource "coder_agent" "main" { - env = { - ANTHROPIC_API_KEY = var.anthropic_api_key - } -} +1. **Web Interface**: Access Amazon Q through the "Amazon Q Web" app in Coder +2. **Task Sidebar**: Tasks appear in real-time in the Coder sidebar +3. **Status Updates**: See live progress as the AI works on your requests +4. **MCP Protocol**: Uses Model Context Protocol for reliable task reporting -module "amazon-q" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/amazon-q/coder" - version = "2.0.0" - agent_id = coder_agent.main.id - use_aider = true - auth_tarball = "dummy" # Not needed for Aider mode -} +The integration provides: + +- Real-time task status (working, complete, failure) +- Granular progress tracking +- Interactive chat interface +- Full task history + +## Configuration Variables + +| Variable | Type | Description | Default | +| ------------------------- | ------ | --------------------------------- | ---------------------- | +| `agent_id` | string | **Required** - The Coder agent ID | - | +| `experiment_report_tasks` | bool | Enable Coder Tasks integration | `true` | +| `install_amazon_q` | bool | Install Amazon Q CLI | `true` | +| `install_agentapi` | bool | Install AgentAPI | `true` | +| `use_aider` | bool | Use Aider instead of Amazon Q | `false` | +| `system_prompt` | string | System instructions for the AI | (task-optimized) | +| `task_prompt` | string | Initial task to start with | `""` | +| `aws_access_key_id` | string | AWS Access Key ID | `""` | +| `aws_secret_access_key` | string | AWS Secret Access Key | `""` | +| `aws_region` | string | AWS Region | `"us-east-1"` | +| `order` | number | App display order | `null` | +| `group` | string | App group name | `null` | +| `icon` | string | App icon path | `"/icon/amazon-q.svg"` | + +## AWS Authentication + +The module supports multiple authentication methods: + +### 1. Environment Variables + +```hcl +aws_access_key_id = var.aws_access_key_id +aws_secret_access_key = var.aws_secret_access_key ``` -### With Task Automation +### 2. IAM Instance Role -```tf -data "coder_parameter" "ai_prompt" { - type = "string" - name = "AI Task" - default = "" - description = "Task for the AI agent to complete" - mutable = true -} +Leave credentials empty to use the workspace's IAM role. -module "amazon-q" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/amazon-q/coder" - version = "2.0.0" - agent_id = coder_agent.example.id - auth_tarball = var.amazon_q_auth_tarball - task_prompt = data.coder_parameter.ai_prompt.value -} +### 3. AWS Profile + +```hcl +aws_profile = "my-profile" ``` -### With Custom Extensions +## Advanced Configuration -```tf -module "amazon-q" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/amazon-q/coder" - version = "2.0.0" - agent_id = coder_agent.example.id - auth_tarball = var.amazon_q_auth_tarball - - additional_extensions = <<-EOT -custom-tool: - args: [] - cmd: custom-tool-command - description: A custom tool for the AI agent +### Custom MCP Extensions + +Add additional MCP servers for enhanced functionality: + +```hcl +additional_extensions = <<-YAML +desktop-commander: + cmd: desktop-commander-server + args: ["--server"] + description: Long-running processes enabled: true - envs: {} - name: custom-tool - timeout: 300 type: stdio -EOT -} +playwright: + cmd: npx + args: ["--yes", "@mcp-get/playwright", "server"] + description: Web testing + enabled: true + type: stdio +YAML ``` -## Features +### Custom Scripts + +Run scripts before/after installation: + +```hcl +experiment_pre_install_script = <<-BASH + echo "Preparing environment..." + pip install -U pip +BASH + +experiment_post_install_script = <<-BASH + echo "Setup complete!" +BASH +``` + +## Troubleshooting + +### Task Reporting Issues + +- Ensure `experiment_report_tasks = true` +- Check AgentAPI status: `curl http://localhost:3284/status` +- Verify MCP config: `cat ~/.config/coder/mcp/amazon-q.yaml` +- Check logs: `tail -f ~/.amazon-q-module/logs/*.log` + +### Amazon Q Not Starting + +- Verify installation: `q --version` +- Check AWS credentials: `aws sts get-caller-identity` +- Review logs in `~/.amazon-q-module/logs/` + +### Web Interface Not Loading + +- Ensure AgentAPI is running on port 3284 +- Check the "Amazon Q Web" app in Coder UI +- Verify health check passes + +## Architecture + +```mermaid +graph LR + A[User] --> B[Coder Web UI] + B --> C[Amazon Q Web App] + C --> D[AgentAPI :3284] + D --> E[Amazon Q CLI] + E --> F[AWS Services] + D --> G[Coder Tasks API] + G --> H[Task Sidebar] +``` + +## Support + +- [Amazon Q Documentation](https://docs.aws.amazon.com/amazonq/) +- [Coder Tasks Guide](https://coder.com/docs/tasks) +- [AgentAPI Repository](https://github.com/coder/agentapi) +- [Module Issues](https://github.com/coder/registry/issues) + +## License -- **Web Chat Interface**: Modern web interface powered by AgentAPI -- **Coder Tasks Integration**: Full integration with Coder's Tasks system -- **Dual AI Support**: Choose between Amazon Q or Aider -- **Task Reporting**: Automatic status reporting to Coder dashboard -- **Persistent Sessions**: Sessions persist across browser refreshes -- **Custom Extensions**: Support for additional MCP extensions - -## Module Parameters - -| Parameter | Description | Type | Default | -|-----------|-------------|------|---------| -| `agent_id` | The ID of a Coder agent (required) | `string` | - | -| `auth_tarball` | Base64 encoded Amazon Q auth tarball | `string` | - | -| `use_aider` | Whether to use Aider instead of Amazon Q | `bool` | `false` | -| `task_prompt` | Initial task prompt | `string` | `""` | -| `additional_extensions` | Additional extensions in YAML format | `string` | `null` | -| `install_agentapi` | Whether to install AgentAPI | `bool` | `true` | -| `agentapi_version` | Version of AgentAPI to install | `string` | `"latest"` | - -## Migration from v1.x - -The v2.0 release introduces AgentAPI integration and breaking changes: - -- `experiment_auth_tarball` → `auth_tarball` -- `experiment_report_tasks` → Always enabled -- `experiment_use_screen/tmux` → Replaced by AgentAPI -- New web interface replaces terminal-only access -- Full Coder Tasks integration - -## Notes - -- This module now uses AgentAPI for web interface and task reporting -- Task reporting is always enabled in v2.0 -- For legacy behavior, use v1.x of this module -- For more details, see the [main.tf](./main.tf) source. +This module is licensed under the MIT License. Amazon Q is subject to AWS service terms. diff --git a/registry/saheli/modules/amazon-q/main.tf b/registry/saheli/modules/amazon-q/main.tf index fe7d9925..74b38c8e 100644 --- a/registry/saheli/modules/amazon-q/main.tf +++ b/registry/saheli/modules/amazon-q/main.tf @@ -173,23 +173,45 @@ variable "additional_extensions" { } locals { - app_slug = "amazon-q" + app_slug = "amazon-q" module_dir_name = ".amazon-q-module" - + + # MCP extensions configuration following Goose pattern + base_extensions = <<-EOT +coder: + args: + - exp + - mcp + - server + cmd: coder + description: Report ALL tasks and statuses (in progress, done, failed) you are working on. + enabled: true + envs: + CODER_MCP_APP_STATUS_SLUG: ${local.app_slug} + CODER_MCP_AI_AGENTAPI_URL: http://localhost:3284 + name: Coder + timeout: 3000 + type: stdio +developer: + display_name: Developer + enabled: true + name: developer + timeout: 300 + type: builtin +EOT + + # Format extensions to match YAML structure + formatted_base = " ${replace(trimspace(local.base_extensions), "\n", "\n ")}" + additional_extensions = var.additional_extensions != null ? "\n ${replace(trimspace(var.additional_extensions), "\n", "\n ")}" : "" + combined_extensions = <<-EOT +extensions: +${local.formatted_base}${local.additional_extensions} +EOT + # Load scripts from files like Goose module install_script_content = file("${path.module}/scripts/install.sh") - start_script_content = templatefile("${path.module}/scripts/start.sh", { - system_prompt = var.system_prompt - task_prompt = var.task_prompt - folder = var.folder - use_aider = var.use_aider - report_tasks = var.experiment_report_tasks - aws_access_key_id = var.aws_access_key_id - aws_secret_access_key = var.aws_secret_access_key - aws_region = var.aws_region - aws_profile = var.aws_profile - }) - + start_script_content = file("${path.module}/scripts/start.sh") + } module "agentapi" { @@ -211,6 +233,49 @@ module "agentapi" { pre_install_script = var.experiment_pre_install_script post_install_script = var.experiment_post_install_script start_script = local.start_script_content - install_script = local.install_script_content - + install_script = <<-EOT + #!/bin/bash + set -o errexit + set -o pipefail + + echo -n '${base64encode(local.install_script_content)}' | base64 -d > /tmp/install.sh + chmod +x /tmp/install.sh + + ARG_AMAZON_Q_CONFIG="$(echo -n '${base64encode(local.combined_extensions)}' | base64 -d)" \ + ARG_INSTALL='${var.install_amazon_q}' \ + ARG_AMAZON_Q_VERSION='${var.amazon_q_version}' \ + ARG_USE_AIDER='${var.use_aider}' \ + ARG_AIDER_VERSION='${var.aider_version}' \ + ARG_AWS_ACCESS_KEY_ID='${var.aws_access_key_id}' \ + ARG_AWS_SECRET_ACCESS_KEY='${var.aws_secret_access_key}' \ + ARG_AWS_REGION='${var.aws_region}' \ + ARG_AWS_PROFILE='${var.aws_profile}' \ + /tmp/install.sh + EOT + +} + +# Create web app for Amazon Q chat interface +resource "coder_app" "amazon_q_web" { + count = var.experiment_report_tasks ? 1 : 0 + + slug = "aqw" # Short slug to avoid URL length issues + display_name = var.use_aider ? "Amazon Q + Aider Web" : "Amazon Q Web" + agent_id = var.agent_id + url = "http://localhost:3284/" + subdomain = true + healthcheck { + url = "http://localhost:3284/status" + interval = 3 + threshold = 20 + } +} + +# Create AI task resource for sidebar integration +resource "coder_ai_task" "amazon_q" { + count = var.experiment_report_tasks ? 1 : 0 + + sidebar_app { + id = coder_app.amazon_q_web[0].id + } } diff --git a/registry/saheli/modules/amazon-q/scripts/install.sh b/registry/saheli/modules/amazon-q/scripts/install.sh index 266366fa..abffbca6 100644 --- a/registry/saheli/modules/amazon-q/scripts/install.sh +++ b/registry/saheli/modules/amazon-q/scripts/install.sh @@ -14,6 +14,17 @@ mkdir -p "$HOME/.amazon-q-module/logs" log "INFO: Starting Amazon Q installation..." +# Get environment variables from Terraform +INSTALL_AMAZON_Q="${ARG_INSTALL:-true}" +AMAZON_Q_VERSION="${ARG_AMAZON_Q_VERSION:-latest}" +USE_AIDER="${ARG_USE_AIDER:-false}" +AIDER_VERSION="${ARG_AIDER_VERSION:-latest}" +AMAZON_Q_CONFIG="${ARG_AMAZON_Q_CONFIG:-}" +AWS_ACCESS_KEY_ID="${ARG_AWS_ACCESS_KEY_ID:-}" +AWS_SECRET_ACCESS_KEY="${ARG_AWS_SECRET_ACCESS_KEY:-}" +AWS_REGION="${ARG_AWS_REGION:-us-east-1}" +AWS_PROFILE="${ARG_AWS_PROFILE:-default}" + # Check if Amazon Q is already installed if command -v q >/dev/null 2>&1; then log "INFO: Amazon Q is already installed" @@ -117,4 +128,60 @@ region: ${AWS_REGION:-us-east-1} profile: ${AWS_PROFILE:-default} EOF +# Install Aider if requested +if [ "$USE_AIDER" = "true" ]; then + log "INFO: Installing Aider..." + if ! command -v pip3 >/dev/null 2>&1; then + log "INFO: Installing Python 3 and pip..." + if command -v apt-get >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y python3 python3-pip + elif command -v yum >/dev/null 2>&1; then + sudo yum install -y python3 python3-pip + fi + fi + + # Install Aider + if [ "$AIDER_VERSION" = "latest" ]; then + pip3 install --user aider-chat + else + pip3 install --user "aider-chat==$AIDER_VERSION" + fi + + # Add to PATH + if ! grep -q ".local/bin" "$HOME/.bashrc"; then + echo 'export PATH="$PATH:$HOME/.local/bin"' >> "$HOME/.bashrc" + fi + export PATH="$PATH:$HOME/.local/bin" + + # Verify Aider installation + if command -v aider >/dev/null 2>&1; then + log "SUCCESS: Aider installed successfully" + aider --version | tee -a "$HOME/.amazon-q-module/logs/install.log" + else + log "ERROR: Aider installation failed" + exit 1 + fi +fi + +# Create MCP configuration directory +log "INFO: Creating MCP configuration..." +mkdir -p "$HOME/.amazon-q-module/mcp" +mkdir -p "$HOME/.config/coder/mcp" + +# Write MCP configuration if provided +if [ ! -z "$AMAZON_Q_CONFIG" ]; then + echo "$AMAZON_Q_CONFIG" > "$HOME/.amazon-q-module/mcp/config.yaml" + log "INFO: MCP configuration written to $HOME/.amazon-q-module/mcp/config.yaml" + + # Also write to Coder MCP config location for Amazon Q + if [ "$USE_AIDER" = "true" ]; then + echo "$AMAZON_Q_CONFIG" > "$HOME/.config/coder/mcp/aider.yaml" + log "INFO: MCP configuration written for Aider" + else + echo "$AMAZON_Q_CONFIG" > "$HOME/.config/coder/mcp/amazon-q.yaml" + log "INFO: MCP configuration written for Amazon Q" + fi +fi + log "INFO: Installation completed successfully" \ No newline at end of file diff --git a/registry/saheli/modules/amazon-q/scripts/start.sh b/registry/saheli/modules/amazon-q/scripts/start.sh index 6a6bdfda..f5df6a5f 100644 --- a/registry/saheli/modules/amazon-q/scripts/start.sh +++ b/registry/saheli/modules/amazon-q/scripts/start.sh @@ -10,7 +10,11 @@ log() { # Create log directory mkdir -p "$HOME/.amazon-q-module/logs" -log "INFO: Starting Amazon Q..." +log "INFO: Starting Amazon Q module..." + +# Module directory matching main.tf +MODULE_DIR="$HOME/.amazon-q-module" +mkdir -p "$MODULE_DIR" # Add Amazon Q to PATH export PATH="$PATH:$HOME/q/bin" @@ -19,11 +23,7 @@ export PATH="$PATH:$HOME/q/bin" export CODER_MCP_APP_STATUS_SLUG="amazon-q" export CODER_MCP_AI_AGENTAPI_URL="http://localhost:3284" -# Create module directory -MODULE_DIR="$HOME/.amazon-q-module" -mkdir -p "$MODULE_DIR" - -# Template variables from Terraform +# Get template variables SYSTEM_PROMPT="${system_prompt}" TASK_PROMPT="${task_prompt}" FOLDER="${folder}" @@ -36,29 +36,39 @@ export AWS_SECRET_ACCESS_KEY="${aws_secret_access_key}" export AWS_REGION="${aws_region}" export AWS_PROFILE="${aws_profile}" -# Handle system prompt -if [ ! -z "$SYSTEM_PROMPT" ]; then - log "INFO: Setting system prompt" - echo "$SYSTEM_PROMPT" > "$MODULE_DIR/system_prompt.txt" +# Configure MCP if task reporting is enabled +if [ "$REPORT_TASKS" = "true" ]; then + log "INFO: Configuring MCP for task reporting..." + + # Set the workdir for Amazon Q + WORKDIR="${FOLDER:-/home/coder}" + + # Configure MCP with Amazon Q specific settings + export CODER_MCP_AMAZON_Q_TASK_PROMPT="$TASK_PROMPT" + export CODER_MCP_AMAZON_Q_SYSTEM_PROMPT="$SYSTEM_PROMPT" + + # Run MCP configuration + coder exp mcp configure amazon-q "$WORKDIR" || { + log "WARNING: MCP configuration failed, continuing without task reporting" + } fi -# Handle task prompt +# Handle task prompt and system prompt if [ ! -z "$TASK_PROMPT" ]; then log "INFO: Starting with task prompt" - echo "$TASK_PROMPT" > "$MODULE_DIR/task_prompt.txt" + PROMPT="Review your instructions. Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $TASK_PROMPT" + PROMPT_FILE="$MODULE_DIR/prompt.txt" + echo -n "$PROMPT" > "$PROMPT_FILE" - # Create combined prompt - COMBINED_PROMPT="You are Amazon Q, an AI coding assistant. Follow these instructions:\n\n" - - if [ -f "$MODULE_DIR/system_prompt.txt" ]; then - COMBINED_PROMPT="$${COMBINED_PROMPT}$(cat $MODULE_DIR/system_prompt.txt)\n\n" + if [ "$USE_AIDER" = "true" ]; then + AMAZON_Q_ARGS=(--instructions "$PROMPT_FILE") + else + # For Amazon Q, we'll need to pass the prompt differently + AMAZON_Q_ARGS=() fi - - COMBINED_PROMPT="$${COMBINED_PROMPT}Current task: $(cat $MODULE_DIR/task_prompt.txt)" - - log "INFO: Using combined prompt for task execution" else - log "INFO: Starting without specific task prompt" + log "INFO: Starting without a prompt" + AMAZON_Q_ARGS=() fi # Signal handling for graceful shutdown @@ -82,15 +92,9 @@ if [ "$USE_AIDER" = "true" ]; then exit 1 fi - # Start Aider with the system prompt and task - if [ -n "$TASK_PROMPT" ]; then - FULL_PROMPT="SYSTEM PROMPT:\n$SYSTEM_PROMPT\n\nThis is your current task: $TASK_PROMPT" - echo -e "$FULL_PROMPT" | agentapi server --term-width 67 --term-height 1190 -- \ - aider --yes-always 2>&1 | tee -a "$HOME/.aider.log" - else - agentapi server --term-width 67 --term-height 1190 -- \ - aider 2>&1 | tee -a "$HOME/.aider.log" - fi + # Start Aider with AgentAPI + agentapi server --term-width 67 --term-height 1190 -- \ + bash -c "$(printf '%q ' aider --yes-always "${AMAZON_Q_ARGS[@]}")" else log "INFO: Starting Amazon Q with AgentAPI..." @@ -102,13 +106,7 @@ else fi # Start Amazon Q via AgentAPI - if [ "$REPORT_TASKS" = "true" ]; then - log "INFO: Starting with MCP task reporting support" - agentapi server --term-width 67 --term-height 1190 -- \ - bash -c "export PATH=\"$PATH:$HOME/q/bin\" && q chat --trust-all-tools" - else - log "INFO: Starting without MCP task reporting" - agentapi server --term-width 67 --term-height 1190 -- \ - bash -c "export PATH=\"$PATH:$HOME/q/bin\" && q chat" - fi + # Amazon Q needs the --trust-all-tools flag for automated operation + agentapi server --term-width 67 --term-height 1190 -- \ + bash -c "export PATH=\"$PATH:$HOME/q/bin\" && q chat --trust-all-tools" fi \ No newline at end of file