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,958 @@
1
+ """
2
+ 真实CLI Hook系统 - 基于已安装CLI的直接Hook和调用
3
+ 严格基于真实研究,严禁推测
4
+ """
5
+
6
+ import os
7
+ import sys
8
+ import json
9
+ import subprocess
10
+ import time
11
+ import signal
12
+ from pathlib import Path
13
+ from typing import Dict, List, Optional, Any, Callable
14
+ from dataclasses import dataclass, asdict
15
+ from datetime import datetime
16
+ import threading
17
+ from concurrent.futures import ThreadPoolExecutor
18
+
19
+ # 导入跨CLI调用系统
20
+ sys.path.append(str(Path(__file__).parent))
21
+ from real_cross_cli_system import RealCrossCLISystem
22
+
23
+ @dataclass
24
+ class CLIHookEvent:
25
+ """CLI Hook事件"""
26
+ timestamp: str
27
+ source_cli: str
28
+ event_type: str # 'input', 'output', 'command', 'cross_cli_intent'
29
+ content: str
30
+ working_directory: str
31
+ user_intent: Optional[str] = None
32
+ target_clis: List[str] = None
33
+ confidence: float = 0.0
34
+ detected_pattern: Optional[str] = None
35
+
36
+ class DirectCLIHookManager:
37
+ """直接CLI Hook管理器 - 基于已安装CLI的真实Hook"""
38
+
39
+ def __init__(self, hook_dir: str = None):
40
+ self.hook_dir = Path(hook_dir or Path.home() / '.direct_cli_hooks')
41
+ self.hook_dir.mkdir(parents=True, exist_ok=True)
42
+
43
+ # 跨CLI调用系统
44
+ self.cross_system = RealCrossCLISystem()
45
+
46
+ # Hook配置文件
47
+ self.hook_config_file = self.hook_dir / 'hook_config.json'
48
+ self.event_log_file = self.hook_dir / 'hook_events.json'
49
+ self.intercept_patterns_file = self.hook_dir / 'intercept_patterns.json'
50
+ self.hook_scripts_dir = self.hook_dir / 'hook_scripts'
51
+ self.hook_scripts_dir.mkdir(exist_ok=True)
52
+
53
+ # 运行时状态
54
+ self.active_hooks = {}
55
+ self.event_processors = {}
56
+ self.pattern_matchers = {}
57
+
58
+ self._initialize_hooks()
59
+
60
+ def _initialize_hooks(self):
61
+ """初始化Hook系统"""
62
+ # 初始化配置
63
+ if not self.hook_config_file.exists():
64
+ config = {
65
+ 'enabled_hooks': ['shell_interception', 'intent_detection', 'auto_cross_call'],
66
+ 'detection_confidence_threshold': 0.7,
67
+ 'auto_cross_call_enabled': True,
68
+ 'supported_clis': list(self.cross_system.cli_methods.keys()),
69
+ 'hook_timeout': 30,
70
+ 'max_concurrent_hooks': 5,
71
+ 'shell_integration': True,
72
+ 'version': '1.0.0'
73
+ }
74
+ self._safe_write_json(self.hook_config_file, config)
75
+
76
+ # 初始化拦截模式
77
+ if not self.intercept_patterns_file.exists():
78
+ patterns = {
79
+ 'cross_cli_patterns': [
80
+ r'(?:call|invoke|use|run|execute|ask|tell|request)\s+(?:the\s+)?([a-z]+)\s+(?:cli|tool|assistant|ai)',
81
+ r'(?:with|using|via|through)\s+([a-z]+)',
82
+ r'(?:let|have|can|should)\s+([a-z]+)\s+(?:help|assist|process|handle|deal)',
83
+ r'(?:switch|change|switch to)\s+([a-z]+)',
84
+ r'(?:in|using)\s+([a-z]+)\s+(?:mode|context)',
85
+ ],
86
+ 'intent_keywords': {
87
+ 'code_generation': [
88
+ 'generate', 'create', 'write', 'build', 'develop', 'implement', 'make', 'produce'
89
+ ],
90
+ 'code_analysis': [
91
+ 'analyze', 'review', 'check', 'examine', 'inspect', 'audit', 'look at', 'scan'
92
+ ],
93
+ 'debugging': [
94
+ 'fix', 'debug', 'repair', 'solve', 'resolve', 'troubleshoot', 'correct'
95
+ ],
96
+ 'documentation': [
97
+ 'document', 'explain', 'describe', 'comment', 'manual', 'guide'
98
+ ],
99
+ 'optimization': [
100
+ 'optimize', 'improve', 'refactor', 'enhance', 'better', 'faster'
101
+ ],
102
+ 'testing': [
103
+ 'test', 'validate', 'verify', 'check', 'run tests'
104
+ ]
105
+ },
106
+ 'cli_aliases': {
107
+ 'claude': ['claude', 'anthropic', 'ai-assistant'],
108
+ 'gemini': ['gemini', 'google', 'bard'],
109
+ 'copilot': ['copilot', 'github', 'gh'],
110
+ 'iflow': ['iflow', 'flow', 'mindflow'],
111
+ 'qwencode': ['qwencode', 'qwen', 'alibaba'],
112
+ 'qoder': ['qoder', 'code-assistant'],
113
+ 'codebuddy': ['codebuddy', 'tencent', 'buddy'],
114
+ 'codex': ['codex', 'openai', 'gpt']
115
+ },
116
+ 'version': '1.0.0'
117
+ }
118
+ self._safe_write_json(self.intercept_patterns_file, patterns)
119
+
120
+ # 加载配置
121
+ self._load_configurations()
122
+
123
+ def _load_configurations(self):
124
+ """加载配置文件"""
125
+ try:
126
+ with open(self.hook_config_file, 'r', encoding='utf-8') as f:
127
+ self.config = json.load(f)
128
+ except:
129
+ self.config = {'enabled_hooks': [], 'supported_clis': []}
130
+
131
+ try:
132
+ with open(self.intercept_patterns_file, 'r', encoding='utf-8') as f:
133
+ patterns = json.load(f)
134
+ self.cross_cli_patterns = patterns.get('cross_cli_patterns', [])
135
+ self.intent_keywords = patterns.get('intent_keywords', {})
136
+ self.cli_aliases = patterns.get('cli_aliases', {})
137
+ except:
138
+ self.cross_cli_patterns = []
139
+ self.intent_keywords = {}
140
+ self.cli_aliases = {}
141
+
142
+ def install_shell_hooks(self) -> Dict[str, Any]:
143
+ """安装Shell级别Hook - 不修改CLI本身,Hook Shell输入"""
144
+ result = {
145
+ 'success': False,
146
+ 'message': '',
147
+ 'installed_hooks': [],
148
+ 'shell_type': '',
149
+ 'integration_method': ''
150
+ }
151
+
152
+ try:
153
+ # 检测Shell类型
154
+ shell_type = self._detect_shell_type()
155
+
156
+ if shell_type == 'bash':
157
+ hooks = self._install_bash_hooks()
158
+ elif shell_type == 'zsh':
159
+ hooks = self._install_zsh_hooks()
160
+ elif shell_type == 'powershell':
161
+ hooks = self._install_powershell_hooks()
162
+ elif shell_type == 'cmd':
163
+ hooks = self._install_cmd_hooks()
164
+ else:
165
+ hooks = self._install_generic_hooks()
166
+
167
+ result.update({
168
+ 'success': True,
169
+ 'message': f"Successfully installed Shell hooks for {shell_type}",
170
+ 'installed_hooks': hooks,
171
+ 'shell_type': shell_type,
172
+ 'integration_method': 'shell_function_interception'
173
+ })
174
+
175
+ # 注册事件处理器
176
+ self._register_event_processors()
177
+
178
+ except Exception as e:
179
+ result['message'] = f"Hook installation failed: {str(e)}"
180
+
181
+ return result
182
+
183
+ def _detect_shell_type(self) -> str:
184
+ """检测当前Shell类型"""
185
+ shell = os.environ.get('SHELL', '').lower()
186
+
187
+ if 'bash' in shell:
188
+ return 'bash'
189
+ elif 'zsh' in shell:
190
+ return 'zsh'
191
+ elif 'powershell' in shell or 'pwsh' in shell:
192
+ return 'powershell'
193
+ elif 'cmd' in shell or os.name == 'nt':
194
+ return 'cmd'
195
+ else:
196
+ return 'generic'
197
+
198
+ def _install_bash_hooks(self) -> List[str]:
199
+ """安装Bash Hook"""
200
+ hooks = []
201
+
202
+ # 创建Bash Hook函数
203
+ bash_hook_content = f'''#!/bin/bash
204
+ # Direct CLI Hook System for Bash
205
+
206
+ # Hook配置目录
207
+ HOOK_DIR="{self.hook_dir}"
208
+ EVENT_LOG="$HOOK_DIR/hook_events.json"
209
+
210
+ # 记录Hook事件
211
+ log_hook_event() {{
212
+ local event_type="$1"
213
+ local content="$2"
214
+ local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
215
+ local working_dir=$(pwd)
216
+
217
+ # 创建事件JSON
218
+ local event='{{'
219
+ event+='"timestamp":"'"$timestamp"'",'
220
+ event+='"source_cli":"shell",'
221
+ event+='"event_type":"'"$event_type"'",'
222
+ event+='"content":"'"$content"'",'
223
+ event+='"working_directory":"'"$working_dir"'"'
224
+ event+='}}'
225
+
226
+ # 添加到事件日志
227
+ echo "$event" >> "$EVENT_LOG.tmp"
228
+
229
+ # 检测跨CLI意图
230
+ if [[ "$event_type" == "input" ]]; then
231
+ detect_cross_cli_intent "$content" &
232
+ fi
233
+ }}
234
+
235
+ # 检测跨CLI意图
236
+ detect_cross_cli_intent() {{
237
+ local input="$1"
238
+ local intent_file="$HOOK_DIR/intent_detection.tmp"
239
+
240
+ # 调用Python脚本进行意图检测
241
+ echo "$input" | python3 "{Path(__file__).parent}/intent_detector.py" "$intent_file" &
242
+
243
+ # 等待检测结果
244
+ wait
245
+
246
+ if [[ -f "$intent_file" ]]; then
247
+ local detection=$(cat "$intent_file")
248
+ if [[ "$detection" != "none" ]]; then
249
+ echo "🔗 检测到跨CLI协作意图: $detection"
250
+
251
+ # 触发跨CLI调用(如果启用)
252
+ if {str(self.config.get('auto_cross_call_enabled', False)).lower()}; then
253
+ execute_cross_cli_call "$input" "$detection" &
254
+ fi
255
+ fi
256
+ rm -f "$intent_file"
257
+ fi
258
+ }}
259
+
260
+ # 执行跨CLI调用
261
+ execute_cross_cli_call() {{
262
+ local input="$1"
263
+ local detection="$2"
264
+ local python_script="{Path(__file__).parent}/cross_cli_executor.py"
265
+
266
+ # 调用Python执行器
267
+ python3 "$python_script" --shell-input "$input" --target-cli "$detection" &
268
+ }}
269
+
270
+ # Hook命令执行
271
+ hook_command_execution() {{
272
+ local command="$*"
273
+
274
+ # 记录输入事件
275
+ log_hook_event "input" "$command"
276
+
277
+ # 执行原始命令
278
+ eval "$command"
279
+ local exit_code=$?
280
+
281
+ # 记录输出事件
282
+ log_hook_event "output" "Command completed with exit code: $exit_code"
283
+
284
+ return $exit_code
285
+ }}
286
+
287
+ # Shell集成:重写命令执行函数
288
+ if [[ "{self.config.get('shell_integration', True)}" == "True" ]]; then
289
+ # 创建alias来hook常见命令
290
+ alias {self.config.get('hooked_commands', ['echo', 'cat', 'ls'])[0]}='hook_command_execution {self.config.get('hooked_commands', ['echo', 'cat', 'ls'])[0]}'
291
+
292
+ # 重写PROMPT_COMMAND来捕获命令
293
+ if [[ -z "$PROMPT_COMMAND" ]]; then
294
+ PROMPT_COMMAND="log_hook_event prompt \$PWD"
295
+ else
296
+ PROMPT_COMMAND="$PROMPT_COMMAND; log_hook_event prompt \$PWD"
297
+ fi
298
+ fi
299
+ '''
300
+
301
+ bash_hook_file = self.hook_scripts_dir / 'bash_hooks.sh'
302
+ self._safe_write_file(bash_hook_file, bash_hook_content)
303
+ hooks.append(f"bash_hook_script: {bash_hook_file}")
304
+
305
+ # 创建加载脚本
306
+ loader_content = f'''#!/bin/bash
307
+ # Load Direct CLI Hooks
308
+
309
+ if [[ -f "{bash_hook_file}" ]]; then
310
+ source "{bash_hook_file}"
311
+ echo "✅ Direct CLI Hooks loaded in Bash"
312
+ else
313
+ echo "❌ Hook file not found: {bash_hook_file}"
314
+ fi
315
+ '''
316
+
317
+ loader_file = self.hook_scripts_dir / 'load_bash_hooks.sh'
318
+ self._safe_write_file(loader_file, loader_content)
319
+ hooks.append(f"bash_loader: {loader_file}")
320
+
321
+ return hooks
322
+
323
+ def _install_powershell_hooks(self) -> List[str]:
324
+ """安装PowerShell Hook"""
325
+ hooks = []
326
+
327
+ ps_hook_content = f'''# Direct CLI Hook System for PowerShell
328
+
329
+ # Hook配置
330
+ $Global:HookDir = "{self.hook_dir}"
331
+ $Global:EventLog = Join-Path $HookDir "hook_events.json"
332
+
333
+ # 记录Hook事件
334
+ function Log-HookEvent {{
335
+ param(
336
+ [string]$EventType,
337
+ [string]$Content
338
+ )
339
+
340
+ $timestamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffZ"
341
+ $workingDir = Get-Location
342
+
343
+ $event = @{{
344
+ timestamp = $timestamp
345
+ source_cli = "powershell"
346
+ event_type = $EventType
347
+ content = $Content
348
+ working_directory = $workingDir
349
+ }}
350
+
351
+ $eventJson = $event | ConvertTo-Json -Compress
352
+ Add-Content -Path "$($Global:EventLog).tmp" -Value $eventJson
353
+
354
+ # 检测跨CLI意图
355
+ if ($EventType -eq "input") {{
356
+ Detect-CrossCLIIntent -Input $Content
357
+ }}
358
+ }}
359
+
360
+ # 检测跨CLI意图
361
+ function Detect-CrossCLIIntent {{
362
+ param([string]$Input)
363
+
364
+ $intentFile = Join-Path $Global:HookDir "intent_detection.tmp"
365
+ $pythonScript = "{Path(__file__).parent}/intent_detector.py"
366
+
367
+ try {{
368
+ $Input | python3 $pythonScript $intentFile
369
+ if (Test-Path $intentFile) {{
370
+ $detection = Get-Content $intentFile
371
+ if ($detection -ne "none") {{
372
+ Write-Host "🔗 检测到跨CLI协作意图: $detection" -ForegroundColor Green
373
+
374
+ if ({str(self.config.get('auto_cross_call_enabled', False)).lower()}) {{
375
+ Execute-CrossCLICall -Input $Input -TargetCLI $detection
376
+ }}
377
+ }}
378
+ Remove-Item $intentFile -ErrorAction SilentlyContinue
379
+ }}
380
+ }} catch {{
381
+ # 意图检测失败,继续执行
382
+ }}
383
+ }}
384
+
385
+ # 执行跨CLI调用
386
+ function Execute-CrossCLICall {{
387
+ param(
388
+ [string]$Input,
389
+ [string]$TargetCLI
390
+ )
391
+
392
+ $pythonScript = "{Path(__file__).parent}/cross_cli_executor.py"
393
+
394
+ Start-Job -ScriptBlock {{
395
+ param($Script, $Input, $Target)
396
+ & python3 $Script --shell-input $Input --target-cli $Target
397
+ }} -ArgumentList $pythonScript, $Input, $TargetCLI | Out-Null
398
+ }}
399
+
400
+ # Hook命令执行
401
+ function Invoke-OriginalCommand {{
402
+ param([string]$Command)
403
+
404
+ # 记录输入事件
405
+ Log-HookEvent -EventType "input" -Content $Command
406
+
407
+ # 执行原始命令
408
+ try {{
409
+ $result = Invoke-Expression $Command
410
+ $exitCode = $LASTEXITCODE
411
+
412
+ # 记录输出事件
413
+ Log-HookEvent -EventType "output" -Content "Command completed with exit code: $exitCode"
414
+
415
+ return $result
416
+ }} catch {{
417
+ Log-HookEvent -EventType "error" -Content "Command failed: $($_.Exception.Message)"
418
+ throw
419
+ }}
420
+ }}
421
+
422
+ # PowerShell集成
423
+ if ({str(self.config.get('shell_integration', True)).lower()}) {{
424
+ # 重写一些常用的PowerShell命令
425
+ Set-Alias -Name hooked-echo -Value Invoke-OriginalCommand
426
+
427
+ # 添加到PowerShell Profile
428
+ $profilePath = $PROFILE.CurrentUserAllHosts
429
+ if (-not (Test-Path $profilePath)) {{
430
+ New-Item -ItemType File -Path $profilePath -Force
431
+ }}
432
+
433
+ # 避免重复加载
434
+ $hookLine = "# Direct CLI Hooks loaded"
435
+ $profileContent = Get-Content $profilePath -ErrorAction SilentlyContinue
436
+ if ($hookLine -notin $profileContent) {{
437
+ Add-Content -Path $profilePath -Value @"
438
+ # Direct CLI Hooks - Auto-generated
439
+ $hookLine
440
+ if (Test-Path "{self.hook_scripts_dir}/powershell_hooks.ps1") {{
441
+ . "{self.hook_scripts_dir}/powershell_hooks.ps1"
442
+ Write-Host "✅ Direct CLI Hooks loaded in PowerShell" -ForegroundColor Green
443
+ }}
444
+ "@
445
+ }}
446
+ }}
447
+ '''
448
+
449
+ ps_hook_file = self.hook_scripts_dir / 'powershell_hooks.ps1'
450
+ self._safe_write_file(ps_hook_file, ps_hook_content)
451
+ hooks.append(f"powershell_hook_script: {ps_hook_file}")
452
+
453
+ return hooks
454
+
455
+ def _install_zsh_hooks(self) -> List[str]:
456
+ """安装Zsh Hook"""
457
+ hooks = []
458
+
459
+ zsh_hook_content = f'''#!/bin/zsh
460
+ # Direct CLI Hook System for Zsh
461
+
462
+ # Hook配置目录
463
+ HOOK_DIR="{self.hook_dir}"
464
+ EVENT_LOG="$HOOK_DIR/hook_events.json"
465
+
466
+ # 记录Hook事件
467
+ log_hook_event() {{
468
+ local event_type="$1"
469
+ local content="$2"
470
+ local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
471
+ local working_dir=$(pwd)
472
+
473
+ # 创建事件JSON
474
+ local event='{{'
475
+ event+='"timestamp":"'"$timestamp"'",'
476
+ event+='"source_cli":"zsh",'
477
+ event+='"event_type":"'"$event_type"'",'
478
+ event+='"content":"'"$content"'",'
479
+ event+='"working_directory":"'"$working_dir"'"'
480
+ event+='}}'
481
+
482
+ # 添加到事件日志
483
+ echo "$event" >> "$EVENT_LOG.tmp"
484
+
485
+ # 检测跨CLI意图
486
+ if [[ "$event_type" == "input" ]]; then
487
+ detect_cross_cli_intent "$content" &
488
+ fi
489
+ }}
490
+
491
+ # Zsh特定Hook:使用preexec和precmd
492
+ autoload -Uz add-zsh-hook
493
+
494
+ # 命令执行前Hook
495
+ hook_preexec() {{
496
+ local command="$1"
497
+ log_hook_event "input" "$command"
498
+ }}
499
+
500
+ # 命令执行后Hook
501
+ hook_precmd() {{
502
+ local exit_code=$?
503
+ log_hook_event "output" "Command completed with exit code: $exit_code"
504
+ }}
505
+
506
+ # 注册Hook
507
+ add-zsh-hook preexec hook_preexec
508
+ add-zsh-hook precmd hook_precmd
509
+
510
+ echo "✅ Direct CLI Hooks loaded in Zsh"
511
+ '''
512
+
513
+ zsh_hook_file = self.hook_scripts_dir / 'zsh_hooks.zsh'
514
+ self._safe_write_file(zsh_hook_file, zsh_hook_content)
515
+ hooks.append(f"zsh_hook_script: {zsh_hook_file}")
516
+
517
+ return hooks
518
+
519
+ def _install_cmd_hooks(self) -> List[str]:
520
+ """安装Windows CMD Hook"""
521
+ hooks = []
522
+
523
+ # CMD Hook需要使用批处理文件和doskey
524
+ cmd_hook_content = f'''@echo off
525
+ REM Direct CLI Hook System for Windows CMD
526
+
527
+ set HOOK_DIR={self.hook_dir}
528
+ set EVENT_LOG=%HOOK_DIR%\\hook_events.json
529
+
530
+ REM 记录Hook事件
531
+ :log_hook_event
532
+ set event_type=%1
533
+ set content=%2
534
+
535
+ REM 获取时间戳
536
+ for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
537
+ set timestamp=%dt:~0,4%-%dt:~4,2%-%dt:~6,2%T%dt:~8,2%:%dt:~10,2%:%dt:~12,2%.%dt:~15,3%Z
538
+
539
+ REM 获取当前目录
540
+ set working_dir=%CD%
541
+
542
+ REM 创建事件JSON(简化版)
543
+ echo { "timestamp": "%timestamp%", "source_cli": "cmd", "event_type": "%event_type%", "content": "%content%", "working_directory": "%working_dir%" } >> "%EVENT_LOG%.tmp"
544
+
545
+ goto :eof
546
+
547
+ REM 主Hook函数
548
+ :hook_command
549
+ set command=%*
550
+ call :log_hook_event "input" "%command%"
551
+
552
+ REM 执行原始命令
553
+ %command%
554
+ set exit_code=%errorlevel%
555
+
556
+ call :log_hook_event "output" "Command completed with exit code: %exit_code%"
557
+
558
+ goto :eof
559
+ '''
560
+
561
+ cmd_hook_file = self.hook_scripts_dir / 'cmd_hooks.bat'
562
+ self._safe_write_file(cmd_hook_file, cmd_hook_content)
563
+ hooks.append(f"cmd_hook_script: {cmd_hook_file}")
564
+
565
+ # 创建doskey加载脚本
566
+ doskey_content = f'''@echo off
567
+ REM Load Direct CLI Hooks for CMD
568
+
569
+ doskey hook=call "{cmd_hook_file}" $*
570
+ echo ✅ Direct CLI Hooks loaded in CMD
571
+ '''
572
+
573
+ doskey_file = self.hook_scripts_dir / 'load_cmd_hooks.bat'
574
+ self._safe_write_file(doskey_file, doskey_content)
575
+ hooks.append(f"cmd_doskey_loader: {doskey_file}")
576
+
577
+ return hooks
578
+
579
+ def _install_generic_hooks(self) -> List[str]:
580
+ """安装通用Hook"""
581
+ hooks = []
582
+
583
+ # 创建通用Python脚本作为Hook入口
584
+ generic_hook_content = f'''#!/usr/bin/env python3
585
+ """
586
+ Direct CLI Hook System - Generic Hook
587
+ """
588
+
589
+ import os
590
+ import sys
591
+ import json
592
+ import subprocess
593
+ from datetime import datetime
594
+
595
+ # Hook配置
596
+ HOOK_DIR = "{self.hook_dir}"
597
+ EVENT_LOG = os.path.join(HOOK_DIR, "hook_events.json")
598
+
599
+ def log_hook_event(event_type, content):
600
+ """记录Hook事件"""
601
+ timestamp = datetime.now().isoformat() + "Z"
602
+ working_dir = os.getcwd()
603
+
604
+ event = {{
605
+ "timestamp": timestamp,
606
+ "source_cli": "generic",
607
+ "event_type": event_type,
608
+ "content": content,
609
+ "working_directory": working_dir
610
+ }}
611
+
612
+ # 添加到事件日志
613
+ with open(f"{{EVENT_LOG}}.tmp", "a", encoding="utf-8") as f:
614
+ f.write(json.dumps(event, ensure_ascii=False) + "\\n")
615
+
616
+ def main():
617
+ if len(sys.argv) < 3:
618
+ print("Usage: python generic_hook.py <event_type> <content>")
619
+ return 1
620
+
621
+ event_type = sys.argv[1]
622
+ content = " ".join(sys.argv[2:])
623
+
624
+ log_hook_event(event_type, content)
625
+ return 0
626
+
627
+ if __name__ == "__main__":
628
+ sys.exit(main())
629
+ '''
630
+
631
+ generic_hook_file = self.hook_scripts_dir / 'generic_hook.py'
632
+ self._safe_write_file(generic_hook_file, generic_hook_content)
633
+ hooks.append(f"generic_hook_script: {generic_hook_file}")
634
+
635
+ # 创建Shell别名生成脚本
636
+ alias_generator_content = f'''#!/bin/bash
637
+ # Generate Shell Aliases for Direct CLI Hooks
638
+
639
+ GENERIC_HOOK="{generic_hook_file}"
640
+
641
+ echo "# Direct CLI Hooks - Generated Aliases"
642
+ echo "# Add these to your shell configuration (.bashrc, .zshrc, etc.)"
643
+ echo ""
644
+
645
+ # 为常见命令生成别名
646
+ commands=("ls" "cat" "echo" "grep" "find" "mkdir" "rm" "cp" "mv")
647
+
648
+ for cmd in "${{commands[@]}}"; do
649
+ echo "alias $cmd='python3 $GENERIC_HOOK input \"\\$*\" && $cmd'"
650
+ done
651
+
652
+ echo ""
653
+ echo "# Load aliases with: source generated_aliases.sh"
654
+ '''
655
+
656
+ alias_file = self.hook_scripts_dir / 'generate_aliases.sh'
657
+ self._safe_write_file(alias_file, alias_generator_content)
658
+ hooks.append(f"alias_generator: {alias_file}")
659
+
660
+ return hooks
661
+
662
+ def _register_event_processors(self):
663
+ """注册事件处理器"""
664
+ self.event_processors = {
665
+ 'input': self._process_input_event,
666
+ 'output': self._process_output_event,
667
+ 'error': self._process_error_event,
668
+ 'cross_cli_intent': self._process_cross_cli_intent_event
669
+ }
670
+
671
+ # 注册模式匹配器
672
+ self.pattern_matchers = {
673
+ 'cross_cli_detection': self._detect_cross_cli_patterns,
674
+ 'intent_classification': self._classify_user_intent
675
+ }
676
+
677
+ def _process_input_event(self, event: CLIHookEvent):
678
+ """处理输入事件"""
679
+ # 检测跨CLI意图
680
+ intent = self._detect_cross_cli_patterns(event.content)
681
+ if intent:
682
+ event.user_intent = 'cross_cli_call'
683
+ event.target_clis = intent['target_clis']
684
+ event.confidence = intent['confidence']
685
+ event.detected_pattern = intent['pattern']
686
+
687
+ # 如果启用自动调用
688
+ if self.config.get('auto_cross_call_enabled', False):
689
+ self._execute_auto_cross_call(event)
690
+
691
+ def _process_output_event(self, event: CLIHookEvent):
692
+ """处理输出事件"""
693
+ # 分析输出,学习成功模式
694
+ pass
695
+
696
+ def _process_error_event(self, event: CLIHookEvent):
697
+ """处理错误事件"""
698
+ # 记录错误,优化检测
699
+ pass
700
+
701
+ def _process_cross_cli_intent_event(self, event: CLIHookEvent):
702
+ """处理跨CLI意图事件"""
703
+ # 执行跨CLI调用
704
+ for target_cli in event.target_clis:
705
+ result = self.cross_system.call_cli(
706
+ source_cli=event.source_cli,
707
+ target_cli=target_cli,
708
+ request=event.content,
709
+ working_dir=event.working_directory
710
+ )
711
+
712
+ # 显示结果
713
+ if result['success']:
714
+ print(f"\\n🔗 跨CLI协作结果 ({event.source_cli} -> {target_cli}):")
715
+ print(result['response'][:500] + '...' if len(result['response']) > 500 else result['response'])
716
+ print("-" * 50)
717
+
718
+ def _detect_cross_cli_patterns(self, content: str) -> Optional[Dict[str, Any]]:
719
+ """检测跨CLI协作模式"""
720
+ content_lower = content.lower()
721
+
722
+ # 检测跨CLI模式
723
+ for pattern in self.cross_cli_patterns:
724
+ import re
725
+ match = re.search(pattern, content_lower)
726
+ if match:
727
+ target_cli = match.group(1)
728
+
729
+ # 解析CLI别名
730
+ for canonical_name, aliases in self.cli_aliases.items():
731
+ if target_cli in aliases:
732
+ target_cli = canonical_name
733
+ break
734
+
735
+ if target_cli in self.cross_system.cli_methods:
736
+ return {
737
+ 'target_clis': [target_cli],
738
+ 'confidence': 0.8,
739
+ 'pattern': pattern,
740
+ 'detected_text': match.group(0)
741
+ }
742
+
743
+ return None
744
+
745
+ def _classify_user_intent(self, content: str) -> Optional[str]:
746
+ """分类用户意图"""
747
+ content_lower = content.lower()
748
+
749
+ for intent_type, keywords in self.intent_keywords.items():
750
+ for keyword in keywords:
751
+ if keyword in content_lower:
752
+ return intent_type
753
+
754
+ return None
755
+
756
+ def _execute_auto_cross_call(self, event: CLIHookEvent):
757
+ """执行自动跨CLI调用"""
758
+ if not event.target_clis or event.confidence < self.config.get('detection_confidence_threshold', 0.7):
759
+ return
760
+
761
+ for target_cli in event.target_clis:
762
+ # 检查目标CLI是否可用
763
+ status = self.cross_system.check_cli_status(target_cli)
764
+ if not status['exists']:
765
+ continue
766
+
767
+ # 异步执行跨CLI调用
768
+ def async_call():
769
+ result = self.cross_system.call_cli(
770
+ source_cli=event.source_cli,
771
+ target_cli=target_cli,
772
+ request=event.content,
773
+ working_dir=event.working_directory
774
+ )
775
+
776
+ if result['success']:
777
+ self._display_cross_cli_result(event, target_cli, result)
778
+
779
+ # 在后台线程中执行
780
+ threading.Thread(target=async_call, daemon=True).start()
781
+
782
+ def _display_cross_cli_result(self, event: CLIHookEvent, target_cli: str, result: Dict[str, Any]):
783
+ """显示跨CLI调用结果"""
784
+ print(f"\\n🔗 跨CLI协作结果 ({event.source_cli} -> {target_cli}):")
785
+ print(f"⏱️ 执行时间: {result.get('execution_time', 0):.2f}s")
786
+
787
+ response = result.get('response', '')
788
+ if len(response) > 800:
789
+ print(response[:800] + "\\n... (响应已截断)")
790
+ else:
791
+ print(response)
792
+
793
+ print("-" * 50)
794
+
795
+ def process_pending_events(self):
796
+ """处理待处理的事件"""
797
+ temp_event_file = self.event_log_file.with_suffix('.json.tmp')
798
+
799
+ if not temp_event_file.exists():
800
+ return
801
+
802
+ try:
803
+ # 读取临时事件文件
804
+ with open(temp_event_file, 'r', encoding='utf-8') as f:
805
+ lines = f.readlines()
806
+
807
+ if not lines:
808
+ return
809
+
810
+ # 处理每个事件
811
+ for line in lines:
812
+ line = line.strip()
813
+ if not line:
814
+ continue
815
+
816
+ try:
817
+ event_data = json.loads(line)
818
+ event = CLIHookEvent(**event_data)
819
+
820
+ # 根据事件类型处理
821
+ if event.event_type in self.event_processors:
822
+ self.event_processors[event.event_type](event)
823
+
824
+ # 记录到主事件日志
825
+ self._record_event(event)
826
+
827
+ except json.JSONDecodeError:
828
+ continue
829
+ except Exception as e:
830
+ print(f"Warning: Failed to process event: {e}")
831
+ continue
832
+
833
+ # 清空临时文件
834
+ temp_event_file.unlink()
835
+
836
+ except Exception as e:
837
+ print(f"Warning: Failed to process pending events: {e}")
838
+
839
+ def _record_event(self, event: CLIHookEvent):
840
+ """记录Hook事件到主日志"""
841
+ try:
842
+ if self.event_log_file.exists():
843
+ with open(self.event_log_file, 'r', encoding='utf-8') as f:
844
+ events = json.load(f)
845
+ else:
846
+ events = []
847
+
848
+ events.append(asdict(event))
849
+
850
+ # 保留最近1000个事件
851
+ if len(events) > 1000:
852
+ events = events[-1000:]
853
+
854
+ self._safe_write_json(self.event_log_file, events)
855
+
856
+ except Exception as e:
857
+ print(f"Warning: Failed to record event: {e}")
858
+
859
+ def _safe_write_file(self, file_path: Path, content: str):
860
+ """安全写入文件"""
861
+ try:
862
+ with open(file_path, 'w', encoding='utf-8') as f:
863
+ f.write(content)
864
+
865
+ # 设置执行权限(对于脚本文件)
866
+ if file_path.suffix in ['.sh', '.py', '.bat', '.ps1', '.zsh']:
867
+ os.chmod(file_path, 0o755)
868
+
869
+ except Exception as e:
870
+ raise Exception(f"Failed to write file {file_path}: {e}")
871
+
872
+ def _safe_write_json(self, file_path: Path, data: Any):
873
+ """安全写入JSON文件"""
874
+ try:
875
+ with open(file_path, 'w', encoding='utf-8') as f:
876
+ json.dump(data, f, indent=2, ensure_ascii=False)
877
+ except Exception as e:
878
+ raise Exception(f"Failed to write JSON file {file_path}: {e}")
879
+
880
+ def get_hook_status(self) -> Dict[str, Any]:
881
+ """获取Hook状态"""
882
+ status = {
883
+ 'config': self.config,
884
+ 'hook_directory': str(self.hook_dir),
885
+ 'hook_scripts': [],
886
+ 'event_count': 0,
887
+ 'recent_events': [],
888
+ 'active_processors': list(self.event_processors.keys()),
889
+ 'pattern_matchers': list(self.pattern_matchers.keys())
890
+ }
891
+
892
+ # 列出Hook脚本
893
+ if self.hook_scripts_dir.exists():
894
+ status['hook_scripts'] = [f.name for f in self.hook_scripts_dir.iterdir() if f.is_file()]
895
+
896
+ # 统计事件数量
897
+ try:
898
+ if self.event_log_file.exists():
899
+ with open(self.event_log_file, 'r', encoding='utf-8') as f:
900
+ events = json.load(f)
901
+ status['event_count'] = len(events)
902
+ status['recent_events'] = events[-5:] # 最近5个事件
903
+ except:
904
+ pass
905
+
906
+ return status
907
+
908
+ # 使用示例
909
+ if __name__ == '__main__':
910
+ hook_manager = DirectCLIHookManager()
911
+
912
+ print("🔗 真实CLI Hook系统")
913
+ print("=" * 50)
914
+
915
+ # 安装Shell Hook
916
+ print("🔧 安装Shell Hook...")
917
+ install_result = hook_manager.install_shell_hooks()
918
+
919
+ if install_result['success']:
920
+ print(f"✅ Hook安装成功: {install_result['shell_type']}")
921
+ print(f"📁 Hook目录: {hook_manager.hook_dir}")
922
+ print(f"📄 安装的Hook: {len(install_result['installed_hooks'])}")
923
+
924
+ for hook in install_result['installed_hooks']:
925
+ print(f" - {hook}")
926
+
927
+ # 处理待处理事件
928
+ print("\\n🔄 处理待处理事件...")
929
+ hook_manager.process_pending_events()
930
+
931
+ # 获取Hook状态
932
+ print("\\n📊 Hook状态:")
933
+ status = hook_manager.get_hook_status()
934
+ print(f" Hook脚本数量: {len(status['hook_scripts'])}")
935
+ print(f" 事件处理器: {', '.join(status['active_processors'])}")
936
+ print(f" 模式匹配器: {', '.join(status['pattern_matchers'])}")
937
+ print(f" 事件数量: {status['event_count']}")
938
+
939
+ # 显示使用说明
940
+ print("\\n📖 使用说明:")
941
+ if install_result['shell_type'] == 'bash':
942
+ print(" 在Bash中运行: source ~/.direct_cli_hooks/hook_scripts/load_bash_hooks.sh")
943
+ elif install_result['shell_type'] == 'powershell':
944
+ print(" 在PowerShell中重新启动或运行: . ~/.direct_cli_hooks/hook_scripts/powershell_hooks.ps1")
945
+ elif install_result['shell_type'] == 'zsh':
946
+ print(" 在Zsh中运行: source ~/.direct_cli_hooks/hook_scripts/zsh_hooks.zsh")
947
+ else:
948
+ print(" 手动加载Hook脚本中的函数到你的Shell配置文件")
949
+
950
+ print("\\n🔍 Hook现在可以检测跨CLI协作意图:")
951
+ print(" 示例: 'call claude to analyze this file'")
952
+ print(" 示例: 'using gemini to generate code'")
953
+ print(" 示例: 'ask copilot to help with debugging'")
954
+
955
+ else:
956
+ print(f"❌ Hook安装失败: {install_result['message']}")
957
+
958
+ print("\\n✅ Hook系统初始化完成!")