From 52a60b7333ee1c0505765bf36d8ed62e72540cc1 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 23 Oct 2025 13:43:32 -0500 Subject: [PATCH 1/6] feat: add session resumption feature to codex module --- registry/coder-labs/modules/codex/README.md | 1 + .../coder-labs/modules/codex/main.test.ts | 31 +++ registry/coder-labs/modules/codex/main.tf | 7 + .../coder-labs/modules/codex/scripts/start.sh | 208 ++++++++++++++---- 4 files changed, 207 insertions(+), 40 deletions(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index 9c749229f..be2e7343c 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -84,6 +84,7 @@ module "codex" { - **System Prompt**: If `codex_system_prompt` is set, writes the prompt to `AGENTS.md` in the `~/.codex/` directory - **Start**: Launches Codex CLI in the specified directory, wrapped by AgentAPI - **Configuration**: Sets `OPENAI_API_KEY` environment variable and passes `--model` flag to Codex CLI (if variables provided) +- **Session Continuity**: When `continue = true` (default), the module automatically tracks task sessions `~/.codex/.codex-task-session`. On workspace restart, it resumes the existing session with full conversation history. Set `continue = false` to always start fresh sessions. ## Configuration diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts index 7d34a9c43..8a2ab6779 100644 --- a/registry/coder-labs/modules/codex/main.test.ts +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -368,4 +368,35 @@ describe("codex", async () => { expect(prompt.exitCode).not.toBe(0); expect(prompt.stderr).toContain("No such file or directory"); }); + + test("codex-continue-resume-existing-session", async () => { + const { id } = await setup({ + moduleVariables: { + continue: "true", + ai_prompt: "test prompt", + }, + }); + + const workdir = "/home/coder"; + const mockSessionId = "019a1234-5678-9abc-def0-123456789012"; + const trackingFile = "/home/coder/.codex/.codex-task-session"; + + await execContainer(id, ["mkdir", "-p", "/home/coder/.codex"]); + await execContainer(id, [ + "bash", + "-c", + `echo "${workdir}|${mockSessionId}" > ${trackingFile}`, + ]); + + await execModuleScript(id); + + const startLog = await execContainer(id, [ + "bash", + "-c", + "cat /home/coder/.codex-module/agentapi-start.log", + ]); + expect(startLog.stdout).toContain("Found existing task session"); + expect(startLog.stdout).toContain(mockSessionId); + expect(startLog.stdout).toContain("Resuming existing session"); + }); }); diff --git a/registry/coder-labs/modules/codex/main.tf b/registry/coder-labs/modules/codex/main.tf index d181c10f5..81746833b 100644 --- a/registry/coder-labs/modules/codex/main.tf +++ b/registry/coder-labs/modules/codex/main.tf @@ -137,6 +137,12 @@ variable "ai_prompt" { default = "" } +variable "continue" { + type = bool + description = "Automatically continue existing sessions on workspace restart. When true, resumes existing conversation if found, otherwise runs prompt or starts new session. When false, always starts fresh (ignores existing sessions)." + default = true +} + variable "codex_system_prompt" { type = string description = "System instructions written to AGENTS.md in the ~/.codex directory" @@ -189,6 +195,7 @@ module "agentapi" { ARG_CODEX_MODEL='${var.codex_model}' \ ARG_CODEX_START_DIRECTORY='${var.workdir}' \ ARG_CODEX_TASK_PROMPT='${base64encode(var.ai_prompt)}' \ + ARG_CONTINUE='${var.continue}' \ /tmp/start.sh EOT diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh index be54d5755..5b7d5df1c 100644 --- a/registry/coder-labs/modules/codex/scripts/start.sh +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -3,6 +3,7 @@ source "$HOME"/.bashrc set -o errexit set -o pipefail + command_exists() { command -v "$1" > /dev/null 2>&1 } @@ -16,6 +17,7 @@ fi printf "Version: %s\n" "$(codex --version)" set -o nounset ARG_CODEX_TASK_PROMPT=$(echo -n "$ARG_CODEX_TASK_PROMPT" | base64 -d) +ARG_CONTINUE=${ARG_CONTINUE:-true} echo "=== Codex Launch Configuration ===" printf "OpenAI API Key: %s\n" "$([ -n "$ARG_OPENAI_API_KEY" ] && echo "Provided" || echo "Not provided")" @@ -23,53 +25,179 @@ printf "Codex Model: %s\n" "${ARG_CODEX_MODEL:-"Default"}" printf "Start Directory: %s\n" "$ARG_CODEX_START_DIRECTORY" printf "Has Task Prompt: %s\n" "$([ -n "$ARG_CODEX_TASK_PROMPT" ] && echo "Yes" || echo "No")" printf "Report Tasks: %s\n" "$ARG_REPORT_TASKS" +printf "Continue Sessions: %s\n" "$ARG_CONTINUE" echo "======================================" set +o nounset -CODEX_ARGS=() -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 +SESSION_TRACKING_FILE="$HOME/.codex/.codex-task-session" -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" "${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 "${ARG_CODEX_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${ARG_CODEX_START_DIRECTORY}" +find_session_for_directory() { + local target_dir="$1" + + if [ ! -f "$SESSION_TRACKING_FILE" ]; then + return 1 + fi + + local session_id=$(grep "^$target_dir|" "$SESSION_TRACKING_FILE" | cut -d'|' -f2 | head -1) + + if [ -n "$session_id" ]; then + echo "$session_id" + return 0 + fi + + return 1 +} + +store_session_mapping() { + local dir="$1" + local session_id="$2" + + mkdir -p "$(dirname "$SESSION_TRACKING_FILE")" + + if [ -f "$SESSION_TRACKING_FILE" ]; then + grep -v "^$dir|" "$SESSION_TRACKING_FILE" > "$SESSION_TRACKING_FILE.tmp" 2> /dev/null || true + mv "$SESSION_TRACKING_FILE.tmp" "$SESSION_TRACKING_FILE" + fi + + echo "$dir|$session_id" >> "$SESSION_TRACKING_FILE" +} + +find_recent_session_file() { + local target_dir="$1" + local sessions_dir="$HOME/.codex/sessions" + + if [ ! -d "$sessions_dir" ]; then + return 1 + fi + + local latest_file="" + local latest_time=0 + + while IFS= read -r session_file; do + local file_time=$(stat -c %Y "$session_file" 2> /dev/null || stat -f %m "$session_file" 2> /dev/null || echo "0") + local first_line=$(head -n 1 "$session_file" 2> /dev/null) + local session_cwd=$(echo "$first_line" | grep -o '"cwd":"[^"]*"' | cut -d'"' -f4) + + if [ "$session_cwd" = "$target_dir" ] && [ "$file_time" -gt "$latest_time" ]; then + latest_file="$session_file" + latest_time="$file_time" + fi + done < <(find "$sessions_dir" -type f -name "*.jsonl" -mmin -2 2> /dev/null) + + if [ -n "$latest_file" ]; then + local first_line=$(head -n 1 "$latest_file") + local session_id=$(echo "$first_line" | grep -o '"id":"[^"]*"' | cut -d'"' -f4) + if [ -n "$session_id" ]; then + echo "$session_id" + return 0 + fi + fi + + return 1 +} + +validate_codex_installation() { + 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 + fi +} -if [ -n "$ARG_CODEX_MODEL" ]; then - CODEX_ARGS+=("--model" "$ARG_CODEX_MODEL") -fi +setup_workdir() { + 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" "${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 "${ARG_CODEX_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${ARG_CODEX_START_DIRECTORY}" + exit 1 + } + fi +} + +build_codex_args() { + CODEX_ARGS=() + + if [ -n "$ARG_CODEX_MODEL" ]; then + CODEX_ARGS+=("--model" "$ARG_CODEX_MODEL") + fi -if [ -n "$ARG_CODEX_TASK_PROMPT" ]; then - printf "Running the task prompt %s\n" "$ARG_CODEX_TASK_PROMPT" - if [ "${ARG_REPORT_TASKS}" == "true" ]; then - PROMPT="Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_CODEX_TASK_PROMPT" + if [ "$ARG_CONTINUE" = "true" ]; then + existing_session=$(find_session_for_directory "$ARG_CODEX_START_DIRECTORY" 2> /dev/null || echo "") + + if [ -n "$existing_session" ]; then + printf "Found existing task session for this directory: %s\n" "$existing_session" + printf "Resuming existing session...\n" + CODEX_ARGS+=("resume" "$existing_session") + + if [ -n "$ARG_CODEX_TASK_PROMPT" ]; then + if [ "${ARG_REPORT_TASKS}" == "true" ]; then + PROMPT="Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_CODEX_TASK_PROMPT" + else + PROMPT="Your task at hand: $ARG_CODEX_TASK_PROMPT" + fi + CODEX_ARGS+=("$PROMPT") + fi + else + printf "No existing task session found for this directory\n" + printf "Starting new task session...\n" + + if [ -n "$ARG_CODEX_TASK_PROMPT" ]; then + if [ "${ARG_REPORT_TASKS}" == "true" ]; then + PROMPT="Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_CODEX_TASK_PROMPT" + else + PROMPT="Your task at hand: $ARG_CODEX_TASK_PROMPT" + fi + CODEX_ARGS+=("$PROMPT") + fi + fi else - PROMPT="Your task at hand: $ARG_CODEX_TASK_PROMPT" + printf "Continue disabled, starting fresh session\n" + + if [ -n "$ARG_CODEX_TASK_PROMPT" ]; then + if [ "${ARG_REPORT_TASKS}" == "true" ]; then + PROMPT="Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_CODEX_TASK_PROMPT" + else + PROMPT="Your task at hand: $ARG_CODEX_TASK_PROMPT" + fi + CODEX_ARGS+=("$PROMPT") + fi fi - CODEX_ARGS+=("$PROMPT") -else - printf "No task prompt given.\n" -fi +} + +capture_session_id() { + if [ "$ARG_CONTINUE" = "true" ] && [ -z "$existing_session" ]; then + printf "Capturing new session ID...\n" + new_session=$(find_recent_session_file "$ARG_CODEX_START_DIRECTORY" 2> /dev/null || echo "") + + if [ -n "$new_session" ]; then + store_session_mapping "$ARG_CODEX_START_DIRECTORY" "$new_session" + printf "✓ Session tracked: %s\n" "$new_session" + printf "This session will be automatically resumed on next restart\n" + else + printf "⚠ Could not capture session ID automatically\n" + fi + fi +} + +start_codex() { + printf "Starting Codex with arguments: %s\n" "${CODEX_ARGS[*]}" + agentapi server --term-width 67 --term-height 1190 -- codex "${CODEX_ARGS[@]}" & + sleep 3 + capture_session_id +} -# Terminal dimensions optimized for Coder Tasks UI sidebar: -# - Width 67: fits comfortably in sidebar -# - Height 1190: adjusted due to Codex terminal height bug -printf "Starting Codex with arguments: %s\n" "${CODEX_ARGS[*]}" -agentapi server --term-width 67 --term-height 1190 -- codex "${CODEX_ARGS[@]}" +validate_codex_installation +setup_workdir +build_codex_args +start_codex From f1355eaf485394bcefd67389f7b7d9d2aa0c22f9 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 23 Oct 2025 14:01:16 -0500 Subject: [PATCH 2/6] fix: update codex module to use local.workdir for start directory --- registry/coder-labs/modules/codex/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/coder-labs/modules/codex/main.tf b/registry/coder-labs/modules/codex/main.tf index 81746833b..a68cd79fe 100644 --- a/registry/coder-labs/modules/codex/main.tf +++ b/registry/coder-labs/modules/codex/main.tf @@ -193,7 +193,7 @@ module "agentapi" { ARG_OPENAI_API_KEY='${var.openai_api_key}' \ ARG_REPORT_TASKS='${var.report_tasks}' \ ARG_CODEX_MODEL='${var.codex_model}' \ - ARG_CODEX_START_DIRECTORY='${var.workdir}' \ + ARG_CODEX_START_DIRECTORY='${local.workdir}' \ ARG_CODEX_TASK_PROMPT='${base64encode(var.ai_prompt)}' \ ARG_CONTINUE='${var.continue}' \ /tmp/start.sh @@ -213,7 +213,7 @@ module "agentapi" { ARG_BASE_CONFIG_TOML='${base64encode(var.base_config_toml)}' \ ARG_ADDITIONAL_MCP_SERVERS='${base64encode(var.additional_mcp_servers)}' \ ARG_CODER_MCP_APP_STATUS_SLUG='${local.app_slug}' \ - ARG_CODEX_START_DIRECTORY='${var.workdir}' \ + ARG_CODEX_START_DIRECTORY='${local.workdir}' \ ARG_CODEX_INSTRUCTION_PROMPT='${base64encode(var.codex_system_prompt)}' \ /tmp/install.sh EOT From 628c7df424279ff4703dd2976bab2d15528f86bb Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 23 Oct 2025 14:19:20 -0500 Subject: [PATCH 3/6] test: remove prompt from when session resumption --- registry/coder-labs/modules/codex/README.md | 2 +- registry/coder-labs/modules/codex/main.test.ts | 2 ++ registry/coder-labs/modules/codex/scripts/start.sh | 9 --------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index be2e7343c..c08beaaa1 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -84,7 +84,7 @@ module "codex" { - **System Prompt**: If `codex_system_prompt` is set, writes the prompt to `AGENTS.md` in the `~/.codex/` directory - **Start**: Launches Codex CLI in the specified directory, wrapped by AgentAPI - **Configuration**: Sets `OPENAI_API_KEY` environment variable and passes `--model` flag to Codex CLI (if variables provided) -- **Session Continuity**: When `continue = true` (default), the module automatically tracks task sessions `~/.codex/.codex-task-session`. On workspace restart, it resumes the existing session with full conversation history. Set `continue = false` to always start fresh sessions. +- **Session Continuity**: When `continue = true` (default), the module automatically tracks task sessions in `~/.codex/.codex-task-session`. On workspace restart, it resumes the existing session with full conversation history. Set `continue = false` to always start fresh sessions. ## Configuration diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts index 8a2ab6779..5e02af2f6 100644 --- a/registry/coder-labs/modules/codex/main.test.ts +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -398,5 +398,7 @@ describe("codex", async () => { expect(startLog.stdout).toContain("Found existing task session"); expect(startLog.stdout).toContain(mockSessionId); expect(startLog.stdout).toContain("Resuming existing session"); + expect(startLog.stdout).toContain(`Starting Codex with arguments: --model gpt-4-turbo resume ${mockSessionId}`); + expect(startLog.stdout).not.toContain("test prompt"); }); }); diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh index 5b7d5df1c..dda805f72 100644 --- a/registry/coder-labs/modules/codex/scripts/start.sh +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -139,15 +139,6 @@ build_codex_args() { printf "Found existing task session for this directory: %s\n" "$existing_session" printf "Resuming existing session...\n" CODEX_ARGS+=("resume" "$existing_session") - - if [ -n "$ARG_CODEX_TASK_PROMPT" ]; then - if [ "${ARG_REPORT_TASKS}" == "true" ]; then - PROMPT="Complete the task at hand in one go. Every step of the way, report your progress using coder_report_task tool with proper summary and statuses. Your task at hand: $ARG_CODEX_TASK_PROMPT" - else - PROMPT="Your task at hand: $ARG_CODEX_TASK_PROMPT" - fi - CODEX_ARGS+=("$PROMPT") - fi else printf "No existing task session found for this directory\n" printf "Starting new task session...\n" From bc8a4cfe0b9423bb4775c367249cb8c222b9294c Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 23 Oct 2025 14:32:11 -0500 Subject: [PATCH 4/6] chore: update codex module version to 3.1.0 --- registry/coder-labs/modules/codex/README.md | 8 ++++---- registry/coder-labs/modules/codex/main.test.ts | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index c08beaaa1..01acf738d 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -13,7 +13,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" - version = "3.0.0" + version = "3.1.0" agent_id = coder_agent.example.id openai_api_key = var.openai_api_key workdir = "/home/coder/project" @@ -33,7 +33,7 @@ module "codex" { module "codex" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder-labs/codex/coder" - version = "3.0.0" + version = "3.1.0" agent_id = coder_agent.example.id openai_api_key = "..." workdir = "/home/coder/project" @@ -61,7 +61,7 @@ module "coder-login" { module "codex" { source = "registry.coder.com/coder-labs/codex/coder" - version = "3.0.0" + version = "3.1.0" agent_id = coder_agent.example.id openai_api_key = "..." ai_prompt = data.coder_parameter.ai_prompt.value @@ -108,7 +108,7 @@ For custom Codex configuration, use `base_config_toml` and/or `additional_mcp_se ```tf module "codex" { source = "registry.coder.com/coder-labs/codex/coder" - version = "3.0.0" + version = "3.1.0" # ... other variables ... # Override default configuration diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts index 5e02af2f6..c400a2f61 100644 --- a/registry/coder-labs/modules/codex/main.test.ts +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -398,7 +398,9 @@ describe("codex", async () => { expect(startLog.stdout).toContain("Found existing task session"); expect(startLog.stdout).toContain(mockSessionId); expect(startLog.stdout).toContain("Resuming existing session"); - expect(startLog.stdout).toContain(`Starting Codex with arguments: --model gpt-4-turbo resume ${mockSessionId}`); + expect(startLog.stdout).toContain( + `Starting Codex with arguments: --model gpt-4-turbo resume ${mockSessionId}`, + ); expect(startLog.stdout).not.toContain("test prompt"); }); }); From 5819331249f866b7b3ff61e6fbdfbcd0d3354060 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 23 Oct 2025 14:57:39 -0500 Subject: [PATCH 5/6] feat: add wait_for_session_file function to improve session handling in codex module --- .../coder-labs/modules/codex/scripts/start.sh | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh index dda805f72..675fadada 100644 --- a/registry/coder-labs/modules/codex/scripts/start.sh +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -82,7 +82,7 @@ find_recent_session_file() { latest_file="$session_file" latest_time="$file_time" fi - done < <(find "$sessions_dir" -type f -name "*.jsonl" -mmin -2 2> /dev/null) + done < <(find "$sessions_dir" -type f -name "*.jsonl" 2> /dev/null) if [ -n "$latest_file" ]; then local first_line=$(head -n 1 "$latest_file") @@ -96,6 +96,24 @@ find_recent_session_file() { return 1 } +wait_for_session_file() { + local target_dir="$1" + local max_attempts=20 + local attempt=0 + + while [ $attempt -lt $max_attempts ]; do + local session_id=$(find_recent_session_file "$target_dir" 2> /dev/null || echo "") + if [ -n "$session_id" ]; then + echo "$session_id" + return 0 + fi + sleep 0.5 + attempt=$((attempt + 1)) + done + + return 1 +} + validate_codex_installation() { if command_exists codex; then printf "Codex is installed\n" @@ -169,14 +187,14 @@ build_codex_args() { capture_session_id() { if [ "$ARG_CONTINUE" = "true" ] && [ -z "$existing_session" ]; then printf "Capturing new session ID...\n" - new_session=$(find_recent_session_file "$ARG_CODEX_START_DIRECTORY" 2> /dev/null || echo "") + new_session=$(wait_for_session_file "$ARG_CODEX_START_DIRECTORY" || echo "") if [ -n "$new_session" ]; then store_session_mapping "$ARG_CODEX_START_DIRECTORY" "$new_session" printf "✓ Session tracked: %s\n" "$new_session" printf "This session will be automatically resumed on next restart\n" else - printf "⚠ Could not capture session ID automatically\n" + printf "⚠ Could not capture session ID after 10s timeout\n" fi fi } @@ -184,7 +202,6 @@ capture_session_id() { start_codex() { printf "Starting Codex with arguments: %s\n" "${CODEX_ARGS[*]}" agentapi server --term-width 67 --term-height 1190 -- codex "${CODEX_ARGS[@]}" & - sleep 3 capture_session_id } From 00ef582abbbf5923a5769f10ac0cac92bce497e9 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Fri, 24 Oct 2025 15:33:54 -0500 Subject: [PATCH 6/6] chore: move session tracking and add test for capture logic --- registry/coder-labs/modules/codex/README.md | 2 +- .../coder-labs/modules/codex/main.test.ts | 55 ++++++++++++++++++- .../coder-labs/modules/codex/scripts/start.sh | 2 +- .../modules/codex/testdata/codex-mock.sh | 26 ++++++++- 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/registry/coder-labs/modules/codex/README.md b/registry/coder-labs/modules/codex/README.md index 01acf738d..980623262 100644 --- a/registry/coder-labs/modules/codex/README.md +++ b/registry/coder-labs/modules/codex/README.md @@ -84,7 +84,7 @@ module "codex" { - **System Prompt**: If `codex_system_prompt` is set, writes the prompt to `AGENTS.md` in the `~/.codex/` directory - **Start**: Launches Codex CLI in the specified directory, wrapped by AgentAPI - **Configuration**: Sets `OPENAI_API_KEY` environment variable and passes `--model` flag to Codex CLI (if variables provided) -- **Session Continuity**: When `continue = true` (default), the module automatically tracks task sessions in `~/.codex/.codex-task-session`. On workspace restart, it resumes the existing session with full conversation history. Set `continue = false` to always start fresh sessions. +- **Session Continuity**: When `continue = true` (default), the module automatically tracks task sessions in `~/.codex-module/.codex-task-session`. On workspace restart, it resumes the existing session with full conversation history. Set `continue = false` to always start fresh sessions. ## Configuration diff --git a/registry/coder-labs/modules/codex/main.test.ts b/registry/coder-labs/modules/codex/main.test.ts index c400a2f61..2041e36e6 100644 --- a/registry/coder-labs/modules/codex/main.test.ts +++ b/registry/coder-labs/modules/codex/main.test.ts @@ -369,6 +369,57 @@ describe("codex", async () => { expect(prompt.stderr).toContain("No such file or directory"); }); + test("codex-continue-capture-new-session", async () => { + const { id } = await setup({ + moduleVariables: { + continue: "true", + ai_prompt: "test task", + }, + }); + + const workdir = "/home/coder"; + const expectedSessionId = "019a1234-5678-9abc-def0-123456789012"; + const sessionsDir = "/home/coder/.codex/sessions"; + const sessionFile = `${sessionsDir}/${expectedSessionId}.jsonl`; + + await execContainer(id, ["mkdir", "-p", sessionsDir]); + await execContainer(id, [ + "bash", + "-c", + `echo '{"id":"${expectedSessionId}","cwd":"${workdir}","created":"2024-10-24T20:00:00Z","model":"gpt-4-turbo"}' > ${sessionFile}`, + ]); + + await execModuleScript(id); + + await expectAgentAPIStarted(id); + + const trackingFile = "/home/coder/.codex-module/.codex-task-session"; + const maxAttempts = 30; + let trackingFileContents = ""; + for (let attempt = 0; attempt < maxAttempts; attempt++) { + const result = await execContainer(id, [ + "bash", + "-c", + `cat ${trackingFile} 2>/dev/null || echo ""`, + ]); + if (result.stdout.trim().length > 0) { + trackingFileContents = result.stdout; + break; + } + await new Promise((resolve) => setTimeout(resolve, 500)); + } + + expect(trackingFileContents).toContain(`${workdir}|${expectedSessionId}`); + + const startLog = await readFileContainer( + id, + "/home/coder/.codex-module/agentapi-start.log", + ); + expect(startLog).toContain("Capturing new session ID"); + expect(startLog).toContain("Session tracked"); + expect(startLog).toContain(expectedSessionId); + }); + test("codex-continue-resume-existing-session", async () => { const { id } = await setup({ moduleVariables: { @@ -379,9 +430,9 @@ describe("codex", async () => { const workdir = "/home/coder"; const mockSessionId = "019a1234-5678-9abc-def0-123456789012"; - const trackingFile = "/home/coder/.codex/.codex-task-session"; + const trackingFile = "/home/coder/.codex-module/.codex-task-session"; - await execContainer(id, ["mkdir", "-p", "/home/coder/.codex"]); + await execContainer(id, ["mkdir", "-p", "/home/coder/.codex-module"]); await execContainer(id, [ "bash", "-c", diff --git a/registry/coder-labs/modules/codex/scripts/start.sh b/registry/coder-labs/modules/codex/scripts/start.sh index 675fadada..663e80e50 100644 --- a/registry/coder-labs/modules/codex/scripts/start.sh +++ b/registry/coder-labs/modules/codex/scripts/start.sh @@ -29,7 +29,7 @@ printf "Continue Sessions: %s\n" "$ARG_CONTINUE" echo "======================================" set +o nounset -SESSION_TRACKING_FILE="$HOME/.codex/.codex-task-session" +SESSION_TRACKING_FILE="$HOME/.codex-module/.codex-task-session" find_session_for_directory() { local target_dir="$1" diff --git a/registry/coder-labs/modules/codex/testdata/codex-mock.sh b/registry/coder-labs/modules/codex/testdata/codex-mock.sh index 8c1c7366d..fe8f3806c 100644 --- a/registry/coder-labs/modules/codex/testdata/codex-mock.sh +++ b/registry/coder-labs/modules/codex/testdata/codex-mock.sh @@ -1,5 +1,6 @@ #!/bin/bash +# Handle --version flag if [[ "$1" == "--version" ]]; then echo "HELLO: $(bash -c env)" echo "codex version v1.0.0" @@ -8,7 +9,30 @@ fi set -e +SESSION_ID="" +IS_RESUME=false + +while [[ $# -gt 0 ]]; do + case $1 in + resume) + IS_RESUME=true + SESSION_ID="$2" + shift 2 + ;; + *) + shift + ;; + esac +done + +if [ "$IS_RESUME" = false ]; then + SESSION_ID="019a1234-5678-9abc-def0-123456789012" + echo "Created new session: $SESSION_ID" +else + echo "Resuming session: $SESSION_ID" +fi + while true; do - echo "$(date) - codex-mock" + echo "$(date) - codex-mock (session: $SESSION_ID)" sleep 15 done