name: 'Codex CLI' description: 'Codex CLI 工具' author: 'Jeffery' inputs: prompt: description: '傳給 Codex CLI 的提示詞' required: false default: "請自我介紹" oauth: description: 'base64 編碼的 Codex OAuth token 檔案內容' required: true outputs: text: description: '輸出的文字' value: ${{ steps.codex.outputs.text }} email: description: '目前登入帳號的電子郵件(由 codex app-server account/read 取得)' value: ${{ steps.account.outputs.email }} runs: using: 'composite' steps: - name: 安裝工具 env: OAUTH: ${{ inputs.oauth }} run: | npm install -g @openai/codex oauth_file="$HOME/.codex/auth.json" install -d -m 700 "$(dirname "$oauth_file")" printf '%s' "$OAUTH" | base64 -d > "$oauth_file" chmod 600 "$oauth_file" shell: bash - name: 執行工具 id: codex env: MODEL: ${{ vars.CODEX_MODEL }} PROMPT: ${{ inputs.prompt }} run: | if [ -z "$MODEL" ]; then echo 'CODEX_MODEL repository variable is required.' >&2 exit 1 fi text="$(codex exec --skip-git-repo-check -s danger-full-access --model "$MODEL" "$PROMPT")" printf '%s\n' "$text" { echo 'text<> "$GITHUB_OUTPUT" shell: bash - name: 取得登入帳號 id: account run: | cat > "$RUNNER_TEMP/codex_account.py" <<'PY' import json, subprocess, time p = subprocess.Popen( ["codex", "app-server"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True, bufsize=1, ) def send(obj): p.stdin.write(json.dumps(obj) + "\n") p.stdin.flush() send({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"clientInfo": {"name": "ci", "version": "1.0"}}}) send({"jsonrpc": "2.0", "method": "initialized", "params": {}}) send({"jsonrpc": "2.0", "id": 2, "method": "account/read", "params": {}}) email = "" deadline = time.time() + 25 while time.time() < deadline: line = p.stdout.readline() if not line: break try: msg = json.loads(line) except Exception: continue if msg.get("id") == 2: account = (msg.get("result") or {}).get("account") or {} email = account.get("email") or "" break p.terminate() print(email) PY email="$(python3 "$RUNNER_TEMP/codex_account.py")" printf 'email=%s\n' "$email" >> "$GITHUB_OUTPUT" shell: bash