deepcode-hku 1.0.1__py3-none-any.whl
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.
- cli/__init__.py +18 -0
- cli/cli_app.py +296 -0
- cli/cli_interface.py +744 -0
- cli/cli_launcher.py +155 -0
- cli/main_cli.py +243 -0
- cli/workflows/__init__.py +11 -0
- cli/workflows/cli_workflow_adapter.py +336 -0
- deepcode.py +219 -0
- deepcode_hku-1.0.1.dist-info/METADATA +695 -0
- deepcode_hku-1.0.1.dist-info/RECORD +44 -0
- deepcode_hku-1.0.1.dist-info/WHEEL +5 -0
- deepcode_hku-1.0.1.dist-info/entry_points.txt +2 -0
- deepcode_hku-1.0.1.dist-info/licenses/LICENSE +21 -0
- deepcode_hku-1.0.1.dist-info/top_level.txt +6 -0
- tools/__init__.py +0 -0
- tools/code_implementation_server.py +1045 -0
- tools/code_indexer.py +1657 -0
- tools/code_reference_indexer.py +486 -0
- tools/command_executor.py +324 -0
- tools/git_command.py +356 -0
- tools/pdf_converter.py +640 -0
- tools/pdf_downloader.py +1370 -0
- tools/pdf_utils.py +52 -0
- ui/__init__.py +43 -0
- ui/app.py +13 -0
- ui/components.py +1450 -0
- ui/handlers.py +773 -0
- ui/layout.py +106 -0
- ui/streamlit_app.py +38 -0
- ui/styles.py +2116 -0
- utils/__init__.py +17 -0
- utils/cli_interface.py +459 -0
- utils/dialogue_logger.py +671 -0
- utils/file_processor.py +426 -0
- utils/simple_llm_logger.py +198 -0
- workflows/__init__.py +31 -0
- workflows/agent_orchestration_engine.py +1371 -0
- workflows/agents/__init__.py +13 -0
- workflows/agents/code_implementation_agent.py +1093 -0
- workflows/agents/memory_agent_concise.py +923 -0
- workflows/agents/memory_agent_concise_index.py +935 -0
- workflows/code_implementation_workflow.py +924 -0
- workflows/code_implementation_workflow_index.py +931 -0
- workflows/codebase_index_workflow.py +726 -0
cli/cli_launcher.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
DeepCode - CLI Research Engine Launcher
|
|
4
|
+
DeepCode - CLI研究引擎启动器
|
|
5
|
+
|
|
6
|
+
🧬 Open-Source Code Agent by Data Intelligence Lab @ HKU (CLI Edition)
|
|
7
|
+
⚡ Revolutionizing research reproducibility through collaborative AI via command line
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def check_dependencies():
|
|
15
|
+
"""检查必要的依赖是否已安装 / Check if necessary dependencies are installed"""
|
|
16
|
+
import importlib.util
|
|
17
|
+
|
|
18
|
+
print("🔍 Checking CLI dependencies...")
|
|
19
|
+
|
|
20
|
+
missing_deps = []
|
|
21
|
+
|
|
22
|
+
# Check asyncio availability
|
|
23
|
+
if importlib.util.find_spec("asyncio") is not None:
|
|
24
|
+
print("✅ Asyncio is available")
|
|
25
|
+
else:
|
|
26
|
+
missing_deps.append("asyncio")
|
|
27
|
+
|
|
28
|
+
# Check PyYAML availability
|
|
29
|
+
if importlib.util.find_spec("yaml") is not None:
|
|
30
|
+
print("✅ PyYAML is installed")
|
|
31
|
+
else:
|
|
32
|
+
missing_deps.append("pyyaml")
|
|
33
|
+
|
|
34
|
+
# Check Tkinter availability
|
|
35
|
+
if importlib.util.find_spec("tkinter") is not None:
|
|
36
|
+
print("✅ Tkinter is available (for file dialogs)")
|
|
37
|
+
else:
|
|
38
|
+
print("⚠️ Tkinter not available - file dialogs will use manual input")
|
|
39
|
+
|
|
40
|
+
# Check for MCP agent dependencies
|
|
41
|
+
if importlib.util.find_spec("mcp_agent.app") is not None:
|
|
42
|
+
print("✅ MCP Agent framework is available")
|
|
43
|
+
else:
|
|
44
|
+
missing_deps.append("mcp-agent")
|
|
45
|
+
|
|
46
|
+
# Check for workflow dependencies
|
|
47
|
+
# 添加项目根目录到路径
|
|
48
|
+
current_dir = Path(__file__).parent
|
|
49
|
+
project_root = current_dir.parent
|
|
50
|
+
if str(project_root) not in sys.path:
|
|
51
|
+
sys.path.insert(0, str(project_root))
|
|
52
|
+
|
|
53
|
+
if importlib.util.find_spec("workflows.agent_orchestration_engine") is not None:
|
|
54
|
+
print("✅ Workflow modules are available")
|
|
55
|
+
else:
|
|
56
|
+
print("⚠️ Workflow modules may not be properly configured")
|
|
57
|
+
|
|
58
|
+
# Check for CLI components
|
|
59
|
+
if importlib.util.find_spec("cli.cli_app") is not None:
|
|
60
|
+
print("✅ CLI application components are available")
|
|
61
|
+
else:
|
|
62
|
+
print("❌ CLI application components missing")
|
|
63
|
+
missing_deps.append("cli-components")
|
|
64
|
+
|
|
65
|
+
if missing_deps:
|
|
66
|
+
print("\n❌ Missing dependencies:")
|
|
67
|
+
for dep in missing_deps:
|
|
68
|
+
print(f" - {dep}")
|
|
69
|
+
print("\nPlease install missing dependencies using:")
|
|
70
|
+
print(
|
|
71
|
+
f"pip install {' '.join([d for d in missing_deps if d != 'cli-components'])}"
|
|
72
|
+
)
|
|
73
|
+
if "cli-components" in missing_deps:
|
|
74
|
+
print(
|
|
75
|
+
"CLI components appear to be missing - please check the cli/ directory"
|
|
76
|
+
)
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
print("✅ All CLI dependencies satisfied")
|
|
80
|
+
return True
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def print_banner():
|
|
84
|
+
"""显示CLI启动横幅 / Display CLI startup banner"""
|
|
85
|
+
banner = """
|
|
86
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
87
|
+
║ ║
|
|
88
|
+
║ 🧬 DeepCode - Open-Source Code Agent ║
|
|
89
|
+
║ ║
|
|
90
|
+
║ ⚡ DATA INTELLIGENCE LAB @ HKU ⚡ ║
|
|
91
|
+
║ ║
|
|
92
|
+
║ ║
|
|
93
|
+
║ ║
|
|
94
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
95
|
+
"""
|
|
96
|
+
print(banner)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def main():
|
|
100
|
+
"""主函数 / Main function"""
|
|
101
|
+
print_banner()
|
|
102
|
+
|
|
103
|
+
# 检查依赖 / Check dependencies
|
|
104
|
+
if not check_dependencies():
|
|
105
|
+
print("\n🚨 Please install missing dependencies and try again.")
|
|
106
|
+
sys.exit(1)
|
|
107
|
+
|
|
108
|
+
# 获取当前脚本目录 / Get current script directory
|
|
109
|
+
current_dir = Path(__file__).parent
|
|
110
|
+
project_root = current_dir.parent
|
|
111
|
+
cli_app_path = current_dir / "cli_app.py"
|
|
112
|
+
|
|
113
|
+
# 检查cli_app.py是否存在 / Check if cli_app.py exists
|
|
114
|
+
if not cli_app_path.exists():
|
|
115
|
+
print(f"❌ CLI application file not found: {cli_app_path}")
|
|
116
|
+
print("Please ensure the cli/cli_app.py file exists.")
|
|
117
|
+
sys.exit(1)
|
|
118
|
+
|
|
119
|
+
print(f"\n📁 CLI App location: {cli_app_path}")
|
|
120
|
+
print("🖥️ Starting DeepCode CLI interface...")
|
|
121
|
+
print("🚀 Initializing command line application")
|
|
122
|
+
print("=" * 70)
|
|
123
|
+
print("💡 Tip: Follow the interactive prompts to process your research")
|
|
124
|
+
print("🛑 Press Ctrl+C to exit at any time")
|
|
125
|
+
print("=" * 70)
|
|
126
|
+
|
|
127
|
+
# 启动CLI应用 / Launch CLI application
|
|
128
|
+
try:
|
|
129
|
+
# 导入并运行CLI应用
|
|
130
|
+
if str(project_root) not in sys.path:
|
|
131
|
+
sys.path.insert(0, str(project_root)) # 添加项目根目录到路径
|
|
132
|
+
from cli.cli_app import main as cli_main
|
|
133
|
+
|
|
134
|
+
print("\n🎯 Launching CLI application...")
|
|
135
|
+
|
|
136
|
+
# 使用asyncio运行主函数
|
|
137
|
+
import asyncio
|
|
138
|
+
|
|
139
|
+
asyncio.run(cli_main())
|
|
140
|
+
|
|
141
|
+
except KeyboardInterrupt:
|
|
142
|
+
print("\n\n🛑 DeepCode CLI stopped by user")
|
|
143
|
+
print("Thank you for using DeepCode CLI! 🧬")
|
|
144
|
+
except ImportError as e:
|
|
145
|
+
print(f"\n❌ Failed to import CLI application: {e}")
|
|
146
|
+
print("Please check if all modules are properly installed.")
|
|
147
|
+
sys.exit(1)
|
|
148
|
+
except Exception as e:
|
|
149
|
+
print(f"\n❌ Unexpected error: {e}")
|
|
150
|
+
print("Please check your Python environment and try again.")
|
|
151
|
+
sys.exit(1)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
main()
|
cli/main_cli.py
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
DeepCode CLI - Open-Source Code Agent
|
|
4
|
+
深度代码CLI - 开源代码智能体
|
|
5
|
+
|
|
6
|
+
🧬 Data Intelligence Lab @ HKU
|
|
7
|
+
⚡ Revolutionizing Research Reproducibility through Multi-Agent Architecture
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
import asyncio
|
|
13
|
+
import argparse
|
|
14
|
+
|
|
15
|
+
# 禁止生成.pyc文件
|
|
16
|
+
os.environ["PYTHONDONTWRITEBYTECODE"] = "1"
|
|
17
|
+
|
|
18
|
+
# 添加项目根目录到路径
|
|
19
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
20
|
+
parent_dir = os.path.dirname(current_dir)
|
|
21
|
+
if parent_dir not in sys.path:
|
|
22
|
+
sys.path.insert(0, parent_dir)
|
|
23
|
+
|
|
24
|
+
# 导入CLI应用
|
|
25
|
+
from cli.cli_app import CLIApp, Colors
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def print_enhanced_banner():
|
|
29
|
+
"""显示增强版启动横幅"""
|
|
30
|
+
banner = f"""
|
|
31
|
+
{Colors.CYAN}╔══════════════════════════════════════════════════════════════════════════════╗
|
|
32
|
+
║ ║
|
|
33
|
+
║ {Colors.BOLD}{Colors.MAGENTA}🧬 DeepCode - Open-Source Code Agent{Colors.CYAN} ║
|
|
34
|
+
║ ║
|
|
35
|
+
║ {Colors.BOLD}{Colors.YELLOW}⚡ DATA INTELLIGENCE LAB @ HKU ⚡{Colors.CYAN} ║
|
|
36
|
+
║ ║
|
|
37
|
+
║ Revolutionizing research reproducibility through collaborative AI ║
|
|
38
|
+
║ Building the future where code is reproduced from natural language ║
|
|
39
|
+
║ ║
|
|
40
|
+
║ {Colors.BOLD}{Colors.GREEN}🤖 Key Features:{Colors.CYAN} ║
|
|
41
|
+
║ • Automated paper-to-code reproduction ║
|
|
42
|
+
║ • Multi-agent collaborative architecture ║
|
|
43
|
+
║ • Open-source and extensible design ║
|
|
44
|
+
║ • Join our growing research community ║
|
|
45
|
+
║ ║
|
|
46
|
+
╚══════════════════════════════════════════════════════════════════════════════╝{Colors.ENDC}
|
|
47
|
+
"""
|
|
48
|
+
print(banner)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def check_environment():
|
|
52
|
+
"""检查运行环境"""
|
|
53
|
+
print(f"{Colors.CYAN}🔍 Checking environment...{Colors.ENDC}")
|
|
54
|
+
|
|
55
|
+
# 检查Python版本
|
|
56
|
+
if sys.version_info < (3, 8):
|
|
57
|
+
print(
|
|
58
|
+
f"{Colors.FAIL}❌ Python 3.8+ required. Current: {sys.version}{Colors.ENDC}"
|
|
59
|
+
)
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
print(f"{Colors.OKGREEN}✅ Python {sys.version.split()[0]} - OK{Colors.ENDC}")
|
|
63
|
+
|
|
64
|
+
# 检查必要模块
|
|
65
|
+
required_modules = [
|
|
66
|
+
("asyncio", "Async IO support"),
|
|
67
|
+
("pathlib", "Path handling"),
|
|
68
|
+
("typing", "Type hints"),
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
missing_modules = []
|
|
72
|
+
for module, desc in required_modules:
|
|
73
|
+
try:
|
|
74
|
+
__import__(module)
|
|
75
|
+
print(f"{Colors.OKGREEN}✅ {desc} - OK{Colors.ENDC}")
|
|
76
|
+
except ImportError:
|
|
77
|
+
missing_modules.append(module)
|
|
78
|
+
print(f"{Colors.FAIL}❌ {desc} - Missing{Colors.ENDC}")
|
|
79
|
+
|
|
80
|
+
if missing_modules:
|
|
81
|
+
print(
|
|
82
|
+
f"{Colors.FAIL}❌ Missing required modules: {', '.join(missing_modules)}{Colors.ENDC}"
|
|
83
|
+
)
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
print(f"{Colors.OKGREEN}✅ Environment check passed{Colors.ENDC}")
|
|
87
|
+
return True
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def parse_arguments():
|
|
91
|
+
"""解析命令行参数"""
|
|
92
|
+
parser = argparse.ArgumentParser(
|
|
93
|
+
description="DeepCode CLI - Open-Source Code Agent by Data Intelligence Lab @ HKU",
|
|
94
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
95
|
+
epilog=f"""
|
|
96
|
+
{Colors.BOLD}Examples:{Colors.ENDC}
|
|
97
|
+
{Colors.CYAN}python main_cli.py{Colors.ENDC} # Interactive mode
|
|
98
|
+
{Colors.CYAN}python main_cli.py --file paper.pdf{Colors.ENDC} # Process file directly
|
|
99
|
+
{Colors.CYAN}python main_cli.py --url https://...{Colors.ENDC} # Process URL directly
|
|
100
|
+
{Colors.CYAN}python main_cli.py --chat "Build a web app..."{Colors.ENDC} # Process chat requirements
|
|
101
|
+
{Colors.CYAN}python main_cli.py --optimized{Colors.ENDC} # Use optimized mode
|
|
102
|
+
|
|
103
|
+
{Colors.BOLD}Pipeline Modes:{Colors.ENDC}
|
|
104
|
+
{Colors.GREEN}Comprehensive{Colors.ENDC}: Full intelligence analysis with indexing
|
|
105
|
+
{Colors.YELLOW}Optimized{Colors.ENDC}: Fast processing without indexing
|
|
106
|
+
""",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"--file", "-f", type=str, help="Process a specific file (PDF, DOCX, TXT, etc.)"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
parser.add_argument(
|
|
114
|
+
"--url", "-u", type=str, help="Process a research paper from URL"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
parser.add_argument(
|
|
118
|
+
"--chat",
|
|
119
|
+
"-t",
|
|
120
|
+
type=str,
|
|
121
|
+
help="Process coding requirements via chat input (provide requirements as argument)",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
parser.add_argument(
|
|
125
|
+
"--optimized",
|
|
126
|
+
"-o",
|
|
127
|
+
action="store_true",
|
|
128
|
+
help="Use optimized mode (skip indexing for faster processing)",
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
parser.add_argument(
|
|
132
|
+
"--verbose", "-v", action="store_true", help="Enable verbose output"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
return parser.parse_args()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
async def run_direct_processing(app: CLIApp, input_source: str, input_type: str):
|
|
139
|
+
"""直接处理模式(非交互式)"""
|
|
140
|
+
try:
|
|
141
|
+
print(
|
|
142
|
+
f"\n{Colors.BOLD}{Colors.CYAN}🚀 Starting direct processing mode...{Colors.ENDC}"
|
|
143
|
+
)
|
|
144
|
+
print(f"{Colors.CYAN}Input: {input_source}{Colors.ENDC}")
|
|
145
|
+
print(f"{Colors.CYAN}Type: {input_type}{Colors.ENDC}")
|
|
146
|
+
print(
|
|
147
|
+
f"{Colors.CYAN}Mode: {'🧠 Comprehensive' if app.cli.enable_indexing else '⚡ Optimized'}{Colors.ENDC}"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# 初始化应用
|
|
151
|
+
init_result = await app.initialize_mcp_app()
|
|
152
|
+
if init_result["status"] != "success":
|
|
153
|
+
print(
|
|
154
|
+
f"{Colors.FAIL}❌ Initialization failed: {init_result['message']}{Colors.ENDC}"
|
|
155
|
+
)
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
# 处理输入
|
|
159
|
+
result = await app.process_input(input_source, input_type)
|
|
160
|
+
|
|
161
|
+
if result["status"] == "success":
|
|
162
|
+
print(
|
|
163
|
+
f"\n{Colors.BOLD}{Colors.OKGREEN}🎉 Processing completed successfully!{Colors.ENDC}"
|
|
164
|
+
)
|
|
165
|
+
return True
|
|
166
|
+
else:
|
|
167
|
+
print(
|
|
168
|
+
f"\n{Colors.BOLD}{Colors.FAIL}❌ Processing failed: {result.get('error', 'Unknown error')}{Colors.ENDC}"
|
|
169
|
+
)
|
|
170
|
+
return False
|
|
171
|
+
|
|
172
|
+
except Exception as e:
|
|
173
|
+
print(f"\n{Colors.FAIL}❌ Direct processing error: {str(e)}{Colors.ENDC}")
|
|
174
|
+
return False
|
|
175
|
+
finally:
|
|
176
|
+
await app.cleanup_mcp_app()
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
async def main():
|
|
180
|
+
"""主函数"""
|
|
181
|
+
# 解析命令行参数
|
|
182
|
+
args = parse_arguments()
|
|
183
|
+
|
|
184
|
+
# 显示横幅
|
|
185
|
+
print_enhanced_banner()
|
|
186
|
+
|
|
187
|
+
# 检查环境
|
|
188
|
+
if not check_environment():
|
|
189
|
+
print(
|
|
190
|
+
f"\n{Colors.FAIL}🚨 Environment check failed. Please fix the issues and try again.{Colors.ENDC}"
|
|
191
|
+
)
|
|
192
|
+
sys.exit(1)
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
# 创建CLI应用
|
|
196
|
+
app = CLIApp()
|
|
197
|
+
|
|
198
|
+
# 设置配置
|
|
199
|
+
if args.optimized:
|
|
200
|
+
app.cli.enable_indexing = False
|
|
201
|
+
print(
|
|
202
|
+
f"\n{Colors.YELLOW}⚡ Optimized mode enabled - indexing disabled{Colors.ENDC}"
|
|
203
|
+
)
|
|
204
|
+
else:
|
|
205
|
+
print(
|
|
206
|
+
f"\n{Colors.GREEN}🧠 Comprehensive mode enabled - full intelligence analysis{Colors.ENDC}"
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# 检查是否为直接处理模式
|
|
210
|
+
if args.file or args.url or args.chat:
|
|
211
|
+
if args.file:
|
|
212
|
+
# 验证文件存在
|
|
213
|
+
if not os.path.exists(args.file):
|
|
214
|
+
print(f"{Colors.FAIL}❌ File not found: {args.file}{Colors.ENDC}")
|
|
215
|
+
sys.exit(1)
|
|
216
|
+
success = await run_direct_processing(app, args.file, "file")
|
|
217
|
+
elif args.url:
|
|
218
|
+
success = await run_direct_processing(app, args.url, "url")
|
|
219
|
+
elif args.chat:
|
|
220
|
+
# 验证chat输入长度
|
|
221
|
+
if len(args.chat.strip()) < 20:
|
|
222
|
+
print(
|
|
223
|
+
f"{Colors.FAIL}❌ Chat input too short. Please provide more detailed requirements (at least 20 characters){Colors.ENDC}"
|
|
224
|
+
)
|
|
225
|
+
sys.exit(1)
|
|
226
|
+
success = await run_direct_processing(app, args.chat, "chat")
|
|
227
|
+
|
|
228
|
+
sys.exit(0 if success else 1)
|
|
229
|
+
else:
|
|
230
|
+
# 交互式模式
|
|
231
|
+
print(f"\n{Colors.CYAN}🎮 Starting interactive mode...{Colors.ENDC}")
|
|
232
|
+
await app.run_interactive_session()
|
|
233
|
+
|
|
234
|
+
except KeyboardInterrupt:
|
|
235
|
+
print(f"\n{Colors.WARNING}⚠️ Application interrupted by user{Colors.ENDC}")
|
|
236
|
+
sys.exit(1)
|
|
237
|
+
except Exception as e:
|
|
238
|
+
print(f"\n{Colors.FAIL}❌ Application errors: {str(e)}{Colors.ENDC}")
|
|
239
|
+
sys.exit(1)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
if __name__ == "__main__":
|
|
243
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI-specific Workflow Adapters
|
|
3
|
+
CLI专用工作流适配器
|
|
4
|
+
|
|
5
|
+
This module provides CLI-optimized versions of workflow components that are
|
|
6
|
+
specifically adapted for command-line interface usage patterns.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .cli_workflow_adapter import CLIWorkflowAdapter
|
|
10
|
+
|
|
11
|
+
__all__ = ["CLIWorkflowAdapter"]
|