diagram-to-iac 1.11.0__py3-none-any.whl → 1.13.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.
@@ -0,0 +1,236 @@
1
+ # src/diagram_to_iac/config.yaml
2
+ # Central application configuration for diagram-to-iac
3
+ # This file contains common settings shared across agents and tools
4
+ # Individual agent/tool configs can override these values
5
+
6
+ # System settings
7
+ system:
8
+ workspace_base: "/workspace"
9
+ log_level: "INFO"
10
+
11
+ # Network timeouts
12
+ network:
13
+ api_timeout: 10 # Used in api_utils.py for API calls
14
+ shell_timeout: 30 # Used in shell tools
15
+ terraform_timeout: 300 # Used in terraform tools
16
+ github_timeout: 15 # Used in GitHub API calls
17
+ git_timeout: 300 # Used in git operations
18
+
19
+ # AI/LLM settings (common defaults)
20
+ ai:
21
+ default_model: "gpt-4o-mini"
22
+ default_temperature: 0.1 # Most agents use 0.1
23
+ max_tokens: 1000 # Common across agents
24
+
25
+ # Provider selection strategy for intelligent fallback
26
+ provider_selection:
27
+ strategy: "auto" # Options: "auto", "prefer_cost", "prefer_performance", "manual"
28
+ preferred_order: # Provider preference order when strategy is "auto"
29
+ - "openai" # Primary choice - good balance of cost/performance
30
+ - "anthropic" # Secondary - good for reasoning tasks
31
+ - "google" # Tertiary - good for multimodal tasks
32
+ - "grok" # Experimental - not implemented yet
33
+
34
+ # Strategy-specific configurations
35
+ cost_optimization:
36
+ prefer_models:
37
+ - "gpt-4o-mini" # Most cost-effective
38
+ - "gpt-3.5-turbo" # Good performance/cost ratio
39
+ - "claude-3-haiku" # Fast and cheap
40
+ - "gemini-pro" # Google's cost-effective option
41
+
42
+ performance_optimization:
43
+ prefer_models:
44
+ - "gpt-4o" # Best OpenAI performance
45
+ - "claude-3-sonnet" # Best Anthropic reasoning
46
+ - "gpt-4-turbo" # High performance OpenAI
47
+ - "gemini-1.5-pro" # Best Google model
48
+
49
+ # Fallback behavior when all providers fail
50
+ fallback:
51
+ enabled: true
52
+ retry_attempts: 2
53
+ retry_delay_seconds: 1
54
+ default_to_offline: false # If true, gracefully degrade to offline mode
55
+
56
+ # Common memory settings
57
+ memory:
58
+ type: "persistent"
59
+ max_history: 100
60
+
61
+ # Common error handling
62
+ error_handling:
63
+ max_retries: 3
64
+ retry_delay_seconds: 5
65
+ auto_fix_enabled: true
66
+ create_github_issues: true
67
+
68
+ # Common logging
69
+ logging:
70
+ level: "INFO"
71
+ format: "%(asctime)s - %(name)s - %(levelname)s - %(threadName)s - %(message)s"
72
+
73
+ # Route tokens (commonly used across agents)
74
+ routing:
75
+ tokens:
76
+ # Hello agent operations
77
+ addition: "ROUTE_TO_ADDITION"
78
+ multiplication: "ROUTE_TO_MULTIPLICATION"
79
+
80
+ # Git operations
81
+ git_clone: "ROUTE_TO_GIT_CLONE"
82
+ github_cli: "ROUTE_TO_GITHUB_CLI"
83
+ github_issue: "ROUTE_TO_GITHUB_ISSUE"
84
+ shell_exec: "ROUTE_TO_SHELL_EXEC"
85
+ shell: "ROUTE_TO_SHELL"
86
+ create_pr: "ROUTE_TO_CREATE_PR"
87
+
88
+ # Terraform operations
89
+ terraform_init: "ROUTE_TO_TF_INIT"
90
+ terraform_plan: "ROUTE_TO_TF_PLAN"
91
+ terraform_apply: "ROUTE_TO_TF_APPLY"
92
+
93
+ # Supervisor operations
94
+ clone: "ROUTE_TO_CLONE"
95
+ stack_detect: "ROUTE_TO_STACK_DETECT"
96
+ terraform: "ROUTE_TO_TERRAFORM"
97
+ issue: "ROUTE_TO_ISSUE"
98
+
99
+ # Demonstrator operations
100
+ analyze: "ROUTE_TO_ANALYZE"
101
+ demonstrate: "ROUTE_TO_DEMONSTRATE"
102
+ collect_inputs: "ROUTE_TO_COLLECT_INPUTS"
103
+ retry: "ROUTE_TO_RETRY"
104
+
105
+ # Policy operations
106
+ policy_scan: "ROUTE_TO_POLICY_SCAN"
107
+ policy_evaluate: "ROUTE_TO_POLICY_EVALUATE"
108
+ policy_block: "ROUTE_TO_POLICY_BLOCK"
109
+ policy_report: "ROUTE_TO_POLICY_REPORT"
110
+
111
+ # End states
112
+ create_issue: "ROUTE_TO_CREATE_ISSUE"
113
+ open_issue: "ROUTE_TO_OPEN_ISSUE"
114
+ end: "ROUTE_TO_END"
115
+
116
+ # Tool settings (common defaults)
117
+ tools:
118
+ shell:
119
+ allowed_binaries:
120
+ - "terraform"
121
+ - "git"
122
+ - "bash"
123
+ - "sh"
124
+ - "curl"
125
+ - "wget"
126
+ - "jq"
127
+ - "gh"
128
+ - "tfsec"
129
+ - "ls"
130
+ - "find"
131
+ - "wc"
132
+ max_output_size: 8192
133
+ allow_relative_paths: true
134
+ restrict_to_workspace: true
135
+
136
+ git:
137
+ default_clone_depth: 1
138
+ sanitize_repo_names: true
139
+ store_operations_in_memory: true
140
+ remote_name: "origin"
141
+
142
+ terraform:
143
+ allowed_binaries:
144
+ - "terraform"
145
+ - "git"
146
+ - "bash"
147
+ - "sh"
148
+ default_plan_file: "plan.tfplan"
149
+ default_auto_approve: true
150
+ restrict_to_workspace: true
151
+ store_operations_in_memory: true
152
+
153
+ policy:
154
+ tfsec_enabled: true
155
+ block_on_severity: ["CRITICAL", "HIGH"]
156
+ artifact_on_severity: ["CRITICAL", "HIGH", "MEDIUM"]
157
+
158
+ # Agent-specific configurations
159
+ agents:
160
+ policy_agent:
161
+ # Policy enforcement settings
162
+ policy:
163
+ tfsec:
164
+ enabled: true
165
+ timeout_seconds: 120
166
+ output_format: "json"
167
+ block_on_severity: ["CRITICAL", "HIGH"]
168
+ artifact_on_severity: ["CRITICAL", "HIGH", "MEDIUM"]
169
+ working_directory: "/workspace"
170
+ artifacts:
171
+ output_dir: "/workspace/.policy_findings"
172
+ json_filename: "policy_findings_{timestamp}.json"
173
+ summary_filename: "policy_summary_{timestamp}.txt"
174
+
175
+ # Agent-specific routing tokens
176
+ routing_keys:
177
+ policy_scan: "ROUTE_TO_POLICY_SCAN"
178
+ policy_evaluate: "ROUTE_TO_POLICY_EVALUATE"
179
+ policy_block: "ROUTE_TO_POLICY_BLOCK"
180
+ policy_report: "ROUTE_TO_POLICY_REPORT"
181
+ end: "ROUTE_TO_END"
182
+
183
+ # Memory settings
184
+ memory:
185
+ max_history: 50
186
+
187
+ policy:
188
+ tfsec_enabled: true
189
+ block_on_severity:
190
+ - "CRITICAL"
191
+ - "HIGH"
192
+ artifact_on_severity:
193
+ - "CRITICAL"
194
+ - "HIGH"
195
+ - "MEDIUM"
196
+
197
+ # GitHub settings
198
+ github:
199
+ default_assignees: ["team-infra"]
200
+ copilot_assignee: "CopilotUser"
201
+
202
+ # GitHub credentials and repository settings (for tests and development)
203
+ username: "amartyamandal" # GitHub username used in tests and development
204
+ default_repo: "amartyamandal/diagram-to-iac" # Default repository for development
205
+
206
+ # Secret management
207
+ security:
208
+ required_secrets:
209
+ - "REPO_API_KEY"
210
+ optional_secrets:
211
+ - "TF_API_KEY"
212
+ - "OPENAI_API_KEY"
213
+ - "GOOGLE_API_KEY"
214
+ - "ANTHROPIC_API_KEY"
215
+ - "GROK_API_KEY"
216
+ - "DOCKERHUB_API_KEY"
217
+ - "DOCKERHUB_USERNAME"
218
+ - "PYPI_API_KEY"
219
+ secret_mappings:
220
+ REPO_API_KEY: "GITHUB_TOKEN"
221
+ TF_API_KEY: "TFE_TOKEN"
222
+
223
+ # Environment variable overrides configuration
224
+ environment_overrides:
225
+ allowed_overrides:
226
+ - "network.api_timeout"
227
+ - "network.shell_timeout"
228
+ - "network.terraform_timeout"
229
+ - "network.github_timeout"
230
+ - "network.git_timeout"
231
+ - "ai.default_model"
232
+ - "ai.default_temperature"
233
+ - "ai.max_tokens"
234
+ - "system.workspace_base"
235
+ - "system.log_level"
236
+ - "logging.level"
@@ -101,12 +101,12 @@ class PersistentFileMemory(MemoryInterface):
101
101
 
102
102
  def __init__(self, file_path: Optional[str] = None):
103
103
  if file_path is None:
104
- # Get workspace base from config with fallback
105
- workspace_base = get_config_value("system.workspace_base", "/workspace")
104
+ # Get workspace base from environment variable first, then config with fallback
105
+ workspace_base = os.environ.get("WORKSPACE_BASE") or get_config_value("system.workspace_base", "/workspace")
106
106
 
107
107
  # Default to workspace or /tmp directory for container safety
108
108
  try:
109
- # Try workspace first (from config)
109
+ # Try workspace first (from environment or config)
110
110
  base_dir = Path(workspace_base) if Path(workspace_base).exists() else Path.cwd()
111
111
  data_dir = base_dir / "data" / "db"
112
112
  data_dir.mkdir(parents=True, exist_ok=True)
@@ -1,35 +1,126 @@
1
1
  import json
2
+ import os
2
3
  from pathlib import Path
3
4
  from typing import Dict, Optional
5
+ import logging
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ try:
10
+ from .config_loader import get_config_value
11
+ except ImportError:
12
+ # Fallback for tests or standalone usage
13
+ def get_config_value(path: str, default: any = None) -> any:
14
+ return default
4
15
 
5
16
  class IssueTracker:
6
17
  """Simple persistent tracker for GitHub issues keyed by repo and error type."""
7
18
 
8
19
  def __init__(self, file_path: Optional[str] = None):
9
20
  if file_path is None:
10
- base_dir = Path(__file__).resolve().parents[3]
11
- file_path = base_dir / "data" / "db" / "issue_tracker.json"
21
+ # Debug: Check current working directory
22
+ cwd = os.getcwd()
23
+ logger.debug(f"IssueTracker: Current working directory = {cwd}")
24
+
25
+ # Get workspace base from environment variable first, then config with fallback
26
+ workspace_base = os.environ.get("WORKSPACE_BASE")
27
+ logger.debug(f"IssueTracker: WORKSPACE_BASE env var = {workspace_base}")
28
+
29
+ if not workspace_base:
30
+ # Try to get from config
31
+ try:
32
+ workspace_base = get_config_value("system.workspace_base", "/workspace")
33
+ logger.debug(f"IssueTracker: workspace_base from config = {workspace_base}")
34
+ except Exception as e:
35
+ logger.debug(f"IssueTracker: Failed to get workspace_base from config: {e}")
36
+ workspace_base = "/workspace"
37
+
38
+ # Safeguard: Never use Python installation paths or current working directory if it's a Python path
39
+ if (workspace_base and
40
+ "/usr/local/lib/python" not in workspace_base and
41
+ "/site-packages" not in workspace_base and
42
+ not workspace_base.startswith(cwd) if "/usr/local/lib/python" in cwd else True):
43
+
44
+ try:
45
+ base_dir = Path(workspace_base)
46
+ logger.debug(f"IssueTracker: Using workspace base_dir = {base_dir}")
47
+
48
+ # For container environments, always try /workspace first
49
+ if base_dir == Path("/workspace"):
50
+ data_dir = base_dir / "data" / "db"
51
+ data_dir.mkdir(parents=True, exist_ok=True)
52
+ file_path = str(data_dir / "issue_tracker.json")
53
+ logger.debug(f"IssueTracker: Using workspace path = {file_path}")
54
+ # For other paths, check if they exist and are writable
55
+ elif base_dir.exists() and base_dir.is_dir():
56
+ # Test if we can write to this directory
57
+ test_file = base_dir / "test_write_access"
58
+ try:
59
+ test_file.touch()
60
+ test_file.unlink()
61
+ data_dir = base_dir / "data" / "db"
62
+ data_dir.mkdir(parents=True, exist_ok=True)
63
+ file_path = str(data_dir / "issue_tracker.json")
64
+ logger.debug(f"IssueTracker: Using accessible workspace path = {file_path}")
65
+ except (PermissionError, OSError):
66
+ raise PermissionError(f"Workspace directory {base_dir} not writable")
67
+ else:
68
+ raise PermissionError(f"Workspace directory {base_dir} not accessible")
69
+
70
+ except (PermissionError, OSError) as e:
71
+ logger.debug(f"IssueTracker: Workspace not accessible ({e}), falling back to /tmp")
72
+ # Fallback to /tmp for container environments
73
+ data_dir = Path("/tmp") / "diagram_to_iac" / "data" / "db"
74
+ data_dir.mkdir(parents=True, exist_ok=True)
75
+ file_path = str(data_dir / "issue_tracker.json")
76
+ logger.debug(f"IssueTracker: Using tmp path = {file_path}")
77
+ else:
78
+ logger.debug(f"IssueTracker: Invalid workspace_base ({workspace_base}) or unsafe cwd ({cwd}), using /tmp")
79
+ # Always fallback to /tmp if workspace_base is invalid or points to Python paths
80
+ data_dir = Path("/tmp") / "diagram_to_iac" / "data" / "db"
81
+ data_dir.mkdir(parents=True, exist_ok=True)
82
+ file_path = str(data_dir / "issue_tracker.json")
83
+ logger.debug(f"IssueTracker: Using tmp fallback path = {file_path}")
84
+
12
85
  self.file_path = Path(file_path)
86
+ logger.debug(f"IssueTracker: Final file_path = {self.file_path}")
87
+
88
+ # Final safety check: ensure the path is never in Python installation
89
+ if "/usr/local/lib/python" in str(self.file_path) or "/site-packages" in str(self.file_path):
90
+ logger.warning(f"IssueTracker: Detected Python installation path {self.file_path}, forcing /tmp fallback")
91
+ data_dir = Path("/tmp") / "diagram_to_iac" / "data" / "db"
92
+ data_dir.mkdir(parents=True, exist_ok=True)
93
+ self.file_path = data_dir / "issue_tracker.json"
94
+ logger.debug(f"IssueTracker: Corrected file_path = {self.file_path}")
95
+
13
96
  self._table: Dict[str, Dict[str, int]] = {}
14
97
  self._load()
15
98
 
16
99
  def _load(self) -> None:
100
+ """Load the issue tracker data from file."""
17
101
  if self.file_path.exists():
18
102
  try:
19
103
  with open(self.file_path, "r") as f:
20
104
  self._table = json.load(f)
21
- except Exception:
105
+ logger.debug(f"IssueTracker: Loaded {len(self._table)} repos from {self.file_path}")
106
+ except Exception as e:
107
+ logger.warning(f"IssueTracker: Failed to load from {self.file_path}: {e}")
22
108
  self._table = {}
23
109
  else:
24
- self.file_path.parent.mkdir(parents=True, exist_ok=True)
110
+ # File doesn't exist, start with empty table
111
+ # Directory was already created in __init__, so no need to create again
25
112
  self._table = {}
113
+ logger.debug(f"IssueTracker: Starting with empty table at {self.file_path}")
26
114
 
27
115
  def _save(self) -> None:
116
+ """Save the issue tracker data to file."""
28
117
  try:
29
- self.file_path.parent.mkdir(parents=True, exist_ok=True)
118
+ # Directory was already created in __init__, no need to create again
30
119
  with open(self.file_path, "w") as f:
31
120
  json.dump(self._table, f, indent=2)
32
- except Exception:
121
+ logger.debug(f"IssueTracker: Saved {len(self._table)} repos to {self.file_path}")
122
+ except Exception as e:
123
+ logger.error(f"IssueTracker: Failed to save to {self.file_path}: {e}")
33
124
  pass
34
125
 
35
126
  def get_issue(self, repo_url: str, error_type: str) -> Optional[int]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diagram-to-iac
3
- Version: 1.11.0
3
+ Version: 1.13.0
4
4
  Summary: Convert architecture diagrams into IaC modules
5
5
  Author-email: vindpro <admin@vindpro.com>
6
6
  Description-Content-Type: text/markdown
@@ -1,5 +1,6 @@
1
1
  diagram_to_iac/__init__.py,sha256=gQanRC5O_7AMB-NQFEEd-MU0GICa-dBsgvcJgquKBfs,1427
2
2
  diagram_to_iac/cli.py,sha256=uumG1frF42eCkdLIZxyxQB1x6lDwtG-qKL4vcHnLLXY,400
3
+ diagram_to_iac/config.yaml,sha256=M2INu-Vfsbb-oWQgv_puoUljRj1GhcnwuWAbDsE7bMc,6739
3
4
  diagram_to_iac/r2d.py,sha256=I7XSuUtu8TdvAhK4tCMLc3U_3ZtP7DJGfq168aeI3Mk,13208
4
5
  diagram_to_iac/actions/__init__.py,sha256=P1CjjY4FYUA0Tcx8FQNLYYSI9fhv8yKd_TmRGtmhW50,229
5
6
  diagram_to_iac/actions/git_entry.py,sha256=mhY6gYquUPVvyvnTC2S90z_uXEe1asqWLoi1989aB_Q,5403
@@ -34,9 +35,9 @@ diagram_to_iac/agents/terraform_langgraph/parser.py,sha256=J56CPlpIEIPuDHeAOL3sz
34
35
  diagram_to_iac/core/__init__.py,sha256=VjXPYLIS2SAPIDniBkeA2EDK0VHJvdaKIC8dzVneaTM,140
35
36
  diagram_to_iac/core/agent_base.py,sha256=DjZjcfzDpEhfIOki00XwQ-4lPli3OBcQ_7RNKsT7JSI,505
36
37
  diagram_to_iac/core/config_loader.py,sha256=6WWOp6G7_xYUhm1x62sVa-7kFlCthcthbppmeGz1YsM,9276
37
- diagram_to_iac/core/enhanced_memory.py,sha256=fJ8r-MREZRnm6Rg01CDCicMEx-dDxDEjJgrk8rnVc5Y,11761
38
+ diagram_to_iac/core/enhanced_memory.py,sha256=PI7GPpgo4APeRZ7b9t0MqWKqthRI4_iAg-GLCykDhtU,11845
38
39
  diagram_to_iac/core/errors.py,sha256=gZwZocnIcBlS4YccIBdjG8XztRCtMe4Cu6KWxLzebDM,115
39
- diagram_to_iac/core/issue_tracker.py,sha256=0eo289hn94yCoFCkLaYiDOIJBjk33i2dk6eLeYe_9YE,1659
40
+ diagram_to_iac/core/issue_tracker.py,sha256=_Hl1fG6jUczqzB-Cmwx8qzYqB10ijyRKFBGrsy4Hfp4,7097
40
41
  diagram_to_iac/core/memory.py,sha256=P9URX8m2nab65ZPF36uf6Z9hEXQGXrjrXa8dPXG7pm8,4444
41
42
  diagram_to_iac/core/registry.py,sha256=ibdMz68W7qkwF0dprt4ni5pekgJfAPuRgL85uRU7wHY,26632
42
43
  diagram_to_iac/core/test_config.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -63,8 +64,8 @@ diagram_to_iac/tools/llm_utils/router.py,sha256=ga8xfmPMl_SGINDwazeAAFYTAx9L_IQc
63
64
  diagram_to_iac/tools/shell/__init__.py,sha256=6UZjBcnbPabA6Qy7t4j-dCi3S2sE6sB2bTE9PIL98bA,292
64
65
  diagram_to_iac/tools/shell/shell.py,sha256=ZOJ7Vo3l_R2Gm6Ml2FL0RX__-C_JOsUrLJVvBMwAy9E,21122
65
66
  diagram_to_iac/tools/tf/terraform.py,sha256=j1boWRo6JKpNGf1OwnWoWboO0gMYTizCOHDSxozoFZw,37343
66
- diagram_to_iac-1.11.0.dist-info/METADATA,sha256=oUVHnfKjHzEHlJQlPgAy0I20q2hPPoZFBo7U_wpE7Wo,10690
67
- diagram_to_iac-1.11.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
- diagram_to_iac-1.11.0.dist-info/entry_points.txt,sha256=DfGCnmgWWGHtQpqU8VqcUWs5k_be-bfO67z1vOuTitA,277
69
- diagram_to_iac-1.11.0.dist-info/top_level.txt,sha256=k1cV0YODiCUU46qlmbQaquMcbMXhNm05NZLxsinDUBA,15
70
- diagram_to_iac-1.11.0.dist-info/RECORD,,
67
+ diagram_to_iac-1.13.0.dist-info/METADATA,sha256=N4FyUgEIYvHVHN1dzQ2v8R6AZD-hvDHOYRfA1bRMUOo,10690
68
+ diagram_to_iac-1.13.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
69
+ diagram_to_iac-1.13.0.dist-info/entry_points.txt,sha256=DfGCnmgWWGHtQpqU8VqcUWs5k_be-bfO67z1vOuTitA,277
70
+ diagram_to_iac-1.13.0.dist-info/top_level.txt,sha256=k1cV0YODiCUU46qlmbQaquMcbMXhNm05NZLxsinDUBA,15
71
+ diagram_to_iac-1.13.0.dist-info/RECORD,,