From 5bbca3078a2b15f567ce53a75c1b319ddc70b73e Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Fri, 1 Aug 2025 19:10:00 +0530 Subject: [PATCH 01/13] feat: add codex module --- registry/coder-labs/modules/codex/README.md | 94 ++++++++ .../coder-labs/modules/codex/main.test.ts | 210 ++++++++++++++++++ registry/coder-labs/modules/codex/main.tf | 177 +++++++++++++++ .../modules/codex/scripts/install.sh | 141 ++++++++++++ .../coder-labs/modules/codex/scripts/start.sh | 68 ++++++ .../modules/codex/testdata/codex-mock.sh | 14 ++ 6 files changed, 704 insertions(+) create mode 100644 registry/coder-labs/modules/codex/README.md create mode 100644 registry/coder-labs/modules/codex/main.test.ts create mode 100644 registry/coder-labs/modules/codex/main.tf create mode 100644 registry/coder-labs/modules/codex/scripts/install.sh create mode 100644 registry/coder-labs/modules/codex/scripts/start.sh create mode 100644 registry/coder-labs/modules/codex/testdata/codex-mock.sh diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md new file mode 100644 index 00000000..b4a3affb --- /dev/null +++ b/registry/coder-labs/modules/codex/README.md @@ -0,0 +1,94 @@ +--- +display_name: Codex CLI +icon: ../../../../.icons/codex.svg +description: Run Codex CLI in your workspace with AgentAPI integration +verified: true +tags: [agent, codex, ai, openai, tasks] +--- + +# Codex CLI + +Run Codex CLI in your workspace to access OpenAI's models through the Codex interface, with custom pre/post install scripts. This module integrates with [AgentAPI](https://github.com/coder/agentapi) for Coder Tasks compatibility. + +```tf +module "codex" { + source = "registry.coder.com/coder-labs/codex/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + codex_api_key = var.codex_api_key + agentapi_version = "v0.3.0" +} +``` + +## Prerequisites + +- You must add the [Coder Login](https://registry.coder.com/modules/coder-login/coder) module to your template +- OpenAI API key for Codex access + +## Usage Example + +- Simple usage Example: +```tf +module "codex" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder-labs/codex/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + codex_api_key = "..." + codex_model = "o4-mini" + install_codex = true + codex_version = "latest" + folder = "/home/coder/project" + codex_system_prompt = "You are a helpful coding assistant. Start every response with `Codex says:`" + agentapi_version = "v0.3.0" +} +``` + +- Example usage with Tasks: +```tf +# This +data "coder_parameter" "ai_prompt" { + type = "string" + name = "AI Prompt" + default = "" + description = "Initial prompt for the Codex CLI" + mutable = true +} + +module "coder-login" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/coder-login/coder" + version = "1.0.31" + agent_id = coder_agent.example.id +} + +module "codex" { + source = "/Users/jkmr/Documents/work/registry/registry/coder-labs/modules/codex" + agent_id = coder_agent.example.id + codex_api_key = "..." + ai_prompt = data.coder_parameter.ai_prompt.value + agentapi_version = "v0.3.0" +} +``` + +## How it Works + +- **Install**: The module installs Codex CLI and sets up the environment +- **System Prompt**: If `codex_system_prompt` and `folder` are set, creates the directory (if needed) and writes the prompt to `AGENTS.md` +- **Start**: Launches Codex CLI in the specified directory, wrapped by AgentAPI +- **Environment**: Sets `OPENAI_API_KEY` and `CODEX_MODEL` for the CLI (if variables provided) + +## Troubleshooting + +- Check logs in `/home/coder/.codex-module/` for install/start output +- Ensure your OpenAI API key has access to the specified model + +> [!IMPORTANT] +> To use tasks with Codex CLI, ensure you have the `codex_api_key` variable set, and **you create an `ai_prompt` `coder_parametre` and pass it's value to codex `ai_prompt` variable**. +> The module automatically configures Codex with your API key and model preferences. + +## References + +- [OpenAI API Documentation](https://platform.openai.com/docs) +- [AgentAPI Documentation](https://github.com/coder/agentapi) +- [Coder AI Agents Guide](https://coder.com/docs/tutorials/ai-agents) diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts new file mode 100644 index 00000000..3d7799fc --- /dev/null +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -0,0 +1,210 @@ +import { + test, + afterEach, + describe, + setDefaultTimeout, + beforeAll, + expect, +} from "bun:test"; +import { execContainer, readFileContainer, runTerraformInit } from "~test"; +import { + loadTestFile, + writeExecutable, + setup as setupUtil, + execModuleScript, + expectAgentAPIStarted, +} from "../../../coder/modules/agentapi/test-util"; + +let cleanupFunctions: (() => Promise)[] = []; +const registerCleanup = (cleanup: () => Promise) => { + cleanupFunctions.push(cleanup); +}; +afterEach(async () => { + const cleanupFnsCopy = cleanupFunctions.slice().reverse(); + cleanupFunctions = []; + for (const cleanup of cleanupFnsCopy) { + try { + await cleanup(); + } catch (error) { + console.error("Error during cleanup:", error); + } + } +}); + +interface SetupProps { + skipAgentAPIMock?: boolean; + skipCodexMock?: boolean; + moduleVariables?: Record; + agentapiMockScript?: string; +} + +const setup = async (props?: SetupProps): Promise<{ id: string }> => { + const projectDir = "/home/coder/project"; + const { id } = await setupUtil({ + moduleDir: import.meta.dir, + moduleVariables: { + install_codex: props?.skipCodexMock ? "true" : "false", + install_agentapi: props?.skipAgentAPIMock ? "true" : "false", + codex_model: "gpt-4-turbo", + ...props?.moduleVariables, + }, + registerCleanup, + projectDir, + skipAgentAPIMock: props?.skipAgentAPIMock, + agentapiMockScript: props?.agentapiMockScript, + }); + if (!props?.skipCodexMock) { + await writeExecutable({ + containerId: id, + filePath: "/usr/bin/codex", + content: await loadTestFile(import.meta.dir, "codex-mock.sh"), + }); + } + return { id }; +}; + +setDefaultTimeout(60 * 1000); + +describe("codex", async () => { + beforeAll(async () => { + await runTerraformInit(import.meta.dir); + }); + + test("happy-path", async () => { + const { id } = await setup(); + await execModuleScript(id); + await expectAgentAPIStarted(id); + }); + + test("install-codex-version", async () => { + const version_to_install = "1.0.0"; + const { id } = await setup({ + skipCodexMock: true, + moduleVariables: { + install_codex: "true", + codex_version: version_to_install, + }, + }); + await execModuleScript(id); + const resp = await execContainer(id, [ + "bash", + "-c", + `cat /home/coder/.codex-module/install.log || true`, + ]); + expect(resp.stdout).toContain(version_to_install); + }); + + test("codex-config-toml", async () => { + const settings = '[mcp_servers.CustomMCP]\n' + + 'command = "/Users/jkmr/Documents/work/coder/coder_darwin_arm64"\n' + + 'args = ["exp", "mcp", "server", "app-status-slug=codex"]\n' + + 'env = { "CODER_MCP_APP_STATUS_SLUG" = "codex", "CODER_MCP_AI_AGENTAPI_URL"= "http://localhost:3284" }\n' + + 'description = "Report ALL tasks and statuses (in progress, done, failed) you are working on."\n' + + 'enabled = true\n' + + 'type = "stdio"'; + const { id } = await setup({ + moduleVariables: { + codex_settings_toml: settings, + }, + }); + await execModuleScript(id); + const resp = await readFileContainer(id, "/home/coder/.codex/config.toml"); + expect(resp).toContain("[mcp_servers.CustomMCP]"); + expect(resp).toContain("[mcp_servers.Coder]"); + }); + + test("codex-api-key", async () => { + const apiKey = "test-api-key-123"; + const { id } = await setup({ + moduleVariables: { + codex_api_key: apiKey, + }, + }); + await execModuleScript(id); + + const resp = await readFileContainer(id, "/home/coder/.codex-module/agentapi-start.log"); + expect(resp).toContain("codex_api_key provided !"); + }); + + test("pre-post-install-scripts", async () => { + const { id } = await setup({ + moduleVariables: { + pre_install_script: "#!/bin/bash\necho 'pre-install-script'", + post_install_script: "#!/bin/bash\necho 'post-install-script'", + }, + }); + await execModuleScript(id); + const preInstallLog = await readFileContainer(id, "/home/coder/.codex-module/pre_install.log"); + expect(preInstallLog).toContain("pre-install-script"); + const postInstallLog = await readFileContainer(id, "/home/coder/.codex-module/post_install.log"); + expect(postInstallLog).toContain("post-install-script"); + }); + + test("folder-variable", async () => { + const folder = "/tmp/codex-test-folder"; + const { id } = await setup({ + skipCodexMock: false, + moduleVariables: { + folder, + }, + }); + await execModuleScript(id); + const resp = await readFileContainer(id, "/home/coder/.codex-module/install.log"); + expect(resp).toContain(folder); + }); + + test("additional-extensions", async () => { + const additional = '[mcp_servers.CustomMCP]\n' + + 'command = "/Users/jkmr/Documents/work/coder/coder_darwin_arm64"\n' + + 'args = ["exp", "mcp", "server", "app-status-slug=codex"]\n' + + 'env = { "CODER_MCP_APP_STATUS_SLUG" = "codex", "CODER_MCP_AI_AGENTAPI_URL"= "http://localhost:3284" }\n' + + 'description = "Report ALL tasks and statuses (in progress, done, failed) you are working on."\n' + + 'enabled = true\n' + + 'type = "stdio"'; + const { id } = await setup({ + moduleVariables: { + additional_extensions: additional, + }, + }); + await execModuleScript(id); + const resp = await readFileContainer(id, "/home/coder/.codex/config.toml"); + expect(resp).toContain("[mcp_servers.CustomMCP]"); + expect(resp).toContain("[mcp_servers.Coder]"); + }); + + test("codex-system-prompt", async () => { + const prompt = "This is a system prompt for Codex."; + const { id } = await setup({ + moduleVariables: { + codex_system_prompt: prompt, + }, + }); + await execModuleScript(id); + const resp = await readFileContainer(id, "/home/coder/AGENTS.md"); + expect(resp).toContain(prompt); + }); + + test("codex-ai-task-prompt", async () => { + const prompt = "This is a system prompt for Codex."; + const { id } = await setup({ + moduleVariables: { + ai_prompt: prompt, + }, + }); + await execModuleScript(id); + const resp = await execContainer(id, [ + "bash", + "-c", + `cat /home/coder/.codex-module/agentapi-start.log || true`, + ]); + expect(resp.stdout).toContain(`Every step of the way, report tasks to Coder with proper descriptions and statuses, when each part of the task is finished report with . Your task at hand: ${prompt}`); + }); + + test("start-without-prompt", async () => { + const { id } = await setup(); + await execModuleScript(id); + const prompt = await execContainer(id, ["ls", "-l", "/home/coder/AGENTS.md"]); + expect(prompt.exitCode).not.toBe(0); + expect(prompt.stderr).toContain("No such file or directory"); + }); +}); \ No newline at end of file diff --git a/registry/coder-labs/modules/codex/main.tf b/registry/coder-labs/modules/codex/main.tf new file mode 100644 index 00000000..5ccd8066 --- /dev/null +++ b/registry/coder-labs/modules/codex/main.tf @@ -0,0 +1,177 @@ +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/code.svg" +} + +variable "folder" { + type = string + description = "The folder to run Codex in." + default = "/home/coder" +} + +variable "install_codex" { + type = bool + description = "Whether to install Codex." + default = true +} + +variable "codex_version" { + type = string + description = "The version of Codex to install." + default = "" +} + +variable "codex_settings_toml" { + type = string + description = "json to use in ~/.codex/config.toml." + default = "" +} + +variable "codex_api_key" { + type = string + description = "Codex API Key" + default = "" +} + +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 = "v0.3.0" +} + +variable "codex_model" { + type = string + description = "The model to use for Codex (e.g., o4-mini)." + default = "" +} + +variable "pre_install_script" { + type = string + description = "Custom script to run before installing Codex." + default = null +} + +variable "post_install_script" { + type = string + description = "Custom script to run after installing Codex." + default = null +} + +variable "ai_prompt" { + type = string + description = "Task prompt for the Codex CLI" + default = "" +} + +variable "additional_extensions" { + type = string + description = "Additional extensions configuration in json format to append to the config." + default = "" +} + +variable "codex_system_prompt" { + type = string + description = "System prompt for Codex. It will be added to AGENTS.md in the specified folder." + default = "" +} + +resource "coder_env" "codex_api_key" { + agent_id = var.agent_id + name = "OPENAI_API_KEY" + value = var.codex_api_key +} + +locals { + app_slug = "codex" + install_script = file("${path.module}/scripts/install.sh") + start_script = file("${path.module}/scripts/start.sh") + module_dir_name = ".codex-module" +} + +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 = "Codex" + cli_app_slug = "${local.app_slug}-cli" + cli_app_display_name = "Codex CLI" + module_dir_name = local.module_dir_name + install_agentapi = var.install_agentapi + agentapi_version = var.agentapi_version + pre_install_script = var.pre_install_script + post_install_script = var.post_install_script + start_script = <<-EOT + #!/bin/bash + set -o errexit + set -o pipefail + + echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh + chmod +x /tmp/start.sh + CODEX_API_KEY='${var.codex_api_key}' \ + CODEX_MODEL='${var.codex_model}' \ + CODEX_START_DIRECTORY='${var.folder}' \ + CODEX_TASK_PROMPT='${base64encode(var.ai_prompt)}' \ + /tmp/start.sh + EOT + + install_script = <<-EOT + #!/bin/bash + set -o errexit + set -o pipefail + + echo -n '${base64encode(local.install_script)}' | base64 -d > /tmp/install.sh + chmod +x /tmp/install.sh + ARG_INSTALL='${var.install_codex}' \ + ARG_CODEX_VERSION='${var.codex_version}' \ + ARG_CODEX_CONFIG='${base64encode(var.codex_settings_toml)}' \ + CODER_MCP_APP_STATUS_SLUG='${local.app_slug}' \ + ADDITIONAL_EXTENSIONS='${base64encode(var.additional_extensions)}' \ + CODEX_START_DIRECTORY='${var.folder}' \ + CODEX_INSTRUCTION_PROMPT='${base64encode(var.codex_system_prompt)}' \ + /tmp/install.sh + EOT +} \ No newline at end of file diff --git a/registry/coder-labs/modules/codex/scripts/install.sh b/registry/coder-labs/modules/codex/scripts/install.sh new file mode 100644 index 00000000..68090265 --- /dev/null +++ b/registry/coder-labs/modules/codex/scripts/install.sh @@ -0,0 +1,141 @@ +#!/bin/bash + +BOLD='\033[0;1m' + +# Function to check if a command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +set -o nounset + +ARG_CODEX_CONFIG=$(echo -n "$ARG_CODEX_CONFIG" | base64 -d) +ADDITIONAL_EXTENSIONS=$(echo -n "$ADDITIONAL_EXTENSIONS" | base64 -d) +CODEX_INSTRUCTION_PROMPT=$(echo -n "$CODEX_INSTRUCTION_PROMPT" | base64 -d) + +echo "--------------------------------" +printf "codex_config: %s\n" "$ARG_CODEX_CONFIG" +printf "install: %s\n" "$ARG_INSTALL" +printf "codex_version: %s\n" "$ARG_CODEX_VERSION" +echo "--------------------------------" + +set +o nounset + +function install_node() { + # borrowed from claude-code module + if ! command_exists npm; then + printf "npm not found, checking for Node.js installation...\n" + if ! command_exists node; then + printf "Node.js not found, installing Node.js via NVM...\n" + export NVM_DIR="$HOME/.nvm" + if [ ! -d "$NVM_DIR" ]; then + mkdir -p "$NVM_DIR" + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + else + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + fi + + nvm install --lts + nvm use --lts + nvm alias default node + + printf "Node.js installed: %s\n" "$(node --version)" + printf "npm installed: %s\n" "$(npm --version)" + else + printf "Node.js is installed but npm is not available. Please install npm manually.\n" + exit 1 + fi + fi +} + +function install_codex() { + if [ "${ARG_INSTALL}" = "true" ]; then + # we need node to install and run codex-cli + install_node + + # If nvm does not exist, we will create a global npm directory (this os to prevent the possibility of EACCESS issues on npm -g) + if ! command_exists nvm; then + printf "which node: %s\n" "$(which node)" + printf "which npm: %s\n" "$(which npm)" + + # Create a directory for global packages + mkdir -p "$HOME"/.npm-global + + # Configure npm to use it + npm config set prefix "$HOME/.npm-global" + + # Add to PATH for current session + export PATH="$HOME/.npm-global/bin:$PATH" + + # Add to shell profile for future sessions + if ! grep -q "export PATH=$HOME/.npm-global/bin:\$PATH" ~/.bashrc; then + echo "export PATH=$HOME/.npm-global/bin:\$PATH" >> ~/.bashrc + fi + fi + + printf "%s Installing Codex CLI\n" "${BOLD}" + + if [ -n "$ARG_CODEX_VERSION" ]; then + npm install -g "@openai/codex@$ARG_CODEX_VERSION" + else + npm install -g "@openai/codex" + fi + printf "%s Successfully installed Codex CLI. Version: %s\n" "${BOLD}" "$(codex --version)" + fi +} + +function populate_config_toml() { + CONFIG_PATH="$HOME/.codex/config.toml" + mkdir -p "$(dirname "$CONFIG_PATH")" + printf "Custom codex_config is provided !\n" + BASE_EXTENSIONS="[mcp_servers.Coder] + command = \"coder\" + args = [\"exp\", \"mcp\", \"server\"] + env = { \"CODER_MCP_APP_STATUS_SLUG\" = \"${CODER_MCP_APP_STATUS_SLUG}\", \"CODER_MCP_AI_AGENTAPI_URL\"= \"http://localhost:3284\", \"CODER_AGENT_URL\" = \"${CODER_AGENT_URL}\", \"CODER_AGENT_TOKEN\" = \"${CODER_AGENT_TOKEN}\" } + description = \"Report ALL tasks and statuses (in progress, done, failed) you are working on.\" + type = \"stdio\"" + + echo " +${ARG_CODEX_CONFIG} + +${BASE_EXTENSIONS} + +${ADDITIONAL_EXTENSIONS} + " > "$HOME/.codex/config.toml" + +} + +function add_instruction_prompt_if_exists() { + if [ -n "${CODEX_INSTRUCTION_PROMPT:-}" ]; then + if [ -d "${CODEX_START_DIRECTORY}" ]; then + printf "Directory '%s' exists. Changing to it.\\n" "${CODEX_START_DIRECTORY}" + cd "${CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + exit 1 + } + else + printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${CODEX_START_DIRECTORY}" + mkdir -p "${CODEX_START_DIRECTORY}" || { + printf "Error: Could not create directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + exit 1 + } + cd "${CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + exit 1 + } + fi + touch AGENTS.md + printf "Setting AGENTS.md\n" + echo "${CODEX_INSTRUCTION_PROMPT}" > AGENTS.md + else + printf "AGENTS.md is not set.\n" + fi +} + + +# Install Codex +install_codex +codex --version +populate_config_toml +add_instruction_prompt_if_exists \ No newline at end of file diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh new file mode 100644 index 00000000..c319c95d --- /dev/null +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Load shell environment +source "$HOME"/.bashrc + +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +if [ -f "$HOME/.nvm/nvm.sh" ]; then + source "$HOME"/.nvm/nvm.sh +else + export PATH="$HOME/.npm-global/bin:$PATH" +fi + +printf "Version: %s\n" "$(codex --version)" + +CODEX_TASK_PROMPT=$(echo -n "$CODEX_TASK_PROMPT" | base64 -d) +CODEX_ARGS=("--skip-git-repo-check") + +if command_exists codex; then + printf "Codex is installed\n" +else + printf "Error: Codex is not installed. Please enable install_codex or install it manually :)\n" + exit 1 +fi + +if [ -d "${CODEX_START_DIRECTORY}" ]; then + printf "Directory '%s' exists. Changing to it.\\n" "${CODEX_START_DIRECTORY}" + cd "${CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + exit 1 + } +else + printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${CODEX_START_DIRECTORY}" + mkdir -p "${CODEX_START_DIRECTORY}" || { + printf "Error: Could not create directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + exit 1 + } + cd "${CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + exit 1 + } +fi + +if [ -n "$CODEX_MODEL" ]; then + CODEX_ARGS+=("--model" "$CODEX_MODEL") +fi + +if [ -n "$CODEX_TASK_PROMPT" ]; then + printf "Running the task prompt %s\n" "$CODEX_TASK_PROMPT" + PROMPT="Every step of the way, report tasks to Coder with proper descriptions and statuses, when each part of the task is finished report with . Your task at hand: $CODEX_TASK_PROMPT" + CODEX_ARGS+=("--dangerously-bypass-approvals-and-sandbox" "$PROMPT") +else + printf "No task prompt given.\n" +fi + +if [ -n "$CODEX_API_KEY" ]; then + printf "codex_api_key provided !\n" +else + printf "codex_api_key not provided\n" +fi + +# use low width to fit in the tasks UI sidebar. height is adjusted so that width x height ~= 80x1000 characters +# are visible in the terminal screen by default. +# in case of codex we adjust the height to 930 due to a bug in codex module, see: https://github.com/openai/codex/issues/1608 +printf "Starting codex with %s\n" "${CODEX_ARGS[@]}" +agentapi server --term-width 70 --term-height 930 -- codex "${CODEX_ARGS[@]}" \ No newline at end of file diff --git a/registry/coder-labs/modules/codex/testdata/codex-mock.sh b/registry/coder-labs/modules/codex/testdata/codex-mock.sh new file mode 100644 index 00000000..989abd1e --- /dev/null +++ b/registry/coder-labs/modules/codex/testdata/codex-mock.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +if [[ "$1" == "--version" ]]; then + echo "HELLO: $(bash -c env)" + echo "codex version v1.0.0" + exit 0 +fi + +set -e + +while true; do + echo "$(date) - codex-mock" + sleep 15 +done \ No newline at end of file From be3bc0a6fbcfac3c7648142072e60f79e8ca66cc Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Fri, 1 Aug 2025 19:10:28 +0530 Subject: [PATCH 02/13] feat: bun fmt --- registry/coder-labs/modules/codex/README.md | 36 +++++++++++---------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index b4a3affb..351073a4 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -12,7 +12,7 @@ Run Codex CLI in your workspace to access OpenAI's models through the Codex inte ```tf module "codex" { - source = "registry.coder.com/coder-labs/codex/coder" + source = "registry.coder.com/coder-labs/codex/coder" version = "1.0.0" agent_id = coder_agent.example.id codex_api_key = var.codex_api_key @@ -28,23 +28,25 @@ module "codex" { ## Usage Example - Simple usage Example: + ```tf module "codex" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder-labs/codex/coder" - version = "1.0.0" - agent_id = coder_agent.example.id - codex_api_key = "..." - codex_model = "o4-mini" - install_codex = true - codex_version = "latest" - folder = "/home/coder/project" - codex_system_prompt = "You are a helpful coding assistant. Start every response with `Codex says:`" - agentapi_version = "v0.3.0" + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder-labs/codex/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + codex_api_key = "..." + codex_model = "o4-mini" + install_codex = true + codex_version = "latest" + folder = "/home/coder/project" + codex_system_prompt = "You are a helpful coding assistant. Start every response with `Codex says:`" + agentapi_version = "v0.3.0" } ``` - Example usage with Tasks: + ```tf # This data "coder_parameter" "ai_prompt" { @@ -63,10 +65,10 @@ module "coder-login" { } module "codex" { - source = "/Users/jkmr/Documents/work/registry/registry/coder-labs/modules/codex" - agent_id = coder_agent.example.id - codex_api_key = "..." - ai_prompt = data.coder_parameter.ai_prompt.value + source = "/Users/jkmr/Documents/work/registry/registry/coder-labs/modules/codex" + agent_id = coder_agent.example.id + codex_api_key = "..." + ai_prompt = data.coder_parameter.ai_prompt.value agentapi_version = "v0.3.0" } ``` @@ -85,7 +87,7 @@ module "codex" { > [!IMPORTANT] > To use tasks with Codex CLI, ensure you have the `codex_api_key` variable set, and **you create an `ai_prompt` `coder_parametre` and pass it's value to codex `ai_prompt` variable**. -> The module automatically configures Codex with your API key and model preferences. +> The module automatically configures Codex with your API key and model preferences. ## References From 5ac3d7ac6d60566788e4000223a1c595c4ee0818 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Fri, 1 Aug 2025 19:15:29 +0530 Subject: [PATCH 03/13] fix: fix typo --- registry/coder-labs/modules/codex/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index 351073a4..9d5f105d 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -86,7 +86,7 @@ module "codex" { - Ensure your OpenAI API key has access to the specified model > [!IMPORTANT] -> To use tasks with Codex CLI, ensure you have the `codex_api_key` variable set, and **you create an `ai_prompt` `coder_parametre` and pass it's value to codex `ai_prompt` variable**. +> To use tasks with Codex CLI, ensure you have the `codex_api_key` variable set, and **you create an `ai_prompt` `coder_parameter` and pass it's value to codex `ai_prompt` variable**. > The module automatically configures Codex with your API key and model preferences. ## References From 37f85c659b1d8ab755efcb3b9241194d0e10d9e1 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Fri, 1 Aug 2025 19:39:29 +0530 Subject: [PATCH 04/13] feat: add codex svg --- .icons/codex.svg | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .icons/codex.svg diff --git a/.icons/codex.svg b/.icons/codex.svg new file mode 100644 index 00000000..3b4eff96 --- /dev/null +++ b/.icons/codex.svg @@ -0,0 +1,2 @@ + +OpenAI icon \ No newline at end of file From 13b776d5e4f5be992170be652ee9e887f6556073 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Fri, 1 Aug 2025 19:40:21 +0530 Subject: [PATCH 05/13] feat: update readme --- registry/coder-labs/modules/codex/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index 9d5f105d..f167b6f4 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -88,6 +88,7 @@ module "codex" { > [!IMPORTANT] > To use tasks with Codex CLI, ensure you have the `codex_api_key` variable set, and **you create an `ai_prompt` `coder_parameter` and pass it's value to codex `ai_prompt` variable**. > The module automatically configures Codex with your API key and model preferences. +> Tasks are run with `--dangerously-bypass-approvals-and-sandbox` ## References From 4e45ffd2e7f44e0649ac86394a5fba4ed1b50a93 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Sat, 2 Aug 2025 09:41:36 +0530 Subject: [PATCH 06/13] chore: update icon name --- .icons/{codex.svg => openai.svg} | 0 registry/coder-labs/modules/codex/README.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename .icons/{codex.svg => openai.svg} (100%) diff --git a/.icons/codex.svg b/.icons/openai.svg similarity index 100% rename from .icons/codex.svg rename to .icons/openai.svg diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index f167b6f4..80ac5345 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -1,6 +1,6 @@ --- display_name: Codex CLI -icon: ../../../../.icons/codex.svg +icon: ../../../../.icons/openai.svg description: Run Codex CLI in your workspace with AgentAPI integration verified: true tags: [agent, codex, ai, openai, tasks] From 66bb40e88efcf6dc0af5cba9ed9c45b308842244 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Sat, 2 Aug 2025 14:29:17 +0530 Subject: [PATCH 07/13] chore: rename codex_api_key to openai_api_key --- registry/coder-labs/modules/codex/main.tf | 8 ++++---- registry/coder-labs/modules/codex/scripts/start.sh | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/registry/coder-labs/modules/codex/main.tf b/registry/coder-labs/modules/codex/main.tf index 5ccd8066..b9e9e15c 100644 --- a/registry/coder-labs/modules/codex/main.tf +++ b/registry/coder-labs/modules/codex/main.tf @@ -60,7 +60,7 @@ variable "codex_settings_toml" { default = "" } -variable "codex_api_key" { +variable "openai_api_key" { type = string description = "Codex API Key" default = "" @@ -114,10 +114,10 @@ variable "codex_system_prompt" { default = "" } -resource "coder_env" "codex_api_key" { +resource "coder_env" "openai_api_key" { agent_id = var.agent_id name = "OPENAI_API_KEY" - value = var.codex_api_key + value = var.openai_api_key } locals { @@ -151,7 +151,7 @@ module "agentapi" { echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh chmod +x /tmp/start.sh - CODEX_API_KEY='${var.codex_api_key}' \ + OPENAI_API_KEY='${var.openai_api_key}' \ CODEX_MODEL='${var.codex_model}' \ CODEX_START_DIRECTORY='${var.folder}' \ CODEX_TASK_PROMPT='${base64encode(var.ai_prompt)}' \ diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh index c319c95d..86a4fcda 100644 --- a/registry/coder-labs/modules/codex/scripts/start.sh +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -55,10 +55,10 @@ else printf "No task prompt given.\n" fi -if [ -n "$CODEX_API_KEY" ]; then - printf "codex_api_key provided !\n" +if [ -n "$OPENAI_API_KEY" ]; then + printf "openai_api_key provided !\n" else - printf "codex_api_key not provided\n" + printf "openai_api_key not provided\n" fi # use low width to fit in the tasks UI sidebar. height is adjusted so that width x height ~= 80x1000 characters From b08aadf0cc2bbbf69d2b90f57d1100aed8fa1f41 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Sat, 2 Aug 2025 14:29:29 +0530 Subject: [PATCH 08/13] chore: rename codex_api_key to openai_api_key --- registry/coder-labs/modules/codex/main.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts index 3d7799fc..bd0184d6 100644 --- a/registry/coder-labs/modules/codex/main.test.ts +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -117,13 +117,13 @@ describe("codex", async () => { const apiKey = "test-api-key-123"; const { id } = await setup({ moduleVariables: { - codex_api_key: apiKey, + openai_api_key: apiKey, }, }); await execModuleScript(id); const resp = await readFileContainer(id, "/home/coder/.codex-module/agentapi-start.log"); - expect(resp).toContain("codex_api_key provided !"); + expect(resp).toContain("openai_api_key provided !"); }); test("pre-post-install-scripts", async () => { From 93b16cb2fa3260af2e1e9bc4fe05ebad648dc056 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Sat, 2 Aug 2025 14:32:34 +0530 Subject: [PATCH 09/13] chore: update README.md --- registry/coder-labs/modules/codex/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index 80ac5345..a7cf2413 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -15,7 +15,7 @@ module "codex" { source = "registry.coder.com/coder-labs/codex/coder" version = "1.0.0" agent_id = coder_agent.example.id - codex_api_key = var.codex_api_key + openai_api_key = var.openai_api_key agentapi_version = "v0.3.0" } ``` @@ -35,7 +35,7 @@ module "codex" { source = "registry.coder.com/coder-labs/codex/coder" version = "1.0.0" agent_id = coder_agent.example.id - codex_api_key = "..." + openai_api_key = "..." codex_model = "o4-mini" install_codex = true codex_version = "latest" @@ -67,7 +67,7 @@ module "coder-login" { module "codex" { source = "/Users/jkmr/Documents/work/registry/registry/coder-labs/modules/codex" agent_id = coder_agent.example.id - codex_api_key = "..." + openai_api_key = "..." ai_prompt = data.coder_parameter.ai_prompt.value agentapi_version = "v0.3.0" } @@ -86,7 +86,7 @@ module "codex" { - Ensure your OpenAI API key has access to the specified model > [!IMPORTANT] -> To use tasks with Codex CLI, ensure you have the `codex_api_key` variable set, and **you create an `ai_prompt` `coder_parameter` and pass it's value to codex `ai_prompt` variable**. +> To use tasks with Codex CLI, ensure you have the `openai_api_key` variable set, and **you create an `ai_prompt` `coder_parameter` and pass it's value to codex `ai_prompt` variable**. [Tasks Template Example](https://registry.coder.com/templates/coder-labs/tasks-docker). > The module automatically configures Codex with your API key and model preferences. > Tasks are run with `--dangerously-bypass-approvals-and-sandbox` From 92e6bb516d033c48cceed1b1a869a823e1ffc313 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Mon, 4 Aug 2025 19:28:46 +0530 Subject: [PATCH 10/13] chore: bump agentapi_version to v0.3.2 --- registry/coder-labs/modules/codex/README.md | 6 +++--- registry/coder-labs/modules/codex/main.tf | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index a7cf2413..98cbe235 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -16,7 +16,7 @@ module "codex" { version = "1.0.0" agent_id = coder_agent.example.id openai_api_key = var.openai_api_key - agentapi_version = "v0.3.0" + agentapi_version = "v0.3.2" } ``` @@ -41,7 +41,7 @@ module "codex" { codex_version = "latest" folder = "/home/coder/project" codex_system_prompt = "You are a helpful coding assistant. Start every response with `Codex says:`" - agentapi_version = "v0.3.0" + agentapi_version = "v0.3.2" } ``` @@ -69,7 +69,7 @@ module "codex" { agent_id = coder_agent.example.id openai_api_key = "..." ai_prompt = data.coder_parameter.ai_prompt.value - agentapi_version = "v0.3.0" + agentapi_version = "v0.3.2" } ``` diff --git a/registry/coder-labs/modules/codex/main.tf b/registry/coder-labs/modules/codex/main.tf index b9e9e15c..9c2fa45c 100644 --- a/registry/coder-labs/modules/codex/main.tf +++ b/registry/coder-labs/modules/codex/main.tf @@ -75,7 +75,7 @@ variable "install_agentapi" { variable "agentapi_version" { type = string description = "The version of AgentAPI to install." - default = "v0.3.0" + default = "v0.3.2" } variable "codex_model" { From 77393b4407402f789c60efa2eeaae591c0082375 Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Tue, 5 Aug 2025 19:21:18 +0530 Subject: [PATCH 11/13] fix: update README.md --- registry/coder-labs/modules/codex/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index 98cbe235..c5548b0e 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -65,7 +65,7 @@ module "coder-login" { } module "codex" { - source = "/Users/jkmr/Documents/work/registry/registry/coder-labs/modules/codex" + source = "registry.coder.com/coder-labs/codex/coder" agent_id = coder_agent.example.id openai_api_key = "..." ai_prompt = data.coder_parameter.ai_prompt.value @@ -73,6 +73,11 @@ module "codex" { } ``` +> **Security Notice**: This module uses the `--dangerously-bypass-approvals-and-sandbox` flag when running Codex CLI. This flag +> bypasses standard permission checks and allows Codex CLI broader access to your system than normally permitted. While +> this enables more functionality, it also means Codex CLI can potentially execute commands with the same privileges as +> the user running it. Use this module _only_ in trusted environments and be aware of the security implications. + ## How it Works - **Install**: The module installs Codex CLI and sets up the environment @@ -82,13 +87,12 @@ module "codex" { ## Troubleshooting -- Check logs in `/home/coder/.codex-module/` for install/start output +- Check installation and startup logs in `~/.codex-module/` - Ensure your OpenAI API key has access to the specified model > [!IMPORTANT] > To use tasks with Codex CLI, ensure you have the `openai_api_key` variable set, and **you create an `ai_prompt` `coder_parameter` and pass it's value to codex `ai_prompt` variable**. [Tasks Template Example](https://registry.coder.com/templates/coder-labs/tasks-docker). > The module automatically configures Codex with your API key and model preferences. -> Tasks are run with `--dangerously-bypass-approvals-and-sandbox` ## References From b33bbdae8c01e96949dbe167b195e0d8c4da897a Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Tue, 5 Aug 2025 19:31:59 +0530 Subject: [PATCH 12/13] wip: apply suggestions --- .../coder-labs/modules/codex/main.test.ts | 41 +++++++++++-------- registry/coder-labs/modules/codex/main.tf | 8 ++-- .../modules/codex/scripts/install.sh | 21 ++++++---- .../coder-labs/modules/codex/scripts/start.sh | 11 +++-- 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts index bd0184d6..465bbf7f 100644 --- a/registry/coder-labs/modules/codex/main.test.ts +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -14,6 +14,7 @@ import { execModuleScript, expectAgentAPIStarted, } from "../../../coder/modules/agentapi/test-util"; +import dedent from "dedent"; let cleanupFunctions: (() => Promise)[] = []; const registerCleanup = (cleanup: () => Promise) => { @@ -89,22 +90,24 @@ describe("codex", async () => { const resp = await execContainer(id, [ "bash", "-c", - `cat /home/coder/.codex-module/install.log || true`, + `cat /home/coder/.codex-module/install.log`, ]); expect(resp.stdout).toContain(version_to_install); }); test("codex-config-toml", async () => { - const settings = '[mcp_servers.CustomMCP]\n' + - 'command = "/Users/jkmr/Documents/work/coder/coder_darwin_arm64"\n' + - 'args = ["exp", "mcp", "server", "app-status-slug=codex"]\n' + - 'env = { "CODER_MCP_APP_STATUS_SLUG" = "codex", "CODER_MCP_AI_AGENTAPI_URL"= "http://localhost:3284" }\n' + - 'description = "Report ALL tasks and statuses (in progress, done, failed) you are working on."\n' + - 'enabled = true\n' + - 'type = "stdio"'; + const settings = dedent` + [mcp_servers.CustomMCP] + command = "/Users/jkmr/Documents/work/coder/coder_darwin_arm64" + args = ["exp", "mcp", "server", "app-status-slug=codex"] + env = { "CODER_MCP_APP_STATUS_SLUG" = "codex", "CODER_MCP_AI_AGENTAPI_URL"= "http://localhost:3284" } + description = "Report ALL tasks and statuses (in progress, done, failed) you are working on." + enabled = true + type = "stdio" + `.trim(); const { id } = await setup({ moduleVariables: { - codex_settings_toml: settings, + extra_codex_settings_toml: settings, }, }); await execModuleScript(id); @@ -154,13 +157,15 @@ describe("codex", async () => { }); test("additional-extensions", async () => { - const additional = '[mcp_servers.CustomMCP]\n' + - 'command = "/Users/jkmr/Documents/work/coder/coder_darwin_arm64"\n' + - 'args = ["exp", "mcp", "server", "app-status-slug=codex"]\n' + - 'env = { "CODER_MCP_APP_STATUS_SLUG" = "codex", "CODER_MCP_AI_AGENTAPI_URL"= "http://localhost:3284" }\n' + - 'description = "Report ALL tasks and statuses (in progress, done, failed) you are working on."\n' + - 'enabled = true\n' + - 'type = "stdio"'; + const additional = dedent` + [mcp_servers.CustomMCP] + command = "/Users/jkmr/Documents/work/coder/coder_darwin_arm64" + args = ["exp", "mcp", "server", "app-status-slug=codex"] + env = { "CODER_MCP_APP_STATUS_SLUG" = "codex", "CODER_MCP_AI_AGENTAPI_URL"= "http://localhost:3284" } + description = "Report ALL tasks and statuses (in progress, done, failed) you are working on." + enabled = true + type = "stdio" + `.trim(); const { id } = await setup({ moduleVariables: { additional_extensions: additional, @@ -195,9 +200,9 @@ describe("codex", async () => { const resp = await execContainer(id, [ "bash", "-c", - `cat /home/coder/.codex-module/agentapi-start.log || true`, + `cat /home/coder/.codex-module/agentapi-start.log`, ]); - expect(resp.stdout).toContain(`Every step of the way, report tasks to Coder with proper descriptions and statuses, when each part of the task is finished report with . Your task at hand: ${prompt}`); + expect(resp.stdout).toContain(`Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: ${prompt}`); }); test("start-without-prompt", async () => { diff --git a/registry/coder-labs/modules/codex/main.tf b/registry/coder-labs/modules/codex/main.tf index 9c2fa45c..7a871a5f 100644 --- a/registry/coder-labs/modules/codex/main.tf +++ b/registry/coder-labs/modules/codex/main.tf @@ -54,9 +54,9 @@ variable "codex_version" { default = "" } -variable "codex_settings_toml" { +variable "extra_codex_settings_toml" { type = string - description = "json to use in ~/.codex/config.toml." + description = "Settings to append to ~/.codex/config.toml." default = "" } @@ -129,7 +129,7 @@ locals { module "agentapi" { source = "registry.coder.com/coder/agentapi/coder" - version = "1.0.0" + version = "1.0.1" agent_id = var.agent_id web_app_slug = local.app_slug @@ -167,7 +167,7 @@ module "agentapi" { chmod +x /tmp/install.sh ARG_INSTALL='${var.install_codex}' \ ARG_CODEX_VERSION='${var.codex_version}' \ - ARG_CODEX_CONFIG='${base64encode(var.codex_settings_toml)}' \ + ARG_CODEX_CONFIG='${base64encode(var.extra_codex_settings_toml)}' \ CODER_MCP_APP_STATUS_SLUG='${local.app_slug}' \ ADDITIONAL_EXTENSIONS='${base64encode(var.additional_extensions)}' \ CODEX_START_DIRECTORY='${var.folder}' \ diff --git a/registry/coder-labs/modules/codex/scripts/install.sh b/registry/coder-labs/modules/codex/scripts/install.sh index 68090265..e7e843bb 100644 --- a/registry/coder-labs/modules/codex/scripts/install.sh +++ b/registry/coder-labs/modules/codex/scripts/install.sh @@ -89,12 +89,20 @@ function populate_config_toml() { CONFIG_PATH="$HOME/.codex/config.toml" mkdir -p "$(dirname "$CONFIG_PATH")" printf "Custom codex_config is provided !\n" - BASE_EXTENSIONS="[mcp_servers.Coder] - command = \"coder\" - args = [\"exp\", \"mcp\", \"server\"] - env = { \"CODER_MCP_APP_STATUS_SLUG\" = \"${CODER_MCP_APP_STATUS_SLUG}\", \"CODER_MCP_AI_AGENTAPI_URL\"= \"http://localhost:3284\", \"CODER_AGENT_URL\" = \"${CODER_AGENT_URL}\", \"CODER_AGENT_TOKEN\" = \"${CODER_AGENT_TOKEN}\" } - description = \"Report ALL tasks and statuses (in progress, done, failed) you are working on.\" - type = \"stdio\"" + BASE_EXTENSIONS=$(cat < AGENTS.md else diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh index 86a4fcda..77db1f3c 100644 --- a/registry/coder-labs/modules/codex/scripts/start.sh +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -21,7 +21,7 @@ CODEX_ARGS=("--skip-git-repo-check") if command_exists codex; then printf "Codex is installed\n" else - printf "Error: Codex is not installed. Please enable install_codex or install it manually :)\n" + printf "Error: Codex is not installed. Please enable install_codex or install it manually\n" exit 1 fi @@ -49,7 +49,7 @@ fi if [ -n "$CODEX_TASK_PROMPT" ]; then printf "Running the task prompt %s\n" "$CODEX_TASK_PROMPT" - PROMPT="Every step of the way, report tasks to Coder with proper descriptions and statuses, when each part of the task is finished report with . Your task at hand: $CODEX_TASK_PROMPT" + PROMPT="Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $CODEX_TASK_PROMPT" CODEX_ARGS+=("--dangerously-bypass-approvals-and-sandbox" "$PROMPT") else printf "No task prompt given.\n" @@ -61,8 +61,7 @@ else printf "openai_api_key not provided\n" fi -# use low width to fit in the tasks UI sidebar. height is adjusted so that width x height ~= 80x1000 characters -# are visible in the terminal screen by default. -# in case of codex we adjust the height to 930 due to a bug in codex module, see: https://github.com/openai/codex/issues/1608 +# use low width to fit in the tasks UI sidebar +# we adjust the height to 930 due to a bug in codex module, see: https://github.com/openai/codex/issues/1608 printf "Starting codex with %s\n" "${CODEX_ARGS[@]}" -agentapi server --term-width 70 --term-height 930 -- codex "${CODEX_ARGS[@]}" \ No newline at end of file +agentapi server --term-width 63 --term-height 930 -- codex "${CODEX_ARGS[@]}" \ No newline at end of file From dc154d0d0236cc294cb9c764f8a28cf5a6a4e0aa Mon Sep 17 00:00:00 2001 From: 35C4n0r Date: Tue, 5 Aug 2025 22:34:23 +0530 Subject: [PATCH 13/13] fix: apply suggestions --- .../coder-labs/modules/codex/main.test.ts | 2 +- registry/coder-labs/modules/codex/main.tf | 18 +++---- .../modules/codex/scripts/install.sh | 54 ++++++++++--------- .../coder-labs/modules/codex/scripts/start.sh | 40 ++++++++------ 4 files changed, 64 insertions(+), 50 deletions(-) diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts index 465bbf7f..c2b482d9 100644 --- a/registry/coder-labs/modules/codex/main.test.ts +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -78,7 +78,7 @@ describe("codex", async () => { }); test("install-codex-version", async () => { - const version_to_install = "1.0.0"; + const version_to_install = "0.10.0"; const { id } = await setup({ skipCodexMock: true, moduleVariables: { diff --git a/registry/coder-labs/modules/codex/main.tf b/registry/coder-labs/modules/codex/main.tf index 7a871a5f..0b9d1f33 100644 --- a/registry/coder-labs/modules/codex/main.tf +++ b/registry/coder-labs/modules/codex/main.tf @@ -151,10 +151,10 @@ module "agentapi" { echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh chmod +x /tmp/start.sh - OPENAI_API_KEY='${var.openai_api_key}' \ - CODEX_MODEL='${var.codex_model}' \ - CODEX_START_DIRECTORY='${var.folder}' \ - CODEX_TASK_PROMPT='${base64encode(var.ai_prompt)}' \ + ARG_OPENAI_API_KEY='${var.openai_api_key}' \ + ARG_CODEX_MODEL='${var.codex_model}' \ + ARG_CODEX_START_DIRECTORY='${var.folder}' \ + ARG_CODEX_TASK_PROMPT='${base64encode(var.ai_prompt)}' \ /tmp/start.sh EOT @@ -167,11 +167,11 @@ module "agentapi" { chmod +x /tmp/install.sh ARG_INSTALL='${var.install_codex}' \ ARG_CODEX_VERSION='${var.codex_version}' \ - ARG_CODEX_CONFIG='${base64encode(var.extra_codex_settings_toml)}' \ - CODER_MCP_APP_STATUS_SLUG='${local.app_slug}' \ - ADDITIONAL_EXTENSIONS='${base64encode(var.additional_extensions)}' \ - CODEX_START_DIRECTORY='${var.folder}' \ - CODEX_INSTRUCTION_PROMPT='${base64encode(var.codex_system_prompt)}' \ + ARG_EXTRA_CODEX_CONFIG='${base64encode(var.extra_codex_settings_toml)}' \ + ARG_CODER_MCP_APP_STATUS_SLUG='${local.app_slug}' \ + ARG_ADDITIONAL_EXTENSIONS='${base64encode(var.additional_extensions)}' \ + ARG_CODEX_START_DIRECTORY='${var.folder}' \ + ARG_CODEX_INSTRUCTION_PROMPT='${base64encode(var.codex_system_prompt)}' \ /tmp/install.sh EOT } \ No newline at end of file diff --git a/registry/coder-labs/modules/codex/scripts/install.sh b/registry/coder-labs/modules/codex/scripts/install.sh index e7e843bb..e9a54adc 100644 --- a/registry/coder-labs/modules/codex/scripts/install.sh +++ b/registry/coder-labs/modules/codex/scripts/install.sh @@ -9,14 +9,19 @@ command_exists() { set -o nounset -ARG_CODEX_CONFIG=$(echo -n "$ARG_CODEX_CONFIG" | base64 -d) -ADDITIONAL_EXTENSIONS=$(echo -n "$ADDITIONAL_EXTENSIONS" | base64 -d) -CODEX_INSTRUCTION_PROMPT=$(echo -n "$CODEX_INSTRUCTION_PROMPT" | base64 -d) +ARG_EXTRA_CODEX_CONFIG=$(echo -n "$ARG_EXTRA_CODEX_CONFIG" | base64 -d) +ARG_ADDITIONAL_EXTENSIONS=$(echo -n "$ARG_ADDITIONAL_EXTENSIONS" | base64 -d) +ARG_CODEX_INSTRUCTION_PROMPT=$(echo -n "$ARG_CODEX_INSTRUCTION_PROMPT" | base64 -d) echo "--------------------------------" -printf "codex_config: %s\n" "$ARG_CODEX_CONFIG" printf "install: %s\n" "$ARG_INSTALL" printf "codex_version: %s\n" "$ARG_CODEX_VERSION" +printf "codex_config: %s\n" "$ARG_EXTRA_CODEX_CONFIG" +printf "app_slug: %s\n" "$ARG_CODER_MCP_APP_STATUS_SLUG" +printf "additional_extensions: %s\n" "$ARG_ADDITIONAL_EXTENSIONS" +printf "start_directory: %s\n" "$ARG_CODEX_START_DIRECTORY" +printf "instruction_prompt: %s\n" "$ARG_CODEX_INSTRUCTION_PROMPT" + echo "--------------------------------" set +o nounset @@ -93,48 +98,49 @@ function populate_config_toml() { [mcp_servers.Coder] command = "coder" args = ["exp", "mcp", "server"] -env = { - "CODER_MCP_APP_STATUS_SLUG" = "${CODER_MCP_APP_STATUS_SLUG}", - "CODER_MCP_AI_AGENTAPI_URL"= "http://localhost:3284", - "CODER_AGENT_URL" = "${CODER_AGENT_URL}", - "CODER_AGENT_TOKEN" = "${CODER_AGENT_TOKEN}" -} +env = { "CODER_MCP_APP_STATUS_SLUG" = "${ARG_CODER_MCP_APP_STATUS_SLUG}", "CODER_MCP_AI_AGENTAPI_URL"= "http://localhost:3284", "CODER_AGENT_URL" = "${CODER_AGENT_URL}", "CODER_AGENT_TOKEN" = "${CODER_AGENT_TOKEN}" } description = "Report ALL tasks and statuses (in progress, done, failed) you are working on." type = "stdio" EOF ) echo " -${ARG_CODEX_CONFIG} +${ARG_EXTRA_CODEX_CONFIG} ${BASE_EXTENSIONS} -${ADDITIONAL_EXTENSIONS} +${ARG_ADDITIONAL_EXTENSIONS} " > "$HOME/.codex/config.toml" } function add_instruction_prompt_if_exists() { - if [ -n "${CODEX_INSTRUCTION_PROMPT:-}" ]; then - if [ -d "${CODEX_START_DIRECTORY}" ]; then - printf "Directory '%s' exists. Changing to it.\\n" "${CODEX_START_DIRECTORY}" - cd "${CODEX_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + if [ -n "${ARG_CODEX_INSTRUCTION_PROMPT:-}" ]; then + if [ -d "${ARG_CODEX_START_DIRECTORY}" ]; then + printf "Directory '%s' exists. Changing to it.\\n" "${ARG_CODEX_START_DIRECTORY}" + cd "${ARG_CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${ARG_CODEX_START_DIRECTORY}" exit 1 } else - printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${CODEX_START_DIRECTORY}" - mkdir -p "${CODEX_START_DIRECTORY}" || { - printf "Error: Could not create directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${ARG_CODEX_START_DIRECTORY}" + mkdir -p "${ARG_CODEX_START_DIRECTORY}" || { + printf "Error: Could not create directory '%s'.\\n" "${ARG_CODEX_START_DIRECTORY}" exit 1 } - cd "${CODEX_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + cd "${ARG_CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${ARG_CODEX_START_DIRECTORY}" exit 1 } fi - printf "Setting AGENTS.md\n" - echo "${CODEX_INSTRUCTION_PROMPT}" > AGENTS.md + + # Check if AGENTS.md contains the instruction prompt already + if [ -f AGENTS.md ] && grep -Fxq "${ARG_CODEX_INSTRUCTION_PROMPT}" AGENTS.md; then + printf "AGENTS.md already contains the instruction prompt. Skipping append.\n" + else + printf "Appending instruction prompt to AGENTS.md\n" + echo -e "\n${ARG_CODEX_INSTRUCTION_PROMPT}" >> AGENTS.md + fi else printf "AGENTS.md is not set.\n" fi diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh index 77db1f3c..833a26dd 100644 --- a/registry/coder-labs/modules/codex/scripts/start.sh +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -15,7 +15,15 @@ fi printf "Version: %s\n" "$(codex --version)" -CODEX_TASK_PROMPT=$(echo -n "$CODEX_TASK_PROMPT" | base64 -d) +ARG_CODEX_TASK_PROMPT=$(echo -n "$ARG_CODEX_TASK_PROMPT" | base64 -d) + +echo "--------------------------------" +printf "openai_api_key: %s\n" "$ARG_OPENAI_API_KEY" +printf "codex_model: %s\n" "$ARG_CODEX_MODEL" +printf "start_directory: %s\n" "$ARG_CODEX_START_DIRECTORY" +printf "task_prompt: %s\n" "$ARG_CODEX_TASK_PROMPT" +echo "--------------------------------" + CODEX_ARGS=("--skip-git-repo-check") if command_exists codex; then @@ -25,37 +33,37 @@ else exit 1 fi -if [ -d "${CODEX_START_DIRECTORY}" ]; then - printf "Directory '%s' exists. Changing to it.\\n" "${CODEX_START_DIRECTORY}" - cd "${CODEX_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${CODEX_START_DIRECTORY}" +if [ -d "${ARG_CODEX_START_DIRECTORY}" ]; then + printf "Directory '%s' exists. Changing to it.\\n" "${ARG_CODEX_START_DIRECTORY}" + cd "${ARG_CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${ARG_CODEX_START_DIRECTORY}" exit 1 } else - printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${CODEX_START_DIRECTORY}" - mkdir -p "${CODEX_START_DIRECTORY}" || { - printf "Error: Could not create directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${ARG_CODEX_START_DIRECTORY}" + mkdir -p "${ARG_CODEX_START_DIRECTORY}" || { + printf "Error: Could not create directory '%s'.\\n" "${ARG_CODEX_START_DIRECTORY}" exit 1 } - cd "${CODEX_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${CODEX_START_DIRECTORY}" + cd "${ARG_CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${ARG_CODEX_START_DIRECTORY}" exit 1 } fi -if [ -n "$CODEX_MODEL" ]; then - CODEX_ARGS+=("--model" "$CODEX_MODEL") +if [ -n "$ARG_CODEX_MODEL" ]; then + CODEX_ARGS+=("--model" "$ARG_CODEX_MODEL") fi -if [ -n "$CODEX_TASK_PROMPT" ]; then - printf "Running the task prompt %s\n" "$CODEX_TASK_PROMPT" - PROMPT="Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $CODEX_TASK_PROMPT" +if [ -n "$ARG_CODEX_TASK_PROMPT" ]; then + printf "Running the task prompt %s\n" "$ARG_CODEX_TASK_PROMPT" + PROMPT="Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $ARG_CODEX_TASK_PROMPT" CODEX_ARGS+=("--dangerously-bypass-approvals-and-sandbox" "$PROMPT") else printf "No task prompt given.\n" fi -if [ -n "$OPENAI_API_KEY" ]; then +if [ -n "$ARG_OPENAI_API_KEY" ]; then printf "openai_api_key provided !\n" else printf "openai_api_key not provided\n"