stigmergy 1.0.68 → 1.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +306 -300
- package/README.md +469 -301
- package/package.json +97 -81
- package/scripts/publish.js +268 -0
- package/scripts/simple-publish.js +59 -0
- package/src/index.js +12 -0
- package/test/enhanced-main-alignment.test.js +298 -0
- package/test/hook-system-integration-test.js +307 -0
- package/test/natural-language-skills-test.js +320 -0
- package/test/nl-integration-test.js +179 -0
- package/test/parameter-parsing-test.js +143 -0
- package/test/real-test.js +435 -0
- package/test/system-compatibility-test.js +447 -0
- package/test/tdd-fixes-test.js +211 -0
- package/test/third-party-skills-test.js +321 -0
- package/test/tool-selection-integration-test.js +157 -0
- package/test/unit/cli-scanner.test.js +291 -0
- package/test/unit/cross-cli-executor.test.js +399 -0
- package/src/adapters/claude/__init__.py +0 -13
- package/src/adapters/claude/claude_skills_integration.py +0 -609
- package/src/adapters/claude/hook_adapter.py +0 -663
- package/src/adapters/claude/install_claude_integration.py +0 -265
- package/src/adapters/claude/skills_hook_adapter.py +0 -841
- package/src/adapters/claude/standalone_claude_adapter.py +0 -384
- package/src/adapters/cline/__init__.py +0 -20
- package/src/adapters/cline/config.py +0 -108
- package/src/adapters/cline/install_cline_integration.py +0 -617
- package/src/adapters/cline/mcp_server.py +0 -713
- package/src/adapters/cline/standalone_cline_adapter.py +0 -459
- package/src/adapters/codebuddy/__init__.py +0 -13
- package/src/adapters/codebuddy/buddy_adapter.py +0 -1125
- package/src/adapters/codebuddy/install_codebuddy_integration.py +0 -279
- package/src/adapters/codebuddy/skills_hook_adapter.py +0 -672
- package/src/adapters/codebuddy/skills_integration.py +0 -395
- package/src/adapters/codebuddy/standalone_codebuddy_adapter.py +0 -403
- package/src/adapters/codex/__init__.py +0 -11
- package/src/adapters/codex/base.py +0 -46
- package/src/adapters/codex/install_codex_integration.py +0 -311
- package/src/adapters/codex/mcp_server.py +0 -493
- package/src/adapters/codex/natural_language_parser.py +0 -82
- package/src/adapters/codex/slash_command_adapter.py +0 -326
- package/src/adapters/codex/standalone_codex_adapter.py +0 -362
- package/src/adapters/copilot/__init__.py +0 -13
- package/src/adapters/copilot/install_copilot_integration.py +0 -564
- package/src/adapters/copilot/mcp_adapter.py +0 -772
- package/src/adapters/copilot/mcp_server.py +0 -168
- package/src/adapters/copilot/standalone_copilot_adapter.py +0 -114
- package/src/adapters/gemini/__init__.py +0 -13
- package/src/adapters/gemini/extension_adapter.py +0 -690
- package/src/adapters/gemini/install_gemini_integration.py +0 -257
- package/src/adapters/gemini/standalone_gemini_adapter.py +0 -366
- package/src/adapters/iflow/__init__.py +0 -7
- package/src/adapters/iflow/hook_adapter.py +0 -1038
- package/src/adapters/iflow/hook_installer.py +0 -536
- package/src/adapters/iflow/install_iflow_integration.py +0 -271
- package/src/adapters/iflow/official_hook_adapter.py +0 -1272
- package/src/adapters/iflow/standalone_iflow_adapter.py +0 -48
- package/src/adapters/iflow/workflow_adapter.py +0 -793
- package/src/adapters/qoder/hook_installer.py +0 -732
- package/src/adapters/qoder/install_qoder_integration.py +0 -265
- package/src/adapters/qoder/notification_hook_adapter.py +0 -863
- package/src/adapters/qoder/standalone_qoder_adapter.py +0 -48
- package/src/adapters/qwen/__init__.py +0 -17
- package/src/adapters/qwencode/__init__.py +0 -13
- package/src/adapters/qwencode/inheritance_adapter.py +0 -818
- package/src/adapters/qwencode/install_qwencode_integration.py +0 -276
- package/src/adapters/qwencode/standalone_qwencode_adapter.py +0 -399
- package/src/atomic_collaboration_handler.py +0 -461
- package/src/cli_collaboration_agent.py +0 -697
- package/src/collaboration/hooks.py +0 -315
- package/src/core/__init__.py +0 -21
- package/src/core/ai_environment_scanner.py +0 -331
- package/src/core/base_adapter.py +0 -220
- package/src/core/cli_hook_integration.py +0 -406
- package/src/core/cross_cli_executor.py +0 -713
- package/src/core/cross_cli_mapping.py +0 -1165
- package/src/core/cross_platform_encoding.py +0 -365
- package/src/core/cross_platform_safe_cli.py +0 -894
- package/src/core/direct_cli_executor.py +0 -805
- package/src/core/direct_cli_hook_system.py +0 -958
- package/src/core/enhanced_init_processor.py +0 -467
- package/src/core/graceful_cli_executor.py +0 -912
- package/src/core/md_enhancer.py +0 -342
- package/src/core/md_generator.py +0 -619
- package/src/core/models.py +0 -218
- package/src/core/parser.py +0 -108
- package/src/core/real_cli_hook_system.py +0 -852
- package/src/core/real_cross_cli_system.py +0 -925
- package/src/core/verified_cross_cli_system.py +0 -961
- package/src/deploy.js +0 -737
- package/src/enhanced-main.js +0 -626
- package/src/enhanced_deploy.js +0 -303
- package/src/enhanced_universal_cli_setup.py +0 -930
- package/src/kimi_wrapper.py +0 -104
- package/src/main.js +0 -1309
- package/src/shell_integration.py +0 -398
- package/src/simple-main.js +0 -315
- package/src/smart_router_creator.py +0 -323
- package/src/universal_cli_setup.py +0 -1289
- package/src/utils/__init__.py +0 -12
- package/src/utils/cli_detector.py +0 -445
- package/src/utils/file_utils.py +0 -246
|
@@ -1,793 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
iFlow CLI Workflow Pipeline适配器
|
|
3
|
-
|
|
4
|
-
通过iFlow CLI的Workflow Pipeline系统实现跨CLI调用功能。
|
|
5
|
-
基于通用workflow插件架构,支持灵活的工作流扩展。
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import asyncio
|
|
9
|
-
import json
|
|
10
|
-
import logging
|
|
11
|
-
from datetime import datetime
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
from typing import Dict, Any, Optional, List, Union
|
|
14
|
-
|
|
15
|
-
from src.core.base_adapter import BaseCrossCLIAdapter
|
|
16
|
-
from src.core.parser import NaturalLanguageParser
|
|
17
|
-
|
|
18
|
-
# 配置日志
|
|
19
|
-
logger = logging.getLogger(__name__)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class WorkflowContext:
|
|
23
|
-
"""iFlow CLI工作流上下文"""
|
|
24
|
-
|
|
25
|
-
def __init__(self, workflow_id: str = "", stage: str = "", data: Dict = None):
|
|
26
|
-
self.workflow_id = workflow_id
|
|
27
|
-
self.stage = stage
|
|
28
|
-
self.data = data or {}
|
|
29
|
-
self.metadata = {
|
|
30
|
-
'user_id': 'default_user',
|
|
31
|
-
'session_id': '',
|
|
32
|
-
'pipeline_config': {}
|
|
33
|
-
}
|
|
34
|
-
self.pipeline_name = "cross-cli-integration"
|
|
35
|
-
self.version = "1.0.0"
|
|
36
|
-
self.start_time = datetime.now()
|
|
37
|
-
self.status = "pending"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class WorkflowStage:
|
|
41
|
-
"""工作流阶段"""
|
|
42
|
-
|
|
43
|
-
def __init__(self, name: str, description: str = "", required: bool = True, timeout: int = 30):
|
|
44
|
-
self.name = name
|
|
45
|
-
self.description = description
|
|
46
|
-
self.required = required
|
|
47
|
-
self.timeout = timeout
|
|
48
|
-
self.status = "pending"
|
|
49
|
-
self.result = None
|
|
50
|
-
self.error = None
|
|
51
|
-
self.start_time = None
|
|
52
|
-
self.end_time = None
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class IFlowWorkflowAdapter(BaseCrossCLIAdapter):
|
|
56
|
-
"""
|
|
57
|
-
iFlow CLI Workflow Pipeline适配器
|
|
58
|
-
|
|
59
|
-
通过iFlow CLI的Workflow Pipeline系统实现跨CLI调用功能。
|
|
60
|
-
基于工作流的无损扩展实现。
|
|
61
|
-
|
|
62
|
-
Pipeline机制:
|
|
63
|
-
- on_workflow_start: 工作流开始时触发
|
|
64
|
-
- on_stage_complete: 阶段完成时触发
|
|
65
|
-
- on_workflow_success: 工作流成功完成时触发
|
|
66
|
-
- on_workflow_error: 工作流错误时触发
|
|
67
|
-
- on_pipeline_ready: 流水线就绪时触发
|
|
68
|
-
"""
|
|
69
|
-
|
|
70
|
-
def __init__(self, cli_name: str = "iflow"):
|
|
71
|
-
super().__init__(cli_name)
|
|
72
|
-
|
|
73
|
-
# Pipeline相关属性
|
|
74
|
-
self.pipeline_stages: List[WorkflowStage] = []
|
|
75
|
-
self.workflow_hooks: Dict[str, callable] = {}
|
|
76
|
-
self.processed_workflows: List[Dict] = []
|
|
77
|
-
self.workflow_executions: List[Dict] = []
|
|
78
|
-
self.task_queue: Optional[asyncio.Queue] = None
|
|
79
|
-
|
|
80
|
-
# 统计信息
|
|
81
|
-
self.stages_processed = 0
|
|
82
|
-
self.cross_cli_calls_count = 0
|
|
83
|
-
self.workflow_count = 0
|
|
84
|
-
|
|
85
|
-
# 配置
|
|
86
|
-
self.pipeline_config: Dict = {}
|
|
87
|
-
self.workflow_config: Dict = {}
|
|
88
|
-
|
|
89
|
-
# 组件
|
|
90
|
-
self.parser = NaturalLanguageParser()
|
|
91
|
-
|
|
92
|
-
logger.info("iFlow Workflow Pipeline适配器初始化完成")
|
|
93
|
-
|
|
94
|
-
async def initialize(self) -> bool:
|
|
95
|
-
"""
|
|
96
|
-
初始化适配器
|
|
97
|
-
|
|
98
|
-
Returns:
|
|
99
|
-
bool: 初始化是否成功
|
|
100
|
-
"""
|
|
101
|
-
try:
|
|
102
|
-
logger.info("开始初始化iFlow Workflow Pipeline适配器...")
|
|
103
|
-
|
|
104
|
-
# 1. 加载Pipeline配置
|
|
105
|
-
if not await self._load_pipeline_config():
|
|
106
|
-
logger.error("Pipeline配置加载失败")
|
|
107
|
-
return False
|
|
108
|
-
|
|
109
|
-
# 2. 初始化工作流阶段
|
|
110
|
-
if not await self._initialize_workflow_stages():
|
|
111
|
-
logger.error("工作流阶段初始化失败")
|
|
112
|
-
return False
|
|
113
|
-
|
|
114
|
-
# 3. 注册工作流Hooks
|
|
115
|
-
if not await self._register_workflow_hooks():
|
|
116
|
-
logger.error("工作流Hooks注册失败")
|
|
117
|
-
return False
|
|
118
|
-
|
|
119
|
-
# 4. 初始化任务队列
|
|
120
|
-
if not await self._initialize_task_queue():
|
|
121
|
-
logger.error("任务队列初始化失败")
|
|
122
|
-
return False
|
|
123
|
-
|
|
124
|
-
# 5. 创建工作流配置目录
|
|
125
|
-
await self._ensure_config_directory()
|
|
126
|
-
|
|
127
|
-
logger.info("iFlow Workflow Pipeline适配器初始化成功")
|
|
128
|
-
return True
|
|
129
|
-
|
|
130
|
-
except Exception as e:
|
|
131
|
-
logger.error(f"初始化iFlow Workflow Pipeline适配器失败: {e}")
|
|
132
|
-
return False
|
|
133
|
-
|
|
134
|
-
async def _load_pipeline_config(self) -> bool:
|
|
135
|
-
"""
|
|
136
|
-
加载Pipeline配置
|
|
137
|
-
|
|
138
|
-
Returns:
|
|
139
|
-
bool: 加载是否成功
|
|
140
|
-
"""
|
|
141
|
-
try:
|
|
142
|
-
config_path = Path(__file__).parent / "config.json"
|
|
143
|
-
|
|
144
|
-
if config_path.exists():
|
|
145
|
-
with open(config_path, 'r', encoding='utf-8') as f:
|
|
146
|
-
config = json.load(f)
|
|
147
|
-
|
|
148
|
-
self.pipeline_config = config
|
|
149
|
-
self.workflow_config = config.get('workflow', {})
|
|
150
|
-
logger.info("Pipeline配置加载成功")
|
|
151
|
-
return True
|
|
152
|
-
else:
|
|
153
|
-
logger.warning("Pipeline配置文件不存在,使用默认配置")
|
|
154
|
-
self.pipeline_config = self._get_default_config()
|
|
155
|
-
return True
|
|
156
|
-
|
|
157
|
-
except Exception as e:
|
|
158
|
-
logger.error(f"加载Pipeline配置失败: {e}")
|
|
159
|
-
return False
|
|
160
|
-
|
|
161
|
-
def _get_default_config(self) -> Dict:
|
|
162
|
-
"""获取默认配置"""
|
|
163
|
-
return {
|
|
164
|
-
"adapter_name": "iFlow Workflow Pipeline Adapter",
|
|
165
|
-
"pipeline_mechanism": "workflow_pipeline",
|
|
166
|
-
"supported_clis": ["claude", "gemini", "qwencode", "qoder", "codebuddy", "codex"],
|
|
167
|
-
"workflow": {
|
|
168
|
-
"default_settings": {
|
|
169
|
-
"parallel_execution": True,
|
|
170
|
-
"error_handling": "continue",
|
|
171
|
-
"retry_on_failure": True
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async def _initialize_workflow_stages(self) -> bool:
|
|
177
|
-
"""
|
|
178
|
-
初始化工作流阶段
|
|
179
|
-
|
|
180
|
-
Returns:
|
|
181
|
-
bool: 初始化是否成功
|
|
182
|
-
"""
|
|
183
|
-
try:
|
|
184
|
-
stage_configs = self.workflow_config.get('pipeline_setup', {}).get('stages', [])
|
|
185
|
-
|
|
186
|
-
default_stages = [
|
|
187
|
-
WorkflowStage("input_validation", "输入数据验证", True, 5),
|
|
188
|
-
WorkflowStage("cross_cli_detection", "跨CLI调用检测", True, 10),
|
|
189
|
-
WorkflowStage("target_execution", "目标CLI执行", False, 25),
|
|
190
|
-
WorkflowStage("result_processing", "结果处理", True, 8),
|
|
191
|
-
WorkflowStage("output_formatting", "输出格式化", True, 3)
|
|
192
|
-
]
|
|
193
|
-
|
|
194
|
-
# 如果配置中有阶段定义,使用配置中的定义
|
|
195
|
-
if stage_configs:
|
|
196
|
-
self.pipeline_stages = []
|
|
197
|
-
for stage_config in stage_configs:
|
|
198
|
-
stage = WorkflowStage(
|
|
199
|
-
stage_config['name'],
|
|
200
|
-
stage_config.get('description', ''),
|
|
201
|
-
stage_config.get('required', True),
|
|
202
|
-
stage_config.get('timeout', 30)
|
|
203
|
-
)
|
|
204
|
-
self.pipeline_stages.append(stage)
|
|
205
|
-
else:
|
|
206
|
-
self.pipeline_stages = default_stages
|
|
207
|
-
|
|
208
|
-
logger.info(f"工作流阶段初始化完成,共{len(self.pipeline_stages)}个阶段")
|
|
209
|
-
return True
|
|
210
|
-
|
|
211
|
-
except Exception as e:
|
|
212
|
-
logger.error(f"初始化工作流阶段失败: {e}")
|
|
213
|
-
return False
|
|
214
|
-
|
|
215
|
-
async def _register_workflow_hooks(self) -> bool:
|
|
216
|
-
"""
|
|
217
|
-
注册工作流Hooks
|
|
218
|
-
|
|
219
|
-
Returns:
|
|
220
|
-
bool: 注册是否成功
|
|
221
|
-
"""
|
|
222
|
-
try:
|
|
223
|
-
self.workflow_hooks = {
|
|
224
|
-
'on_workflow_start': self.on_workflow_start,
|
|
225
|
-
'on_stage_complete': self.on_stage_complete,
|
|
226
|
-
'on_workflow_success': self.on_workflow_success,
|
|
227
|
-
'on_workflow_error': self.on_workflow_error,
|
|
228
|
-
'on_pipeline_ready': self.on_pipeline_ready
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
logger.info("工作流Hooks注册成功")
|
|
232
|
-
return True
|
|
233
|
-
|
|
234
|
-
except Exception as e:
|
|
235
|
-
logger.error(f"注册工作流Hooks失败: {e}")
|
|
236
|
-
return False
|
|
237
|
-
|
|
238
|
-
async def _initialize_task_queue(self) -> bool:
|
|
239
|
-
"""
|
|
240
|
-
初始化任务队列
|
|
241
|
-
|
|
242
|
-
Returns:
|
|
243
|
-
bool: 初始化是否成功
|
|
244
|
-
"""
|
|
245
|
-
try:
|
|
246
|
-
self.task_queue = asyncio.Queue()
|
|
247
|
-
logger.info("任务队列初始化成功")
|
|
248
|
-
return True
|
|
249
|
-
|
|
250
|
-
except Exception as e:
|
|
251
|
-
logger.error(f"初始化任务队列失败: {e}")
|
|
252
|
-
return False
|
|
253
|
-
|
|
254
|
-
async def _ensure_config_directory(self) -> None:
|
|
255
|
-
"""确保配置目录存在"""
|
|
256
|
-
config_dir = Path.home() / ".config" / "iflow" / "adapters"
|
|
257
|
-
config_dir.mkdir(parents=True, exist_ok=True)
|
|
258
|
-
|
|
259
|
-
def is_available(self) -> bool:
|
|
260
|
-
"""
|
|
261
|
-
检查适配器是否可用
|
|
262
|
-
|
|
263
|
-
Returns:
|
|
264
|
-
bool: 是否可用
|
|
265
|
-
"""
|
|
266
|
-
return (
|
|
267
|
-
len(self.pipeline_stages) > 0 and
|
|
268
|
-
len(self.workflow_hooks) > 0 and
|
|
269
|
-
self.task_queue is not None
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
async def execute_task(self, task: str, context: Dict[str, Any]) -> str:
|
|
273
|
-
"""
|
|
274
|
-
执行工作流任务
|
|
275
|
-
|
|
276
|
-
Args:
|
|
277
|
-
task: 要执行的任务
|
|
278
|
-
context: 执行上下文
|
|
279
|
-
|
|
280
|
-
Returns:
|
|
281
|
-
str: 执行结果
|
|
282
|
-
"""
|
|
283
|
-
try:
|
|
284
|
-
logger.info(f"执行iFlow工作流任务: {task}")
|
|
285
|
-
|
|
286
|
-
# 创建工作流上下文
|
|
287
|
-
workflow_context = WorkflowContext(
|
|
288
|
-
workflow_id=context.get('workflow_id', f'workflow-{datetime.now().timestamp()}'),
|
|
289
|
-
stage="execution",
|
|
290
|
-
data={"task": task, **context}
|
|
291
|
-
)
|
|
292
|
-
|
|
293
|
-
# 执行工作流
|
|
294
|
-
result = await self._execute_workflow(workflow_context)
|
|
295
|
-
|
|
296
|
-
return result
|
|
297
|
-
|
|
298
|
-
except Exception as e:
|
|
299
|
-
logger.error(f"执行工作流任务失败: {e}")
|
|
300
|
-
return f"工作流执行失败: {str(e)}"
|
|
301
|
-
|
|
302
|
-
# ==================== Workflow Hook处理器 ====================
|
|
303
|
-
|
|
304
|
-
async def on_workflow_start(self, context: WorkflowContext) -> Optional[str]:
|
|
305
|
-
"""
|
|
306
|
-
工作流开始Hook
|
|
307
|
-
|
|
308
|
-
Args:
|
|
309
|
-
context: 工作流上下文
|
|
310
|
-
|
|
311
|
-
Returns:
|
|
312
|
-
Optional[str]: 处理结果
|
|
313
|
-
"""
|
|
314
|
-
try:
|
|
315
|
-
self.workflow_count += 1
|
|
316
|
-
self.stages_processed += 1
|
|
317
|
-
|
|
318
|
-
# 记录工作流开始
|
|
319
|
-
workflow_record = {
|
|
320
|
-
'type': 'workflow_start',
|
|
321
|
-
'workflow_id': context.workflow_id,
|
|
322
|
-
'stage': context.stage,
|
|
323
|
-
'data': context.data,
|
|
324
|
-
'metadata': context.metadata,
|
|
325
|
-
'timestamp': datetime.now().isoformat()
|
|
326
|
-
}
|
|
327
|
-
self.processed_workflows.append(workflow_record)
|
|
328
|
-
|
|
329
|
-
logger.info(f"工作流开始: {context.workflow_id}")
|
|
330
|
-
|
|
331
|
-
# 检测跨CLI调用意图
|
|
332
|
-
user_input = context.data.get('prompt', context.data.get('task', ''))
|
|
333
|
-
if not user_input:
|
|
334
|
-
return None
|
|
335
|
-
|
|
336
|
-
intent = self.parser.parse_intent(user_input, "iflow")
|
|
337
|
-
|
|
338
|
-
if intent.is_cross_cli and intent.target_cli != self.cli_name:
|
|
339
|
-
# 执行跨CLI调用
|
|
340
|
-
result = await self._execute_cross_cli_workflow(
|
|
341
|
-
intent.target_cli,
|
|
342
|
-
intent.task,
|
|
343
|
-
context
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
if result:
|
|
347
|
-
self.cross_cli_calls_count += 1
|
|
348
|
-
return result
|
|
349
|
-
|
|
350
|
-
return None # 继续正常工作流
|
|
351
|
-
|
|
352
|
-
except Exception as e:
|
|
353
|
-
logger.error(f"工作流开始Hook处理失败: {e}")
|
|
354
|
-
self.record_error()
|
|
355
|
-
return None
|
|
356
|
-
|
|
357
|
-
async def on_stage_complete(self, context: WorkflowContext, stage_result: Any) -> Optional[str]:
|
|
358
|
-
"""
|
|
359
|
-
阶段完成Hook
|
|
360
|
-
|
|
361
|
-
Args:
|
|
362
|
-
context: 工作流上下文
|
|
363
|
-
stage_result: 阶段结果
|
|
364
|
-
|
|
365
|
-
Returns:
|
|
366
|
-
Optional[str]: 处理结果
|
|
367
|
-
"""
|
|
368
|
-
try:
|
|
369
|
-
self.stages_processed += 1
|
|
370
|
-
|
|
371
|
-
# 记录阶段完成
|
|
372
|
-
stage_record = {
|
|
373
|
-
'type': 'stage_complete',
|
|
374
|
-
'workflow_id': context.workflow_id,
|
|
375
|
-
'stage': context.stage,
|
|
376
|
-
'result': str(stage_result) if stage_result else None,
|
|
377
|
-
'timestamp': datetime.now().isoformat()
|
|
378
|
-
}
|
|
379
|
-
self.processed_workflows.append(stage_record)
|
|
380
|
-
|
|
381
|
-
logger.debug(f"工作流阶段完成: {context.workflow_id} - {context.stage}")
|
|
382
|
-
return None
|
|
383
|
-
|
|
384
|
-
except Exception as e:
|
|
385
|
-
logger.error(f"阶段完成Hook处理失败: {e}")
|
|
386
|
-
self.record_error()
|
|
387
|
-
return None
|
|
388
|
-
|
|
389
|
-
async def on_workflow_success(self, context: WorkflowContext, final_result: Any) -> Optional[str]:
|
|
390
|
-
"""
|
|
391
|
-
工作流成功Hook
|
|
392
|
-
|
|
393
|
-
Args:
|
|
394
|
-
context: 工作流上下文
|
|
395
|
-
final_result: 最终结果
|
|
396
|
-
|
|
397
|
-
Returns:
|
|
398
|
-
Optional[str]: 处理结果
|
|
399
|
-
"""
|
|
400
|
-
try:
|
|
401
|
-
# 记录工作流成功
|
|
402
|
-
success_record = {
|
|
403
|
-
'type': 'workflow_success',
|
|
404
|
-
'workflow_id': context.workflow_id,
|
|
405
|
-
'result': str(final_result) if final_result else None,
|
|
406
|
-
'duration': (datetime.now() - context.start_time).total_seconds(),
|
|
407
|
-
'timestamp': datetime.now().isoformat()
|
|
408
|
-
}
|
|
409
|
-
self.processed_workflows.append(success_record)
|
|
410
|
-
|
|
411
|
-
logger.info(f"工作流成功完成: {context.workflow_id}")
|
|
412
|
-
return None
|
|
413
|
-
|
|
414
|
-
except Exception as e:
|
|
415
|
-
logger.error(f"工作流成功Hook处理失败: {e}")
|
|
416
|
-
self.record_error()
|
|
417
|
-
return None
|
|
418
|
-
|
|
419
|
-
async def on_workflow_error(self, context: WorkflowContext, error: Exception) -> Optional[str]:
|
|
420
|
-
"""
|
|
421
|
-
工作流错误Hook
|
|
422
|
-
|
|
423
|
-
Args:
|
|
424
|
-
context: 工作流上下文
|
|
425
|
-
error: 错误信息
|
|
426
|
-
|
|
427
|
-
Returns:
|
|
428
|
-
Optional[str]: 处理结果
|
|
429
|
-
"""
|
|
430
|
-
try:
|
|
431
|
-
# 记录工作流错误
|
|
432
|
-
error_record = {
|
|
433
|
-
'type': 'workflow_error',
|
|
434
|
-
'workflow_id': context.workflow_id,
|
|
435
|
-
'error': str(error),
|
|
436
|
-
'error_type': type(error).__name__,
|
|
437
|
-
'timestamp': datetime.now().isoformat()
|
|
438
|
-
}
|
|
439
|
-
self.processed_workflows.append(error_record)
|
|
440
|
-
|
|
441
|
-
logger.error(f"工作流执行错误: {context.workflow_id} - {error}")
|
|
442
|
-
return None
|
|
443
|
-
|
|
444
|
-
except Exception as e:
|
|
445
|
-
logger.error(f"工作流错误Hook处理失败: {e}")
|
|
446
|
-
self.record_error()
|
|
447
|
-
return None
|
|
448
|
-
|
|
449
|
-
async def on_pipeline_ready(self, pipeline_config: Dict) -> Optional[str]:
|
|
450
|
-
"""
|
|
451
|
-
流水线就绪Hook
|
|
452
|
-
|
|
453
|
-
Args:
|
|
454
|
-
pipeline_config: 流水线配置
|
|
455
|
-
|
|
456
|
-
Returns:
|
|
457
|
-
Optional[str]: 处理结果
|
|
458
|
-
"""
|
|
459
|
-
try:
|
|
460
|
-
logger.info("iFlow流水线已就绪")
|
|
461
|
-
return None
|
|
462
|
-
|
|
463
|
-
except Exception as e:
|
|
464
|
-
logger.error(f"流水线就绪Hook处理失败: {e}")
|
|
465
|
-
self.record_error()
|
|
466
|
-
return None
|
|
467
|
-
|
|
468
|
-
# ==================== 跨CLI功能 ====================
|
|
469
|
-
|
|
470
|
-
async def _execute_cross_cli_workflow(
|
|
471
|
-
self,
|
|
472
|
-
target_cli: str,
|
|
473
|
-
task: str,
|
|
474
|
-
context: WorkflowContext
|
|
475
|
-
) -> Optional[str]:
|
|
476
|
-
"""
|
|
477
|
-
执行跨CLI工作流
|
|
478
|
-
|
|
479
|
-
Args:
|
|
480
|
-
target_cli: 目标CLI工具
|
|
481
|
-
task: 要执行的任务
|
|
482
|
-
context: 工作流上下文
|
|
483
|
-
|
|
484
|
-
Returns:
|
|
485
|
-
Optional[str]: 执行结果
|
|
486
|
-
"""
|
|
487
|
-
try:
|
|
488
|
-
logger.info(f"执行跨CLI工作流: {target_cli} -> {task}")
|
|
489
|
-
|
|
490
|
-
# 记录跨CLI调用
|
|
491
|
-
workflow_execution = {
|
|
492
|
-
'workflow_id': context.workflow_id,
|
|
493
|
-
'target_cli': target_cli,
|
|
494
|
-
'task': task,
|
|
495
|
-
'stage': context.stage,
|
|
496
|
-
'timestamp': datetime.now().isoformat()
|
|
497
|
-
}
|
|
498
|
-
self.workflow_executions.append(workflow_execution)
|
|
499
|
-
|
|
500
|
-
# 获取目标CLI适配器
|
|
501
|
-
target_adapter = self.get_adapter(target_cli)
|
|
502
|
-
|
|
503
|
-
if not target_adapter:
|
|
504
|
-
logger.warning(f"目标CLI适配器不可用: {target_cli}")
|
|
505
|
-
return self._format_workflow_error(
|
|
506
|
-
target_cli,
|
|
507
|
-
task,
|
|
508
|
-
f"目标CLI工具 '{target_cli}' 不可用或未安装"
|
|
509
|
-
)
|
|
510
|
-
|
|
511
|
-
if not target_adapter.is_available():
|
|
512
|
-
logger.warning(f"目标CLI工具不可用: {target_cli}")
|
|
513
|
-
return self._format_workflow_error(
|
|
514
|
-
target_cli,
|
|
515
|
-
task,
|
|
516
|
-
f"目标CLI工具 '{target_cli}' 当前不可用"
|
|
517
|
-
)
|
|
518
|
-
|
|
519
|
-
# 构建执行上下文
|
|
520
|
-
execution_context = {
|
|
521
|
-
'source_cli': self.cli_name,
|
|
522
|
-
'target_cli': target_cli,
|
|
523
|
-
'original_task': task,
|
|
524
|
-
'workflow_context': context.__dict__,
|
|
525
|
-
'timestamp': datetime.now().isoformat()
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
# 执行任务
|
|
529
|
-
result = await target_adapter.execute_task(task, execution_context)
|
|
530
|
-
|
|
531
|
-
# 记录成功的跨CLI调用
|
|
532
|
-
self.processed_requests.append({
|
|
533
|
-
'type': 'cross_cli_workflow_execution',
|
|
534
|
-
'target_cli': target_cli,
|
|
535
|
-
'task': task,
|
|
536
|
-
'workflow_id': context.workflow_id,
|
|
537
|
-
'success': True,
|
|
538
|
-
'result_length': len(result),
|
|
539
|
-
'timestamp': datetime.now().isoformat()
|
|
540
|
-
})
|
|
541
|
-
|
|
542
|
-
# 格式化结果
|
|
543
|
-
formatted_result = self._format_workflow_result(target_cli, result, context)
|
|
544
|
-
|
|
545
|
-
logger.info(f"跨CLI工作流执行成功: {target_cli}")
|
|
546
|
-
return formatted_result
|
|
547
|
-
|
|
548
|
-
except Exception as e:
|
|
549
|
-
logger.error(f"跨CLI工作流执行失败: {target_cli}, {e}")
|
|
550
|
-
|
|
551
|
-
# 记录失败的跨CLI调用
|
|
552
|
-
self.processed_requests.append({
|
|
553
|
-
'type': 'cross_cli_workflow_execution',
|
|
554
|
-
'target_cli': target_cli,
|
|
555
|
-
'task': task,
|
|
556
|
-
'workflow_id': context.workflow_id,
|
|
557
|
-
'success': False,
|
|
558
|
-
'error': str(e),
|
|
559
|
-
'timestamp': datetime.now().isoformat()
|
|
560
|
-
})
|
|
561
|
-
|
|
562
|
-
return self._format_workflow_error(target_cli, task, str(e))
|
|
563
|
-
|
|
564
|
-
async def _execute_workflow(self, context: WorkflowContext) -> str:
|
|
565
|
-
"""
|
|
566
|
-
执行工作流
|
|
567
|
-
|
|
568
|
-
Args:
|
|
569
|
-
context: 工作流上下文
|
|
570
|
-
|
|
571
|
-
Returns:
|
|
572
|
-
str: 执行结果
|
|
573
|
-
"""
|
|
574
|
-
try:
|
|
575
|
-
# 触发工作流开始Hook
|
|
576
|
-
start_result = await self.on_workflow_start(context)
|
|
577
|
-
if start_result:
|
|
578
|
-
return start_result
|
|
579
|
-
|
|
580
|
-
# 执行各个阶段
|
|
581
|
-
final_result = None
|
|
582
|
-
for stage in self.pipeline_stages:
|
|
583
|
-
stage_context = WorkflowContext(
|
|
584
|
-
workflow_id=context.workflow_id,
|
|
585
|
-
stage=stage.name,
|
|
586
|
-
data=context.data
|
|
587
|
-
)
|
|
588
|
-
|
|
589
|
-
# 执行阶段
|
|
590
|
-
stage_result = await self._execute_stage(stage, stage_context)
|
|
591
|
-
|
|
592
|
-
# 触发阶段完成Hook
|
|
593
|
-
await self.on_stage_complete(stage_context, stage_result)
|
|
594
|
-
|
|
595
|
-
if stage_result is not None:
|
|
596
|
-
final_result = stage_result
|
|
597
|
-
|
|
598
|
-
# 触发工作流成功Hook
|
|
599
|
-
await self.on_workflow_success(context, final_result)
|
|
600
|
-
|
|
601
|
-
return final_result or "工作流执行完成"
|
|
602
|
-
|
|
603
|
-
except Exception as e:
|
|
604
|
-
# 触发工作流错误Hook
|
|
605
|
-
await self.on_workflow_error(context, e)
|
|
606
|
-
raise
|
|
607
|
-
|
|
608
|
-
async def _execute_stage(self, stage: WorkflowStage, context: WorkflowContext) -> Any:
|
|
609
|
-
"""
|
|
610
|
-
执行工作流阶段
|
|
611
|
-
|
|
612
|
-
Args:
|
|
613
|
-
stage: 工作流阶段
|
|
614
|
-
context: 工作流上下文
|
|
615
|
-
|
|
616
|
-
Returns:
|
|
617
|
-
Any: 阶段结果
|
|
618
|
-
"""
|
|
619
|
-
try:
|
|
620
|
-
stage.start_time = datetime.now()
|
|
621
|
-
stage.status = "running"
|
|
622
|
-
|
|
623
|
-
# 这里可以根据阶段名称执行不同的逻辑
|
|
624
|
-
if stage.name == "cross_cli_detection":
|
|
625
|
-
return await self._stage_cross_cli_detection(context)
|
|
626
|
-
elif stage.name == "target_execution":
|
|
627
|
-
return await self._stage_target_execution(context)
|
|
628
|
-
elif stage.name == "result_processing":
|
|
629
|
-
return await self._stage_result_processing(context)
|
|
630
|
-
elif stage.name == "output_formatting":
|
|
631
|
-
return await self._stage_output_formatting(context)
|
|
632
|
-
else:
|
|
633
|
-
# 默认处理
|
|
634
|
-
return f"阶段 {stage.name} 执行完成"
|
|
635
|
-
|
|
636
|
-
except Exception as e:
|
|
637
|
-
stage.status = "failed"
|
|
638
|
-
stage.error = str(e)
|
|
639
|
-
raise
|
|
640
|
-
finally:
|
|
641
|
-
stage.end_time = datetime.now()
|
|
642
|
-
if stage.error is None:
|
|
643
|
-
stage.status = "completed"
|
|
644
|
-
|
|
645
|
-
async def _stage_cross_cli_detection(self, context: WorkflowContext) -> Any:
|
|
646
|
-
"""跨CLI检测阶段"""
|
|
647
|
-
user_input = context.data.get('prompt', context.data.get('task', ''))
|
|
648
|
-
intent = self.parser.parse_intent(user_input, "iflow")
|
|
649
|
-
return intent
|
|
650
|
-
|
|
651
|
-
async def _stage_target_execution(self, context: WorkflowContext) -> Any:
|
|
652
|
-
"""目标执行阶段"""
|
|
653
|
-
# 这个阶段的逻辑在on_workflow_start中已经处理
|
|
654
|
-
return None
|
|
655
|
-
|
|
656
|
-
async def _stage_result_processing(self, context: WorkflowContext) -> Any:
|
|
657
|
-
"""结果处理阶段"""
|
|
658
|
-
return "结果处理完成"
|
|
659
|
-
|
|
660
|
-
async def _stage_output_formatting(self, context: WorkflowContext) -> Any:
|
|
661
|
-
"""输出格式化阶段"""
|
|
662
|
-
return "输出格式化完成"
|
|
663
|
-
|
|
664
|
-
def _format_workflow_result(
|
|
665
|
-
self,
|
|
666
|
-
target_cli: str,
|
|
667
|
-
result: str,
|
|
668
|
-
context: WorkflowContext
|
|
669
|
-
) -> str:
|
|
670
|
-
"""
|
|
671
|
-
格式化工作流结果
|
|
672
|
-
|
|
673
|
-
Args:
|
|
674
|
-
target_cli: 目标CLI工具
|
|
675
|
-
result: 执行结果
|
|
676
|
-
context: 工作流上下文
|
|
677
|
-
|
|
678
|
-
Returns:
|
|
679
|
-
str: 格式化的结果
|
|
680
|
-
"""
|
|
681
|
-
return f"""## 🔄 跨CLI工作流结果
|
|
682
|
-
|
|
683
|
-
**源工作流**: iFlow Pipeline ({context.workflow_id})
|
|
684
|
-
**目标CLI**: {target_cli.upper()}
|
|
685
|
-
**工作流阶段**: {context.stage}
|
|
686
|
-
**执行时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
|
687
|
-
|
|
688
|
-
---
|
|
689
|
-
|
|
690
|
-
{result}
|
|
691
|
-
|
|
692
|
-
---
|
|
693
|
-
|
|
694
|
-
*此结果由iFlow跨CLI集成系统通过Workflow Pipeline提供*"""
|
|
695
|
-
|
|
696
|
-
def _format_workflow_error(
|
|
697
|
-
self,
|
|
698
|
-
target_cli: str,
|
|
699
|
-
task: str,
|
|
700
|
-
error_message: str
|
|
701
|
-
) -> str:
|
|
702
|
-
"""
|
|
703
|
-
格式化工作流错误结果
|
|
704
|
-
|
|
705
|
-
Args:
|
|
706
|
-
target_cli: 目标CLI工具
|
|
707
|
-
task: 原始任务
|
|
708
|
-
error_message: 错误信息
|
|
709
|
-
|
|
710
|
-
Returns:
|
|
711
|
-
str: 格式化的错误结果
|
|
712
|
-
"""
|
|
713
|
-
return f"""## ❌ 跨CLI工作流失败
|
|
714
|
-
|
|
715
|
-
**源工作流**: iFlow Pipeline
|
|
716
|
-
**目标CLI**: {target_cli.upper()}
|
|
717
|
-
**错误信息**: {error_message}
|
|
718
|
-
**失败时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
|
719
|
-
|
|
720
|
-
请检查目标CLI工具是否正确安装和配置。
|
|
721
|
-
|
|
722
|
-
---
|
|
723
|
-
|
|
724
|
-
*此错误由iFlow跨CLI集成系统报告*"""
|
|
725
|
-
|
|
726
|
-
# ==================== 测试兼容方法 ====================
|
|
727
|
-
|
|
728
|
-
def _detect_cross_cli_intent(self, context: WorkflowContext) -> bool:
|
|
729
|
-
"""
|
|
730
|
-
检测跨CLI调用意图(测试兼容方法)
|
|
731
|
-
|
|
732
|
-
Args:
|
|
733
|
-
context: 工作流上下文
|
|
734
|
-
|
|
735
|
-
Returns:
|
|
736
|
-
bool: 是否为跨CLI调用
|
|
737
|
-
"""
|
|
738
|
-
try:
|
|
739
|
-
user_input = context.data.get('prompt', context.data.get('task', ''))
|
|
740
|
-
if not user_input:
|
|
741
|
-
return False
|
|
742
|
-
|
|
743
|
-
intent = self.parser.parse_intent(user_input, "iflow")
|
|
744
|
-
return intent.is_cross_cli
|
|
745
|
-
|
|
746
|
-
except Exception:
|
|
747
|
-
return False
|
|
748
|
-
|
|
749
|
-
def _parse_cross_cli_task(self, context: WorkflowContext) -> tuple:
|
|
750
|
-
"""
|
|
751
|
-
解析跨CLI任务(测试兼容方法)
|
|
752
|
-
|
|
753
|
-
Args:
|
|
754
|
-
context: 工作流上下文
|
|
755
|
-
|
|
756
|
-
Returns:
|
|
757
|
-
tuple: (target_cli, task)
|
|
758
|
-
"""
|
|
759
|
-
try:
|
|
760
|
-
user_input = context.data.get('prompt', context.data.get('task', ''))
|
|
761
|
-
if not user_input:
|
|
762
|
-
return None, None
|
|
763
|
-
|
|
764
|
-
intent = self.parser.parse_intent(user_input, "iflow")
|
|
765
|
-
if intent.is_cross_cli:
|
|
766
|
-
return intent.target_cli, intent.task
|
|
767
|
-
|
|
768
|
-
return None, None
|
|
769
|
-
|
|
770
|
-
except Exception:
|
|
771
|
-
return None, None
|
|
772
|
-
|
|
773
|
-
async def _execute_cross_cli_workflow_call(
|
|
774
|
-
self,
|
|
775
|
-
target_cli: str,
|
|
776
|
-
task: str,
|
|
777
|
-
context: WorkflowContext
|
|
778
|
-
) -> str:
|
|
779
|
-
"""
|
|
780
|
-
执行跨CLI工作流调用(测试兼容方法)
|
|
781
|
-
|
|
782
|
-
Args:
|
|
783
|
-
target_cli: 目标CLI工具
|
|
784
|
-
task: 要执行的任务
|
|
785
|
-
context: 工作流上下文
|
|
786
|
-
|
|
787
|
-
Returns:
|
|
788
|
-
str: 执行结果
|
|
789
|
-
"""
|
|
790
|
-
result = await self._execute_cross_cli_workflow(target_cli, task, context)
|
|
791
|
-
if result:
|
|
792
|
-
return result
|
|
793
|
-
return f"跨CLI工作流调用失败: {target_cli} -> {task}"
|