stigmergy 1.0.68 → 1.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +306 -300
- package/README.md +469 -301
- package/package.json +97 -81
- package/scripts/publish.js +268 -0
- package/scripts/simple-publish.js +59 -0
- package/src/index.js +12 -0
- package/test/enhanced-main-alignment.test.js +298 -0
- package/test/hook-system-integration-test.js +307 -0
- package/test/natural-language-skills-test.js +320 -0
- package/test/nl-integration-test.js +179 -0
- package/test/parameter-parsing-test.js +143 -0
- package/test/real-test.js +435 -0
- package/test/system-compatibility-test.js +447 -0
- package/test/tdd-fixes-test.js +211 -0
- package/test/third-party-skills-test.js +321 -0
- package/test/tool-selection-integration-test.js +157 -0
- package/test/unit/cli-scanner.test.js +291 -0
- package/test/unit/cross-cli-executor.test.js +399 -0
- package/src/adapters/claude/__init__.py +0 -13
- package/src/adapters/claude/claude_skills_integration.py +0 -609
- package/src/adapters/claude/hook_adapter.py +0 -663
- package/src/adapters/claude/install_claude_integration.py +0 -265
- package/src/adapters/claude/skills_hook_adapter.py +0 -841
- package/src/adapters/claude/standalone_claude_adapter.py +0 -384
- package/src/adapters/cline/__init__.py +0 -20
- package/src/adapters/cline/config.py +0 -108
- package/src/adapters/cline/install_cline_integration.py +0 -617
- package/src/adapters/cline/mcp_server.py +0 -713
- package/src/adapters/cline/standalone_cline_adapter.py +0 -459
- package/src/adapters/codebuddy/__init__.py +0 -13
- package/src/adapters/codebuddy/buddy_adapter.py +0 -1125
- package/src/adapters/codebuddy/install_codebuddy_integration.py +0 -279
- package/src/adapters/codebuddy/skills_hook_adapter.py +0 -672
- package/src/adapters/codebuddy/skills_integration.py +0 -395
- package/src/adapters/codebuddy/standalone_codebuddy_adapter.py +0 -403
- package/src/adapters/codex/__init__.py +0 -11
- package/src/adapters/codex/base.py +0 -46
- package/src/adapters/codex/install_codex_integration.py +0 -311
- package/src/adapters/codex/mcp_server.py +0 -493
- package/src/adapters/codex/natural_language_parser.py +0 -82
- package/src/adapters/codex/slash_command_adapter.py +0 -326
- package/src/adapters/codex/standalone_codex_adapter.py +0 -362
- package/src/adapters/copilot/__init__.py +0 -13
- package/src/adapters/copilot/install_copilot_integration.py +0 -564
- package/src/adapters/copilot/mcp_adapter.py +0 -772
- package/src/adapters/copilot/mcp_server.py +0 -168
- package/src/adapters/copilot/standalone_copilot_adapter.py +0 -114
- package/src/adapters/gemini/__init__.py +0 -13
- package/src/adapters/gemini/extension_adapter.py +0 -690
- package/src/adapters/gemini/install_gemini_integration.py +0 -257
- package/src/adapters/gemini/standalone_gemini_adapter.py +0 -366
- package/src/adapters/iflow/__init__.py +0 -7
- package/src/adapters/iflow/hook_adapter.py +0 -1038
- package/src/adapters/iflow/hook_installer.py +0 -536
- package/src/adapters/iflow/install_iflow_integration.py +0 -271
- package/src/adapters/iflow/official_hook_adapter.py +0 -1272
- package/src/adapters/iflow/standalone_iflow_adapter.py +0 -48
- package/src/adapters/iflow/workflow_adapter.py +0 -793
- package/src/adapters/qoder/hook_installer.py +0 -732
- package/src/adapters/qoder/install_qoder_integration.py +0 -265
- package/src/adapters/qoder/notification_hook_adapter.py +0 -863
- package/src/adapters/qoder/standalone_qoder_adapter.py +0 -48
- package/src/adapters/qwen/__init__.py +0 -17
- package/src/adapters/qwencode/__init__.py +0 -13
- package/src/adapters/qwencode/inheritance_adapter.py +0 -818
- package/src/adapters/qwencode/install_qwencode_integration.py +0 -276
- package/src/adapters/qwencode/standalone_qwencode_adapter.py +0 -399
- package/src/atomic_collaboration_handler.py +0 -461
- package/src/cli_collaboration_agent.py +0 -697
- package/src/collaboration/hooks.py +0 -315
- package/src/core/__init__.py +0 -21
- package/src/core/ai_environment_scanner.py +0 -331
- package/src/core/base_adapter.py +0 -220
- package/src/core/cli_hook_integration.py +0 -406
- package/src/core/cross_cli_executor.py +0 -713
- package/src/core/cross_cli_mapping.py +0 -1165
- package/src/core/cross_platform_encoding.py +0 -365
- package/src/core/cross_platform_safe_cli.py +0 -894
- package/src/core/direct_cli_executor.py +0 -805
- package/src/core/direct_cli_hook_system.py +0 -958
- package/src/core/enhanced_init_processor.py +0 -467
- package/src/core/graceful_cli_executor.py +0 -912
- package/src/core/md_enhancer.py +0 -342
- package/src/core/md_generator.py +0 -619
- package/src/core/models.py +0 -218
- package/src/core/parser.py +0 -108
- package/src/core/real_cli_hook_system.py +0 -852
- package/src/core/real_cross_cli_system.py +0 -925
- package/src/core/verified_cross_cli_system.py +0 -961
- package/src/deploy.js +0 -737
- package/src/enhanced-main.js +0 -626
- package/src/enhanced_deploy.js +0 -303
- package/src/enhanced_universal_cli_setup.py +0 -930
- package/src/kimi_wrapper.py +0 -104
- package/src/main.js +0 -1309
- package/src/shell_integration.py +0 -398
- package/src/simple-main.js +0 -315
- package/src/smart_router_creator.py +0 -323
- package/src/universal_cli_setup.py +0 -1289
- package/src/utils/__init__.py +0 -12
- package/src/utils/cli_detector.py +0 -445
- package/src/utils/file_utils.py +0 -246
|
@@ -1,1125 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
CodeBuddy CLI Buddy适配器 - 基于CodeBuddy CLI Buddy系统的原生集成
|
|
3
|
-
|
|
4
|
-
基于CodeBuddy CLI的Buddy系统实现跨CLI调用功能。
|
|
5
|
-
CodeBuddy CLI使用Buddy模式,每个Buddy代表一个特定的技能或功能领域。
|
|
6
|
-
|
|
7
|
-
Buddy系统机制:
|
|
8
|
-
- @buddy装饰器: 用于注册Buddy技能
|
|
9
|
-
- 能力声明: 声明Buddy的功能和专长
|
|
10
|
-
- 优先级系统: Buddy调用时的优先级排序
|
|
11
|
-
- 协作协议: Buddy之间的协作机制
|
|
12
|
-
- 配置文件: buddy_config.json配置Buddy技能
|
|
13
|
-
|
|
14
|
-
完全符合项目约束条件:
|
|
15
|
-
- 使用CodeBuddy CLI官方Buddy机制
|
|
16
|
-
- 不改变CLI启动和使用方式
|
|
17
|
-
- 不依赖包装器
|
|
18
|
-
- 完全无损扩展
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
import os
|
|
22
|
-
import sys
|
|
23
|
-
import json
|
|
24
|
-
import logging
|
|
25
|
-
import asyncio
|
|
26
|
-
import importlib
|
|
27
|
-
import inspect
|
|
28
|
-
from typing import Dict, Any, Optional, List, Callable, Union
|
|
29
|
-
from datetime import datetime
|
|
30
|
-
from pathlib import Path
|
|
31
|
-
from dataclasses import dataclass, field
|
|
32
|
-
from functools import wraps
|
|
33
|
-
|
|
34
|
-
from ...core.base_adapter import BaseCrossCLIAdapter, IntentResult
|
|
35
|
-
from ...core.parser import NaturalLanguageParser
|
|
36
|
-
|
|
37
|
-
logger = logging.getLogger(__name__)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
@dataclass
|
|
41
|
-
class BuddySkill:
|
|
42
|
-
"""Buddy技能数据类"""
|
|
43
|
-
name: str
|
|
44
|
-
description: str
|
|
45
|
-
version: str = "1.0.0"
|
|
46
|
-
capabilities: List[str] = field(default_factory=list)
|
|
47
|
-
priority: int = 50
|
|
48
|
-
supported_clis: List[str] = field(default_factory=list)
|
|
49
|
-
protocols: List[str] = field(default_factory=list)
|
|
50
|
-
cross_cli_enabled: bool = True
|
|
51
|
-
auto_collaboration: bool = False
|
|
52
|
-
requires_authorization: bool = False
|
|
53
|
-
dependencies: List[str] = field(default_factory=list)
|
|
54
|
-
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
@dataclass
|
|
58
|
-
class BuddyContext:
|
|
59
|
-
"""Buddy上下文"""
|
|
60
|
-
session_id: str
|
|
61
|
-
user_input: str
|
|
62
|
-
intent: Optional[IntentResult] = None
|
|
63
|
-
buddy_name: str = ""
|
|
64
|
-
stage: str = "processing"
|
|
65
|
-
parameters: Dict[str, Any] = field(default_factory=dict)
|
|
66
|
-
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
67
|
-
timestamp: datetime = field(default_factory=datetime.now)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class CodeBuddyBuddyAdapter(BaseCrossCLIAdapter):
|
|
71
|
-
"""
|
|
72
|
-
CodeBuddy CLI Buddy适配器
|
|
73
|
-
|
|
74
|
-
通过CodeBuddy CLI的Buddy系统实现跨CLI调用功能。
|
|
75
|
-
每个Buddy代表一个特定的AI技能或功能领域。
|
|
76
|
-
|
|
77
|
-
Buddy机制:
|
|
78
|
-
- @buddy装饰器注册技能
|
|
79
|
-
- can_handle方法判断处理能力
|
|
80
|
-
- handle_request方法执行任务
|
|
81
|
-
- get_capabilities获取技能声明
|
|
82
|
-
- 优先级和能力匹配
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
def __init__(self, cli_name: str = "codebuddy"):
|
|
86
|
-
"""
|
|
87
|
-
初始化CodeBuddy Buddy适配器
|
|
88
|
-
|
|
89
|
-
Args:
|
|
90
|
-
cli_name: CLI工具名称,默认为"codebuddy"
|
|
91
|
-
"""
|
|
92
|
-
super().__init__(cli_name)
|
|
93
|
-
|
|
94
|
-
# Buddy系统配置
|
|
95
|
-
self.buddy_config_file = os.path.expanduser("~/.codebuddy/buddy_config.json")
|
|
96
|
-
self.buddy_modules_dir = os.path.expanduser("~/.codebuddy/buddies")
|
|
97
|
-
self.skills_registry: Dict[str, BuddySkill] = {}
|
|
98
|
-
self.active_buddies: Dict[str, Any] = {}
|
|
99
|
-
self.buddy_instances: Dict[str, Any] = {}
|
|
100
|
-
|
|
101
|
-
# 统计信息
|
|
102
|
-
self.buddy_calls_count = 0
|
|
103
|
-
self.cross_cli_calls_count = 0
|
|
104
|
-
self.processed_requests: List[Dict[str, Any]] = []
|
|
105
|
-
self.collaboration_sessions: Dict[str, Dict] = {}
|
|
106
|
-
|
|
107
|
-
# 组件
|
|
108
|
-
self.parser = NaturalLanguageParser()
|
|
109
|
-
|
|
110
|
-
# Buddy配置
|
|
111
|
-
self.buddy_config = {
|
|
112
|
-
"enabled": True,
|
|
113
|
-
"auto_discovery": True,
|
|
114
|
-
"max_concurrent_buddies": 10,
|
|
115
|
-
"default_timeout": 30,
|
|
116
|
-
"fallback_buddy": "general_assistant",
|
|
117
|
-
"cross_cli_integration": {
|
|
118
|
-
"enabled": True,
|
|
119
|
-
"preferred_buddies": [
|
|
120
|
-
"cross_cli_coordinator",
|
|
121
|
-
"ai_tool_bridge",
|
|
122
|
-
"universal_assistant"
|
|
123
|
-
]
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
logger.info("CodeBuddy Buddy适配器初始化完成")
|
|
128
|
-
|
|
129
|
-
async def initialize(self) -> bool:
|
|
130
|
-
"""
|
|
131
|
-
初始化适配器
|
|
132
|
-
|
|
133
|
-
Returns:
|
|
134
|
-
bool: 初始化是否成功
|
|
135
|
-
"""
|
|
136
|
-
try:
|
|
137
|
-
logger.info("开始初始化CodeBuddy Buddy适配器...")
|
|
138
|
-
|
|
139
|
-
# 1. 检查CodeBuddy CLI环境
|
|
140
|
-
if not self._check_codebuddy_environment():
|
|
141
|
-
logger.error("CodeBuddy CLI环境检查失败")
|
|
142
|
-
return False
|
|
143
|
-
|
|
144
|
-
# 2. 创建Buddy配置目录
|
|
145
|
-
await self._ensure_buddy_directories()
|
|
146
|
-
|
|
147
|
-
# 3. 加载Buddy配置
|
|
148
|
-
await self._load_buddy_config()
|
|
149
|
-
|
|
150
|
-
# 4. 注册Buddy技能
|
|
151
|
-
if not await self._register_builtin_buddies():
|
|
152
|
-
logger.error("Buddy技能注册失败")
|
|
153
|
-
return False
|
|
154
|
-
|
|
155
|
-
# 5. 发现和加载外部Buddy模块
|
|
156
|
-
if self.buddy_config["auto_discovery"]:
|
|
157
|
-
await self._discover_buddy_modules()
|
|
158
|
-
|
|
159
|
-
# 6. 初始化跨CLI协作系统
|
|
160
|
-
await self._initialize_cross_cli_system()
|
|
161
|
-
|
|
162
|
-
logger.info("CodeBuddy Buddy适配器初始化成功")
|
|
163
|
-
return True
|
|
164
|
-
|
|
165
|
-
except Exception as e:
|
|
166
|
-
logger.error(f"初始化CodeBuddy Buddy适配器失败: {e}")
|
|
167
|
-
self.record_error()
|
|
168
|
-
return False
|
|
169
|
-
|
|
170
|
-
def _check_codebuddy_environment(self) -> bool:
|
|
171
|
-
"""
|
|
172
|
-
检查CodeBuddy CLI环境
|
|
173
|
-
|
|
174
|
-
Returns:
|
|
175
|
-
bool: 环境是否可用
|
|
176
|
-
"""
|
|
177
|
-
try:
|
|
178
|
-
# 检查CodeBuddy CLI命令
|
|
179
|
-
import subprocess
|
|
180
|
-
result = subprocess.run(
|
|
181
|
-
['codebuddy', '--version'],
|
|
182
|
-
capture_output=True,
|
|
183
|
-
text=True,
|
|
184
|
-
timeout=5
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
if result.returncode == 0:
|
|
188
|
-
logger.info(f"检测到CodeBuddy CLI: {result.stdout.strip()}")
|
|
189
|
-
return True
|
|
190
|
-
else:
|
|
191
|
-
logger.warning("CodeBuddy CLI不可用,使用开发模式")
|
|
192
|
-
return True # 开发环境中继续
|
|
193
|
-
|
|
194
|
-
except (subprocess.TimeoutExpired, FileNotFoundError):
|
|
195
|
-
logger.warning("CodeBuddy CLI环境检查失败,使用开发模式")
|
|
196
|
-
return True # 开发环境中继续
|
|
197
|
-
|
|
198
|
-
async def _ensure_buddy directories(self) -> None:
|
|
199
|
-
"""确保Buddy目录存在"""
|
|
200
|
-
directories = [
|
|
201
|
-
os.path.expanduser("~/.codebuddy"),
|
|
202
|
-
self.buddy_modules_dir,
|
|
203
|
-
os.path.expanduser("~/.codebuddy/logs"),
|
|
204
|
-
os.path.expanduser("~/.codebuddy/cache"),
|
|
205
|
-
os.path.expanduser("~/.codebuddy/collaboration")
|
|
206
|
-
]
|
|
207
|
-
|
|
208
|
-
for directory in directories:
|
|
209
|
-
os.makedirs(directory, exist_ok=True)
|
|
210
|
-
|
|
211
|
-
async def _load_buddy_config(self) -> None:
|
|
212
|
-
"""加载Buddy配置"""
|
|
213
|
-
try:
|
|
214
|
-
if os.path.exists(self.buddy_config_file):
|
|
215
|
-
with open(self.buddy_config_file, 'r', encoding='utf-8') as f:
|
|
216
|
-
loaded_config = json.load(f)
|
|
217
|
-
|
|
218
|
-
# 合并配置
|
|
219
|
-
for key, value in loaded_config.items():
|
|
220
|
-
if key in self.buddy_config:
|
|
221
|
-
if isinstance(self.buddy_config[key], dict) and isinstance(value, dict):
|
|
222
|
-
self.buddy_config[key].update(value)
|
|
223
|
-
else:
|
|
224
|
-
self.buddy_config[key] = value
|
|
225
|
-
else:
|
|
226
|
-
self.buddy_config[key] = value
|
|
227
|
-
|
|
228
|
-
logger.info("Buddy配置加载成功")
|
|
229
|
-
else:
|
|
230
|
-
logger.info("Buddy配置文件不存在,使用默认配置")
|
|
231
|
-
await self._save_buddy_config()
|
|
232
|
-
|
|
233
|
-
except Exception as e:
|
|
234
|
-
logger.error(f"加载Buddy配置失败: {e}")
|
|
235
|
-
logger.info("使用默认Buddy配置")
|
|
236
|
-
|
|
237
|
-
async def _save_buddy_config(self) -> bool:
|
|
238
|
-
"""保存Buddy配置"""
|
|
239
|
-
try:
|
|
240
|
-
os.makedirs(os.path.dirname(self.buddy_config_file), exist_ok=True)
|
|
241
|
-
with open(self.buddy_config_file, 'w', encoding='utf-8') as f:
|
|
242
|
-
json.dump(self.buddy_config, f, indent=2, ensure_ascii=False)
|
|
243
|
-
|
|
244
|
-
logger.info(f"Buddy配置已保存到: {self.buddy_config_file}")
|
|
245
|
-
return True
|
|
246
|
-
|
|
247
|
-
except Exception as e:
|
|
248
|
-
logger.error(f"保存Buddy配置失败: {e}")
|
|
249
|
-
return False
|
|
250
|
-
|
|
251
|
-
async def _register_builtin_buddies(self) -> bool:
|
|
252
|
-
"""
|
|
253
|
-
注册内置Buddy技能
|
|
254
|
-
|
|
255
|
-
Returns:
|
|
256
|
-
bool: 注册是否成功
|
|
257
|
-
"""
|
|
258
|
-
try:
|
|
259
|
-
# 注册跨CLI协作Buddy
|
|
260
|
-
await self._register_cross_cli_coordinator_buddy()
|
|
261
|
-
|
|
262
|
-
# 注册通用AI工具Buddy
|
|
263
|
-
await self._register_ai_tool_bridge_buddy()
|
|
264
|
-
|
|
265
|
-
# 注册通用助手Buddy
|
|
266
|
-
await self._register_universal_assistant_buddy()
|
|
267
|
-
|
|
268
|
-
logger.info("内置Buddy技能注册成功")
|
|
269
|
-
return True
|
|
270
|
-
|
|
271
|
-
except Exception as e:
|
|
272
|
-
logger.error(f"注册内置Buddy技能失败: {e}")
|
|
273
|
-
return False
|
|
274
|
-
|
|
275
|
-
def buddy(self, name: str = "", description: str = "",
|
|
276
|
-
capabilities: List[str] = None, priority: int = 50,
|
|
277
|
-
supported_clis: List[str] = None, protocols: List[str] = None,
|
|
278
|
-
cross_cli_enabled: bool = True, auto_collaboration: bool = False):
|
|
279
|
-
"""
|
|
280
|
-
Buddy装饰器,用于注册Buddy技能
|
|
281
|
-
|
|
282
|
-
Args:
|
|
283
|
-
name: Buddy名称
|
|
284
|
-
description: Buddy描述
|
|
285
|
-
capabilities: Buddy能力列表
|
|
286
|
-
priority: 优先级
|
|
287
|
-
supported_clis: 支持的CLI工具列表
|
|
288
|
-
protocols: 支持的协议列表
|
|
289
|
-
cross_cli_enabled: 是否启用跨CLI功能
|
|
290
|
-
auto_collaboration: 是否启用自动协作
|
|
291
|
-
"""
|
|
292
|
-
def decorator(func: Callable):
|
|
293
|
-
# 创建Buddy技能
|
|
294
|
-
buddy_skill = BuddySkill(
|
|
295
|
-
name=name or func.__name__,
|
|
296
|
-
description=description or f"Buddy技能: {func.__name__}",
|
|
297
|
-
version="1.0.0",
|
|
298
|
-
capabilities=capabilities or [],
|
|
299
|
-
priority=priority,
|
|
300
|
-
supported_clis=supported_clis or [],
|
|
301
|
-
protocols=protocols or [
|
|
302
|
-
"请用{cli}帮我{task}",
|
|
303
|
-
"调用{cli}来{task}",
|
|
304
|
-
"用{cli}处理{task}",
|
|
305
|
-
"use {cli} to {task}",
|
|
306
|
-
"ask {cli} for {task}"
|
|
307
|
-
],
|
|
308
|
-
cross_cli_enabled=cross_cli_enabled,
|
|
309
|
-
auto_collaboration=auto_collaboration
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
# 存储技能信息
|
|
313
|
-
buddy_skill.metadata['function'] = func.__name__
|
|
314
|
-
buddy_skill.metadata['module'] = func.__module__
|
|
315
|
-
buddy_skill.metadata['docstring'] = func.__doc__
|
|
316
|
-
|
|
317
|
-
# 包装原始函数
|
|
318
|
-
@wraps(func)
|
|
319
|
-
async def wrapped_func(context: BuddyContext, *args, **kwargs) -> Any:
|
|
320
|
-
try:
|
|
321
|
-
logger.info(f"执行Buddy技能: {buddy_skill.name}")
|
|
322
|
-
|
|
323
|
-
# 记录Buddy调用
|
|
324
|
-
self.buddy_calls_count += 1
|
|
325
|
-
|
|
326
|
-
# 执行原始函数
|
|
327
|
-
result = await func(context, *args, **kwargs)
|
|
328
|
-
|
|
329
|
-
logger.info(f"Buddy技能 {buddy_skill.name} 执行完成")
|
|
330
|
-
return result
|
|
331
|
-
|
|
332
|
-
except Exception as e:
|
|
333
|
-
logger.error(f"Buddy技能 {buddy_skill.name} 执行失败: {e}")
|
|
334
|
-
self.record_error()
|
|
335
|
-
raise
|
|
336
|
-
|
|
337
|
-
# 注册技能
|
|
338
|
-
self.skills_registry[buddy_skill.name] = buddy_skill
|
|
339
|
-
|
|
340
|
-
# 如果启用了跨CLI功能,注册跨CLI能力
|
|
341
|
-
if buddy_skill.cross_cli_enabled:
|
|
342
|
-
await self._register_cross_cli_capabilities(buddy_skill, wrapped_func)
|
|
343
|
-
|
|
344
|
-
return wrapped_func
|
|
345
|
-
|
|
346
|
-
return decorator
|
|
347
|
-
|
|
348
|
-
async def _register_cross_cli_coordinator_buddy(self) -> None:
|
|
349
|
-
"""注册跨CLI协调器Buddy"""
|
|
350
|
-
|
|
351
|
-
@self.buddy(
|
|
352
|
-
name="cross_cli_coordinator",
|
|
353
|
-
description="跨CLI协调器 - 协调不同AI CLI工具的调用",
|
|
354
|
-
capabilities=[
|
|
355
|
-
"跨CLI调用协调",
|
|
356
|
-
"多工具协作",
|
|
357
|
-
"任务路由",
|
|
358
|
-
"结果整合"
|
|
359
|
-
],
|
|
360
|
-
priority=100,
|
|
361
|
-
supported_clis=["claude", "gemini", "qwencode", "iflow", "qoder", "codex"],
|
|
362
|
-
cross_cli_enabled=True,
|
|
363
|
-
auto_collaboration=True
|
|
364
|
-
)
|
|
365
|
-
async def cross_cli_coordinator_buddy(context: BuddyContext) -> str:
|
|
366
|
-
"""跨CLI协调器Buddy处理函数"""
|
|
367
|
-
if not context.intent or not context.intent.is_cross_cli:
|
|
368
|
-
return "没有检测到跨CLI调用意图"
|
|
369
|
-
|
|
370
|
-
target_cli = context.intent.target_cli
|
|
371
|
-
task = context.intent.task
|
|
372
|
-
|
|
373
|
-
logger.info(f"跨CLI协调器: 调用 {target_cli} 执行任务: {task}")
|
|
374
|
-
|
|
375
|
-
# 获取目标CLI适配器
|
|
376
|
-
from ...core.base_adapter import get_cross_cli_adapter
|
|
377
|
-
target_adapter = get_cross_cli_adapter(target_cli)
|
|
378
|
-
|
|
379
|
-
if not target_adapter or not target_adapter.is_available():
|
|
380
|
-
return f"目标CLI工具 '{target_cli}' 不可用"
|
|
381
|
-
|
|
382
|
-
# 构建执行上下文
|
|
383
|
-
execution_context = {
|
|
384
|
-
'source_cli': self.cli_name,
|
|
385
|
-
'target_cli': target_cli,
|
|
386
|
-
'original_task': task,
|
|
387
|
-
'buddy_context': {
|
|
388
|
-
'buddy_name': 'cross_cli_coordinator',
|
|
389
|
-
'capabilities': ['跨CLI调用协调', '多工具协作']
|
|
390
|
-
},
|
|
391
|
-
'timestamp': datetime.now().isoformat()
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
# 执行跨CLI调用
|
|
395
|
-
result = await target_adapter.execute_task(task, execution_context)
|
|
396
|
-
|
|
397
|
-
# 格式化结果
|
|
398
|
-
formatted_result = self._format_buddy_result(
|
|
399
|
-
"cross_cli_coordinator",
|
|
400
|
-
target_cli,
|
|
401
|
-
task,
|
|
402
|
-
result
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
return formatted_result
|
|
406
|
-
|
|
407
|
-
async def _register_ai_tool_bridge_buddy(self) -> None:
|
|
408
|
-
"""注册AI工具桥接Buddy"""
|
|
409
|
-
|
|
410
|
-
@self.buddy(
|
|
411
|
-
name="ai_tool_bridge",
|
|
412
|
-
description="AI工具桥接器 - 连接各种AI工具的通用接口",
|
|
413
|
-
capabilities=[
|
|
414
|
-
"AI工具调用",
|
|
415
|
-
"工具适配",
|
|
416
|
-
"结果转换",
|
|
417
|
-
"错误处理"
|
|
418
|
-
],
|
|
419
|
-
priority=90,
|
|
420
|
-
supported_clis=["claude", "gemini", "qwencode", "iflow", "qoder", "codex"],
|
|
421
|
-
cross_cli_enabled=True,
|
|
422
|
-
auto_collaboration=False
|
|
423
|
-
)
|
|
424
|
-
async def ai_tool_bridge_buddy(context: BuddyContext) -> str:
|
|
425
|
-
"""AI工具桥接器Buddy处理函数"""
|
|
426
|
-
if not context.intent or not context.intent.is_cross_cli:
|
|
427
|
-
return "没有检测到跨CLI调用意图"
|
|
428
|
-
|
|
429
|
-
target_cli = context.intent.target_cli
|
|
430
|
-
task = context.intent.task
|
|
431
|
-
|
|
432
|
-
# 标准化CLI名称
|
|
433
|
-
cli_mapping = {
|
|
434
|
-
'claude': 'claude',
|
|
435
|
-
'gemini': 'gemini',
|
|
436
|
-
'qwen': 'qwencode',
|
|
437
|
-
'iflow': 'iflow',
|
|
438
|
-
'qoder': 'qoder',
|
|
439
|
-
'codebuddy': 'codex'
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
normalized_cli = cli_mapping.get(target_cli.lower(), target_cli)
|
|
443
|
-
|
|
444
|
-
logger.info(f"AI工具桥接器: 桥接调用 {normalized_cli} 执行任务: {task}")
|
|
445
|
-
|
|
446
|
-
# 获取目标CLI适配器
|
|
447
|
-
from ...core.base_adapter import get_cross_cli_adapter
|
|
448
|
-
target_adapter = get_cross_cli_adapter(normalized_cli)
|
|
449
|
-
|
|
450
|
-
if not target_adapter or not target_adapter.is_available():
|
|
451
|
-
return f"目标AI工具 '{normalized_cli}' 不可用或未安装"
|
|
452
|
-
|
|
453
|
-
# 预处理任务内容
|
|
454
|
-
processed_task = self._preprocess_task_for_cli(task, normalized_cli)
|
|
455
|
-
|
|
456
|
-
# 构建执行上下文
|
|
457
|
-
execution_context = {
|
|
458
|
-
'source_cli': self.cli_name,
|
|
459
|
-
'target_cli': normalized_cli,
|
|
460
|
-
'original_task': task,
|
|
461
|
-
'processed_task': processed_task,
|
|
462
|
-
'buddy_context': {
|
|
463
|
-
'buddy_name': 'ai_tool_bridge',
|
|
464
|
-
'capabilities': ['AI工具调用', '工具适配', '结果转换']
|
|
465
|
-
},
|
|
466
|
-
'timestamp': datetime.now().isoformat()
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
# 执行跨CLI调用
|
|
470
|
-
result = await target_adapter.execute_task(processed_task, execution_context)
|
|
471
|
-
|
|
472
|
-
# 后处理结果
|
|
473
|
-
processed_result = self._postprocess_result_from_cli(result, normalized_cli)
|
|
474
|
-
|
|
475
|
-
# 格式化结果
|
|
476
|
-
formatted_result = self._format_buddy_result(
|
|
477
|
-
"ai_tool_bridge",
|
|
478
|
-
normalized_cli,
|
|
479
|
-
task,
|
|
480
|
-
processed_result
|
|
481
|
-
)
|
|
482
|
-
|
|
483
|
-
return formatted_result
|
|
484
|
-
|
|
485
|
-
async def _register_universal_assistant_buddy(self) -> None:
|
|
486
|
-
"""注册通用助手Buddy"""
|
|
487
|
-
|
|
488
|
-
@self.buddy(
|
|
489
|
-
name="universal_assistant",
|
|
490
|
-
description="通用助手 - 处理各种通用任务和协调其他Buddy",
|
|
491
|
-
capabilities=[
|
|
492
|
-
"通用问题解答",
|
|
493
|
-
"任务协调",
|
|
494
|
-
"结果整合",
|
|
495
|
-
"Buddy协作"
|
|
496
|
-
],
|
|
497
|
-
priority=70,
|
|
498
|
-
supported_clis=["claude", "gemini", "qwencode", "iflow", "qoder", "codex"],
|
|
499
|
-
cross_cli_enabled=True,
|
|
500
|
-
auto_collaboration=True
|
|
501
|
-
)
|
|
502
|
-
async def universal_assistant_buddy(context: BuddyContext) -> str:
|
|
503
|
-
"""通用助手Buddy处理函数"""
|
|
504
|
-
user_input = context.user_input
|
|
505
|
-
|
|
506
|
-
# 首先检查是否为跨CLI调用
|
|
507
|
-
if context.intent and context.intent.is_cross_cli:
|
|
508
|
-
return await self._handle_cross_cli_with_universal_assistant(context)
|
|
509
|
-
|
|
510
|
-
# 处理通用任务
|
|
511
|
-
result = await self._handle_general_task_with_universal_assistant(context)
|
|
512
|
-
return result
|
|
513
|
-
|
|
514
|
-
async def _handle_cross_cli_with_universal_assistant(self, context: BuddyContext) -> str:
|
|
515
|
-
"""通过通用助手处理跨CLI调用"""
|
|
516
|
-
target_cli = context.intent.target_cli
|
|
517
|
-
task = context.intent.task
|
|
518
|
-
|
|
519
|
-
logger.info(f"通用助手: 处理跨CLI调用到 {target_cli}")
|
|
520
|
-
|
|
521
|
-
# 使用AI工具桥接器
|
|
522
|
-
from ...core.base_adapter import get_cross_cli_adapter
|
|
523
|
-
target_adapter = get_cross_cli_adapter(target_cli)
|
|
524
|
-
|
|
525
|
-
if not target_adapter or not target_adapter.is_available():
|
|
526
|
-
return f"目标工具 '{target_cli}' 不可用"
|
|
527
|
-
|
|
528
|
-
execution_context = {
|
|
529
|
-
'source_cli': self.cli_name,
|
|
530
|
-
'target_cli': target_cli,
|
|
531
|
-
'original_task': task,
|
|
532
|
-
'buddy_context': {
|
|
533
|
-
'buddy_name': 'universal_assistant',
|
|
534
|
-
'handling_mode': 'cross_cli'
|
|
535
|
-
},
|
|
536
|
-
'timestamp': datetime.now().isoformat()
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
result = await target_adapter.execute_task(task, execution_context)
|
|
540
|
-
|
|
541
|
-
return self._format_buddy_result("universal_assistant", target_cli, task, result)
|
|
542
|
-
|
|
543
|
-
async def _handle_general_task_with_universal_assistant(self, context: BuddyContext) -> str:
|
|
544
|
-
"""通过通用助手处理通用任务"""
|
|
545
|
-
user_input = context.user_input
|
|
546
|
-
|
|
547
|
-
# 尝试在当前CLI中处理
|
|
548
|
-
try:
|
|
549
|
-
# 这里可以添加CodeBuddy自身的任务处理逻辑
|
|
550
|
-
result = f"CodeBuddy处理任务: {user_input[:100]}..."
|
|
551
|
-
|
|
552
|
-
# 记录处理
|
|
553
|
-
self.processed_requests.append({
|
|
554
|
-
'type': 'buddy_task',
|
|
555
|
-
'buddy_name': 'universal_assistant',
|
|
556
|
-
'task': user_input,
|
|
557
|
-
'result': result,
|
|
558
|
-
'timestamp': datetime.now().isoformat()
|
|
559
|
-
})
|
|
560
|
-
|
|
561
|
-
return result
|
|
562
|
-
|
|
563
|
-
except Exception as e:
|
|
564
|
-
logger.error(f"通用任务处理失败: {e}")
|
|
565
|
-
return f"任务处理失败: {str(e)}"
|
|
566
|
-
|
|
567
|
-
def _preprocess_task_for_cli(self, task: str, target_cli: str) -> str:
|
|
568
|
-
"""为特定CLI预处理任务"""
|
|
569
|
-
# 根据目标CLI特性调整任务内容
|
|
570
|
-
cli_specific_adjustments = {
|
|
571
|
-
'claude': {
|
|
572
|
-
'prefix': 'Please help me ',
|
|
573
|
-
'suffix': ' Provide detailed analysis.'
|
|
574
|
-
},
|
|
575
|
-
'gemini': {
|
|
576
|
-
'prefix': 'Analyze and process: ',
|
|
577
|
-
'suffix': ' Give comprehensive insights.'
|
|
578
|
-
},
|
|
579
|
-
'qwencode': {
|
|
580
|
-
'prefix': 'Optimize and implement: ',
|
|
581
|
-
'suffix': ' Focus on code quality and best practices.'
|
|
582
|
-
},
|
|
583
|
-
'iflow': {
|
|
584
|
-
'prefix': 'Process through workflow: ',
|
|
585
|
-
'suffix': ' Use appropriate stages and tools.'
|
|
586
|
-
},
|
|
587
|
-
'qoder': {
|
|
588
|
-
'prefix': 'Analyze and suggest: ',
|
|
589
|
-
'suffix': ' Provide actionable recommendations.'
|
|
590
|
-
},
|
|
591
|
-
'codex': {
|
|
592
|
-
'prefix': 'Generate and explain: ',
|
|
593
|
-
'suffix': ' Include code examples and documentation.'
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
if target_cli.lower() in cli_specific_adjustments:
|
|
598
|
-
adjustment = cli_specific_adjustments[target_cli.lower()]
|
|
599
|
-
return f"{adjustment['prefix']}{task}{adjustment['suffix']}"
|
|
600
|
-
|
|
601
|
-
return task
|
|
602
|
-
|
|
603
|
-
def _postprocess_result_from_cli(self, result: str, target_cli: str) -> str:
|
|
604
|
-
"""后处理来自特定CLI的结果"""
|
|
605
|
-
# 根据CLI特性调整结果格式
|
|
606
|
-
cli_specific_postprocessing = {
|
|
607
|
-
'claude': {
|
|
608
|
-
'add_source_attribution': True,
|
|
609
|
-
'format_response': True
|
|
610
|
-
},
|
|
611
|
-
'gemini': {
|
|
612
|
-
'add_confidence_scores': True,
|
|
613
|
-
'format_response': True
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
if target_cli.lower() in cli_specific_postprocessing:
|
|
618
|
-
processing = cli_specific_postprocessing[target_cli.lower()]
|
|
619
|
-
|
|
620
|
-
if processing.get('format_response', False):
|
|
621
|
-
# 简单的响应格式化
|
|
622
|
-
if not result.strip().endswith(('.', '!', '?')):
|
|
623
|
-
result = result.rstrip('.') + '.'
|
|
624
|
-
|
|
625
|
-
if processing.get('add_source_attribution', False):
|
|
626
|
-
# 添加来源标注
|
|
627
|
-
result = f"[{target_cli.upper()}]\n{result}"
|
|
628
|
-
|
|
629
|
-
return result
|
|
630
|
-
|
|
631
|
-
def _format_buddy_result(self, buddy_name: str, target_cli: str, task: str, result: str) -> str:
|
|
632
|
-
"""
|
|
633
|
-
格式化Buddy结果
|
|
634
|
-
|
|
635
|
-
Args:
|
|
636
|
-
buddy_name: Buddy名称
|
|
637
|
-
target_cli: 目标CLI工具
|
|
638
|
-
task: 原始任务
|
|
639
|
-
result: 执行结果
|
|
640
|
-
|
|
641
|
-
Returns:
|
|
642
|
-
str: 格式化的结果
|
|
643
|
-
"""
|
|
644
|
-
return f"""## [INSTALL] CodeBuddy Buddy结果
|
|
645
|
-
|
|
646
|
-
**执行Buddy**: {buddy_name}
|
|
647
|
-
**调用工具**: {target_cli.upper()}
|
|
648
|
-
**原始任务**: {task}
|
|
649
|
-
**执行时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
|
650
|
-
|
|
651
|
-
---
|
|
652
|
-
|
|
653
|
-
{result}
|
|
654
|
-
|
|
655
|
-
---
|
|
656
|
-
|
|
657
|
-
*此结果由CodeBuddy CLI Buddy系统提供*"""
|
|
658
|
-
|
|
659
|
-
# ==================== Buddy技能注册方法 ====================
|
|
660
|
-
|
|
661
|
-
async def _register_cross_cli_capabilities(self, buddy_skill: BuddySkill, handler_func: Callable) -> None:
|
|
662
|
-
"""为Buddy注册跨CLI能力"""
|
|
663
|
-
try:
|
|
664
|
-
# 动态添加跨CLI检测方法
|
|
665
|
-
original_can_handle = getattr(handler_func, 'can_handle', None)
|
|
666
|
-
|
|
667
|
-
async def enhanced_can_handle(context: BuddyContext, *args, **kwargs) -> float:
|
|
668
|
-
# 优先检查跨CLI调用
|
|
669
|
-
if context.intent and context.intent.is_cross_cli:
|
|
670
|
-
# 检查Buddy是否支持目标CLI
|
|
671
|
-
if (buddy_skill.cross_cli_enabled and
|
|
672
|
-
context.intent.target_cli.lower() in [cli.lower() for cli in buddy_skill.supported_clis]):
|
|
673
|
-
return 0.9 # 高优先级处理跨CLI调用
|
|
674
|
-
|
|
675
|
-
# 如果不是跨CLI调用,调用原始方法
|
|
676
|
-
if original_can_handle:
|
|
677
|
-
return await original_can_handle(context, *args, **kwargs)
|
|
678
|
-
|
|
679
|
-
return 0.0 # 默认不处理
|
|
680
|
-
|
|
681
|
-
# 包装原始函数的can_handle方法
|
|
682
|
-
setattr(handler_func, 'can_handle', enhanced_can_handle)
|
|
683
|
-
|
|
684
|
-
except Exception as e:
|
|
685
|
-
logger.error(f"注册跨CLI能力失败: {e}")
|
|
686
|
-
|
|
687
|
-
async def _discover_buddy_modules(self) -> None:
|
|
688
|
-
"""发现和加载外部Buddy模块"""
|
|
689
|
-
try:
|
|
690
|
-
if not os.path.exists(self.buddy_modules_dir):
|
|
691
|
-
logger.info("Buddy模块目录不存在,跳过发现")
|
|
692
|
-
return
|
|
693
|
-
|
|
694
|
-
# 扫描Python文件
|
|
695
|
-
for module_file in Path(self.buddy_modules_dir).glob("*.py"):
|
|
696
|
-
if module_file.name.startswith("__"):
|
|
697
|
-
continue
|
|
698
|
-
|
|
699
|
-
try:
|
|
700
|
-
# 动态导入模块
|
|
701
|
-
module_name = f"buddies.{module_file.stem}"
|
|
702
|
-
spec = importlib.util.spec_from_file_location(module_name, module_file)
|
|
703
|
-
module = importlib.util.module_from_spec(spec)
|
|
704
|
-
|
|
705
|
-
# 查找Buddy装饰器的方法
|
|
706
|
-
for attr_name in dir(module):
|
|
707
|
-
attr = getattr(module, attr_name)
|
|
708
|
-
if callable(attr) and hasattr(attr, '__wrapped__'):
|
|
709
|
-
# 这是一个被@buddy装饰的方法
|
|
710
|
-
original_func = attr.__wrapped__
|
|
711
|
-
|
|
712
|
-
# 获取Buddy技能信息
|
|
713
|
-
buddy_name = getattr(original_func, '_buddy_name', attr_name)
|
|
714
|
-
if buddy_name not in self.skills_registry:
|
|
715
|
-
# 创建默认技能信息
|
|
716
|
-
buddy_skill = BuddySkill(
|
|
717
|
-
name=buddy_name,
|
|
718
|
-
description=f"外部Buddy技能: {attr_name}",
|
|
719
|
-
capabilities=[],
|
|
720
|
-
priority=50
|
|
721
|
-
)
|
|
722
|
-
|
|
723
|
-
# 存储原始函数引用
|
|
724
|
-
buddy_skill.metadata['function'] = original_func.__name__
|
|
725
|
-
buddy_skill.metadata['module'] = module_name
|
|
726
|
-
self.skills_registry[buddy_name] = buddy_skill
|
|
727
|
-
|
|
728
|
-
# 注册跨CLI能力
|
|
729
|
-
await self._register_cross_cli_capabilities(buddy_skill, attr)
|
|
730
|
-
|
|
731
|
-
self.buddy_instances[buddy_name] = attr
|
|
732
|
-
self.active_buddies[buddy_name] = {
|
|
733
|
-
'module': module_name,
|
|
734
|
-
'instance': attr,
|
|
735
|
-
'last_used': datetime.now()
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
logger.info(f"发现并加载Buddy模块: {module_file.name}")
|
|
739
|
-
|
|
740
|
-
except Exception as e:
|
|
741
|
-
logger.error(f"加载Buddy模块 {module_file} 失败: {e}")
|
|
742
|
-
|
|
743
|
-
except Exception as e:
|
|
744
|
-
logger.error(f"Buddy模块发现失败: {e}")
|
|
745
|
-
|
|
746
|
-
async def _initialize_cross_cli_system(self) -> None:
|
|
747
|
-
"""初始化跨CLI协作系统"""
|
|
748
|
-
try:
|
|
749
|
-
logger.info("初始化CodeBuddy跨CLI协作系统")
|
|
750
|
-
|
|
751
|
-
# 设置协作会话跟踪
|
|
752
|
-
self.collaboration_sessions = {}
|
|
753
|
-
|
|
754
|
-
logger.info("跨CLI协作系统初始化完成")
|
|
755
|
-
|
|
756
|
-
except Exception as e:
|
|
757
|
-
logger.error(f"初始化跨CLI协作系统失败: {e}")
|
|
758
|
-
|
|
759
|
-
# ==================== Buddy调用处理 ====================
|
|
760
|
-
|
|
761
|
-
async def execute_task(self, task: str, context: Dict[str, Any]) -> str:
|
|
762
|
-
"""
|
|
763
|
-
执行跨CLI任务 - CodeBuddy适配器的具体实现
|
|
764
|
-
|
|
765
|
-
Args:
|
|
766
|
-
task: 要执行的任务描述
|
|
767
|
-
context: 执行上下文信息
|
|
768
|
-
|
|
769
|
-
Returns:
|
|
770
|
-
str: 任务执行结果
|
|
771
|
-
"""
|
|
772
|
-
try:
|
|
773
|
-
session_id = context.get('session_id', f"task-{datetime.now().timestamp()}")
|
|
774
|
-
|
|
775
|
-
# 创建Buddy上下文
|
|
776
|
-
buddy_context = BuddyContext(
|
|
777
|
-
session_id=session_id,
|
|
778
|
-
user_input=task,
|
|
779
|
-
parameters=context.get('parameters', {}),
|
|
780
|
-
metadata=context.get('metadata', {})
|
|
781
|
-
)
|
|
782
|
-
|
|
783
|
-
# 解析意图
|
|
784
|
-
intent = self.parser.parse_intent(task, "codebuddy")
|
|
785
|
-
buddy_context.intent = intent
|
|
786
|
-
|
|
787
|
-
# 选择最合适的Buddy
|
|
788
|
-
selected_buddy = await self._select_best_buddy(buddy_context)
|
|
789
|
-
|
|
790
|
-
if selected_buddy:
|
|
791
|
-
# 调用选中的Buddy
|
|
792
|
-
buddy_instance = self.active_buddies.get(selected_buddy)
|
|
793
|
-
if buddy_instance:
|
|
794
|
-
# 更新使用时间
|
|
795
|
-
self.active_buddies[selected_buddy]['last_used'] = datetime.now()
|
|
796
|
-
|
|
797
|
-
# 设置Buddy名称到上下文
|
|
798
|
-
buddy_context.buddy_name = selected_buddy
|
|
799
|
-
|
|
800
|
-
try:
|
|
801
|
-
# 调用Buddy处理函数
|
|
802
|
-
result = await buddy_instance(buddy_context)
|
|
803
|
-
|
|
804
|
-
# 记录Buddy调用
|
|
805
|
-
self.processed_requests.append({
|
|
806
|
-
'type': 'buddy_call',
|
|
807
|
-
'buddy_name': selected_buddy,
|
|
808
|
-
'task': task,
|
|
809
|
-
'session_id': session_id,
|
|
810
|
-
'success': True,
|
|
811
|
-
'result_length': len(str(result)),
|
|
812
|
-
'timestamp': datetime.now().isoformat()
|
|
813
|
-
})
|
|
814
|
-
|
|
815
|
-
return result
|
|
816
|
-
|
|
817
|
-
except Exception as e:
|
|
818
|
-
logger.error(f"Buddy {selected_buddy} 调用失败: {e}")
|
|
819
|
-
self.record_error()
|
|
820
|
-
|
|
821
|
-
# 记录失败
|
|
822
|
-
self.processed_requests.append({
|
|
823
|
-
'type': 'buddy_call',
|
|
824
|
-
'buddy_name': selected_buddy,
|
|
825
|
-
'task': task,
|
|
826
|
-
'session_id': session_id,
|
|
827
|
-
'success': False,
|
|
828
|
-
'error': str(e),
|
|
829
|
-
'timestamp': datetime.now().isoformat()
|
|
830
|
-
})
|
|
831
|
-
|
|
832
|
-
return f"Buddy {selected_buddy} 调用失败: {str(e)}"
|
|
833
|
-
else:
|
|
834
|
-
# 没有合适的Buddy,使用通用助手
|
|
835
|
-
logger.warning("没有找到合适的Buddy,使用通用助手")
|
|
836
|
-
return await self._fallback_to_general_assistant(buddy_context)
|
|
837
|
-
|
|
838
|
-
except Exception as e:
|
|
839
|
-
logger.error(f"执行任务失败: {task}, 错误: {e}")
|
|
840
|
-
self.record_error()
|
|
841
|
-
return f"任务执行失败: {str(e)}"
|
|
842
|
-
|
|
843
|
-
async def _select_best_buddy(self, context: BuddyContext) -> Optional[str]:
|
|
844
|
-
"""
|
|
845
|
-
选择最合适的Buddy
|
|
846
|
-
|
|
847
|
-
Args:
|
|
848
|
-
context: Buddy上下文
|
|
849
|
-
|
|
850
|
-
Returns:
|
|
851
|
-
Optional[str]: 选择的Buddy名称,如果没有合适的返回None
|
|
852
|
-
"""
|
|
853
|
-
try:
|
|
854
|
-
candidates = []
|
|
855
|
-
|
|
856
|
-
for buddy_name, buddy_instance in self.active_buddies.items():
|
|
857
|
-
try:
|
|
858
|
-
# 检查Buddy是否愿意处理
|
|
859
|
-
can_handle = await buddy_instance.can_handle(context)
|
|
860
|
-
if can_handle > 0:
|
|
861
|
-
buddy_skill = self.skills_registry.get(buddy_name)
|
|
862
|
-
if buddy_skill:
|
|
863
|
-
candidates.append({
|
|
864
|
-
'name': buddy_name,
|
|
865
|
-
'priority': buddy_skill.priority,
|
|
866
|
-
'can_handle': can_handle,
|
|
867
|
-
'buddy_skill': buddy_skill
|
|
868
|
-
})
|
|
869
|
-
except Exception as e:
|
|
870
|
-
logger.warning(f"检查Buddy {buddy_name} 处理能力失败: {e}")
|
|
871
|
-
continue
|
|
872
|
-
|
|
873
|
-
# 如果是跨CLI调用,优先选择支持跨CLI的Buddy
|
|
874
|
-
if context.intent and context.intent.is_cross_cli:
|
|
875
|
-
cross_cli_candidates = [
|
|
876
|
-
c for c in candidates
|
|
877
|
-
if (c['buddy_skill'].cross_cli_enabled and
|
|
878
|
-
context.intent.target_cli.lower() in [cli.lower() for cli in c['buddy_skill'].supported_clis])
|
|
879
|
-
]
|
|
880
|
-
if cross_cli_candidates:
|
|
881
|
-
# 选择优先级最高的跨CLI Buddy
|
|
882
|
-
cross_cli_candidates.sort(key=lambda x: (x['priority'], x['can_handle']), reverse=True)
|
|
883
|
-
return cross_cli_candidates[0]['name']
|
|
884
|
-
|
|
885
|
-
# 按优先级和匹配度排序
|
|
886
|
-
if candidates:
|
|
887
|
-
candidates.sort(key=lambda x: (x['priority'], x['can_handle']), reverse=True)
|
|
888
|
-
return candidates[0]['name']
|
|
889
|
-
|
|
890
|
-
return None
|
|
891
|
-
|
|
892
|
-
except Exception as e:
|
|
893
|
-
logger.error(f"选择Buddy失败: {e}")
|
|
894
|
-
return None
|
|
895
|
-
|
|
896
|
-
async def _fallback_to_general_assistant(self, context: BuddyContext) -> str:
|
|
897
|
-
"""回退到通用助手"""
|
|
898
|
-
try:
|
|
899
|
-
# 使用内置的通用助手Buddy
|
|
900
|
-
universal_buddy = self.active_buddies.get('universal_assistant')
|
|
901
|
-
if universal_buddy:
|
|
902
|
-
context.buddy_name = 'universal_assistant'
|
|
903
|
-
return await universal_buddy(context)
|
|
904
|
-
|
|
905
|
-
return "CodeBuddy: 没有可用的助手来处理这个任务"
|
|
906
|
-
|
|
907
|
-
except Exception as e:
|
|
908
|
-
logger.error(f"通用助手回退失败: {e}")
|
|
909
|
-
return f"任务处理失败: {str(e)}"
|
|
910
|
-
|
|
911
|
-
# ==================== 基础接口实现 ====================
|
|
912
|
-
|
|
913
|
-
def is_available(self) -> bool:
|
|
914
|
-
"""
|
|
915
|
-
检查适配器是否可用
|
|
916
|
-
|
|
917
|
-
Returns:
|
|
918
|
-
bool: 是否可用
|
|
919
|
-
"""
|
|
920
|
-
return (
|
|
921
|
-
len(self.skills_registry) > 0 and
|
|
922
|
-
len(self.active_buddies) > 0 and
|
|
923
|
-
os.path.exists(self.buddy_config_file)
|
|
924
|
-
)
|
|
925
|
-
|
|
926
|
-
async def health_check(self) -> Dict[str, Any]:
|
|
927
|
-
"""
|
|
928
|
-
健康检查
|
|
929
|
-
|
|
930
|
-
Returns:
|
|
931
|
-
Dict[str, Any]: 健康状态
|
|
932
|
-
"""
|
|
933
|
-
base_health = await super().health_check()
|
|
934
|
-
|
|
935
|
-
codebuddy_health = {
|
|
936
|
-
'buddy_config_file': self.buddy_config_file,
|
|
937
|
-
'buddy_modules_dir': self.buddy_modules_dir,
|
|
938
|
-
'config_exists': os.path.exists(self.buddy_config_file),
|
|
939
|
-
'modules_dir_exists': os.path.exists(self.buddy_modules_dir),
|
|
940
|
-
'registered_skills_count': len(self.skills_registry),
|
|
941
|
-
'active_buddies_count': len(self.active_buddies),
|
|
942
|
-
'buddy_calls_count': self.buddy_calls_count,
|
|
943
|
-
'cross_cli_calls_count': self.cross_cli_calls_count,
|
|
944
|
-
'processed_requests_count': len(self.processed_requests),
|
|
945
|
-
'collaboration_sessions_count': len(self.collaboration_sessions),
|
|
946
|
-
'buddy_config': self.buddy_config.copy(),
|
|
947
|
-
'supported_clis': list(set().union(*[
|
|
948
|
-
skill.supported_clis for skill in self.skills_registry.values()
|
|
949
|
-
])),
|
|
950
|
-
'enabled_buddies': list(self.skills_registry.keys())
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
# 检查环境
|
|
954
|
-
try:
|
|
955
|
-
codebuddy_health['codebuddy_environment'] = self._check_codebuddy_environment()
|
|
956
|
-
except Exception as e:
|
|
957
|
-
codebuddy_health['codebuddy_environment_error'] = str(e)
|
|
958
|
-
|
|
959
|
-
# 检查Buddy状态
|
|
960
|
-
try:
|
|
961
|
-
for buddy_name, buddy_instance in self.active_buddies.items():
|
|
962
|
-
buddy_skill = self.skills_registry.get(buddy_name)
|
|
963
|
-
if buddy_skill:
|
|
964
|
-
# 尝试检查Buddy是否响应
|
|
965
|
-
if hasattr(buddy_instance, 'is_healthy'):
|
|
966
|
-
if isinstance(buddy_instance.is_healthy, type(True)):
|
|
967
|
-
healthy = buddy_instance.is_healthy()
|
|
968
|
-
else:
|
|
969
|
-
# 假设为健康
|
|
970
|
-
healthy = True
|
|
971
|
-
else:
|
|
972
|
-
healthy = True
|
|
973
|
-
|
|
974
|
-
codebuddy_health[f'buddy_{buddy_name}_healthy'] = healthy
|
|
975
|
-
|
|
976
|
-
except Exception as e:
|
|
977
|
-
logger.error(f"检查Buddy状态失败: {e}")
|
|
978
|
-
|
|
979
|
-
# 合并基础健康信息
|
|
980
|
-
base_health.update(codebuddy_health)
|
|
981
|
-
return base_health
|
|
982
|
-
|
|
983
|
-
def get_statistics(self) -> Dict[str, Any]:
|
|
984
|
-
"""
|
|
985
|
-
获取适配器统计信息
|
|
986
|
-
|
|
987
|
-
Returns:
|
|
988
|
-
Dict[str, Any]: 统计信息
|
|
989
|
-
"""
|
|
990
|
-
base_stats = super().get_statistics()
|
|
991
|
-
|
|
992
|
-
codebuddy_stats = {
|
|
993
|
-
'registered_skills_count': len(self.skills_registry),
|
|
994
|
-
'active_buddies_count': len(self.active_buddy_instances),
|
|
995
|
-
'buddy_calls_count': self.buddy_calls_count,
|
|
996
|
-
'cross_cli_calls_count': self.cross_cli_calls_count,
|
|
997
|
-
'processed_requests_count': len(self.processed_requests),
|
|
998
|
-
'collaboration_sessions_count': len(self.collaboration_sessions),
|
|
999
|
-
'supported_clis': list(set().union(*[
|
|
1000
|
-
skill.supported_clis for skill in self.skills_registry.values()
|
|
1001
|
-
])),
|
|
1002
|
-
'enabled_buddies': list(self.skills_registry.keys()),
|
|
1003
|
-
'buddy_priorities': {
|
|
1004
|
-
name: skill.priority for name, skill in self.skills_registry.items()
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
# 计算Buddy使用统计
|
|
1009
|
-
buddy_usage = {}
|
|
1010
|
-
for buddy_name, buddy_info in self.active_buddies.items():
|
|
1011
|
-
buddy_skill = self.skills_registry.get(buddy_name)
|
|
1012
|
-
if buddy_skill:
|
|
1013
|
-
buddy_usage[buddy_name] = {
|
|
1014
|
-
'calls': buddy_info.get('call_count', 0),
|
|
1015
|
-
'last_used': buddy_info.get('last_used'),
|
|
1016
|
-
'priority': buddy_skill.priority
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
codebuddy_stats['buddy_usage'] = buddy_usage
|
|
1020
|
-
base_stats.update(codebuddy_stats)
|
|
1021
|
-
return base_stats
|
|
1022
|
-
|
|
1023
|
-
async def cleanup(self) -> bool:
|
|
1024
|
-
"""
|
|
1025
|
-
清理适配器资源
|
|
1026
|
-
|
|
1027
|
-
Returns:
|
|
1028
|
-
bool: 清理是否成功
|
|
1029
|
-
"""
|
|
1030
|
-
try:
|
|
1031
|
-
# 清理统计信息
|
|
1032
|
-
self.processed_requests.clear()
|
|
1033
|
-
self.collaboration_sessions.clear()
|
|
1034
|
-
self.buddy_calls_count = 0
|
|
1035
|
-
self.cross_cli_calls_count = 0
|
|
1036
|
-
|
|
1037
|
-
# 清理Buddy实例
|
|
1038
|
-
self.buddy_instances.clear()
|
|
1039
|
-
self.active_buddies.clear()
|
|
1040
|
-
|
|
1041
|
-
logger.info("CodeBuddy Buddy适配器清理完成")
|
|
1042
|
-
return True
|
|
1043
|
-
|
|
1044
|
-
except Exception as e:
|
|
1045
|
-
logger.error(f"清理CodeBuddy Buddy适配器失败: {e}")
|
|
1046
|
-
return False
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
# 创建全局适配器实例
|
|
1050
|
-
_global_adapter: Optional[CodeBuddyBuddyAdapter] = None
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
def get_codebuddy_buddy_adapter() -> CodeBuddyBuddyAdapter:
|
|
1054
|
-
"""
|
|
1055
|
-
获取CodeBuddy Buddy适配器实例
|
|
1056
|
-
|
|
1057
|
-
Returns:
|
|
1058
|
-
CodeBuddyBuddyAdapter: 适配器实例
|
|
1059
|
-
"""
|
|
1060
|
-
global _global_adapter
|
|
1061
|
-
if _global_adapter is None:
|
|
1062
|
-
_global_adapter = CodeBuddyBuddyAdapter()
|
|
1063
|
-
# 异步初始化需要在调用时进行
|
|
1064
|
-
return _global_adapter
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
# 便捷函数
|
|
1068
|
-
async def initialize_codebuddy_buddy_adapter() -> bool:
|
|
1069
|
-
"""
|
|
1070
|
-
初始化CodeBuddy Buddy适配器
|
|
1071
|
-
|
|
1072
|
-
Returns:
|
|
1073
|
-
bool: 初始化是否成功
|
|
1074
|
-
"""
|
|
1075
|
-
adapter = get_codebuddy_buddy_adapter()
|
|
1076
|
-
return await adapter.initialize()
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
def is_codebuddy_buddy_adapter_available() -> bool:
|
|
1080
|
-
"""
|
|
1081
|
-
检查CodeBuddy Buddy适配器是否可用
|
|
1082
|
-
|
|
1083
|
-
Returns:
|
|
1084
|
-
bool: 是否可用
|
|
1085
|
-
"""
|
|
1086
|
-
adapter = get_codebuddy_buddy_adapter()
|
|
1087
|
-
return adapter.is_available()
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
# 便捷装饰器
|
|
1091
|
-
def register_buddy(name: str = "", description: str = "", **kwargs):
|
|
1092
|
-
"""
|
|
1093
|
-
便捷的Buddy注册装饰器
|
|
1094
|
-
|
|
1095
|
-
Args:
|
|
1096
|
-
name: Buddy名称
|
|
1097
|
-
description: Buddy描述
|
|
1098
|
-
**kwargs: 其他参数传递给@buddy装饰器
|
|
1099
|
-
"""
|
|
1100
|
-
adapter = get_codebuddy_buddy_adapter()
|
|
1101
|
-
return adapter.buddy(name, description, **kwargs)
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
if __name__ == "__main__":
|
|
1105
|
-
import asyncio
|
|
1106
|
-
|
|
1107
|
-
async def main():
|
|
1108
|
-
"""主函数 - 用于测试和独立运行"""
|
|
1109
|
-
adapter = CodeBuddyBuddyAdapter()
|
|
1110
|
-
|
|
1111
|
-
# 初始化
|
|
1112
|
-
if await adapter.initialize():
|
|
1113
|
-
print("CodeBuddy Buddy适配器初始化成功")
|
|
1114
|
-
|
|
1115
|
-
# 显示统计信息
|
|
1116
|
-
stats = adapter.get_statistics()
|
|
1117
|
-
print("\nBuddy系统统计:")
|
|
1118
|
-
print(f"注册技能数: {stats['registered_skills_count']}")
|
|
1119
|
-
print(f"活动Buddy数: {stats['active_buddies_count']}")
|
|
1120
|
-
print(f"支持的CLI工具: {', '.join(stats['supported_clis'])}")
|
|
1121
|
-
|
|
1122
|
-
else:
|
|
1123
|
-
print("CodeBuddy Buddy适配器初始化失败")
|
|
1124
|
-
|
|
1125
|
-
asyncio.run(main())
|