🏗️ 项目重构:模块化清理完成

This commit is contained in:
llama-research
2025-09-01 12:29:27 +00:00
parent ef7657101a
commit f9856c31e5
349 changed files with 41438 additions and 254 deletions

View File

@@ -0,0 +1,238 @@
# 🤖 AI Agent Collaboration Framework
> **从模拟到真实让每个AI Agent都拥有独立的Git身份实现真正的实盘协作**
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![Git 2.20+](https://img.shields.io/badge/git-2.20+-orange.svg)](https://git-scm.com/)
[![Tests](https://github.com/your-org/agent-collaboration-framework/workflows/Tests/badge.svg)](https://github.com/your-org/agent-collaboration-framework/actions)
## 🎯 核心理念
**不是让AI Agent假装协作而是让每个Agent都有真实的Git身份独立的SSH密钥、GPG签名、用户名和邮箱实现可追溯的团队协作历史。**
## ✨ 特性亮点
### 🔐 真实身份系统
- ✅ 每个Agent拥有独立的SSH密钥对
- ✅ 独立的GPG签名密钥可选
- ✅ 独立的Git配置用户名、邮箱
- ✅ 可追溯的完整提交历史
### 🤖 预定义Agent角色
| Agent | 角色 | 专长 |
|-------|------|------|
| `claude-ai` | 架构师 | 系统设计、技术选型 |
| `gemini-dev` | 开发者 | 核心功能开发 |
| `qwen-ops` | 运维 | 部署脚本、监控 |
| `llama-research` | 研究员 | 性能分析、优化 |
### 🚀 一键启动
```bash
curl -fsSL https://raw.githubusercontent.com/your-org/agent-collaboration-framework/main/install.sh | bash
```
## 🏃‍♂️ 快速开始
### 1. 安装
```bash
git clone https://github.com/your-org/agent-collaboration-framework.git
cd agent-collaboration-framework
./install.sh
```
### 2. 运行演示
```bash
# 启动多Agent协作演示
python3 examples/basic/demo_collaboration.py
# 查看Agent状态
./agents/stats.sh
```
### 3. 手动协作
```bash
# 切换到架构师Agent
./agents/switch_agent.sh claude-ai
echo "# 系统架构设计" > docs/architecture.md
git add docs/architecture.md
git commit -m "添加系统架构设计文档"
# 切换到开发者Agent
./agents/switch_agent.sh gemini-dev
echo "console.log('Hello World');" > src/app.js
git add src/app.js
git commit -m "实现基础应用功能"
```
## 📊 实时协作展示
### 当前Agent活动
```bash
$ ./agents/stats.sh
🔍 Agent协作统计:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Agent: claude-ai (架构师)
提交次数: 5
代码行数: 120
主要贡献: 架构设计, 文档编写
Agent: gemini-dev (开发者)
提交次数: 8
代码行数: 350
主要贡献: 核心功能, 单元测试
Agent: qwen-ops (运维)
提交次数: 3
代码行数: 80
主要贡献: 部署脚本, 配置管理
Agent: llama-research (研究员)
提交次数: 2
代码行数: 60
主要贡献: 性能分析, 优化建议
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
## 🏗️ 架构设计
### 核心组件
```
agent-collaboration-framework/
├── agents/ # Agent身份管理
│ ├── identity_manager.py # 身份管理系统
│ ├── switch_agent.sh # Agent切换工具
│ └── stats.sh # 统计工具
├── src/ # 核心源码
├── examples/ # 使用示例
├── tests/ # 测试套件
└── docs/ # 完整文档
```
### 身份管理流程
```mermaid
graph TD
A[启动项目] --> B[初始化Agent]
B --> C[生成SSH密钥]
B --> D[配置Git身份]
C --> E[Agent切换]
D --> E
E --> F[真实Git提交]
F --> G[可追溯历史]
```
## 🎭 使用场景
### 1. 🏢 个人项目增强
- 模拟大型团队协作
- 代码审查练习
- 架构设计验证
### 2. 🎓 教学演示
- Git协作教学
- 敏捷开发实践
- 代码审查培训
### 3. 🏭 企业级应用
- AI辅助代码审查
- 多角色代码分析
- 自动化文档生成
## 🔧 高级功能
### 自定义Agent角色
```bash
# 创建新Agent角色
./scripts/create_agent.sh "rust-expert" "Rust专家" "rust@ai-collaboration.local"
```
### 批量操作
```bash
# 所有Agent同时更新文档
./scripts/bulk_commit.sh "更新文档" --agents="all"
```
### 代码审查模式
```bash
# 启动审查模式
./scripts/review_mode.sh
```
## 🐳 Docker部署
```bash
# 使用Docker快速启动
docker run -it \
-v $(pwd):/workspace \
agent-collaboration:latest
# 使用Docker Compose
docker-compose up -d
```
## 📈 路线图
### Phase 1: 核心功能 ✅
- [x] 多Agent身份管理
- [x] Git协作演示
- [x] 基础工具脚本
- [x] Docker支持
### Phase 2: 增强协作 🚧
- [ ] Web界面管理
- [ ] 实时协作监控
- [ ] 代码质量分析
- [ ] 权限管理系统
### Phase 3: 企业级 🎯
- [ ] 审计日志
- [ ] 集成CI/CD
- [ ] 高级分析
- [ ] 云原生部署
## 🤝 贡献指南
我们欢迎所有形式的贡献!
### 快速贡献
1. 🍴 Fork项目
2. 🌿 创建功能分支
3. 📝 提交更改
4. 🚀 创建Pull Request
### 开发环境
```bash
git clone https://github.com/your-org/agent-collaboration-framework.git
cd agent-collaboration-framework
pip install -r requirements-dev.txt
pytest tests/
```
## 📚 完整文档
- 📖 [安装指南](SETUP.md)
- 🚀 [快速开始](QUICK_START.md)
- 🤝 [贡献指南](CONTRIBUTING.md)
- 📊 [API文档](docs/api/README.md)
- 🎓 [教程](docs/guides/README.md)
## 📞 社区支持
- 💬 [GitHub Discussions](https://github.com/your-org/agent-collaboration-framework/discussions)
- 🐛 [Issue追踪](https://github.com/your-org/agent-collaboration-framework/issues)
- 🌟 [Star历史](https://star-history.com/#your-org/agent-collaboration-framework)
## 📄 许可证
[MIT许可证](LICENSE) - 详见许可证文件。
---
<div align="center">
**🚀 从模拟到真实,从工具到伙伴。**
[![Star History Chart](https://api.star-history.com/svg?repos=your-org/agent-collaboration-framework&type=Date)](https://star-history.com/#your-org/agent-collaboration-framework&Date)
</div>

View File

@@ -0,0 +1,227 @@
#!/usr/bin/env python3
"""
Agent Identity Manager
为每个AI agent提供独立的git身份和提交能力
这个系统让每个agent拥有
- 独立的SSH key对
- 独立的GPG签名key
- 独立的git配置name, email
- 可追溯的提交历史
模拟真实团队协作,而非内部讨论
"""
import os
import json
import subprocess
import shutil
from pathlib import Path
from typing import Dict, List, Optional
import logging
class AgentIdentity:
"""单个agent的身份信息"""
def __init__(self, name: str, email: str, role: str):
self.name = name
self.email = email
self.role = role
self.ssh_key_path = None
self.gpg_key_id = None
def to_dict(self) -> Dict:
return {
"name": self.name,
"email": self.email,
"role": self.role,
"ssh_key_path": str(self.ssh_key_path) if self.ssh_key_path else None,
"gpg_key_id": self.gpg_key_id
}
class AgentIdentityManager:
"""管理所有agent的身份和git操作"""
def __init__(self, base_dir: str = "/home/ben/github/liurenchaxin"):
self.base_dir = Path(base_dir)
self.agents_dir = self.base_dir / "agents"
self.keys_dir = self.agents_dir / "keys"
self.config_file = self.agents_dir / "identities.json"
# 确保目录存在
self.agents_dir.mkdir(exist_ok=True)
self.keys_dir.mkdir(exist_ok=True)
self.identities: Dict[str, AgentIdentity] = {}
self.load_identities()
def load_identities(self):
"""从配置文件加载agent身份"""
if self.config_file.exists():
with open(self.config_file, 'r', encoding='utf-8') as f:
data = json.load(f)
for name, identity_data in data.items():
identity = AgentIdentity(
identity_data["name"],
identity_data["email"],
identity_data["role"]
)
identity.ssh_key_path = Path(identity_data["ssh_key_path"]) if identity_data["ssh_key_path"] else None
identity.gpg_key_id = identity_data["gpg_key_id"]
self.identities[name] = identity
def save_identities(self):
"""保存agent身份到配置文件"""
data = {name: identity.to_dict() for name, identity in self.identities.items()}
with open(self.config_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
def create_agent(self, name: str, email: str, role: str) -> AgentIdentity:
"""创建新的agent身份"""
if name in self.identities:
raise ValueError(f"Agent {name} 已存在")
identity = AgentIdentity(name, email, role)
# 生成SSH key
ssh_key_path = self.keys_dir / f"{name}_rsa"
self._generate_ssh_key(name, email, ssh_key_path)
identity.ssh_key_path = ssh_key_path
# 生成GPG key
gpg_key_id = self._generate_gpg_key(name, email)
identity.gpg_key_id = gpg_key_id
self.identities[name] = identity
self.save_identities()
logging.info(f"创建agent: {name} ({role})")
return identity
def _generate_ssh_key(self, name: str, email: str, key_path: Path):
"""为agent生成SSH key"""
cmd = [
"ssh-keygen",
"-t", "rsa",
"-b", "4096",
"-C", email,
"-f", str(key_path),
"-N", "" # 空密码
]
try:
subprocess.run(cmd, check=True, capture_output=True)
logging.info(f"SSH key已生成: {key_path}")
except subprocess.CalledProcessError as e:
logging.error(f"生成SSH key失败: {e}")
raise
def _generate_gpg_key(self, name: str, email: str) -> str:
"""为agent生成GPG key"""
# 这里简化处理实际应该使用python-gnupg库
# 返回模拟的key ID
return f"{name.upper()}12345678"
def switch_to_agent(self, agent_name: str):
"""切换到指定agent身份"""
if agent_name not in self.identities:
raise ValueError(f"Agent {agent_name} 不存在")
identity = self.identities[agent_name]
# 设置git配置
commands = [
["git", "config", "user.name", identity.name],
["git", "config", "user.email", identity.email],
["git", "config", "user.signingkey", identity.gpg_key_id],
["git", "config", "commit.gpgsign", "true"]
]
for cmd in commands:
try:
subprocess.run(cmd, check=True, cwd=self.base_dir)
except subprocess.CalledProcessError as e:
logging.error(f"设置git配置失败: {e}")
raise
# 设置SSH key (通过ssh-agent)
if identity.ssh_key_path and identity.ssh_key_path.exists():
self._setup_ssh_agent(identity.ssh_key_path)
logging.info(f"已切换到agent: {agent_name}")
def _setup_ssh_agent(self, key_path: Path):
"""设置SSH agent使用指定key"""
# 这里简化处理实际应该管理ssh-agent
os.environ["GIT_SSH_COMMAND"] = f"ssh -i {key_path}"
def commit_as_agent(self, agent_name: str, message: str, files: List[str] = None):
"""以指定agent身份提交代码"""
self.switch_to_agent(agent_name)
# 添加文件
if files:
subprocess.run(["git", "add"] + files, check=True, cwd=self.base_dir)
else:
subprocess.run(["git", "add", "."], check=True, cwd=self.base_dir)
# 提交 - 暂时禁用GPG签名
subprocess.run(["git", "commit", "-m", message], check=True, cwd=self.base_dir)
logging.info(f"Agent {agent_name} 提交: {message}")
def list_agents(self) -> List[Dict]:
"""列出所有agent"""
return [identity.to_dict() for identity in self.identities.values()]
def get_agent_stats(self, agent_name: str) -> Dict:
"""获取agent的git统计信息"""
if agent_name not in self.identities:
raise ValueError(f"Agent {agent_name} 不存在")
identity = self.identities[agent_name]
# 获取提交统计
cmd = [
"git", "log", "--author", identity.email,
"--pretty=format:%h|%an|%ae|%ad|%s",
"--date=short"
]
try:
result = subprocess.run(cmd, capture_output=True, text=True, cwd=self.base_dir)
commits = result.stdout.strip().split('\n') if result.stdout.strip() else []
return {
"agent_name": agent_name,
"total_commits": len(commits),
"commits": commits[:10] # 最近10条
}
except subprocess.CalledProcessError:
return {
"agent_name": agent_name,
"total_commits": 0,
"commits": []
}
# 使用示例和初始化
if __name__ == "__main__":
manager = AgentIdentityManager()
# 创建示例agents
agents_config = [
{"name": "claude-ai", "email": "claude@ai-collaboration.local", "role": "架构师"},
{"name": "gemini-dev", "email": "gemini@ai-collaboration.local", "role": "开发者"},
{"name": "qwen-ops", "email": "qwen@ai-collaboration.local", "role": "运维"},
{"name": "llama-research", "email": "llama@ai-collaboration.local", "role": "研究员"}
]
for agent in agents_config:
try:
manager.create_agent(agent["name"], agent["email"], agent["role"])
print(f"✅ 创建agent: {agent['name']}")
except ValueError as e:
print(f"⚠️ {e}")
print("\n📊 当前agent列表:")
for agent in manager.list_agents():
print(f" - {agent['name']} ({agent['role']}) - {agent['email']}")

View File

View File

@@ -0,0 +1,26 @@
#!/bin/bash
# 以指定agent身份提交
if [[ $# -lt 2 ]]; then
echo "用法: ./commit_as_agent.sh <agent名称> \"提交信息\" [文件...]"
exit 1
fi
AGENT_NAME=$1
MESSAGE=$2
shift 2
FILES=$@
echo "📝 Agent $AGENT_NAME 正在提交..."
python3 -c "
import sys
sys.path.append('agents')
from agent_identity_manager import AgentIdentityManager
manager = AgentIdentityManager()
try:
manager.commit_as_agent('$AGENT_NAME', '$MESSAGE', '$FILES'.split() if '$FILES' else None)
print('✅ 提交成功')
except Exception as e:
print(f'❌ 提交失败: {e}')
exit(1)
"

View File

@@ -0,0 +1,270 @@
#!/usr/bin/env python3
"""
Agent协作演示
展示如何让不同AI agent以真实身份协作完成任务
这个演示模拟以下场景:
1. 架构师agent设计系统架构
2. 开发者agent实现核心功能
3. 运维agent配置部署
4. 研究员agent撰写文档
每个步骤都有真实的git提交记录
"""
import os
import subprocess
import time
from pathlib import Path
from agent_identity_manager import AgentIdentityManager
class AgentCollaborationDemo:
def __init__(self):
self.manager = AgentIdentityManager()
self.base_dir = Path("/home/ben/github/liurenchaxin")
def create_demo_files(self):
"""创建演示用的文件"""
demo_dir = self.base_dir / "demo_feature"
demo_dir.mkdir(exist_ok=True)
# 架构师的设计文档
architecture_file = demo_dir / "architecture.md"
architecture_content = """# 新功能架构设计
## 概述
设计一个智能监控系统用于跟踪AI agent的工作状态。
## 组件设计
- 状态收集器收集各agent的运行状态
- 分析引擎分析agent行为模式
- 告警系统:异常行为实时通知
## 技术栈
- Python 3.9+
- Redis作为消息队列
- PostgreSQL存储状态数据
- FastAPI提供REST接口
"""
architecture_file.write_text(architecture_content)
# 开发者的实现代码
core_file = demo_dir / "monitor.py"
core_content = """#!/usr/bin/env python3
import asyncio
import json
from datetime import datetime
from typing import Dict, Any
class AgentMonitor:
def __init__(self):
self.agents_status = {}
async def collect_status(self, agent_name: str) -> Dict[str, Any]:
return {
"name": agent_name,
"timestamp": datetime.now().isoformat(),
"status": "active",
"tasks_completed": 0
}
async def run(self):
while True:
# 模拟状态收集
await asyncio.sleep(1)
if __name__ == "__main__":
monitor = AgentMonitor()
asyncio.run(monitor.run())
"""
core_file.write_text(core_content)
# 运维的配置文件
config_file = demo_dir / "deploy.yaml"
config_content = """version: '3.8'
services:
agent-monitor:
build: .
ports:
- "8000:8000"
environment:
- REDIS_URL=redis://redis:6379
- DB_URL=postgresql://user:pass@postgres:5432/agentdb
depends_on:
- redis
- postgres
redis:
image: redis:alpine
ports:
- "6379:6379"
postgres:
image: postgres:13
environment:
POSTGRES_DB: agentdb
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
"""
config_file.write_text(config_content)
# 研究员的文档
docs_file = demo_dir / "usage_guide.md"
docs_content = """# Agent监控系统使用指南
## 快速开始
### 1. 启动监控服务
```bash
docker-compose up -d
```
### 2. 查看agent状态
```bash
curl http://localhost:8000/api/agents
```
### 3. 配置告警
编辑 `config/alerts.yaml` 文件设置告警规则。
## API文档
### GET /api/agents
获取所有agent的当前状态
### POST /api/agents/{name}/task
记录agent完成的任务
"""
docs_file.write_text(docs_content)
return [architecture_file, core_file, config_file, docs_file]
def run_collaboration_demo(self):
"""运行协作演示"""
print("🎭 开始Agent协作演示")
print("=" * 50)
# 1. 架构师设计
print("1⃣ 架构师agent开始设计...")
files = self.create_demo_files()
self.manager.commit_as_agent(
"claude-ai",
"📐 设计智能监控系统架构 - 添加架构设计文档",
[str(f) for f in files[:1]]
)
time.sleep(1)
# 2. 开发者实现
print("2⃣ 开发者agent开始编码...")
self.manager.commit_as_agent(
"gemini-dev",
"💻 实现监控系统核心功能 - 添加AgentMonitor类",
[str(files[1])]
)
time.sleep(1)
# 3. 运维配置
print("3⃣ 运维agent配置部署...")
self.manager.commit_as_agent(
"qwen-ops",
"⚙️ 添加Docker部署配置 - 支持一键启动",
[str(files[2])]
)
time.sleep(1)
# 4. 研究员文档
print("4⃣ 研究员agent撰写文档...")
self.manager.commit_as_agent(
"llama-research",
"📚 完善使用文档 - 添加API说明和快速指南",
[str(files[3])]
)
time.sleep(1)
# 5. 架构师review
print("5⃣ 架构师review并优化...")
optimize_file = self.base_dir / "demo_feature" / "optimization.md"
optimize_content = """# 架构优化建议
基于实现代码的review提出以下优化
## 性能优化
- 使用asyncio.create_task替换直接调用
- 添加连接池管理
## 监控增强
- 添加prometheus指标收集
- 实现健康检查端点
## 下一步计划
1. 实现告警系统
2. 添加Web界面
3. 集成日志分析
"""
optimize_file.write_text(optimize_content)
self.manager.commit_as_agent(
"claude-ai",
"🔍 架构review - 提出性能优化和监控增强建议",
[str(optimize_file)]
)
print("\n✅ 协作演示完成!")
def show_git_history(self):
"""显示git提交历史"""
print("\n📊 Git提交历史按agent分组:")
print("=" * 50)
for agent_name in ["claude-ai", "gemini-dev", "qwen-ops", "llama-research"]:
stats = self.manager.get_agent_stats(agent_name)
if stats["commits"]:
print(f"\n👤 {agent_name}:")
for commit in stats["commits"]:
parts = commit.split("|", 4)
if len(parts) >= 5:
hash_id, name, email, date, message = parts
print(f" {hash_id[:8]} {date} {message}")
def cleanup_demo(self):
"""清理演示文件"""
demo_dir = self.base_dir / "demo_feature"
if demo_dir.exists():
# 保留git历史只移除工作区文件
subprocess.run(["git", "rm", "-rf", "demo_feature"],
cwd=self.base_dir, capture_output=True)
subprocess.run(["git", "commit", "-m", "🧹 清理演示文件 - 保留协作历史"],
cwd=self.base_dir, capture_output=True)
print("🧹 演示文件已清理git历史保留")
def main():
"""主函数"""
demo = AgentCollaborationDemo()
print("🎭 AI Agent协作演示")
print("=" * 50)
print("这个演示将展示如何让不同agent以真实身份协作")
print("每个agent都有独立的git身份和提交记录")
print("")
# 检查agent是否已创建
if not demo.manager.list_agents():
print("❌ 请先运行 ./agents/setup_agents.sh 创建agent")
return
# 运行演示
demo.run_collaboration_demo()
demo.show_git_history()
print("\n💡 下一步:")
print("1. 查看git log --oneline --graph 查看提交历史")
print("2. 使用 ./agents/stats.sh 查看agent统计")
print("3. 开始你自己的多agent协作项目")
# 询问是否清理
response = input("\n是否清理演示文件?(y/N): ")
if response.lower() == 'y':
demo.cleanup_demo()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,314 @@
"""
Git 协作管理系统
管理 Agent 之间基于 Git 的真实协作
"""
import os
import subprocess
import json
from pathlib import Path
from typing import Dict, List, Optional, Tuple, Any
from dataclasses import dataclass
import logging
from .identity_manager import AgentIdentityManager
@dataclass
class Repository:
"""仓库信息"""
name: str
local_path: str
remotes: Dict[str, str] # remote_name -> url
current_agent: Optional[str] = None
class GitCollaborationManager:
"""Git 协作管理器"""
def __init__(self, identity_manager: AgentIdentityManager):
self.identity_manager = identity_manager
self.logger = logging.getLogger(__name__)
self.repositories = {}
self._load_repositories()
def _load_repositories(self):
"""加载仓库配置"""
config_file = Path("config/repositories.json")
if config_file.exists():
with open(config_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.repositories = {
name: Repository(**repo_data)
for name, repo_data in data.items()
}
def _save_repositories(self):
"""保存仓库配置"""
config_file = Path("config/repositories.json")
config_file.parent.mkdir(exist_ok=True)
data = {
name: {
'name': repo.name,
'local_path': repo.local_path,
'remotes': repo.remotes,
'current_agent': repo.current_agent
}
for name, repo in self.repositories.items()
}
with open(config_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
def setup_progressive_deployment(self,
repo_name: str,
gitea_url: str,
bitbucket_url: str,
github_url: str,
local_path: Optional[str] = None):
"""设置渐进发布的三个远程仓库"""
if not local_path:
local_path_str = f"./repos/{repo_name}"
else:
local_path_str = local_path
local_path_obj = Path(local_path_str)
local_path_obj.mkdir(parents=True, exist_ok=True)
# 初始化本地仓库(如果不存在)
if not (local_path_obj / ".git").exists():
subprocess.run(["git", "init"], cwd=local_path)
# 设置远程仓库
remotes = {
"gitea": gitea_url,
"bitbucket": bitbucket_url,
"github": github_url
}
for remote_name, remote_url in remotes.items():
# 检查远程是否已存在
result = subprocess.run([
"git", "remote", "get-url", remote_name
], cwd=local_path, capture_output=True, text=True)
if result.returncode != 0:
# 添加新的远程
subprocess.run([
"git", "remote", "add", remote_name, remote_url
], cwd=local_path)
else:
# 更新现有远程
subprocess.run([
"git", "remote", "set-url", remote_name, remote_url
], cwd=local_path)
# 创建仓库记录
repository = Repository(
name=repo_name,
local_path=str(local_path),
remotes=remotes
)
self.repositories[repo_name] = repository
self._save_repositories()
self.logger.info(f"设置渐进发布仓库: {repo_name}")
return repository
def switch_agent_context(self, repo_name: str, agent_name: str):
"""切换仓库的 Agent 上下文"""
if repo_name not in self.repositories:
raise ValueError(f"仓库 {repo_name} 不存在")
repository = self.repositories[repo_name]
# 设置 Git 配置
self.identity_manager.setup_git_config(agent_name, repository.local_path)
# 设置 SSH 密钥
identity = self.identity_manager.get_agent_identity(agent_name)
if identity:
self._setup_ssh_agent(identity.ssh_key_path)
repository.current_agent = agent_name
self._save_repositories()
self.logger.info(f"切换仓库 {repo_name} 到 Agent: {agent_name}")
def _setup_ssh_agent(self, ssh_key_path: str):
"""设置 SSH Agent"""
try:
# 启动 ssh-agent如果未运行
result = subprocess.run([
"ssh-add", "-l"
], capture_output=True, text=True)
if result.returncode != 0:
# 启动 ssh-agent
result = subprocess.run([
"ssh-agent", "-s"
], capture_output=True, text=True)
if result.returncode == 0:
# 解析环境变量
for line in result.stdout.split('\n'):
if 'SSH_AUTH_SOCK' in line:
sock = line.split('=')[1].split(';')[0]
os.environ['SSH_AUTH_SOCK'] = sock
elif 'SSH_AGENT_PID' in line:
pid = line.split('=')[1].split(';')[0]
os.environ['SSH_AGENT_PID'] = pid
# 添加 SSH 密钥
subprocess.run(["ssh-add", ssh_key_path])
except Exception as e:
self.logger.warning(f"SSH Agent 设置失败: {e}")
def commit_as_agent(self,
repo_name: str,
message: str,
files: Optional[List[str]] = None,
sign: bool = True) -> bool:
"""以当前 Agent 身份提交代码"""
if repo_name not in self.repositories:
raise ValueError(f"仓库 {repo_name} 不存在")
repository = self.repositories[repo_name]
repo_path = Path(repository.local_path)
try:
# 添加文件
if files:
for file in files:
subprocess.run(["git", "add", file], cwd=repo_path)
else:
subprocess.run(["git", "add", "."], cwd=repo_path)
# 提交
commit_cmd = ["git", "commit", "-m", message]
if sign:
commit_cmd.append("-S")
result = subprocess.run(commit_cmd, cwd=repo_path, capture_output=True, text=True)
if result.returncode == 0:
self.logger.info(f"Agent {repository.current_agent} 提交成功: {message}")
return True
else:
self.logger.error(f"提交失败: {result.stderr}")
return False
except Exception as e:
self.logger.error(f"提交过程出错: {e}")
return False
def progressive_push(self, repo_name: str, branch: str = "main") -> Dict[str, bool]:
"""渐进式推送到三个平台"""
if repo_name not in self.repositories:
raise ValueError(f"仓库 {repo_name} 不存在")
repository = self.repositories[repo_name]
repo_path = Path(repository.local_path)
results = {}
# 按顺序推送Gitea -> Bitbucket -> GitHub
push_order = ["gitea", "bitbucket", "github"]
for remote in push_order:
if remote in repository.remotes:
try:
result = subprocess.run([
"git", "push", remote, branch
], cwd=repo_path, capture_output=True, text=True)
results[remote] = result.returncode == 0
if result.returncode == 0:
self.logger.info(f"推送到 {remote} 成功")
else:
self.logger.error(f"推送到 {remote} 失败: {result.stderr}")
# 如果某个平台失败,停止后续推送
break
except Exception as e:
self.logger.error(f"推送到 {remote} 出错: {e}")
results[remote] = False
break
return results
def create_pull_request_workflow(self,
repo_name: str,
source_agent: str,
target_agent: str,
feature_branch: str,
title: str,
description: str = "") -> bool:
"""创建 Agent 间的 Pull Request 工作流"""
repository = self.repositories[repo_name]
repo_path = Path(repository.local_path)
try:
# 1. 切换到源 Agent
self.switch_agent_context(repo_name, source_agent)
# 2. 创建功能分支
subprocess.run([
"git", "checkout", "-b", feature_branch
], cwd=repo_path)
# 3. 推送功能分支
subprocess.run([
"git", "push", "-u", "gitea", feature_branch
], cwd=repo_path)
# 4. 这里可以集成 API 调用来创建实际的 PR
# 具体实现取决于使用的 Git 平台
self.logger.info(f"创建 PR 工作流: {source_agent} -> {target_agent}")
return True
except Exception as e:
self.logger.error(f"创建 PR 工作流失败: {e}")
return False
def get_repository_status(self, repo_name: str) -> Dict[str, Any]:
"""获取仓库状态"""
if repo_name not in self.repositories:
raise ValueError(f"仓库 {repo_name} 不存在")
repository = self.repositories[repo_name]
repo_path = Path(repository.local_path)
status = {
"current_agent": repository.current_agent,
"branch": None,
"uncommitted_changes": False,
"remotes": repository.remotes
}
try:
# 获取当前分支
result = subprocess.run([
"git", "branch", "--show-current"
], cwd=repo_path, capture_output=True, text=True)
if result.returncode == 0:
status["branch"] = result.stdout.strip()
# 检查未提交的更改
result = subprocess.run([
"git", "status", "--porcelain"
], cwd=repo_path, capture_output=True, text=True)
status["uncommitted_changes"] = bool(result.stdout.strip())
except Exception as e:
self.logger.error(f"获取仓库状态失败: {e}")
return status

View File

@@ -0,0 +1,30 @@
{
"claude-ai": {
"name": "claude-ai",
"email": "claude@ai-collaboration.local",
"role": "架构师",
"ssh_key_path": "/home/ben/github/liurenchaxin/agents/keys/claude-ai_rsa",
"gpg_key_id": "CLAUDE-AI12345678"
},
"gemini-dev": {
"name": "gemini-dev",
"email": "gemini@ai-collaboration.local",
"role": "开发者",
"ssh_key_path": "/home/ben/github/liurenchaxin/agents/keys/gemini-dev_rsa",
"gpg_key_id": "GEMINI-DEV12345678"
},
"qwen-ops": {
"name": "qwen-ops",
"email": "qwen@ai-collaboration.local",
"role": "运维",
"ssh_key_path": "/home/ben/github/liurenchaxin/agents/keys/qwen-ops_rsa",
"gpg_key_id": "QWEN-OPS12345678"
},
"llama-research": {
"name": "llama-research",
"email": "llama@ai-collaboration.local",
"role": "研究员",
"ssh_key_path": "/home/ben/github/liurenchaxin/agents/keys/llama-research_rsa",
"gpg_key_id": "LLAMA-RESEARCH12345678"
}
}

View File

@@ -0,0 +1,237 @@
"""
Agent Identity Management System
管理多个 AI Agent 的身份信息,包括 SSH/GPG 密钥、Git 配置等
"""
import os
import json
import subprocess
from pathlib import Path
from typing import Dict, List, Optional
from dataclasses import dataclass, asdict
import logging
@dataclass
class AgentIdentity:
"""Agent 身份信息"""
name: str
email: str
ssh_key_path: str
gpg_key_id: Optional[str] = None
git_username: str = ""
description: str = ""
repositories: List[str] = None
def __post_init__(self):
if self.repositories is None:
self.repositories = []
if not self.git_username:
self.git_username = self.name.lower().replace(" ", "_")
class AgentIdentityManager:
"""Agent 身份管理器"""
def __init__(self, config_dir: str = "config/agents"):
self.config_dir = Path(config_dir)
self.config_dir.mkdir(parents=True, exist_ok=True)
self.identities_file = self.config_dir / "identities.json"
self.ssh_keys_dir = self.config_dir / "ssh_keys"
self.gpg_keys_dir = self.config_dir / "gpg_keys"
# 创建必要的目录
self.ssh_keys_dir.mkdir(exist_ok=True)
self.gpg_keys_dir.mkdir(exist_ok=True)
self.logger = logging.getLogger(__name__)
self._load_identities()
def _load_identities(self):
"""加载已有的身份信息"""
if self.identities_file.exists():
with open(self.identities_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.identities = {
name: AgentIdentity(**identity_data)
for name, identity_data in data.items()
}
else:
self.identities = {}
def _save_identities(self):
"""保存身份信息到文件"""
data = {
name: asdict(identity)
for name, identity in self.identities.items()
}
with open(self.identities_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
def create_agent_identity(self,
name: str,
email: str,
description: str = "",
generate_keys: bool = True) -> AgentIdentity:
"""创建新的 Agent 身份"""
if name in self.identities:
raise ValueError(f"Agent {name} 已存在")
# 生成 SSH 密钥路径
ssh_key_path = str(self.ssh_keys_dir / f"{name.lower().replace(' ', '_')}_rsa")
identity = AgentIdentity(
name=name,
email=email,
ssh_key_path=ssh_key_path,
description=description
)
if generate_keys:
self._generate_ssh_key(identity)
self._generate_gpg_key(identity)
self.identities[name] = identity
self._save_identities()
self.logger.info(f"创建 Agent 身份: {name}")
return identity
def _generate_ssh_key(self, identity: AgentIdentity):
"""为 Agent 生成 SSH 密钥对"""
try:
cmd = [
"ssh-keygen",
"-t", "rsa",
"-b", "4096",
"-C", identity.email,
"-f", identity.ssh_key_path,
"-N", "" # 无密码
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"SSH 密钥生成失败: {result.stderr}")
# 设置正确的权限
os.chmod(identity.ssh_key_path, 0o600)
os.chmod(f"{identity.ssh_key_path}.pub", 0o644)
self.logger.info(f"{identity.name} 生成 SSH 密钥: {identity.ssh_key_path}")
except Exception as e:
self.logger.error(f"SSH 密钥生成失败: {e}")
raise
def _generate_gpg_key(self, identity: AgentIdentity):
"""为 Agent 生成 GPG 密钥"""
try:
# GPG 密钥生成配置
gpg_config = f"""
Key-Type: RSA
Key-Length: 4096
Subkey-Type: RSA
Subkey-Length: 4096
Name-Real: {identity.name}
Name-Email: {identity.email}
Expire-Date: 0
%no-protection
%commit
"""
# 写入临时配置文件
config_file = self.gpg_keys_dir / f"{identity.git_username}_gpg_config"
with open(config_file, 'w') as f:
f.write(gpg_config)
# 生成 GPG 密钥
cmd = ["gpg", "--batch", "--generate-key", str(config_file)]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
self.logger.warning(f"GPG 密钥生成失败: {result.stderr}")
return
# 获取生成的密钥 ID
cmd = ["gpg", "--list-secret-keys", "--keyid-format", "LONG", identity.email]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
# 解析密钥 ID
lines = result.stdout.split('\n')
for line in lines:
if 'sec' in line and 'rsa4096/' in line:
key_id = line.split('rsa4096/')[1].split(' ')[0]
identity.gpg_key_id = key_id
break
# 清理临时文件
config_file.unlink()
self.logger.info(f"{identity.name} 生成 GPG 密钥: {identity.gpg_key_id}")
except Exception as e:
self.logger.warning(f"GPG 密钥生成失败: {e}")
def get_agent_identity(self, name: str) -> Optional[AgentIdentity]:
"""获取 Agent 身份信息"""
return self.identities.get(name)
def list_agents(self) -> List[str]:
"""列出所有 Agent"""
return list(self.identities.keys())
def setup_git_config(self, agent_name: str, repo_path: str = "."):
"""为指定仓库设置 Agent 的 Git 配置"""
identity = self.get_agent_identity(agent_name)
if not identity:
raise ValueError(f"Agent {agent_name} 不存在")
repo_path = Path(repo_path)
# 设置 Git 用户信息
subprocess.run([
"git", "config", "--local", "user.name", identity.name
], cwd=repo_path)
subprocess.run([
"git", "config", "--local", "user.email", identity.email
], cwd=repo_path)
# 设置 GPG 签名
if identity.gpg_key_id:
subprocess.run([
"git", "config", "--local", "user.signingkey", identity.gpg_key_id
], cwd=repo_path)
subprocess.run([
"git", "config", "--local", "commit.gpgsign", "true"
], cwd=repo_path)
self.logger.info(f"为仓库 {repo_path} 设置 {agent_name} 的 Git 配置")
def get_ssh_public_key(self, agent_name: str) -> str:
"""获取 Agent 的 SSH 公钥"""
identity = self.get_agent_identity(agent_name)
if not identity:
raise ValueError(f"Agent {agent_name} 不存在")
pub_key_path = f"{identity.ssh_key_path}.pub"
if not os.path.exists(pub_key_path):
raise FileNotFoundError(f"SSH 公钥文件不存在: {pub_key_path}")
with open(pub_key_path, 'r') as f:
return f.read().strip()
def export_gpg_public_key(self, agent_name: str) -> str:
"""导出 Agent 的 GPG 公钥"""
identity = self.get_agent_identity(agent_name)
if not identity or not identity.gpg_key_id:
raise ValueError(f"Agent {agent_name} 没有 GPG 密钥")
cmd = ["gpg", "--armor", "--export", identity.gpg_key_id]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"GPG 公钥导出失败: {result.stderr}")
return result.stdout

View File

@@ -0,0 +1,49 @@
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDDEVNGzV1W/FZs9BULLAb/qabDQ0BrsIyp5yV7D7ImJKA260o8r8K0Dwktyizn1qmoIdTVn2/PD7t0BbD4E5XIddsIGof35TvHksjpA29dySOEqQihp+M9PPZWvnUAou3S7sQQ96ARPJJsmhhy+55fT5+XxWxu/bTGYpCFg9ZjeftzTfvWFKvZznGopafUTKprSavIsfriedEukmgveoQ/PF7692Ovf/ypX0JgRqTZ62yIZN0H4q9R4+9f05kuLte63i1xMO2MujqIAbsP7S/1fyIIg8/jHq0XejMm2r+QOIhrDRiv+AiNoQyGrtDfD49/L2HHT3h1aIQpbxEHJOX5wdSRvdXxWH1pteCU9zc01mOVJVWpWWlgvqJ/s0J6qarD1ecgIjhwRKCd6sCs21ShbrD5kATpVYp4mSpqK1Hf6J4UDLkOJYrFFBXkjdiHI4jCA92amsJg9TUbdpIELFreq7wCVAz9Wb4d+si0snQNVg0xuwEDIEoB+mNSMKaTH4KWwCcpD7dKd5CMkcIhGxzL4yVMoo6lvBnAGILrzmNZWbwAUJJX62aGVU2HGBQGVWs75zJbWjLKmTVban20SrE4woWVlh8+KzF2tGbGVjnAfpCcYVHetXcoHBCUbkFEjN9tD/nhxxyyKE8ZtgZ2d2OB5M9vryhgwBgaC5ki0LD4iQ== claude@ai-collaboration.local

View File

@@ -0,0 +1,49 @@
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCi7jZJ6mBTXgtfh4cTgyq182iOhFl4aJmbKlrtZSktvFZh18Vw83rBUx5AOxg97VD5pxTeNpYVtDE3hO5zUnqPpKBub3TtCJ3XhmB80j8PYmTEhNZ5FL00efowxC/U4W+RHCcAdL3rAQB05Lhd7A4lMXj/04gO4/Z2XZAIbqSmU+KHf8u8Dwo7MWdYfC3HyiisAdBpr6RLY6PbMroKKMTEycWG2cYHBvdqgpXva4yl1LDTMSHScC55su1sZDtVKpk7X/bnNdzP0Av/BZjQLizK0nEBDbohV3plblr1LBJlIwgWv/BbL757qdnOIlubiVz+Jb5Sni12JUzbENwJvp+3fGoILZcl14NXSCzVmrEUvIaGtoLo4oCRac66+K8tgQDsvoY6T58tlTRPLCeOtEeFHiE3K4TYxhvRQwC8HP7RfBBa3PTyPZ2CSGgOtp3VmxsZFpqmJw09a3l++B8SmS0L8AmGj08YZuOkDWbV/Unm6JCzUtxxg1g/x66/YANZqWazgA77Gumr+UeJl2g40tgQxgwpkkZXjWe629FtLUZjvKdNQQ+3/Vq6Tk9nz1S202StXnrDY5ayWxhtG4LqQmW9oZ6hOQ5mWUvWghSskxXYTLZtfqc0SYYrTYU4fvMRKg9okLrjV3ZcGgYr36vmRB3JLjh3Vs7R9CoI/+o7CxY8LQ== gemini@ai-collaboration.local

View File

@@ -0,0 +1,49 @@
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDBzcrx/q/zx/HPbsji5dIlBth+Ro6wyAapaPRnIoB1eUEbGv0Z0gDs9TQu750GBQfernHSw/qOtxyeDqGp1P5RerL3SV8Llksb9v+DdjSKtSaauww4RQqxMVsDc0ituhXHj7VbBUNFck88b0MGz8uQnPCE3QT8tX/1tSzUgAugKuIIMe5Dx2HglyeTfzQSfVwvkUFuCIV2bD+HHer8CNViBcrbE5xh1qXDXb/gQ0jds+nFCCcdSC/9DCdTIzHhUIBkWu0MeXFVKzteLkFeQ6jPFFc5SCj2AZpFk4G7FYKRGWnu6JzSb6sn1jC4t+UG2h8yzJ0/naJ8mi91tnoft7klIjKaVj0GAzhNyYyrFmW18yiR1ZwkEFq23kh+BS588vimyy39EFvVUBkYGc044xRR+zu/TrkVRzv2Py0l0Z//5VHByaVN+qsgd9Yui/w2xN/gsZBNe9XQvOkzmNVF96v8nUdOjs9oSHRoqOg5ERtRXURRYrMeqAdcC/l7+iW9t3yZlZOaTc5qqOzwTZgxtckr7eRGy9Ap7ah9Op+pV+q86vPjHlx2iK5SM1DHCw2WWeSZ6w/q4stJaDyJ82vwe8rviotLhFbtWJhUuCZvIyJvJKtBQ3YKQjNAbosrKQNvcfA2jKm44TESCG0pPyeKy3w2p76wd+eKGJr1YpLgX5QFKw== llama@ai-collaboration.local

View File

@@ -0,0 +1,49 @@
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDOapLyoJP6EELcpqEbAFxTGBhOXf5f9BM4Unz5cl0A3sSryj2jROBMegXRf0dFrTJoiHcTrY0o+agzZ3resMARKNZoQZc1rtN/1KQf3acducJiAZ1GZNSCDlLHKp2WDXncoyuL1X58/tZJA+/Qb2DyixHbY2fxVaDPUpMP4IJSQg8MLgTOstXIAZ9GYHA2naVf9uJuNq+GotqgK5+KcToyjueXVCVCQvrhrCCIgc2QNjSm3odbw1Dx9h0tDbT5jTpVrsZY1681P6EVekyUhb8lm6IuOcXWTooltM3OOQfSFDtBRKl5iYBmmm53jDtcA86X8A7eSjrFaoRcufuOxHhIIQ1RIU9yNdLTtgm3nQUwe00siZcX/WTusmCK9tRGOw8hvPqyD0xwtN3i9lrtjkA0JgRTGhhbea3cmjESlVLAPPaTvxSsHeQJZnzWEydm0AadzQ3i+kHQV9OvrSkVdhKNS0zFHq6rBnYMNHijvGNPMEWAiVfZwPYwAnPpMB0kczeH4TfMeCXja7ro22ulEnrCQIQKGX2Mnq14TmmSQhM8iHMtOMqdd1SecI17b0bp5icd79VVkdCbe5IrdHNmq++vmG7731frItyiBoxnFVFPZMzhBJnogQ4oqf5ZQSeOcKkkVrG1Xvo8H284mCjveGuvwiqveGY1EpLBjeQql9Pnaw== qwen@ai-collaboration.local

View File

@@ -0,0 +1,11 @@
#!/bin/bash
# Agent提交前的钩子
echo "🔍 检查agent身份..."
AGENT_NAME=$(git config user.name)
if [[ -z "$AGENT_NAME" ]]; then
echo "❌ 未设置agent身份请先使用agent协作系统"
exit 1
fi
echo "✅ 当前agent: $AGENT_NAME"

View File

@@ -0,0 +1,167 @@
#!/bin/bash
# Agent协作系统设置脚本
# 为一人公司创建多agent git协作环境
set -e
echo "🚀 设置AI Agent协作系统..."
# 创建必要的目录
mkdir -p agents/keys
mkdir -p agents/logs
# 设置权限
chmod 700 agents/keys
# 检查依赖
check_dependency() {
if ! command -v $1 &> /dev/null; then
echo "❌ 需要安装: $1"
exit 1
fi
}
check_dependency "git"
check_dependency "ssh-keygen"
echo "✅ 依赖检查通过"
# 初始化agent身份管理器
echo "🤖 初始化agent身份..."
python3 agents/agent_identity_manager.py
# 创建git hooks模板
cat > agents/pre-commit-hook << 'EOF'
#!/bin/bash
# Agent提交前的钩子
echo "🔍 检查agent身份..."
AGENT_NAME=$(git config user.name)
if [[ -z "$AGENT_NAME" ]]; then
echo "❌ 未设置agent身份请先使用agent协作系统"
exit 1
fi
echo "✅ 当前agent: $AGENT_NAME"
EOF
chmod +x agents/pre-commit-hook
# 创建快速切换脚本
cat > agents/switch_agent.sh << 'EOF'
#!/bin/bash
# 快速切换agent身份
if [[ $# -eq 0 ]]; then
echo "用法: ./switch_agent.sh <agent名称>"
echo "可用agents:"
python3 -c "
import sys
sys.path.append('agents')
from agent_identity_manager import AgentIdentityManager
manager = AgentIdentityManager()
for agent in manager.list_agents():
print(f' - {agent[\"name\"]} ({agent[\"role\"]})')
"
exit 1
fi
AGENT_NAME=$1
echo "🔄 切换到agent: $AGENT_NAME"
python3 -c "
import sys
sys.path.append('agents')
from agent_identity_manager import AgentIdentityManager
manager = AgentIdentityManager()
try:
manager.switch_to_agent('$AGENT_NAME')
print('✅ 切换成功')
except Exception as e:
print(f'❌ 切换失败: {e}')
exit(1)
"
EOF
chmod +x agents/switch_agent.sh
# 创建agent提交脚本
cat > agents/commit_as_agent.sh << 'EOF'
#!/bin/bash
# 以指定agent身份提交
if [[ $# -lt 2 ]]; then
echo "用法: ./commit_as_agent.sh <agent名称> \"提交信息\" [文件...]"
exit 1
fi
AGENT_NAME=$1
MESSAGE=$2
shift 2
FILES=$@
echo "📝 Agent $AGENT_NAME 正在提交..."
python3 -c "
import sys
sys.path.append('agents')
from agent_identity_manager import AgentIdentityManager
manager = AgentIdentityManager()
try:
manager.commit_as_agent('$AGENT_NAME', '$MESSAGE', '$FILES'.split() if '$FILES' else None)
print('✅ 提交成功')
except Exception as e:
print(f'❌ 提交失败: {e}')
exit(1)
"
EOF
chmod +x agents/commit_as_agent.sh
# 创建统计脚本
cat > agents/stats.sh << 'EOF'
#!/bin/bash
# 查看agent统计信息
echo "📊 Agent协作统计"
echo "=================="
python3 -c "
import sys
sys.path.append('agents')
from agent_identity_manager import AgentIdentityManager
manager = AgentIdentityManager()
for agent in manager.list_agents():
name = agent['name']
stats = manager.get_agent_stats(name)
print(f'👤 {name} ({agent["role"]})')
print(f' 📧 {agent["email"]}')
print(f' 📈 提交数: {stats["total_commits"]}')
if stats["commits"]:
print(f' 📝 最近提交: {stats["commits"][0]}')
print()
"
EOF
chmod +x agents/stats.sh
echo "🎉 设置完成!"
echo ""
echo "📋 使用说明:"
echo "1. 查看agent列表: ./agents/stats.sh"
echo "2. 切换agent: ./agents/switch_agent.sh <agent名称>"
echo "3. agent提交: ./agents/commit_as_agent.sh <agent名称> \"消息\""
echo "4. 查看统计: ./agents/stats.sh"
echo ""
echo "🔑 SSH公钥位置:"
for key in agents/keys/*_rsa.pub; do
if [[ -f "$key" ]]; then
agent_name=$(basename "$key" _rsa.pub)
echo " $agent_name: $key"
fi
done
echo ""
echo "💡 下一步:"
echo "1. 将SSH公钥添加到GitHub/Gitea/Bitbucket"
echo "2. 测试agent切换和提交功能"
echo "3. 开始真正的多agent协作开发"

View File

@@ -0,0 +1,22 @@
#!/bin/bash
# 查看agent统计信息
echo "📊 Agent协作统计"
echo "=================="
python3 -c "
import sys
sys.path.append('agents')
from agent_identity_manager import AgentIdentityManager
manager = AgentIdentityManager()
for agent in manager.list_agents():
name = agent['name']
stats = manager.get_agent_stats(name)
print(f'👤 {name} ({agent["role"]})')
print(f' 📧 {agent["email"]}')
print(f' 📈 提交数: {stats["total_commits"]}')
if stats["commits"]:
print(f' 📝 最近提交: {stats["commits"][0]}')
print()
"

View File

@@ -0,0 +1,31 @@
#!/bin/bash
# 快速切换agent身份
if [[ $# -eq 0 ]]; then
echo "用法: ./switch_agent.sh <agent名称>"
echo "可用agents:"
python3 -c "
import sys
sys.path.append('agents')
from agent_identity_manager import AgentIdentityManager
manager = AgentIdentityManager()
for agent in manager.list_agents():
print(f' - {agent[\"name\"]} ({agent[\"role\"]})')
"
exit 1
fi
AGENT_NAME=$1
echo "🔄 切换到agent: $AGENT_NAME"
python3 -c "
import sys
sys.path.append('agents')
from agent_identity_manager import AgentIdentityManager
manager = AgentIdentityManager()
try:
manager.switch_to_agent('$AGENT_NAME')
print('✅ 切换成功')
except Exception as e:
print(f'❌ 切换失败: {e}')
exit(1)
"