name: gemini - manual on: issue_comment: types: [created] pull_request_review_comment: types: [created] concurrency: group: agent-issue-${{ github.event.issue.number || github.event.pull_request.number }} cancel-in-progress: false permissions: contents: write issues: write pull-requests: write actions: write jobs: agent-dispatch: name: Agent / Dispatch if: > (github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR') && (contains(github.event.comment.body, '/plan') || contains(github.event.comment.body, '/implement') || contains(github.event.comment.body, '/fix')) runs-on: [self-hosted, eliza] container: image: node:20-bookworm options: --add-host host.docker.internal:host-gateway env: HTTP_PROXY: http://host.docker.internal:1080 HTTPS_PROXY: http://host.docker.internal:1080 ALL_PROXY: http://host.docker.internal:1080 NO_PROXY: localhost,127.0.0.1 timeout-minutes: 30 steps: - name: Verify Collaborator Authorization id: auth-check run: | AUTHOR_ASSOC="${{ github.event.comment.author_association }}" echo "Author association: $AUTHOR_ASSOC" if [[ "$AUTHOR_ASSOC" != "OWNER" && "$AUTHOR_ASSOC" != "MEMBER" && "$AUTHOR_ASSOC" != "COLLABORATOR" ]]; then echo "::error::Unauthorized trigger by user with association '$AUTHOR_ASSOC'." exit 1 fi - name: Ensure GitHub CLI is Installed run: | if ! command -v gh &> /dev/null; then echo "Installing GitHub CLI..." curl -fsSL https://github.com/cli/cli/releases/download/v2.67.0/gh_2.67.0_linux_amd64.tar.gz | tar -xz -C /usr/local --strip-components=1 fi - name: Acknowledge Command (Add Eyes Reaction) if: success() env: GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }} COMMENT_ID: ${{ github.event.comment.id }} run: | gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}/reactions" -f content=eyes || true - name: Checkout Codebase uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }} - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 9.12.3 - name: Setup Node.js with pnpm cache uses: actions/setup-node@v4 with: node-version: 20 cache: 'pnpm' - name: Install Dependencies & Build Workspace Packages run: | pnpm install --frozen-lockfile pnpm build:deps - name: Restore Agent Conversation Context uses: actions/cache@v4 id: agent-context-cache with: path: | ~/.gemini/antigravity-cli/conversations ~/.gemini/antigravity-cli/brain key: agent-context-issue-${{ github.event.issue.number }}-${{ github.run_id }} restore-keys: | agent-context-issue-${{ github.event.issue.number }}- - name: Setup Antigravity CLI & Credentials env: GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }} AGY_AUTH_TOKEN: ${{ secrets.AGY_AUTH_TOKEN }} run: | # 1. Download official Antigravity CLI binary from google-antigravity/antigravity-cli mkdir -p "$HOME/.local/bin" if ! command -v agy &> /dev/null; then echo "Fetching Antigravity CLI from google-antigravity/antigravity-cli..." gh release download --repo google-antigravity/antigravity-cli -p "agy_cli_linux_x64.tar.gz" -O - | tar -xz -C "$HOME/.local/bin" if [ -f "$HOME/.local/bin/antigravity" ] && [ ! -f "$HOME/.local/bin/agy" ]; then mv "$HOME/.local/bin/antigravity" "$HOME/.local/bin/agy" fi ln -sf "$HOME/.local/bin/agy" "$HOME/.local/bin/antigravity" chmod +x "$HOME/.local/bin/agy" "$HOME/.local/bin/antigravity" fi echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.gemini/antigravity-cli/bin" >> $GITHUB_PATH export PATH="$HOME/.local/bin:$HOME/.gemini/antigravity-cli/bin:$PATH" # 2. Patch location eligibility check (open-antigravity-patcher CLI_GATE_X64) node -e ' const fs = require("fs"); const file = process.env.HOME + "/.local/bin/agy"; if (!fs.existsSync(file)) process.exit(0); const buf = fs.readFileSync(file); let count = 0; for (let i = 0; i < buf.length - 18; i++) { if (buf[i] === 0x48 && buf[i+1] === 0x85 && buf[i+2] === 0xc0 && buf[i+3] === 0x0f && buf[i+4] === 0x84 && buf[i+9] === 0x80 && buf[i+10] === 0x78 && buf[i+11] === 0x08 && buf[i+12] === 0x00 && buf[i+13] === 0x0f && buf[i+14] === 0x85) { buf[i+9] = 0x48; buf[i+10] = 0x85; buf[i+11] = 0xc0; buf[i+12] = 0x90; count++; } } if (count > 0) { fs.writeFileSync(file, buf); console.log(`Applied open-antigravity-patcher: ${count} gates patched.`); } else { console.log("Antigravity CLI is already patched or signature not found."); } ' # 3. Inject OAuth Token mkdir -p ~/.gemini/antigravity-cli if [ -n "$AGY_AUTH_TOKEN" ]; then if echo "$AGY_AUTH_TOKEN" | base64 --decode >/dev/null 2>&1; then echo "$AGY_AUTH_TOKEN" | base64 --decode > ~/.gemini/antigravity-cli/antigravity-oauth-token else echo "$AGY_AUTH_TOKEN" > ~/.gemini/antigravity-cli/antigravity-oauth-token fi chmod 600 ~/.gemini/antigravity-cli/antigravity-oauth-token else echo "::warning::AGY_AUTH_TOKEN secret is not set." fi - name: Configure Git Bot Identity run: | git config --global user.name "Adam Jensen [bot]" git config --global user.email "adam@ermnvldmr.com" git config --global --add safe.directory "$GITHUB_WORKSPACE" # --- COMMAND: /plan --- - name: Handle /plan (Issue Planning) if: contains(github.event.comment.body, '/plan') && github.event.issue.pull_request == null env: GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }} ISSUE_NUMBER: ${{ github.event.issue.number }} COMMENT_BODY: ${{ github.event.comment.body }} run: | echo "Generating plan for Issue #${ISSUE_NUMBER}..." ISSUE_DATA=$(gh issue view "$ISSUE_NUMBER" --comments --json title,body,comments) CONTINUE_FLAG="" if [ -d "$HOME/.gemini/antigravity-cli/conversations" ] && [ "$(ls -A $HOME/.gemini/antigravity-cli/conversations 2>/dev/null)" ]; then CONTINUE_FLAG="--continue" fi PROMPT="You are operating via GitHub Actions in non-interactive headless mode on Issue #${ISSUE_NUMBER}.\n\nIssue Context:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nPlease generate/update a detailed technical implementation plan adhering to project GEMINI.md guidelines." PLAN_OUTPUT=$(agy $CONTINUE_FLAG --mode plan --dangerously-skip-permissions --print-timeout 20m -p "$PROMPT" || echo "Agent encountered an error generating the plan.") DISCLOSURE="\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" gh issue comment "$ISSUE_NUMBER" --body "${PLAN_OUTPUT}${DISCLOSURE}" # --- COMMAND: /implement --- - name: Handle /implement (Issue Implementation & PR) if: contains(github.event.comment.body, '/implement') && github.event.issue.pull_request == null env: GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }} ISSUE_NUMBER: ${{ github.event.issue.number }} COMMENT_BODY: ${{ github.event.comment.body }} run: | BRANCH_NAME="agent/issue-${ISSUE_NUMBER}" git checkout -b "$BRANCH_NAME" ISSUE_DATA=$(gh issue view "$ISSUE_NUMBER" --comments --json title,body,comments) CONTINUE_FLAG="" if [ -d "$HOME/.gemini/antigravity-cli/conversations" ] && [ "$(ls -A $HOME/.gemini/antigravity-cli/conversations 2>/dev/null)" ]; then CONTINUE_FLAG="--continue" fi PROMPT="You are operating via GitHub Actions in non-interactive headless mode to implement Issue #${ISSUE_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nLatest instruction:\n${COMMENT_BODY}\n\nTask: Inspect relevant files, implement the necessary code changes directly in the workspace adhering to GEMINI.md rules, and verify them. Do not exit or stop before applying edits to the source code." agy $CONTINUE_FLAG --dangerously-skip-permissions --print-timeout 25m -p "$PROMPT" echo "Running repository verification gates..." pnpm typecheck pnpm lint pnpm test ISSUE_TITLE=$(gh issue view "$ISSUE_NUMBER" --json title -q .title) git add -A if git diff --staged --quiet; then echo "No changes produced by agent." gh issue comment "$ISSUE_NUMBER" --body "No changes were produced for implementation.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" exit 0 fi git commit -m "feat: implement issue #${ISSUE_NUMBER} (${ISSUE_TITLE})" git push -u origin "$BRANCH_NAME" --force PR_BODY="Resolves #${ISSUE_NUMBER}\n\nAutomated implementation generated via \`/implement\`.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" gh pr create \ --title "feat: ${ISSUE_TITLE}" \ --body "$PR_BODY" \ --base next \ --head "$BRANCH_NAME" # --- COMMAND: /fix --- - name: Handle /fix (PR Review Adjustments & CI Failure Debugging) if: contains(github.event.comment.body, '/fix') env: GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }} ISSUE_OR_PR_NUMBER: ${{ github.event.issue.number }} COMMENT_BODY: ${{ github.event.comment.body }} run: | IS_PR="${{ github.event.issue.pull_request != null }}" if [ "$IS_PR" = "true" ]; then # Verify PR is not from an untrusted cross-repository fork IS_CROSS_REPO=$(gh pr view "$ISSUE_OR_PR_NUMBER" --json isCrossRepository -q .isCrossRepository) if [ "$IS_CROSS_REPO" = "true" ]; then echo "::error::Cross-repository fork PRs cannot be automatically processed in privileged context." exit 1 fi gh pr checkout "$ISSUE_OR_PR_NUMBER" BRANCH_NAME=$(git branch --show-current) PR_DIFF=$(gh pr diff "$ISSUE_OR_PR_NUMBER" || true) FAILED_RUN_ID=$(gh run list --branch "$BRANCH_NAME" --status failure --limit 1 --json databaseId -q '.[0].databaseId' || true) CI_LOGS="" if [ -n "$FAILED_RUN_ID" ] && [ "$FAILED_RUN_ID" != "null" ]; then echo "Found failed CI run: #$FAILED_RUN_ID. Fetching failure logs..." CI_LOGS=$(gh run view "$FAILED_RUN_ID" --log-failed | tail -n 200 || true) fi CONTINUE_FLAG="" if [ -d "$HOME/.gemini/antigravity-cli/conversations" ] && [ "$(ls -A $HOME/.gemini/antigravity-cli/conversations 2>/dev/null)" ]; then CONTINUE_FLAG="--continue" fi PROMPT="You are operating via GitHub Actions in non-interactive headless mode to fix/adjust PR #${ISSUE_OR_PR_NUMBER} on branch ${BRANCH_NAME}.\n\nFeedback / Comment:\n${COMMENT_BODY}\n\nPR Diff:\n${PR_DIFF}\n\nFailed CI Logs (if any):\n${CI_LOGS}\n\nTask: Apply the necessary fixes directly to the files, ensuring all lint, typecheck, and test checks pass. Do not exit without applying the changes." agy $CONTINUE_FLAG --dangerously-skip-permissions --print-timeout 25m -p "$PROMPT" echo "Running repository verification gates..." pnpm typecheck pnpm lint pnpm test git add -A if git diff --staged --quiet; then echo "No additional changes were needed." gh pr comment "$ISSUE_OR_PR_NUMBER" --body "Analyzed the request; no additional changes were needed.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" exit 0 fi git commit -m "fix: apply review adjustments and CI fixes" git push origin "$BRANCH_NAME" gh pr comment "$ISSUE_OR_PR_NUMBER" --body "Applied adjustments and verified build/test suite.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" else echo "Handling /fix on Issue #${ISSUE_OR_PR_NUMBER}..." BRANCH_NAME="agent/fix-issue-${ISSUE_OR_PR_NUMBER}" git checkout -b "$BRANCH_NAME" ISSUE_DATA=$(gh issue view "$ISSUE_OR_PR_NUMBER" --comments --json title,body,comments) PROMPT="You are operating via GitHub Actions in non-interactive headless mode to fix issue #${ISSUE_OR_PR_NUMBER}.\n\nContext:\n${ISSUE_DATA}\n\nInstruction:\n${COMMENT_BODY}\n\nTask: Apply the necessary fixes directly to the files adhering to GEMINI.md rules." agy --dangerously-skip-permissions --print-timeout 25m -p "$PROMPT" pnpm typecheck pnpm lint pnpm test git add -A git commit -m "fix: resolve issue #${ISSUE_OR_PR_NUMBER}" git push -u origin "$BRANCH_NAME" --force gh pr create \ --title "fix: resolve issue #${ISSUE_OR_PR_NUMBER}" \ --body "Resolves #${ISSUE_OR_PR_NUMBER}\n\nFix applied via \`/fix\`.\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" \ --base next \ --head "$BRANCH_NAME" fi - name: Complete Command (Add Rocket Reaction) if: success() env: GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }} COMMENT_ID: ${{ github.event.comment.id }} run: | gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}/reactions" -f content=rocket || true - name: Report Failure on Comment if: failure() env: GH_TOKEN: ${{ secrets.GITOPS_TOKEN || secrets.GITHUB_TOKEN }} ISSUE_NUMBER: ${{ github.event.issue.number }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | gh issue comment "$ISSUE_NUMBER" --body "⚠️ Workflow failed during execution. View run logs: [Action Run #${{ github.run_id }}](${RUN_URL})\n\n---\n*Disclosure: I'm an AI assistant helping deytenit; I'm not deytenit.*" || true