name: AI Agent - Development on: workflow_dispatch: inputs: component: description: 'Component to develop' required: true type: choice options: - web_v2 - backend - common schedule: # Run every 30 minutes - cron: '*/20 * * * *' # Other schedule options (uncomment to use): # Run every 15 minutes # - cron: '*/15 * * * *' # Run every hour # - cron: '0 * * * *' # Run every 6 hours (at 2:00, 8:00, 14:00, 20:00 UTC) # - cron: '0 */6 * * *' # Run every day at 2:00 AM UTC (5:00 AM MSK) # - cron: '0 2 * * *' # Run every day at 9:00 AM UTC (12:00 PM MSK) # - cron: '0 9 * * *' jobs: development: runs-on: ubuntu-latest container: ghcr.io/cirruslabs/flutter:3.35.5 timeout-minutes: 360 # 6 hours # For scheduled runs, use matrix to run all components # For manual runs, use input component strategy: matrix: component: [web_v2, backend, common] fail-fast: false # Only use matrix for scheduled runs (when inputs.component is not set) # For workflow_dispatch, matrix will be ignored and inputs.component will be used env: # Use input component if provided (workflow_dispatch), otherwise use matrix component (schedule) COMPONENT: ${{ inputs.component || matrix.component }} # For workflow_dispatch, only run the selected component # For schedule, run all components (matrix will create jobs for all) if: github.event_name == 'schedule' || inputs.component == '' || inputs.component == matrix.component steps: - name: Install Node.js run: | # Try to install nodejs if missing (required for actions) if ! command -v node &> /dev/null; then echo "Node.js not found, installing..." # Check if running as root if [ "$(id -u)" -eq 0 ]; then apt-get update && apt-get install -y nodejs npm else sudo apt-get update && sudo apt-get install -y nodejs npm fi fi - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 submodules: recursive - name: Set up Python and dependencies run: | apt-get update -qq apt-get install -y -qq python3 python3-pip python3-venv jq bash git python3 --version pip3 --version bash --version || echo "bash check failed" - name: Install Cursor CLI run: | # bash should already be installed in previous step curl https://cursor.com/install -fsS | bash # Cursor installs to ~/.local/bin by default export PATH="$HOME/.local/bin:$PATH" echo "$HOME/.local/bin" >> $GITHUB_PATH # Also check ~/.cursor/bin (older location) if [ -d "$HOME/.cursor/bin" ]; then export PATH="$HOME/.cursor/bin:$PATH" echo "$HOME/.cursor/bin" >> $GITHUB_PATH fi # Verify installation if [ -f "$HOME/.local/bin/cursor-agent" ]; then echo "✅ Cursor CLI installed at $HOME/.local/bin/cursor-agent" chmod +x "$HOME/.local/bin/cursor-agent" "$HOME/.local/bin/cursor-agent" --version || echo "cursor-agent executable found but version check failed" elif [ -f "$HOME/.cursor/bin/cursor-agent" ]; then echo "✅ Cursor CLI installed at $HOME/.cursor/bin/cursor-agent" chmod +x "$HOME/.cursor/bin/cursor-agent" "$HOME/.cursor/bin/cursor-agent" --version || echo "cursor-agent executable found but version check failed" else echo "❌ Cursor CLI not found in expected locations" echo "Checking PATH..." command -v cursor-agent || echo "cursor-agent not in PATH" find "$HOME" -name "cursor-agent" -type f 2>/dev/null | head -5 || echo "No cursor-agent found in $HOME" exit 1 fi - name: Configure Git run: | git config --global user.name "AI Agent" git config --global user.email "ai-agent@mnemo-cards.com" - name: Install Dependencies run: | COMPONENT="${{ env.COMPONENT }}" if [ "$COMPONENT" == "web_v2" ]; then cd mnemo_cards_web_v2 flutter pub get elif [ "$COMPONENT" == "backend" ]; then cd mnemo_cards_backend dart pub get elif [ "$COMPONENT" == "common" ]; then cd mnemo_cards_common dart pub get fi - name: Run Development Agent env: CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} CURSOR_MODEL: ${{ secrets.CURSOR_MODEL }} PROJECT_ROOT: ${{ github.workspace }} MAX_ITERATIONS: 10 MAX_RETRIES: 3 TIMEOUT_HOURS: 6 run: | # Verify cursor-agent is accessible echo "Current PATH: $PATH" if ! command -v cursor-agent &> /dev/null; then echo "❌ cursor-agent not found in PATH" echo "PATH: $PATH" echo "Trying full paths..." if [ -f "$HOME/.local/bin/cursor-agent" ]; then export PATH="$HOME/.local/bin:$PATH" echo "✅ Found at $HOME/.local/bin/cursor-agent" elif [ -f "$HOME/.cursor/bin/cursor-agent" ]; then export PATH="$HOME/.cursor/bin:$PATH" echo "✅ Found at $HOME/.cursor/bin/cursor-agent" else echo "❌ cursor-agent not found in any expected location" find "$HOME" -name "cursor-agent" -type f 2>/dev/null | head -5 || echo "No cursor-agent found" exit 1 fi else echo "✅ cursor-agent found at: $(command -v cursor-agent)" fi cd ${{ github.workspace }} python3 tools/agent/agent_orchestrator.py ${{ env.COMPONENT }} - name: Create Summary Report if: always() run: | COMPONENT="${{ env.COMPONENT }}" STATE_FILE="ai_docs/agent/${COMPONENT}/agent_state.json" echo "# Development Agent Summary" > /tmp/summary.md echo "" >> /tmp/summary.md echo "**Component:** ${COMPONENT}" >> /tmp/summary.md echo "**Started:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")" >> /tmp/summary.md echo "" >> /tmp/summary.md if [ -f "$STATE_FILE" ]; then echo "## Agent State" >> /tmp/summary.md echo "\`\`\`json" >> /tmp/summary.md cat "$STATE_FILE" >> /tmp/summary.md echo "\`\`\`" >> /tmp/summary.md fi cat /tmp/summary.md - name: Check if all tasks completed id: check_completion run: | COMPONENT="${{ env.COMPONENT }}" STATE_FILE="ai_docs/agent/${COMPONENT}/agent_state.json" TASK_LIST="ai_docs/agent/${COMPONENT}/task_list.json" if [ -f "$STATE_FILE" ] && [ -f "$TASK_LIST" ]; then # Check if all tasks are completed python3 << 'EOF' import json import os import sys component = os.environ.get('COMPONENT', 'unknown') state_file = f"ai_docs/agent/{component}/agent_state.json" task_list_file = f"ai_docs/agent/{component}/task_list.json" try: with open(state_file, 'r') as f: state = json.load(f) with open(task_list_file, 'r') as f: task_list = json.load(f) tasks = task_list.get('tasks', []) pending = [t for t in tasks if t.get('status') == 'pending'] # Check if status is completed or no pending tasks if state.get('status') == 'completed' or len(pending) == 0: print("all_completed=true") else: print("all_completed=false") except Exception as e: print(f"Error: {e}", file=sys.stderr) print("all_completed=false") EOF else echo "all_completed=false" fi > /tmp/completion_status.txt cat /tmp/completion_status.txt >> $GITHUB_OUTPUT env: COMPONENT: ${{ env.COMPONENT }} - name: Trigger Planning Agent (if all completed) if: contains(steps.check_completion.outputs.*, 'all_completed=true') run: | COMPONENT="${{ inputs.component }}" echo "All tasks completed! Triggering planning agent for new tasks..." # Trigger via Forgejo API API_URL="${{ github.api_url }}/repos/${{ github.repository }}/actions/workflows/agent-planning.yml/dispatches" curl -X POST "$API_URL" \ -H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \ -H "Content-Type: application/json" \ -d "{\"ref\":\"master\",\"inputs\":{\"component\":\"$COMPONENT\"}}"