stigmergy 1.0.57

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.
Files changed (94) hide show
  1. package/LICENSE +19 -0
  2. package/README.de.md +301 -0
  3. package/README.en.md +301 -0
  4. package/README.es.md +301 -0
  5. package/README.fr.md +301 -0
  6. package/README.ja.md +301 -0
  7. package/README.ko.md +301 -0
  8. package/README.md +301 -0
  9. package/README.ru.md +301 -0
  10. package/README.zh.md +301 -0
  11. package/package.json +82 -0
  12. package/src/adapters/claude/__init__.py +13 -0
  13. package/src/adapters/claude/claude_skills_integration.py +609 -0
  14. package/src/adapters/claude/hook_adapter.py +663 -0
  15. package/src/adapters/claude/install_claude_integration.py +265 -0
  16. package/src/adapters/claude/skills_hook_adapter.py +841 -0
  17. package/src/adapters/claude/standalone_claude_adapter.py +384 -0
  18. package/src/adapters/cline/__init__.py +20 -0
  19. package/src/adapters/cline/config.py +108 -0
  20. package/src/adapters/cline/install_cline_integration.py +617 -0
  21. package/src/adapters/cline/mcp_server.py +713 -0
  22. package/src/adapters/cline/standalone_cline_adapter.py +459 -0
  23. package/src/adapters/codebuddy/__init__.py +13 -0
  24. package/src/adapters/codebuddy/buddy_adapter.py +1125 -0
  25. package/src/adapters/codebuddy/install_codebuddy_integration.py +279 -0
  26. package/src/adapters/codebuddy/skills_hook_adapter.py +672 -0
  27. package/src/adapters/codebuddy/skills_integration.py +395 -0
  28. package/src/adapters/codebuddy/standalone_codebuddy_adapter.py +403 -0
  29. package/src/adapters/codex/__init__.py +11 -0
  30. package/src/adapters/codex/base.py +46 -0
  31. package/src/adapters/codex/install_codex_integration.py +311 -0
  32. package/src/adapters/codex/mcp_server.py +493 -0
  33. package/src/adapters/codex/natural_language_parser.py +82 -0
  34. package/src/adapters/codex/slash_command_adapter.py +326 -0
  35. package/src/adapters/codex/standalone_codex_adapter.py +362 -0
  36. package/src/adapters/copilot/__init__.py +13 -0
  37. package/src/adapters/copilot/install_copilot_integration.py +564 -0
  38. package/src/adapters/copilot/mcp_adapter.py +772 -0
  39. package/src/adapters/copilot/mcp_server.py +168 -0
  40. package/src/adapters/copilot/standalone_copilot_adapter.py +114 -0
  41. package/src/adapters/gemini/__init__.py +13 -0
  42. package/src/adapters/gemini/extension_adapter.py +690 -0
  43. package/src/adapters/gemini/install_gemini_integration.py +257 -0
  44. package/src/adapters/gemini/standalone_gemini_adapter.py +366 -0
  45. package/src/adapters/iflow/__init__.py +7 -0
  46. package/src/adapters/iflow/hook_adapter.py +1038 -0
  47. package/src/adapters/iflow/hook_installer.py +536 -0
  48. package/src/adapters/iflow/install_iflow_integration.py +271 -0
  49. package/src/adapters/iflow/official_hook_adapter.py +1272 -0
  50. package/src/adapters/iflow/standalone_iflow_adapter.py +48 -0
  51. package/src/adapters/iflow/workflow_adapter.py +793 -0
  52. package/src/adapters/qoder/hook_installer.py +732 -0
  53. package/src/adapters/qoder/install_qoder_integration.py +265 -0
  54. package/src/adapters/qoder/notification_hook_adapter.py +863 -0
  55. package/src/adapters/qoder/standalone_qoder_adapter.py +48 -0
  56. package/src/adapters/qwen/__init__.py +17 -0
  57. package/src/adapters/qwencode/__init__.py +13 -0
  58. package/src/adapters/qwencode/inheritance_adapter.py +818 -0
  59. package/src/adapters/qwencode/install_qwencode_integration.py +276 -0
  60. package/src/adapters/qwencode/standalone_qwencode_adapter.py +399 -0
  61. package/src/atomic_collaboration_handler.py +461 -0
  62. package/src/cli_collaboration_agent.py +697 -0
  63. package/src/collaboration/hooks.py +315 -0
  64. package/src/core/__init__.py +21 -0
  65. package/src/core/ai_environment_scanner.py +331 -0
  66. package/src/core/base_adapter.py +220 -0
  67. package/src/core/cli_hook_integration.py +406 -0
  68. package/src/core/cross_cli_executor.py +713 -0
  69. package/src/core/cross_cli_mapping.py +1163 -0
  70. package/src/core/cross_platform_encoding.py +365 -0
  71. package/src/core/cross_platform_safe_cli.py +894 -0
  72. package/src/core/direct_cli_executor.py +805 -0
  73. package/src/core/direct_cli_hook_system.py +958 -0
  74. package/src/core/enhanced_init_processor.py +427 -0
  75. package/src/core/graceful_cli_executor.py +912 -0
  76. package/src/core/md_enhancer.py +342 -0
  77. package/src/core/md_generator.py +619 -0
  78. package/src/core/models.py +218 -0
  79. package/src/core/parser.py +108 -0
  80. package/src/core/real_cli_hook_system.py +852 -0
  81. package/src/core/real_cross_cli_system.py +925 -0
  82. package/src/core/verified_cross_cli_system.py +961 -0
  83. package/src/deploy.js +737 -0
  84. package/src/enhanced_deploy.js +303 -0
  85. package/src/enhanced_universal_cli_setup.py +930 -0
  86. package/src/kimi_wrapper.py +104 -0
  87. package/src/main.js +1309 -0
  88. package/src/shell_integration.py +398 -0
  89. package/src/simple-main.js +315 -0
  90. package/src/smart_router_creator.py +323 -0
  91. package/src/universal_cli_setup.py +1289 -0
  92. package/src/utils/__init__.py +12 -0
  93. package/src/utils/cli_detector.py +445 -0
  94. package/src/utils/file_utils.py +246 -0
@@ -0,0 +1,772 @@
1
+ """
2
+ CopilotCLI MCP适配器 - 基于Model Context Protocol (MCP)的原生集成
3
+
4
+ 这是TDD驱动的实现,基于test_copilot_adapter.py中的测试用例
5
+ 完全符合项目约束条件:
6
+ - 使用Copilot CLI官方MCP服务器机制
7
+ - 不改变CLI启动和使用方式
8
+ - 不依赖包装器
9
+ - 完全无损扩展
10
+ """
11
+
12
+ import os
13
+ import json
14
+ import logging
15
+ import asyncio
16
+ from typing import Dict, Any, Optional, List
17
+ from datetime import datetime
18
+ from pathlib import Path
19
+
20
+ from ...core.base_adapter import BaseCrossCLIAdapter, IntentResult
21
+ from ...core.parser import NaturalLanguageParser
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ class CopilotMCPContext:
27
+ """Copilot CLI MCP上下文模拟类"""
28
+
29
+ def __init__(self, prompt: str = "", metadata: Optional[Dict] = None):
30
+ self.prompt = prompt
31
+ self.metadata = metadata or {}
32
+ self.session_id = self.metadata.get('session_id', 'unknown')
33
+ self.user_id = self.metadata.get('user_id', 'unknown')
34
+ self.timestamp = datetime.now()
35
+ self.tool_permissions = self.metadata.get('tool_permissions', {})
36
+
37
+
38
+ class CopilotMCPAdapter(BaseCrossCLIAdapter):
39
+ """
40
+ Copilot CLI MCP适配器
41
+
42
+ 通过Copilot CLI官方MCP服务器系统实现跨CLI调用功能。
43
+ 这是完全基于原生MCP机制的无损扩展实现。
44
+
45
+ MCP集成机制:
46
+ - 通过自定义MCP服务器注册到Copilot CLI
47
+ - 使用MCP工具调用接口处理跨CLI请求
48
+ - 利用Copilot的权限管理系统确保安全
49
+ - 支持并行工具执行和异步任务委托
50
+ """
51
+
52
+ def __init__(self, cli_name: str = "copilot"):
53
+ """
54
+ 初始化Copilot MCP适配器
55
+
56
+ Args:
57
+ cli_name: CLI工具名称,默认为"copilot"
58
+ """
59
+ super().__init__(cli_name)
60
+
61
+ # MCP相关配置
62
+ self.copilot_config_dir = os.path.expanduser("~/.copilot")
63
+ self.mcp_config_file = os.path.join(self.copilot_config_dir, "mcp-config.json")
64
+ self.custom_agents_dir = os.path.join(self.copilot_config_dir, "agents")
65
+ self.mcp_server_registered = False
66
+
67
+ # 跨CLI MCP服务器配置
68
+ self.cross_cli_mcp_server = {
69
+ "name": "cross-cli-adapter",
70
+ "description": "Cross-CLI integration adapter for universal AI tool collaboration",
71
+ "version": "1.0.0",
72
+ "command": "python",
73
+ "args": [
74
+ "-m", "src.adapters.copilot.mcp_server"
75
+ ],
76
+ "env": {
77
+ "CROSS_CLI_ADAPTER": "enabled",
78
+ "LOG_LEVEL": "INFO"
79
+ }
80
+ }
81
+
82
+ # 统计信息
83
+ self.mcp_calls_count = 0
84
+ self.cross_cli_calls_count = 0
85
+ self.processed_requests: List[Dict[str, Any]] = []
86
+ self.agent_executions: List[Dict[str, Any]] = []
87
+
88
+ # 解析器
89
+ self.parser = NaturalLanguageParser()
90
+
91
+ # 跨CLI适配器工厂
92
+ from ...core.base_adapter import get_cross_cli_adapter
93
+ self.get_adapter = get_cross_cli_adapter
94
+
95
+ async def initialize(self) -> bool:
96
+ """
97
+ 初始化适配器
98
+
99
+ Returns:
100
+ bool: 初始化是否成功
101
+ """
102
+ try:
103
+ # 1. 检查Copilot CLI环境
104
+ if not self._check_copilot_environment():
105
+ logger.error("Copilot CLI环境检查失败")
106
+ return False
107
+
108
+ # 2. 注册MCP服务器
109
+ if not await self._register_mcp_server():
110
+ logger.error("MCP服务器注册失败")
111
+ return False
112
+
113
+ # 3. 创建自定义代理
114
+ await self._create_custom_agents()
115
+
116
+ # 4. 确保配置目录存在
117
+ await self._ensure_config_directory()
118
+
119
+ self.mcp_server_registered = True
120
+ logger.info("Copilot MCP适配器初始化成功")
121
+ return True
122
+
123
+ except Exception as e:
124
+ logger.error(f"初始化Copilot MCP适配器失败: {e}")
125
+ self.record_error()
126
+ return False
127
+
128
+ async def _register_mcp_server(self) -> bool:
129
+ """
130
+ 注册MCP服务器到Copilot CLI
131
+
132
+ Returns:
133
+ bool: 注册是否成功
134
+ """
135
+ try:
136
+ # 读取现有MCP配置
137
+ mcp_config = self._load_mcp_config()
138
+
139
+ # 添加我们的跨CLI MCP服务器
140
+ mcp_servers = mcp_config.get('mcpServers', {})
141
+
142
+ # 检查是否已存在
143
+ if self.cross_cli_mcp_server['name'] not in mcp_servers:
144
+ mcp_servers[self.cross_cli_mcp_server['name']] = {
145
+ "command": self.cross_cli_mcp_server['command'],
146
+ "args": self.cross_cli_mcp_server['args'],
147
+ "env": self.cross_cli_mcp_server['env']
148
+ }
149
+
150
+ mcp_config['mcpServers'] = mcp_servers
151
+
152
+ # 保存配置
153
+ await self._save_mcp_config(mcp_config)
154
+ logger.info(f"注册MCP服务器: {self.cross_cli_mcp_server['name']}")
155
+ else:
156
+ logger.info("MCP服务器已存在,跳过注册")
157
+
158
+ return True
159
+
160
+ except Exception as e:
161
+ logger.error(f"注册MCP服务器失败: {e}")
162
+ return False
163
+
164
+ def _load_mcp_config(self) -> Dict[str, Any]:
165
+ """
166
+ 加载MCP配置
167
+
168
+ Returns:
169
+ Dict[str, Any]: MCP配置
170
+ """
171
+ if os.path.exists(self.mcp_config_file):
172
+ try:
173
+ with open(self.mcp_config_file, 'r', encoding='utf-8') as f:
174
+ return json.load(f)
175
+ except (json.JSONDecodeError, IOError) as e:
176
+ logger.warning(f"加载MCP配置失败,使用默认配置: {e}")
177
+
178
+ # 返回默认配置
179
+ return {
180
+ "mcpServers": {}
181
+ }
182
+
183
+ async def _save_mcp_config(self, config: Dict[str, Any]) -> bool:
184
+ """
185
+ 保存MCP配置
186
+
187
+ Args:
188
+ config: MCP配置
189
+
190
+ Returns:
191
+ bool: 保存是否成功
192
+ """
193
+ try:
194
+ os.makedirs(os.path.dirname(self.mcp_config_file), exist_ok=True)
195
+
196
+ with open(self.mcp_config_file, 'w', encoding='utf-8') as f:
197
+ json.dump(config, f, indent=2, ensure_ascii=False)
198
+
199
+ logger.info(f"保存MCP配置到: {self.mcp_config_file}")
200
+ return True
201
+
202
+ except Exception as e:
203
+ logger.error(f"保存MCP配置失败: {e}")
204
+ return False
205
+
206
+ async def _create_custom_agents(self) -> bool:
207
+ """
208
+ 创建自定义代理用于跨CLI调用
209
+
210
+ Returns:
211
+ bool: 创建是否成功
212
+ """
213
+ try:
214
+ os.makedirs(self.custom_agents_dir, exist_ok=True)
215
+
216
+ # 创建跨CLI调用代理
217
+ cross_cli_agent = {
218
+ "name": "cross-cli-caller",
219
+ "description": "Agent for handling cross-CLI tool calls and collaboration",
220
+ "version": "1.0.0",
221
+ "instructions": """You are a cross-CLI integration agent that helps users collaborate between different AI CLI tools.
222
+
223
+ When you detect a request to use another CLI tool (like Claude, Gemini, QwenCode, etc.):
224
+ 1. Parse the target CLI and task from the user's request
225
+ 2. Execute the task using the appropriate CLI tool
226
+ 3. Return the results in a clear, structured format
227
+
228
+ Support both Chinese and English collaboration patterns:
229
+ - "请用{CLI}帮我{task}" -> Use {CLI} to help with {task}
230
+ - "use {CLI} to {task}" -> Execute {task} with {CLI}
231
+
232
+ Always maintain the original intent and context of the user's request.""",
233
+ "tools": [
234
+ "cross_cli_execute",
235
+ "get_available_clis",
236
+ "check_cli_status"
237
+ ],
238
+ "permissions": {
239
+ "allowShellExecution": True,
240
+ "allowNetworkAccess": True,
241
+ "allowedPaths": ["*"]
242
+ }
243
+ }
244
+
245
+ agent_file = os.path.join(self.custom_agents_dir, "cross-cli-caller.json")
246
+ with open(agent_file, 'w', encoding='utf-8') as f:
247
+ json.dump(cross_cli_agent, f, indent=2, ensure_ascii=False)
248
+
249
+ logger.info(f"创建自定义代理: {cross_cli_agent['name']}")
250
+ return True
251
+
252
+ except Exception as e:
253
+ logger.error(f"创建自定义代理失败: {e}")
254
+ return False
255
+
256
+ async def _ensure_config_directory(self) -> bool:
257
+ """
258
+ 确保配置目录存在
259
+
260
+ Returns:
261
+ bool: 创建是否成功
262
+ """
263
+ try:
264
+ directories = [
265
+ self.copilot_config_dir,
266
+ self.custom_agents_dir,
267
+ os.path.join(self.copilot_config_dir, "sessions"),
268
+ os.path.join(self.copilot_config_dir, "logs")
269
+ ]
270
+
271
+ for directory in directories:
272
+ os.makedirs(directory, exist_ok=True)
273
+
274
+ logger.info(f"配置目录已准备: {self.copilot_config_dir}")
275
+ return True
276
+
277
+ except Exception as e:
278
+ logger.error(f"创建配置目录失败: {e}")
279
+ return False
280
+
281
+ def _check_copilot_environment(self) -> bool:
282
+ """
283
+ 检查Copilot CLI环境
284
+
285
+ Returns:
286
+ bool: 环境是否可用
287
+ """
288
+ try:
289
+ # 检查配置目录
290
+ if not os.path.exists(self.copilot_config_dir):
291
+ logger.warning(f"Copilot配置目录不存在: {self.copilot_config_dir}")
292
+ return False
293
+
294
+ # 检查是否有copilot命令(简化检查)
295
+ # 在实际环境中,这里应该检查copilot命令是否可用
296
+ return True
297
+
298
+ except Exception as e:
299
+ logger.error(f"检查Copilot环境失败: {e}")
300
+ return False
301
+
302
+ async def on_mcp_tool_call(self, tool_name: str, arguments: Dict[str, Any], context: CopilotMCPContext) -> Optional[str]:
303
+ """
304
+ 处理MCP工具调用
305
+
306
+ 这是核心Hook,用于检测和执行跨CLI调用。
307
+
308
+ Args:
309
+ tool_name: 工具名称
310
+ arguments: 工具参数
311
+ context: MCP上下文
312
+
313
+ Returns:
314
+ Optional[str]: 处理结果
315
+ """
316
+ try:
317
+ self.mcp_calls_count += 1
318
+
319
+ # 记录请求
320
+ request_record = {
321
+ 'tool_name': tool_name,
322
+ 'arguments': arguments,
323
+ 'context': context.__dict__,
324
+ 'timestamp': datetime.now().isoformat()
325
+ }
326
+ self.processed_requests.append(request_record)
327
+
328
+ if tool_name == "cross_cli_execute":
329
+ return await self._handle_cross_cli_execute(arguments, context)
330
+ elif tool_name == "get_available_clis":
331
+ return await self._handle_get_available_clis(context)
332
+ elif tool_name == "check_cli_status":
333
+ return await self._handle_check_cli_status(arguments, context)
334
+
335
+ return None
336
+
337
+ except Exception as e:
338
+ logger.error(f"MCP工具调用处理失败: {tool_name}, {e}")
339
+ self.record_error()
340
+ return None
341
+
342
+ async def _handle_cross_cli_execute(self, arguments: Dict[str, Any], context: CopilotMCPContext) -> str:
343
+ """
344
+ 处理跨CLI执行请求
345
+
346
+ Args:
347
+ arguments: 执行参数,包含target_cli和task
348
+ context: MCP上下文
349
+
350
+ Returns:
351
+ str: 执行结果
352
+ """
353
+ target_cli = arguments.get('target_cli')
354
+ task = arguments.get('task')
355
+
356
+ if not target_cli or not task:
357
+ return self._format_error_result(
358
+ target_cli or "unknown",
359
+ task or "unknown",
360
+ "缺少必要参数:target_cli和task"
361
+ )
362
+
363
+ # 避免自我调用
364
+ if target_cli.lower() == self.cli_name:
365
+ return self._format_error_result(
366
+ target_cli,
367
+ task,
368
+ "不能自我调用,请使用其他CLI工具"
369
+ )
370
+
371
+ try:
372
+ logger.info(f"执行跨CLI调用: {target_cli} -> {task}")
373
+
374
+ # 获取目标CLI适配器
375
+ target_adapter = self.get_adapter(target_cli)
376
+
377
+ if not target_adapter:
378
+ logger.warning(f"目标CLI适配器不可用: {target_cli}")
379
+ return self._format_error_result(
380
+ target_cli,
381
+ task,
382
+ f"目标CLI工具 '{target_cli}' 不可用或未安装"
383
+ )
384
+
385
+ if not target_adapter.is_available():
386
+ logger.warning(f"目标CLI工具不可用: {target_cli}")
387
+ return self._format_error_result(
388
+ target_cli,
389
+ task,
390
+ f"目标CLI工具 '{target_cli}' 当前不可用"
391
+ )
392
+
393
+ # 构建执行上下文
394
+ execution_context = {
395
+ 'source_cli': self.cli_name,
396
+ 'target_cli': target_cli,
397
+ 'original_task': task,
398
+ 'mcp_context': context.__dict__,
399
+ 'timestamp': datetime.now().isoformat()
400
+ }
401
+
402
+ # 执行任务
403
+ result = await target_adapter.execute_task(task, execution_context)
404
+
405
+ # 记录成功的跨CLI调用
406
+ self.cross_cli_calls_count += 1
407
+ self.processed_requests.append({
408
+ 'type': 'cross_cli_execution',
409
+ 'target_cli': target_cli,
410
+ 'task': task,
411
+ 'success': True,
412
+ 'result_length': len(result),
413
+ 'timestamp': datetime.now().isoformat()
414
+ })
415
+
416
+ # 格式化结果
417
+ formatted_result = self._format_success_result(target_cli, task, result)
418
+
419
+ logger.info(f"跨CLI调用成功: {target_cli}")
420
+ return formatted_result
421
+
422
+ except Exception as e:
423
+ logger.error(f"跨CLI调用失败: {target_cli}, {e}")
424
+ self.record_error()
425
+
426
+ self.processed_requests.append({
427
+ 'type': 'cross_cli_execution',
428
+ 'target_cli': target_cli,
429
+ 'task': task,
430
+ 'success': False,
431
+ 'error': str(e),
432
+ 'timestamp': datetime.now().isoformat()
433
+ })
434
+
435
+ return self._format_error_result(target_cli, task, str(e))
436
+
437
+ async def _handle_get_available_clis(self, context: CopilotMCPContext) -> str:
438
+ """
439
+ 处理获取可用CLI列表请求
440
+
441
+ Args:
442
+ context: MCP上下文
443
+
444
+ Returns:
445
+ str: 可用CLI列表
446
+ """
447
+ try:
448
+ from ...core.base_adapter import get_all_adapters
449
+ adapters = get_all_adapters()
450
+
451
+ available_clis = []
452
+ for name, adapter in adapters.items():
453
+ if adapter.is_available():
454
+ available_clis.append({
455
+ 'name': name,
456
+ 'version': getattr(adapter, 'version', 'unknown'),
457
+ 'type': adapter.__class__.__name__
458
+ })
459
+
460
+ result = {
461
+ 'available_clis': available_clis,
462
+ 'total_count': len(available_clis),
463
+ 'timestamp': datetime.now().isoformat()
464
+ }
465
+
466
+ return json.dumps(result, indent=2, ensure_ascii=False)
467
+
468
+ except Exception as e:
469
+ logger.error(f"获取可用CLI列表失败: {e}")
470
+ return json.dumps({'error': str(e)}, ensure_ascii=False)
471
+
472
+ async def _handle_check_cli_status(self, arguments: Dict[str, Any], context: CopilotMCPContext) -> str:
473
+ """
474
+ 处理检查CLI状态请求
475
+
476
+ Args:
477
+ arguments: 包含cli_name的参数
478
+ context: MCP上下文
479
+
480
+ Returns:
481
+ str: CLI状态信息
482
+ """
483
+ cli_name = arguments.get('cli_name')
484
+
485
+ if not cli_name:
486
+ return json.dumps({'error': '缺少cli_name参数'}, ensure_ascii=False)
487
+
488
+ try:
489
+ target_adapter = self.get_adapter(cli_name)
490
+
491
+ if not target_adapter:
492
+ return json.dumps({
493
+ 'cli_name': cli_name,
494
+ 'available': False,
495
+ 'reason': '适配器未找到'
496
+ }, ensure_ascii=False)
497
+
498
+ health = await target_adapter.health_check()
499
+ stats = target_adapter.get_statistics()
500
+
501
+ result = {
502
+ 'cli_name': cli_name,
503
+ 'available': target_adapter.is_available(),
504
+ 'health': health,
505
+ 'statistics': stats,
506
+ 'timestamp': datetime.now().isoformat()
507
+ }
508
+
509
+ return json.dumps(result, indent=2, ensure_ascii=False)
510
+
511
+ except Exception as e:
512
+ logger.error(f"检查CLI状态失败: {cli_name}, {e}")
513
+ return json.dumps({
514
+ 'cli_name': cli_name,
515
+ 'available': False,
516
+ 'error': str(e)
517
+ }, ensure_ascii=False)
518
+
519
+ def _format_success_result(
520
+ self,
521
+ target_cli: str,
522
+ task: str,
523
+ result: str
524
+ ) -> str:
525
+ """
526
+ 格式化成功的跨CLI调用结果
527
+
528
+ Args:
529
+ target_cli: 目标CLI工具
530
+ task: 原始任务
531
+ result: 执行结果
532
+
533
+ Returns:
534
+ str: 格式化的结果
535
+ """
536
+ return f"""## 🔗 跨CLI调用结果
537
+
538
+ **源工具**: Copilot CLI
539
+ **目标工具**: {target_cli.upper()}
540
+ **原始任务**: {task}
541
+ **执行时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
542
+
543
+ ---
544
+
545
+ {result}
546
+
547
+ ---
548
+
549
+ *此结果由跨CLI集成系统通过Copilot CLI MCP提供*"""
550
+
551
+ def _format_error_result(
552
+ self,
553
+ target_cli: str,
554
+ task: str,
555
+ error_message: str
556
+ ) -> str:
557
+ """
558
+ 格式化错误的跨CLI调用结果
559
+
560
+ Args:
561
+ target_cli: 目标CLI工具
562
+ task: 原始任务
563
+ error_message: 错误信息
564
+
565
+ Returns:
566
+ str: 格式化的错误结果
567
+ """
568
+ return f"""## ❌ 跨CLI调用失败
569
+
570
+ **源工具**: Copilot CLI
571
+ **目标工具**: {target_cli.upper()}
572
+ **原始任务**: {task}
573
+ **错误信息**: {error_message}
574
+ **失败时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
575
+
576
+ 请检查目标CLI工具是否正确安装和配置。
577
+
578
+ ---
579
+
580
+ *此错误由跨CLI集成系统报告*"""
581
+
582
+ def is_available(self) -> bool:
583
+ """
584
+ 检查适配器是否可用
585
+
586
+ Returns:
587
+ bool: 是否可用
588
+ """
589
+ return self.mcp_server_registered and self._check_copilot_environment()
590
+
591
+ async def health_check(self) -> Dict[str, Any]:
592
+ """
593
+ 健康检查
594
+
595
+ Returns:
596
+ Dict[str, Any]: 健康状态
597
+ """
598
+ base_health = await super().health_check()
599
+
600
+ copilot_health = {
601
+ 'mcp_server_registered': self.mcp_server_registered,
602
+ 'mcp_calls_count': self.mcp_calls_count,
603
+ 'cross_cli_calls_count': self.cross_cli_calls_count,
604
+ 'processed_requests_count': len(self.processed_requests),
605
+ 'agent_executions_count': len(self.agent_executions),
606
+ 'mcp_config_file': self.mcp_config_file,
607
+ 'mcp_config_exists': os.path.exists(self.mcp_config_file),
608
+ 'custom_agents_dir': self.custom_agents_dir,
609
+ 'custom_agents_dir_exists': os.path.exists(self.custom_agents_dir)
610
+ }
611
+
612
+ # 检查环境
613
+ try:
614
+ copilot_health['copilot_environment'] = self._check_copilot_environment()
615
+ except Exception as e:
616
+ copilot_health['copilot_environment_error'] = str(e)
617
+
618
+ # 合并基础健康信息
619
+ base_health.update(copilot_health)
620
+ return base_health
621
+
622
+ def get_statistics(self) -> Dict[str, Any]:
623
+ """
624
+ 获取适配器统计信息
625
+
626
+ Returns:
627
+ Dict[str, Any]: 统计信息
628
+ """
629
+ base_stats = super().get_statistics()
630
+
631
+ copilot_stats = {
632
+ 'mcp_server_registered': self.mcp_server_registered,
633
+ 'mcp_calls_count': self.mcp_calls_count,
634
+ 'cross_cli_calls_count': self.cross_cli_calls_count,
635
+ 'agent_executions_count': len(self.agent_executions),
636
+ 'success_rate': self._calculate_success_rate(),
637
+ 'last_activity': self._get_last_activity(),
638
+ 'mcp_server_name': self.cross_cli_mcp_server['name']
639
+ }
640
+
641
+ base_stats.update(copilot_stats)
642
+ return base_stats
643
+
644
+ def _calculate_success_rate(self) -> float:
645
+ """
646
+ 计算成功率
647
+
648
+ Returns:
649
+ float: 成功率 (0.0 - 1.0)
650
+ """
651
+ total_cross_cli = self.cross_cli_calls_count
652
+
653
+ if total_cross_cli == 0:
654
+ return 1.0
655
+
656
+ successful_calls = sum(
657
+ 1 for req in self.processed_requests
658
+ if req.get('type') == 'cross_cli_execution' and req.get('success')
659
+ )
660
+
661
+ return successful_calls / total_cross_cli
662
+
663
+ def _get_last_activity(self) -> Optional[str]:
664
+ """
665
+ 获取最后活动时间
666
+
667
+ Returns:
668
+ Optional[str]: 最后活动时间戳
669
+ """
670
+ if not self.processed_requests:
671
+ return None
672
+
673
+ return max(req['timestamp'] for req in self.processed_requests)
674
+
675
+ async def execute_task(self, task: str, context: Dict[str, Any]) -> str:
676
+ """
677
+ 执行跨CLI任务 - Copilot适配器的具体实现
678
+
679
+ Args:
680
+ task: 要执行的任务描述
681
+ context: 执行上下文信息
682
+
683
+ Returns:
684
+ str: 任务执行结果
685
+ """
686
+ try:
687
+ # 创建MCP上下文
688
+ mcp_context = CopilotMCPContext(
689
+ prompt=task,
690
+ metadata=context.get('metadata', {})
691
+ )
692
+
693
+ # 检查是否为跨CLI调用
694
+ intent = self.parser.parse_intent(task, "copilot")
695
+ if intent.is_cross_cli and intent.target_cli != self.cli_name:
696
+ # 执行跨CLI调用
697
+ result = await self._handle_cross_cli_execute(
698
+ {'target_cli': intent.target_cli, 'task': intent.task},
699
+ mcp_context
700
+ )
701
+ return result
702
+ else:
703
+ # 本地Copilot任务处理
704
+ return f"Copilot MCP适配器本地处理: {task}"
705
+
706
+ except Exception as e:
707
+ logger.error(f"执行任务失败: {task}, 错误: {e}")
708
+ self.record_error()
709
+ return f"任务执行失败: {str(e)}"
710
+
711
+ async def cleanup(self) -> bool:
712
+ """
713
+ 清理适配器资源
714
+
715
+ Returns:
716
+ bool: 清理是否成功
717
+ """
718
+ try:
719
+ # 清理统计信息
720
+ self.processed_requests.clear()
721
+ self.agent_executions.clear()
722
+
723
+ # 注销MCP服务器(如果需要)
724
+ # 这里可以实现MCP服务器注销逻辑
725
+
726
+ logger.info("Copilot MCP适配器清理完成")
727
+ return True
728
+
729
+ except Exception as e:
730
+ logger.error(f"清理Copilot MCP适配器失败: {e}")
731
+ return False
732
+
733
+
734
+ # 创建全局适配器实例
735
+ _global_adapter: Optional[CopilotMCPAdapter] = None
736
+
737
+
738
+ def get_copilot_mcp_adapter() -> CopilotMCPAdapter:
739
+ """
740
+ 获取Copilot MCP适配器实例
741
+
742
+ Returns:
743
+ CopilotMCPAdapter: 适配器实例
744
+ """
745
+ global _global_adapter
746
+ if _global_adapter is None:
747
+ _global_adapter = CopilotMCPAdapter()
748
+ # 异步初始化需要在调用时进行
749
+ return _global_adapter
750
+
751
+
752
+ # 便捷函数
753
+ async def initialize_copilot_adapter() -> bool:
754
+ """
755
+ 初始化Copilot MCP适配器
756
+
757
+ Returns:
758
+ bool: 初始化是否成功
759
+ """
760
+ adapter = get_copilot_mcp_adapter()
761
+ return await adapter.initialize()
762
+
763
+
764
+ def is_copilot_adapter_available() -> bool:
765
+ """
766
+ 检查Copilot MCP适配器是否可用
767
+
768
+ Returns:
769
+ bool: 是否可用
770
+ """
771
+ adapter = get_copilot_mcp_adapter()
772
+ return adapter.is_available()