From ca79782cefd6b041de1c6a62918af32b058d44f8 Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 7 Feb 2026 19:47:21 +0000 Subject: [PATCH 1/5] chore: setup repository for npm publishing - Add MIT LICENSE for OpenStaticFish - Add .npmignore to exclude dev files - Rename package to @openstaticfish/actionflow v0.1.0 - Add npm publishing metadata (bin, files, exports, engines) - Update tsconfig.json for declaration generation - Update README.md with new package name and install instructions - Update Header.tsx UI title to ACTIONFLOW - Update AGENTS.md header reference Prepares repository for publishing to npm registry --- .npmignore | 29 +++++++++++++++++++ AGENTS.md | 2 +- LICENSE | 21 ++++++++++++++ README.md | 8 +++--- package.json | 52 +++++++++++++++++++++++++++++++---- src/tui/components/Header.tsx | 2 +- tsconfig.json | 12 ++++++-- 7 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 .npmignore create mode 100644 LICENSE diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..fc9f1c4 --- /dev/null +++ b/.npmignore @@ -0,0 +1,29 @@ +# Source files (we publish compiled dist/) +src/ + +# Development +node_modules/ +.github/ +CLAUDE.md +AGENTS.md +.env +.env.local + +# Build artifacts +dist/**/*.test.js +dist/**/*.test.d.ts +*.log + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Testing +coverage/ +.nyc_output/ + +# OS +.DS_Store +Thumbs.db diff --git a/AGENTS.md b/AGENTS.md index 3ab1457..7a4bd59 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -# Agent Guidelines for workflow-automator +# Agent Guidelines for ActionFlow This document provides guidelines for AI agents working on this repository. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..738c9f6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 OpenStaticFish + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 32e30bc..357fdd9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Workflow Automator +# ActionFlow Interactive TUI for installing curated GitHub Actions workflows with a cyberpunk aesthetic. @@ -30,8 +30,8 @@ bun run src/tui/index.tsx Or install globally: ```bash -bun link -workflow-automator +bun install -g @openstaticfish/actionflow +actionflow ``` ## Keyboard Shortcuts @@ -50,7 +50,7 @@ workflow-automator ``` ┌─────────────────────────────────────────────────────────────────┐ -│ ⚡ WORKFLOW AUTOMATOR v1.0 Category: [opencode ▼] │ +│ ⚡ ACTIONFLOW v0.1.0 Category: [opencode ▼] │ ├──────────────────┬──────────────────────────────────────────────┤ │ 🌲 Tree │ ┌─ Workflow Details ──────────────────────┐│ │ ▾ pr │ │ 🔍 OpenCode AI PR Review ││ diff --git a/package.json b/package.json index b1f5bf9..c64b48c 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,59 @@ { - "name": "workflow-automator", - "module": "src/tui/index.tsx", - "type": "module", - "private": true, + "name": "@openstaticfish/actionflow", + "version": "0.1.0", + "description": "A terminal UI tool for managing and installing GitHub Actions workflow templates", + "license": "MIT", + "author": "OpenStaticFish ", + "repository": { + "type": "git", + "url": "https://github.com/openstaticfish/actionflow.git" + }, + "homepage": "https://github.com/openstaticfish/actionflow#readme", + "bugs": { + "url": "https://github.com/openstaticfish/actionflow/issues" + }, + "keywords": [ + "github-actions", + "workflow", + "cli", + "terminal", + "tui", + "automation", + "ci-cd", + "templates" + ], + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, "bin": { - "workflow-automator": "./src/tui/index.tsx" + "actionflow": "./dist/index.js", + "af": "./dist/index.js" + }, + "files": [ + "dist", + "workflows", + "README.md", + "LICENSE" + ], + "engines": { + "bun": ">=1.0.0" }, "scripts": { "start": "bun run src/tui/index.tsx", "build": "bun build src/tui/index.tsx --outdir=dist --target=bun", + "build:types": "tsc --declaration --emitDeclarationOnly --outDir dist", + "prepublishOnly": "bun run build && bun run build:types", "test": "bun test" }, "devDependencies": { "@types/bun": "latest", - "@types/react": "^18.2.0" + "@types/react": "^18.2.0", + "typescript": "^5.0.0" }, "peerDependencies": { "typescript": "^5" diff --git a/src/tui/components/Header.tsx b/src/tui/components/Header.tsx index 843a68b..d30de13 100644 --- a/src/tui/components/Header.tsx +++ b/src/tui/components/Header.tsx @@ -36,7 +36,7 @@ export function Header({ alignItems="center" > - ⚡ WORKFLOW AUTOMATOR + ⚡ ACTIONFLOW diff --git a/tsconfig.json b/tsconfig.json index bfa0fea..ac576f8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ // Environment setup & latest features "lib": ["ESNext"], "target": "ESNext", - "module": "Preserve", + "module": "ESNext", "moduleDetection": "force", "jsx": "react-jsx", "allowJs": true, @@ -12,7 +12,11 @@ "moduleResolution": "bundler", "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, - "noEmit": true, + "noEmit": false, + "declaration": true, + "declarationMap": true, + "outDir": "./dist", + "rootDir": "./src", // Best practices "strict": true, @@ -25,5 +29,7 @@ "noUnusedLocals": false, "noUnusedParameters": false, "noPropertyAccessFromIndexSignature": false - } + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] } From 7b4783738991fdd7210d39eca19ed3a54e61630d Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 7 Feb 2026 19:56:19 +0000 Subject: [PATCH 2/5] fix: resolve YAML syntax error in OpenCode AI PR review workflow Fixes the heredoc syntax issue that was causing workflow validation failures. Replaced problematic heredoc with jq-based JSON construction for proper escaping of special characters in PR diff and comments. Changes: - workflows/opencode/pr/opencode-pr.yml: Use jq to build API payload - workflows/opencode/pr/opencode-pr-nix.yml: Same fix for Nix variant - .github/workflows/opencode-pr.yml: Apply fix to installed workflow This resolves the "Invalid workflow file" error that prevented the OpenCode AI PR review from running. --- .github/workflows/opencode-pr.yml | 44 +++++++-------------- workflows/opencode/pr/opencode-pr-nix.yml | 47 ++++++++--------------- workflows/opencode/pr/opencode-pr.yml | 44 +++++++-------------- 3 files changed, 45 insertions(+), 90 deletions(-) diff --git a/.github/workflows/opencode-pr.yml b/.github/workflows/opencode-pr.yml index fa63f65..5c879fb 100644 --- a/.github/workflows/opencode-pr.yml +++ b/.github/workflows/opencode-pr.yml @@ -67,41 +67,25 @@ jobs: # Read the diff file DIFF_CONTENT=$(cat "$PR_DIFF") - # Create the review prompt - PROMPT=$(cat < prompt.json # Call OpenCode AI API curl -X POST https://api.opencode.ai/v1/chat/completions \ -H "Authorization: Bearer $KIMI_API_KEY" \ -H "Content-Type: application/json" \ - -d "{ - \"model\": \"kimi-latest\", - \"messages\": [{\"role\": \"user\", \"content\": $(echo "$PROMPT" | jq -Rs .)}] - }" > review_response.json + -d @prompt.json > review_response.json # Extract and post review REVIEW_TEXT=$(cat review_response.json | jq -r '.choices[0].message.content') diff --git a/workflows/opencode/pr/opencode-pr-nix.yml b/workflows/opencode/pr/opencode-pr-nix.yml index b46e576..d71de1a 100644 --- a/workflows/opencode/pr/opencode-pr-nix.yml +++ b/workflows/opencode/pr/opencode-pr-nix.yml @@ -73,44 +73,31 @@ jobs: - name: Run OpenCode AI Review env: KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} + PR_TITLE: ${{ github.event.pull_request.title }} + PR_DESCRIPTION: ${{ github.event.pull_request.body }} + PREVIOUS_COMMENTS: ${{ steps.previous-comments.outputs.result }} run: | nix develop --command bash -c ' DIFF_CONTENT=$(cat pr_diff.txt) - PREVIOUS_COMMENTS="${{ steps.previous-comments.outputs.result }}" - PROMPT=$(cat < prompt.json curl -X POST https://api.opencode.ai/v1/chat/completions \ -H "Authorization: Bearer $KIMI_API_KEY" \ -H "Content-Type: application/json" \ - -d "{ - \"model\": \"kimi-latest\", - \"messages\": [{\"role\": \"user\", \"content\": $(echo "$PROMPT" | jq -Rs .)}] - }" > review_response.json + -d @prompt.json > review_response.json cat review_response.json | jq -r ".choices[0].message.content" > review_output.txt ' diff --git a/workflows/opencode/pr/opencode-pr.yml b/workflows/opencode/pr/opencode-pr.yml index fa63f65..5c879fb 100644 --- a/workflows/opencode/pr/opencode-pr.yml +++ b/workflows/opencode/pr/opencode-pr.yml @@ -67,41 +67,25 @@ jobs: # Read the diff file DIFF_CONTENT=$(cat "$PR_DIFF") - # Create the review prompt - PROMPT=$(cat < prompt.json # Call OpenCode AI API curl -X POST https://api.opencode.ai/v1/chat/completions \ -H "Authorization: Bearer $KIMI_API_KEY" \ -H "Content-Type: application/json" \ - -d "{ - \"model\": \"kimi-latest\", - \"messages\": [{\"role\": \"user\", \"content\": $(echo "$PROMPT" | jq -Rs .)}] - }" > review_response.json + -d @prompt.json > review_response.json # Extract and post review REVIEW_TEXT=$(cat review_response.json | jq -r '.choices[0].message.content') From c6c2e6af80d2e64e3e41be41ef708519b7f515f7 Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 7 Feb 2026 19:58:54 +0000 Subject: [PATCH 3/5] fix: resolve jq escape errors in OpenCode AI PR review workflow The previous fix had issues with backtick escaping in jq strings. Replaced inline jq string construction with printf for building the prompt, then pass the complete prompt to jq using --arg. This avoids escape character issues with backticks and newlines in the JSON construction. --- .github/workflows/opencode-pr.yml | 29 +++++++++++++---------- workflows/opencode/pr/opencode-pr-nix.yml | 23 ++++++++---------- workflows/opencode/pr/opencode-pr.yml | 29 +++++++++++++---------- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/.github/workflows/opencode-pr.yml b/.github/workflows/opencode-pr.yml index 5c879fb..cb7ca0f 100644 --- a/.github/workflows/opencode-pr.yml +++ b/.github/workflows/opencode-pr.yml @@ -67,19 +67,22 @@ jobs: # Read the diff file DIFF_CONTENT=$(cat "$PR_DIFF") - # Build prompt using jq - jq -n \ - --arg title "$PR_TITLE" \ - --arg desc "$PR_DESCRIPTION" \ - --arg previous "$PREVIOUS_COMMENTS" \ - --arg diff "$DIFF_CONTENT" \ - '{ - model: "kimi-latest", - messages: [{ - role: "user", - content: "You are an expert code reviewer. Review the following pull request:\n\nTitle: \($title)\n\nDescription: \($desc)\n\nPrevious Review Context:\n\($previous)\n\nCode Changes:\n\`\`\`diff\n\($diff)\n\`\`\`\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers." - }] - }' > prompt.json + # Build prompt using printf and jq + PROMPT=$(printf '%s\n\nTitle: %s\n\nDescription: %s\n\nPrevious Review Context:\n%s\n\nCode Changes:\n%s\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers.' \ + "You are an expert code reviewer. Review the following pull request:" \ + "$PR_TITLE" \ + "$PR_DESCRIPTION" \ + "$PREVIOUS_COMMENTS" \ + "$DIFF_CONTENT") + + # Create JSON payload using jq + jq -n --arg content "$PROMPT" '{ + model: "kimi-latest", + messages: [{ + role: "user", + content: $content + }] + }' > prompt.json # Call OpenCode AI API curl -X POST https://api.opencode.ai/v1/chat/completions \ diff --git a/workflows/opencode/pr/opencode-pr-nix.yml b/workflows/opencode/pr/opencode-pr-nix.yml index d71de1a..6602809 100644 --- a/workflows/opencode/pr/opencode-pr-nix.yml +++ b/workflows/opencode/pr/opencode-pr-nix.yml @@ -80,19 +80,16 @@ jobs: nix develop --command bash -c ' DIFF_CONTENT=$(cat pr_diff.txt) - # Build prompt using jq - jq -n \ - --arg title "$PR_TITLE" \ - --arg desc "$PR_DESCRIPTION" \ - --arg previous "$PREVIOUS_COMMENTS" \ - --arg diff "$DIFF_CONTENT" \ - \'{ - model: "kimi-latest", - messages: [{ - role: "user", - content: "You are an expert code reviewer. Review the following pull request:\n\nTitle: \($title)\n\nDescription: \($desc)\n\nPrevious Review Context:\n\($previous)\n\nCode Changes:\n\`\`\`diff\n\($diff)\n\`\`\`\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers." - }] - }\' > prompt.json + # Build prompt using printf and jq + PROMPT=$(printf "%s\n\nTitle: %s\n\nDescription: %s\n\nPrevious Review Context:\n%s\n\nCode Changes:\n%s\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers." \ + "You are an expert code reviewer. Review the following pull request:" \ + "$PR_TITLE" \ + "$PR_DESCRIPTION" \ + "$PREVIOUS_COMMENTS" \ + "$DIFF_CONTENT") + + # Create JSON payload using jq + jq -n --arg content "$PROMPT" "{\n model: \\"kimi-latest\\",\n messages: [{\n role: \\"user\\",\n content: $content\n }]\n }" > prompt.json curl -X POST https://api.opencode.ai/v1/chat/completions \ -H "Authorization: Bearer $KIMI_API_KEY" \ diff --git a/workflows/opencode/pr/opencode-pr.yml b/workflows/opencode/pr/opencode-pr.yml index 5c879fb..cb7ca0f 100644 --- a/workflows/opencode/pr/opencode-pr.yml +++ b/workflows/opencode/pr/opencode-pr.yml @@ -67,19 +67,22 @@ jobs: # Read the diff file DIFF_CONTENT=$(cat "$PR_DIFF") - # Build prompt using jq - jq -n \ - --arg title "$PR_TITLE" \ - --arg desc "$PR_DESCRIPTION" \ - --arg previous "$PREVIOUS_COMMENTS" \ - --arg diff "$DIFF_CONTENT" \ - '{ - model: "kimi-latest", - messages: [{ - role: "user", - content: "You are an expert code reviewer. Review the following pull request:\n\nTitle: \($title)\n\nDescription: \($desc)\n\nPrevious Review Context:\n\($previous)\n\nCode Changes:\n\`\`\`diff\n\($diff)\n\`\`\`\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers." - }] - }' > prompt.json + # Build prompt using printf and jq + PROMPT=$(printf '%s\n\nTitle: %s\n\nDescription: %s\n\nPrevious Review Context:\n%s\n\nCode Changes:\n%s\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers.' \ + "You are an expert code reviewer. Review the following pull request:" \ + "$PR_TITLE" \ + "$PR_DESCRIPTION" \ + "$PREVIOUS_COMMENTS" \ + "$DIFF_CONTENT") + + # Create JSON payload using jq + jq -n --arg content "$PROMPT" '{ + model: "kimi-latest", + messages: [{ + role: "user", + content: $content + }] + }' > prompt.json # Call OpenCode AI API curl -X POST https://api.opencode.ai/v1/chat/completions \ From d4d50fdfc5d1de78cd29e37bf72be20c4adb8286 Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 7 Feb 2026 20:20:04 +0000 Subject: [PATCH 4/5] fix: update OpenCode workflow templates to use GitHub Action Replaced broken heredoc/curl approach with anomalyco/opencode/github@latest GitHub Action, matching the working implementation from ZigCraft. Templates updated: - workflows/opencode/pr/opencode-pr.yml - workflows/opencode/opencode/opencode.yml - workflows/opencode/triage/opencode-triage.yml This fixes the YAML syntax errors and API integration issues. --- workflows/opencode/opencode/opencode.yml | 98 ++-------- workflows/opencode/pr/opencode-pr.yml | 182 ++++++++++-------- workflows/opencode/triage/opencode-triage.yml | 155 +++++---------- 3 files changed, 173 insertions(+), 262 deletions(-) diff --git a/workflows/opencode/opencode/opencode.yml b/workflows/opencode/opencode/opencode.yml index 5e31650..3cd58c2 100644 --- a/workflows/opencode/opencode/opencode.yml +++ b/workflows/opencode/opencode/opencode.yml @@ -2,8 +2,8 @@ # id: opencode/opencode # category: opencode # type: set -# name: OpenCode Slash Commands -# description: Responds to /oc and /opencode commands in issues and PRs +# name: OpenCode AI Slash Commands +# description: OpenCode AI slash command handler (/oc, /opencode) # secrets: # - name: KIMI_API_KEY # description: API key for OpenCode AI service @@ -12,12 +12,10 @@ # triggers: [issue_comment, pull_request_review_comment] # variants: # - name: standard -# description: Uses standard GitHub Actions with direct API calls -# - name: nix -# description: Uses Nix for reproducible environment +# description: Uses OpenCode GitHub Action # --- -name: OpenCode Slash Commands +name: OpenCode AI Slash Commands on: issue_comment: @@ -26,84 +24,30 @@ on: types: [created] jobs: - handle-command: + opencode: + if: | + contains(github.event.comment.body, ' /oc') || + startsWith(github.event.comment.body, '/oc') || + contains(github.event.comment.body, ' /opencode') || + startsWith(github.event.comment.body, '/opencode') runs-on: ubuntu-latest - if: github.event.comment.body =~ /^\/(oc|opencode)\b/ - + permissions: + id-token: write + contents: write + pull-requests: write + issues: write steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Parse command - id: parse + - name: Configure git run: | - COMMENT_BODY="${{ github.event.comment.body }}" - - # Extract command after /oc or /opencode - if [[ "$COMMENT_BODY" =~ ^/oc\s*(.*) ]]; then - COMMAND="${BASH_REMATCH[1]}" - elif [[ "$COMMENT_BODY" =~ ^/opencode\s*(.*) ]]; then - COMMAND="${BASH_REMATCH[1]}" - fi - - echo "command=$COMMAND" >> $GITHUB_OUTPUT - echo "Parsed command: $COMMAND" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" - - name: Gather context - id: context - run: | - # Get issue/PR context - if [ "${{ github.event.issue.number }}" != "" ]; then - echo "type=issue" >> $GITHUB_OUTPUT - echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT - else - echo "type=pr" >> $GITHUB_OUTPUT - echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT - fi - - - name: Run OpenCode AI + - name: Run opencode + uses: anomalyco/opencode/github@latest env: KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} - COMMAND: ${{ steps.parse.outputs.command }} - CONTEXT_TYPE: ${{ steps.context.outputs.type }} - ISSUE_NUMBER: ${{ steps.context.outputs.number }} - run: | - # Build context for AI - PROMPT=$(cat < response.json - - cat response.json | jq -r '.choices[0].message.content' > response.txt - - - name: Post response - uses: actions/github-script@v7 with: - script: | - const fs = require('fs'); - const response = fs.readFileSync('response.txt', 'utf8'); - - const reply = `🤖 **OpenCode AI**\n\n${response}`; - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: ${{ steps.context.outputs.number }}, - body: reply - }); + model: kimi-for-coding/k2p5 diff --git a/workflows/opencode/pr/opencode-pr.yml b/workflows/opencode/pr/opencode-pr.yml index cb7ca0f..ad4d289 100644 --- a/workflows/opencode/pr/opencode-pr.yml +++ b/workflows/opencode/pr/opencode-pr.yml @@ -12,9 +12,7 @@ # triggers: [pull_request] # variants: # - name: standard -# description: Uses standard GitHub Actions with direct API calls -# - name: nix -# description: Uses Nix for reproducible environment +# description: Uses OpenCode GitHub Action # --- name: OpenCode AI PR Review @@ -24,89 +22,119 @@ on: types: [opened, synchronize, reopened, ready_for_review] jobs: - review: + opencode: + # Don't run on draft PRs; do run when they become ready_for_review. + if: ${{ github.event.pull_request.draft == false }} runs-on: ubuntu-latest - if: github.event.pull_request.draft == false - + timeout-minutes: 10 + permissions: + id-token: write + contents: write + pull-requests: write + issues: read + steps: - - name: Checkout code + - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Get PR diff - id: diff + - name: Configure git run: | - git diff origin/${{ github.base_ref }}...HEAD > pr_diff.txt - echo "diff_path=pr_diff.txt" >> $GITHUB_OUTPUT + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" - - name: Get previous review comments - id: previous-comments - uses: actions/github-script@v7 - with: - script: | - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number - }); - const opencodeComments = comments.data.filter(c => - c.user.login === 'github-actions[bot]' && - c.body.includes('OpenCode AI Review') - ); - return opencodeComments.map(c => c.body).join('\n---\n'); - - - name: Run OpenCode AI Review + - name: Run opencode + uses: anomalyco/opencode/github@latest env: KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} - PR_DIFF: ${{ steps.diff.outputs.diff_path }} - PREVIOUS_COMMENTS: ${{ steps.previous-comments.outputs.result }} - PR_TITLE: ${{ github.event.pull_request.title }} - PR_DESCRIPTION: ${{ github.event.pull_request.body }} - run: | - # Read the diff file - DIFF_CONTENT=$(cat "$PR_DIFF") - - # Build prompt using printf and jq - PROMPT=$(printf '%s\n\nTitle: %s\n\nDescription: %s\n\nPrevious Review Context:\n%s\n\nCode Changes:\n%s\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers.' \ - "You are an expert code reviewer. Review the following pull request:" \ - "$PR_TITLE" \ - "$PR_DESCRIPTION" \ - "$PREVIOUS_COMMENTS" \ - "$DIFF_CONTENT") - - # Create JSON payload using jq - jq -n --arg content "$PROMPT" '{ - model: "kimi-latest", - messages: [{ - role: "user", - content: $content - }] - }' > prompt.json - - # Call OpenCode AI API - curl -X POST https://api.opencode.ai/v1/chat/completions \ - -H "Authorization: Bearer $KIMI_API_KEY" \ - -H "Content-Type: application/json" \ - -d @prompt.json > review_response.json - - # Extract and post review - REVIEW_TEXT=$(cat review_response.json | jq -r '.choices[0].message.content') - - echo "$REVIEW_TEXT" > review_output.txt - cat review_output.txt - - - name: Post review comment - uses: actions/github-script@v7 with: - script: | - const fs = require('fs'); - const reviewText = fs.readFileSync('review_output.txt', 'utf8'); - const formattedReview = `## OpenCode AI Review 🤖\n\n${reviewText}`; + model: kimi-for-coding/k2p5 + prompt: | + You are reviewing a pull request. Analyze the code changes and output your review in the following STRICT STRUCTURE: + + --- + + ## 📋 Summary + First, check if the PR description mentions any linked issues (e.g., "Closes #123", "Fixes #456", "Resolves #789"). + + If linked issues are found: + - Mention the issue number(s) explicitly + - Verify the PR actually implements what the issue(s) requested + - State whether the implementation fully satisfies the issue requirements + + Then provide 2-3 sentences summarizing the PR purpose, scope, and overall quality. + + ## 🔴 Critical Issues (Must Fix - Blocks Merge) + Only issues that could cause crashes, security vulnerabilities, data loss, or major bugs. + + For each issue, use this exact format: + ``` + **[CRITICAL]** `File:Line` - Issue Title + **Confidence:** High|Medium|Low (how sure you are this is a real problem) + **Description:** Clear explanation of the issue + **Impact:** What could go wrong if merged + **Suggested Fix:** Specific code changes needed + ``` + + ## ⚠️ High Priority Issues (Should Fix) + Significant code quality issues, potential bugs, or architectural problems. + + Same format as Critical, but with **[HIGH]** prefix. + + ## 💡 Medium Priority Issues (Nice to Fix) + Style issues, minor optimizations, or code clarity improvements. - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: formattedReview - }); + Same format, with **[MEDIUM]** prefix. + + ## ℹ️ Low Priority Suggestions (Optional) + Minor suggestions, documentation improvements, or subjective preferences. + + Same format, with **[LOW]** prefix. + + ## 📊 SOLID Principles Score + | Principle | Score | Notes | + |-----------|-------|-------| + | Single Responsibility | 0-10 | Brief justification | + | Open/Closed | 0-10 | Brief justification | + | Liskov Substitution | 0-10 | Brief justification | + | Interface Segregation | 0-10 | Brief justification | + | Dependency Inversion | 0-10 | Brief justification | + | **Average** | **X.X** | | + + ## 🎯 Final Assessment + + ### Overall Confidence Score: XX% + Rate your confidence in this PR being ready to merge (0-100%). + **How to interpret:** + - 0-30%: Major concerns, do not merge without significant rework + - 31-60%: Moderate concerns, several issues need addressing + - 61-80%: Minor concerns, mostly ready with some fixes + - 81-100%: High confidence, ready to merge or with trivial fixes + + ### Confidence Breakdown: + - **Code Quality:** XX% (how well-written is the code?) + - **Completeness:** XX% (does it fulfill requirements?) + - **Risk Level:** XX% (how risky is this change?) + - **Test Coverage:** XX% (are changes adequately tested?) + + ### Merge Readiness: + - [ ] All critical issues resolved + - [ ] SOLID average score >= 6.0 + - [ ] Overall confidence >= 60% + - [ ] No security concerns + - [ ] Tests present and passing (if applicable) + + ### Verdict: + **MERGE** | **MERGE WITH FIXES** | **DO NOT MERGE** + + One-sentence explanation of the verdict. + + --- + + **Review Guidelines:** + 1. Check the PR description for linked issues ("Fixes #123", "Closes #456", etc.) and verify the implementation + 2. Be extremely specific with file paths and line numbers + 3. Confidence scores should reflect how certain you are - use "Low" when unsure + 4. If you have nothing meaningful to add to a section, write "None identified" instead of omitting it + 5. Always provide actionable fixes, never just complaints diff --git a/workflows/opencode/triage/opencode-triage.yml b/workflows/opencode/triage/opencode-triage.yml index bcf418d..3be020a 100644 --- a/workflows/opencode/triage/opencode-triage.yml +++ b/workflows/opencode/triage/opencode-triage.yml @@ -2,8 +2,8 @@ # id: opencode/opencode-triage # category: opencode # type: set -# name: OpenCode Issue Triage -# description: AI-powered issue classification and initial response for new issues +# name: OpenCode AI Issue Triage +# description: Automated issue triage using OpenCode AI # secrets: # - name: KIMI_API_KEY # description: API key for OpenCode AI service @@ -12,10 +12,10 @@ # triggers: [issues] # variants: # - name: standard -# description: Uses standard GitHub Actions +# description: Uses OpenCode GitHub Action # --- -name: OpenCode Issue Triage +name: OpenCode AI Issue Triage on: issues: @@ -24,119 +24,58 @@ on: jobs: triage: runs-on: ubuntu-latest - + permissions: + id-token: write + contents: write + pull-requests: write + issues: write steps: - name: Check account age - id: account-check + id: check uses: actions/github-script@v7 with: script: | - const { data: user } = await github.rest.users.getByUsername({ + const user = await github.rest.users.getByUsername({ username: context.payload.issue.user.login }); - - const createdAt = new Date(user.created_at); - const now = new Date(); - const daysOld = (now - createdAt) / (1000 * 60 * 60 * 24); - - console.log(`Account is ${daysOld} days old`); - - if (daysOld < 30) { - console.log('Account is new, skipping AI triage'); - return 'skip'; - } - return 'process'; + const created = new Date(user.data.created_at); + const days = (Date.now() - created) / (1000 * 60 * 60 * 24); + return days >= 30; + result-encoding: string - - name: Checkout repository - if: steps.account-check.outputs.result == 'process' - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + if: steps.check.outputs.result == 'true' - - name: Analyze issue - if: steps.account-check.outputs.result == 'process' - env: - KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} - ISSUE_TITLE: ${{ github.event.issue.title }} - ISSUE_BODY: ${{ github.event.issue.body }} + - name: Configure git + if: steps.check.outputs.result == 'true' run: | - PROMPT=$(cat < analysis.json - - cat analysis.json | jq -r '.choices[0].message.content' > analysis.txt - cat analysis.txt - - - name: Apply labels and respond - if: steps.account-check.outputs.result == 'process' - uses: actions/github-script@v7 + - uses: anomalyco/opencode/github@latest + if: steps.check.outputs.result == 'true' + env: + KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} with: - script: | - const fs = require('fs'); - const content = fs.readFileSync('analysis.txt', 'utf8'); - - // Try to parse JSON response - let analysis; - try { - // Extract JSON from markdown code block if present - const jsonMatch = content.match(/```json\n?([\s\S]*?)\n?```/) || - content.match(/\{[\s\S]*\}/); - analysis = JSON.parse(jsonMatch ? jsonMatch[1] || jsonMatch[0] : content); - } catch (e) { - console.log('Failed to parse JSON, using raw response'); - analysis = { - classification: 'Unknown', - response: content - }; - } - - // Apply classification label - const labelMap = { - 'Bug': 'bug', - 'Feature Request': 'enhancement', - 'Question': 'question' - }; - - if (labelMap[analysis.classification]) { - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - labels: [labelMap[analysis.classification]] - }); - } - - // Post AI response - const response = analysis.response || content; - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: `🤖 **OpenCode AI Triage**\n\n**Classification:** ${analysis.classification || 'Unknown'}\n**Priority:** ${analysis.priority || 'Unknown'}\n\n${response}` - }); + model: kimi-for-coding/k2p5 + prompt: | + Analyze this issue. You have access to the codebase context. + **CRITICAL: Your only allowed action is to post a COMMENT on the issue. DO NOT create branches, pull requests, or attempt to modify the codebase.** + + 1. **Classify**: Determine if this is a Bug, Feature Request, or Question. + 2. **Validate & Request Info**: + - **Missing Data**: If critical information is needed to understand or reproduce the issue (e.g., reproduction steps, crash logs, version numbers, screenshots), explicitly ask the user to provide it. + 3. **Analyze**: + - If a stack trace or error is provided, analyze the codebase to find the root cause and provide code pointers. + - If it's a feature request, briefly summarize the architectural impact. + - **Check for Scope**: Determine if this issue is too broad or complex and should be broken down into smaller, manageable sub-issues. Consider breaking up if: + - Multiple unrelated changes or features are requested + - The scope spans multiple subsystems (e.g., graphics + physics + UI) + - The issue description is vague or covers multiple distinct problems + - The implementation would require multiple independent PRs + 4. **Action**: + - Your response MUST be a comment on the issue. + - If you can provide a potential fix or documentation link, describe it in the comment but do NOT implement it. + - If you need more info, specify exactly what is missing. + - If the issue is vague, spam, or you have nothing valuable to add: **DO NOT COMMENT**. + - If the issue should be broken into sub-issues, clearly state this and suggest specific sub-tasks or areas to split. From 699ab933bd3cbef553d44414cfdcddc9b4062302 Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 7 Feb 2026 20:31:02 +0000 Subject: [PATCH 5/5] chore: apply fixed opencode-pr workflow via CLI tool --- .github/workflows/opencode-pr.yml | 182 +++++++++++++++++------------- 1 file changed, 105 insertions(+), 77 deletions(-) diff --git a/.github/workflows/opencode-pr.yml b/.github/workflows/opencode-pr.yml index cb7ca0f..ad4d289 100644 --- a/.github/workflows/opencode-pr.yml +++ b/.github/workflows/opencode-pr.yml @@ -12,9 +12,7 @@ # triggers: [pull_request] # variants: # - name: standard -# description: Uses standard GitHub Actions with direct API calls -# - name: nix -# description: Uses Nix for reproducible environment +# description: Uses OpenCode GitHub Action # --- name: OpenCode AI PR Review @@ -24,89 +22,119 @@ on: types: [opened, synchronize, reopened, ready_for_review] jobs: - review: + opencode: + # Don't run on draft PRs; do run when they become ready_for_review. + if: ${{ github.event.pull_request.draft == false }} runs-on: ubuntu-latest - if: github.event.pull_request.draft == false - + timeout-minutes: 10 + permissions: + id-token: write + contents: write + pull-requests: write + issues: read + steps: - - name: Checkout code + - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Get PR diff - id: diff + - name: Configure git run: | - git diff origin/${{ github.base_ref }}...HEAD > pr_diff.txt - echo "diff_path=pr_diff.txt" >> $GITHUB_OUTPUT + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" - - name: Get previous review comments - id: previous-comments - uses: actions/github-script@v7 - with: - script: | - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number - }); - const opencodeComments = comments.data.filter(c => - c.user.login === 'github-actions[bot]' && - c.body.includes('OpenCode AI Review') - ); - return opencodeComments.map(c => c.body).join('\n---\n'); - - - name: Run OpenCode AI Review + - name: Run opencode + uses: anomalyco/opencode/github@latest env: KIMI_API_KEY: ${{ secrets.KIMI_API_KEY }} - PR_DIFF: ${{ steps.diff.outputs.diff_path }} - PREVIOUS_COMMENTS: ${{ steps.previous-comments.outputs.result }} - PR_TITLE: ${{ github.event.pull_request.title }} - PR_DESCRIPTION: ${{ github.event.pull_request.body }} - run: | - # Read the diff file - DIFF_CONTENT=$(cat "$PR_DIFF") - - # Build prompt using printf and jq - PROMPT=$(printf '%s\n\nTitle: %s\n\nDescription: %s\n\nPrevious Review Context:\n%s\n\nCode Changes:\n%s\n\nProvide a structured review with:\n1. Overall assessment (merge-ready, needs changes, etc.)\n2. Critical issues (if any)\n3. High-priority improvements\n4. Medium-priority suggestions\n5. Low-priority nitpicks\n6. Confidence score (0-100)\n\nFormat as markdown with clear headers.' \ - "You are an expert code reviewer. Review the following pull request:" \ - "$PR_TITLE" \ - "$PR_DESCRIPTION" \ - "$PREVIOUS_COMMENTS" \ - "$DIFF_CONTENT") - - # Create JSON payload using jq - jq -n --arg content "$PROMPT" '{ - model: "kimi-latest", - messages: [{ - role: "user", - content: $content - }] - }' > prompt.json - - # Call OpenCode AI API - curl -X POST https://api.opencode.ai/v1/chat/completions \ - -H "Authorization: Bearer $KIMI_API_KEY" \ - -H "Content-Type: application/json" \ - -d @prompt.json > review_response.json - - # Extract and post review - REVIEW_TEXT=$(cat review_response.json | jq -r '.choices[0].message.content') - - echo "$REVIEW_TEXT" > review_output.txt - cat review_output.txt - - - name: Post review comment - uses: actions/github-script@v7 with: - script: | - const fs = require('fs'); - const reviewText = fs.readFileSync('review_output.txt', 'utf8'); - const formattedReview = `## OpenCode AI Review 🤖\n\n${reviewText}`; + model: kimi-for-coding/k2p5 + prompt: | + You are reviewing a pull request. Analyze the code changes and output your review in the following STRICT STRUCTURE: + + --- + + ## 📋 Summary + First, check if the PR description mentions any linked issues (e.g., "Closes #123", "Fixes #456", "Resolves #789"). + + If linked issues are found: + - Mention the issue number(s) explicitly + - Verify the PR actually implements what the issue(s) requested + - State whether the implementation fully satisfies the issue requirements + + Then provide 2-3 sentences summarizing the PR purpose, scope, and overall quality. + + ## 🔴 Critical Issues (Must Fix - Blocks Merge) + Only issues that could cause crashes, security vulnerabilities, data loss, or major bugs. + + For each issue, use this exact format: + ``` + **[CRITICAL]** `File:Line` - Issue Title + **Confidence:** High|Medium|Low (how sure you are this is a real problem) + **Description:** Clear explanation of the issue + **Impact:** What could go wrong if merged + **Suggested Fix:** Specific code changes needed + ``` + + ## ⚠️ High Priority Issues (Should Fix) + Significant code quality issues, potential bugs, or architectural problems. + + Same format as Critical, but with **[HIGH]** prefix. + + ## 💡 Medium Priority Issues (Nice to Fix) + Style issues, minor optimizations, or code clarity improvements. - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: formattedReview - }); + Same format, with **[MEDIUM]** prefix. + + ## ℹ️ Low Priority Suggestions (Optional) + Minor suggestions, documentation improvements, or subjective preferences. + + Same format, with **[LOW]** prefix. + + ## 📊 SOLID Principles Score + | Principle | Score | Notes | + |-----------|-------|-------| + | Single Responsibility | 0-10 | Brief justification | + | Open/Closed | 0-10 | Brief justification | + | Liskov Substitution | 0-10 | Brief justification | + | Interface Segregation | 0-10 | Brief justification | + | Dependency Inversion | 0-10 | Brief justification | + | **Average** | **X.X** | | + + ## 🎯 Final Assessment + + ### Overall Confidence Score: XX% + Rate your confidence in this PR being ready to merge (0-100%). + **How to interpret:** + - 0-30%: Major concerns, do not merge without significant rework + - 31-60%: Moderate concerns, several issues need addressing + - 61-80%: Minor concerns, mostly ready with some fixes + - 81-100%: High confidence, ready to merge or with trivial fixes + + ### Confidence Breakdown: + - **Code Quality:** XX% (how well-written is the code?) + - **Completeness:** XX% (does it fulfill requirements?) + - **Risk Level:** XX% (how risky is this change?) + - **Test Coverage:** XX% (are changes adequately tested?) + + ### Merge Readiness: + - [ ] All critical issues resolved + - [ ] SOLID average score >= 6.0 + - [ ] Overall confidence >= 60% + - [ ] No security concerns + - [ ] Tests present and passing (if applicable) + + ### Verdict: + **MERGE** | **MERGE WITH FIXES** | **DO NOT MERGE** + + One-sentence explanation of the verdict. + + --- + + **Review Guidelines:** + 1. Check the PR description for linked issues ("Fixes #123", "Closes #456", etc.) and verify the implementation + 2. Be extremely specific with file paths and line numbers + 3. Confidence scores should reflect how certain you are - use "Low" when unsure + 4. If you have nothing meaningful to add to a section, write "None identified" instead of omitting it + 5. Always provide actionable fixes, never just complaints