Aggiunge action codex-reply e workflow @codex
This commit is contained in:
27
.gitea/workflows/codex.yml
Normal file
27
.gitea/workflows/codex.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Codex Reply
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
codex:
|
||||||
|
runs-on: linux_amd64
|
||||||
|
if: |
|
||||||
|
contains(github.event.comment.body, '@codex') &&
|
||||||
|
github.event.comment.user.login != 'anuti'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: ./install-opencode
|
||||||
|
|
||||||
|
- uses: ./codex-reply
|
||||||
|
with:
|
||||||
|
issue-number: ${{ github.event.issue.number }}
|
||||||
|
repository: ${{ github.repository }}
|
||||||
|
comment-body: ${{ github.event.comment.body }}
|
||||||
|
comment-author: ${{ github.event.comment.user.login }}
|
||||||
|
issue-title: ${{ github.event.issue.title }}
|
||||||
|
issue-body: ${{ github.event.issue.body }}
|
||||||
|
api-token: ${{ secrets.TOKEN }}
|
||||||
|
api-key: ${{ secrets.OPENCODE_API_KEY }}
|
||||||
136
codex-reply/action.yml
Normal file
136
codex-reply/action.yml
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
name: Codex Reply
|
||||||
|
description: "Risponde a un commento @codex analizzando issue, cronologia e codice repository."
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
issue-number:
|
||||||
|
description: Numero dell'issue.
|
||||||
|
required: true
|
||||||
|
repository:
|
||||||
|
description: Repository in formato owner/repo.
|
||||||
|
required: true
|
||||||
|
comment-body:
|
||||||
|
description: Testo del commento che contiene @codex.
|
||||||
|
required: true
|
||||||
|
comment-author:
|
||||||
|
description: Login dell'autore del commento.
|
||||||
|
required: true
|
||||||
|
issue-title:
|
||||||
|
description: Titolo dell'issue.
|
||||||
|
required: true
|
||||||
|
issue-body:
|
||||||
|
description: Corpo dell'issue.
|
||||||
|
required: true
|
||||||
|
api-token:
|
||||||
|
description: Token API Gitea.
|
||||||
|
required: true
|
||||||
|
gitea-host:
|
||||||
|
description: URL del server Gitea.
|
||||||
|
required: false
|
||||||
|
default: "https://git.incloud.ovh"
|
||||||
|
api-key:
|
||||||
|
description: API key per opencode.
|
||||||
|
required: true
|
||||||
|
model:
|
||||||
|
description: Modello AI in formato provider/model.
|
||||||
|
required: false
|
||||||
|
default: "deepseek/deepseek-v4-flash"
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Configura autenticazione opencode
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if ! command -v jq &> /dev/null; then
|
||||||
|
echo "jq non trovato, tentativo di installazione..."
|
||||||
|
if command -v apt-get &> /dev/null; then
|
||||||
|
apt-get update -qq && apt-get install -y -qq jq 2>&1 || true
|
||||||
|
elif command -v apk &> /dev/null; then
|
||||||
|
apk add --no-cache jq 2>&1 || true
|
||||||
|
fi
|
||||||
|
command -v jq &> /dev/null || { echo "ERRORE: impossibile installare jq."; exit 1; }
|
||||||
|
fi
|
||||||
|
mkdir -p ~/.local/share/opencode
|
||||||
|
jq -n \
|
||||||
|
--arg provider "opencode-go" \
|
||||||
|
--arg key "${{ inputs.api-key }}" \
|
||||||
|
'{($provider): {type: "api", key: $key}}' > ~/.local/share/opencode/auth.json
|
||||||
|
chmod 600 ~/.local/share/opencode/auth.json
|
||||||
|
|
||||||
|
- name: Rispondi a @codex
|
||||||
|
id: codex
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if ! command -v curl &> /dev/null; then
|
||||||
|
echo "curl non trovato, tentativo di installazione..."
|
||||||
|
if command -v apt-get &> /dev/null; then
|
||||||
|
apt-get update -qq && apt-get install -y -qq curl 2>&1 || true
|
||||||
|
elif command -v apk &> /dev/null; then
|
||||||
|
apk add --no-cache curl 2>&1 || true
|
||||||
|
fi
|
||||||
|
command -v curl &> /dev/null || { echo "ERRORE: impossibile installare curl."; exit 1; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
HOST="${{ inputs.gitea-host }}"
|
||||||
|
TOKEN="${{ inputs.api-token }}"
|
||||||
|
REPO="${{ inputs.repository }}"
|
||||||
|
ISSUE_NUM="${{ inputs.issue-number }}"
|
||||||
|
AUTHOR="${{ inputs.comment-author }}"
|
||||||
|
MODEL_ARG=()
|
||||||
|
[ -n "${{ inputs.model }}" ] && MODEL_ARG=(--model "${{ inputs.model }}")
|
||||||
|
|
||||||
|
# Estrai la domanda dopo @codex
|
||||||
|
QUERY=$(echo "${{ inputs.comment-body }}" | sed -n 's/.*@codex[[:space:],:]*//p')
|
||||||
|
if [ -z "$QUERY" ]; then
|
||||||
|
QUERY="(nessuna domanda specifica dopo @codex)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Recupera cronologia commenti, escludendo quelli del bot
|
||||||
|
COMMENTS_JSON=$(curl -sS -f "$HOST/api/v1/repos/$REPO/issues/$ISSUE_NUM/comments" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Accept: application/json" 2>/dev/null || echo "[]")
|
||||||
|
COMMENTS_TEXT=$(echo "$COMMENTS_JSON" | jq -r '
|
||||||
|
[.[] | select(.user.login != "anuti")]
|
||||||
|
| sort_by(.created_at)
|
||||||
|
| .[-20:]
|
||||||
|
| .[]
|
||||||
|
| "**\(.user.login)**: \(.body)\n"
|
||||||
|
' 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
# Costruisci il prompt
|
||||||
|
BODY=$(echo "${{ inputs.issue-body }}" | head -c 10000)
|
||||||
|
[ "${#BODY}" -ge 10000 ] && BODY+=$'\n... (troncato)'
|
||||||
|
|
||||||
|
printf -v PROMPT '%s\n\n%s\n%s\n\n## %s\n%s\n%s\n\n## %s\n%s\n\n## %s - @%s\n%s' \
|
||||||
|
"Sei un assistente esperto per repository software." \
|
||||||
|
"Rispondi alla domanda in modo diretto e tecnico, in italiano." \
|
||||||
|
"Analizza il codice sorgente nel repository quando e' rilevante." \
|
||||||
|
"Issue" \
|
||||||
|
"**Titolo**: ${{ inputs.issue-title }}" \
|
||||||
|
"**Corpo**: $BODY" \
|
||||||
|
"Cronologia commenti" "$COMMENTS_TEXT" \
|
||||||
|
"Domanda" "$AUTHOR" "$QUERY"
|
||||||
|
|
||||||
|
# Esegui opencode
|
||||||
|
OUTFILE="$GITHUB_WORKSPACE/opencode-codex.txt"
|
||||||
|
opencode run "$PROMPT" "${MODEL_ARG[@]}" --dangerously-skip-permissions 2>&1 | tee "$OUTFILE"
|
||||||
|
|
||||||
|
# Pulisci la risposta: togli ANSI codes, banner build, righe vuote iniziali
|
||||||
|
ESC=$(printf '\x1b')
|
||||||
|
sed "s/${ESC}\[[0-9;]*m//g" "$OUTFILE" > /tmp/codex-clean.txt
|
||||||
|
RESPONSE=$(sed '/^> build /d; /^[[:space:]]*$/d' /tmp/codex-clean.txt)
|
||||||
|
if [ -z "$RESPONSE" ]; then
|
||||||
|
RESPONSE="Mi dispiace, non ho generato una risposta. Riprova."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pubblica il commento
|
||||||
|
COMMENT_JSON=$(jq -n --arg body "$RESPONSE" '{body: $body}')
|
||||||
|
curl -sS -X POST "$HOST/api/v1/repos/$REPO/issues/$ISSUE_NUM/comments" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$COMMENT_JSON" 2>/dev/null && \
|
||||||
|
echo "Risposta @codex pubblicata sull'issue #$ISSUE_NUM" || \
|
||||||
|
echo "WARN: Impossibile pubblicare la risposta"
|
||||||
Reference in New Issue
Block a user