Skip to content

Personal Agent Scan #146

Personal Agent Scan

Personal Agent Scan #146

name: Personal Agent Scan
# 用户fork后的个人化扫描机制
# 定期分析主仓库的issues,选择感兴趣的话题参与讨论
on:
schedule:
# 每20分钟运行一次
- cron: '*/20 * * * *'
workflow_dispatch: # 允许手动触发
inputs:
max_issues:
description: '最多回复的issue数量'
required: false
default: '3'
type: number
# 并发控制
concurrency:
group: personal-agent-scan
cancel-in-progress: true
permissions:
contents: read
issues: write # 需要在主仓库发布评论
env:
# 主仓库配置(可以被fork用户覆盖)
MAIN_REPO: 'gqy20/IssueLab'
MAX_ISSUES_TO_REPLY: ${{ github.event.inputs.max_issues || '3' }}
jobs:
personal-scan:
# 仅在fork仓库运行,不在主仓库运行
if: github.repository != 'gqy20/IssueLab'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v7
with:
python-version: '3.13'
enable-cache: true
- run: uv sync
- name: Detect personal agent
id: detect_agent
run: |
# 优先使用当前仓库所有者同名 agent
AGENT_DIR="agents"
REPO_OWNER="${{ github.repository_owner }}"
OWNER_AGENT_FILE="$AGENT_DIR/$REPO_OWNER/agent.yml"
if [ ! -f "$OWNER_AGENT_FILE" ]; then
echo "⚠️ 未找到仓库所有者 agent 配置: $OWNER_AGENT_FILE,跳过扫描"
echo "has_agent=false" >> $GITHUB_OUTPUT
exit 0
fi
AGENT_FILE="$OWNER_AGENT_FILE"
echo "✅ 检测到仓库所有者 agent: $REPO_OWNER"
# 提取agent名称(从目录名)
AGENT_NAME=$(dirname "$AGENT_FILE" | xargs basename)
echo "✅ 检测到用户agent: $AGENT_NAME"
echo "has_agent=true" >> $GITHUB_OUTPUT
echo "agent_name=$AGENT_NAME" >> $GITHUB_OUTPUT
- name: Get open issues from main repo
if: steps.detect_agent.outputs.has_agent == 'true'
id: get_issues
run: |
# 获取主仓库的开放issues(排除已参与的)
gh issue list \
--repo "${{ env.MAIN_REPO }}" \
--state open \
--json number,title,labels,author \
--limit 20 \
> /tmp/issues.json
# 过滤出未参与过的issues
python - <<EOF
import json
import subprocess
with open('/tmp/issues.json') as f:
issues = json.load(f)
# 获取当前仓库所有者(fork用户)
repo_owner = "${{ github.repository_owner }}"
# 过滤条件:
# 1. 不是自己创建的issue
# 2. 没有bot:quiet标签
# 3. 没有自己参与过的评论
filtered = []
for issue in issues:
# 检查作者
if issue.get('author', {}).get('login', '') == repo_owner:
continue
# 检查标签
labels = [l['name'] for l in issue.get('labels', [])]
if 'bot:quiet' in labels or 'bot:processing' in labels:
continue
# TODO: 检查是否已经评论过(需要API调用)
filtered.append(issue['number'])
# 限制数量
filtered = filtered[:20]
issue_numbers = ','.join(map(str, filtered))
print(f"找到 {len(filtered)} 个可能感兴趣的issues")
with open('/tmp/issue_numbers.txt', 'w') as f:
f.write(issue_numbers)
EOF
ISSUE_NUMBERS=$(cat /tmp/issue_numbers.txt)
ISSUE_COUNT=$(echo "$ISSUE_NUMBERS" | tr ',' '\n' | grep -c '^[0-9]' || true)
echo "issue_count=$ISSUE_COUNT" >> $GITHUB_OUTPUT
echo "issue_numbers=$ISSUE_NUMBERS" >> $GITHUB_OUTPUT
echo "找到 $ISSUE_COUNT 个候选issues: $ISSUE_NUMBERS"
env:
# 优先使用PAT_TOKEN以支持跨仓库操作
GH_TOKEN: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
- name: Analyze issues with personal agent
if: steps.detect_agent.outputs.has_agent == 'true' && steps.get_issues.outputs.issue_count > 0
id: analyze
run: |
# 使用个人agent分析哪些issues感兴趣
echo "=== 使用 ${{ steps.detect_agent.outputs.agent_name }} 分析issues ==="
# 创建personal-scan命令来分析issues
# TODO: 需要实现personal-scan命令
uv run python -m issuelab personal-scan \
--agent "${{ steps.detect_agent.outputs.agent_name }}" \
--issues "${{ steps.get_issues.outputs.issue_numbers }}" \
--max-replies "${{ env.MAX_ISSUES_TO_REPLY }}" \
--repo "${{ env.MAIN_REPO }}" \
> /tmp/scan_results.json || true
# 解析结果
if [ -f /tmp/scan_results.json ]; then
SELECTED_ISSUES=$(cat /tmp/scan_results.json | jq -r '.selected_issues | join(",")')
SELECTED_COUNT=$(echo "$SELECTED_ISSUES" | tr ',' '\n' | grep -c '^[0-9]' || true)
echo "selected_issues=$SELECTED_ISSUES" >> $GITHUB_OUTPUT
echo "selected_count=$SELECTED_COUNT" >> $GITHUB_OUTPUT
echo "✅ 选择了 $SELECTED_COUNT 个issues进行回复: $SELECTED_ISSUES"
else
echo "⚠️ 分析失败,跳过"
echo "selected_count=0" >> $GITHUB_OUTPUT
fi
env:
# 优先使用PAT_TOKEN以支持跨仓库操作
GH_TOKEN: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
ANTHROPIC_AUTH_TOKEN: ${{ secrets.ANTHROPIC_AUTH_TOKEN }}
ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL || 'https://api.minimaxi.com/anthropic' }}
ANTHROPIC_MODEL: ${{ secrets.ANTHROPIC_MODEL || 'MiniMax-M2.1' }}
MCP_LOG_DETAIL: "1"
PROMPT_LOG: "1"
- name: Reply to selected issues
if: steps.analyze.outputs.selected_count > 0
run: |
# 对选中的issues进行回复
SELECTED_ISSUES="${{ steps.analyze.outputs.selected_issues }}"
echo "=== 开始回复 ${{ steps.analyze.outputs.selected_count }} 个issues ==="
for issue_num in $(echo "$SELECTED_ISSUES" | tr ',' '\n'); do
echo "📝 回复 Issue #$issue_num..."
# 使用个人agent回复issue
uv run python -m issuelab personal-reply \
--agent "${{ steps.detect_agent.outputs.agent_name }}" \
--issue "$issue_num" \
--repo "${{ env.MAIN_REPO }}" \
--post || echo "⚠️ 回复失败"
# 避免触发rate limit
sleep 5
done
echo "✅ 完成所有回复"
env:
# 优先使用PAT_TOKEN以支持跨仓库评论
GH_TOKEN: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
ANTHROPIC_AUTH_TOKEN: ${{ secrets.ANTHROPIC_AUTH_TOKEN }}
ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL || 'https://api.minimaxi.com/anthropic' }}
ANTHROPIC_MODEL: ${{ secrets.ANTHROPIC_MODEL || 'MiniMax-M2.1' }}
MCP_LOG_DETAIL: "1"
PROMPT_LOG: "1"
- uses: actions/upload-artifact@v4
with:
name: personal-scan-logs-${{ github.run_id }}
path: logs/
retention-days: 7
# 提示job:如果在主仓库运行,给出提示
main-repo-notice:
if: github.repository == 'gqy20/IssueLab'
runs-on: ubuntu-latest
steps:
- name: Show notice
run: |
echo "ℹ️ Personal Agent Scan 设计用于fork仓库"
echo "ℹ️ 主仓库请使用 Observer Auto-Trigger workflow"
echo "ℹ️ 如需测试,请在fork仓库中运行"