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.
- package/LICENSE +19 -0
- package/README.de.md +301 -0
- package/README.en.md +301 -0
- package/README.es.md +301 -0
- package/README.fr.md +301 -0
- package/README.ja.md +301 -0
- package/README.ko.md +301 -0
- package/README.md +301 -0
- package/README.ru.md +301 -0
- package/README.zh.md +301 -0
- package/package.json +82 -0
- package/src/adapters/claude/__init__.py +13 -0
- package/src/adapters/claude/claude_skills_integration.py +609 -0
- package/src/adapters/claude/hook_adapter.py +663 -0
- package/src/adapters/claude/install_claude_integration.py +265 -0
- package/src/adapters/claude/skills_hook_adapter.py +841 -0
- package/src/adapters/claude/standalone_claude_adapter.py +384 -0
- package/src/adapters/cline/__init__.py +20 -0
- package/src/adapters/cline/config.py +108 -0
- package/src/adapters/cline/install_cline_integration.py +617 -0
- package/src/adapters/cline/mcp_server.py +713 -0
- package/src/adapters/cline/standalone_cline_adapter.py +459 -0
- package/src/adapters/codebuddy/__init__.py +13 -0
- package/src/adapters/codebuddy/buddy_adapter.py +1125 -0
- package/src/adapters/codebuddy/install_codebuddy_integration.py +279 -0
- package/src/adapters/codebuddy/skills_hook_adapter.py +672 -0
- package/src/adapters/codebuddy/skills_integration.py +395 -0
- package/src/adapters/codebuddy/standalone_codebuddy_adapter.py +403 -0
- package/src/adapters/codex/__init__.py +11 -0
- package/src/adapters/codex/base.py +46 -0
- package/src/adapters/codex/install_codex_integration.py +311 -0
- package/src/adapters/codex/mcp_server.py +493 -0
- package/src/adapters/codex/natural_language_parser.py +82 -0
- package/src/adapters/codex/slash_command_adapter.py +326 -0
- package/src/adapters/codex/standalone_codex_adapter.py +362 -0
- package/src/adapters/copilot/__init__.py +13 -0
- package/src/adapters/copilot/install_copilot_integration.py +564 -0
- package/src/adapters/copilot/mcp_adapter.py +772 -0
- package/src/adapters/copilot/mcp_server.py +168 -0
- package/src/adapters/copilot/standalone_copilot_adapter.py +114 -0
- package/src/adapters/gemini/__init__.py +13 -0
- package/src/adapters/gemini/extension_adapter.py +690 -0
- package/src/adapters/gemini/install_gemini_integration.py +257 -0
- package/src/adapters/gemini/standalone_gemini_adapter.py +366 -0
- package/src/adapters/iflow/__init__.py +7 -0
- package/src/adapters/iflow/hook_adapter.py +1038 -0
- package/src/adapters/iflow/hook_installer.py +536 -0
- package/src/adapters/iflow/install_iflow_integration.py +271 -0
- package/src/adapters/iflow/official_hook_adapter.py +1272 -0
- package/src/adapters/iflow/standalone_iflow_adapter.py +48 -0
- package/src/adapters/iflow/workflow_adapter.py +793 -0
- package/src/adapters/qoder/hook_installer.py +732 -0
- package/src/adapters/qoder/install_qoder_integration.py +265 -0
- package/src/adapters/qoder/notification_hook_adapter.py +863 -0
- package/src/adapters/qoder/standalone_qoder_adapter.py +48 -0
- package/src/adapters/qwen/__init__.py +17 -0
- package/src/adapters/qwencode/__init__.py +13 -0
- package/src/adapters/qwencode/inheritance_adapter.py +818 -0
- package/src/adapters/qwencode/install_qwencode_integration.py +276 -0
- package/src/adapters/qwencode/standalone_qwencode_adapter.py +399 -0
- package/src/atomic_collaboration_handler.py +461 -0
- package/src/cli_collaboration_agent.py +697 -0
- package/src/collaboration/hooks.py +315 -0
- package/src/core/__init__.py +21 -0
- package/src/core/ai_environment_scanner.py +331 -0
- package/src/core/base_adapter.py +220 -0
- package/src/core/cli_hook_integration.py +406 -0
- package/src/core/cross_cli_executor.py +713 -0
- package/src/core/cross_cli_mapping.py +1163 -0
- package/src/core/cross_platform_encoding.py +365 -0
- package/src/core/cross_platform_safe_cli.py +894 -0
- package/src/core/direct_cli_executor.py +805 -0
- package/src/core/direct_cli_hook_system.py +958 -0
- package/src/core/enhanced_init_processor.py +427 -0
- package/src/core/graceful_cli_executor.py +912 -0
- package/src/core/md_enhancer.py +342 -0
- package/src/core/md_generator.py +619 -0
- package/src/core/models.py +218 -0
- package/src/core/parser.py +108 -0
- package/src/core/real_cli_hook_system.py +852 -0
- package/src/core/real_cross_cli_system.py +925 -0
- package/src/core/verified_cross_cli_system.py +961 -0
- package/src/deploy.js +737 -0
- package/src/enhanced_deploy.js +303 -0
- package/src/enhanced_universal_cli_setup.py +930 -0
- package/src/kimi_wrapper.py +104 -0
- package/src/main.js +1309 -0
- package/src/shell_integration.py +398 -0
- package/src/simple-main.js +315 -0
- package/src/smart_router_creator.py +323 -0
- package/src/universal_cli_setup.py +1289 -0
- package/src/utils/__init__.py +12 -0
- package/src/utils/cli_detector.py +445 -0
- package/src/utils/file_utils.py +246 -0
|
@@ -0,0 +1,1289 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
通用CLI智能路由自动化部署脚本
|
|
5
|
+
可配置、跨平台、自适应不同环境和AI工具
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
import json
|
|
11
|
+
import platform
|
|
12
|
+
import subprocess
|
|
13
|
+
import shutil
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class UniversalCLISetup:
|
|
19
|
+
"""通用CLI设置管理器"""
|
|
20
|
+
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.config_file = "cli_config.json"
|
|
23
|
+
self.setup_dir = Path.cwd()
|
|
24
|
+
self.system = platform.system().lower()
|
|
25
|
+
self.config = self.load_or_create_config()
|
|
26
|
+
|
|
27
|
+
def load_or_create_config(self):
|
|
28
|
+
"""加载或创建配置"""
|
|
29
|
+
default_config = {
|
|
30
|
+
"version": "1.0.0",
|
|
31
|
+
"system": self.system,
|
|
32
|
+
"tools": {
|
|
33
|
+
"claude": {
|
|
34
|
+
"command": {
|
|
35
|
+
"windows": "claude.cmd",
|
|
36
|
+
"linux": "claude",
|
|
37
|
+
"darwin": "claude"
|
|
38
|
+
},
|
|
39
|
+
"description": "Anthropic Claude",
|
|
40
|
+
"keywords": ["claude", "anthropic"],
|
|
41
|
+
"priority": 1,
|
|
42
|
+
"wrapper": False,
|
|
43
|
+
"check_command": ["--version"]
|
|
44
|
+
},
|
|
45
|
+
"gemini": {
|
|
46
|
+
"command": {
|
|
47
|
+
"windows": "gemini.cmd",
|
|
48
|
+
"linux": "gemini",
|
|
49
|
+
"darwin": "gemini"
|
|
50
|
+
},
|
|
51
|
+
"description": "Google Gemini AI",
|
|
52
|
+
"keywords": ["gemini", "google", "谷歌"],
|
|
53
|
+
"priority": 2,
|
|
54
|
+
"wrapper": False,
|
|
55
|
+
"check_command": ["--version"]
|
|
56
|
+
},
|
|
57
|
+
"kimi": {
|
|
58
|
+
"command": {
|
|
59
|
+
"windows": "kimi_wrapper",
|
|
60
|
+
"linux": "kimi_wrapper",
|
|
61
|
+
"darwin": "kimi_wrapper"
|
|
62
|
+
},
|
|
63
|
+
"description": "月之暗面Kimi",
|
|
64
|
+
"keywords": ["kimi", "月之暗面", "moonshot"],
|
|
65
|
+
"priority": 3,
|
|
66
|
+
"wrapper": True,
|
|
67
|
+
"wrapper_script": "kimi_wrapper.py",
|
|
68
|
+
"check_command": ["--version"]
|
|
69
|
+
},
|
|
70
|
+
"qwen": {
|
|
71
|
+
"command": {
|
|
72
|
+
"windows": "qwen.cmd",
|
|
73
|
+
"linux": "qwen",
|
|
74
|
+
"darwin": "qwen"
|
|
75
|
+
},
|
|
76
|
+
"description": "阿里通义千问",
|
|
77
|
+
"keywords": ["qwen", "通义", "阿里"],
|
|
78
|
+
"priority": 4,
|
|
79
|
+
"wrapper": False,
|
|
80
|
+
"check_command": ["--version"]
|
|
81
|
+
},
|
|
82
|
+
"ollama": {
|
|
83
|
+
"command": {
|
|
84
|
+
"windows": "ollama",
|
|
85
|
+
"linux": "ollama",
|
|
86
|
+
"darwin": "ollama"
|
|
87
|
+
},
|
|
88
|
+
"description": "Ollama本地模型",
|
|
89
|
+
"keywords": ["ollama", "本地", "离线"],
|
|
90
|
+
"priority": 5,
|
|
91
|
+
"wrapper": False,
|
|
92
|
+
"check_command": ["--version"]
|
|
93
|
+
},
|
|
94
|
+
"codebuddy": {
|
|
95
|
+
"command": {
|
|
96
|
+
"windows": "codebuddy",
|
|
97
|
+
"linux": "codebuddy",
|
|
98
|
+
"darwin": "codebuddy"
|
|
99
|
+
},
|
|
100
|
+
"description": "CodeBuddy代码助手",
|
|
101
|
+
"keywords": ["codebuddy", "代码助手", "编程"],
|
|
102
|
+
"priority": 6,
|
|
103
|
+
"wrapper": False,
|
|
104
|
+
"check_command": ["--version"]
|
|
105
|
+
},
|
|
106
|
+
"qodercli": {
|
|
107
|
+
"command": {
|
|
108
|
+
"windows": "qodercli",
|
|
109
|
+
"linux": "qodercli",
|
|
110
|
+
"darwin": "qodercli"
|
|
111
|
+
},
|
|
112
|
+
"description": "QoderCLI代码生成",
|
|
113
|
+
"keywords": ["qodercli", "代码生成", "编程"],
|
|
114
|
+
"priority": 7,
|
|
115
|
+
"wrapper": False,
|
|
116
|
+
"check_command": ["--version"]
|
|
117
|
+
},
|
|
118
|
+
"iflow": {
|
|
119
|
+
"command": {
|
|
120
|
+
"windows": "iflow.cmd",
|
|
121
|
+
"linux": "iflow",
|
|
122
|
+
"darwin": "iflow"
|
|
123
|
+
},
|
|
124
|
+
"description": "iFlow智能助手",
|
|
125
|
+
"keywords": ["iflow", "智能", "助手", "心流"],
|
|
126
|
+
"priority": 8,
|
|
127
|
+
"wrapper": False,
|
|
128
|
+
"check_command": ["--version"]
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"route_keywords": ["用", "帮我", "请", "智能", "ai", "写", "生成", "解释", "分析", "翻译", "代码", "文章"],
|
|
132
|
+
"default_tool": "claude",
|
|
133
|
+
"fallback_strategy": "first_available",
|
|
134
|
+
"wrapper_scripts": {
|
|
135
|
+
"kimi_wrapper": "kimi_wrapper.py"
|
|
136
|
+
},
|
|
137
|
+
"output_formats": ["cmd", "powershell", "bash", "python"],
|
|
138
|
+
"install_global": False
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if os.path.exists(self.config_file):
|
|
142
|
+
try:
|
|
143
|
+
with open(self.config_file, 'r', encoding='utf-8') as f:
|
|
144
|
+
user_config = json.load(f)
|
|
145
|
+
# 合并配置,用户配置优先
|
|
146
|
+
self._merge_config(default_config, user_config)
|
|
147
|
+
return default_config
|
|
148
|
+
except Exception as e:
|
|
149
|
+
print(f"⚠️ 配置文件加载失败,使用默认配置: {e}")
|
|
150
|
+
|
|
151
|
+
# 保存默认配置
|
|
152
|
+
self.save_config(default_config)
|
|
153
|
+
return default_config
|
|
154
|
+
|
|
155
|
+
def _merge_config(self, default, user):
|
|
156
|
+
"""递归合并配置"""
|
|
157
|
+
for key, value in user.items():
|
|
158
|
+
if key in default:
|
|
159
|
+
if isinstance(default[key], dict) and isinstance(value, dict):
|
|
160
|
+
self._merge_config(default[key], value)
|
|
161
|
+
else:
|
|
162
|
+
default[key] = value
|
|
163
|
+
else:
|
|
164
|
+
default[key] = value
|
|
165
|
+
|
|
166
|
+
def save_config(self, config):
|
|
167
|
+
"""保存配置"""
|
|
168
|
+
with open(self.config_file, 'w', encoding='utf-8') as f:
|
|
169
|
+
json.dump(config, f, ensure_ascii=False, indent=2)
|
|
170
|
+
|
|
171
|
+
def discover_available_tools(self):
|
|
172
|
+
"""发现可用工具"""
|
|
173
|
+
available = {}
|
|
174
|
+
|
|
175
|
+
for tool_name, tool_config in self.config["tools"].items():
|
|
176
|
+
command = tool_config["command"][self.system]
|
|
177
|
+
|
|
178
|
+
# 特殊处理包装器
|
|
179
|
+
if tool_config.get("wrapper") and tool_config.get("wrapper_script"):
|
|
180
|
+
wrapper_path = self.setup_dir / tool_config["wrapper_script"]
|
|
181
|
+
if wrapper_path.exists():
|
|
182
|
+
available[tool_name] = True
|
|
183
|
+
continue
|
|
184
|
+
|
|
185
|
+
# 检查命令可用性
|
|
186
|
+
try:
|
|
187
|
+
if self.system == "windows":
|
|
188
|
+
result = subprocess.run(["where", command.split()[0]],
|
|
189
|
+
capture_output=True, text=True, timeout=5)
|
|
190
|
+
available[tool_name] = result.returncode == 0
|
|
191
|
+
else:
|
|
192
|
+
result = subprocess.run(["which", command],
|
|
193
|
+
capture_output=True, text=True, timeout=5)
|
|
194
|
+
available[tool_name] = result.returncode == 0
|
|
195
|
+
except:
|
|
196
|
+
available[tool_name] = False
|
|
197
|
+
|
|
198
|
+
return available
|
|
199
|
+
|
|
200
|
+
def generate_smart_router(self, cli_name, output_format="cmd"):
|
|
201
|
+
"""生成智能路由器"""
|
|
202
|
+
available_tools = self.discover_available_tools()
|
|
203
|
+
|
|
204
|
+
if output_format == "cmd":
|
|
205
|
+
return self._generate_cmd_router(cli_name, available_tools)
|
|
206
|
+
elif output_format == "powershell":
|
|
207
|
+
return self._generate_powershell_router(cli_name, available_tools)
|
|
208
|
+
elif output_format == "bash":
|
|
209
|
+
return self._generate_bash_router(cli_name, available_tools)
|
|
210
|
+
elif output_format == "python":
|
|
211
|
+
return self._generate_python_router(cli_name, available_tools)
|
|
212
|
+
else:
|
|
213
|
+
raise ValueError(f"不支持的输出格式: {output_format}")
|
|
214
|
+
|
|
215
|
+
def _generate_cmd_router(self, cli_name, available_tools):
|
|
216
|
+
"""生成CMD路由器 - 支持协作日志记录"""
|
|
217
|
+
router_content = f'''@echo off
|
|
218
|
+
setlocal enabledelayedexpansion
|
|
219
|
+
|
|
220
|
+
:: 智能{cli_name}路由器 - 支持多智能体协作 - 自动生成
|
|
221
|
+
:: 系统: {self.system}
|
|
222
|
+
:: 可用工具: {list(available_tools.keys())}
|
|
223
|
+
:: 支持基于项目规范文档的间接协同(Stigmergy)
|
|
224
|
+
|
|
225
|
+
set "USER_INPUT=%*"
|
|
226
|
+
|
|
227
|
+
if "%USER_INPUT%"=="" (
|
|
228
|
+
echo 🎯 智能{cli_name}路由器 - 支持多智能体协作
|
|
229
|
+
echo 💡 原始功能: {cli_name} [参数]
|
|
230
|
+
echo 🤖 智能路由示例:
|
|
231
|
+
'''
|
|
232
|
+
|
|
233
|
+
# 添加可用工具的路由逻辑
|
|
234
|
+
for tool_name in sorted(available_tools.keys(), key=lambda x: self.config["tools"][x]["priority"]):
|
|
235
|
+
if available_tools[tool_name]:
|
|
236
|
+
keywords = self.config["tools"][tool_name]["keywords"]
|
|
237
|
+
keyword_pattern = "|".join(keywords)
|
|
238
|
+
router_content += f''' echo 智能{cli_name}.bat 用{keyword_pattern}
|
|
239
|
+
'''
|
|
240
|
+
|
|
241
|
+
router_content += f'''
|
|
242
|
+
exit /b
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
:: 检查项目规范文档是否存在
|
|
246
|
+
if not exist "PROJECT_SPEC.json" (
|
|
247
|
+
echo.>{{"project_name": "{cli_name} Collaboration Project", "created_at": "%date% %time%", "status": "active", "tasks": {{}}, "collaboration_history": [], "current_state": {{"active_task": null, "completed_tasks": [], "pending_tasks": []}}}} > PROJECT_SPEC.json
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
:: 记录协作日志的函数(通过临时文件)
|
|
251
|
+
:log_collaboration
|
|
252
|
+
set "AGENT_NAME=%~1"
|
|
253
|
+
set "MESSAGE=%~2"
|
|
254
|
+
set "TIMESTAMP=%date% %time%"
|
|
255
|
+
echo {{ "timestamp": "!TIMESTAMP!", "agent": "!AGENT_NAME!", "message": "!MESSAGE!" }} >> COLLAB_LOG_TEMP.txt
|
|
256
|
+
goto :eof
|
|
257
|
+
|
|
258
|
+
:: 智能路由检测
|
|
259
|
+
echo %USER_INPUT% | findstr /i "{" ".join(self.config["route_keywords"])}" >nul
|
|
260
|
+
if %errorlevel% neq 0 (
|
|
261
|
+
:: 不需要路由,执行原始命令
|
|
262
|
+
{cli_name} %USER_INPUT%
|
|
263
|
+
exit /b
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
:: 检查是否需要协作
|
|
267
|
+
set "NEEDS_COLLAB=false"
|
|
268
|
+
echo %USER_INPUT% | findstr /i "协作 一起 共同 多个 团队 分工 complete project full solution entire task" >nul
|
|
269
|
+
if !errorlevel! equ 0 set "NEEDS_COLLAB=true"
|
|
270
|
+
|
|
271
|
+
if "!NEEDS_COLLAB!" == "true" (
|
|
272
|
+
:: 创建协作任务记录
|
|
273
|
+
echo. > COLLAB_TASK_TEMP.txt
|
|
274
|
+
echo {{ "id": "collab_!random!!random!", "type": "collaboration", "description": "%USER_INPUT%", "status": "pending", "created_at": "%date% %time%" }} >> COLLAB_TASK_TEMP.txt
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
'''
|
|
278
|
+
|
|
279
|
+
# 生成路由逻辑
|
|
280
|
+
for tool_name in sorted(available_tools.keys(), key=lambda x: self.config["tools"][x]["priority"]):
|
|
281
|
+
if available_tools[tool_name]:
|
|
282
|
+
keywords = self.config["tools"][tool_name]["keywords"]
|
|
283
|
+
command = self.config["tools"][tool_name]["command"][self.system]
|
|
284
|
+
|
|
285
|
+
router_content += f'''
|
|
286
|
+
echo %USER_INPUT% | findstr /i "{" ".join(keywords)}" >nul
|
|
287
|
+
if !errorlevel! equ 0 (
|
|
288
|
+
echo 🚀 智能路由到: {self.config["tools"][tool_name]["description"]}
|
|
289
|
+
set "CLEAN_INPUT=!USER_INPUT!"
|
|
290
|
+
'''
|
|
291
|
+
|
|
292
|
+
for keyword in keywords:
|
|
293
|
+
router_content += f''' set "CLEAN_INPUT=!CLEAN_INPUT:{keyword}=!"
|
|
294
|
+
'''
|
|
295
|
+
|
|
296
|
+
router_content += f''' set "CLEAN_INPUT=!CLEAN_INPUT:用=!"
|
|
297
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:帮我=!"
|
|
298
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:请=!"
|
|
299
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:写=!"
|
|
300
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:生成=!"
|
|
301
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:解释=!"
|
|
302
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:分析=!"
|
|
303
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:翻译=!"
|
|
304
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:代码=!"
|
|
305
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:文章=!"
|
|
306
|
+
|
|
307
|
+
:: 记录任务执行到项目规范
|
|
308
|
+
call :log_collaboration "{tool_name}" "开始执行任务: !CLEAN_INPUT!"
|
|
309
|
+
|
|
310
|
+
'''
|
|
311
|
+
|
|
312
|
+
if self.config["tools"][tool_name].get("wrapper"):
|
|
313
|
+
wrapper_script = self.config["tools"][tool_name]["wrapper_script"]
|
|
314
|
+
router_content += f''' python {wrapper_script} "!CLEAN_INPUT!"
|
|
315
|
+
set "TASK_RESULT=!ERRORLEVEL!"
|
|
316
|
+
'''
|
|
317
|
+
else:
|
|
318
|
+
router_content += f''' {command} "!CLEAN_INPUT!"
|
|
319
|
+
set "TASK_RESULT=!ERRORLEVEL!"
|
|
320
|
+
'''
|
|
321
|
+
|
|
322
|
+
router_content += f''' :: 更新任务状态到项目规范
|
|
323
|
+
if !TASK_RESULT! equ 0 (
|
|
324
|
+
call :log_collaboration "{tool_name}" "任务成功完成: !CLEAN_INPUT!"
|
|
325
|
+
) else (
|
|
326
|
+
call :log_collaboration "{tool_name}" "任务执行失败: !CLEAN_INPUT!"
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
exit /b
|
|
330
|
+
)
|
|
331
|
+
'''
|
|
332
|
+
|
|
333
|
+
# 默认路由
|
|
334
|
+
default_tool = self.config["default_tool"]
|
|
335
|
+
if default_tool in available_tools:
|
|
336
|
+
command = self.config["tools"][default_tool]["command"][self.system]
|
|
337
|
+
router_content += f'''
|
|
338
|
+
:: 默认路由到{self.config["tools"][default_tool]["description"]}
|
|
339
|
+
set "CLEAN_INPUT=!USER_INPUT!"
|
|
340
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:用=!"
|
|
341
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:帮我=!"
|
|
342
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:请=!"
|
|
343
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:写=!"
|
|
344
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:生成=!"
|
|
345
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:解释=!"
|
|
346
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:分析=!"
|
|
347
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:翻译=!"
|
|
348
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:代码=!"
|
|
349
|
+
set "CLEAN_INPUT=!CLEAN_INPUT:文章=!"
|
|
350
|
+
|
|
351
|
+
:: 记录任务执行到项目规范
|
|
352
|
+
call :log_collaboration "{default_tool}" "开始执行默认任务: !CLEAN_INPUT!"
|
|
353
|
+
|
|
354
|
+
{command} "!CLEAN_INPUT!"
|
|
355
|
+
set "TASK_RESULT=!ERRORLEVEL!"
|
|
356
|
+
|
|
357
|
+
:: 更新任务状态到项目规范
|
|
358
|
+
if !TASK_RESULT! equ 0 (
|
|
359
|
+
call :log_collaboration "{default_tool}" "默认任务成功完成: !CLEAN_INPUT!"
|
|
360
|
+
) else (
|
|
361
|
+
call :log_collaboration "{default_tool}" "默认任务执行失败: !CLEAN_INPUT!"
|
|
362
|
+
)
|
|
363
|
+
'''
|
|
364
|
+
else:
|
|
365
|
+
router_content += f'''
|
|
366
|
+
:: 执行原始{cli_name}
|
|
367
|
+
{cli_name} %USER_INPUT%
|
|
368
|
+
'''
|
|
369
|
+
|
|
370
|
+
router_content += '''
|
|
371
|
+
|
|
372
|
+
exit /b
|
|
373
|
+
|
|
374
|
+
:: 子程序:记录协作日志
|
|
375
|
+
:log_collaboration
|
|
376
|
+
set "AGENT_NAME=%~1"
|
|
377
|
+
set "MESSAGE=%~2"
|
|
378
|
+
set "TIMESTAMP=%date% %time%"
|
|
379
|
+
|
|
380
|
+
:: 读取现有协作历史
|
|
381
|
+
set "HISTORY_FILE=PROJECT_SPEC.json"
|
|
382
|
+
if exist temp_history.txt del temp_history.txt
|
|
383
|
+
for /f "tokens=*" %%a in ('type "%HISTORY_FILE%" 2^>nul ^| findstr /v /c:"\"collaboration_history\":" ^| findstr /v /c:"\[.*\]"') do (
|
|
384
|
+
echo %%a >> temp_history.txt
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
:: 添加新的协作日志
|
|
388
|
+
>> "%HISTORY_FILE%" (
|
|
389
|
+
echo,
|
|
390
|
+
echo "collaboration_history": [
|
|
391
|
+
echo {{ "timestamp": "!TIMESTAMP!", "agent": "!AGENT_NAME!", "message": "!MESSAGE!" }},
|
|
392
|
+
type temp_history.txt
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
goto :eof
|
|
396
|
+
'''
|
|
397
|
+
|
|
398
|
+
return router_content
|
|
399
|
+
|
|
400
|
+
def _generate_powershell_router(self, cli_name, available_tools):
|
|
401
|
+
"""生成PowerShell路由器"""
|
|
402
|
+
router_content = f'''# 智能{cli_name}路由器 - PowerShell版本
|
|
403
|
+
# 系统: {self.system}
|
|
404
|
+
# 可用工具: {list(available_tools.keys())}
|
|
405
|
+
|
|
406
|
+
param(
|
|
407
|
+
[string]$UserInput = ""
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
function SmartRoute {{
|
|
411
|
+
param([string]$Input)
|
|
412
|
+
|
|
413
|
+
$routeKeywords = @({', '.join([f'"{kw}"' for kw in self.config["route_keywords"]])})
|
|
414
|
+
|
|
415
|
+
foreach ($keyword in $routeKeywords) {{
|
|
416
|
+
if ($Input -like "*$keyword*") {{
|
|
417
|
+
return $true
|
|
418
|
+
}}
|
|
419
|
+
}}
|
|
420
|
+
|
|
421
|
+
return $false
|
|
422
|
+
}}
|
|
423
|
+
|
|
424
|
+
function Route-ToTool {{
|
|
425
|
+
param([string]$Input)
|
|
426
|
+
'''
|
|
427
|
+
|
|
428
|
+
# 生成路由逻辑
|
|
429
|
+
for tool_name in sorted(available_tools.keys(), key=lambda x: self.config["tools"][x]["priority"]):
|
|
430
|
+
if available_tools[tool_name]:
|
|
431
|
+
keywords = self.config["tools"][tool_name]["keywords"]
|
|
432
|
+
command = self.config["tools"][tool_name]["command"][self.system]
|
|
433
|
+
|
|
434
|
+
router_content += f'''
|
|
435
|
+
if ($Input -like "*{keywords[0]}*") {{
|
|
436
|
+
Write-Host "🚀 智能路由到: {self.config['tools'][tool_name]['description']}"
|
|
437
|
+
$cleanInput = $Input
|
|
438
|
+
'''
|
|
439
|
+
|
|
440
|
+
for keyword in keywords:
|
|
441
|
+
router_content += f''' $cleanInput = $cleanInput -replace "{keyword}", ""'''
|
|
442
|
+
|
|
443
|
+
router_content += ''' $cleanInput = $cleanInput -replace "^用", "" -replace "^帮我", "" -replace "^请", "" -replace "^写", "" -replace "^生成", "" -replace "^解释", "" -replace "^分析", "" -replace "^翻译", "" -replace "^代码", "" -replace "^文章", ""
|
|
444
|
+
'''
|
|
445
|
+
|
|
446
|
+
if self.config["tools"][tool_name].get("wrapper"):
|
|
447
|
+
wrapper_script = self.config["tools"][tool_name]["wrapper_script"]
|
|
448
|
+
router_content += f''' python {wrapper_script} $cleanInput.Trim()'''
|
|
449
|
+
else:
|
|
450
|
+
router_content += f''' {command} $cleanInput.Trim()'''
|
|
451
|
+
|
|
452
|
+
router_content += ''' return
|
|
453
|
+
}
|
|
454
|
+
'''
|
|
455
|
+
|
|
456
|
+
# 默认路由
|
|
457
|
+
default_tool = self.config["default_tool"]
|
|
458
|
+
if default_tool in available_tools:
|
|
459
|
+
command = self.config["tools"][default_tool]["command"][self.system]
|
|
460
|
+
router_content += f'''
|
|
461
|
+
# 默认路由到{self.config["tools"][default_tool]["description"]}
|
|
462
|
+
$cleanInput = $Input
|
|
463
|
+
$cleanInput = $cleanInput -replace "^用", "" -replace "^帮我", "" -replace "^请", "" -replace "^写", "" -replace "^生成", "" -replace "^解释", "" -replace "^分析", "" -replace "^翻译", "" -replace "^代码", "" -replace "^文章", ""
|
|
464
|
+
{command} $cleanInput.Trim()
|
|
465
|
+
'''
|
|
466
|
+
else:
|
|
467
|
+
router_content += f''' # 执行原始{cli_name}
|
|
468
|
+
{cli_name} $Input'''
|
|
469
|
+
|
|
470
|
+
router_content += '''
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
# 主逻辑
|
|
474
|
+
if (-not $UserInput) {{
|
|
475
|
+
Write-Host "🎯 智能{cli_name}路由器 - PowerShell版本"
|
|
476
|
+
Write-Host "💡 原始功能: .\smart_{cli_name}.ps1 '参数'"
|
|
477
|
+
Write-Host "🤖 智能路由示例:"
|
|
478
|
+
'''
|
|
479
|
+
|
|
480
|
+
# 添加可用工具示例
|
|
481
|
+
for tool_name in sorted(available_tools.keys(), key=lambda x: self.config["tools"][x]["priority"]):
|
|
482
|
+
if available_tools[tool_name]:
|
|
483
|
+
keywords = self.config["tools"][tool_name]["keywords"]
|
|
484
|
+
router_content += f''' Write-Host " .\smart_{cli_name}.ps1 '用{keywords[0]}写代码'"
|
|
485
|
+
'''
|
|
486
|
+
|
|
487
|
+
router_content += ''' exit
|
|
488
|
+
}}
|
|
489
|
+
|
|
490
|
+
if (SmartRoute $UserInput) {{
|
|
491
|
+
Route-ToTool $UserInput
|
|
492
|
+
}} else {{
|
|
493
|
+
{cli_name} $UserInput
|
|
494
|
+
}}
|
|
495
|
+
'''
|
|
496
|
+
|
|
497
|
+
return router_content
|
|
498
|
+
|
|
499
|
+
def _generate_bash_router(self, cli_name, available_tools):
|
|
500
|
+
"""生成Bash路由器 - 支持协作日志记录"""
|
|
501
|
+
router_content = f'''#!/bin/bash
|
|
502
|
+
# 智能{cli_name}路由器 - 支持多智能体协作 - Bash版本
|
|
503
|
+
# 系统: {self.system}
|
|
504
|
+
# 可用工具: {list(available_tools.keys())}
|
|
505
|
+
# 支持基于项目规范文档的间接协同(Stigmergy)
|
|
506
|
+
|
|
507
|
+
USER_INPUT="$*"
|
|
508
|
+
|
|
509
|
+
# 检查并创建项目规范文档
|
|
510
|
+
if [ ! -f "PROJECT_SPEC.json" ]; then
|
|
511
|
+
CURRENT_TIME=$(date -Iseconds)
|
|
512
|
+
cat > PROJECT_SPEC.json << EOF
|
|
513
|
+
{{
|
|
514
|
+
"project_name": "{cli_name} Collaboration Project",
|
|
515
|
+
"created_at": "$CURRENT_TIME",
|
|
516
|
+
"status": "active",
|
|
517
|
+
"tasks": {{}},
|
|
518
|
+
"collaboration_history": [],
|
|
519
|
+
"current_state": {{
|
|
520
|
+
"active_task": null,
|
|
521
|
+
"completed_tasks": [],
|
|
522
|
+
"pending_tasks": []
|
|
523
|
+
}}
|
|
524
|
+
}}
|
|
525
|
+
EOF
|
|
526
|
+
fi
|
|
527
|
+
|
|
528
|
+
# 记录协作日志函数
|
|
529
|
+
log_collaboration() {{
|
|
530
|
+
local agent_name="$1"
|
|
531
|
+
local message="$2"
|
|
532
|
+
local timestamp=$(date -Iseconds)
|
|
533
|
+
|
|
534
|
+
# 读取当前规范文档
|
|
535
|
+
local spec_content=$(cat PROJECT_SPEC.json)
|
|
536
|
+
|
|
537
|
+
# 创建新的日志条目
|
|
538
|
+
local new_log=$(printf '{{"timestamp": "%s", "agent": "%s", "message": "%s"}}' "$timestamp" "$agent_name" "$message")
|
|
539
|
+
|
|
540
|
+
# 简单地追加到协作历史(实际使用时可能需要更复杂的JSON操作)
|
|
541
|
+
echo "记录协作: [$agent_name] $message" >&2
|
|
542
|
+
}}
|
|
543
|
+
|
|
544
|
+
# 检查是否需要智能路由
|
|
545
|
+
if [[ -z "$USER_INPUT" ]]; then
|
|
546
|
+
echo "🎯 智能{cli_name}路由器 - 支持多智能体协作"
|
|
547
|
+
echo "💡 原始功能: ./smart_{cli_name}.sh '参数'"
|
|
548
|
+
echo "🤖 智能路由示例:"
|
|
549
|
+
'''
|
|
550
|
+
|
|
551
|
+
# 添加可用工具示例
|
|
552
|
+
for tool_name in sorted(available_tools.keys(), key=lambda x: self.config["tools"][x]["priority"]):
|
|
553
|
+
if available_tools[tool_name]:
|
|
554
|
+
keywords = self.config["tools"][tool_name]["keywords"]
|
|
555
|
+
router_content += f''' echo " ./smart_{cli_name}.sh '用{keywords[0]}写代码'"
|
|
556
|
+
'''
|
|
557
|
+
|
|
558
|
+
router_content += ''' exit 0
|
|
559
|
+
fi
|
|
560
|
+
|
|
561
|
+
# 检查是否需要协作
|
|
562
|
+
NEEDS_COLLAB=false
|
|
563
|
+
if [[ "$USER_INPUT" =~ 协作|一起|共同|多个|团队|分工|complete[[:space:]]+project|full[[:space:]]+solution|entire[[:space:]]+task ]]; then
|
|
564
|
+
NEEDS_COLLAB=true
|
|
565
|
+
|
|
566
|
+
# 创建协作任务记录
|
|
567
|
+
TASK_ID="collab_$(date +%s)_$RANDOM"
|
|
568
|
+
CURRENT_TIME=$(date -Iseconds)
|
|
569
|
+
echo "创建协作任务: $TASK_ID" >&2
|
|
570
|
+
|
|
571
|
+
# 简单地记录到临时文件,实际使用时应更新PROJECT_SPEC.json
|
|
572
|
+
echo "{{\\"id\\": \\"$TASK_ID\\", \\"type\\": \\"collaboration\\", \\"description\\": \\"$USER_INPUT\\", \\"status\\": \\"pending\\", \\"created_at\\": \\"$CURRENT_TIME\\"}}" >> COLLAB_TASKS_TEMP.json 2>/dev/null
|
|
573
|
+
fi
|
|
574
|
+
|
|
575
|
+
# 智能路由检测
|
|
576
|
+
ROUTE_KEYWORDS="用 帮我 请 智能 ai 写 生成 解释 分析 翻译 代码 文章"
|
|
577
|
+
NEEDS_ROUTE=false
|
|
578
|
+
|
|
579
|
+
for keyword in $ROUTE_KEYWORDS; do
|
|
580
|
+
if echo "$USER_INPUT" | grep -qi "$keyword"; then
|
|
581
|
+
NEEDS_ROUTE=true
|
|
582
|
+
break
|
|
583
|
+
fi
|
|
584
|
+
done
|
|
585
|
+
|
|
586
|
+
if [ "$NEEDS_ROUTE" = false ]; then
|
|
587
|
+
# 不需要路由,执行原始命令
|
|
588
|
+
{cli_name} "$USER_INPUT"
|
|
589
|
+
exit 0
|
|
590
|
+
fi
|
|
591
|
+
|
|
592
|
+
# 智能路由逻辑
|
|
593
|
+
'''
|
|
594
|
+
|
|
595
|
+
# 生成路由逻辑
|
|
596
|
+
for tool_name in sorted(available_tools.keys(), key=lambda x: self.config["tools"][x]["priority"]):
|
|
597
|
+
if available_tools[tool_name]:
|
|
598
|
+
keywords = self.config["tools"][tool_name]["keywords"]
|
|
599
|
+
command = self.config["tools"][tool_name]["command"][self.system]
|
|
600
|
+
|
|
601
|
+
router_content += f'''
|
|
602
|
+
if echo "$USER_INPUT" | grep -qi "{keywords[0]}"; then
|
|
603
|
+
echo "🚀 智能路由到: {self.config["tools"][tool_name]["description"]}"
|
|
604
|
+
|
|
605
|
+
# 记录任务执行到项目规范
|
|
606
|
+
log_collaboration "{tool_name}" "开始执行任务: $USER_INPUT"
|
|
607
|
+
|
|
608
|
+
CLEAN_INPUT=$(echo "$USER_INPUT" | sed 's/{keywords[0]}//g' | sed 's/^用[[:space:]]*//' | sed 's/^帮我[[:space:]]*//' | sed 's/^请[[:space:]]*//' | sed 's/^写[[:space:]]*//' | sed 's/^生成[[:space:]]*//' | sed 's/^解释[[:space:]]*//' | sed 's/^分析[[:space:]]*//' | sed 's/^翻译[[:space:]]*//' | sed 's/^代码[[:space:]]*//' | sed 's/^文章[[:space:]]*//')
|
|
609
|
+
|
|
610
|
+
if [ "{self.config["tools"][tool_name].get("wrapper", False)}" = true ]; then
|
|
611
|
+
python {self.config["tools"][tool_name]["wrapper_script"]} "$CLEAN_INPUT"
|
|
612
|
+
TASK_RESULT=$?
|
|
613
|
+
else
|
|
614
|
+
{command} "$CLEAN_INPUT"
|
|
615
|
+
TASK_RESULT=$?
|
|
616
|
+
fi
|
|
617
|
+
|
|
618
|
+
# 更新任务状态到项目规范
|
|
619
|
+
if [ $TASK_RESULT -eq 0 ]; then
|
|
620
|
+
log_collaboration "{tool_name}" "任务成功完成: $CLEAN_INPUT"
|
|
621
|
+
else
|
|
622
|
+
log_collaboration "{tool_name}" "任务执行失败: $CLEAN_INPUT"
|
|
623
|
+
fi
|
|
624
|
+
|
|
625
|
+
exit $TASK_RESULT
|
|
626
|
+
fi
|
|
627
|
+
'''
|
|
628
|
+
|
|
629
|
+
# 默认路由
|
|
630
|
+
default_tool = self.config["default_tool"]
|
|
631
|
+
if default_tool in available_tools:
|
|
632
|
+
command = self.config["tools"][default_tool]["command"][self.system]
|
|
633
|
+
router_content += f'''
|
|
634
|
+
# 默认路由到{self.config["tools"][default_tool]["description"]}
|
|
635
|
+
echo "🚀 智能路由到: {self.config["tools"][default_tool]["description"]}"
|
|
636
|
+
|
|
637
|
+
# 记录任务执行到项目规范
|
|
638
|
+
log_collaboration "{default_tool}" "开始执行默认任务: $USER_INPUT"
|
|
639
|
+
|
|
640
|
+
CLEAN_INPUT=$(echo "$USER_INPUT" | sed 's/^用[[:space:]]*//' | sed 's/^帮我[[:space:]]*//' | sed 's/^请[[:space:]]*//' | sed 's/^写[[:space:]]*//' | sed 's/^生成[[:space:]]*//' | sed 's/^解释[[:space:]]*//' | sed 's/^分析[[:space:]]*//' | sed 's/^翻译[[:space:]]*//' | sed 's/^代码[[:space:]]*//' | sed 's/^文章[[:space:]]*//')
|
|
641
|
+
|
|
642
|
+
{command} "$CLEAN_INPUT"
|
|
643
|
+
TASK_RESULT=$?
|
|
644
|
+
|
|
645
|
+
# 更新任务状态到项目规范
|
|
646
|
+
if [ $TASK_RESULT -eq 0 ]; then
|
|
647
|
+
log_collaboration "{default_tool}" "默认任务成功完成: $CLEAN_INPUT"
|
|
648
|
+
else
|
|
649
|
+
log_collaboration "{default_tool}" "默认任务执行失败: $CLEAN_INPUT"
|
|
650
|
+
fi
|
|
651
|
+
|
|
652
|
+
exit $TASK_RESULT
|
|
653
|
+
'''
|
|
654
|
+
else:
|
|
655
|
+
router_content += f'''# 执行原始{cli_name}
|
|
656
|
+
{cli_name} "$USER_INPUT"
|
|
657
|
+
'''
|
|
658
|
+
|
|
659
|
+
return router_content
|
|
660
|
+
|
|
661
|
+
def _generate_python_router(self, cli_name, available_tools):
|
|
662
|
+
"""生成Python路由器 - 支持项目背景的间接协同"""
|
|
663
|
+
router_content = f'''#!/usr/bin/env python3
|
|
664
|
+
# -*- coding: utf-8 -*-
|
|
665
|
+
"""
|
|
666
|
+
智能{cli_name}路由器 - Python版本 - 支持基于背景的间接协同
|
|
667
|
+
系统: {self.system}
|
|
668
|
+
可用工具: {list(available_tools.keys())}
|
|
669
|
+
基于项目目录背景的间接协同(Stigmergy)
|
|
670
|
+
"""
|
|
671
|
+
|
|
672
|
+
import sys
|
|
673
|
+
import subprocess
|
|
674
|
+
import re
|
|
675
|
+
import os
|
|
676
|
+
import json
|
|
677
|
+
from datetime import datetime
|
|
678
|
+
from pathlib import Path
|
|
679
|
+
|
|
680
|
+
class ProjectContext:
|
|
681
|
+
"""项目背景管理器 - 实现Stigmergy机制"""
|
|
682
|
+
|
|
683
|
+
def __init__(self, project_path="."):
|
|
684
|
+
self.project_path = Path(project_path)
|
|
685
|
+
self.spec_file = self.project_path / "PROJECT_SPEC.json"
|
|
686
|
+
self.readme_file = self.project_path / "README.md"
|
|
687
|
+
self.tasks_file = self.project_path / "TASKS.md" # 计划列表
|
|
688
|
+
self.log_file = self.project_path / "COLLABORATION_LOG.md" # 协作日志
|
|
689
|
+
self.data = self._load_context()
|
|
690
|
+
|
|
691
|
+
def _load_context(self):
|
|
692
|
+
"""加载项目背景"""
|
|
693
|
+
if self.spec_file.exists():
|
|
694
|
+
with open(self.spec_file, 'r', encoding='utf-8') as f:
|
|
695
|
+
return json.load(f)
|
|
696
|
+
else:
|
|
697
|
+
# 创建默认背景
|
|
698
|
+
default_context = {{
|
|
699
|
+
"project_name": "Collaboration Project",
|
|
700
|
+
"created_at": datetime.now().isoformat(),
|
|
701
|
+
"status": "active",
|
|
702
|
+
"current_agents": {{}},
|
|
703
|
+
"tasks": {{}},
|
|
704
|
+
"collaboration_history": [],
|
|
705
|
+
"decisions": [],
|
|
706
|
+
"communication_log": [],
|
|
707
|
+
"current_state": {{
|
|
708
|
+
"active_task": None,
|
|
709
|
+
"completed_tasks": [],
|
|
710
|
+
"pending_tasks": [],
|
|
711
|
+
"next_scheduled_task": None
|
|
712
|
+
}}
|
|
713
|
+
}}
|
|
714
|
+
self._save_context(default_context)
|
|
715
|
+
return default_context
|
|
716
|
+
|
|
717
|
+
def _save_context(self, data=None):
|
|
718
|
+
"""保存项目背景"""
|
|
719
|
+
if data:
|
|
720
|
+
self.data = data
|
|
721
|
+
with open(self.spec_file, 'w', encoding='utf-8') as f:
|
|
722
|
+
json.dump(self.data, f, ensure_ascii=False, indent=2)
|
|
723
|
+
|
|
724
|
+
def add_collaboration_log(self, message, agent_name=None):
|
|
725
|
+
"""添加协作日志到背景"""
|
|
726
|
+
log_entry = {{
|
|
727
|
+
"timestamp": datetime.now().isoformat(),
|
|
728
|
+
"agent": agent_name,
|
|
729
|
+
"message": message
|
|
730
|
+
}}
|
|
731
|
+
self.data["collaboration_history"].append(log_entry)
|
|
732
|
+
self._save_context()
|
|
733
|
+
|
|
734
|
+
# 同时写入协作日志文件
|
|
735
|
+
with open(self.log_file, 'a', encoding='utf-8') as f:
|
|
736
|
+
f.write(f"[{{log_entry['timestamp']}}] [{{agent_name}}] {{message}}\\n")
|
|
737
|
+
|
|
738
|
+
def update_task_status(self, task_id, status, result=None, completed_by=None):
|
|
739
|
+
"""更新任务状态到背景"""
|
|
740
|
+
if task_id in self.data["tasks"]:
|
|
741
|
+
self.data["tasks"][task_id].update({{
|
|
742
|
+
"status": status,
|
|
743
|
+
"completed_at": datetime.now().isoformat() if status == "completed" else None,
|
|
744
|
+
"result": result,
|
|
745
|
+
"completed_by": completed_by
|
|
746
|
+
}})
|
|
747
|
+
|
|
748
|
+
if status == "completed":
|
|
749
|
+
self.data["current_state"]["completed_tasks"].append(task_id)
|
|
750
|
+
if task_id in self.data["current_state"]["pending_tasks"]:
|
|
751
|
+
self.data["current_state"]["pending_tasks"].remove(task_id)
|
|
752
|
+
|
|
753
|
+
# 更新任务文件
|
|
754
|
+
self._update_tasks_file()
|
|
755
|
+
|
|
756
|
+
self._save_context()
|
|
757
|
+
|
|
758
|
+
def _update_tasks_file(self):
|
|
759
|
+
"""更新任务列表文件"""
|
|
760
|
+
with open(self.tasks_file, 'w', encoding='utf-8') as f:
|
|
761
|
+
f.write("# 项目任务列表\\n\\n")
|
|
762
|
+
f.write("## 已完成任务\\n")
|
|
763
|
+
for task_id in self.data["current_state"]["completed_tasks"]:
|
|
764
|
+
task = self.data["tasks"].get(task_id, {{}})
|
|
765
|
+
f.write(f"- [x] {{task.get('description', task_id)}} (完成于 {{task.get('completed_at', '')}})\\n")
|
|
766
|
+
|
|
767
|
+
f.write("\\n## 待完成任务\\n")
|
|
768
|
+
for task_id in self.data["current_state"]["pending_tasks"]:
|
|
769
|
+
task = self.data["tasks"].get(task_id, {{}})
|
|
770
|
+
f.write(f"- [ ] {{task.get('description', task_id)}}\\n")
|
|
771
|
+
|
|
772
|
+
def analyze_context_for_next_action(self):
|
|
773
|
+
"""分析背景以决定下一步行动"""
|
|
774
|
+
# 检查是否有未分配的任务
|
|
775
|
+
for task_id, task in self.data["tasks"].items():
|
|
776
|
+
if task["status"] == "pending" and task.get("assigned_to") is None:
|
|
777
|
+
return task_id, task
|
|
778
|
+
|
|
779
|
+
# 检查是否有阻塞的任务需要帮助
|
|
780
|
+
# 检查是否有需要审查的任务
|
|
781
|
+
# 检查是否有需要优化的任务
|
|
782
|
+
# 等等...
|
|
783
|
+
|
|
784
|
+
return None, None
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
class SmartRouter:
|
|
788
|
+
def __init__(self):
|
|
789
|
+
self.cli_name = "{cli_name}"
|
|
790
|
+
self.available_tools = {repr(available_tools)}
|
|
791
|
+
self.tools = {repr(self.config["tools"])}
|
|
792
|
+
self.route_keywords = {repr(self.config["route_keywords"])}
|
|
793
|
+
self.default_tool = "{self.config["default_tool"]}"
|
|
794
|
+
# 初始化项目背景
|
|
795
|
+
self.project_context = ProjectContext()
|
|
796
|
+
|
|
797
|
+
def should_route(self, user_input):
|
|
798
|
+
"""检查是否需要智能路由"""
|
|
799
|
+
return any(keyword.lower() in user_input.lower() for keyword in self.route_keywords)
|
|
800
|
+
|
|
801
|
+
def smart_route(self, user_input):
|
|
802
|
+
"""智能路由到合适的工具"""
|
|
803
|
+
user_input = user_input.strip()
|
|
804
|
+
|
|
805
|
+
# 首先分析当前背景
|
|
806
|
+
next_task_id, next_task = self.project_context.analyze_context_for_next_action()
|
|
807
|
+
if next_task_id and next_task:
|
|
808
|
+
# 根据背景中的任务进行路由,而不是仅根据用户输入
|
|
809
|
+
task_description = next_task["description"]
|
|
810
|
+
|
|
811
|
+
# 检测最适合处理此任务的工具
|
|
812
|
+
for tool_name, tool_info in self.tools.items():
|
|
813
|
+
if not self.available_tools.get(tool_name, False):
|
|
814
|
+
continue
|
|
815
|
+
|
|
816
|
+
# 检查任务描述中是否包含工具关键词
|
|
817
|
+
for keyword in tool_info["keywords"]:
|
|
818
|
+
if keyword.lower() in task_description.lower():
|
|
819
|
+
# 更新任务分配
|
|
820
|
+
self.project_context.data["tasks"][next_task_id]["assigned_to"] = tool_name
|
|
821
|
+
self.project_context._save_context()
|
|
822
|
+
|
|
823
|
+
# 准备执行任务
|
|
824
|
+
clean_input = re.sub(r'^(用|帮我|请|麻烦|给我|帮我写|帮我生成)\\s*', '', task_description, flags=re.IGNORECASE).strip()
|
|
825
|
+
return tool_name, [clean_input] if clean_input else []
|
|
826
|
+
|
|
827
|
+
# 如果没有待处理任务,按原始方式路由
|
|
828
|
+
for tool_name, tool_info in self.tools.items():
|
|
829
|
+
if not self.available_tools.get(tool_name, False):
|
|
830
|
+
continue
|
|
831
|
+
|
|
832
|
+
for keyword in tool_info["keywords"]:
|
|
833
|
+
if keyword.lower() in user_input.lower():
|
|
834
|
+
# 提取参数
|
|
835
|
+
clean_input = re.sub(rf'.*{{keyword}}\\s*', '', user_input, flags=re.IGNORECASE).strip()
|
|
836
|
+
clean_input = re.sub(r'^(用|帮我|请|麻烦|给我|帮我写|帮我生成)\\s*', '', clean_input, flags=re.IGNORECASE).strip()
|
|
837
|
+
|
|
838
|
+
# 分析协作意图(检查是否需要路由到其他工具)
|
|
839
|
+
target_agent, task_desc = self._analyze_collaboration_intent(clean_input)
|
|
840
|
+
|
|
841
|
+
# 确保这两个变量在所有分支中都定义
|
|
842
|
+
if target_agent and task_desc:
|
|
843
|
+
# 检查目标工具是否可用
|
|
844
|
+
if self._is_tool_available(target_agent):
|
|
845
|
+
# 目标工具可用,执行协作路由
|
|
846
|
+
self._create_collaboration_tasks(task_desc, target_agent)
|
|
847
|
+
return target_agent, [task_desc] if task_desc else []
|
|
848
|
+
else:
|
|
849
|
+
# 目标工具不可用,创建挂起任务
|
|
850
|
+
self._create_suspended_collaboration_tasks(clean_input, tool_name, target_agent)
|
|
851
|
+
# 返回友好提示
|
|
852
|
+
return tool_name, [f"目标工具 {target_agent} 暂不可用,已记录任务: {task_desc}"]
|
|
853
|
+
elif self._needs_collaboration(clean_input):
|
|
854
|
+
# 检查是否需要协作 - 如果输入包含协作关键词但不是路由语法
|
|
855
|
+
# 创建协作任务
|
|
856
|
+
self._create_collaboration_tasks(clean_input, tool_name)
|
|
857
|
+
|
|
858
|
+
return tool_name, [clean_input] if clean_input else []
|
|
859
|
+
|
|
860
|
+
# 默认路由
|
|
861
|
+
clean_input = re.sub(r'^(用|帮我|请|麻烦|给我|帮我写|帮我生成)\\s*', '', user_input, flags=re.IGNORECASE).strip()
|
|
862
|
+
return self.default_tool, [clean_input] if clean_input else []
|
|
863
|
+
|
|
864
|
+
def _needs_collaboration(self, user_input):
|
|
865
|
+
"""检查是否需要协作"""
|
|
866
|
+
collaboration_keywords = ["协作", "一起", "共同", "多个", "团队", "分工", "complete project", "full solution", "entire task"]
|
|
867
|
+
return any(keyword in user_input.lower() for keyword in collaboration_keywords)
|
|
868
|
+
|
|
869
|
+
def _analyze_collaboration_intent(self, user_input):
|
|
870
|
+
"""分析协作意图 - 检查是否需要路由到其他工具"""
|
|
871
|
+
import re
|
|
872
|
+
patterns = [
|
|
873
|
+
# 让<工具名>帮我<任务>
|
|
874
|
+
r'让\s*([a-zA-Z]+)\s*帮我\s*(.+)',
|
|
875
|
+
# 用<工具名><任务>
|
|
876
|
+
r'用\s*([a-zA-Z]+)\s*(.+)',
|
|
877
|
+
# 请<工具名><任务>
|
|
878
|
+
r'请\s*([a-zA-Z]+)\s*(.+)'
|
|
879
|
+
]
|
|
880
|
+
|
|
881
|
+
for pattern in patterns:
|
|
882
|
+
match = re.search(pattern, user_input, re.IGNORECASE)
|
|
883
|
+
if match:
|
|
884
|
+
target_tool = match.group(1).lower().strip()
|
|
885
|
+
task_desc = match.group(2).strip()
|
|
886
|
+
|
|
887
|
+
# 检查目标工具是否在已知工具列表中
|
|
888
|
+
if target_tool in self.tools:
|
|
889
|
+
return target_tool, task_desc
|
|
890
|
+
|
|
891
|
+
return None, None
|
|
892
|
+
|
|
893
|
+
def _is_tool_available(self, tool_name):
|
|
894
|
+
"""检查工具是否可用"""
|
|
895
|
+
import subprocess
|
|
896
|
+
try:
|
|
897
|
+
# 获取工具命令
|
|
898
|
+
command = self.tools[tool_name]["command"][self.system]
|
|
899
|
+
if isinstance(command, str):
|
|
900
|
+
cmd_parts = command.split()
|
|
901
|
+
else:
|
|
902
|
+
# 如果command是字典,取当前系统的命令
|
|
903
|
+
cmd_parts = command.get(self.system, tool_name).split()
|
|
904
|
+
|
|
905
|
+
main_cmd = cmd_parts[0].split('.')[0] # 只取主命令部分
|
|
906
|
+
|
|
907
|
+
# 尝试查找命令
|
|
908
|
+
if self.system == "windows":
|
|
909
|
+
result = subprocess.run(["where", main_cmd],
|
|
910
|
+
capture_output=True, text=True, timeout=5)
|
|
911
|
+
else:
|
|
912
|
+
result = subprocess.run(["which", main_cmd],
|
|
913
|
+
capture_output=True, text=True, timeout=5)
|
|
914
|
+
|
|
915
|
+
return result.returncode == 0
|
|
916
|
+
except:
|
|
917
|
+
return False
|
|
918
|
+
|
|
919
|
+
def _create_suspended_collaboration_tasks(self, original_input, initiating_tool, target_agent):
|
|
920
|
+
"""创建挂起的协作任务 - 当目标工具不可用时"""
|
|
921
|
+
import time
|
|
922
|
+
task_id = f"suspended_collab_{int(time.time())}_{len(self.project_context.data['tasks'])}"
|
|
923
|
+
|
|
924
|
+
task = {
|
|
925
|
+
"id": task_id,
|
|
926
|
+
"type": "collaboration",
|
|
927
|
+
"description": original_input,
|
|
928
|
+
"initiating_tool": initiating_tool,
|
|
929
|
+
"target_tool": target_agent,
|
|
930
|
+
"status": "suspended", # 挂起状态
|
|
931
|
+
"created_at": datetime.now().isoformat(),
|
|
932
|
+
"assigned_to": target_agent,
|
|
933
|
+
"result": "目标工具 " + target_agent + " 暂不可用,等待可用时自动执行",
|
|
934
|
+
"completed_by": None,
|
|
935
|
+
"completed_at": None
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
self.project_context.data["tasks"][task_id] = task
|
|
939
|
+
# 不添加到pending_tasks,因为它暂时无法执行
|
|
940
|
+
|
|
941
|
+
# 添加协作日志
|
|
942
|
+
self.project_context.add_collaboration_log(
|
|
943
|
+
"创建挂起协作任务 " + task_id + ": 需要 " + target_agent + ",但工具暂不可用: " + original_input,
|
|
944
|
+
initiating_tool
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
self.project_context._save_context()
|
|
948
|
+
|
|
949
|
+
def _create_collaboration_tasks(self, user_input, initiating_tool):
|
|
950
|
+
"""创建协作任务到项目背景"""
|
|
951
|
+
task_id = f"collab_{int(datetime.now().timestamp())}"
|
|
952
|
+
|
|
953
|
+
task = {{
|
|
954
|
+
"id": task_id,
|
|
955
|
+
"type": "collaboration",
|
|
956
|
+
"description": user_input,
|
|
957
|
+
"initiating_tool": initiating_tool,
|
|
958
|
+
"status": "pending",
|
|
959
|
+
"created_at": datetime.now().isoformat(),
|
|
960
|
+
"assigned_to": None, # 由智能体自主认领
|
|
961
|
+
"result": None,
|
|
962
|
+
"completed_by": None,
|
|
963
|
+
"completed_at": None
|
|
964
|
+
}}
|
|
965
|
+
|
|
966
|
+
self.project_context.data["tasks"][task_id] = task
|
|
967
|
+
self.project_context.data["current_state"]["pending_tasks"].append(task_id)
|
|
968
|
+
|
|
969
|
+
# 记录协作任务创建 - 使用字符串拼接以避免生成代码时的转义问题
|
|
970
|
+
log_msg = "协作任务创建: " + user_input + " (由 " + initiating_tool + " 发起)"
|
|
971
|
+
self.project_context.add_collaboration_log(
|
|
972
|
+
log_msg,
|
|
973
|
+
initiating_tool
|
|
974
|
+
)
|
|
975
|
+
|
|
976
|
+
self.project_context._save_context()
|
|
977
|
+
|
|
978
|
+
def execute_tool(self, tool_name, args):
|
|
979
|
+
"""执行工具"""
|
|
980
|
+
if tool_name not in self.tools:
|
|
981
|
+
return 1, "", f"未知工具: {{tool_name}}"
|
|
982
|
+
|
|
983
|
+
tool_info = self.tools[tool_name]
|
|
984
|
+
command = tool_info["command"]["{self.system}"]
|
|
985
|
+
|
|
986
|
+
if tool_info.get("wrapper"):
|
|
987
|
+
wrapper_script = tool_info.get("wrapper_script")
|
|
988
|
+
cmd = ["python", wrapper_script] + args
|
|
989
|
+
else:
|
|
990
|
+
cmd = [command] + args
|
|
991
|
+
|
|
992
|
+
try:
|
|
993
|
+
# 在执行前记录任务
|
|
994
|
+
task_description = ' '.join(args) if args else "no specific task"
|
|
995
|
+
task_id = "task_" + tool_name + "_" + str(int(datetime.now().timestamp()))
|
|
996
|
+
task = {{
|
|
997
|
+
"id": task_id,
|
|
998
|
+
"type": "execution",
|
|
999
|
+
"description": task_description,
|
|
1000
|
+
"initiating_tool": tool_name,
|
|
1001
|
+
"status": "in_progress",
|
|
1002
|
+
"created_at": datetime.now().isoformat(),
|
|
1003
|
+
"assigned_to": tool_name,
|
|
1004
|
+
"result": None,
|
|
1005
|
+
"completed_by": tool_name,
|
|
1006
|
+
"completed_at": None
|
|
1007
|
+
}}
|
|
1008
|
+
|
|
1009
|
+
self.project_context.data["tasks"][task_id] = task
|
|
1010
|
+
self.project_context.data["current_state"]["active_task"] = task_id
|
|
1011
|
+
self.project_context._save_context()
|
|
1012
|
+
|
|
1013
|
+
result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8', timeout=60)
|
|
1014
|
+
|
|
1015
|
+
# 更新任务状态
|
|
1016
|
+
status = "completed" if result.returncode == 0 else "failed"
|
|
1017
|
+
self.project_context.update_task_status(task_id, status,
|
|
1018
|
+
result.stdout if result.returncode == 0 else result.stderr,
|
|
1019
|
+
tool_name)
|
|
1020
|
+
|
|
1021
|
+
# 添加协作日志
|
|
1022
|
+
status_str = '成功' if result.returncode == 0 else '失败'
|
|
1023
|
+
self.project_context.add_collaboration_log(
|
|
1024
|
+
"执行任务 " + task_id + ": " + status_str,
|
|
1025
|
+
tool_name
|
|
1026
|
+
)
|
|
1027
|
+
|
|
1028
|
+
# 执行后分析背景,检查是否需要其他智能体介入
|
|
1029
|
+
self._post_execution_analysis(result.stdout if result.returncode == 0 else result.stderr)
|
|
1030
|
+
|
|
1031
|
+
return result.returncode, result.stdout, result.stderr
|
|
1032
|
+
except Exception as e:
|
|
1033
|
+
# 记录异常情况
|
|
1034
|
+
task_id = "task_" + tool_name + "_" + str(int(datetime.now().timestamp())) + "_error"
|
|
1035
|
+
error_task = {{
|
|
1036
|
+
"id": task_id,
|
|
1037
|
+
"type": "error",
|
|
1038
|
+
"description": str(e),
|
|
1039
|
+
"initiating_tool": tool_name,
|
|
1040
|
+
"status": "failed",
|
|
1041
|
+
"created_at": datetime.now().isoformat(),
|
|
1042
|
+
"assigned_to": tool_name,
|
|
1043
|
+
"result": str(e),
|
|
1044
|
+
"completed_by": tool_name,
|
|
1045
|
+
"completed_at": datetime.now().isoformat()
|
|
1046
|
+
}}
|
|
1047
|
+
|
|
1048
|
+
self.project_context.data["tasks"][task_id] = error_task
|
|
1049
|
+
self.project_context.update_task_status(task_id, "failed", str(e), tool_name)
|
|
1050
|
+
|
|
1051
|
+
return -1, "", "执行失败: " + str(e)
|
|
1052
|
+
|
|
1053
|
+
def _post_execution_analysis(self, result):
|
|
1054
|
+
"""执行后分析背景 - 检查是否需要其他智能体介入"""
|
|
1055
|
+
# 检查结果中是否包含需要其他智能体处理的内容
|
|
1056
|
+
if "code" in result.lower() and "test" in result.lower():
|
|
1057
|
+
# 需要测试智能体介入
|
|
1058
|
+
task_id = "followup_test_" + str(int(datetime.now().timestamp()))
|
|
1059
|
+
task = {{
|
|
1060
|
+
"id": task_id,
|
|
1061
|
+
"type": "testing",
|
|
1062
|
+
"description": "为代码生成测试: " + result[:200] + "...",
|
|
1063
|
+
"initiating_tool": self.cli_name,
|
|
1064
|
+
"status": "pending",
|
|
1065
|
+
"created_at": datetime.now().isoformat(),
|
|
1066
|
+
"assigned_to": "codebuddy", # 或其他测试相关的智能体
|
|
1067
|
+
"result": None,
|
|
1068
|
+
"completed_by": None,
|
|
1069
|
+
"completed_at": None
|
|
1070
|
+
}}
|
|
1071
|
+
|
|
1072
|
+
self.project_context.data["tasks"][task_id] = task
|
|
1073
|
+
self.project_context.data["current_state"]["pending_tasks"].append(task_id)
|
|
1074
|
+
self.project_context.add_collaboration_log(
|
|
1075
|
+
"创建后续任务 " + task_id + ": 需要为结果生成测试",
|
|
1076
|
+
self.cli_name
|
|
1077
|
+
)
|
|
1078
|
+
self.project_context._save_context()
|
|
1079
|
+
|
|
1080
|
+
def execute_original_cli(self, args):
|
|
1081
|
+
"""执行原始CLI"""
|
|
1082
|
+
try:
|
|
1083
|
+
cmd = ["{cli_name}"] + args
|
|
1084
|
+
result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
|
|
1085
|
+
return result.returncode, result.stdout, result.stderr
|
|
1086
|
+
except Exception as e:
|
|
1087
|
+
return -1, "", "原始CLI执行失败: " + str(e)
|
|
1088
|
+
|
|
1089
|
+
def main():
|
|
1090
|
+
router = SmartRouter()
|
|
1091
|
+
|
|
1092
|
+
if len(sys.argv) < 2:
|
|
1093
|
+
print("🎯 智能{{cli_name}}路由器 - Python版本 - 基于背景的间接协同")
|
|
1094
|
+
print("💡 原始功能: python smart_{cli_name}.py '参数'")
|
|
1095
|
+
print("🤖 智能路由示例:")
|
|
1096
|
+
'''
|
|
1097
|
+
|
|
1098
|
+
# 添加可用工具示例
|
|
1099
|
+
for tool_name in sorted(available_tools.keys(), key=lambda x: self.config["tools"][x]["priority"]):
|
|
1100
|
+
keywords = self.config["tools"][tool_name]["keywords"]
|
|
1101
|
+
router_content += f''' print(" python smart_{cli_name}.py '用{keywords[0]}写代码'")
|
|
1102
|
+
'''
|
|
1103
|
+
|
|
1104
|
+
router_content += ''' return 0
|
|
1105
|
+
|
|
1106
|
+
user_input = ' '.join(sys.argv[1:])
|
|
1107
|
+
|
|
1108
|
+
if router.should_route(user_input):
|
|
1109
|
+
tool_name, args = router.smart_route(user_input)
|
|
1110
|
+
if tool_name and tool_name != router.cli_name:
|
|
1111
|
+
print("🚀 智能路由到: " + router.tools[tool_name]['description'])
|
|
1112
|
+
returncode, stdout, stderr = router.execute_tool(tool_name, args)
|
|
1113
|
+
if stdout:
|
|
1114
|
+
print(stdout)
|
|
1115
|
+
if stderr:
|
|
1116
|
+
print(stderr, file=sys.stderr)
|
|
1117
|
+
sys.exit(returncode)
|
|
1118
|
+
|
|
1119
|
+
# 执行原始CLI
|
|
1120
|
+
returncode, stdout, stderr = router.execute_original_cli(sys.argv[1:])
|
|
1121
|
+
if stdout:
|
|
1122
|
+
print(stdout)
|
|
1123
|
+
if stderr:
|
|
1124
|
+
print(stderr, file=sys.stderr)
|
|
1125
|
+
sys.exit(returncode)
|
|
1126
|
+
|
|
1127
|
+
if __name__ == "__main__":
|
|
1128
|
+
main()
|
|
1129
|
+
'''
|
|
1130
|
+
|
|
1131
|
+
return router_content
|
|
1132
|
+
|
|
1133
|
+
def setup_environment(self):
|
|
1134
|
+
"""设置环境"""
|
|
1135
|
+
print(f"🔧 正在设置{self.system}环境...")
|
|
1136
|
+
|
|
1137
|
+
# 检测并安装依赖
|
|
1138
|
+
self._check_python()
|
|
1139
|
+
self._check_required_files()
|
|
1140
|
+
|
|
1141
|
+
# 创建必要的包装器
|
|
1142
|
+
self._create_wrappers()
|
|
1143
|
+
|
|
1144
|
+
# 设置PATH(如果需要)
|
|
1145
|
+
if self.config.get("install_global", False):
|
|
1146
|
+
self._install_global()
|
|
1147
|
+
|
|
1148
|
+
def _check_python(self):
|
|
1149
|
+
"""检查Python环境"""
|
|
1150
|
+
try:
|
|
1151
|
+
subprocess.run([sys.executable, "--version"], check=True, capture_output=True)
|
|
1152
|
+
print("✅ Python环境正常")
|
|
1153
|
+
except subprocess.CalledProcessError:
|
|
1154
|
+
print("❌ Python环境检查失败")
|
|
1155
|
+
sys.exit(1)
|
|
1156
|
+
|
|
1157
|
+
def _check_required_files(self):
|
|
1158
|
+
"""检查必需文件"""
|
|
1159
|
+
required_files = self.config.get("wrapper_scripts", {})
|
|
1160
|
+
for script_name, script_path in required_files.items():
|
|
1161
|
+
if not os.path.exists(script_path):
|
|
1162
|
+
print(f"⚠️ 缺少必需文件: {script_path}")
|
|
1163
|
+
print(f"💡 请确保 {script_path} 存在")
|
|
1164
|
+
|
|
1165
|
+
def _create_wrappers(self):
|
|
1166
|
+
"""创建包装器脚本"""
|
|
1167
|
+
for tool_name, tool_config in self.config["tools"].items():
|
|
1168
|
+
if tool_config.get("wrapper") and tool_config.get("wrapper_script"):
|
|
1169
|
+
script_path = self.setup_dir / tool_config["wrapper_script"]
|
|
1170
|
+
if not script_path.exists():
|
|
1171
|
+
self._create_generic_wrapper(tool_name)
|
|
1172
|
+
|
|
1173
|
+
def _create_generic_wrapper(self, tool_name):
|
|
1174
|
+
"""创建通用包装器"""
|
|
1175
|
+
wrapper_content = f'''#!/usr/bin/env python3
|
|
1176
|
+
# -*- coding: utf-8 -*-
|
|
1177
|
+
"""
|
|
1178
|
+
{tool_name}通用包装器
|
|
1179
|
+
"""
|
|
1180
|
+
|
|
1181
|
+
import subprocess
|
|
1182
|
+
import sys
|
|
1183
|
+
|
|
1184
|
+
def main():
|
|
1185
|
+
if len(sys.argv) < 2:
|
|
1186
|
+
print(f"🎯 {tool_name}包装器")
|
|
1187
|
+
print("💡 用法: python {tool_name}_wrapper.py '参数'")
|
|
1188
|
+
return
|
|
1189
|
+
|
|
1190
|
+
user_input = ' '.join(sys.argv[1:])
|
|
1191
|
+
|
|
1192
|
+
try:
|
|
1193
|
+
# 尝试执行原始{tool_name}
|
|
1194
|
+
result = subprocess.run(["{tool_name}", user_input], capture_output=True, text=True)
|
|
1195
|
+
print(result.stdout)
|
|
1196
|
+
if result.stderr:
|
|
1197
|
+
print(result.stderr, file=sys.stderr)
|
|
1198
|
+
return result.returncode
|
|
1199
|
+
except Exception as e:
|
|
1200
|
+
print(f"❌ {tool_name}执行失败: {{e}}")
|
|
1201
|
+
return 1
|
|
1202
|
+
|
|
1203
|
+
if __name__ == "__main__":
|
|
1204
|
+
sys.exit(main())
|
|
1205
|
+
'''
|
|
1206
|
+
|
|
1207
|
+
script_path = self.setup_dir / f"{tool_name}_wrapper.py"
|
|
1208
|
+
with open(script_path, 'w', encoding='utf-8') as f:
|
|
1209
|
+
f.write(wrapper_content)
|
|
1210
|
+
print(f"✅ 创建通用包装器: {script_path}")
|
|
1211
|
+
|
|
1212
|
+
def _install_global(self):
|
|
1213
|
+
"""全局安装"""
|
|
1214
|
+
print("🌍 设置全局访问...")
|
|
1215
|
+
|
|
1216
|
+
# 这里可以添加全局安装逻辑
|
|
1217
|
+
# 例如:复制到系统PATH、创建符号链接等
|
|
1218
|
+
|
|
1219
|
+
def save_setup_report(self):
|
|
1220
|
+
"""保存设置报告"""
|
|
1221
|
+
report = {
|
|
1222
|
+
"timestamp": str(Path.cwd()),
|
|
1223
|
+
"system": self.system,
|
|
1224
|
+
"config_file": self.config_file,
|
|
1225
|
+
"available_tools": self.discover_available_tools(),
|
|
1226
|
+
"setup_directory": str(self.setup_dir),
|
|
1227
|
+
"created_files": os.listdir(self.setup_dir)
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
report_file = self.setup_dir / "setup_report.json"
|
|
1231
|
+
with open(report_file, 'w', encoding='utf-8') as f:
|
|
1232
|
+
json.dump(report, f, ensure_ascii=False, indent=2)
|
|
1233
|
+
|
|
1234
|
+
print(f"📊 设置报告已保存: {report_file}")
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
def main():
|
|
1238
|
+
"""主函数"""
|
|
1239
|
+
import argparse
|
|
1240
|
+
|
|
1241
|
+
parser = argparse.ArgumentParser(description="通用CLI智能路由自动化部署脚本")
|
|
1242
|
+
parser.add_argument("--setup", action="store_true", help="设置环境")
|
|
1243
|
+
parser.add_argument("--cli", help="指定CLI名称")
|
|
1244
|
+
parser.add_argument("--format", choices=["cmd", "powershell", "bash", "python"], default="cmd", help="输出格式")
|
|
1245
|
+
parser.add_argument("--config", help="配置文件路径")
|
|
1246
|
+
parser.add_argument("--list", action="store_true", help="列出可用工具")
|
|
1247
|
+
parser.add_argument("--generate", help="生成智能路由器")
|
|
1248
|
+
|
|
1249
|
+
args = parser.parse_args()
|
|
1250
|
+
|
|
1251
|
+
setup = UniversalCLISetup()
|
|
1252
|
+
|
|
1253
|
+
if args.config:
|
|
1254
|
+
setup.config_file = args.config
|
|
1255
|
+
setup.config = setup.load_or_create_config()
|
|
1256
|
+
|
|
1257
|
+
if args.setup:
|
|
1258
|
+
setup.setup_environment()
|
|
1259
|
+
setup.save_setup_report()
|
|
1260
|
+
return
|
|
1261
|
+
|
|
1262
|
+
if args.list:
|
|
1263
|
+
available = setup.discover_available_tools()
|
|
1264
|
+
print(f"🔧 可用工具 ({len(available)}个):")
|
|
1265
|
+
for name, available in available.items():
|
|
1266
|
+
status = "✅" if available else "❌"
|
|
1267
|
+
description = setup.config["tools"][name]["description"]
|
|
1268
|
+
print(f" {status} {name:<10} - {description}")
|
|
1269
|
+
return
|
|
1270
|
+
|
|
1271
|
+
if args.cli and not args.setup and not args.list:
|
|
1272
|
+
try:
|
|
1273
|
+
router_content = setup.generate_smart_router(args.cli, args.format)
|
|
1274
|
+
filename = f"smart_{args.cli}.{args.format}"
|
|
1275
|
+
|
|
1276
|
+
with open(filename, 'w', encoding='utf-8') as f:
|
|
1277
|
+
f.write(router_content)
|
|
1278
|
+
|
|
1279
|
+
print(f"✅ 智能路由器已创建: {filename}")
|
|
1280
|
+
print(f"📝 使用示例: {filename} '用kimi写代码'")
|
|
1281
|
+
except Exception as e:
|
|
1282
|
+
print(f"❌ 生成失败: {e}")
|
|
1283
|
+
return
|
|
1284
|
+
|
|
1285
|
+
parser.print_help()
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
if __name__ == "__main__":
|
|
1289
|
+
main()
|