llm-tool-maker 0.1.0__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.
Files changed (48) hide show
  1. llm_tool_maker-0.1.0.dist-info/METADATA +199 -0
  2. llm_tool_maker-0.1.0.dist-info/RECORD +48 -0
  3. llm_tool_maker-0.1.0.dist-info/WHEEL +4 -0
  4. llm_tool_maker-0.1.0.dist-info/entry_points.txt +2 -0
  5. tool_maker/__init__.py +31 -0
  6. tool_maker/analyzer/__init__.py +7 -0
  7. tool_maker/analyzer/project_scanner.py +202 -0
  8. tool_maker/cli/__init__.py +7 -0
  9. tool_maker/cli/main.py +306 -0
  10. tool_maker/config.py +57 -0
  11. tool_maker/db/__init__.py +17 -0
  12. tool_maker/db/config.py +31 -0
  13. tool_maker/db/connection.py +157 -0
  14. tool_maker/db/migrations/001_initial.sql +60 -0
  15. tool_maker/db/migrator.py +121 -0
  16. tool_maker/db/models.py +226 -0
  17. tool_maker/db/pipeline.py +340 -0
  18. tool_maker/dotenv.py +75 -0
  19. tool_maker/flask/__init__.py +7 -0
  20. tool_maker/flask/extension.py +165 -0
  21. tool_maker/llm/__init__.py +7 -0
  22. tool_maker/llm/provider.py +227 -0
  23. tool_maker/planner/__init__.py +22 -0
  24. tool_maker/planner/executor.py +87 -0
  25. tool_maker/planner/models.py +61 -0
  26. tool_maker/planner/planner.py +112 -0
  27. tool_maker/planner/reviewer.py +73 -0
  28. tool_maker/planner/validator.py +109 -0
  29. tool_maker/planner/writer.py +34 -0
  30. tool_maker/tool/__init__.py +15 -0
  31. tool_maker/tool/executor.py +183 -0
  32. tool_maker/tool/generator.py +197 -0
  33. tool_maker/tool/sandbox.py +269 -0
  34. tool_maker/tool_fixer.py +134 -0
  35. tool_maker/tool_maker.py +385 -0
  36. tool_maker/ui/__init__.py +5 -0
  37. tool_maker/ui/app.py +62 -0
  38. tool_maker/ui/log_handler.py +61 -0
  39. tool_maker/ui/routes.py +552 -0
  40. tool_maker/ui/static/style.css +394 -0
  41. tool_maker/ui/templates/analyze.html +65 -0
  42. tool_maker/ui/templates/base.html +27 -0
  43. tool_maker/ui/templates/config.html +132 -0
  44. tool_maker/ui/templates/execute.html +289 -0
  45. tool_maker/ui/templates/generate.html +38 -0
  46. tool_maker/ui/templates/index.html +60 -0
  47. tool_maker/ui/templates/pipeline.html +377 -0
  48. tool_maker/ui/templates/provider.html +60 -0
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.4
2
+ Name: llm-tool-maker
3
+ Version: 0.1.0
4
+ Summary: An intelligent tool-making package that leverages LLMs to analyze projects and generate tools
5
+ Project-URL: Homepage, https://github.com/codewithwest/project_tool-maker
6
+ Project-URL: Repository, https://github.com/codewithwest/project_tool-maker
7
+ Project-URL: Documentation, https://github.com/codewithwest/project_tool-maker#readme
8
+ Project-URL: Issues, https://github.com/codewithwest/project_tool-maker/issues
9
+ Author-email: west <westdynamics.tech@gmail.com>
10
+ License: MIT
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Software Development :: Code Generators
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: httpx>=0.24.0
24
+ Requires-Dist: python-dotenv>=1.2.2
25
+ Requires-Dist: requests>=2.31.0
26
+ Requires-Dist: tomli>=2.0.0; python_version < '3.11'
27
+ Provides-Extra: all
28
+ Requires-Dist: flask>=2.3.0; extra == 'all'
29
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == 'all'
30
+ Provides-Extra: flask
31
+ Requires-Dist: flask>=2.3.0; extra == 'flask'
32
+ Provides-Extra: postgres
33
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == 'postgres'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Tool Maker Package
37
+
38
+ [![CI](https://github.com/codewithwest/project_tool-maker/actions/workflows/ci.yml/badge.svg)](https://github.com/codewithwest/project_tool-maker/actions/workflows/ci.yml)
39
+ [![PyPI version](https://img.shields.io/pypi/v/llm-tool-maker.svg)](https://pypi.org/project/llm-tool-maker/)
40
+ [![Python versions](https://img.shields.io/pypi/pyversions/llm-tool-maker.svg)](https://pypi.org/project/llm-tool-maker/)
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
42
+
43
+ An intelligent tool-making package that leverages LLMs to analyze projects and generate tools.
44
+
45
+ ## Overview
46
+
47
+ Tool Maker is a Python package that:
48
+ - Analyzes projects to understand their structure and capabilities
49
+ - Uses LLMs to formulate intelligent prompts and generate tools
50
+ - Can be integrated into Flask applications or used standalone
51
+ - Provides a CLI for easy command-line usage
52
+
53
+ ## Features
54
+
55
+ - **Project Analysis**: Automatically scans and analyzes project structure
56
+ - **LLM Integration**: Supports multiple LLM providers (OpenAI, Anthropic, local models)
57
+ - **Tool Generation**: Creates appropriate tools based on project capabilities
58
+ - **Flask Integration**: Easy integration with Flask applications
59
+ - **CLI Interface**: Command-line tool for quick usage
60
+
61
+ ## Installation
62
+
63
+ ### Using uv (Recommended)
64
+
65
+ ```bash
66
+ # Install globally
67
+ uv tool install llm-tool-maker
68
+
69
+ # Or add to a project
70
+ uv add llm-tool-maker
71
+ ```
72
+
73
+ ### From Source
74
+
75
+ ```bash
76
+ git clone https://github.com/codewithwest/project_tool-maker.git
77
+ cd tool-maker
78
+ uv sync
79
+ uv run tool-maker --help
80
+ ```
81
+
82
+ ## Quick Start
83
+
84
+ ### Standalone Usage
85
+
86
+ ```python
87
+ from tool_maker import ToolMaker
88
+
89
+ # Initialize with your LLM provider
90
+ tm = ToolMaker(
91
+ llm_provider="openai",
92
+ api_key="your-api-key"
93
+ )
94
+
95
+ # Analyze a project
96
+ project_info = tm.analyze_project("/path/to/project")
97
+
98
+ # Create and execute a tool
99
+ result = tm.create_and_execute_tool("Create a function to parse CSV files")
100
+ print(result)
101
+ ```
102
+
103
+ ### Flask Integration
104
+
105
+ ```python
106
+ from flask import Flask, request, jsonify
107
+ from tool_maker.flask import ToolMakerExtension
108
+
109
+ app = Flask(__name__)
110
+
111
+ # Initialize Tool Maker
112
+ tm = ToolMakerExtension(
113
+ app,
114
+ llm_provider="openai",
115
+ api_key="your-api-key"
116
+ )
117
+
118
+ @app.route('/analyze', methods=['POST'])
119
+ def analyze():
120
+ project_path = request.json.get('project_path')
121
+ return jsonify(tm.analyze_project(project_path))
122
+
123
+ @app.route('/tools', methods=['POST'])
124
+ def create_tool():
125
+ query = request.json.get('query')
126
+ return jsonify(tm.create_and_execute_tool(query))
127
+ ```
128
+
129
+ ## Project Structure
130
+
131
+ ```
132
+ tool_maker/
133
+ ├── analyzer/ # Project analysis module
134
+ ├── llm/ # LLM integration module
135
+ ├── tool/ # Tool generation and execution
136
+ ├── flask/ # Flask integration
137
+ └── cli/ # Command-line interface
138
+ ```
139
+
140
+ ## Configuration
141
+
142
+ ### LLM Providers
143
+
144
+ Tool Maker supports multiple LLM providers:
145
+
146
+ ```python
147
+ # OpenAI
148
+ tm = ToolMaker(llm_provider="openai", api_key="sk-...")
149
+
150
+ # Anthropic (Claude)
151
+ tm = ToolMaker(llm_provider="anthropic", api_key="sk-...")
152
+
153
+ # Local LLM (e.g., Ollama)
154
+ tm = ToolMaker(
155
+ llm_provider="ollama",
156
+ base_url="http://localhost:11434",
157
+ model="llama2"
158
+ )
159
+ ```
160
+
161
+ ## Development
162
+
163
+ ```bash
164
+ # Set up development environment
165
+ uv sync
166
+ uv run pytest
167
+
168
+ # Run linter
169
+ uv run ruff check .
170
+
171
+ # Format code
172
+ uv run black .
173
+ ```
174
+
175
+ ## Examples
176
+
177
+ See the `examples/` directory for more detailed examples:
178
+ - `basic_usage.py` - Standalone usage
179
+ - `flask_integration.py` - Flask integration
180
+ - `custom_analyzer.py` - Custom project analysis
181
+
182
+ ## Contributing
183
+
184
+ Contributions are welcome! Please feel free to submit a Pull Request.
185
+
186
+ 1. Fork the repository
187
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
188
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
189
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
190
+ 5. Open a Pull Request
191
+
192
+ ## License
193
+
194
+ This project is licensed under the MIT License - see the LICENSE file for details.
195
+
196
+ ## Acknowledgments
197
+
198
+ - Built with [uv](https://github.com/astral-sh/uv) for fast Python package management
199
+ - Inspired by AI-powered code generation tools
@@ -0,0 +1,48 @@
1
+ tool_maker/__init__.py,sha256=Fu-PmlqhGH17lYK6_6FHS0uQ6ZcnZVYn1HLhNftLu7Q,792
2
+ tool_maker/config.py,sha256=fLVdB0xp_tFmEurGKkQqMurFzEdyu_LeJo6w8TM6dSI,1504
3
+ tool_maker/dotenv.py,sha256=oT4RFo30JhXma6sf0IiWgxFTjLuNYeipmLE0k7EMQtI,2009
4
+ tool_maker/tool_fixer.py,sha256=U-Ekf1H-ckSZvzMhxaqAwoT2J5IBP9tnvX7T_h6Ftl0,4503
5
+ tool_maker/tool_maker.py,sha256=5C5wUpJJlNrrRtElcxp9duJPbvhS1le3lIgRh7XlAG0,15660
6
+ tool_maker/analyzer/__init__.py,sha256=fec7Oy7Dd4CjNhmFCBnGmtwij-0uh3ZJVn2Y6D32DmA,140
7
+ tool_maker/analyzer/project_scanner.py,sha256=dTQL0Aa0QSmANMKJWt06uF-Lw60nKSyWYsirkXI2Jr4,7246
8
+ tool_maker/cli/__init__.py,sha256=0FLqjwBp_1KGnsjyuixCA4q2VrZmHzX28TxeGOd2AB0,91
9
+ tool_maker/cli/main.py,sha256=I_U2qc5OZ2xTz2uQTczrkNYaxoiJ7FcgcNoAdxE2h9o,10735
10
+ tool_maker/db/__init__.py,sha256=UFrVdyPkqnVO3Xa2HpiHslQGsqngMwGO_hr05LN8HZM,356
11
+ tool_maker/db/config.py,sha256=D8ITwvcyXqtOaOTc5ylGuvTD6lDJqVoGIiQX3vjHSqw,666
12
+ tool_maker/db/connection.py,sha256=7qoZ3C8lOX379zLIGt3OHzH43FIBwgzgj9pciIajy0E,4769
13
+ tool_maker/db/migrator.py,sha256=BtPjI0Orgh9RJtTilLdedEqxfxlF0upZb4aHPl6o4Ic,3392
14
+ tool_maker/db/models.py,sha256=nrxOnL_2H3sz4G6yV7sm5Vdzb5hQ2OUcrdeRYqMXzYU,7979
15
+ tool_maker/db/pipeline.py,sha256=aF3jeE2jrA0G88otDfnzjBnipUqPRZjodhgPkXtS1rg,18400
16
+ tool_maker/db/migrations/001_initial.sql,sha256=Jqxh8SsrRyJl44xXye4svVYFC5t52mQTnwfP4cHduxk,1883
17
+ tool_maker/flask/__init__.py,sha256=kLZQhh9FKTEeelmu8_3y3N_3lL4_jNB0hHuRwH71rcI,152
18
+ tool_maker/flask/extension.py,sha256=oiW7GLHr1W-4aWywdFOLZGsSOKWDFApeh6d-tJ0WFvA,5254
19
+ tool_maker/llm/__init__.py,sha256=_SynbkHqhcgixvxgEsAarOCjEjImG73bX-SLArnMT-s,133
20
+ tool_maker/llm/provider.py,sha256=944shnSzZx1Sv1MvnLFjW9OFZ-aeWARqeDFpJiAIHzY,8182
21
+ tool_maker/planner/__init__.py,sha256=Uy_SmYzRGcOo7B4uGOmcfgBR3TgUXuqO8OIiG4e5RfI,483
22
+ tool_maker/planner/executor.py,sha256=_ec5v9Or5yUpK49kpUH4Tur6re85HKRgPoljpWfOJmc,2992
23
+ tool_maker/planner/models.py,sha256=Glxf3sLqG-fhvaxplFP67s84veyiTiHzFrh_r5fuHF8,1354
24
+ tool_maker/planner/planner.py,sha256=GTFD_JE5tniB21sm3Z60kL9qDuD1adKv5PeDeMxA4Z4,3726
25
+ tool_maker/planner/reviewer.py,sha256=cxG_2tbz1FLwOGx2CI0NieO8R8uOOxENBr666wnkhDE,2357
26
+ tool_maker/planner/validator.py,sha256=0qY_js8mNWLhd8HxwLQsFLW5A4rsR9CXoWwm7URP8NI,3446
27
+ tool_maker/planner/writer.py,sha256=pgisuWufvX1qnpqx8atlA-EixJjIqj4hd2Bp7Ve7WlA,1011
28
+ tool_maker/tool/__init__.py,sha256=OWVMRXdKKdOABkYdn6EPldQfwfA3mWt0q3XjsuVJ1Pc,317
29
+ tool_maker/tool/executor.py,sha256=H6N6zziqqHpHq6_WXMOgfVEkIepml3jlJVVgtCiORAg,5411
30
+ tool_maker/tool/generator.py,sha256=gIJvWNStEBszSVJpwe7mNtcIVvwUxjwP9mtetNbvtYU,6962
31
+ tool_maker/tool/sandbox.py,sha256=-bMSPJTOxDK6Dqq_YUbIs8KBPNKTAbloahEPjA5BmgU,7070
32
+ tool_maker/ui/__init__.py,sha256=Z-QaTL2IfyA4n8Wpy3-BVHz-wNQd_HQAFmVGQSyZXLE,113
33
+ tool_maker/ui/app.py,sha256=IQOPk5iszjLWn2sOxA52lpAFUl1yCDhu53xq78Jgc6U,1756
34
+ tool_maker/ui/log_handler.py,sha256=LJumsSBKNd-Lkk6vNxw5D6AWneggiImP9lN-Jp5IhTg,1813
35
+ tool_maker/ui/routes.py,sha256=a4_qo9wmuaOzrBA6BHVDUhM29_g9f04WGe3lHR8Na-o,17390
36
+ tool_maker/ui/static/style.css,sha256=a0vphjk0gEYC-DViGBXe7ZF3rqHyuUNqsoPSHhc7x4A,11637
37
+ tool_maker/ui/templates/analyze.html,sha256=XjXv1H05Ib44eSQIyeSYOZ16NKVvgYKbxUXtLtnPujM,1613
38
+ tool_maker/ui/templates/base.html,sha256=kDga9Drs-CfI3HNQOv-8H0-Zf0YYUi2t2yqINL4Idcw,881
39
+ tool_maker/ui/templates/config.html,sha256=oa_gpIV8OxhIfUVY29FgRDohX3_yahkfxUMp02MZ8Hc,4138
40
+ tool_maker/ui/templates/execute.html,sha256=5z63ImLnVgz53t4REU55BTR-n2XWGEoYzTX8kqb8-Z4,11101
41
+ tool_maker/ui/templates/generate.html,sha256=Cg3JDwjZrNRbWEWSwuXGZDWfEmHm7uaer6YY1R4Jbks,1447
42
+ tool_maker/ui/templates/index.html,sha256=97ziv9r3Xf6s74JFQBGthu88K6rKOEPTUrmxfzUZXDc,1901
43
+ tool_maker/ui/templates/pipeline.html,sha256=Hjel9HShHN0MatiTyKnKV_HqTUXMa0FcUXWeS_HOEzY,13236
44
+ tool_maker/ui/templates/provider.html,sha256=WxCJKpxV4AvNvNrCNQxLCLLUO487ZgHeJPp9_STAr4Q,1917
45
+ llm_tool_maker-0.1.0.dist-info/METADATA,sha256=OuG5joYDEL_xRBEOJJtW1NWfeRTEfQ2g3eb0f4Ufp74,5768
46
+ llm_tool_maker-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
47
+ llm_tool_maker-0.1.0.dist-info/entry_points.txt,sha256=J_34bQd3noKx-P4tmSB0K9ZMo-i5vN-thBukoqDwV90,60
48
+ llm_tool_maker-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ llm-tool-maker = tool_maker.cli.main:main
tool_maker/__init__.py ADDED
@@ -0,0 +1,31 @@
1
+ """
2
+ Tool Maker - An intelligent tool-making package that leverages LLMs.
3
+ """
4
+
5
+ __version__ = "0.1.0"
6
+ __author__ = "Your Name"
7
+
8
+ from tool_maker.analyzer.project_scanner import ProjectScanner
9
+ from tool_maker.config import ToolMakerConfigFile
10
+ from tool_maker.llm.provider import LLMProvider, get_provider
11
+ from tool_maker.tool.generator import ToolGenerator
12
+ from tool_maker.tool.executor import ToolExecutor
13
+ from tool_maker.tool_fixer import ToolFixer
14
+ from tool_maker.tool_maker import (
15
+ ToolMaker,
16
+ create_tool_maker,
17
+ create_tool_maker_from_env,
18
+ )
19
+
20
+ __all__ = [
21
+ "ProjectScanner",
22
+ "LLMProvider",
23
+ "get_provider",
24
+ "ToolGenerator",
25
+ "ToolExecutor",
26
+ "ToolFixer",
27
+ "ToolMakerConfigFile",
28
+ "ToolMaker",
29
+ "create_tool_maker",
30
+ "create_tool_maker_from_env",
31
+ ]
@@ -0,0 +1,7 @@
1
+ """
2
+ Project Analyzer - Scans and analyzes project structure.
3
+ """
4
+
5
+ from .project_scanner import ProjectScanner
6
+
7
+ __all__ = ["ProjectScanner"]
@@ -0,0 +1,202 @@
1
+ """
2
+ Project Scanner - Scans and analyzes project structure.
3
+ """
4
+
5
+ import ast
6
+ from pathlib import Path
7
+ from typing import Dict, List, Any, Optional
8
+ import json
9
+
10
+
11
+ class ProjectScanner:
12
+ """Scans and analyzes project structure to understand capabilities."""
13
+
14
+ def __init__(self, project_path: str):
15
+ self.project_path = Path(project_path)
16
+ self.modules: List[Dict[str, Any]] = []
17
+ self.dependencies: List[str] = []
18
+ self.entry_points: List[str] = []
19
+ self.project_info: Dict[str, Any] = {}
20
+
21
+ def scan(self) -> Dict[str, Any]:
22
+ """Scan the project and return analysis results."""
23
+ self._scan_modules()
24
+ self._scan_dependencies()
25
+ self._scan_entry_points()
26
+ self._analyze_project()
27
+
28
+ return self.project_info
29
+
30
+ def _scan_modules(self) -> None:
31
+ """Scan Python modules in the project."""
32
+ for py_file in self.project_path.rglob("*.py"):
33
+ if self._should_skip_file(py_file):
34
+ continue
35
+
36
+ try:
37
+ with open(py_file, 'r', encoding='utf-8') as f:
38
+ content = f.read()
39
+
40
+ module_info = {
41
+ "path": str(py_file.relative_to(self.project_path)),
42
+ "name": self._get_module_name(py_file),
43
+ "functions": [],
44
+ "classes": [],
45
+ "imports": []
46
+ }
47
+
48
+ try:
49
+ tree = ast.parse(content)
50
+ module_info = self._parse_ast(tree, module_info)
51
+ except SyntaxError:
52
+ pass
53
+
54
+ self.modules.append(module_info)
55
+ except Exception:
56
+ # Skip files that can't be read or parsed
57
+ continue
58
+
59
+ def _parse_ast(self, tree: ast.AST, module_info: Dict[str, Any]) -> Dict[str, Any]:
60
+ """Parse AST to extract functions, classes, and imports."""
61
+ for node in ast.iter_child_nodes(tree):
62
+ if isinstance(node, ast.FunctionDef):
63
+ module_info["functions"].append({
64
+ "name": node.name,
65
+ "line": node.lineno,
66
+ "docstring": ast.get_docstring(node)
67
+ })
68
+ elif isinstance(node, ast.ClassDef):
69
+ module_info["classes"].append({
70
+ "name": node.name,
71
+ "line": node.lineno,
72
+ "docstring": ast.get_docstring(node)
73
+ })
74
+ elif isinstance(node, ast.Import):
75
+ for alias in node.names:
76
+ module_info["imports"].append(alias.name)
77
+ elif isinstance(node, ast.ImportFrom):
78
+ if node.module:
79
+ for alias in node.names:
80
+ module_info["imports"].append(f"{node.module}.{alias.name}")
81
+
82
+ return module_info
83
+
84
+ def _should_skip_file(self, file_path: Path) -> bool:
85
+ """Determine if a file should be skipped during scanning."""
86
+ skip_patterns = [
87
+ "__pycache__",
88
+ ".venv",
89
+ "venv",
90
+ ".git",
91
+ ".env",
92
+ "node_modules",
93
+ ".mypy_cache",
94
+ ".pytest_cache",
95
+ "dist",
96
+ "build"
97
+ ]
98
+
99
+ return any(pattern in str(file_path) for pattern in skip_patterns)
100
+
101
+ def _get_module_name(self, file_path: Path) -> str:
102
+ """Get the module name from a file path."""
103
+ parts = []
104
+ for part in file_path.relative_to(self.project_path).parts:
105
+ if part == "__init__.py":
106
+ continue
107
+ parts.append(part.replace(".py", ""))
108
+
109
+ return ".".join(parts)
110
+
111
+ def _scan_dependencies(self) -> None:
112
+ """Scan for project dependencies."""
113
+ # Check for pyproject.toml
114
+ pyproject_path = self.project_path / "pyproject.toml"
115
+ if pyproject_path.exists():
116
+ try:
117
+ import tomli
118
+ with open(pyproject_path, 'rb') as f:
119
+ data = tomli.load(f)
120
+
121
+ if "project" in data and "dependencies" in data["project"]:
122
+ self.dependencies = data["project"]["dependencies"]
123
+ except ImportError:
124
+ # Try basic parsing if tomli is not available
125
+ pass
126
+
127
+ # Check for requirements.txt
128
+ requirements_path = self.project_path / "requirements.txt"
129
+ if requirements_path.exists():
130
+ with open(requirements_path, 'r') as f:
131
+ self.dependencies = [
132
+ line.strip() for line in f
133
+ if line.strip() and not line.startswith("#")
134
+ ]
135
+
136
+ def _scan_entry_points(self) -> None:
137
+ """Scan for entry points (main files, Flask apps, etc.)."""
138
+ # Look for common entry point patterns
139
+ entry_point_patterns = [
140
+ "main.py",
141
+ "app.py",
142
+ "wsgi.py",
143
+ "run.py",
144
+ "server.py"
145
+ ]
146
+
147
+ for pattern in entry_point_patterns:
148
+ entry_path = self.project_path / pattern
149
+ if entry_path.exists():
150
+ self.entry_points.append(str(entry_path.relative_to(self.project_path)))
151
+
152
+ def _analyze_project(self) -> None:
153
+ """Analyze the project and create a summary."""
154
+ self.project_info = {
155
+ "path": str(self.project_path),
156
+ "name": self.project_path.name,
157
+ "modules_count": len(self.modules),
158
+ "total_functions": sum(len(m["functions"]) for m in self.modules),
159
+ "total_classes": sum(len(m["classes"]) for m in self.modules),
160
+ "dependencies": self.dependencies,
161
+ "entry_points": self.entry_points,
162
+ "modules": self.modules,
163
+ "summary": self._generate_summary()
164
+ }
165
+
166
+ def _generate_summary(self) -> str:
167
+ """Generate a summary of the project."""
168
+ if not self.modules:
169
+ return "No Python modules found."
170
+
171
+ summary_parts = [
172
+ f"Project '{self.project_path.name}' contains {len(self.modules)} modules",
173
+ f"with {sum(len(m['functions']) for m in self.modules)} functions and "
174
+ f"{sum(len(m['classes']) for m in self.modules)} classes."
175
+ ]
176
+
177
+ if self.dependencies:
178
+ summary_parts.append(f"Has {len(self.dependencies)} dependencies.")
179
+
180
+ if self.entry_points:
181
+ summary_parts.append(f"Entry points: {', '.join(self.entry_points)}.")
182
+
183
+ return " ".join(summary_parts)
184
+
185
+ def get_module_by_name(self, name: str) -> Optional[Dict[str, Any]]:
186
+ """Get a module by its name."""
187
+ for module in self.modules:
188
+ if module["name"] == name:
189
+ return module
190
+ return None
191
+
192
+ def get_functions_by_module(self, module_name: str) -> List[Dict[str, Any]]:
193
+ """Get all functions in a specific module."""
194
+ module = self.get_module_by_name(module_name)
195
+ if module:
196
+ return module["functions"]
197
+ return []
198
+
199
+ def save_analysis(self, output_path: str) -> None:
200
+ """Save the analysis to a JSON file."""
201
+ with open(output_path, 'w') as f:
202
+ json.dump(self.project_info, f, indent=2)
@@ -0,0 +1,7 @@
1
+ """
2
+ Command-line interface for Tool Maker.
3
+ """
4
+
5
+ from .main import main
6
+
7
+ __all__ = ["main"]