This commit is contained in:
Dmitry 2025-11-22 02:26:25 +03:00
parent 249683ab5f
commit ff52bbeb9e
2 changed files with 129 additions and 64 deletions

View file

@ -3,14 +3,6 @@ name: AI Agent - Planning
on:
workflow_dispatch:
inputs:
component:
description: 'Component to plan for'
required: true
type: choice
options:
- web_v2
- backend
- common
llm_model:
description: 'LLM Model'
required: true
@ -49,10 +41,11 @@ jobs:
- name: Set up Python and bash
run: |
apt-get update -qq
apt-get install -y -qq python3 python3-pip python3-venv bash
apt-get install -y -qq python3 python3-pip python3-venv bash jq
python3 --version
pip3 --version
bash --version || echo "bash check failed"
jq --version || echo "jq check failed"
- name: Install Cursor CLI
run: |
@ -88,7 +81,7 @@ jobs:
git config --global user.name "AI Agent"
git config --global user.email "ai-agent@mnemo-cards.com"
- name: Run Planning Agent
- name: Run Planning Agent for All Components
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
CURSOR_MODEL: ${{ inputs.llm_model || secrets.CURSOR_MODEL }}
@ -132,26 +125,40 @@ jobs:
fi
cd ${{ github.workspace }}
python3 tools/agent/planning_agent.py ${{ inputs.component }}
# Plan for all components
COMPONENTS=("web_v2" "backend" "common")
for COMPONENT in "${COMPONENTS[@]}"; do
echo "📋 Planning for component: $COMPONENT"
python3 tools/agent/planning_agent.py "$COMPONENT" || {
echo "⚠️ Planning failed for $COMPONENT, continuing with other components..."
}
done
echo "✅ Planning completed for all components"
- name: Parse Task List and Create Summary
- name: Parse Task Lists and Create Summaries
if: success()
id: parse_tasks
run: |
COMPONENT="${{ inputs.component }}"
TASK_LIST_PATH="ai_docs/agent/${COMPONENT}/task_list.json"
COMPONENTS=("web_v2" "backend" "common")
if [ ! -f "$TASK_LIST_PATH" ]; then
echo "Task list not found"
exit 0
fi
# Parse JSON with Python
python3 << 'EOF'
for COMPONENT in "${COMPONENTS[@]}"; do
TASK_LIST_PATH="ai_docs/agent/${COMPONENT}/task_list.json"
if [ ! -f "$TASK_LIST_PATH" ]; then
echo "⚠️ Task list not found for $COMPONENT, skipping..."
continue
fi
echo "📊 Parsing task list for $COMPONENT..."
# Parse JSON with Python
python3 << EOF
import json
import os
component = os.environ.get('COMPONENT', 'unknown')
component = "$COMPONENT"
task_list_path = f"ai_docs/agent/{component}/task_list.json"
try:
@ -186,61 +193,119 @@ jobs:
body += "\\n---\\n*Generated by AI Planning Agent*"
# Save to file for next step
with open('/tmp/issue_body.txt', 'w') as f:
# Save to file for next step (component-specific)
with open(f'/tmp/issue_body_{component}.txt', 'w') as f:
f.write(body)
title = f"📋 Planning: {component} - {len(tasks)} tasks ({total_hours:.1f}h)"
with open('/tmp/issue_title.txt', 'w') as f:
with open(f'/tmp/issue_title_{component}.txt', 'w') as f:
f.write(title)
print(f"Tasks: {len(tasks)}, High: {high}, Medium: {medium}, Low: {low}")
print(f"✅ {component}: Tasks: {len(tasks)}, High: {high}, Medium: {medium}, Low: {low}")
except Exception as e:
print(f"Error: {e}")
exit(1)
print(f"❌ Error processing {component}: {e}")
import traceback
traceback.print_exc()
EOF
done
echo "✅ All task lists parsed"
- name: Create Issues via Forgejo API
if: success()
env:
COMPONENT: ${{ inputs.component }}
- name: Create Issue via Forgejo API
if: success()
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
API_URL: ${{ github.api_url }}/repos/${{ github.repository }}/issues
run: |
COMPONENT="${{ inputs.component }}"
COMPONENTS=("web_v2" "backend" "common")
if [ ! -f "/tmp/issue_body.txt" ] || [ ! -f "/tmp/issue_title.txt" ]; then
echo "Issue files not found, skipping issue creation"
exit 0
fi
for COMPONENT in "${COMPONENTS[@]}"; do
if [ ! -f "/tmp/issue_body_${COMPONENT}.txt" ] || [ ! -f "/tmp/issue_title_${COMPONENT}.txt" ]; then
echo "⚠️ Issue files not found for $COMPONENT, skipping..."
continue
fi
echo "📝 Creating issue for $COMPONENT..."
# Create issue using Python for proper JSON escaping
python3 << PYTHON_SCRIPT
import json
import sys
import os
import subprocess
TITLE=$(cat /tmp/issue_title.txt)
BODY=$(cat /tmp/issue_body.txt)
component = "$COMPONENT"
api_url = os.environ.get('API_URL')
token = os.environ.get('FORGEJO_TOKEN')
# Forgejo API endpoint (adjust to your Forgejo instance)
API_URL="${{ github.api_url }}/repos/${{ github.repository }}/issues"
if not all([component, api_url, token]):
print("❌ Missing required environment variables")
sys.exit(1)
# Create issue using curl
curl -X POST "$API_URL" \
-H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
"title": "$TITLE",
"body": $(echo "$BODY" | jq -Rs .),
"labels": ["ai-agent", "planning", "$COMPONENT"]
# Read title and body
try:
with open(f'/tmp/issue_title_{component}.txt', 'r') as f:
title = f.read().strip()
with open(f'/tmp/issue_body_{component}.txt', 'r') as f:
body = f.read()
except Exception as e:
print(f"❌ Error reading files: {e}")
sys.exit(1)
# Create JSON payload
payload = {
"title": title,
"body": body,
"labels": ["ai-agent", "planning", component]
}
EOF
# Make API request
json_payload = json.dumps(payload)
curl_cmd = [
"curl", "-X", "POST", api_url,
"-H", f"Authorization: token {token}",
"-H", "Content-Type: application/json",
"-d", json_payload,
"-f", "-s", "-S"
]
result = subprocess.run(curl_cmd, capture_output=True, text=True)
if result.returncode == 0:
print(f"✅ Issue created for {component}")
if result.stdout:
print(f"Response: {result.stdout[:200]}")
else:
print(f"❌ Failed to create issue for {component}")
print(f"Error: {result.stderr}")
if result.stdout:
print(f"Response: {result.stdout}")
sys.exit(1)
PYTHON_SCRIPT
if [ $? -ne 0 ]; then
echo "⚠️ Failed to create issue for $COMPONENT, continuing..."
fi
done
- name: Trigger Development Workflow
- name: Trigger Development Workflow for All Components
if: success()
run: |
COMPONENT="${{ inputs.component }}"
# Trigger via Forgejo API
COMPONENTS=("web_v2" "backend" "common")
API_URL="${{ github.api_url }}/repos/${{ github.repository }}/actions/workflows/agent-development.yml/dispatches"
curl -X POST "$API_URL" \
-H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{\"ref\":\"master\",\"inputs\":{\"component\":\"$COMPONENT\"}}"
for COMPONENT in "${COMPONENTS[@]}"; do
echo "🚀 Triggering development workflow for $COMPONENT..."
curl -X POST "$API_URL" \
-H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{\"ref\":\"master\",\"inputs\":{\"component\":\"$COMPONENT\"}}" || {
echo "⚠️ Failed to trigger workflow for $COMPONENT, continuing..."
}
echo "✅ Development workflow triggered for $COMPONENT"
done

View file

@ -153,10 +153,12 @@ Start planning now!
"""Gather context from existing files."""
context = ""
# Read tasks.md if exists
# Read tasks.md - check multiple locations
# Priority: component-specific > global agent tasks.md
tasks_md = self.config.component_root / "tasks.md"
if not tasks_md.exists():
tasks_md = self.config.project_root / "mnemo_cards_web_v2" / "tasks.md"
# Fallback to global agent tasks.md
tasks_md = self.config.project_root / "ai_docs" / "agent" / "tasks.md"
if tasks_md.exists():
with open(tasks_md, 'r') as f:
@ -166,10 +168,8 @@ Start planning now!
content = content[:10000] + "\n... (truncated)"
context += f"### tasks.md:\n```\n{content}\n```\n\n"
# Read workflow_state.md if exists
# Read workflow_state.md - component-specific only
workflow_state = self.config.component_root / "workflow_state.md"
if not workflow_state.exists():
workflow_state = self.config.project_root / "mnemo_cards_web_v2" / "workflow_state.md"
if workflow_state.exists():
with open(workflow_state, 'r') as f: