docs(codex): 補齊 function docstring 與指令檔註解並重建 README #4

Merged
admin merged 18 commits from develop into master 2026-06-29 07:09:22 +00:00
4 changed files with 181 additions and 29 deletions
Showing only changes of commit 5c5dc2bca4 - Show all commits
+24 -9
View File
@@ -1,19 +1,34 @@
name: CI
on:
pull_request:
branches-ignore:
- master
types: [opened, synchronize]
jobs:
ai-code-review:
name: AI Code Review
release-tag-version:
name: Release Tag Version
runs-on: ubuntu
permissions:
contents: write
pull-requests: write
issues: write
outputs:
version: ${{ steps.release-tag-version.outputs.version }}
steps:
- name: AI 程式碼審查 by OpenCode
uses: https://gitea.jsc.idv.tw/composite-actions/opencode-code-review@${{ vars.ACTION_OPENCODE_CODE_REVIEW_VERSION }}
- name: 計算版本號
id: release-tag-version
uses: https://gitea.jsc.idv.tw/composite-actions/release-tag-version@${{ vars.ACTION_RELEASE_TAG_VERSION }}
with:
token: ${{ secrets.TOKEN }}
is_beta: 'true'
codex:
name: Codex
runs-on: ubuntu
needs: release-tag-version
steps:
- name: 測試工具
id: codex
uses: https://gitea.jsc.idv.tw/composite-actions/codex@v${{ needs.release-tag-version.outputs.version }}
with:
oauth: ${{ secrets.CODEX_OAUTH }}
- name: 檢查輸出
if: ${{ steps.codex.outputs.text != vars.CODEX_EMAIL }}
run: exit 1
+57
View File
@@ -0,0 +1,57 @@
# Codex CLI Composite Action
此 repository 提供一個 Gitea/GitHub Actions composite action,用於安裝 Codex CLI、寫入 OAuth token、執行指定提示詞,並將 CLI 輸出寫入 action output。
## 專案列表
### 專案描述
| 專案名稱 | 專案描述 |
| --- | --- |
| [codex](https://gitea.jsc.idv.tw/composite-actions/codex) | 提供 Codex CLI composite action,讓 workflow 可透過 `oauth``prompt` 輸入執行 CLI,並從 repository variable 讀取模型名稱後取得文字輸出。 |
### 參考專案
| 專案名稱 | 參考專案列表 |
| --- | --- |
| [codex](https://gitea.jsc.idv.tw/composite-actions/codex) | 無 |
### NuGet 套件
| 專案名稱 | NuGet 套件列表 |
| --- | --- |
| [codex](https://gitea.jsc.idv.tw/composite-actions/codex) | 無 |
## 功能列表
此 repository 未包含可列入 README 的 public method、public constructor、public extension method 或 public operator。
## 使用範例
### 在 workflow 中呼叫 Codex CLI
以下範例示範在 workflow step 中呼叫此 composite action,傳入 OAuth token 與提示詞,並在後續步驟讀取 `text` output。模型名稱由 action 直接讀取 `vars.CODEX_MODEL`
```yaml
- name: 執行 Codex CLI
id: codex
uses: https://gitea.jsc.idv.tw/composite-actions/codex@v1
with:
oauth: ${{ secrets.CODEX_OAUTH }}
prompt: "請自我介紹"
- name: 使用輸出文字
run: printf '%s\n' '${{ steps.codex.outputs.text }}'
```
前置條件:
- `secrets.CODEX_OAUTH` 必須是 Codex OAuth token 檔案內容的 base64 字串。
- `vars.CODEX_MODEL` 必須是 Codex CLI 可用的模型名稱。
- runner 必須可透過 npm 安裝 `@openai/codex`
預期結果:
- action 會安裝 `codex` CLI。
- action 會將 OAuth token 寫入 `$HOME/.codex/auth.json` 並設定檔案權限為 `600`
- action 會執行 `codex exec --model "$MODEL" "$PROMPT"`,並把 stdout 寫入 `steps.codex.outputs.text`
+43 -20
View File
@@ -1,33 +1,56 @@
name: 'Composite Action Template'
description: 'Composite Action 範本'
name: 'Codex CLI'
description: 'Codex CLI 工具'
author: 'Jeffery'
inputs:
text:
description: '輸入的文字'
prompt:
description: '傳給 Codex CLI 的提示詞'
required: false
default: 'Hello, World!'
oauth:
description: 'base64 編碼的 Codex OAuth token 檔案內容'
required: true
outputs:
text:
description: '輸出的文字'
value: ${{ steps.change.outputs.text }}
value: ${{ steps.codex.outputs.text }}
runs:
using: 'composite'
steps:
- name: 交換
id: change
- name: 安裝工具
env:
GITEA_SERVER_URL: ${{ gitea.server_url }}
GITEA_REPOSITORY: ${{ gitea.repository }}
GITEA_TOKEN: ${{ gitea.token }}
TEXT: ${{ inputs.text }}
OAUTH: ${{ inputs.oauth }}
run: |
echo "Gitea Server Url: $GITEA_SERVER_URL"
if [ -z "$OAUTH" ]; then
echo 'oauth input (secrets.CODEX_OAUTH) is required and must not be empty.' >&2
exit 1
fi
echo "Gitea Repository: $GITEA_REPOSITORY"
npm install -g @openai/codex
echo "Gitea Token: $GITEA_TOKEN"
echo "Text: $TEXT"
echo "text=$TEXT" >> "$GITHUB_OUTPUT"
shell: bash
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
if [ -z "$PROMPT" ]; then
email="$(python3 "$GITHUB_ACTION_PATH/app/codex_account.py")"
echo "text=$email" >> "$GITHUB_OUTPUT"
exit 0
fi
text="$(codex exec --skip-git-repo-check -s danger-full-access --model "$MODEL" "$PROMPT")"
printf '%s\n' "$text"
{
echo 'text<<CODEX_OUTPUT'
printf '%s\n' "$text"
echo 'CODEX_OUTPUT'
} >> "$GITHUB_OUTPUT"
shell: bash
+57
View File
@@ -0,0 +1,57 @@
"""透過 codex app-server 的 JSON-RPC account/read 取得目前登入帳號的 email。
這是 TUI `/status` Account 欄位的程式化來源,不解析本地 OAuth token
而是由 codex 自身回報登入帳號。將 email 印到 stdout(取不到時印空字串)。
"""
import json
import subprocess
import time
def read_account_email(timeout_seconds: float = 25.0) -> str:
process = subprocess.Popen(
["codex", "app-server"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
text=True,
bufsize=1,
)
def send(obj):
process.stdin.write(json.dumps(obj) + "\n")
process.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() + timeout_seconds
try:
while time.time() < deadline:
line = process.stdout.readline()
if not line:
break
try:
message = json.loads(line)
except ValueError:
continue
if message.get("id") == 2:
account = (message.get("result") or {}).get("account") or {}
email = account.get("email") or ""
break
finally:
process.terminate()
return email
if __name__ == "__main__":
print(read_account_email())