From b4ad53b7e82bfe55608731b5eab4c20f1c24ba9d Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 12 Aug 2025 18:00:40 +0100 Subject: [PATCH 1/2] feat(dogfood): integrate tasks support --- dogfood/coder/main.tf | 98 +++++++++++++++++++++++++++++++++++++++++++ dogfood/main.tf | 13 ++++++ 2 files changed, 111 insertions(+) diff --git a/dogfood/coder/main.tf b/dogfood/coder/main.tf index ae4088ec40fe7..678dbd3801934 100644 --- a/dogfood/coder/main.tf +++ b/dogfood/coder/main.tf @@ -38,6 +38,7 @@ locals { repo_base_dir = data.coder_parameter.repo_base_dir.value == "~" ? "/home/coder" : replace(data.coder_parameter.repo_base_dir.value, "/^~\\//", "/home/coder/") repo_dir = replace(try(module.git-clone[0].repo_dir, ""), "/^~\\//", "/home/coder/") container_name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" + has_ai_prompt = data.coder_parameter.ai_prompt.value != "" } data "coder_workspace_preset" "cpt" { @@ -150,6 +151,13 @@ data "coder_parameter" "image_type" { } } +variable "anthropic_api_key" { + type = string + description = "The API key used to authenticate with the Anthropic API." + default = "" + sensitive = true +} + locals { default_regions = { // keys should match group names @@ -242,6 +250,14 @@ data "coder_parameter" "devcontainer_autostart" { mutable = true } +data "coder_parameter" "ai_prompt" { + type = "string" + name = "AI Prompt" + default = "" + description = "Prompt for Claude Code" + mutable = false +} + provider "docker" { host = lookup(local.docker_host, data.coder_parameter.region.value) } @@ -380,6 +396,25 @@ module "devcontainers-cli" { agent_id = coder_agent.dev.id } +module "claude-code" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + source = "dev.registry.coder.com/coder/claude-code/coder" + version = "~>2.0" + agent_id = coder_agent.dev.id + folder = local.repo_dir + install_claude_code = true + claude_code_version = "latest" + order = 999 + + experiment_report_tasks = true + # TODO(Cian): Add post-install script to set up required MCP servers: + # - desktop-commander + # - playwright + #experiment_post_install_script = <<-EOT + #EOT +} + + resource "coder_agent" "dev" { arch = "amd64" os = "linux" @@ -710,4 +745,67 @@ resource "coder_metadata" "container_info" { key = "region" value = data.coder_parameter.region.option[index(data.coder_parameter.region.option.*.value, data.coder_parameter.region.value)].name } + item { + key = "ai_task" + value = local.has_ai_prompt ? "yes" : "no" + } +} + +resource "coder_env" "claude_system_prompt" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + agent_id = coder_agent.dev.id + name = "CODER_MCP_CLAUDE_SYSTEM_PROMPT" + value = <<-EOT + + -- Framing -- + 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. + + -- Tool Selection -- + - coder_report_task: providing status updates or requesting user input. + - Built-in tools - use for everything else: + (file operations, git commands, builds & installs, one-off shell commands) + + -- Task Reporting -- + Report all tasks to Coder, following these EXACT guidelines: + 1. Be granular. If you are investigating with multiple steps, report each step + to coder. + 2. IMMEDIATELY report status after receiving ANY user message + 3. Use "state": "working" when actively processing WITHOUT needing + additional user input + 4. Use "state": "complete" only when finished with a task + 5. Use "state": "failure" when you need ANY user input, lack sufficient + details, or encounter blockers + + In your summary: + - Be specific about what you're doing + - Clearly indicate what information you need from the user when in + "failure" state + - Keep it under 160 characters + - Make it actionable + + -- Context -- + There is an existing application in the current directory. + Be sure to read CLAUDE.md before making any changes. + + This is a real-world production application. As such, make sure to think carefully, use TODO lists, and plan carefully before making changes. + + EOT +} + +resource "coder_env" "claude_task_prompt" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + agent_id = coder_agent.dev.id + name = "CODER_MCP_CLAUDE_TASK_PROMPT" + value = data.coder_parameter.ai_prompt.value +} + +resource "coder_env" "anthropic_api_key" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + agent_id = coder_agent.dev.id + name = "ANTHROPIC_API_KEY" + value = var.anthropic_api_key } diff --git a/dogfood/main.tf b/dogfood/main.tf index 72cd868f61645..c79e950efadf4 100644 --- a/dogfood/main.tf +++ b/dogfood/main.tf @@ -33,6 +33,13 @@ variable "CODER_TEMPLATE_MESSAGE" { type = string } +variable "CODER_DOGFOOD_ANTHROPIC_API_KEY" { + type = string + description = "The API key that workspaces will use to authenticate with the Anthropic API." + default = "" + sensitive = true +} + resource "coderd_template" "dogfood" { name = var.CODER_TEMPLATE_NAME display_name = "Write Coder on Coder" @@ -45,6 +52,12 @@ resource "coderd_template" "dogfood" { message = var.CODER_TEMPLATE_MESSAGE directory = var.CODER_TEMPLATE_DIR active = true + tf_vars = [ + { + name = "anthropic_api_key" + value = var.CODER_DOGFOOD_ANTHROPIC_API_KEY + } + ] } ] acl = { From 34b0423bb72105cc2a6ec3df70b3a13afa295ed5 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 12 Aug 2025 18:02:53 +0100 Subject: [PATCH 2/2] fixup! feat(dogfood): integrate tasks support --- .github/workflows/dogfood.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dogfood.yaml b/.github/workflows/dogfood.yaml index db3292392db19..6735f7d2ce8ae 100644 --- a/.github/workflows/dogfood.yaml +++ b/.github/workflows/dogfood.yaml @@ -169,6 +169,7 @@ jobs: CODER_URL: https://dev.coder.com CODER_SESSION_TOKEN: ${{ secrets.CODER_SESSION_TOKEN }} # Template source & details + TF_VAR_CODER_DOGFOOD_ANTHROPIC_API_KEY: ${{ secrets.CODER_DOGFOOD_ANTHROPIC_API_KEY }} TF_VAR_CODER_TEMPLATE_NAME: ${{ secrets.CODER_TEMPLATE_NAME }} TF_VAR_CODER_TEMPLATE_VERSION: ${{ steps.vars.outputs.sha_short }} TF_VAR_CODER_TEMPLATE_DIR: ./coder