mirror of
https://github.com/openai/codex.git
synced 2026-05-03 12:52:11 +03:00
170 lines
5.2 KiB
Bash
Executable File
170 lines
5.2 KiB
Bash
Executable File
#!/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 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}"
|
|
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/tasks/launch-commit-agent.sh" "$task_slug"
|
|
fi
|