Spaces:
Paused
Paused
| name: 'Bot Setup' | |
| description: 'Performs all common setup steps for bot workflows, including token generation, git config, and dependency installation.' | |
| inputs: | |
| bot-app-id: | |
| description: 'The ID of the GitHub App.' | |
| required: true | |
| bot-private-key: | |
| description: 'The private key of the GitHub App.' | |
| required: true | |
| opencode-api-key: | |
| description: 'The default API key, used for providers that do not have one defined in the custom providers JSON.' | |
| required: false | |
| opencode-model: | |
| description: 'The main model to use (e.g., openai/gpt-4o or a custom one from custom providers JSON).' | |
| required: true | |
| opencode-fast-model: | |
| description: 'Optional: The fast model for smaller tasks.' | |
| required: false | |
| custom-providers-json: | |
| description: 'Optional: A JSON string defining custom providers. Use minifier to correctly format.' | |
| required: false | |
| outputs: | |
| token: | |
| description: "The generated GitHub App token." | |
| value: ${{ steps.generate_token.outputs.token }} | |
| runs: | |
| using: "composite" | |
| steps: | |
| - name: Generate GitHub App Token | |
| id: generate_token | |
| uses: actions/create-github-app-token@v1 | |
| with: | |
| app-id: ${{ inputs.bot-app-id }} | |
| private-key: ${{ inputs.bot-private-key }} | |
| - name: Configure Git for Bot | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ steps.generate_token.outputs.token }} | |
| run: | | |
| git config --global user.name "mirrobot-agent[bot]" | |
| git config --global user.email "${{ inputs.bot-app-id }}+mirrobot-agent@users.noreply.github.com" | |
| git config --global url."https://x-access-token:${{ steps.generate_token.outputs.token }}@github.com/".insteadOf "https://github.com/" | |
| - name: Generate OpenCode Configuration | |
| shell: bash | |
| run: | | |
| set -e # Exit immediately if a command fails | |
| # --- HARDCODED TOGGLE --- | |
| # Set to "true" to add 'reasoning_effort: "high"' to the main model's request body. | |
| # Set to "false" to disable. | |
| ADD_REASONING_EFFORT="true" | |
| mkdir -p ~/.config/opencode | |
| # --- INPUTS --- | |
| MAIN_MODEL="${{ inputs.opencode-model }}" | |
| FAST_MODEL="${{ inputs.opencode-fast-model }}" | |
| DEFAULT_API_KEY="${{ inputs.opencode-api-key }}" | |
| # Use command substitution with a heredoc to safely read the input into a variable. | |
| # This is robust against complex characters and avoids creating a giant line of code that can break shell parsers. | |
| CUSTOM_PROVIDERS=$(cat <<'EOF' | |
| ${{ inputs.custom-providers-json }} | |
| EOF | |
| ) | |
| # If the input was empty (or just whitespace), the variable will be empty. Set a default. | |
| if [ -z "$CUSTOM_PROVIDERS" ]; then | |
| CUSTOM_PROVIDERS='{}' | |
| fi | |
| # --- INITIAL CONFIG SETUP --- | |
| mkdir -p ~/.config/opencode | |
| CONFIG='{"$schema": "https://opencode.ai/config.json", "username": "mirrobot-agent", "autoupdate": true}' | |
| # Merge custom provider definitions if they are not the empty default | |
| if [ "$CUSTOM_PROVIDERS" != "{}" ]; then | |
| echo "Custom provider definitions found. Merging into configuration." | |
| CONFIG=$(jq --argjson customProviders "$CUSTOM_PROVIDERS" '. * {provider: $customProviders}' <<< "$CONFIG") | |
| else | |
| echo "No custom provider definitions supplied." | |
| fi | |
| # --- MODULAR FUNCTION TO CONFIGURE A MODEL --- | |
| configure_model() { | |
| local model_string="$1" | |
| local config_key="$2" | |
| local provider="${model_string%%/*}" | |
| local model_name="${model_string#*/}" | |
| # echo "--- Configuring ${config_key} with '${model_string}' ---" | |
| # Check if the provider exists in the custom definitions | |
| if jq -e --arg provider "$provider" '. | has($provider)' <<< "$CUSTOM_PROVIDERS" >/dev/null; then | |
| echo "Provider found in custom definitions." | |
| # CASE 2: Provider exists, but the model does not. This is an error. | |
| if ! jq -e --arg provider "$provider" --arg modelName "$model_name" '.[$provider].models | has($modelName)' <<< "$CUSTOM_PROVIDERS" >/dev/null; then | |
| echo "::error::Configuration error: Provider is defined, but model is not found within it. Aborting." | |
| exit 1 | |
| fi | |
| # CASE 1: Provider and model both exist. Use it as is. | |
| # echo "Model '$model_name' also found. Setting '${config_key}' to '${model_string}'." | |
| CONFIG=$(jq --arg key "$config_key" --arg val "$model_string" '.[$key] = $val' <<< "$CONFIG") | |
| else | |
| # CASE 3: Provider does not exist in custom definitions. Treat as a standard provider. | |
| echo "Provider not found in custom definitions. Configuring as a standard provider." | |
| CONFIG=$(jq --arg key "$config_key" --arg val "$model_string" '.[$key] = $val' <<< "$CONFIG") | |
| echo "Setting default API key for provider." | |
| CONFIG=$(jq \ | |
| --arg provider "$provider" \ | |
| --arg apiKey "$DEFAULT_API_KEY" \ | |
| '.provider[$provider].options.apiKey = $apiKey' <<< "$CONFIG") | |
| if [[ "$config_key" == "model" && "$ADD_REASONING_EFFORT" == "true" ]]; then | |
| echo "Reasoning effort toggle is ON. Applying to standard provider model." | |
| CONFIG=$(jq \ | |
| --arg provider "$provider" \ | |
| --arg modelName "$model_name" \ | |
| '.provider[$provider].models[$modelName].options.reasoningEffort = "high"' <<< "$CONFIG") | |
| fi | |
| fi | |
| } | |
| # --- EXECUTION --- | |
| configure_model "$MAIN_MODEL" "model" | |
| if [ -n "$FAST_MODEL" ]; then | |
| configure_model "$FAST_MODEL" "small_model" | |
| fi | |
| # --- FINALIZATION --- | |
| echo "$CONFIG" > ~/.config/opencode/opencode.json | |
| # echo "--- Generated OpenCode Configuration ---" | |
| # jq . ~/.config/opencode/opencode.json | |
| # echo "----------------------------------------" | |
| echo "Successfully generated OpenCode configuration." | |
| - name: Check for Python requirements file | |
| id: check_requirements_file | |
| shell: bash | |
| run: | | |
| if [ -f requirements.txt ]; then | |
| echo "exists=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "exists=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Set up uv | |
| if: steps.check_requirements_file.outputs.exists == 'true' | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "requirements.txt" | |
| - name: Set up Python with uv | |
| if: steps.check_requirements_file.outputs.exists == 'true' | |
| shell: bash | |
| run: | | |
| uv python install 3.12 | |
| uv venv --python 3.12 | |
| - name: Install dependencies | |
| if: steps.check_requirements_file.outputs.exists == 'true' | |
| shell: bash | |
| run: | | |
| source .venv/bin/activate | |
| uv pip install -r requirements.txt | |
| - name: Install opencode | |
| shell: bash | |
| run: curl -fsSL https://opencode.ai/install | bash | |
| - name: Ensure opencode directory exists | |
| shell: bash | |
| run: mkdir -p /home/runner/.local/share/opencode/project |