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,930 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ 增强版通用CLI智能路由自动化部署脚本
5
+ 集成高级检测机制,使用npm包管理器进行精确工具检测
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
+ import tempfile
16
+
17
+
18
+ class EnhancedCLISetup:
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
+ # npm包名映射用于精确检测
28
+ self.npm_package_map = {
29
+ 'claude': '@anthropic-ai/claude-code',
30
+ 'gemini': '@google/gemini-cli',
31
+ 'qwen': '@qwen-code/qwen-code',
32
+ 'copilot': '@github/copilot',
33
+ 'codebuddy': '@tencent-ai/codebuddy-code',
34
+ 'qoder': '@qoder-ai/qodercli',
35
+ 'kimi': '@jacksontian/kimi-cli',
36
+ 'iflow': '@iflow-ai/iflow-cli',
37
+ 'arxiv': 'arxiv-mcp-server'
38
+ }
39
+
40
+ def load_or_create_config(self):
41
+ """加载或创建配置"""
42
+ default_config = {
43
+ "version": "2.0.0", # 增强版配置
44
+ "system": self.system,
45
+ "tools": {
46
+ "claude": {
47
+ "command": {
48
+ "windows": "claude.cmd",
49
+ "linux": "claude",
50
+ "darwin": "claude"
51
+ },
52
+ "description": "Anthropic Claude",
53
+ "keywords": ["claude", "anthropic"],
54
+ "priority": 1,
55
+ "wrapper": False,
56
+ "check_command": ["--version"],
57
+ "npm_package": "@anthropic-ai/claude-code"
58
+ },
59
+ "gemini": {
60
+ "command": {
61
+ "windows": "gemini.cmd",
62
+ "linux": "gemini",
63
+ "darwin": "gemini"
64
+ },
65
+ "description": "Google Gemini AI",
66
+ "keywords": ["gemini", "google", "谷歌"],
67
+ "priority": 2,
68
+ "wrapper": False,
69
+ "check_command": ["--version"],
70
+ "npm_package": "@google/gemini-cli"
71
+ },
72
+ "kimi": {
73
+ "command": {
74
+ "windows": "kimi_wrapper",
75
+ "linux": "kimi_wrapper",
76
+ "darwin": "kimi_wrapper"
77
+ },
78
+ "description": "月之暗面Kimi",
79
+ "keywords": ["kimi", "月之暗面", "moonshot"],
80
+ "priority": 3,
81
+ "wrapper": True,
82
+ "wrapper_script": "kimi_wrapper.py",
83
+ "check_command": ["--version"],
84
+ "npm_package": "@jacksontian/kimi-cli"
85
+ },
86
+ "qwen": {
87
+ "command": {
88
+ "windows": "qwen.cmd",
89
+ "linux": "qwen",
90
+ "darwin": "qwen"
91
+ },
92
+ "description": "阿里通义千问",
93
+ "keywords": ["qwen", "通义", "阿里"],
94
+ "priority": 4,
95
+ "wrapper": False,
96
+ "check_command": ["--version"],
97
+ "npm_package": "@qwen-code/qwen-code"
98
+ },
99
+ "ollama": {
100
+ "command": {
101
+ "windows": "ollama",
102
+ "linux": "ollama",
103
+ "darwin": "ollama"
104
+ },
105
+ "description": "Ollama本地模型",
106
+ "keywords": ["ollama", "本地", "离线"],
107
+ "priority": 5,
108
+ "wrapper": False,
109
+ "check_command": ["--version"],
110
+ "npm_package": None
111
+ },
112
+ "codebuddy": {
113
+ "command": {
114
+ "windows": "codebuddy",
115
+ "linux": "codebuddy",
116
+ "darwin": "codebuddy"
117
+ },
118
+ "description": "CodeBuddy代码助手",
119
+ "keywords": ["codebuddy", "代码助手", "编程"],
120
+ "priority": 6,
121
+ "wrapper": False,
122
+ "check_command": ["--version"],
123
+ "npm_package": "@tencent-ai/codebuddy-code"
124
+ },
125
+ "qodercli": {
126
+ "command": {
127
+ "windows": "qodercli",
128
+ "linux": "qodercli",
129
+ "darwin": "qodercli"
130
+ },
131
+ "description": "QoderCLI代码生成",
132
+ "keywords": ["qodercli", "代码生成", "编程"],
133
+ "priority": 7,
134
+ "wrapper": False,
135
+ "check_command": ["--version"],
136
+ "npm_package": "@qoder-ai/qodercli"
137
+ },
138
+ "iflow": {
139
+ "command": {
140
+ "windows": "iflow.cmd",
141
+ "linux": "iflow",
142
+ "darwin": "iflow"
143
+ },
144
+ "description": "iFlow智能助手",
145
+ "keywords": ["iflow", "智能", "助手", "心流"],
146
+ "priority": 8,
147
+ "wrapper": False,
148
+ "check_command": ["--version"],
149
+ "npm_package": "@iflow-ai/iflow-cli"
150
+ }
151
+ },
152
+ "route_keywords": ["用", "帮我", "请", "智能", "ai", "写", "生成", "解释", "分析", "翻译", "代码", "文章"],
153
+ "default_tool": "claude",
154
+ "fallback_strategy": "first_available",
155
+ "wrapper_scripts": {
156
+ "kimi_wrapper": "kimi_wrapper.py"
157
+ },
158
+ "output_formats": ["cmd", "powershell", "bash", "python"],
159
+ "install_global": False,
160
+ "enhanced_detection": True # 标记使用增强检测
161
+ }
162
+
163
+ if os.path.exists(self.config_file):
164
+ try:
165
+ with open(self.config_file, 'r', encoding='utf-8') as f:
166
+ user_config = json.load(f)
167
+ # 合并配置,用户配置优先
168
+ self._merge_config(default_config, user_config)
169
+ return default_config
170
+ except Exception as e:
171
+ print(f"⚠️ 配置文件加载失败,使用默认配置: {e}")
172
+
173
+ # 保存默认配置
174
+ self.save_config(default_config)
175
+ return default_config
176
+
177
+ def _merge_config(self, default, user):
178
+ """递归合并配置"""
179
+ for key, value in user.items():
180
+ if key in default:
181
+ if isinstance(default[key], dict) and isinstance(value, dict):
182
+ self._merge_config(default[key], value)
183
+ else:
184
+ default[key] = value
185
+ else:
186
+ default[key] = value
187
+
188
+ def save_config(self, config):
189
+ """保存配置"""
190
+ with open(self.config_file, 'w', encoding='utf-8') as f:
191
+ json.dump(config, f, ensure_ascii=False, indent=2)
192
+
193
+ def detect_with_npm(self, package_name: str, force_rescan=False) -> dict:
194
+ """
195
+ 使用npm检测包安装状态(文件重定向方式)
196
+
197
+ Args:
198
+ package_name: npm包名
199
+ force_rescan: 是否强制重新扫描(忽略缓存)
200
+
201
+ Returns:
202
+ 检测结果字典
203
+ """
204
+ # 如果不是强制重扫描,可以检查缓存
205
+ if not force_rescan:
206
+ # TODO: 实现简单的内存缓存机制
207
+ pass
208
+
209
+ with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.json', encoding='utf-8') as tmp_file:
210
+ temp_filename = tmp_file.name
211
+
212
+ try:
213
+ # 使用shell重定向方式运行npm命令
214
+ # 添加 --depth=0 选项确保只检查顶层包,避免扫描所有依赖
215
+ # 对于强制重扫描,我们确保每次都执行新命令
216
+ subprocess.run(f'npm list -g --depth=0 --json > "{temp_filename}"',
217
+ shell=True, capture_output=True, timeout=15)
218
+
219
+ # 检查文件是否存在且有内容
220
+ if os.path.exists(temp_filename):
221
+ with open(temp_filename, 'r', encoding='utf-8') as f:
222
+ content = f.read().strip()
223
+ if content:
224
+ packages = json.loads(content)
225
+ if 'dependencies' in packages:
226
+ for pkg_name, pkg_info in packages['dependencies'].items():
227
+ # 检查包名是否匹配
228
+ if pkg_name.lower() == package_name.lower():
229
+ version = pkg_info.get('version', 'unknown')
230
+ if not version or version == 'unknown':
231
+ version = pkg_info.get('resolved', 'unknown')
232
+
233
+ return {
234
+ 'installed': True,
235
+ 'version': version,
236
+ 'packageName': pkg_name,
237
+ 'installPath': pkg_info.get('resolved', 'unknown')
238
+ }
239
+
240
+ # 也检查部分匹配
241
+ if package_name.lower() in pkg_name.lower():
242
+ version = pkg_info.get('version', 'unknown')
243
+ if not version or version == 'unknown':
244
+ version = pkg_info.get('resolved', 'unknown')
245
+
246
+ return {
247
+ 'installed': True,
248
+ 'version': version,
249
+ 'packageName': pkg_name,
250
+ 'installPath': pkg_info.get('resolved', 'unknown')
251
+ }
252
+
253
+ return {
254
+ 'installed': False,
255
+ 'error': 'Package not found in npm global list'
256
+ }
257
+ except Exception as e:
258
+ return {
259
+ 'installed': False,
260
+ 'error': str(e)
261
+ }
262
+ finally:
263
+ # 清理临时文件
264
+ if os.path.exists(temp_filename):
265
+ os.unlink(temp_filename)
266
+
267
+ def detect_with_which(self, command: str, force_rescan=False) -> bool:
268
+ """使用which或where命令检测可执行文件
269
+
270
+ Args:
271
+ command: 要检测的命令
272
+ force_rescan: 是否强制重新扫描(忽略缓存)
273
+ """
274
+ # which/where命令通常不需要缓存,但可以在这里实现缓存逻辑
275
+ try:
276
+ if platform.system() == 'Windows':
277
+ result = subprocess.run(
278
+ ['where', command],
279
+ capture_output=True,
280
+ text=True,
281
+ timeout=5
282
+ )
283
+ else:
284
+ result = subprocess.run(
285
+ ['which', command],
286
+ capture_output=True,
287
+ text=True,
288
+ timeout=5
289
+ )
290
+
291
+ return result.returncode == 0
292
+ except:
293
+ return False
294
+
295
+ def discover_available_tools(self, force_rescan=False):
296
+ """发现可用工具 - 增强版,使用npm检测和命令检测双重机制
297
+
298
+ Args:
299
+ force_rescan: 是否强制重新扫描,清除缓存
300
+ """
301
+ available = {}
302
+ npm_results = {}
303
+
304
+ scan_type = "🔄 强制重新扫描" if force_rescan else "🔍 正在使用增强检测机制发现可用工具"
305
+ print(f"{scan_type}...")
306
+
307
+ for tool_name, tool_config in self.config["tools"].items():
308
+ print(f" 检测 {tool_name}...")
309
+
310
+ # 获取系统特定命令
311
+ command = tool_config["command"][self.system]
312
+ npm_package = tool_config.get("npm_package")
313
+
314
+ # 方法1: npm包检测(如果适用)
315
+ npm_installed = False
316
+ npm_version = None
317
+ if npm_package:
318
+ npm_result = self.detect_with_npm(npm_package, force_rescan)
319
+ npm_installed = npm_result.get('installed', False)
320
+ npm_version = npm_result.get('version', 'unknown')
321
+ npm_results[tool_name] = npm_result
322
+
323
+ if npm_installed:
324
+ print(f" npm: ✅ {npm_version}")
325
+
326
+ # 方法2: 命令行检测
327
+ cmd_installed = False
328
+ if tool_config.get("wrapper") and tool_config.get("wrapper_script"):
329
+ # 检查包装器脚本
330
+ wrapper_path = self.setup_dir / tool_config["wrapper_script"]
331
+ cmd_installed = wrapper_path.exists()
332
+ else:
333
+ # 检查命令是否存在
334
+ cmd_installed = self.detect_with_which(command.split()[0], force_rescan)
335
+
336
+ if cmd_installed:
337
+ print(f" cmd: ✅")
338
+
339
+ # 工具可用性:npm或命令行任一检测到即可
340
+ available[tool_name] = npm_installed or cmd_installed
341
+
342
+ print(f"📊 检测完成: {sum(1 for v in available.values() if v)}/{len(available)} 个工具可用")
343
+ return available
344
+
345
+ def generate_smart_router(self, cli_name, output_format="cmd"):
346
+ """生成智能路由器"""
347
+ available_tools = self.discover_available_tools()
348
+
349
+ if output_format == "cmd":
350
+ return self._generate_cmd_router(cli_name, available_tools)
351
+ elif output_format == "powershell":
352
+ return self._generate_powershell_router(cli_name, available_tools)
353
+ elif output_format == "bash":
354
+ return self._generate_bash_router(cli_name, available_tools)
355
+ elif output_format == "python":
356
+ return self._generate_python_router(cli_name, available_tools)
357
+ else:
358
+ raise ValueError(f"不支持的输出格式: {output_format}")
359
+
360
+ def _generate_cmd_router(self, cli_name, available_tools):
361
+ """生成CMD路由器"""
362
+ router_content = f'''@echo off
363
+ setlocal enabledelayedexpansion
364
+
365
+ :: 智能{cli_name}路由器 - 增强版
366
+ :: 系统: {self.system}
367
+ :: 可用工具: {list(available_tools.keys())}
368
+
369
+ set "USER_INPUT=%*"
370
+
371
+ if "%USER_INPUT%"=="" (
372
+ echo 🎯 智能{cli_name}路由器 - 增强版
373
+ echo 💡 原始功能: {cli_name} [参数]
374
+ echo 🤖 智能路由示例:
375
+ '''
376
+
377
+ # 添加可用工具的路由逻辑
378
+ for tool_name in sorted(available_tools.keys(),
379
+ key=lambda x: self.config["tools"][x].get("priority", 99) if x in self.config["tools"] else 99):
380
+ if available_tools[tool_name] and tool_name in self.config["tools"]:
381
+ keywords = self.config["tools"][tool_name]["keywords"]
382
+ keyword_pattern = "|".join(keywords)
383
+ router_content += f''' echo 智能{cli_name}.bat 用{keyword_pattern}
384
+ '''
385
+
386
+ router_content += f'''
387
+ exit /b
388
+ )
389
+
390
+ :: 智能路由检测
391
+ echo %USER_INPUT% | findstr /i "{" ".join(self.config["route_keywords"])}" >nul
392
+ if %errorlevel% neq 0 (
393
+ :: 不需要路由,执行原始命令
394
+ {cli_name} %USER_INPUT%
395
+ exit /b
396
+ )
397
+
398
+ '''
399
+
400
+ # 生成路由逻辑
401
+ for tool_name in sorted(available_tools.keys(),
402
+ key=lambda x: self.config["tools"][x].get("priority", 99) if x in self.config["tools"] else 99):
403
+ if available_tools[tool_name] and tool_name in self.config["tools"]:
404
+ keywords = self.config["tools"][tool_name]["keywords"]
405
+ command = self.config["tools"][tool_name]["command"][self.system]
406
+
407
+ router_content += f'''echo %USER_INPUT% | findstr /i "{" ".join(keywords)}" >nul
408
+ if !errorlevel! equ 0 (
409
+ echo 🚀 智能路由到: {self.config["tools"][tool_name]["description"]}
410
+ set "CLEAN_INPUT=!USER_INPUT!"
411
+ '''
412
+
413
+ for keyword in keywords:
414
+ router_content += f''' set "CLEAN_INPUT=!CLEAN_INPUT:{keyword}=!"
415
+ '''
416
+
417
+ router_content += f''' set "CLEAN_INPUT=!CLEAN_INPUT:用=!"
418
+ set "CLEAN_INPUT=!CLEAN_INPUT:帮我=!"
419
+ set "CLEAN_INPUT=!CLEAN_INPUT:请=!"
420
+ set "CLEAN_INPUT=!CLEAN_INPUT:写=!"
421
+ set "CLEAN_INPUT=!CLEAN_INPUT:生成=!"
422
+ set "CLEAN_INPUT=!CLEAN_INPUT:解释=!"
423
+ set "CLEAN_INPUT=!CLEAN_INPUT:分析=!"
424
+ set "CLEAN_INPUT=!CLEAN_INPUT:翻译=!"
425
+ set "CLEAN_INPUT=!CLEAN_INPUT:代码=!"
426
+ set "CLEAN_INPUT=!CLEAN_INPUT:文章=!"
427
+
428
+ '''
429
+
430
+ if self.config["tools"][tool_name].get("wrapper"):
431
+ wrapper_script = self.config["tools"][tool_name]["wrapper_script"]
432
+ router_content += f''' python {wrapper_script} "!CLEAN_INPUT!"
433
+ '''
434
+ else:
435
+ router_content += f''' {command} "!CLEAN_INPUT!"
436
+ '''
437
+
438
+ router_content += ''' exit /b
439
+ )
440
+ '''
441
+
442
+ # 默认路由
443
+ default_tool = self.config["default_tool"]
444
+ if default_tool in available_tools and default_tool in self.config["tools"]:
445
+ command = self.config["tools"][default_tool]["command"][self.system]
446
+ router_content += f'''
447
+ :: 默认路由到{self.config["tools"][default_tool]["description"]}
448
+ set "CLEAN_INPUT=!USER_INPUT!"
449
+ set "CLEAN_INPUT=!CLEAN_INPUT:用=!"
450
+ set "CLEAN_INPUT=!CLEAN_INPUT:帮我=!"
451
+ set "CLEAN_INPUT=!CLEAN_INPUT:请=!"
452
+ set "CLEAN_INPUT=!CLEAN_INPUT:写=!"
453
+ set "CLEAN_INPUT=!CLEAN_INPUT:生成=!"
454
+ set "CLEAN_INPUT=!CLEAN_INPUT:解释=!"
455
+ set "CLEAN_INPUT=!CLEAN_INPUT:分析=!"
456
+ set "CLEAN_INPUT=!CLEAN_INPUT:翻译=!"
457
+ set "CLEAN_INPUT=!CLEAN_INPUT:代码=!"
458
+ set "CLEAN_INPUT=!CLEAN_INPUT:文章=!"
459
+ {command} "!CLEAN_INPUT!"
460
+ '''
461
+ else:
462
+ router_content += f'''
463
+ :: 执行原始{cli_name}
464
+ {cli_name} %USER_INPUT%
465
+ '''
466
+
467
+ return router_content
468
+
469
+ def _generate_powershell_router(self, cli_name, available_tools):
470
+ """生成PowerShell路由器"""
471
+ router_content = f'''# 智能{cli_name}路由器 - PowerShell版 - 增强版
472
+ # 系统: {self.system}
473
+ # 可用工具: {list(available_tools.keys())}
474
+
475
+ param(
476
+ [string]$UserInput = ""
477
+ )
478
+
479
+ function SmartRoute {{
480
+ param([string]$Input)
481
+
482
+ $routeKeywords = @({', '.join([f'"{kw}"' for kw in self.config["route_keywords"]])})
483
+
484
+ foreach ($keyword in $routeKeywords) {{
485
+ if ($Input -like "*$keyword*") {{
486
+ return $true
487
+ }}
488
+ }}
489
+
490
+ return $false
491
+ }}
492
+
493
+ function Route-ToTool {{
494
+ param([string]$Input)
495
+ '''
496
+
497
+ # 生成路由逻辑
498
+ for tool_name in sorted(available_tools.keys(),
499
+ key=lambda x: self.config["tools"][x].get("priority", 99) if x in self.config["tools"] else 99):
500
+ if available_tools[tool_name] and tool_name in self.config["tools"]:
501
+ keywords = self.config["tools"][tool_name]["keywords"]
502
+ command = self.config["tools"][tool_name]["command"][self.system]
503
+
504
+ router_content += f'''
505
+ if ($Input -like "*{keywords[0]}*") {{
506
+ Write-Host "🚀 智能路由到: {self.config['tools'][tool_name]['description']}"
507
+ $cleanInput = $Input
508
+ '''
509
+
510
+ for keyword in keywords:
511
+ router_content += f''' $cleanInput = $cleanInput -replace "{keyword}", ""'''
512
+
513
+ router_content += ''' $cleanInput = $cleanInput -replace "^用", "" -replace "^帮我", "" -replace "^请", "" -replace "^写", "" -replace "^生成", "" -replace "^解释", "" -replace "^分析", "" -replace "^翻译", "" -replace "^代码", "" -replace "^文章", ""
514
+ '''
515
+
516
+ if self.config["tools"][tool_name].get("wrapper"):
517
+ wrapper_script = self.config["tools"][tool_name]["wrapper_script"]
518
+ router_content += f''' python {wrapper_script} $cleanInput.Trim()'''
519
+ else:
520
+ router_content += f''' {command} $cleanInput.Trim()'''
521
+
522
+ router_content += ''' return
523
+ }
524
+ '''
525
+
526
+ # 默认路由
527
+ default_tool = self.config["default_tool"]
528
+ if default_tool in available_tools and default_tool in self.config["tools"]:
529
+ command = self.config["tools"][default_tool]["command"][self.system]
530
+ router_content += f'''
531
+ # 默认路由到{self.config["tools"][default_tool]["description"]}
532
+ $cleanInput = $Input
533
+ $cleanInput = $cleanInput -replace "^用", "" -replace "^帮我", "" -replace "^请", "" -replace "^写", "" -replace "^生成", "" -replace "^解释", "" -replace "^分析", "" -replace "^翻译", "" -replace "^代码", "" -replace "^文章", ""
534
+ {command} $cleanInput.Trim()
535
+ '''
536
+ else:
537
+ router_content += f''' # 执行原始{cli_name}
538
+ {cli_name} $UserInput'''
539
+
540
+ router_content += '''
541
+ }
542
+
543
+ # 主逻辑
544
+ if (-not $UserInput) {{
545
+ Write-Host "🎯 智能{cli_name}路由器 - PowerShell版 - 增强版"
546
+ Write-Host "💡 原始功能: .\smart_{cli_name}.ps1 '参数'"
547
+ Write-Host "🤖 智能路由示例:"
548
+ '''
549
+
550
+ # 添加可用工具示例
551
+ for tool_name in sorted(available_tools.keys(),
552
+ key=lambda x: self.config["tools"][x].get("priority", 99) if x in self.config["tools"] else 99):
553
+ if available_tools[tool_name] and tool_name in self.config["tools"]:
554
+ keywords = self.config["tools"][tool_name]["keywords"]
555
+ router_content += f''' Write-Host " .\smart_{cli_name}.ps1 '用{keywords[0]}写代码'"
556
+ '''
557
+
558
+ router_content += ''' exit
559
+ }}
560
+
561
+ if (SmartRoute $UserInput) {{
562
+ Route-ToTool $UserInput
563
+ }} else {{
564
+ {cli_name} $UserInput
565
+ }}
566
+ '''
567
+
568
+ return router_content
569
+
570
+ def _generate_bash_router(self, cli_name, available_tools):
571
+ """生成Bash路由器 - 增强版"""
572
+ router_content = f'''#!/bin/bash
573
+ # 智能{cli_name}路由器 - Bash版 - 增强版
574
+ # 系统: {self.system}
575
+ # 可用工具: {list(available_tools.keys())}
576
+
577
+ USER_INPUT="$*"
578
+
579
+ # 检查是否需要智能路由
580
+ if [[ -z "$USER_INPUT" ]]; then
581
+ echo "🎯 智能{cli_name}路由器 - Bash版 - 增强版"
582
+ echo "💡 原始功能: ./smart_{cli_name}.sh '参数'"
583
+ echo "🤖 智能路由示例:"
584
+ '''
585
+
586
+ # 添加可用工具示例
587
+ for tool_name in sorted(available_tools.keys(),
588
+ key=lambda x: self.config["tools"][x].get("priority", 99) if x in self.config["tools"] else 99):
589
+ if available_tools[tool_name] and tool_name in self.config["tools"]:
590
+ keywords = self.config["tools"][tool_name]["keywords"]
591
+ router_content += f''' echo " ./smart_{cli_name}.sh '用{keywords[0]}写代码'"
592
+ '''
593
+
594
+ router_content += ''' exit 0
595
+ fi
596
+
597
+ # 智能路由检测
598
+ ROUTE_KEYWORDS="用 帮我 请 智能 ai 写 生成 解释 分析 翻译 代码 文章"
599
+ NEEDS_ROUTE=false
600
+
601
+ for keyword in $ROUTE_KEYWORDS; do
602
+ if echo "$USER_INPUT" | grep -qi "$keyword"; then
603
+ NEEDS_ROUTE=true
604
+ break
605
+ fi
606
+ done
607
+
608
+ if [ "$NEEDS_ROUTE" = false ]; then
609
+ # 不需要路由,执行原始命令
610
+ {cli_name} $USER_INPUT
611
+ exit 0
612
+ fi
613
+
614
+ # 智能路由逻辑
615
+ '''
616
+
617
+ # 生成路由逻辑
618
+ for tool_name in sorted(available_tools.keys(),
619
+ key=lambda x: self.config["tools"][x].get("priority", 99) if x in self.config["tools"] else 99):
620
+ if available_tools[tool_name] and tool_name in self.config["tools"]:
621
+ keywords = self.config["tools"][tool_name]["keywords"]
622
+ command = self.config["tools"][tool_name]["command"][self.system]
623
+
624
+ router_content += f'''
625
+ if echo "$USER_INPUT" | grep -qi "{keywords[0]}"; then
626
+ echo "🚀 智能路由到: {self.config["tools"][tool_name]["description"]}"
627
+ CLEAN_INPUT=$(echo "$USER_INPUT" | sed 's/{keywords[0]}//g' | sed 's/^用\s*//' | sed 's/^帮我\s*//' | sed 's/^请\s*//' | sed 's/^写\s*//' | sed 's/^生成\s*//' | sed 's/^解释\s*//' | sed 's/^分析\s*//' | sed 's/^翻译\s*//' | sed 's/^代码\s*//' | sed 's/^文章\s*//')
628
+ '''
629
+
630
+ if self.config["tools"][tool_name].get("wrapper"):
631
+ wrapper_script = self.config["tools"][tool_name]["wrapper_script"]
632
+ router_content += f''' python {wrapper_script} "$CLEAN_INPUT"'''
633
+ else:
634
+ router_content += f''' {command} "$CLEAN_INPUT"'''
635
+
636
+ router_content += ''' exit 0
637
+ fi
638
+ '''
639
+
640
+ # 默认路由
641
+ default_tool = self.config["default_tool"]
642
+ if default_tool in available_tools and default_tool in self.config["tools"]:
643
+ command = self.config["tools"][default_tool]["command"][self.system]
644
+ router_content += f'''
645
+ # 默认路由到{self.config["tools"][default_tool]["description"]}
646
+ echo "🚀 智能路由到: {self.config["tools"][default_tool]["description"]}"
647
+ CLEAN_INPUT=$(echo "$USER_INPUT" | sed 's/^用\s*//' | sed 's/^帮我\s*//' | sed 's/^请\s*//' | sed 's/^写\s*//' | sed 's/^生成\s*//' | sed 's/^解释\s*//' | sed 's/^分析\s*//' | sed 's/^翻译\s*//' | sed 's/^代码\s*//' | sed 's/^文章\s*//')
648
+ {command} "$CLEAN_INPUT"
649
+ '''
650
+ else:
651
+ router_content += f'''# 执行原始{cli_name}
652
+ {cli_name} "$USER_INPUT"
653
+ '''
654
+
655
+ return router_content
656
+
657
+ def _generate_python_router(self, cli_name, available_tools):
658
+ """生成Python路由器 - 增强版"""
659
+ router_content = f'''#!/usr/bin/env python3
660
+ # -*- coding: utf-8 -*-
661
+ """
662
+ 智能{cli_name}路由器 - Python版 - 增强版
663
+ 系统: {self.system}
664
+ 可用工具: {list(available_tools.keys())}
665
+ 检测方式: npm包管理器 + 命令行双重检测
666
+ """
667
+
668
+ import sys
669
+ import subprocess
670
+ import re
671
+ import os
672
+
673
+ class SmartRouter:
674
+ def __init__(self):
675
+ self.cli_name = "{cli_name}"
676
+ self.available_tools = {repr(available_tools)}
677
+ self.tools = {repr({k: v for k, v in self.config["tools"].items() if k in available_tools and v.get("installed", True)})}
678
+ self.route_keywords = {repr(self.config["route_keywords"])}
679
+ self.default_tool = "{self.config["default_tool"]}"
680
+
681
+ def should_route(self, user_input):
682
+ """检查是否需要智能路由"""
683
+ return any(keyword.lower() in user_input.lower() for keyword in self.route_keywords)
684
+
685
+ def smart_route(self, user_input):
686
+ """智能路由到合适的工具"""
687
+ user_input = user_input.strip()
688
+
689
+ # 检测工具关键词
690
+ for tool_name, tool_info in self.tools.items():
691
+ for keyword in tool_info["keywords"]:
692
+ if keyword.lower() in user_input.lower():
693
+ # 提取参数
694
+ clean_input = re.sub(rf'.*{{keyword}}\\s*', '', user_input, flags=re.IGNORECASE).strip()
695
+ clean_input = re.sub(r'^(用|帮我|请|麻烦|给我|帮我写|帮我生成)\\s*', '', clean_input, flags=re.IGNORECASE).strip()
696
+ return tool_name, [clean_input] if clean_input else []
697
+
698
+ # 默认路由
699
+ clean_input = re.sub(r'^(用|帮我|请|麻烦|给我|帮我写|帮我生成)\\s*', '', user_input, flags=re.IGNORECASE).strip()
700
+ return self.default_tool, [clean_input] if clean_input else []
701
+
702
+ def execute_tool(self, tool_name, args):
703
+ """执行工具"""
704
+ if tool_name not in self.tools:
705
+ return 1, "", f"未知工具: {{tool_name}}"
706
+
707
+ tool_info = self.tools[tool_name]
708
+ command = tool_info["command"]["{self.system}"]
709
+
710
+ if tool_info.get("wrapper"):
711
+ wrapper_script = tool_info.get("wrapper_script")
712
+ cmd = ["python", wrapper_script] + args
713
+ else:
714
+ cmd = [command] + args
715
+
716
+ try:
717
+ result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8', timeout=60)
718
+ return result.returncode, result.stdout, result.stderr
719
+ except Exception as e:
720
+ return -1, "", f"执行失败: {{e}}"
721
+
722
+ def execute_original_cli(self, args):
723
+ """执行原始CLI"""
724
+ try:
725
+ cmd = ["{cli_name}"] + args
726
+ result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
727
+ return result.returncode, result.stdout, result.stderr
728
+ except Exception as e:
729
+ return -1, "", f"原始CLI执行失败: {{e}}"
730
+
731
+ def main():
732
+ router = SmartRouter()
733
+
734
+ if len(sys.argv) < 2:
735
+ print("🎯 智能{{cli_name}}路由器 - Python版 - 增强版")
736
+ print("💡 原始功能: python smart_{cli_name}.py '参数'")
737
+ print("🤖 智能路由示例:")
738
+ '''
739
+
740
+ # 添加可用工具示例
741
+ for tool_name in sorted(available_tools.keys(),
742
+ key=lambda x: self.config["tools"][x].get("priority", 99) if x in self.config["tools"] else 99):
743
+ if available_tools[tool_name] and tool_name in self.config["tools"]:
744
+ keywords = self.config["tools"][tool_name]["keywords"]
745
+ router_content += f''' print(" python smart_{cli_name}.py '用{keywords[0]}写代码'")
746
+ '''
747
+
748
+ router_content += ''' return 0
749
+
750
+ user_input = ' '.join(sys.argv[1:])
751
+
752
+ if router.should_route(user_input):
753
+ tool_name, args = router.smart_route(user_input)
754
+ if tool_name and tool_name != router.cli_name:
755
+ print(f"🚀 智能路由到: {{router.tools[tool_name]['description']}}")
756
+ returncode, stdout, stderr = router.execute_tool(tool_name, args)
757
+ if stdout:
758
+ print(stdout)
759
+ if stderr:
760
+ print(stderr, file=sys.stderr)
761
+ sys.exit(returncode)
762
+
763
+ # 执行原始CLI
764
+ returncode, stdout, stderr = router.execute_original_cli(sys.argv[1:])
765
+ if stdout:
766
+ print(stdout)
767
+ if stderr:
768
+ print(stderr, file=sys.stderr)
769
+ sys.exit(returncode)
770
+
771
+ if __name__ == "__main__":
772
+ main()
773
+ '''
774
+
775
+ return router_content
776
+
777
+ def enhanced_setup_environment(self, refresh_after_install=True):
778
+ """增强环境设置"""
779
+ print(f"🚀 开始增强环境设置...")
780
+
781
+ # 检测所有工具
782
+ available_tools = self.discover_available_tools()
783
+
784
+ # 生成所有增强路由器
785
+ formats = self.config.get("output_formats", ["cmd", "powershell", "bash", "python"])
786
+
787
+ print(f"🔧 为 {len(available_tools)} 个可用工具生成增强路由器...")
788
+
789
+ for tool_name in available_tools:
790
+ if available_tools[tool_name]:
791
+ print(f" 生成 {tool_name} 路由器...")
792
+ for fmt in formats:
793
+ try:
794
+ content = self.generate_smart_router(tool_name, fmt)
795
+ filename = f"smart_{tool_name}.{fmt if fmt != 'python' else 'py'}"
796
+ with open(filename, 'w', encoding='utf-8') as f:
797
+ f.write(content)
798
+ print(f" ✅ {filename}")
799
+ except Exception as e:
800
+ print(f" ❌ 生成 {tool_name}.{fmt} 失败: {e}")
801
+
802
+ print(f"✅ 增强环境设置完成!")
803
+
804
+ # 保存增强检测报告
805
+ self.save_enhanced_report(available_tools)
806
+
807
+ def refresh_tools_and_configure(self):
808
+ """刷新工具列表并配置插件 - 用于CLI安装后重新扫描"""
809
+ print("🔄 刷新工具列表...")
810
+
811
+ # 强制重新扫描所有工具
812
+ refreshed_tools = self.discover_available_tools(force_rescan=True)
813
+
814
+ print(f"🔧 发现 {len(refreshed_tools)} 个工具,配置插件...")
815
+
816
+ # 重新配置插件/路由器
817
+ formats = self.config.get("output_formats", ["cmd", "powershell", "bash", "python"])
818
+
819
+ for tool_name in refreshed_tools:
820
+ if refreshed_tools[tool_name]:
821
+ print(f" 为新安装的 {tool_name} 配置插件...")
822
+ for fmt in formats:
823
+ try:
824
+ content = self.generate_smart_router(tool_name, fmt)
825
+ filename = f"smart_{tool_name}.{fmt if fmt != 'python' else 'py'}"
826
+ with open(filename, 'w', encoding='utf-8') as f:
827
+ f.write(content)
828
+ print(f" ✅ {filename}")
829
+ except Exception as e:
830
+ print(f" ❌ 配置 {tool_name}.{fmt} 失败: {e}")
831
+
832
+ print("✅ 插件配置完成!")
833
+ return refreshed_tools
834
+
835
+ def save_enhanced_report(self, available_tools):
836
+ """保存增强检测报告"""
837
+ report = {
838
+ "timestamp": str(Path.cwd()),
839
+ "system": self.system,
840
+ "config_file": self.config_file,
841
+ "enhanced_detection": True,
842
+ "available_tools": available_tools,
843
+ "setup_directory": str(self.setup_dir),
844
+ "detected_using_npm": [tool for tool, available in available_tools.items() if available],
845
+ "enhancement_features": [
846
+ "npm package detection",
847
+ "dual detection mechanism",
848
+ "enhanced routers generation",
849
+ "improved accuracy"
850
+ ]
851
+ }
852
+
853
+ report_file = self.setup_dir / "enhanced_setup_report.json"
854
+ with open(report_file, 'w', encoding='utf-8') as f:
855
+ json.dump(report, f, ensure_ascii=False, indent=2)
856
+
857
+ print(f"📊 增强检测报告已保存: {report_file}")
858
+
859
+
860
+ def main():
861
+ """主函数"""
862
+ import argparse
863
+
864
+ parser = argparse.ArgumentParser(description="增强版通用CLI智能路由自动化部署脚本")
865
+ parser.add_argument("--setup", action="store_true", help="运行增强设置")
866
+ parser.add_argument("--cli", help="指定CLI名称")
867
+ parser.add_argument("--format", choices=["cmd", "powershell", "bash", "python"], default="cmd", help="输出格式")
868
+ parser.add_argument("--all", action="store_true", help="为所有工具生成路由器")
869
+ parser.add_argument("--detect", action="store_true", help="仅运行检测")
870
+ parser.add_argument("--enhanced", action="store_true", help="使用增强检测")
871
+ parser.add_argument("--list-tools", action="store_true", help="列出所有工具")
872
+
873
+ args = parser.parse_args()
874
+
875
+ setup = EnhancedCLISetup()
876
+
877
+ if args.enhanced or args.setup:
878
+ setup.enhanced_setup_environment()
879
+ elif args.detect:
880
+ tools = setup.discover_available_tools()
881
+ print("\n🔍 检测结果:")
882
+ for tool, available in tools.items():
883
+ status = "✅" if available else "❌"
884
+ config = setup.config["tools"].get(tool, {})
885
+ desc = config.get("description", tool)
886
+ print(f" {status} {tool}: {desc}")
887
+ print(f"\n总计: {sum(1 for v in tools.values() if v)}/{len(tools)} 个工具可用")
888
+ elif args.list_tools:
889
+ print("📋 配置的工具:")
890
+ for tool_name, config in setup.config["tools"].items():
891
+ desc = config.get("description", tool_name)
892
+ npm_pkg = config.get("npm_package", "N/A")
893
+ print(f" - {tool_name}: {desc} (npm: {npm_pkg})")
894
+ elif args.all:
895
+ available_tools = setup.discover_available_tools()
896
+ formats = setup.config.get("output_formats", ["cmd", "powershell", "bash", "python"])
897
+
898
+ for tool_name in available_tools:
899
+ if available_tools[tool_name]:
900
+ for fmt in formats:
901
+ try:
902
+ content = setup.generate_smart_router(tool_name, fmt)
903
+ filename = f"smart_{tool_name}.{fmt if fmt != 'python' else 'py'}"
904
+ with open(filename, 'w', encoding='utf-8') as f:
905
+ f.write(content)
906
+ print(f"✅ 生成: {filename}")
907
+ except Exception as e:
908
+ print(f"❌ 生成 {tool_name}.{fmt} 失败: {e}")
909
+ elif args.cli:
910
+ try:
911
+ content = setup.generate_smart_router(args.cli, args.format)
912
+ filename = f"smart_{args.cli}.{args.format if args.format != 'python' else 'py'}"
913
+ with open(filename, 'w', encoding='utf-8') as f:
914
+ f.write(content)
915
+ print(f"✅ 智能路由器已创建: {filename}")
916
+ print(f"📝 使用: {filename} '用kimi写代码'")
917
+ except Exception as e:
918
+ print(f"❌ 创建失败: {e}")
919
+ else:
920
+ print("🎯 增强版通用CLI智能路由自动化部署脚本")
921
+ print("💡 使用方法:")
922
+ print(" python enhanced_universal_cli_setup.py --setup # 运行增强设置")
923
+ print(" python enhanced_universal_cli_setup.py --detect # 仅检测工具")
924
+ print(" python enhanced_universal_cli_setup.py --cli mytool # 为特定工具创建路由器")
925
+ print(" python enhanced_universal_cli_setup.py --all # 为所有工具创建路由器")
926
+ print(" python enhanced_universal_cli_setup.py --list-tools # 列出所有工具")
927
+
928
+
929
+ if __name__ == "__main__":
930
+ main()