codeframe-ai 0.9.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 (197) hide show
  1. codeframe/__init__.py +11 -0
  2. codeframe/__main__.py +20 -0
  3. codeframe/adapters/__init__.py +5 -0
  4. codeframe/adapters/e2b/__init__.py +13 -0
  5. codeframe/adapters/e2b/adapter.py +342 -0
  6. codeframe/adapters/e2b/budget.py +71 -0
  7. codeframe/adapters/e2b/credential_scanner.py +134 -0
  8. codeframe/adapters/llm/__init__.py +92 -0
  9. codeframe/adapters/llm/anthropic.py +414 -0
  10. codeframe/adapters/llm/base.py +444 -0
  11. codeframe/adapters/llm/mock.py +281 -0
  12. codeframe/adapters/llm/openai.py +483 -0
  13. codeframe/agents/__init__.py +8 -0
  14. codeframe/agents/dependency_resolver.py +714 -0
  15. codeframe/auth/__init__.py +16 -0
  16. codeframe/auth/api_key_router.py +238 -0
  17. codeframe/auth/api_keys.py +156 -0
  18. codeframe/auth/dependencies.py +358 -0
  19. codeframe/auth/manager.py +178 -0
  20. codeframe/auth/models.py +30 -0
  21. codeframe/auth/router.py +93 -0
  22. codeframe/auth/schemas.py +15 -0
  23. codeframe/auth/scopes.py +53 -0
  24. codeframe/cli/__init__.py +12 -0
  25. codeframe/cli/__main__.py +20 -0
  26. codeframe/cli/api_client.py +275 -0
  27. codeframe/cli/app.py +5688 -0
  28. codeframe/cli/auth.py +122 -0
  29. codeframe/cli/auth_commands.py +958 -0
  30. codeframe/cli/commands/__init__.py +5 -0
  31. codeframe/cli/config_commands.py +79 -0
  32. codeframe/cli/dashboard_commands.py +67 -0
  33. codeframe/cli/engines_commands.py +205 -0
  34. codeframe/cli/env_commands.py +409 -0
  35. codeframe/cli/helpers.py +56 -0
  36. codeframe/cli/hooks_commands.py +208 -0
  37. codeframe/cli/import_commands.py +129 -0
  38. codeframe/cli/pr_commands.py +549 -0
  39. codeframe/cli/proof_commands.py +415 -0
  40. codeframe/cli/stats_commands.py +311 -0
  41. codeframe/cli/telemetry_runtime.py +153 -0
  42. codeframe/cli/validators.py +123 -0
  43. codeframe/config/rate_limits.py +165 -0
  44. codeframe/core/__init__.py +15 -0
  45. codeframe/core/adapters/__init__.py +43 -0
  46. codeframe/core/adapters/agent_adapter.py +114 -0
  47. codeframe/core/adapters/builtin.py +326 -0
  48. codeframe/core/adapters/claude_code.py +62 -0
  49. codeframe/core/adapters/codex.py +393 -0
  50. codeframe/core/adapters/git_utils.py +40 -0
  51. codeframe/core/adapters/kilocode.py +126 -0
  52. codeframe/core/adapters/opencode.py +48 -0
  53. codeframe/core/adapters/streaming_chat.py +483 -0
  54. codeframe/core/adapters/subprocess_adapter.py +213 -0
  55. codeframe/core/adapters/verification_wrapper.py +269 -0
  56. codeframe/core/agent.py +2183 -0
  57. codeframe/core/agents_config.py +569 -0
  58. codeframe/core/api_key_service.py +211 -0
  59. codeframe/core/artifacts.py +428 -0
  60. codeframe/core/blocker_detection.py +218 -0
  61. codeframe/core/blockers.py +433 -0
  62. codeframe/core/checkpoints.py +481 -0
  63. codeframe/core/conductor.py +2255 -0
  64. codeframe/core/config.py +827 -0
  65. codeframe/core/config_watcher.py +268 -0
  66. codeframe/core/context.py +542 -0
  67. codeframe/core/context_packager.py +234 -0
  68. codeframe/core/credentials.py +735 -0
  69. codeframe/core/dependency_analyzer.py +229 -0
  70. codeframe/core/dependency_graph.py +290 -0
  71. codeframe/core/diagnostic_agent.py +712 -0
  72. codeframe/core/diagnostics.py +616 -0
  73. codeframe/core/editor.py +556 -0
  74. codeframe/core/engine_registry.py +256 -0
  75. codeframe/core/engine_stats.py +231 -0
  76. codeframe/core/environment.py +697 -0
  77. codeframe/core/events.py +375 -0
  78. codeframe/core/executor.py +1005 -0
  79. codeframe/core/fix_tracker.py +480 -0
  80. codeframe/core/gates.py +1322 -0
  81. codeframe/core/git.py +477 -0
  82. codeframe/core/github_connect_service.py +178 -0
  83. codeframe/core/github_integration_config.py +118 -0
  84. codeframe/core/github_issues_service.py +449 -0
  85. codeframe/core/hooks.py +184 -0
  86. codeframe/core/importers/__init__.py +1 -0
  87. codeframe/core/importers/ralph.py +540 -0
  88. codeframe/core/installer.py +650 -0
  89. codeframe/core/models.py +1026 -0
  90. codeframe/core/notifications_config.py +183 -0
  91. codeframe/core/planner.py +437 -0
  92. codeframe/core/prd.py +670 -0
  93. codeframe/core/prd_discovery.py +1118 -0
  94. codeframe/core/prd_stress_test.py +499 -0
  95. codeframe/core/progress.py +126 -0
  96. codeframe/core/proof/__init__.py +34 -0
  97. codeframe/core/proof/capture.py +79 -0
  98. codeframe/core/proof/evidence.py +56 -0
  99. codeframe/core/proof/ledger.py +574 -0
  100. codeframe/core/proof/models.py +162 -0
  101. codeframe/core/proof/obligations.py +103 -0
  102. codeframe/core/proof/runner.py +233 -0
  103. codeframe/core/proof/scope.py +81 -0
  104. codeframe/core/proof/stubs.py +156 -0
  105. codeframe/core/quick_fixes.py +558 -0
  106. codeframe/core/react_agent.py +1650 -0
  107. codeframe/core/reconciliation.py +183 -0
  108. codeframe/core/replay.py +788 -0
  109. codeframe/core/review.py +285 -0
  110. codeframe/core/runtime.py +1134 -0
  111. codeframe/core/sandbox/__init__.py +27 -0
  112. codeframe/core/sandbox/context.py +98 -0
  113. codeframe/core/sandbox/worktree.py +20 -0
  114. codeframe/core/schedule.py +396 -0
  115. codeframe/core/stall_detector.py +71 -0
  116. codeframe/core/stall_monitor.py +134 -0
  117. codeframe/core/state_machine.py +121 -0
  118. codeframe/core/streaming.py +502 -0
  119. codeframe/core/task_tree.py +400 -0
  120. codeframe/core/tasks.py +1022 -0
  121. codeframe/core/telemetry.py +232 -0
  122. codeframe/core/templates.py +221 -0
  123. codeframe/core/tools.py +942 -0
  124. codeframe/core/workspace.py +887 -0
  125. codeframe/core/worktrees.py +276 -0
  126. codeframe/git/__init__.py +5 -0
  127. codeframe/git/github_integration.py +505 -0
  128. codeframe/lib/__init__.py +0 -0
  129. codeframe/lib/audit_logger.py +248 -0
  130. codeframe/lib/metrics_tracker.py +800 -0
  131. codeframe/lib/quality/__init__.py +7 -0
  132. codeframe/lib/quality/complexity_analyzer.py +316 -0
  133. codeframe/lib/quality/owasp_patterns.py +284 -0
  134. codeframe/lib/quality/security_scanner.py +250 -0
  135. codeframe/lib/rate_limiter.py +312 -0
  136. codeframe/notifications/__init__.py +0 -0
  137. codeframe/notifications/webhook.py +380 -0
  138. codeframe/planning/__init__.py +30 -0
  139. codeframe/planning/issue_generator.py +219 -0
  140. codeframe/planning/prd_template_functions.py +137 -0
  141. codeframe/planning/prd_templates.py +975 -0
  142. codeframe/planning/task_scheduler.py +511 -0
  143. codeframe/planning/task_templates.py +533 -0
  144. codeframe/platform_store/__init__.py +5 -0
  145. codeframe/platform_store/database.py +277 -0
  146. codeframe/platform_store/repositories/__init__.py +24 -0
  147. codeframe/platform_store/repositories/api_key_repository.py +245 -0
  148. codeframe/platform_store/repositories/audit_repository.py +67 -0
  149. codeframe/platform_store/repositories/base.py +295 -0
  150. codeframe/platform_store/repositories/interactive_sessions.py +165 -0
  151. codeframe/platform_store/repositories/token_repository.py +598 -0
  152. codeframe/platform_store/repositories/workspace_registry_repository.py +175 -0
  153. codeframe/platform_store/schema_manager.py +321 -0
  154. codeframe/templates/AGENTS.md.default +94 -0
  155. codeframe/tui/__init__.py +5 -0
  156. codeframe/tui/app.py +256 -0
  157. codeframe/tui/data_service.py +103 -0
  158. codeframe/ui/__init__.py +0 -0
  159. codeframe/ui/dependencies.py +103 -0
  160. codeframe/ui/models.py +999 -0
  161. codeframe/ui/response_models.py +201 -0
  162. codeframe/ui/routers/__init__.py +5 -0
  163. codeframe/ui/routers/_helpers.py +29 -0
  164. codeframe/ui/routers/batches_v2.py +315 -0
  165. codeframe/ui/routers/blockers_v2.py +320 -0
  166. codeframe/ui/routers/checkpoints_v2.py +310 -0
  167. codeframe/ui/routers/costs_v2.py +322 -0
  168. codeframe/ui/routers/diagnose_v2.py +225 -0
  169. codeframe/ui/routers/discovery_v2.py +417 -0
  170. codeframe/ui/routers/environment_v2.py +284 -0
  171. codeframe/ui/routers/events_v2.py +75 -0
  172. codeframe/ui/routers/gates_v2.py +166 -0
  173. codeframe/ui/routers/git_v2.py +284 -0
  174. codeframe/ui/routers/github_integrations_v2.py +532 -0
  175. codeframe/ui/routers/interactive_sessions_v2.py +238 -0
  176. codeframe/ui/routers/pr_v2.py +709 -0
  177. codeframe/ui/routers/prd_v2.py +695 -0
  178. codeframe/ui/routers/proof_v2.py +755 -0
  179. codeframe/ui/routers/review_v2.py +360 -0
  180. codeframe/ui/routers/schedule_v2.py +214 -0
  181. codeframe/ui/routers/session_chat_ws.py +354 -0
  182. codeframe/ui/routers/settings_v2.py +562 -0
  183. codeframe/ui/routers/streaming_v2.py +155 -0
  184. codeframe/ui/routers/tasks_v2.py +1098 -0
  185. codeframe/ui/routers/templates_v2.py +232 -0
  186. codeframe/ui/routers/terminal_ws.py +267 -0
  187. codeframe/ui/routers/workspace_v2.py +527 -0
  188. codeframe/ui/server.py +568 -0
  189. codeframe/ui/shared.py +241 -0
  190. codeframe/workspace/__init__.py +5 -0
  191. codeframe/workspace/manager.py +249 -0
  192. codeframe_ai-0.9.0.dist-info/METADATA +517 -0
  193. codeframe_ai-0.9.0.dist-info/RECORD +197 -0
  194. codeframe_ai-0.9.0.dist-info/WHEEL +5 -0
  195. codeframe_ai-0.9.0.dist-info/entry_points.txt +3 -0
  196. codeframe_ai-0.9.0.dist-info/licenses/LICENSE +661 -0
  197. codeframe_ai-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,269 @@
1
+ """Verification gate wrapper for agent adapters.
2
+
3
+ Wraps any AgentAdapter with post-execution verification gates, quick fixes,
4
+ fix attempt tracking, and escalation to blockers. This gives all execution
5
+ engines (built-in and external) the same self-correction capabilities that
6
+ ReactAgent has internally.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import logging
12
+ from pathlib import Path
13
+ from typing import Callable, Optional
14
+
15
+ from codeframe.core.adapters.agent_adapter import AgentAdapter, AgentEvent, AgentResult
16
+ from codeframe.core import blockers
17
+ from codeframe.core.fix_tracker import (
18
+ EscalationDecision,
19
+ FixAttemptTracker,
20
+ FixOutcome,
21
+ build_escalation_question,
22
+ )
23
+ from codeframe.core.gates import GateStatus
24
+ from codeframe.core.gates import run as run_gates
25
+ from codeframe.core.quick_fixes import apply_quick_fix, find_quick_fix
26
+ from codeframe.core.workspace import Workspace
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ class VerificationWrapper:
32
+ """Wraps any AgentAdapter with post-execution verification gates.
33
+
34
+ After the inner adapter completes, runs verification gates (pytest, ruff, etc.).
35
+ If gates fail:
36
+ 1. Try a pattern-based quick fix (no LLM needed)
37
+ 2. If quick fix applied, re-run gates immediately
38
+ 3. If no quick fix, re-invoke adapter with error context for self-correction
39
+ 4. Track all fix attempts to detect loops
40
+ 5. Escalate to blocker when fix tracker recommends it or retries exhausted
41
+
42
+ This is the same self-correction pattern that ReactAgent._run_final_verification()
43
+ uses, but decoupled from any specific engine so it wraps any adapter.
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ inner: AgentAdapter,
49
+ workspace: Workspace,
50
+ max_correction_rounds: int = 5,
51
+ gate_names: Optional[list[str]] = None,
52
+ verbose: bool = False,
53
+ ) -> None:
54
+ self._inner = inner
55
+ self._workspace = workspace
56
+ self._max_correction_rounds = max_correction_rounds
57
+ self._gate_names = gate_names # None = use default gates
58
+ self._verbose = verbose
59
+ self.fix_tracker = FixAttemptTracker()
60
+
61
+ @property
62
+ def name(self) -> str:
63
+ return f"verified-{self._inner.name}"
64
+
65
+ def run(
66
+ self,
67
+ task_id: str,
68
+ prompt: str,
69
+ workspace_path: Path,
70
+ on_event: Callable[[AgentEvent], None] | None = None,
71
+ ) -> AgentResult:
72
+ """Run the inner adapter, then verify with gates. Self-correct on failure."""
73
+
74
+ # Initial run
75
+ result = self._inner.run(task_id, prompt, workspace_path, on_event)
76
+
77
+ # Only verify if the adapter reported success
78
+ if result.status != "completed":
79
+ return result
80
+
81
+ # Run verification gates with self-correction loop
82
+ for round_num in range(self._max_correction_rounds):
83
+ if on_event:
84
+ on_event(AgentEvent(
85
+ type="verification",
86
+ data={
87
+ "round": round_num + 1,
88
+ "max_rounds": self._max_correction_rounds,
89
+ },
90
+ ))
91
+
92
+ gate_result = run_gates(
93
+ self._workspace,
94
+ gates=self._gate_names,
95
+ verbose=self._verbose,
96
+ )
97
+
98
+ if gate_result.passed:
99
+ if on_event:
100
+ on_event(AgentEvent(type="verification_passed", data={}))
101
+ return result
102
+
103
+ # Gates failed — get structured error summary
104
+ error_summary = (
105
+ gate_result.get_error_summary() or
106
+ self._format_gate_errors(gate_result)
107
+ )
108
+
109
+ if on_event:
110
+ on_event(AgentEvent(
111
+ type="verification_failed",
112
+ data={
113
+ "round": round_num + 1,
114
+ "checks": len(gate_result.checks),
115
+ },
116
+ ))
117
+
118
+ # 1. Record the attempt (outcome deferred until we know if fix works)
119
+ self.fix_tracker.record_attempt(error_summary, "verification_gate")
120
+
121
+ # 2. Check escalation based on prior history
122
+ escalation = self.fix_tracker.should_escalate(error_summary)
123
+ if escalation.should_escalate:
124
+ self.fix_tracker.record_outcome(
125
+ error_summary, "verification_gate", FixOutcome.FAILED,
126
+ )
127
+ return self._create_escalation_blocker(
128
+ task_id, error_summary, escalation,
129
+ last_output=result.output,
130
+ )
131
+
132
+ # 3. Try quick fix first (no adapter re-invocation needed)
133
+ if self._try_quick_fix(error_summary):
134
+ self.fix_tracker.record_outcome(
135
+ error_summary, "verification_gate", FixOutcome.SUCCESS,
136
+ )
137
+ self._verbose_print(
138
+ f"[VerificationWrapper] Quick fix applied (round {round_num + 1})"
139
+ )
140
+ continue # Re-run gates without re-invoking adapter
141
+
142
+ # 4. No quick fix — record failure and re-invoke adapter with error context
143
+ self.fix_tracker.record_outcome(
144
+ error_summary, "verification_gate", FixOutcome.FAILED,
145
+ )
146
+ formatted_errors = self._format_gate_errors(gate_result)
147
+ correction_prompt = (
148
+ f"{prompt}\n\n"
149
+ f"## Verification Gate Failures (Correction Round {round_num + 1})\n\n"
150
+ f"Your previous changes failed the following verification gates. "
151
+ f"Fix these issues:\n\n{formatted_errors}"
152
+ )
153
+
154
+ result = self._inner.run(
155
+ task_id, correction_prompt, workspace_path, on_event,
156
+ )
157
+
158
+ if result.status != "completed":
159
+ return result
160
+
161
+ # Final gate check after all correction rounds
162
+ gate_result = run_gates(
163
+ self._workspace,
164
+ gates=self._gate_names,
165
+ verbose=self._verbose,
166
+ )
167
+
168
+ if gate_result.passed:
169
+ return result
170
+
171
+ # All rounds exhausted — create blocker
172
+ error_summary = self._format_gate_errors(gate_result)
173
+ return self._create_exhaustion_blocker(
174
+ task_id, error_summary, last_output=result.output,
175
+ )
176
+
177
+ def _try_quick_fix(self, error_summary: str) -> bool:
178
+ """Attempt a pattern-based quick fix for the gate error.
179
+
180
+ Returns True if a fix was successfully applied.
181
+ """
182
+ fix = find_quick_fix(error_summary, repo_path=self._workspace.repo_path)
183
+ if fix is None:
184
+ return False
185
+
186
+ success, msg = apply_quick_fix(fix, self._workspace.repo_path)
187
+ if success:
188
+ self._verbose_print(f"[VerificationWrapper] Quick fix: {msg}")
189
+ return success
190
+
191
+ def _create_escalation_blocker(
192
+ self,
193
+ task_id: str,
194
+ error: str,
195
+ escalation: EscalationDecision,
196
+ last_output: str = "",
197
+ ) -> AgentResult:
198
+ """Create a blocker when fix tracker recommends escalation."""
199
+ question = build_escalation_question(
200
+ error, escalation.reason, self.fix_tracker,
201
+ )
202
+
203
+ try:
204
+ blockers.create(
205
+ workspace=self._workspace,
206
+ question=question,
207
+ task_id=task_id,
208
+ created_by="agent",
209
+ )
210
+ except Exception:
211
+ logger.warning("Failed to create escalation blocker", exc_info=True)
212
+
213
+ return AgentResult(
214
+ status="blocked",
215
+ output=last_output,
216
+ blocker_question=question,
217
+ error=f"Escalated to blocker: {escalation.reason}",
218
+ )
219
+
220
+ def _create_exhaustion_blocker(
221
+ self,
222
+ task_id: str,
223
+ error_summary: str,
224
+ last_output: str = "",
225
+ ) -> AgentResult:
226
+ """Create a blocker when all correction rounds are exhausted."""
227
+ question = (
228
+ f"Verification gates still failing after "
229
+ f"{self._max_correction_rounds} correction rounds.\n\n"
230
+ f"Errors:\n{error_summary[:500]}\n\n"
231
+ f"Please investigate and provide guidance."
232
+ )
233
+
234
+ try:
235
+ blockers.create(
236
+ workspace=self._workspace,
237
+ question=question,
238
+ task_id=task_id,
239
+ created_by="agent",
240
+ )
241
+ except Exception:
242
+ logger.warning("Failed to create exhaustion blocker", exc_info=True)
243
+
244
+ return AgentResult(
245
+ status="blocked",
246
+ output=last_output,
247
+ blocker_question=question,
248
+ error=(
249
+ f"Verification gates still failing after "
250
+ f"{self._max_correction_rounds} correction rounds:\n{error_summary}"
251
+ ),
252
+ )
253
+
254
+ def _verbose_print(self, msg: str) -> None:
255
+ if self._verbose:
256
+ print(msg)
257
+
258
+ @staticmethod
259
+ def _format_gate_errors(gate_result) -> str:
260
+ """Format gate check failures into a readable summary."""
261
+
262
+ lines: list[str] = []
263
+ for check in gate_result.checks:
264
+ if check.status == GateStatus.FAILED:
265
+ lines.append(f"### {check.name}: FAILED")
266
+ if check.output:
267
+ lines.append(f"```\n{check.output[:2000]}\n```")
268
+ lines.append("")
269
+ return "\n".join(lines) if lines else "Gate checks failed (no details available)"