Skip to content
This repository was archived by the owner on Apr 16, 2026. It is now read-only.

LLM Bot Runner

LLM Bot Runner #169

name: LLM Bot Runner
on:
workflow_dispatch:
inputs:
task:
description: 'LLM的任务描述'
required: true
type: string
context:
description: '任务的JSON上下文'
required: true
type: string
jobs:
create-issue:
runs-on: ubuntu-latest
permissions:
issues: write
outputs:
issue_number: ${{ steps.create-issue.outputs.issue_number }}
steps:
- name: Create issue
id: create-issue
env:
GH_TOKEN: ${{ github.token }}
TASK_CONTENT: ${{ inputs.task }}
CONTEXT_RAW: ${{ inputs.context }}
GITHUB_RUN_ID: ${{ github.run_id }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
# 1. 格式化 Context
FORMATTED_CONTEXT=$(echo "$CONTEXT_RAW" | sed 's/^"//; s/"$//' | jq '.')
# 2. 构建 Markdown 正文
printf "[工作流运行 #$GITHUB_RUN_ID](https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID)\n\n## Task\n%s\n\n## Context\n\`\`\`json\n%s\n\`\`\`" \
"$TASK_CONTENT" "$FORMATTED_CONTEXT" > body.md
# 3. 创建 Issue(硬编码标签 workflow)
ISSUE_URL=$(gh issue create \
--repo "$GITHUB_REPOSITORY" \
--title "[工作流] Run $GITHUB_RUN_ID" \
--body-file body.md \
--label "workflow")
# 4. 提取 Issue 编号
ISSUE_NUMBER=${ISSUE_URL##*/}
echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
echo "成功创建 Issue: $ISSUE_NUMBER"
run-llm-bot:
needs: create-issue
runs-on: ubuntu-latest
env:
LLM_TASK: ${{ inputs.task }}
LLM_CONTEXT: ${{ inputs.context }}
LOG_ISSUE_NUMBER: ${{ needs.create-issue.outputs.issue_number }}
# GitHub身份令牌(4个名称都设置)- 使用agent的token
GITHUB_TOKEN: ${{ secrets.WEINAR_API_KEY }}
GH_TOKEN: ${{ secrets.WEINAR_API_KEY }}
GITHUBTOKEN: ${{ secrets.WEINAR_API_KEY }}
GHTOKEN: ${{ secrets.WEINAR_API_KEY }}
# Claude Code环境变量配置
ANTHROPIC_API_KEY: ${{ secrets.MIMO_API_KEY }}
ANTHROPIC_AUTH_TOKEN: ${{ secrets.MIMO_API_KEY }}
ANTHROPIC_BASE_URL: "https://api.xiaomimimo.com/anthropic"
ANTHROPIC_DEFAULT_OPUS_MODEL: "mimo-v2-flash"
ANTHROPIC_DEFAULT_SONNET_MODEL: "mimo-v2-flash"
ANTHROPIC_DEFAULT_HAIKU_MODEL: "mimo-v2-flash"
# MCP服务器环境变量
CONTEXT7_API_KEY: ${{ secrets.CONTEXT7_API_KEY }}
# 系统提示词
SYSTEM_PROMPT: ${{ vars.SYSTEM_PROMPT }}
# 其他令牌
MIMO_API_KEY: ${{ secrets.MIMO_API_KEY }}
WEINAR_API_KEY: ${{ secrets.WEINAR_API_KEY }}
permissions:
contents: write
pull-requests: write
issues: write
discussions: write
steps:
- name: Install Claude CLI
run: |
curl -fsSL https://claude.ai/install.sh | bash
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: false
- name: Validate tokens
run: |
echo "验证环境变量..."
# 验证GitHub令牌
if [ -z "$GITHUB_TOKEN" ]; then
echo "错误: GITHUB_TOKEN未设置"
exit 1
else
echo "GitHub令牌已设置"
fi
# 验证Anthropic认证令牌
if [ -z "$ANTHROPIC_AUTH_TOKEN" ]; then
echo "错误: ANTHROPIC_AUTH_TOKEN未设置"
exit 1
else
echo "Anthropic认证令牌已设置"
fi
# 验证系统提示词
if [ -z "$SYSTEM_PROMPT" ]; then
echo "错误: SYSTEM_PROMPT未设置"
exit 1
else
echo "系统提示词已设置"
fi
- name: Add MCP servers
run: |
# 添加DuckDuckGo搜索服务器
echo "添加DuckDuckGo搜索服务器..."
claude mcp add ddg-search -- uvx duckduckgo-mcp-server
# 添加Context7 HTTP服务器(如果CONTEXT7_API_KEY已设置)
if [ -n "$CONTEXT7_API_KEY" ]; then
echo "添加Context7 HTTP服务器..."
claude mcp add --transport http context7 https://mcp.context7.com/mcp \
--header "CONTEXT7_API_KEY: $CONTEXT7_API_KEY"
else
echo "警告: CONTEXT7_API_KEY未设置,跳过Context7服务器添加"
fi
env:
CONTEXT7_API_KEY: ${{ secrets.CONTEXT7_API_KEY }}
- name: Configure WakaTime
run: |
# 安装WakaTime插件
echo "安装WakaTime插件..."
claude plugin marketplace add https://github.com/wakatime/claude-code-wakatime.git
claude plugin i claude-code-wakatime@wakatime
# 配置WakaTime API Key
if [ -n "$WAKE_TIME_API_KEY" ]; then
echo "配置WakaTime API Key..."
mkdir -p ~
printf "[settings]\napi_key = %s\n" "$WAKE_TIME_API_KEY" > ~/.wakatime.cfg
echo "WakaTime配置完成"
else
echo "警告: WAKE_TIME_API_KEY未设置,跳过WakaTime配置"
fi
env:
WAKE_TIME_API_KEY: ${{ secrets.WAKE_TIME_API_KEY }}
- name: Pre-configure Git
run: |
echo "配置Git用户信息..."
git config --global user.name "WhiteElephantIsNotARobot"
git config --global user.email "257136373+WhiteElephantIsNotARobot@users.noreply.github.com"
echo "配置SSH认证..."
# 创建SSH目录
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# 从环境变量写入SSH私钥(如果提供了SSH_PRIVATE_KEY)
if [ -n "$SSH_PRIVATE_KEY" ]; then
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
echo "SSH私钥已写入 ~/.ssh/id_rsa"
# 启动ssh-agent并添加密钥
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
echo "SSH密钥已添加到ssh-agent"
else
echo "警告: SSH_PRIVATE_KEY环境变量未设置,跳过SSH配置"
fi
# 添加GitHub到known_hosts
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null
chmod 644 ~/.ssh/known_hosts
echo "配置GPG签名..."
# 从环境变量写入GPG私钥(如果提供了GPG_PRIVATE_KEY)
if [ -n "$GPG_PRIVATE_KEY" ]; then
echo "$GPG_PRIVATE_KEY" | gpg --import --batch
echo "GPG私钥已导入"
# 获取GPG密钥ID
GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format LONG "257136373+WhiteElephantIsNotARobot@users.noreply.github.com" 2>/dev/null | grep sec | awk '{print $2}' | cut -d'/' -f2)
if [ -n "$GPG_KEY_ID" ]; then
# 配置git使用GPG签名
git config --global user.signingkey "$GPG_KEY_ID"
git config --global commit.gpgsign true
git config --global gpg.program gpg
echo "GPG签名已配置,密钥ID: $GPG_KEY_ID"
else
echo "警告: 无法找到GPG密钥ID"
fi
else
echo "警告: GPG_PRIVATE_KEY环境变量未设置,跳过GPG配置"
fi
echo "Git预配置完成"
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
- name: Run Claude Code
run: |
# 使用bind mount将深层目录映射到根路径,避免软链接被解析
echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE"
# 创建/app目录并绑定挂载
sudo mkdir -p /app
sudo mount --bind "$GITHUB_WORKSPACE" /app
# 切换到简洁的/app目录运行Claude Code
cd /app
echo "当前工作目录: $(pwd)"
echo "运行Claude Code..."
echo "原始任务: $LLM_TASK"
echo "系统提示词长度: ${#SYSTEM_PROMPT} 字符"
# 将JSON上下文写入文件(保存到/app目录)
echo "$LLM_CONTEXT" > /app/context.json
CONTEXT_CHARS=$(wc -m < /app/context.json)
echo "上下文文件大小: $CONTEXT_CHARS 字符"
# 不直接cat内容,避免日志污染
echo ""
# 构建新任务字符串,包含读取context.json的指示
ENHANCED_TASK=$(printf "%s\n\n> 任务上下文已保存到/app/context.json,共%s字符。阅读该文件以了解上下文!" "$LLM_TASK" "$CONTEXT_CHARS")
echo "增强任务: $ENHANCED_TASK"
claude \
-p "$ENHANCED_TASK" \
--system-prompt "$SYSTEM_PROMPT" \
--allowedTools "Bash,TaskOutput,Edit,ExitPlanMode,Glob,Grep,KillShell,MCPSearch,NotebookEdit,Read,Skill,Task,TaskCreate,TaskGet,TaskList,TaskUpdate,WebFetch,WebSearch,Write,mcp__ddg-search__*,mcp__context7__*" \
--output-format=stream-json \
--verbose
# 自查
claude \
-p "请快速自查是否在 GitHub 留下回复,确认是否已有回复,避免重复回复,若无回复,才应当回复。!避免重复回复!另请快速检查工作区,确保所有更改都已经提交并推送(若修改了仓库文件),确保 PR 已存在(若修改了仓库文件),任何未推送的更改都将在此会话结束后被永久销毁!" \
--system-prompt "$SYSTEM_PROMPT" \
--allowedTools "Bash,TaskOutput,Edit,ExitPlanMode,Glob,Grep,KillShell,MCPSearch,NotebookEdit,Read,Skill,Task,TaskCreate,TaskGet,TaskList,TaskUpdate,WebFetch,WebSearch,Write,mcp__ddg-search__*,mcp__context7__*" \
--output-format=stream-json \
--verbose \
--continue
# 再次自查
claude \
-p "请再次确认:所有更改都已经提交并推送(若修改了文件),并且 PR 已存在(若修改了文件),任何未推送的更改都将在此会话结束后被永久销毁!" \
--system-prompt "$SYSTEM_PROMPT" \
--allowedTools "Bash,TaskOutput,Edit,ExitPlanMode,Glob,Grep,KillShell,MCPSearch,NotebookEdit,Read,Skill,Task,TaskCreate,TaskGet,TaskList,TaskUpdate,WebFetch,WebSearch,Write,mcp__ddg-search__*,mcp__context7__*" \
--output-format=stream-json \
--verbose \
--continue