diagram-to-iac 0.7.0__py3-none-any.whl → 0.8.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.
- diagram_to_iac/__init__.py +10 -0
- diagram_to_iac/actions/__init__.py +7 -0
- diagram_to_iac/actions/git_entry.py +174 -0
- diagram_to_iac/actions/supervisor_entry.py +116 -0
- diagram_to_iac/actions/terraform_agent_entry.py +207 -0
- diagram_to_iac/agents/__init__.py +26 -0
- diagram_to_iac/agents/demonstrator_langgraph/__init__.py +10 -0
- diagram_to_iac/agents/demonstrator_langgraph/agent.py +826 -0
- diagram_to_iac/agents/git_langgraph/__init__.py +10 -0
- diagram_to_iac/agents/git_langgraph/agent.py +1018 -0
- diagram_to_iac/agents/git_langgraph/pr.py +146 -0
- diagram_to_iac/agents/hello_langgraph/__init__.py +9 -0
- diagram_to_iac/agents/hello_langgraph/agent.py +621 -0
- diagram_to_iac/agents/policy_agent/__init__.py +15 -0
- diagram_to_iac/agents/policy_agent/agent.py +507 -0
- diagram_to_iac/agents/policy_agent/integration_example.py +191 -0
- diagram_to_iac/agents/policy_agent/tools/__init__.py +14 -0
- diagram_to_iac/agents/policy_agent/tools/tfsec_tool.py +259 -0
- diagram_to_iac/agents/shell_langgraph/__init__.py +21 -0
- diagram_to_iac/agents/shell_langgraph/agent.py +122 -0
- diagram_to_iac/agents/shell_langgraph/detector.py +50 -0
- diagram_to_iac/agents/supervisor_langgraph/__init__.py +17 -0
- diagram_to_iac/agents/supervisor_langgraph/agent.py +1947 -0
- diagram_to_iac/agents/supervisor_langgraph/demonstrator.py +22 -0
- diagram_to_iac/agents/supervisor_langgraph/guards.py +23 -0
- diagram_to_iac/agents/supervisor_langgraph/pat_loop.py +49 -0
- diagram_to_iac/agents/supervisor_langgraph/router.py +9 -0
- diagram_to_iac/agents/terraform_langgraph/__init__.py +15 -0
- diagram_to_iac/agents/terraform_langgraph/agent.py +1216 -0
- diagram_to_iac/agents/terraform_langgraph/parser.py +76 -0
- diagram_to_iac/core/__init__.py +7 -0
- diagram_to_iac/core/agent_base.py +19 -0
- diagram_to_iac/core/enhanced_memory.py +302 -0
- diagram_to_iac/core/errors.py +4 -0
- diagram_to_iac/core/issue_tracker.py +49 -0
- diagram_to_iac/core/memory.py +132 -0
- diagram_to_iac/services/__init__.py +10 -0
- diagram_to_iac/services/observability.py +59 -0
- diagram_to_iac/services/step_summary.py +77 -0
- diagram_to_iac/tools/__init__.py +11 -0
- diagram_to_iac/tools/api_utils.py +108 -26
- diagram_to_iac/tools/git/__init__.py +45 -0
- diagram_to_iac/tools/git/git.py +956 -0
- diagram_to_iac/tools/hello/__init__.py +30 -0
- diagram_to_iac/tools/hello/cal_utils.py +31 -0
- diagram_to_iac/tools/hello/text_utils.py +97 -0
- diagram_to_iac/tools/llm_utils/__init__.py +20 -0
- diagram_to_iac/tools/llm_utils/anthropic_driver.py +87 -0
- diagram_to_iac/tools/llm_utils/base_driver.py +90 -0
- diagram_to_iac/tools/llm_utils/gemini_driver.py +89 -0
- diagram_to_iac/tools/llm_utils/openai_driver.py +93 -0
- diagram_to_iac/tools/llm_utils/router.py +303 -0
- diagram_to_iac/tools/sec_utils.py +4 -2
- diagram_to_iac/tools/shell/__init__.py +17 -0
- diagram_to_iac/tools/shell/shell.py +415 -0
- diagram_to_iac/tools/text_utils.py +277 -0
- diagram_to_iac/tools/tf/terraform.py +851 -0
- diagram_to_iac-0.8.0.dist-info/METADATA +99 -0
- diagram_to_iac-0.8.0.dist-info/RECORD +64 -0
- {diagram_to_iac-0.7.0.dist-info → diagram_to_iac-0.8.0.dist-info}/WHEEL +1 -1
- diagram_to_iac-0.8.0.dist-info/entry_points.txt +4 -0
- diagram_to_iac/agents/codegen_agent.py +0 -0
- diagram_to_iac/agents/consensus_agent.py +0 -0
- diagram_to_iac/agents/deployment_agent.py +0 -0
- diagram_to_iac/agents/github_agent.py +0 -0
- diagram_to_iac/agents/interpretation_agent.py +0 -0
- diagram_to_iac/agents/question_agent.py +0 -0
- diagram_to_iac/agents/supervisor.py +0 -0
- diagram_to_iac/agents/vision_agent.py +0 -0
- diagram_to_iac/core/config.py +0 -0
- diagram_to_iac/tools/cv_utils.py +0 -0
- diagram_to_iac/tools/gh_utils.py +0 -0
- diagram_to_iac/tools/tf_utils.py +0 -0
- diagram_to_iac-0.7.0.dist-info/METADATA +0 -16
- diagram_to_iac-0.7.0.dist-info/RECORD +0 -32
- diagram_to_iac-0.7.0.dist-info/entry_points.txt +0 -2
- {diagram_to_iac-0.7.0.dist-info → diagram_to_iac-0.8.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import json
|
4
|
+
import re
|
5
|
+
from datetime import datetime
|
6
|
+
from pathlib import Path
|
7
|
+
|
8
|
+
|
9
|
+
def _parse_timestamp(ts: str) -> datetime:
|
10
|
+
try:
|
11
|
+
return datetime.fromisoformat(ts)
|
12
|
+
except Exception:
|
13
|
+
# Fallback for timestamps that may not be ISO formatted
|
14
|
+
return datetime.strptime(ts.split(".")[0], "%Y-%m-%dT%H:%M:%S")
|
15
|
+
|
16
|
+
|
17
|
+
def generate_step_summary(log_path: str | Path, output_path: str | Path, *, stdout: bool = False) -> str:
|
18
|
+
"""Generate a Markdown step summary from JSONL logs."""
|
19
|
+
log_path = Path(log_path)
|
20
|
+
output_path = Path(output_path)
|
21
|
+
|
22
|
+
modules: set[str] = set()
|
23
|
+
adds = changes = destroys = 0
|
24
|
+
critical = high = medium = low = 0
|
25
|
+
start: datetime | None = None
|
26
|
+
end: datetime | None = None
|
27
|
+
|
28
|
+
if not log_path.exists():
|
29
|
+
raise FileNotFoundError(log_path)
|
30
|
+
|
31
|
+
with log_path.open("r", encoding="utf-8") as f:
|
32
|
+
for line in f:
|
33
|
+
line = line.strip()
|
34
|
+
if not line:
|
35
|
+
continue
|
36
|
+
data = json.loads(line)
|
37
|
+
ts = data.get("timestamp")
|
38
|
+
if ts:
|
39
|
+
ts_dt = _parse_timestamp(ts)
|
40
|
+
if start is None or ts_dt < start:
|
41
|
+
start = ts_dt
|
42
|
+
if end is None or ts_dt > end:
|
43
|
+
end = ts_dt
|
44
|
+
result = data.get("result", "")
|
45
|
+
if result:
|
46
|
+
modules.update(re.findall(r"module\.([\w-]+)", result))
|
47
|
+
m = re.search(r"Plan:\s*(\d+)\s*to\s*add,\s*(\d+)\s*to\s*change,\s*(\d+)\s*to\s*destroy", result)
|
48
|
+
if m:
|
49
|
+
adds = int(m.group(1))
|
50
|
+
changes = int(m.group(2))
|
51
|
+
destroys = int(m.group(3))
|
52
|
+
m = re.search(r"(\d+)\s*critical", result, re.IGNORECASE)
|
53
|
+
if m:
|
54
|
+
critical = int(m.group(1))
|
55
|
+
m = re.search(r"(\d+)\s*high", result, re.IGNORECASE)
|
56
|
+
if m:
|
57
|
+
high = int(m.group(1))
|
58
|
+
m = re.search(r"(\d+)\s*medium", result, re.IGNORECASE)
|
59
|
+
if m:
|
60
|
+
medium = int(m.group(1))
|
61
|
+
m = re.search(r"(\d+)\s*low", result, re.IGNORECASE)
|
62
|
+
if m:
|
63
|
+
low = int(m.group(1))
|
64
|
+
|
65
|
+
runtime = (end - start).total_seconds() if start and end else 0
|
66
|
+
modules_str = ", ".join(sorted(modules)) if modules else "root"
|
67
|
+
|
68
|
+
md = (
|
69
|
+
"| Module | Adds | Changes | Destroys | Critical | High | Medium | Low | Run Time (s) |\n"
|
70
|
+
"| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n"
|
71
|
+
f"| {modules_str} | {adds} | {changes} | {destroys} | {critical} | {high} | {medium} | {low} | {int(runtime)} |\n"
|
72
|
+
)
|
73
|
+
|
74
|
+
output_path.write_text(md, encoding="utf-8")
|
75
|
+
if stdout:
|
76
|
+
print(md)
|
77
|
+
return md
|
diagram_to_iac/tools/__init__.py
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
# This file makes the 'tools' module a package.
|
2
|
+
|
3
|
+
# Note: Agent-specific tools organization:
|
4
|
+
# - cal_utils, text_utils -> tools/hello/
|
5
|
+
# - git_tools -> tools/git/ (moved from agents/git_langgraph/tools/)
|
6
|
+
# - shell_tools -> agents/shell_langgraph/tools/
|
7
|
+
|
8
|
+
# You can expose shared tools here as needed
|
9
|
+
# For example:
|
10
|
+
# from .llm_utils import router (if router.py is in llm_utils subdirectory)
|
11
|
+
# from .cv_utils import some_vision_function
|
@@ -5,9 +5,7 @@ from anthropic import Anthropic
|
|
5
5
|
import requests
|
6
6
|
import google.generativeai as genai
|
7
7
|
import googleapiclient.discovery
|
8
|
-
|
9
|
-
# sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
10
|
-
# from scripts.env_loader import load_env_keys
|
8
|
+
from concurrent.futures import ThreadPoolExecutor, TimeoutError
|
11
9
|
|
12
10
|
def test_openai_api():
|
13
11
|
try:
|
@@ -15,12 +13,20 @@ def test_openai_api():
|
|
15
13
|
print("❌ OpenAI API error: OPENAI_API_KEY environment variable not set.")
|
16
14
|
return False
|
17
15
|
client = OpenAI()
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
|
17
|
+
# Run the API call with a 10-second timeout
|
18
|
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
19
|
+
future = executor.submit(
|
20
|
+
client.chat.completions.create,
|
21
|
+
model="gpt-3.5-turbo",
|
22
|
+
messages=[{"role": "user", "content": "Hello, are you working?"}],
|
23
|
+
max_tokens=10
|
24
|
+
)
|
25
|
+
try:
|
26
|
+
response = future.result(timeout=10)
|
27
|
+
except TimeoutError:
|
28
|
+
print("❌ OpenAI API error: request timed out.")
|
29
|
+
return False
|
24
30
|
return True
|
25
31
|
except Exception as e:
|
26
32
|
print(f"❌ Open AI API error: {str(e)}")
|
@@ -33,8 +39,16 @@ def test_gemini_api():
|
|
33
39
|
print("❌ Gemini API error: GOOGLE_API_KEY environment variable not set.")
|
34
40
|
return False
|
35
41
|
genai.configure(api_key=google_api_key)
|
36
|
-
model = genai.GenerativeModel('gemini-
|
37
|
-
|
42
|
+
model = genai.GenerativeModel('gemini-2.0-flash') # Corrected model name
|
43
|
+
|
44
|
+
# Run the API call with a 10-second timeout
|
45
|
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
46
|
+
future = executor.submit(model.generate_content, "Hello, are you working?")
|
47
|
+
try:
|
48
|
+
response = future.result(timeout=10)
|
49
|
+
except TimeoutError:
|
50
|
+
print("❌ Gemini API error: request timed out.")
|
51
|
+
return False
|
38
52
|
return True
|
39
53
|
except Exception as e:
|
40
54
|
print(f"❌ Gemini API error: {str(e)}")
|
@@ -46,11 +60,20 @@ def test_anthropic_api():
|
|
46
60
|
print("❌ Anthropic API error: ANTHROPIC_API_KEY environment variable not set.")
|
47
61
|
return False
|
48
62
|
client = Anthropic()
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
63
|
+
|
64
|
+
# Run the API call with a 10-second timeout
|
65
|
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
66
|
+
future = executor.submit(
|
67
|
+
client.messages.create,
|
68
|
+
model="claude-3-haiku-20240307",
|
69
|
+
max_tokens=10,
|
70
|
+
messages=[{"role": "user", "content": "Hello, are you working?"}]
|
71
|
+
)
|
72
|
+
try:
|
73
|
+
response = future.result(timeout=10)
|
74
|
+
except TimeoutError:
|
75
|
+
print("❌ Anthropic API error: request timed out.")
|
76
|
+
return False
|
54
77
|
return True
|
55
78
|
except Exception as e:
|
56
79
|
print(f"❌ Anthropic API error: {str(e)}")
|
@@ -69,9 +92,18 @@ def test_github_api():
|
|
69
92
|
"Accept": "application/vnd.github.v3+json"
|
70
93
|
}
|
71
94
|
|
72
|
-
#
|
73
|
-
|
74
|
-
|
95
|
+
# Run the API call with a 10-second timeout
|
96
|
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
97
|
+
future = executor.submit(
|
98
|
+
requests.get,
|
99
|
+
"https://api.github.com/user",
|
100
|
+
headers=headers
|
101
|
+
)
|
102
|
+
try:
|
103
|
+
response = future.result(timeout=10)
|
104
|
+
except TimeoutError:
|
105
|
+
print("❌ GitHub API error: request timed out.")
|
106
|
+
return False
|
75
107
|
|
76
108
|
if response.status_code == 200:
|
77
109
|
user_data = response.json()
|
@@ -85,25 +117,75 @@ def test_github_api():
|
|
85
117
|
print(f"❌ GitHub API error: {str(e)}")
|
86
118
|
return False
|
87
119
|
|
120
|
+
def test_Terraform_API():
|
121
|
+
try:
|
122
|
+
if not os.environ.get("TFE_TOKEN"):
|
123
|
+
print("❌ Terraform API error: TFE_TOKEN environment variable not set.")
|
124
|
+
return False
|
125
|
+
headers = {
|
126
|
+
"Authorization": f"Bearer {os.environ.get('TFE_TOKEN')}",
|
127
|
+
"Content-Type": "application/vnd.api+json"
|
128
|
+
}
|
129
|
+
# Run the API call with a 10-second timeout
|
130
|
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
131
|
+
future = executor.submit(
|
132
|
+
requests.get,
|
133
|
+
"https://app.terraform.io/api/v2/organizations",
|
134
|
+
headers=headers
|
135
|
+
)
|
136
|
+
try:
|
137
|
+
response = future.result(timeout=10)
|
138
|
+
except TimeoutError:
|
139
|
+
print("❌ Terraform API error: request timed out.")
|
140
|
+
return False
|
141
|
+
if response.status_code == 200:
|
142
|
+
org_data = response.json()
|
143
|
+
# print(f"✅ Terraform API works! Organizations: {org_data}")
|
144
|
+
return True
|
145
|
+
else:
|
146
|
+
print(f"❌ Terraform API error: Status code {response.status_code}")
|
147
|
+
if hasattr(response, 'text'):
|
148
|
+
print(f" Response body: {response.text}")
|
149
|
+
return False
|
150
|
+
except requests.exceptions.ConnectionError as e:
|
151
|
+
print(f"❌ Terraform API error: Connection failed - {str(e)}")
|
152
|
+
print(" This could be due to:")
|
153
|
+
print(" - Network connectivity issues")
|
154
|
+
print(" - DNS resolution problems")
|
155
|
+
print(" - Firewall blocking the connection")
|
156
|
+
return False
|
157
|
+
except requests.exceptions.SSLError as e:
|
158
|
+
print(f"❌ Terraform API error: SSL/TLS error - {str(e)}")
|
159
|
+
return False
|
160
|
+
except requests.exceptions.Timeout as e:
|
161
|
+
print(f"❌ Terraform API error: Request timeout - {str(e)}")
|
162
|
+
return False
|
163
|
+
except requests.exceptions.RequestException as e:
|
164
|
+
print(f"❌ Terraform API error: Request failed - {str(e)}")
|
165
|
+
return False
|
166
|
+
except Exception as e:
|
167
|
+
print(f"❌ Terraform API error: Unexpected error - {str(e)}")
|
168
|
+
return False
|
169
|
+
|
88
170
|
def test_all_apis():
|
89
171
|
print("Hello from the test workflow!")
|
90
|
-
|
91
|
-
# Load environment keys once before running all tests
|
92
|
-
#load_env_keys()
|
172
|
+
|
93
173
|
|
94
174
|
print("Testing API connections...")
|
95
175
|
openai_success = test_openai_api()
|
96
176
|
gemini_success = test_gemini_api()
|
97
177
|
anthropic_success = test_anthropic_api()
|
98
|
-
github_success = test_github_api()
|
178
|
+
github_success = test_github_api()
|
179
|
+
terraform_success = test_Terraform_API()
|
99
180
|
|
100
181
|
print("\nSummary:")
|
101
182
|
print(f"OpenAI API: {'✅ Working' if openai_success else '❌ Failed'}")
|
102
183
|
print(f"Gemini API: {'✅ Working' if gemini_success else '❌ Failed'}")
|
103
184
|
print(f"Anthropic API: {'✅ Working' if anthropic_success else '❌ Failed'}")
|
104
|
-
print(f"GitHub API: {'✅ Working' if github_success else '❌ Failed'}")
|
105
|
-
|
106
|
-
|
185
|
+
print(f"GitHub API: {'✅ Working' if github_success else '❌ Failed'}")
|
186
|
+
print(f"Terraform API: {'✅ Working' if terraform_success else '❌ Failed'}")
|
187
|
+
|
188
|
+
if openai_success and gemini_success and anthropic_success and github_success and terraform_success: # Updated condition
|
107
189
|
print("\n🎉 All APIs are working correctly!")
|
108
190
|
else:
|
109
191
|
print("\n⚠️ Some APIs failed. Check the errors above.")
|
@@ -0,0 +1,45 @@
|
|
1
|
+
"""
|
2
|
+
Git Tools Package
|
3
|
+
|
4
|
+
This package contains git-related tools and utilities:
|
5
|
+
- git: Core git operations (clone, GitHub CLI)
|
6
|
+
- git_config.yaml: Configuration for git operations
|
7
|
+
|
8
|
+
Moved from agents/git_langgraph/tools for better organization.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from .git import (
|
12
|
+
GitExecutor,
|
13
|
+
git_clone,
|
14
|
+
gh_open_issue,
|
15
|
+
get_git_executor,
|
16
|
+
GitCloneInput,
|
17
|
+
GitCloneOutput,
|
18
|
+
GhOpenIssueInput,
|
19
|
+
GhOpenIssueOutput,
|
20
|
+
)
|
21
|
+
|
22
|
+
# Ensure the tool functions reference the exported get_git_executor so that
|
23
|
+
# tests can patch `diagram_to_iac.tools.git.get_git_executor` and have the
|
24
|
+
# patch affect the functions imported from this package. Without this,
|
25
|
+
# git_clone and gh_open_issue would retain references to the original function
|
26
|
+
# defined in ``git.py`` making patching ineffective.
|
27
|
+
import importlib
|
28
|
+
|
29
|
+
def _patched_get_git_executor():
|
30
|
+
"""Resolve get_git_executor dynamically so tests can patch it easily."""
|
31
|
+
return importlib.import_module(__name__).get_git_executor()
|
32
|
+
|
33
|
+
git_clone.func.__globals__["get_git_executor"] = _patched_get_git_executor
|
34
|
+
gh_open_issue.func.__globals__["get_git_executor"] = _patched_get_git_executor
|
35
|
+
|
36
|
+
__all__ = [
|
37
|
+
"GitExecutor",
|
38
|
+
"git_clone",
|
39
|
+
"gh_open_issue",
|
40
|
+
"get_git_executor",
|
41
|
+
"GitCloneInput",
|
42
|
+
"GitCloneOutput",
|
43
|
+
"GhOpenIssueInput",
|
44
|
+
"GhOpenIssueOutput"
|
45
|
+
]
|