diff --git a/.github/workflows/comment-revalidation.yml b/.github/workflows/comment-revalidation.yml index fe65b1d..16c6317 100644 --- a/.github/workflows/comment-revalidation.yml +++ b/.github/workflows/comment-revalidation.yml @@ -35,8 +35,13 @@ on: required: false type: string default: 'gemini-2.5-flash' - openrouter-model: - description: 'OpenRouter model ID (when provider is opencode)' + opencode-provider: + description: 'AI provider for OpenCode (e.g., openrouter, anthropic, openai)' + required: false + type: string + default: 'openrouter' + opencode-model: + description: 'Model ID (when provider is opencode)' required: false type: string default: 'moonshotai/kimi-k2.5' @@ -54,8 +59,8 @@ on: GEMINI_SERVICE_ACCOUNT_KEY: description: 'Base64-encoded Gemini service account key (required when provider is gemini)' required: false - OPENROUTER_API_KEY: - description: 'OpenRouter API key (required when provider is opencode)' + OPENCODE_API_KEY: + description: 'OpenCode provider API key (required when provider is opencode)' required: false USABLE_API_TOKEN: description: 'Usable API token' @@ -288,14 +293,15 @@ jobs: base-ref: ${{ steps.base-ref.outputs.base-ref }} provider: ${{ inputs.provider || 'opencode' }} gemini-model: ${{ inputs.gemini-model || 'gemini-2.5-flash' }} - openrouter-model: ${{ inputs.openrouter-model || 'moonshotai/kimi-k2.5' }} + opencode-provider: ${{ inputs.opencode-provider || 'openrouter' }} + opencode-model: ${{ inputs.opencode-model || 'moonshotai/kimi-k2.5' }} comment-title: ${{ inputs.comment-title || '🔄 Revalidation (Comment Triggered)' }} comment-mode: 'create' fail-on-critical: ${{ inputs.fail-on-critical || false }} override-comment: ${{ needs.check-trigger.outputs.comment-body }} env: GEMINI_SERVICE_ACCOUNT_KEY: ${{ secrets.GEMINI_SERVICE_ACCOUNT_KEY }} - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} COMMENT_AUTHOR: ${{ github.event.comment.user.login }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 449d5d1..81d516f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -319,7 +319,7 @@ jobs: fail-on-critical: false provider: 'opencode' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} GEMINI_SERVICE_ACCOUNT_KEY: ${{ secrets.GEMINI_SERVICE_ACCOUNT_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} @@ -438,7 +438,7 @@ jobs: fail-on-critical: false provider: 'opencode' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} GEMINI_SERVICE_ACCOUNT_KEY: ${{ secrets.GEMINI_SERVICE_ACCOUNT_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} @@ -579,7 +579,7 @@ jobs: fail-on-critical: false provider: 'opencode' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} GEMINI_SERVICE_ACCOUNT_KEY: ${{ secrets.GEMINI_SERVICE_ACCOUNT_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} COMMENT_AUTHOR: 'test-user' diff --git a/README.md b/README.md index ff9e9b1..1936b4c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🤖 Usable PR Validator -> Validate Pull Requests against your Usable knowledge base standards using AI (OpenCode/OpenRouter or Google Gemini) +> Validate Pull Requests against your Usable knowledge base standards using AI (OpenCode with OpenRouter, Anthropic, OpenAI, or Google Gemini) [![GitHub Marketplace](https://img.shields.io/badge/Marketplace-Usable%20PR%20Validator-blue?logo=github)](https://github.com/marketplace/actions/usable-pr-validator) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) @@ -8,8 +8,8 @@ ## ✨ Features -- 🧠 **AI-Powered Validation**: Uses OpenCode/OpenRouter (default) or Google Gemini to understand context and architectural patterns -- 🔀 **Multi-Provider Support**: Choose between OpenRouter (75+ models) or Google Gemini +- 🧠 **AI-Powered Validation**: Uses OpenCode with OpenRouter (default), Anthropic, OpenAI, or Google Gemini to understand context and architectural patterns +- 🔀 **Multi-Provider Support**: Choose between OpenRouter (75+ models), Anthropic, OpenAI, or Google Gemini - 📚 **Usable Integration**: Validate PRs against your team's knowledge base stored in Usable - 🔌 **MCP Protocol**: Connects directly to Usable's MCP server for real-time standards - 🎯 **System Prompts**: Organization-wide validation standards fetched from Usable and auto-merged @@ -26,8 +26,8 @@ ### Prerequisites -**For OpenRouter (default provider):** -1. An OpenRouter API key ([get one at openrouter.ai](https://openrouter.ai/settings/keys)) +**For OpenCode (default, supports OpenRouter, Anthropic, OpenAI):** +1. An API key for your chosen provider (e.g., [OpenRouter](https://openrouter.ai/settings/keys), [Anthropic](https://console.anthropic.com/), or [OpenAI](https://platform.openai.com/)) 2. A Usable account with API token ([get one at usable.dev](https://usable.dev)) 3. GitHub repository with pull requests @@ -37,6 +37,24 @@ 3. A Usable account with API token ([get one at usable.dev](https://usable.dev)) 4. GitHub repository with pull requests +### Choosing a Provider + +Provider selection works in two levels: + +1. **`provider`** chooses the CLI tool: `opencode` (default) or `gemini` +2. **`opencode-provider`** chooses which AI service OpenCode connects to (only applies when `provider` is `opencode`) + +``` +provider +├── opencode (default) +│ └── opencode-provider +│ ├── openrouter (default) ─ 75+ models via OpenRouter +│ ├── anthropic ─ Claude models direct +│ └── openai ─ GPT models direct +└── gemini + └── Uses Google Gemini directly (configured via gemini-model) +``` + ### Step 1: Create Validation Prompt Create `.github/prompts/pr-validation.md` in your repository: @@ -64,10 +82,18 @@ git diff origin/{{BASE_BRANCH}}...{{HEAD_BRANCH}} Go to your repository Settings → Secrets → Actions and add: -**For OpenRouter (default):** -- `OPENROUTER_API_KEY`: Your OpenRouter API key (get from [openrouter.ai](https://openrouter.ai/settings/keys)) +**For OpenCode (default):** +- `OPENCODE_API_KEY`: Your AI provider API key (e.g., [OpenRouter](https://openrouter.ai/settings/keys), [Anthropic](https://console.anthropic.com/), or [OpenAI](https://platform.openai.com/)) - `USABLE_API_TOKEN`: Your Usable API token (get from [usable.dev](https://usable.dev) → Settings → API Tokens) +> If using a non-default provider, also set `opencode-provider` and `opencode-model` in your workflow: +> +> | Provider | `opencode-provider` | `opencode-model` example | +> |----------|--------------------|-----------------------| +> | OpenRouter (default) | `openrouter` | `moonshotai/kimi-k2.5` | +> | Anthropic | `anthropic` | `claude-sonnet-4-5` | +> | OpenAI | `openai` | `gpt-4o` | + **For Gemini (alternative):** - `GEMINI_SERVICE_ACCOUNT_KEY`: Base64-encoded service account JSON key @@ -105,7 +131,7 @@ jobs: prompt-file: '.github/prompts/pr-validation.md' workspace-id: 'your-workspace-uuid' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} ``` @@ -123,8 +149,9 @@ That's it! Your PRs will now be validated automatically. 🎉 | `workspace-id` | Usable workspace UUID (required - used to fetch MCP system prompt) | ✓ | | | `merge-custom-prompt` | Merge fetched Usable prompt with custom `prompt-file` (only when both are provided) | | `true` | | `provider` | AI provider to use (`opencode` or `gemini`) | | `opencode` | -| `openrouter-model` | OpenRouter model ID (when provider is `opencode`) | | `moonshotai/kimi-k2.5` | -| `openrouter-api-key-secret` | Secret name for OpenRouter API key | | `OPENROUTER_API_KEY` | +| `opencode-provider` | AI provider for OpenCode (e.g., `openrouter`, `anthropic`, `openai`) | | `openrouter` | +| `opencode-model` | Model ID for OpenCode | | `moonshotai/kimi-k2.5` | +| `opencode-api-key-secret` | Secret name for the configured opencode-provider API key | | `OPENCODE_API_KEY` | | `gemini-model` | Gemini model to use (when provider is `gemini`) | | `gemini-2.5-flash` | | `service-account-key-secret` | Secret name for Gemini service account key | | `GEMINI_SERVICE_ACCOUNT_KEY` | | `mcp-server-url` | Usable MCP server URL | | `https://usable.dev/api/mcp` | @@ -139,7 +166,7 @@ That's it! Your PRs will now be validated automatically. 🎉 | `head-ref` | Head reference for diff comparison | | PR head branch | | `allow-web-fetch` | Allow AI to use web_fetch tool for external resources (security consideration) | | `false` | -> **Note**: You must set the `USABLE_API_TOKEN` secret and either `OPENROUTER_API_KEY` (default provider) or `GEMINI_SERVICE_ACCOUNT_KEY` (gemini provider). Usable MCP integration is required for this action. +> **Note**: You must set the `USABLE_API_TOKEN` secret and either `OPENCODE_API_KEY` (default provider) or `GEMINI_SERVICE_ACCOUNT_KEY` (gemini provider). Usable MCP integration is required for this action. ### 🧠 System Prompts (Automatic) @@ -246,7 +273,7 @@ Instead of maintaining static prompt files, you can now fetch prompts dynamicall prompt-fragment-id: 'user-prompt-uuid' workspace-id: 'your-workspace-uuid' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} # Static user prompt file (most common) @@ -255,7 +282,7 @@ Instead of maintaining static prompt files, you can now fetch prompts dynamicall prompt-file: '.github/prompts/pr-validation.md' workspace-id: 'your-workspace-uuid' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} ``` @@ -270,7 +297,7 @@ Instead of maintaining static prompt files, you can now fetch prompts dynamicall ## 🎯 Usage Examples -### Minimal Setup (OpenRouter - default) +### Minimal Setup (OpenCode - default) ```yaml - uses: flowcore/usable-pr-validator@latest @@ -278,7 +305,7 @@ Instead of maintaining static prompt files, you can now fetch prompts dynamicall prompt-file: '.github/prompts/validate.md' workspace-id: 'your-workspace-uuid' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} ``` @@ -305,7 +332,7 @@ Instead of maintaining static prompt files, you can now fetch prompts dynamicall mcp-server-url: 'https://your-custom-mcp.com/api/mcp' mcp-token-secret: 'YOUR_CUSTOM_TOKEN' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} YOUR_CUSTOM_TOKEN: ${{ secrets.YOUR_MCP_TOKEN }} ``` @@ -317,7 +344,8 @@ Instead of maintaining static prompt files, you can now fetch prompts dynamicall prompt-file: '.github/validation/standards.md' workspace-id: 'your-workspace-uuid' provider: 'opencode' - openrouter-model: 'anthropic/claude-sonnet-4-5' + opencode-provider: 'anthropic' + opencode-model: 'claude-sonnet-4-5' mcp-server-url: 'https://confluence.company.com/api/mcp' mcp-token-secret: 'CONFLUENCE_TOKEN' fail-on-critical: true @@ -325,7 +353,7 @@ Instead of maintaining static prompt files, you can now fetch prompts dynamicall artifact-retention-days: 90 max-retries: 3 env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} CONFLUENCE_TOKEN: ${{ secrets.CONF_API_TOKEN }} ``` @@ -348,7 +376,7 @@ jobs: workspace-id: 'your-workspace-uuid' comment-title: 'Backend Validation' # Creates unique comment env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} validate-frontend: @@ -364,7 +392,7 @@ jobs: workspace-id: 'your-workspace-uuid' comment-title: 'Frontend Validation' # Creates unique comment env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} ``` @@ -410,7 +438,7 @@ jobs: workspace-id: 'your-workspace-uuid' base-ref: ${{ steps.base-ref.outputs.ref }} # Custom base reference env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} ``` @@ -491,7 +519,7 @@ Usable is a team knowledge base and memory system that stores your: ```bash # In your repo: Settings → Secrets → Actions USABLE_API_TOKEN=your_usable_token_here - OPENROUTER_API_KEY=your_openrouter_key_here + OPENCODE_API_KEY=your_api_key_here ``` 3. **Configure Workflow** @@ -502,7 +530,7 @@ Usable is a team knowledge base and memory system that stores your: prompt-file: '.github/prompts/pr-validation.md' workspace-id: 'your-workspace-uuid' env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} ``` @@ -573,11 +601,11 @@ jobs: # use-dynamic-prompts: true # prompt-fragment-id: 'fragment-uuid' # provider: 'opencode' - # openrouter-model: 'moonshotai/kimi-k2.5' + # opencode-model: 'moonshotai/kimi-k2.5' # comment-title: '🔄 Custom Title' # fail-on-critical: false secrets: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} permissions: contents: read @@ -700,7 +728,7 @@ The `allow-web-fetch` input controls whether the AI can download external resour prompt-file: '.github/prompts/validate-api-docs.md' allow-web-fetch: true # Only enable when needed env: - OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} USABLE_API_TOKEN: ${{ secrets.USABLE_API_TOKEN }} ``` @@ -985,7 +1013,7 @@ git clone https://github.com/flowcore/usable-pr-validator.git cd usable-pr-validator # Test locally (requires act) -act pull_request -s OPENROUTER_API_KEY="your-key-here" -s USABLE_API_TOKEN="your-token" +act pull_request -s OPENCODE_API_KEY="your-key-here" -s USABLE_API_TOKEN="your-token" ``` ## 📜 License diff --git a/action.yml b/action.yml index bd5a555..b134aa2 100644 --- a/action.yml +++ b/action.yml @@ -1,5 +1,5 @@ name: 'Usable PR Validator' -description: 'Validate Pull Requests against your Usable knowledge base standards using AI (OpenCode/OpenRouter or Google Gemini) and Usable MCP integration' +description: 'Validate Pull Requests against your Usable knowledge base standards using AI (OpenCode with OpenRouter, Anthropic, OpenAI, or Google Gemini) and Usable MCP integration' author: 'Flowcore' branding: @@ -86,14 +86,18 @@ inputs: description: 'AI provider to use (opencode or gemini)' required: false default: 'opencode' - openrouter-model: - description: 'OpenRouter model ID when provider is opencode (e.g., moonshotai/kimi-k2.5)' + opencode-provider: + description: 'AI provider for OpenCode (e.g., openrouter, anthropic, openai)' + required: false + default: 'openrouter' + opencode-model: + description: 'Model ID for OpenCode (e.g., moonshotai/kimi-k2.5 for openrouter, claude-sonnet-4-5 for anthropic)' required: false default: 'moonshotai/kimi-k2.5' - openrouter-api-key-secret: - description: 'Name of secret containing OpenRouter API key (when provider is opencode)' + opencode-api-key-secret: + description: 'Name of secret containing the API key for the configured opencode-provider' required: false - default: 'OPENROUTER_API_KEY' + default: 'OPENCODE_API_KEY' outputs: validation-status: @@ -196,7 +200,8 @@ runs: if: inputs.provider == 'opencode' shell: bash env: - OPENROUTER_SECRET_NAME: ${{ inputs.openrouter-api-key-secret }} + OPENCODE_PROVIDER: ${{ inputs.opencode-provider }} + OPENCODE_SECRET_NAME: ${{ inputs.opencode-api-key-secret }} run: | ${{ github.action_path }}/scripts/setup-opencode.sh @@ -319,7 +324,8 @@ runs: MCP_SECRET_NAME: ${{ inputs.mcp-token-secret }} WORKSPACE_ID: ${{ inputs.workspace-id }} PROVIDER: ${{ inputs.provider }} - OPENROUTER_MODEL: ${{ inputs.openrouter-model }} + OPENCODE_PROVIDER: ${{ inputs.opencode-provider }} + OPENCODE_MODEL: ${{ inputs.opencode-model }} run: | ${{ github.action_path }}/scripts/setup-mcp.sh @@ -344,7 +350,8 @@ runs: USE_DYNAMIC_PROMPTS: ${{ inputs.use-dynamic-prompts }} PROVIDER: ${{ inputs.provider }} GEMINI_MODEL: ${{ inputs.gemini-model }} - OPENROUTER_MODEL: ${{ inputs.openrouter-model }} + OPENCODE_PROVIDER: ${{ inputs.opencode-provider }} + OPENCODE_MODEL: ${{ inputs.opencode-model }} MAX_RETRIES: ${{ inputs.max-retries }} PR_NUMBER: ${{ github.event.pull_request.number }} PR_TITLE: ${{ github.event.pull_request.title }} @@ -384,7 +391,7 @@ runs: const provider = '${{ inputs.provider }}'; const modelInfo = provider === 'opencode' - ? 'OpenRouter ${{ inputs.openrouter-model }}' + ? '${{ inputs.opencode-provider }}/${{ inputs.opencode-model }}' : 'Google Gemini ${{ inputs.gemini-model }}'; const commentBody = marker + '\n## 🤖 ' + commentTitle + '\n\n' + diff --git a/scripts/setup-mcp.sh b/scripts/setup-mcp.sh index a2ec4f4..69eb3b7 100755 --- a/scripts/setup-mcp.sh +++ b/scripts/setup-mcp.sh @@ -7,7 +7,8 @@ echo "::group::Setting up MCP Server Integration" MCP_SECRET_NAME="${MCP_SECRET_NAME:-USABLE_API_TOKEN}" MCP_URL="${MCP_SERVER_URL:-https://usable.dev/api/mcp}" PROVIDER="${PROVIDER:-opencode}" -OPENROUTER_MODEL="${OPENROUTER_MODEL:-moonshotai/kimi-k2.5}" +OPENCODE_PROVIDER="${OPENCODE_PROVIDER:-openrouter}" +OPENCODE_MODEL="${OPENCODE_MODEL:-moonshotai/kimi-k2.5}" # Get the MCP token from environment using the secret name MCP_TOKEN="${!MCP_SECRET_NAME:-}" @@ -31,9 +32,9 @@ if [ "$PROVIDER" = "opencode" ]; then { "\$schema": "https://opencode.ai/config.json", "provider": { - "openrouter": {} + "${OPENCODE_PROVIDER}": {} }, - "model": "openrouter/${OPENROUTER_MODEL}", + "model": "${OPENCODE_PROVIDER}/${OPENCODE_MODEL}", "autoupdate": false, "mcp": { "usable": { @@ -58,7 +59,7 @@ EOF echo "✅ OpenCode MCP server configured" echo " URL: $MCP_URL" - echo " Model: openrouter/${OPENROUTER_MODEL}" + echo " Model: ${OPENCODE_PROVIDER}/${OPENCODE_MODEL}" echo " Settings file: ./opencode.json" # Debug: Show settings file content (mask token) diff --git a/scripts/setup-opencode.sh b/scripts/setup-opencode.sh index 988b210..44de57b 100755 --- a/scripts/setup-opencode.sh +++ b/scripts/setup-opencode.sh @@ -1,16 +1,17 @@ #!/usr/bin/env bash set -euo pipefail -echo "::group::Setting up OpenCode CLI + OpenRouter" +OPENCODE_PROVIDER="${OPENCODE_PROVIDER:-openrouter}" + +echo "::group::Setting up OpenCode CLI + ${OPENCODE_PROVIDER}" # Get the secret value from the environment using the secret name -SECRET_NAME="${OPENROUTER_SECRET_NAME:-OPENROUTER_API_KEY}" +SECRET_NAME="${OPENCODE_SECRET_NAME:-OPENCODE_API_KEY}" SECRET_VALUE="${!SECRET_NAME:-}" if [ -z "$SECRET_VALUE" ]; then - echo "::error::OpenRouter API key not found in environment variable: $SECRET_NAME" + echo "::error::API key not found in environment variable: $SECRET_NAME" echo "Please ensure the secret is set in your workflow: env.$SECRET_NAME" - echo "For local testing: export OPENROUTER_API_KEY=''" exit 1 fi @@ -43,13 +44,16 @@ fi echo "✅ OpenCode CLI installed: $(opencode --version 2>/dev/null || echo 'version unknown')" -# Export OpenRouter API key for OpenCode to use -export OPENROUTER_API_KEY="$SECRET_VALUE" +# Determine the correct env var name for the provider +# OpenCode expects provider-specific env vars (e.g., OPENROUTER_API_KEY, ANTHROPIC_API_KEY) +PROVIDER_ENV_VAR="$(echo "${OPENCODE_PROVIDER}" | tr '[:lower:]' '[:upper:]')_API_KEY" + +export "$PROVIDER_ENV_VAR"="$SECRET_VALUE" # Write to GITHUB_ENV for subsequent steps (if in GitHub Actions) if [ -n "${GITHUB_ENV:-}" ]; then - echo "OPENROUTER_API_KEY=$SECRET_VALUE" >> "$GITHUB_ENV" + echo "$PROVIDER_ENV_VAR=$SECRET_VALUE" >> "$GITHUB_ENV" fi -echo "✅ OpenRouter authentication configured" +echo "✅ ${OPENCODE_PROVIDER} authentication configured (${PROVIDER_ENV_VAR})" echo "::endgroup::" diff --git a/scripts/validate.sh b/scripts/validate.sh index a279391..b6a94f5 100755 --- a/scripts/validate.sh +++ b/scripts/validate.sh @@ -356,7 +356,9 @@ run_opencode() { local prompt_file="$1" local retry_count=0 local max_retries="${MAX_RETRIES:-2}" - local model="${OPENROUTER_MODEL:-moonshotai/kimi-k2.5}" + local opencode_provider="${OPENCODE_PROVIDER:-openrouter}" + local model="${OPENCODE_MODEL:-moonshotai/kimi-k2.5}" + local full_model="${opencode_provider}/${model}" while [ $retry_count -le "$max_retries" ]; do echo "Attempt $((retry_count + 1))/$((max_retries + 1)): Running OpenCode validation..." @@ -374,7 +376,7 @@ run_opencode() { # Show detailed execution info echo "🤖 Running OpenCode CLI" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "Model: openrouter/$model" + echo "Model: $full_model" echo "Prompt size: $(wc -c < "$prompt_file") bytes" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" @@ -382,7 +384,7 @@ run_opencode() { # Run OpenCode CLI and capture output set +e # Temporarily disable exit on error to capture exit code - opencode -q -m "openrouter/$model" -p "$(cat "$prompt_file")" 2>&1 | tee /tmp/validation-full-output.md + opencode run -m "$full_model" "$(cat "$prompt_file")" 2>&1 | tee /tmp/validation-full-output.md local exit_code=$? set -e # Re-enable exit on error