chore: commit remaining workspace changes
This commit is contained in:
parent
bc30a02151
commit
70db3fae34
105
assets/aris/acp-servers/external-acp-server/README.md
Normal file
105
assets/aris/acp-servers/external-acp-server/README.md
Normal file
@ -0,0 +1,105 @@
|
||||
# External ACP Server
|
||||
|
||||
一个独立的 Agent Communication Protocol (ACP) 服务实现,支持:
|
||||
- **Single-agent 模式**: 单代理执行
|
||||
- **Multi-agent 模式**: 多代理协作
|
||||
- **自定义工具**: 扩展 MCP 工具能力
|
||||
|
||||
## 架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ ACP Server │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ WebSocket │ │ HTTP POST │ │ Tool Bridge │ │
|
||||
│ │ /acp │ │ /acp/rpc │ │ (MCP) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │ │
|
||||
│ └────────────────┴────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────▼──────┐ │
|
||||
│ │ Router │ │
|
||||
│ └──────┬──────┘ │
|
||||
│ │ │
|
||||
│ ┌────────────────┼────────────────┐ │
|
||||
│ │ │ │ │
|
||||
│ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ │
|
||||
│ │ Session │ │ Agent │ │ Tool │ │
|
||||
│ │ Manager │ │ Executor │ │ Handler │ │
|
||||
│ └───────────┘ └───────────┘ └───────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 配置环境变量
|
||||
export ACP_LISTEN_ADDR="127.0.0.1:8787"
|
||||
export ACP_MULTI_AGENT_ENABLED="true"
|
||||
|
||||
# 启动服务
|
||||
python server.py serve
|
||||
|
||||
# 或使用自定义配置
|
||||
python server.py serve --listen 0.0.0.0:9000
|
||||
```
|
||||
|
||||
## 环境变量
|
||||
|
||||
| 变量 | 默认值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `ACP_LISTEN_ADDR` | `127.0.0.1:8787` | 服务监听地址 |
|
||||
| `ACP_MULTI_AGENT_ENABLED` | `true` | 是否启用多代理模式 |
|
||||
| `ACP_MULTI_AGENT_MODEL` | `gpt-4o` | 多代理使用的模型 |
|
||||
|
||||
## 协议
|
||||
|
||||
### JSON-RPC 方法
|
||||
|
||||
| 方法 | 说明 |
|
||||
|------|------|
|
||||
| `acp.capabilities` | 查询服务器能力 |
|
||||
| `session.start` | 启动新会话 |
|
||||
| `session.message` | 发送消息(延续会话)|
|
||||
| `session.cancel` | 取消会话 |
|
||||
| `session.close` | 关闭会话 |
|
||||
|
||||
### 通知类型
|
||||
|
||||
| type | 说明 |
|
||||
|------|------|
|
||||
| `status` | 会话状态变更 |
|
||||
| `delta` | 增量文本输出 |
|
||||
| `step` | 多代理步骤进度 |
|
||||
|
||||
## 扩展自定义工具
|
||||
|
||||
在 `tools/` 目录下添加新的工具实现:
|
||||
|
||||
```python
|
||||
# tools/my_tool.py
|
||||
class MyTool:
|
||||
name = "my_tool"
|
||||
description = "工具描述"
|
||||
input_schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"input": {"type": "string", "description": "输入参数"}
|
||||
},
|
||||
"required": ["input"]
|
||||
}
|
||||
|
||||
def execute(self, arguments: dict) -> str:
|
||||
return f"处理结果: {arguments.get('input')}"
|
||||
```
|
||||
|
||||
在 `server.py` 中注册:
|
||||
|
||||
```python
|
||||
from tools.my_tool import MyTool
|
||||
|
||||
tool_registry.register(MyTool())
|
||||
```
|
||||
@ -0,0 +1,3 @@
|
||||
# ACP Server dependencies
|
||||
aiohttp>=3.9.0
|
||||
requests>=2.31.0
|
||||
1158
assets/aris/acp-servers/external-acp-server/server.py
Normal file
1158
assets/aris/acp-servers/external-acp-server/server.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,4 @@
|
||||
# Tools package for external ACP server
|
||||
# Add your custom tools here
|
||||
|
||||
from .base import Tool, ToolRegistry
|
||||
94
assets/aris/acp-servers/external-acp-server/tools/base.py
Normal file
94
assets/aris/acp-servers/external-acp-server/tools/base.py
Normal file
@ -0,0 +1,94 @@
|
||||
"""
|
||||
Tool base classes for external ACP server
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
class Tool(ABC):
|
||||
"""
|
||||
工具基类
|
||||
|
||||
所有自定义工具必须继承此类并实现以下方法:
|
||||
- name: 工具名称
|
||||
- description: 工具描述
|
||||
- input_schema: 输入参数 JSON Schema
|
||||
- execute: 执行逻辑
|
||||
"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def name(self) -> str:
|
||||
"""
|
||||
工具名称
|
||||
|
||||
必须唯一,使用小写字母和下划线,例如: code_review
|
||||
"""
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def description(self) -> str:
|
||||
"""
|
||||
工具描述
|
||||
|
||||
简短描述工具的功能,用于 AI 选择合适的工具
|
||||
"""
|
||||
pass
|
||||
|
||||
@property
|
||||
def input_schema(self) -> dict:
|
||||
"""
|
||||
输入参数 JSON Schema
|
||||
|
||||
定义工具接受的参数结构
|
||||
"""
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
|
||||
@abstractmethod
|
||||
def execute(self, arguments: dict) -> str:
|
||||
"""
|
||||
执行工具
|
||||
|
||||
Args:
|
||||
arguments: 工具参数,根据 input_schema 验证
|
||||
|
||||
Returns:
|
||||
工具执行结果,作为文本返回
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class ToolRegistry:
|
||||
"""工具注册表"""
|
||||
|
||||
def __init__(self):
|
||||
self._tools: dict[str, Tool] = {}
|
||||
|
||||
def register(self, tool: Tool):
|
||||
"""注册工具"""
|
||||
self._tools[tool.name] = tool
|
||||
|
||||
def get(self, name: str) -> Optional[Tool]:
|
||||
"""获取工具"""
|
||||
return self._tools.get(name)
|
||||
|
||||
def list_all(self) -> list[Tool]:
|
||||
"""列出所有工具"""
|
||||
return list(self._tools.values())
|
||||
|
||||
def to_mcp_tools_list(self) -> list[dict]:
|
||||
"""转换为 MCP 工具列表格式"""
|
||||
return [
|
||||
{
|
||||
"name": tool.name,
|
||||
"description": tool.description,
|
||||
"inputSchema": tool.input_schema
|
||||
}
|
||||
for tool in self._tools.values()
|
||||
]
|
||||
117
assets/aris/acp-servers/external-acp-server/tools/code_review.py
Normal file
117
assets/aris/acp-servers/external-acp-server/tools/code_review.py
Normal file
@ -0,0 +1,117 @@
|
||||
"""
|
||||
示例自定义工具:代码审查工具
|
||||
|
||||
这个工具展示了如何扩展 ACP 服务器添加自定义工具。
|
||||
"""
|
||||
|
||||
|
||||
class CodeReviewTool:
|
||||
"""代码审查工具 - 使用 LLM 审查代码变更"""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "code_review"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "Review code changes and provide feedback"
|
||||
|
||||
@property
|
||||
def input_schema(self) -> dict:
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"diff": {
|
||||
"type": "string",
|
||||
"description": "The git diff or code changes to review"
|
||||
},
|
||||
"context": {
|
||||
"type": "string",
|
||||
"description": "Optional context about the changes"
|
||||
},
|
||||
"focus": {
|
||||
"type": "string",
|
||||
"description": "Areas to focus on (security, performance, style, etc.)"
|
||||
}
|
||||
},
|
||||
"required": ["diff"]
|
||||
}
|
||||
|
||||
def execute(self, arguments: dict) -> str:
|
||||
"""
|
||||
执行代码审查
|
||||
|
||||
实际实现中,你可以:
|
||||
1. 调用外部 LLM API
|
||||
2. 使用本地模型
|
||||
3. 执行静态分析工具
|
||||
4. 查询代码库知识库
|
||||
"""
|
||||
import os
|
||||
|
||||
diff = arguments.get("diff", "")
|
||||
context = arguments.get("context", "")
|
||||
focus = arguments.get("focus", "general")
|
||||
|
||||
# 获取 LLM 配置
|
||||
api_key = os.environ.get("LLM_API_KEY", "")
|
||||
base_url = os.environ.get("LLM_BASE_URL", "https://api.openai.com/v1")
|
||||
model = os.environ.get("LLM_MODEL", "gpt-4o")
|
||||
|
||||
if not api_key:
|
||||
return "Error: LLM_API_KEY environment variable not set"
|
||||
|
||||
# 构建审查提示
|
||||
system_prompt = """You are an expert code reviewer. Analyze the provided code changes and provide:
|
||||
1. Summary of changes
|
||||
2. Potential issues (bugs, security, performance)
|
||||
3. Code style suggestions
|
||||
4. Overall assessment
|
||||
|
||||
Be concise and actionable."""
|
||||
|
||||
if focus != "general":
|
||||
system_prompt += f"\n\nFocus particularly on: {focus}"
|
||||
|
||||
user_prompt = f"Context: {context}\n\nCode changes:\n```\n{diff}\n```" if context else f"Code changes:\n```\n{diff}\n```"
|
||||
|
||||
# 调用 LLM API
|
||||
try:
|
||||
import requests
|
||||
|
||||
response = requests.post(
|
||||
f"{base_url.rstrip('/')}/chat/completions",
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {api_key}"
|
||||
},
|
||||
json={
|
||||
"model": model,
|
||||
"messages": [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": user_prompt}
|
||||
],
|
||||
"max_tokens": 4096
|
||||
},
|
||||
timeout=120
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
return f"Error: API returned {response.status_code}: {response.text[:200]}"
|
||||
|
||||
return response.json()["choices"][0]["message"]["content"]
|
||||
|
||||
except Exception as e:
|
||||
return f"Error: {e}"
|
||||
|
||||
|
||||
# 注册工具的示例
|
||||
def register_tools(registry):
|
||||
"""注册所有自定义工具"""
|
||||
from .base import Tool
|
||||
|
||||
# 注册代码审查工具
|
||||
registry.register(CodeReviewTool())
|
||||
|
||||
# 在这里添加更多工具...
|
||||
# registry.register(AnotherTool())
|
||||
@ -26,8 +26,8 @@
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||
8E6F4A7D31A1A10100A1B2C3 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 8E6F4A7C31A1A10100A1B2C3 /* PrivacyInfo.xcprivacy */; };
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||
8E6F4A7D31A1A10100A1B2C3 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 8E6F4A7C31A1A10100A1B2C3 /* PrivacyInfo.xcprivacy */; };
|
||||
A96EF8FFA0E80B16252FE834 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5F4830709C3A67EC8096888 /* Pods_RunnerTests.framework */; };
|
||||
F02922E20E15948F8CE5469F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2099D82E31DC5912EA477802 /* Pods_Runner.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
@ -74,7 +74,6 @@
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
|
||||
8E6F4A7C31A1A10100A1B2C3 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Runner/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
|
||||
@ -85,6 +84,7 @@
|
||||
73098D7450C105A02267F617 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
890E8B245EC31E1C0F085895 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
8E6F4A7C31A1A10100A1B2C3 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Runner/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
B5F4830709C3A67EC8096888 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D8467093D02A39550CF15067 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
@ -422,7 +422,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n/bin/sh \"${PROJECT_DIR}/../scripts/ensure-framework-dsyms.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
@ -4,7 +4,13 @@ set -euo pipefail
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
BRIDGE_DIR="$ROOT_DIR/go/go_core"
|
||||
OUTPUT_DIR="${OUTPUT_DIR:-$ROOT_DIR/build/bin}"
|
||||
OUTPUT_PATH="${OUTPUT_PATH:-$OUTPUT_DIR/xworkmate-go-core}"
|
||||
OUTPUT_PATH_BASE="${OUTPUT_DIR}/xworkmate-go-core"
|
||||
|
||||
if [[ "$(uname -s)" == *MINGW* || "$(uname -s)" == *MSYS* || "$(uname -s)" == *CYGWIN* ]]; then
|
||||
OUTPUT_PATH="${OUTPUT_PATH:-${OUTPUT_PATH_BASE}.exe}"
|
||||
else
|
||||
OUTPUT_PATH="${OUTPUT_PATH:-${OUTPUT_PATH_BASE}}"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$BRIDGE_DIR/go.mod" ]]; then
|
||||
echo "Missing go.mod in $BRIDGE_DIR" >&2
|
||||
|
||||
Loading…
Reference in New Issue
Block a user