mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
wip
This commit is contained in:
@@ -33,6 +33,6 @@
|
||||
- **Merged:** tasks with no branch/worktree.
|
||||
- **Ready to merge:** tasks marked Done with branch commits ahead.
|
||||
- **Unblocked:** tasks with no outstanding dependencies.
|
||||
- The script also prints a `create-task-worktree.sh --agent --tmux <IDs>` command for all unblocked tasks.
|
||||
- The script also prints a `agentydragon/tools/create_task_worktree.py --agent --tmux <IDs>` command for all unblocked tasks.
|
||||
|
||||
This guide centralizes the handoff workflow for all agents.
|
||||
|
||||
@@ -7,7 +7,7 @@ tydragon-driven task workflow:
|
||||
e, “Status”, “Goal”, and sections for “Acceptance Criteria”, “Implementation”, and “Notes”.
|
||||
|
||||
2. **Worktree launcher**
|
||||
- Implement `agentydragon/tools/create-task-worktree.sh` with:
|
||||
- Implement `agentydragon/tools/create_task_worktree.py` with:
|
||||
- `--agent` mode to spin up a Codex agent in the worktree,
|
||||
- `--tmux` to tile panes for multiple tasks in a single tmux session,
|
||||
- two‑digit or slug ID resolution.
|
||||
@@ -26,7 +26,7 @@ e, “Status”, “Goal”, and sections for “Acceptance Criteria”, “Impl
|
||||
You are the **Project Manager** Codex agent for the `codex` repository. Your responsibilities include:
|
||||
|
||||
- **Reading documentation**: Load and understand all relevant docs in this repo (especially those defining task, worktree, and branch conventions, as well as each task file and top‑level README files).
|
||||
- **Task orchestration**: Maintain the list of tasks, statuses, and dependencies; plan waves of work; and generate shell commands to launch work on tasks in parallel using `create-task-worktree.sh` with `--agent` and `--tmux`.
|
||||
- **Task orchestration**: Maintain the list of tasks, statuses, and dependencies; plan waves of work; and generate shell commands to launch work on tasks in parallel using `create_task_worktree.py` with `--agent` and `--tmux`.
|
||||
- **Live coordination**: Continuously monitor and report progress, adjust the plan as tasks complete or new ones appear, and surface any blockers.
|
||||
- **Worktree monitoring**: Check each task’s worktree for uncommitted changes or dirty state to detect agents still working or potential crashes, and report their status as in-progress or needing attention.
|
||||
- **Background polling**: On user request, enter a sleep‑and‑scan loop (e.g. 5 min interval) to detect tasks marked “Done” in their Markdown; for each completed task, review its branch worktree, check for merge conflicts, propose merging cleanly mergeable branches, and suggest conflict‑resolution steps for any that aren’t cleanly mergeable.
|
||||
@@ -35,7 +35,7 @@ e, “Status”, “Goal”, and sections for “Acceptance Criteria”, “Impl
|
||||
|
||||
### First Actions
|
||||
|
||||
1. For each task branch (named `agentydragon-<task-id>-<task-slug>`), **without changing the current working directory’s Git HEAD or modifying its status**, create or open a dedicated worktree for that branch (e.g. via `create-task-worktree.sh <task-slug>`) and read the task’s Markdown copy under that worktree’s `agentydragon/tasks/` to extract and list the task number, title, live **Status**, and dependencies. *(Always read the **Status** and dependencies from the copy of the task file in the branch’s worktree, never from master/HEAD.)*
|
||||
1. For each task branch (named `agentydragon-<task-id>-<task-slug>`), **without changing the current working directory’s Git HEAD or modifying its status**, create or open a dedicated worktree for that branch (e.g. via `create_task_worktree.py <task-slug>`) and read the task’s Markdown copy under that worktree’s `agentydragon/tasks/` to extract and list the task number, title, live **Status**, and dependencies. *(Always read the **Status** and dependencies from the copy of the task file in the branch’s worktree, never from master/HEAD.)*
|
||||
2. Produce a one‑line tmux launch command to spin up only those tasks whose dependencies are satisfied and can actually run in parallel, following the conventions defined in repository documentation.
|
||||
3. Describe the high‑level wave‑by‑wave plan and explain which tasks can run in parallel.
|
||||
|
||||
@@ -58,7 +58,7 @@ entions.
|
||||
- Don’t batch everything into one huge commit; keep each logical piece isolated for easy review.
|
||||
|
||||
**Reporting**
|
||||
After each commit, print a short status message (e.g. “✅ Task stubs created”, “✅ create-task-worktree.sh implemented”, etc.) and await confirmation before continuing
|
||||
After each commit, print a short status message (e.g. “✅ Task stubs created”, “✅ create_task_worktree.py implemented”, etc.) and await confirmation before continuing
|
||||
the next step.
|
||||
|
||||
---
|
||||
|
||||
32
agentydragon/tools/common.py
Normal file
32
agentydragon/tools/common.py
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
common.py: Shared utilities for agentydragon tooling scripts.
|
||||
"""
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def repo_root() -> Path:
|
||||
"""Return the Git repository root directory."""
|
||||
out = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'])
|
||||
return Path(out.decode().strip())
|
||||
|
||||
|
||||
def tasks_dir() -> Path:
|
||||
"""Path to the agentydragon/tasks directory."""
|
||||
return repo_root() / 'agentydragon' / 'tasks'
|
||||
|
||||
|
||||
def worktrees_dir() -> Path:
|
||||
"""Path to the agentydragon/tasks/.worktrees directory."""
|
||||
return tasks_dir() / '.worktrees'
|
||||
|
||||
|
||||
def resolve_slug(input_id: str) -> str:
|
||||
"""Resolve a two-digit task ID into its full slug, or return slug unchanged."""
|
||||
if input_id.isdigit() and len(input_id) == 2:
|
||||
matches = list(tasks_dir().glob(f"{input_id}-*.md"))
|
||||
if len(matches) == 1:
|
||||
return matches[0].stem
|
||||
raise ValueError(f"Expected one task file for ID {input_id}, found {len(matches)}")
|
||||
return input_id
|
||||
@@ -1,180 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# create-task-worktree.sh
|
||||
#
|
||||
# Create or reuse a git worktree for a specific task branch under agentydragon/tasks/.worktrees.
|
||||
# Usage: create-task-worktree.sh [-a|--agent] [-t|--tmux] <task-slug|NN> [<task-slug|NN>...]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
agent_mode=false
|
||||
tmux_mode=false
|
||||
interactive_mode=false
|
||||
shell_mode=false
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-a|--agent)
|
||||
agent_mode=true
|
||||
shift
|
||||
;;
|
||||
-t|--tmux)
|
||||
tmux_mode=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
cat << EOF
|
||||
Usage: $0 [-a|--agent] [-s|--shell] [-i|--interactive] [-t|--tmux] <task-slug|NN> [<task-slug|NN>...]
|
||||
|
||||
Options:
|
||||
-a, --agent create/reuse worktree, run pre-commit checks (aborting on failure),
|
||||
and launch a Codex agent with prompt injection; when the agent exits,
|
||||
auto-run commit helper
|
||||
-s, --shell create/reuse worktree and launch an interactive Codex shell
|
||||
(no prompt injection, skip auto-commit)
|
||||
-i, --interactive run the agent in interactive mode (no 'exec'); implies --agent
|
||||
-t, --tmux open each task in its own tmux window; implies --agent
|
||||
-h, --help show this help message and exit
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
-i|--interactive)
|
||||
interactive_mode=true
|
||||
agent_mode=true
|
||||
shift
|
||||
;;
|
||||
-s|--shell)
|
||||
# Launch agent in an interactive shell (no prompt injection, no auto-commit)
|
||||
shell_mode=true
|
||||
agent_mode=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate number of task arguments based on mode
|
||||
if [ "$tmux_mode" = true ]; then
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "Usage: $0 [-a|--agent] [-t|--tmux] <task-id>-<task-slug> [<more-task-ids>...]"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 [-a|--agent] [-t|--tmux] <task-id>-<task-slug> [<more-task-ids>...]"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Capture raw input so we can accept just a two-digit task ID
|
||||
task_inputs=("$@")
|
||||
|
||||
# If tmux mode, batch-create worktrees and launch in tmux
|
||||
if [ "$tmux_mode" = true ]; then
|
||||
# Implicitly enable agent mode in tmux panes
|
||||
agent_mode=true
|
||||
# Build a unique session name from task IDs
|
||||
session="agentydragon-${task_inputs[*]// /_}"
|
||||
cmd="$0"
|
||||
# First pane: first task
|
||||
first="${task_inputs[0]}"
|
||||
pane_cmd="$cmd${agent_mode:+ -a} $first"
|
||||
tmux new-session -d -s "$session" "$pane_cmd"
|
||||
# Open each additional task in its own tmux window
|
||||
for task in "${task_inputs[@]:1}"; do
|
||||
tmux new-window -t "$session" "$cmd${agent_mode:+ -a} $task"
|
||||
done
|
||||
tmux attach -t "$session"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
task_input="${task_inputs[0]}"
|
||||
|
||||
# Determine repository root and tasks directory
|
||||
repo_root=$(git rev-parse --show-toplevel)
|
||||
tasks_dir="$repo_root/agentydragon/tasks"
|
||||
|
||||
# If given only a two-digit ID, resolve to the full task slug
|
||||
if [[ "$task_input" =~ ^[0-9]{2}$ ]]; then
|
||||
matches=( "$tasks_dir/${task_input}-"*.md )
|
||||
if [ "${#matches[@]}" -eq 1 ]; then
|
||||
task_slug="$(basename "${matches[0]}" .md)"
|
||||
echo "Resolved task ID '$task_input' to slug '$task_slug'"
|
||||
else
|
||||
echo "Error: expected exactly one task file matching '${task_input}-*.md', found ${#matches[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
task_slug="$task_input"
|
||||
fi
|
||||
# Use dash-separated branch name to avoid ref-dir conflicts
|
||||
branch="agentydragon-$task_slug"
|
||||
worktrees_dir="$tasks_dir/.worktrees"
|
||||
worktree_path="$worktrees_dir/$task_slug"
|
||||
|
||||
mkdir -p "$worktrees_dir"
|
||||
|
||||
# Create branch if it does not exist
|
||||
if ! git show-ref --verify --quiet "refs/heads/$branch"; then
|
||||
echo "Creating branch $branch from agentydragon branch..."
|
||||
git branch --track "$branch" agentydragon
|
||||
fi
|
||||
|
||||
# Create worktree if it does not exist
|
||||
if [ ! -d "$worktree_path" ]; then
|
||||
echo "Creating worktree for $branch at $worktree_path"
|
||||
git worktree add "$worktree_path" "$branch"
|
||||
# Install pre-commit hooks in the new worktree if pre-commit is available
|
||||
if command -v pre-commit >/dev/null 2>&1; then
|
||||
(cd "$worktree_path" && pre-commit install)
|
||||
else
|
||||
echo "Warning: pre-commit not found; skipping hook install in $worktree_path"
|
||||
fi
|
||||
|
||||
else
|
||||
echo "Worktree for $branch already exists at $worktree_path"
|
||||
fi
|
||||
|
||||
echo "Done."
|
||||
|
||||
if [ "$agent_mode" = true ]; then
|
||||
echo "Launching Developer Codex agent for task $task_slug in sandboxed worktree"
|
||||
cd "${worktree_path}"
|
||||
# Before launching the developer agent, run pre-commit checks and abort if hooks fail
|
||||
if command -v pre-commit >/dev/null 2>&1; then
|
||||
echo "Running pre-commit checks in $(pwd)"
|
||||
if ! pre-commit run --all-files; then
|
||||
echo "Error: pre-commit checks failed. Fix issues before launching the developer agent." >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Warning: pre-commit is not installed; skipping pre-commit checks." >&2
|
||||
fi
|
||||
echo "Launching Developer Codex agent for task $task_slug in sandboxed worktree"
|
||||
if [ "$shell_mode" = true ]; then
|
||||
# Interactive shell mode: no prompt, skip commit helper
|
||||
cmd=(codex --full-auto)
|
||||
echo "${cmd[*]}"
|
||||
exec "${cmd[@]}"
|
||||
fi
|
||||
|
||||
prompt_file="$repo_root/agentydragon/prompts/developer.md"
|
||||
task_file="$repo_root/agentydragon/tasks/$task_slug.md"
|
||||
if [ ! -f "$prompt_file" ]; then
|
||||
echo "Error: developer prompt file not found at $prompt_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Launch the agent under Landlock+seccomp sandbox: writable only in cwd and TMPDIR, network disabled
|
||||
cmd=(codex --full-auto)
|
||||
if [ "${interactive_mode:-}" != true ]; then
|
||||
cmd+=(exec)
|
||||
fi
|
||||
echo "${cmd[*]}"
|
||||
# Run Developer agent (non-interactive by default) to implement the task
|
||||
"${cmd[@]}" "$(<"$prompt_file")"$'\n\n'"$(<"$task_file")"
|
||||
|
||||
# After the Developer agent exits, stage and commit via the Commit agent helper
|
||||
echo "Running Commit agent to finalize task $task_slug"
|
||||
"$repo_root/agentydragon/tools/launch-commit-agent.sh" "$task_slug"
|
||||
fi
|
||||
109
agentydragon/tools/create_task_worktree.py
Normal file
109
agentydragon/tools/create_task_worktree.py
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
create_task_worktree.py: Create or reuse a git worktree for a specific task and optionally launch a Developer Codex agent.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
||||
from common import repo_root, tasks_dir, worktrees_dir, resolve_slug
|
||||
|
||||
|
||||
def run(cmd, cwd=None):
|
||||
click.echo(f"Running: {' '.join(cmd)}")
|
||||
subprocess.check_call(cmd, cwd=cwd)
|
||||
|
||||
|
||||
def resolve_slug(input_id: str) -> str:
|
||||
if input_id.isdigit() and len(input_id) == 2:
|
||||
matches = list(tasks_dir().glob(f"{input_id}-*.md"))
|
||||
if len(matches) == 1:
|
||||
return matches[0].stem
|
||||
click.echo(f"Error: expected one task file for ID {input_id}, found {len(matches)}", err=True)
|
||||
sys.exit(1)
|
||||
return input_id
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option('-a', '--agent', is_flag=True,
|
||||
help='Launch Developer Codex agent after setting up worktree.')
|
||||
@click.option('-t', '--tmux', 'tmux_mode', is_flag=True,
|
||||
help='Open each task in its own tmux pane; implies --agent.')
|
||||
@click.option('-i', '--interactive', is_flag=True,
|
||||
help='Run agent in interactive mode (no exec); implies --agent.')
|
||||
@click.option('-s', '--shell', 'shell_mode', is_flag=True,
|
||||
help='Launch an interactive Codex shell (skip auto-commit); implies --agent.')
|
||||
@click.argument('task_inputs', nargs=-1, required=True)
|
||||
def main(agent, tmux_mode, interactive, shell_mode, task_inputs):
|
||||
"""Create/reuse a task worktree and optionally launch a Dev agent or tmux session."""
|
||||
if interactive or shell_mode:
|
||||
agent = True
|
||||
|
||||
if tmux_mode:
|
||||
agent = True
|
||||
session = 'agentydragon_' + '_'.join(task_inputs)
|
||||
for idx, inp in enumerate(task_inputs):
|
||||
slug = resolve_slug(inp)
|
||||
cmd = [sys.executable, '-u', __file__]
|
||||
if agent:
|
||||
cmd.append('--agent')
|
||||
cmd.append(slug)
|
||||
if idx == 0:
|
||||
run(['tmux', 'new-session', '-d', '-s', session] + cmd)
|
||||
else:
|
||||
run(['tmux', 'new-window', '-t', session] + cmd)
|
||||
run(['tmux', 'attach', '-t', session])
|
||||
return
|
||||
|
||||
# Single task
|
||||
slug = resolve_slug(task_inputs[0])
|
||||
branch = f"agentydragon-{slug}"
|
||||
wt_root = worktrees_dir()
|
||||
wt_path = wt_root / slug
|
||||
|
||||
# Ensure branch exists
|
||||
if subprocess.call(['git', 'show-ref', '--verify', '--quiet', f'refs/heads/{branch}']) != 0:
|
||||
run(['git', 'branch', '--track', branch, 'agentydragon'])
|
||||
|
||||
wt_root.mkdir(parents=True, exist_ok=True)
|
||||
if not wt_path.exists():
|
||||
# Create worktree without checkout, then hydrate via reflink/rsync for COW performance
|
||||
run(['git', 'worktree', 'add', '--no-checkout', str(wt_path), branch])
|
||||
src = str(repo_root())
|
||||
dst = str(wt_path)
|
||||
try:
|
||||
run(['cp', '-cRp', f'{src}/.', f'{dst}/', '--exclude=.git', '--exclude=.gitlink'])
|
||||
except subprocess.CalledProcessError:
|
||||
run(['rsync', '-a', '--delete', f'{src}/', f'{dst}/', '--exclude=.git*'])
|
||||
if shutil.which('pre-commit'):
|
||||
run(['pre-commit', 'install'], cwd=dst)
|
||||
else:
|
||||
click.echo('Warning: pre-commit not found; skipping hook install', err=True)
|
||||
else:
|
||||
click.echo(f'Worktree already exists at {wt_path}')
|
||||
|
||||
if not agent:
|
||||
return
|
||||
|
||||
# Pre-commit checks
|
||||
if shutil.which('pre-commit'):
|
||||
run(['pre-commit', 'run', '--all-files'], cwd=str(wt_path))
|
||||
else:
|
||||
click.echo('Warning: pre-commit not installed; skipping checks', err=True)
|
||||
|
||||
click.echo(f'Launching Developer Codex agent for task {slug} in sandboxed worktree')
|
||||
os.chdir(wt_path)
|
||||
cmd = ['codex', '--full-auto']
|
||||
if not interactive:
|
||||
cmd.append('exec')
|
||||
prompt = (repo_root() / 'agentydragon' / 'prompts' / 'developer.md').read_text()
|
||||
taskfile = (tasks_dir() / f'{slug}.md').read_text()
|
||||
run(cmd + [prompt + '\n\n' + taskfile])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import shutil
|
||||
main()
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# launch-commit-agent.sh
|
||||
#
|
||||
# Launch the non-interactive Codex Commit agent for a given task worktree,
|
||||
# using the prompt in prompts/commit.md and the task's Markdown file.
|
||||
#
|
||||
# Usage: launch-commit-agent.sh <task-slug|NN> [<task-slug|NN>...]
|
||||
set -euo pipefail
|
||||
|
||||
# Allocate a temporary file to capture the agent's commit message
|
||||
last_message_file="$(mktemp)"
|
||||
trap 'rm -f "$last_message_file"' EXIT
|
||||
|
||||
# Usage: one or more task IDs or slugs
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "Usage: $0 <task-slug|NN> [<task-slug|NN>...]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Locate repository and tasks directory; commit prompt is constant
|
||||
repo_root=$(git rev-parse --show-toplevel)
|
||||
tasks_dir="$repo_root/agentydragon/tasks"
|
||||
prompt_file="$repo_root/agentydragon/prompts/commit.md"
|
||||
|
||||
for input in "$@"; do
|
||||
# Resolve numeric ID to full slug if needed
|
||||
if [[ "$input" =~ ^[0-9]{2}$ ]]; then
|
||||
matches=("$tasks_dir/${input}-"*.md)
|
||||
if [ "${#matches[@]}" -eq 1 ]; then
|
||||
task_slug="$(basename "${matches[0]}" .md)"
|
||||
echo "Resolved task ID '$input' to slug '$task_slug'"
|
||||
else
|
||||
echo "Error: expected exactly one task file matching '${input}-*.md', found ${#matches[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
task_slug="$input"
|
||||
fi
|
||||
|
||||
# Paths for worktree and task file
|
||||
worktrees_dir="$tasks_dir/.worktrees"
|
||||
worktree_path="$worktrees_dir/$task_slug"
|
||||
task_file="$tasks_dir/$task_slug.md"
|
||||
|
||||
# Preconditions
|
||||
if [ ! -d "$worktree_path" ]; then
|
||||
echo "Error: worktree for '$task_slug' not found; run create-task-worktree.sh first" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$prompt_file" ]; then
|
||||
echo "Error: commit prompt not found at $prompt_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$task_file" ]; then
|
||||
echo "Error: task file not found at $task_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Perform commit in the task worktree
|
||||
echo "--- Processing task $task_slug ---"
|
||||
cd "$worktree_path"
|
||||
cmd=(codex --full-auto exec --output-last-message "$last_message_file")
|
||||
echo "Running: ${cmd[*]}"
|
||||
# Write the agent's final message to file, then commit using that file
|
||||
"${cmd[@]}" "$(<"$prompt_file")"$'\n\n'"$(<"$task_file")"
|
||||
git add -u
|
||||
git commit -F "$last_message_file"
|
||||
done
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# launch-project-manager.sh
|
||||
#
|
||||
# Launch the Codex Project Manager agent using the prompt in prompts/manager.md.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
repo_root=$(git rev-parse --show-toplevel)
|
||||
prompt_file="$repo_root/agentydragon/prompts/manager.md"
|
||||
|
||||
if [ ! -f "$prompt_file" ]; then
|
||||
echo "Error: manager prompt file not found at $prompt_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
codex "$(<"$prompt_file")"
|
||||
47
agentydragon/tools/launch_commit_agent.py
Normal file
47
agentydragon/tools/launch_commit_agent.py
Normal file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
launch_commit_agent.py: Run the non-interactive Commit agent for completed tasks.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
||||
from common import repo_root, tasks_dir, worktrees_dir, resolve_slug
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('task_input', required=True)
|
||||
def main(task_input):
|
||||
"""Resolve TASK_INPUT to slug, run the Commit agent, and commit changes."""
|
||||
slug = resolve_slug(task_input)
|
||||
wt = worktrees_dir() / slug
|
||||
if not wt.exists():
|
||||
click.echo(f"Error: worktree for '{slug}' not found; run create_task_worktree.py first", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
prompt_file = repo_root() / 'agentydragon' / 'prompts' / 'commit.md'
|
||||
task_file = tasks_dir() / f'{slug}.md'
|
||||
for f in (prompt_file, task_file):
|
||||
if not f.exists():
|
||||
click.echo(f"Error: file not found: {f}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
msg_file = Path(subprocess.check_output(['mktemp']).decode().strip())
|
||||
try:
|
||||
os.chdir(wt)
|
||||
cmd = ['codex', '--full-auto', 'exec', '--output-last-message', str(msg_file)]
|
||||
click.echo(f"Running: {' '.join(cmd)}")
|
||||
prompt_content = prompt_file.read_text(encoding='utf-8')
|
||||
task_content = task_file.read_text(encoding='utf-8')
|
||||
subprocess.check_call(cmd + [prompt_content + '\n\n' + task_content])
|
||||
subprocess.check_call(['git', 'add', '-u'])
|
||||
subprocess.check_call(['git', 'commit', '-F', str(msg_file)])
|
||||
finally:
|
||||
msg_file.unlink()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
28
agentydragon/tools/launch_project_manager.py
Normal file
28
agentydragon/tools/launch_project_manager.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
launch_project_manager.py: Launch the Codex Project Manager agent prompt.
|
||||
"""
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import click
|
||||
|
||||
from common import repo_root
|
||||
|
||||
|
||||
@click.command()
|
||||
def main():
|
||||
"""Read manager.md prompt and invoke Codex Project Manager agent."""
|
||||
prompt_file = repo_root() / 'agentydragon' / 'prompts' / 'manager.md'
|
||||
if not prompt_file.exists():
|
||||
click.echo(f"Error: manager prompt not found at {prompt_file}", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
prompt = prompt_file.read_text(encoding='utf-8')
|
||||
cmd = ['codex', prompt]
|
||||
click.echo(f"Running: {' '.join(cmd[:1])} <prompt>")
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -6,12 +6,26 @@ This crate implements the business logic for Codex. It is designed to be used by
|
||||
|
||||
Codex composes the initial system message that seeds every chat completion turn as follows:
|
||||
|
||||
1. Load the built-in system prompt from `prompt.md` (unless disabled).
|
||||
1. Load the built-in system prompt from `prompt.md` (unless overridden/disabled).
|
||||
2. If the `CODEX_BASE_INSTRUCTIONS_FILE` env var is set, use that file instead of `prompt.md`.
|
||||
3. Append any user instructions (e.g. from `instructions.md` and merged `AGENTS.md`).
|
||||
4. Append the apply-patch tool instructions when using GPT-4.1 models.
|
||||
5. Finally, the user's command or prompt is sent as the first user message.
|
||||
|
||||
This “system” prompt is delivered to the OpenAI Chat Completions API as the very first message with role `system` in the JSON `messages` array, e.g.:
|
||||
```json
|
||||
{
|
||||
"model": "gpt-4.1",
|
||||
"messages": [
|
||||
{"role": "system", "content": "<base instructions here>"},
|
||||
{"role": "system", "content": "<user_instructions here>"},
|
||||
{"role": "system", "content": "<apply-patch tool instructions>"},
|
||||
{"role": "user", "content": "<your prompt>"}
|
||||
],
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
The base instructions behavior can be customized with `CODEX_BASE_INSTRUCTIONS_FILE`:
|
||||
|
||||
- If unset, the built-in prompt (`prompt.md`) is used.
|
||||
|
||||
Reference in New Issue
Block a user