refactor(input): bake codex cli runtime
This commit is contained in:
@@ -20,13 +20,13 @@ cd input/Docker
|
||||
./run-input-processor.sh up -d
|
||||
```
|
||||
|
||||
Environment variables you can pass before the command:
|
||||
- `CODEX_COMMAND_TEMPLATE` – override the Codex CLI invocation for the resume customization run (defaults to `codex prompt --input {prompt} --output {output} --format markdown`).
|
||||
- `CODEX_NORMALIZER_COMMAND_TEMPLATE` – optional override for the job-description normalization run (defaults to the same value as `CODEX_COMMAND_TEMPLATE`).
|
||||
- Environment variables you can pass before the command:
|
||||
- `POLL_INTERVAL_SECONDS` – watcher polling cadence (default `5`).
|
||||
- `CODEX_TIMEOUT_SECONDS` – hard timeout for Codex calls (default `600`).
|
||||
- `CODEX_CONFIG_DIR` – optional override for the host directory that should mount into `/home/codex/.codex`.
|
||||
|
||||
The container bundles the Codex CLI and expects the caller to mount their `~/.codex` directory for credentials.
|
||||
|
||||
Stop or inspect the stack with:
|
||||
|
||||
```bash
|
||||
@@ -44,4 +44,4 @@ cd input/Docker
|
||||
## Troubleshooting
|
||||
- If Codex CLI fails, the job description moves to `ForCustomizing/failed/`. Check container logs, adjust the Markdown, then requeue it.
|
||||
- Fatal errors (multiple resumes, multiple job descriptions, missing template, or missing Codex binary) stop the container. Resolve the issue and restart via the wrapper.
|
||||
- To change the Codex command format, pass a quoted template (e.g., `CODEX_COMMAND_TEMPLATE='codex run --input {prompt} --output {output}' ./run-input-processor.sh up -d'`). The template must include `{prompt}` and `{output}` placeholders.
|
||||
- The watcher logs the exact `codex prompt --input … --output … --format markdown` command before each invocation; inspect container logs if troubleshooting is needed.
|
||||
|
||||
@@ -15,7 +15,9 @@ RUN apt-get update \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN npm install --location=global codex-cli || true
|
||||
# Install the official Codex CLI so the container can invoke `codex prompt`.
|
||||
# The CLI expects credentials/configuration from the mounted ~/.codex directory.
|
||||
RUN npm install --location=global @openai/codex
|
||||
|
||||
RUN groupadd -r codex && \
|
||||
useradd -r -m -g codex -s /bin/bash codex
|
||||
|
||||
@@ -12,8 +12,6 @@ services:
|
||||
PGID: "${LOCAL_GID:-1000}"
|
||||
POLL_INTERVAL_SECONDS: "${POLL_INTERVAL_SECONDS:-5}"
|
||||
CODEX_TIMEOUT_SECONDS: "${CODEX_TIMEOUT_SECONDS:-600}"
|
||||
CODEX_COMMAND_TEMPLATE: "${CODEX_COMMAND_TEMPLATE:-codex prompt --input {prompt} --output {output} --format markdown}"
|
||||
CODEX_NORMALIZER_COMMAND_TEMPLATE: "${CODEX_NORMALIZER_COMMAND_TEMPLATE:-codex prompt --input {prompt} --output {output} --format markdown}"
|
||||
volumes:
|
||||
- ../ForCustomizing/inbox:/workspace/inbox
|
||||
- ../ForCustomizing/outbox:/workspace/outbox
|
||||
@@ -22,3 +20,4 @@ services:
|
||||
- ../resume:/workspace/resume:ro
|
||||
- ../templates:/templates:ro
|
||||
- ${CODEX_CONFIG_DIR:-/workspace/.codex}:/home/codex/.codex
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
||||
@@ -13,7 +13,6 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
@@ -32,17 +31,9 @@ TEMPLATES_DIR = Path("/templates")
|
||||
TEMPLATE_CACHE = Path("/tmp/templates")
|
||||
PROMPT_TEMPLATE = TEMPLATES_DIR / "ResumeCustomizerPrompt.md"
|
||||
PROMPT_TEMPLATE_EXAMPLE = TEMPLATES_DIR / "ResumeCustomizerPrompt.md.example"
|
||||
NORMALIZER_TEMPLATE = Path('/app/JobDescriptionNormalizerPrompt.md')
|
||||
NORMALIZER_TEMPLATE = Path("/app/JobDescriptionNormalizerPrompt.md")
|
||||
|
||||
POLL_INTERVAL_SECONDS = int(os.environ.get("POLL_INTERVAL_SECONDS", "5"))
|
||||
CODEX_COMMAND_TEMPLATE = os.environ.get(
|
||||
"CODEX_COMMAND_TEMPLATE",
|
||||
"codex prompt --input {prompt} --output {output} --format markdown",
|
||||
)
|
||||
CODEX_NORMALIZER_COMMAND_TEMPLATE = os.environ.get(
|
||||
"CODEX_NORMALIZER_COMMAND_TEMPLATE",
|
||||
CODEX_COMMAND_TEMPLATE,
|
||||
)
|
||||
CODEX_TIMEOUT_SECONDS = int(os.environ.get("CODEX_TIMEOUT_SECONDS", "600"))
|
||||
|
||||
RESOLVED_PROMPT_TEMPLATE: Path | None = None
|
||||
@@ -193,20 +184,19 @@ def slugify(component: str) -> str:
|
||||
return "-".join(parts)
|
||||
|
||||
|
||||
def run_codex(prompt_path: Path, output_path: Path, command_template: str) -> None:
|
||||
"""Execute the Codex CLI using the provided command template."""
|
||||
command_text = command_template.format(
|
||||
prompt=str(prompt_path),
|
||||
output=str(output_path),
|
||||
)
|
||||
logging.info("Running Codex CLI command: %s", command_text)
|
||||
|
||||
try:
|
||||
command = shlex.split(command_text)
|
||||
except ValueError as exc:
|
||||
raise FatalConfigurationError(
|
||||
f"Unable to parse Codex command template into arguments: {exc}"
|
||||
) from exc
|
||||
def run_codex(prompt_path: Path, output_path: Path) -> None:
|
||||
"""Execute the Codex CLI."""
|
||||
command = [
|
||||
"codex",
|
||||
"prompt",
|
||||
"--input",
|
||||
str(prompt_path),
|
||||
"--output",
|
||||
str(output_path),
|
||||
"--format",
|
||||
"markdown",
|
||||
]
|
||||
logging.info("Running Codex CLI command: %s", " ".join(command))
|
||||
|
||||
try:
|
||||
subprocess.run(
|
||||
@@ -217,7 +207,7 @@ def run_codex(prompt_path: Path, output_path: Path, command_template: str) -> No
|
||||
)
|
||||
except FileNotFoundError as exc:
|
||||
raise FatalConfigurationError(
|
||||
f"Executable not found while running Codex CLI command: {command[0]}"
|
||||
"Codex CLI executable 'codex' not found in PATH"
|
||||
) from exc
|
||||
except subprocess.TimeoutExpired as exc:
|
||||
raise RuntimeError("Codex CLI timed out") from exc
|
||||
@@ -301,7 +291,7 @@ def normalize_job_description(job_file: Path) -> NormalizedJobDescription:
|
||||
prompt_path.write_text(prompt_text, encoding="utf-8")
|
||||
|
||||
output_path = tmp_dir / "normalize_output.md"
|
||||
run_codex(prompt_path, output_path, CODEX_NORMALIZER_COMMAND_TEMPLATE)
|
||||
run_codex(prompt_path, output_path)
|
||||
normalized_text = output_path.read_text(encoding="utf-8").strip()
|
||||
|
||||
return parse_normalized_output(normalized_text)
|
||||
@@ -356,7 +346,7 @@ def process_job(job_file: Path) -> None:
|
||||
prompt_path.write_text(prompt_text, encoding="utf-8")
|
||||
|
||||
output_path = tmp_dir / "codex_output.md"
|
||||
run_codex(prompt_path, output_path, CODEX_COMMAND_TEMPLATE)
|
||||
run_codex(prompt_path, output_path)
|
||||
|
||||
generated_output = out_dir / output_filename
|
||||
counter = 1
|
||||
|
||||
@@ -24,9 +24,11 @@ The watcher lives in `input/Docker/`:
|
||||
- `templates/ResumeCustomizerPrompt.md.example` ships with default resume-customization instructions. Copy it to `ResumeCustomizerPrompt.md` to override.
|
||||
- The `.gitignore` in `templates/` keeps local overrides out of version control.
|
||||
|
||||
### Codex CLI
|
||||
- The container image installs the official Codex CLI and expects credentials/configuration from the mounted `~/.codex` directory on the host.
|
||||
- No additional command-line customization is required; the watcher invokes `codex prompt --input … --output … --format markdown` internally for both passes.
|
||||
|
||||
### Key Environment Variables
|
||||
- `CODEX_COMMAND_TEMPLATE` – format string for the resume-customization Codex run (placeholders: `{prompt}`, `{output}`).
|
||||
- `CODEX_NORMALIZER_COMMAND_TEMPLATE` – optional override for the normalization Codex run (defaults to `CODEX_COMMAND_TEMPLATE`).
|
||||
- `POLL_INTERVAL_SECONDS` – watch loop delay (defaults to 5).
|
||||
- `CODEX_TIMEOUT_SECONDS` – wall-clock timeout for each Codex call (defaults to 600).
|
||||
- `CODEX_CONFIG_DIR` – host path to mount as `/home/codex/.codex` (defaults to `${HOME}/.codex` via the wrapper).
|
||||
|
||||
Reference in New Issue
Block a user