File size: 5,587 Bytes
21665fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/bin/bash
# codex with the `viggle-remake` MCP (examples/codex_config.toml: pool image mode by default). Extra args go to codex, e.g.
#   scripts/codex_exec.sh                                              interactive
#   scripts/codex_exec.sh exec "swap the singer in /videos/x.mp4 ..."  non-interactive, resumed after "at capacity"
# Settings (environment):
#   REMAKE_HOME        sessions, queue, workers (default ~/.viggle-remake); must match the workers'
#   REMAKE_CODEX_DIR   codex's home and workspace (default $REMAKE_HOME/codex). Put it on a local disk: codex's sqlite
#                      logs break on network filesystems
#   REMAKE_CODEX_AUTH  a codex login to copy in (default ~/.codex/auth.json; skipped if missing - then log in once
#                      with CODEX_HOME=$REMAKE_CODEX_DIR/codex_home codex login); pool helpers read the same login
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
REMAKE_HOME=$(realpath -m "${REMAKE_HOME:-$HOME/.viggle-remake}")
DIR=${REMAKE_CODEX_DIR:-$REMAKE_HOME/codex}
AUTH=${REMAKE_CODEX_AUTH:-$HOME/.codex/auth.json}
MCP=$(command -v viggle-remake-mcp) || { echo "codex_exec.sh: viggle-remake-mcp is not on PATH (pip install -e .)" >&2; exit 1; }
export CODEX_HOME=$DIR/codex_home
WS=$DIR/ws
mkdir -p "$CODEX_HOME" "$WS" "$REMAKE_HOME/sessions"
[ -f "$AUTH" ] && cp -u "$AUTH" "$CODEX_HOME/auth.json"  # -u: pick up a refreshed login
sed -e "s#@WS@#$WS#g" -e "s#@CODEX_HOME@#$CODEX_HOME#g" -e "s#@REMAKE_HOME@#$REMAKE_HOME#g" -e "s#@MCP@#$MCP#g" "$ROOT/examples/codex_config.toml" \
    > "$CODEX_HOME/config.toml"
# AGENTS.md + the short prompt-writing guide (data/short_guide.md) and the two format examples: codex re-reads AGENTS.md after every
# context compaction, a tool result does not survive one (the config sets REMAKE_GUIDE_IN_AGENTS, so write_prompts and
# cut_windows leave them out, and project_doc_max_bytes, since the whole file is ~60 KB)
G=$ROOT/viggle_remake_mcp/data/short_guide.md
{ cat "$ROOT/viggle_remake_mcp/data/AGENTS.md"
  printf '\n\n# Prompt-writing guide (write_prompts and cut_windows do not repeat it)\n\n=== GUIDE ===\n'
  cat "$G"
  printf '\n\n=== FORMAT EXAMPLE, swap sessions (a different edit of a different clip - copy its structure, tags and level of detail, not its content) ===\n'
  cat "$ROOT/viggle_remake_mcp/data/example_prompt.txt"
  printf '\n\n=== FORMAT EXAMPLE, edit sessions (same) ===\n'
  cat "$ROOT/viggle_remake_mcp/data/example_edit_prompt.txt"; } > "$WS/AGENTS.md"
if [ "$1" = exec ]; then  # the workspace is no git repo; an open stdin makes exec wait for more prompt
    shift
    # "model at capacity" ends the turn: resume the same session, at most 10 times. stdout/stderr still stream through.
    # Assumes the prompt is the last argument and, for `exec resume ...`, the session id is the one before it.
    CONT='Your previous turn was cut off by a transient "model at capacity" error; this is not new user feedback.
Continue the same task from where it stopped: call `status` first and do not redo finished steps. If your last tool
call returned a CODEX IMAGE STEP, call that tool again with the same arguments: it imports the picture if it is in
place, otherwise it gives you a fresh brief.'
    set -o pipefail
    log=$(mktemp -d -p "$DIR")
    : > "$CODEX_HOME/run_sids"  # the MCP adds every session this run touches (REMAKE_RUN_SIDS in the config)
    run() { { codex exec --skip-git-repo-check -C "$WS" "$@" </dev/null 2>&1 1>&3 3>&- | tee "$log/err" >&2; } 3>&1 | tee "$log/out"; }
    run "$@"; rc=$?
    args=("$@"); n=$#
    if [ "$1" = resume ]; then id=${args[n-2]}; opts=("${args[@]:1:n-3}"); else id=; opts=("${args[@]:0:n-1}"); fi
    sid() { [ -n "$id" ] || id=$(grep -ohE '"thread_id":"[0-9a-f-]{36}"|session id: [0-9a-f-]{36}' "$log/out" "$log/err" | grep -oE '[0-9a-f-]{36}' | head -1); }
    for i in $(seq 10); do
        tail -n 5 "$log/out" "$log/err" | grep -q "at capacity" || break
        sid
        echo "codex_exec.sh: model at capacity, resuming $id ($i/10)" >&2
        sleep 30
        run resume "${opts[@]}" "$id" "$CONT"; rc=$?
    done
    # codex sometimes ends its turn with the job half done and nothing saved (3 of ~8 runs on a 2-minute film, each after a `!!` warning or a long to-do list). A session it touched without writing a
    # result.json during this run gets the turn back, at most twice; `save_result` with status failed is the way out.
    for i in 1 2; do
        open=$(for s in $(cat "$CODEX_HOME/run_sids"); do [ "$REMAKE_HOME/sessions/$s/result.json" -nt "$log" ] || printf '%s ' $s; done)
        [ $rc = 0 ] && [ -n "$open" ] && [ ! -f "${REMAKE_STOP:-$REMAKE_HOME/STOP}" ] || break
        sid
        echo "codex_exec.sh: ended without a result for ${open% }, resuming $id ($i/2)" >&2
        run resume "${opts[@]}" "$id" "Your turn ended, but session(s) ${open% } have no result: save_result was not called. This is not new user
feedback. The job is not done and nothing has gone wrong: there is no time or token limit and nobody is waiting - a
film of a minute or more takes an hour or more. Call status first and do not redo finished steps, then continue the
task: paint every remaining keyframe, render every window, review every strip, do the fix round, finish and
save_result. A \`!!\` line from \`windows\` is advice, not a blocker: follow it or accept the weak window, note it and go
on. Only if the job truly cannot go on (painting STOPPED, no live workers) call save_result with status failed and
say why."; rc=$?
    done
    rm -r "$log"
    exit $rc
fi
exec codex -C "$WS" "$@"