teddy-cli 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 (143) hide show
  1. teddy_cli-0.1.0.dist-info/LICENSE +677 -0
  2. teddy_cli-0.1.0.dist-info/METADATA +33 -0
  3. teddy_cli-0.1.0.dist-info/RECORD +143 -0
  4. teddy_cli-0.1.0.dist-info/WHEEL +4 -0
  5. teddy_cli-0.1.0.dist-info/entry_points.txt +3 -0
  6. teddy_executor/__init__.py +1 -0
  7. teddy_executor/__main__.py +335 -0
  8. teddy_executor/adapters/__init__.py +0 -0
  9. teddy_executor/adapters/inbound/__init__.py +0 -0
  10. teddy_executor/adapters/inbound/cli_formatter.py +107 -0
  11. teddy_executor/adapters/inbound/cli_helpers.py +249 -0
  12. teddy_executor/adapters/inbound/console_plan_reviewer.py +69 -0
  13. teddy_executor/adapters/inbound/session_cli_handlers.py +366 -0
  14. teddy_executor/adapters/inbound/textual_plan_reviewer.py +78 -0
  15. teddy_executor/adapters/inbound/textual_plan_reviewer_app.py +367 -0
  16. teddy_executor/adapters/inbound/textual_plan_reviewer_editor.py +281 -0
  17. teddy_executor/adapters/inbound/textual_plan_reviewer_execution.py +213 -0
  18. teddy_executor/adapters/inbound/textual_plan_reviewer_helpers.py +308 -0
  19. teddy_executor/adapters/inbound/textual_plan_reviewer_logic.py +345 -0
  20. teddy_executor/adapters/inbound/textual_plan_reviewer_previews.py +227 -0
  21. teddy_executor/adapters/inbound/textual_plan_reviewer_widgets.py +246 -0
  22. teddy_executor/adapters/outbound/__init__.py +7 -0
  23. teddy_executor/adapters/outbound/console_interactor.py +212 -0
  24. teddy_executor/adapters/outbound/console_interactor_ask_loop.py +121 -0
  25. teddy_executor/adapters/outbound/console_interactor_helpers.py +95 -0
  26. teddy_executor/adapters/outbound/console_tooling.py +62 -0
  27. teddy_executor/adapters/outbound/filesystem_helpers.py +61 -0
  28. teddy_executor/adapters/outbound/litellm_adapter.py +462 -0
  29. teddy_executor/adapters/outbound/local_file_system_adapter.py +300 -0
  30. teddy_executor/adapters/outbound/local_repo_tree_generator.py +96 -0
  31. teddy_executor/adapters/outbound/openrouter_hydrator.py +89 -0
  32. teddy_executor/adapters/outbound/shell_adapter.py +344 -0
  33. teddy_executor/adapters/outbound/shell_command_builder.py +105 -0
  34. teddy_executor/adapters/outbound/system_environment_adapter.py +62 -0
  35. teddy_executor/adapters/outbound/system_environment_inspector.py +54 -0
  36. teddy_executor/adapters/outbound/system_time_adapter.py +22 -0
  37. teddy_executor/adapters/outbound/web_scraper_adapter.py +346 -0
  38. teddy_executor/adapters/outbound/web_searcher_adapter.py +122 -0
  39. teddy_executor/adapters/outbound/yaml_config_adapter.py +105 -0
  40. teddy_executor/container.py +333 -0
  41. teddy_executor/core/__init__.py +0 -0
  42. teddy_executor/core/domain/__init__.py +0 -0
  43. teddy_executor/core/domain/models/__init__.py +44 -0
  44. teddy_executor/core/domain/models/action_ports.py +28 -0
  45. teddy_executor/core/domain/models/change_set.py +10 -0
  46. teddy_executor/core/domain/models/exceptions.py +40 -0
  47. teddy_executor/core/domain/models/execution_report.py +65 -0
  48. teddy_executor/core/domain/models/orchestrator_ports.py +26 -0
  49. teddy_executor/core/domain/models/plan.py +85 -0
  50. teddy_executor/core/domain/models/planning_ports.py +43 -0
  51. teddy_executor/core/domain/models/project_context.py +56 -0
  52. teddy_executor/core/domain/models/report_assembly_data.py +18 -0
  53. teddy_executor/core/domain/models/session.py +17 -0
  54. teddy_executor/core/domain/models/shell_output.py +12 -0
  55. teddy_executor/core/domain/models/web_search_results.py +26 -0
  56. teddy_executor/core/ports/__init__.py +0 -0
  57. teddy_executor/core/ports/inbound/__init__.py +0 -0
  58. teddy_executor/core/ports/inbound/edit_simulator.py +33 -0
  59. teddy_executor/core/ports/inbound/get_context_use_case.py +32 -0
  60. teddy_executor/core/ports/inbound/init.py +15 -0
  61. teddy_executor/core/ports/inbound/plan_parser.py +52 -0
  62. teddy_executor/core/ports/inbound/plan_reviewer.py +44 -0
  63. teddy_executor/core/ports/inbound/plan_validator.py +26 -0
  64. teddy_executor/core/ports/inbound/planning_use_case.py +30 -0
  65. teddy_executor/core/ports/inbound/run_plan_use_case.py +60 -0
  66. teddy_executor/core/ports/outbound/__init__.py +34 -0
  67. teddy_executor/core/ports/outbound/config_service.py +29 -0
  68. teddy_executor/core/ports/outbound/environment_inspector.py +30 -0
  69. teddy_executor/core/ports/outbound/execution_report_assembler.py +19 -0
  70. teddy_executor/core/ports/outbound/file_system_manager.py +131 -0
  71. teddy_executor/core/ports/outbound/llm_client.py +90 -0
  72. teddy_executor/core/ports/outbound/markdown_report_formatter.py +26 -0
  73. teddy_executor/core/ports/outbound/prompt_manager.py +55 -0
  74. teddy_executor/core/ports/outbound/repo_tree_generator.py +17 -0
  75. teddy_executor/core/ports/outbound/session_loop_guard.py +16 -0
  76. teddy_executor/core/ports/outbound/session_manager.py +97 -0
  77. teddy_executor/core/ports/outbound/session_repository.py +65 -0
  78. teddy_executor/core/ports/outbound/shell_executor.py +24 -0
  79. teddy_executor/core/ports/outbound/system_environment.py +25 -0
  80. teddy_executor/core/ports/outbound/time_service.py +28 -0
  81. teddy_executor/core/ports/outbound/user_interactor.py +126 -0
  82. teddy_executor/core/ports/outbound/web_scraper.py +24 -0
  83. teddy_executor/core/ports/outbound/web_searcher.py +25 -0
  84. teddy_executor/core/services/__init__.py +0 -0
  85. teddy_executor/core/services/action_changeset_builder.py +90 -0
  86. teddy_executor/core/services/action_diff_manager.py +110 -0
  87. teddy_executor/core/services/action_dispatcher.py +142 -0
  88. teddy_executor/core/services/action_executor.py +209 -0
  89. teddy_executor/core/services/action_factory.py +197 -0
  90. teddy_executor/core/services/action_parser_complex.py +216 -0
  91. teddy_executor/core/services/action_parser_strategies.py +84 -0
  92. teddy_executor/core/services/context_service.py +437 -0
  93. teddy_executor/core/services/edit_simulator.py +128 -0
  94. teddy_executor/core/services/execution_orchestrator.py +295 -0
  95. teddy_executor/core/services/execution_report_assembler.py +62 -0
  96. teddy_executor/core/services/init_service.py +80 -0
  97. teddy_executor/core/services/markdown_plan_parser.py +309 -0
  98. teddy_executor/core/services/markdown_report_formatter.py +143 -0
  99. teddy_executor/core/services/parser_infrastructure.py +222 -0
  100. teddy_executor/core/services/parser_metadata.py +153 -0
  101. teddy_executor/core/services/parser_reporting.py +267 -0
  102. teddy_executor/core/services/plan_validator.py +82 -0
  103. teddy_executor/core/services/planning_service.py +242 -0
  104. teddy_executor/core/services/prompt_manager.py +146 -0
  105. teddy_executor/core/services/session_lifecycle_manager.py +228 -0
  106. teddy_executor/core/services/session_loop_guard.py +46 -0
  107. teddy_executor/core/services/session_orchestrator.py +538 -0
  108. teddy_executor/core/services/session_planner.py +43 -0
  109. teddy_executor/core/services/session_pruning_service.py +438 -0
  110. teddy_executor/core/services/session_replanner.py +105 -0
  111. teddy_executor/core/services/session_repository.py +194 -0
  112. teddy_executor/core/services/session_service.py +529 -0
  113. teddy_executor/core/services/templates/execution_report.md.j2 +290 -0
  114. teddy_executor/core/services/validation_rules/__init__.py +4 -0
  115. teddy_executor/core/services/validation_rules/edit.py +207 -0
  116. teddy_executor/core/services/validation_rules/edit_matcher.py +247 -0
  117. teddy_executor/core/services/validation_rules/edit_matcher_heuristics.py +84 -0
  118. teddy_executor/core/services/validation_rules/execute.py +37 -0
  119. teddy_executor/core/services/validation_rules/filesystem.py +73 -0
  120. teddy_executor/core/services/validation_rules/helpers.py +178 -0
  121. teddy_executor/core/services/validation_rules/message.py +29 -0
  122. teddy_executor/core/utils/__init__.py +1 -0
  123. teddy_executor/core/utils/diff.py +57 -0
  124. teddy_executor/core/utils/io.py +75 -0
  125. teddy_executor/core/utils/markdown.py +131 -0
  126. teddy_executor/core/utils/serialization.py +39 -0
  127. teddy_executor/core/utils/string.py +351 -0
  128. teddy_executor/prompts.py +45 -0
  129. teddy_executor/registries/__init__.py +1 -0
  130. teddy_executor/registries/infrastructure.py +147 -0
  131. teddy_executor/registries/reviewer.py +57 -0
  132. teddy_executor/registries/validators.py +47 -0
  133. teddy_executor/resources/__init__.py +1 -0
  134. teddy_executor/resources/config/.gitignore +2 -0
  135. teddy_executor/resources/config/__init__.py +1 -0
  136. teddy_executor/resources/config/config.yaml +49 -0
  137. teddy_executor/resources/config/init.context +5 -0
  138. teddy_executor/resources/config/prompts/architect.xml +462 -0
  139. teddy_executor/resources/config/prompts/assistant.xml +336 -0
  140. teddy_executor/resources/config/prompts/debugger.xml +456 -0
  141. teddy_executor/resources/config/prompts/developer.xml +481 -0
  142. teddy_executor/resources/config/prompts/pathfinder.xml +502 -0
  143. teddy_executor/resources/config/prompts/prototyper.xml +425 -0
@@ -0,0 +1,333 @@
1
+ from __future__ import annotations
2
+
3
+ import punq
4
+
5
+
6
+ from teddy_executor.registries.infrastructure import register_infrastructure
7
+ from teddy_executor.registries.reviewer import register_reviewer
8
+ from teddy_executor.registries.validators import register_validators
9
+
10
+ _container = None
11
+
12
+
13
+ def get_container():
14
+ global _container
15
+ if _container is None:
16
+ _container = create_container()
17
+ return _container
18
+
19
+
20
+ def create_container() -> punq.Container:
21
+ """
22
+ Creates and configures the dependency injection container.
23
+ """
24
+ container = punq.Container()
25
+ register_infrastructure(container)
26
+ register_validators(container)
27
+ _register_services(container)
28
+ _register_orchestration(container)
29
+ return container
30
+
31
+
32
+ def _register_services(container: punq.Container) -> None:
33
+ """Registers core application services."""
34
+ from teddy_executor.core.ports.inbound.edit_simulator import IEditSimulator
35
+ from teddy_executor.core.ports.inbound.plan_parser import IPlanParser
36
+ from teddy_executor.core.ports.outbound import (
37
+ IConfigService,
38
+ IFileSystemManager,
39
+ IMarkdownReportFormatter,
40
+ IUserInteractor,
41
+ )
42
+ from teddy_executor.core.services.action_dispatcher import (
43
+ ActionDispatcher,
44
+ IActionFactory,
45
+ )
46
+ from teddy_executor.core.services.action_executor import ActionExecutor
47
+ from teddy_executor.core.services.action_factory import ActionFactory
48
+ from teddy_executor.core.services.edit_simulator import EditSimulator
49
+ from teddy_executor.core.ports.outbound.session_repository import (
50
+ ISessionRepository,
51
+ )
52
+ from teddy_executor.core.services.session_repository import SessionRepository
53
+ from teddy_executor.core.services.markdown_plan_parser import MarkdownPlanParser
54
+ from teddy_executor.core.services.markdown_report_formatter import (
55
+ MarkdownReportFormatter,
56
+ )
57
+ from teddy_executor.core.services.session_loop_guard import (
58
+ ProductionSessionLoopGuard,
59
+ )
60
+ from teddy_executor.core.domain.models.action_ports import ActionPorts
61
+
62
+ container.register(
63
+ ISessionRepository,
64
+ factory=lambda: SessionRepository(container.resolve(IFileSystemManager)),
65
+ scope=punq.Scope.transient,
66
+ )
67
+ container.register(IEditSimulator, EditSimulator, scope=punq.Scope.transient)
68
+ container.register(IPlanParser, MarkdownPlanParser, scope=punq.Scope.transient)
69
+
70
+ register_reviewer(container)
71
+
72
+ from teddy_executor.core.ports.outbound import (
73
+ IShellExecutor,
74
+ IWebScraper,
75
+ IWebSearcher,
76
+ )
77
+ from teddy_executor.core.ports.outbound.session_loop_guard import ISessionLoopGuard
78
+
79
+ container.register(
80
+ IActionFactory,
81
+ factory=lambda: ActionFactory(
82
+ ports=ActionPorts(
83
+ shell_executor=container.resolve(IShellExecutor),
84
+ file_system_manager=container.resolve(IFileSystemManager),
85
+ user_interactor=container.resolve(IUserInteractor),
86
+ web_scraper=container.resolve(IWebScraper),
87
+ web_searcher=container.resolve(IWebSearcher),
88
+ config_service=container.resolve(IConfigService),
89
+ )
90
+ ),
91
+ scope=punq.Scope.transient,
92
+ )
93
+ container.register(ActionDispatcher, scope=punq.Scope.transient)
94
+ container.register(
95
+ ActionExecutor,
96
+ factory=lambda: ActionExecutor(
97
+ action_dispatcher=container.resolve(ActionDispatcher),
98
+ user_interactor=container.resolve(IUserInteractor),
99
+ file_system_manager=container.resolve(IFileSystemManager),
100
+ edit_simulator=container.resolve(IEditSimulator),
101
+ config_service=container.resolve(IConfigService),
102
+ ),
103
+ scope=punq.Scope.transient,
104
+ )
105
+ container.register(
106
+ IMarkdownReportFormatter, MarkdownReportFormatter, scope=punq.Scope.transient
107
+ )
108
+
109
+ container.register(
110
+ ISessionLoopGuard, ProductionSessionLoopGuard, scope=punq.Scope.transient
111
+ )
112
+ _register_orchestration_services(container)
113
+
114
+
115
+ def _register_orchestration_services(container: punq.Container) -> None:
116
+ """Registers orchestration and use case implementation services."""
117
+ from teddy_executor.core.ports.inbound.get_context_use_case import (
118
+ IGetContextUseCase,
119
+ )
120
+ from teddy_executor.core.ports.inbound.init import IInitUseCase
121
+ from teddy_executor.core.ports.inbound.planning_use_case import IPlanningUseCase
122
+ from teddy_executor.core.ports.inbound.plan_parser import IPlanParser
123
+ from teddy_executor.core.ports.inbound.plan_validator import IPlanValidator
124
+ from teddy_executor.core.ports.inbound.plan_reviewer import IPlanReviewer
125
+ from teddy_executor.core.ports.outbound import (
126
+ IConfigService,
127
+ IFileSystemManager,
128
+ ILlmClient,
129
+ ISessionManager,
130
+ IUserInteractor,
131
+ )
132
+ from teddy_executor.core.ports.outbound.execution_report_assembler import (
133
+ IExecutionReportAssembler,
134
+ )
135
+ from teddy_executor.core.services.action_executor import ActionExecutor
136
+ from teddy_executor.core.services.context_service import ContextService
137
+ from teddy_executor.core.services.execution_orchestrator import (
138
+ ExecutionOrchestrator,
139
+ )
140
+ from teddy_executor.core.services.execution_report_assembler import (
141
+ ExecutionReportAssembler,
142
+ )
143
+ from teddy_executor.core.services.init_service import InitService
144
+ from teddy_executor.core.ports.outbound.prompt_manager import IPromptManager
145
+ from teddy_executor.core.services.prompt_manager import PromptManager
146
+ from teddy_executor.core.services.planning_service import PlanningService
147
+ from teddy_executor.core.services.session_service import SessionService
148
+
149
+ container.register(
150
+ IExecutionReportAssembler, ExecutionReportAssembler, scope=punq.Scope.transient
151
+ )
152
+ from teddy_executor.core.domain.models.orchestrator_ports import OrchestratorPorts
153
+
154
+ container.register(
155
+ OrchestratorPorts,
156
+ factory=lambda: OrchestratorPorts(
157
+ plan_parser=container.resolve(IPlanParser),
158
+ plan_validator=container.resolve(IPlanValidator),
159
+ action_executor=container.resolve(ActionExecutor),
160
+ file_system_manager=container.resolve(IFileSystemManager),
161
+ report_assembler=container.resolve(IExecutionReportAssembler),
162
+ user_interactor=container.resolve(IUserInteractor),
163
+ plan_reviewer=container.resolve(IPlanReviewer),
164
+ ),
165
+ scope=punq.Scope.transient,
166
+ )
167
+ container.register(ExecutionOrchestrator, scope=punq.Scope.transient)
168
+ from teddy_executor.core.ports.outbound import (
169
+ IEnvironmentInspector,
170
+ IRepoTreeGenerator,
171
+ IWebScraper,
172
+ )
173
+
174
+ container.register(
175
+ ContextService,
176
+ factory=lambda: ContextService(
177
+ file_system_manager=container.resolve(IFileSystemManager),
178
+ repo_tree_generator=container.resolve(IRepoTreeGenerator),
179
+ environment_inspector=container.resolve(IEnvironmentInspector),
180
+ llm_client=container.resolve(ILlmClient),
181
+ web_scraper=container.resolve(IWebScraper),
182
+ ),
183
+ scope=punq.Scope.transient,
184
+ )
185
+ container.register(IGetContextUseCase, ContextService, scope=punq.Scope.transient)
186
+ from teddy_executor.core.domain.models.planning_ports import PlanningPorts
187
+
188
+ container.register(
189
+ IPromptManager,
190
+ factory=lambda: PromptManager(
191
+ file_system_manager=container.resolve(IFileSystemManager),
192
+ user_interactor=container.resolve(IUserInteractor),
193
+ ),
194
+ scope=punq.Scope.transient,
195
+ )
196
+
197
+ container.register(
198
+ PlanningPorts,
199
+ factory=lambda: PlanningPorts(
200
+ context=container.resolve(IGetContextUseCase),
201
+ llm=container.resolve(ILlmClient),
202
+ fs=container.resolve(IFileSystemManager),
203
+ config=container.resolve(IConfigService),
204
+ prompts=container.resolve(IPromptManager),
205
+ ui=container.resolve(IUserInteractor),
206
+ session_manager=container.resolve(ISessionManager),
207
+ ),
208
+ scope=punq.Scope.transient,
209
+ )
210
+ container.register(PlanningService, scope=punq.Scope.transient)
211
+ container.register(IPlanningUseCase, PlanningService, scope=punq.Scope.transient)
212
+ from teddy_executor.core.ports.outbound.session_repository import ISessionRepository
213
+ from teddy_executor.core.ports.outbound.time_service import ITimeService
214
+
215
+ container.register(
216
+ IInitUseCase,
217
+ factory=lambda: InitService(container.resolve(IFileSystemManager)),
218
+ scope=punq.Scope.transient,
219
+ )
220
+
221
+ container.register(
222
+ ISessionManager,
223
+ factory=lambda: SessionService(
224
+ file_system_manager=container.resolve(IFileSystemManager),
225
+ repository=container.resolve(ISessionRepository),
226
+ time_service=container.resolve(ITimeService),
227
+ prompt_manager=container.resolve(IPromptManager),
228
+ init_service=container.resolve(IInitUseCase),
229
+ config_service=container.resolve(IConfigService),
230
+ ),
231
+ scope=punq.Scope.transient,
232
+ )
233
+
234
+
235
+ def _register_orchestration(container: punq.Container) -> None:
236
+ """Registers session orchestration components."""
237
+ from teddy_executor.core.ports.inbound.get_context_use_case import (
238
+ IGetContextUseCase,
239
+ )
240
+ from teddy_executor.core.ports.inbound.run_plan_use_case import IRunPlanUseCase
241
+ from teddy_executor.core.ports.inbound.planning_use_case import IPlanningUseCase
242
+ from teddy_executor.core.ports.inbound.plan_parser import IPlanParser
243
+ from teddy_executor.core.ports.inbound.plan_validator import IPlanValidator
244
+ from teddy_executor.core.ports.outbound import (
245
+ IConfigService,
246
+ IFileSystemManager,
247
+ ILlmClient,
248
+ IMarkdownReportFormatter,
249
+ ISessionManager,
250
+ IUserInteractor,
251
+ )
252
+ from teddy_executor.core.ports.outbound.prompt_manager import IPromptManager
253
+ from teddy_executor.core.services.execution_orchestrator import (
254
+ ExecutionOrchestrator,
255
+ )
256
+ from teddy_executor.core.services.session_lifecycle_manager import (
257
+ SessionLifecycleManager,
258
+ )
259
+ from teddy_executor.core.services.session_orchestrator import SessionOrchestrator
260
+ from teddy_executor.core.services.session_planner import SessionPlanner
261
+ from teddy_executor.core.services.session_replanner import SessionReplanner
262
+ from teddy_executor.core.services.session_pruning_service import (
263
+ SessionPruningService,
264
+ )
265
+
266
+ container.register(
267
+ SessionPruningService,
268
+ factory=lambda: SessionPruningService(
269
+ config_service=container.resolve(IConfigService),
270
+ file_system_manager=container.resolve(IFileSystemManager),
271
+ ),
272
+ scope=punq.Scope.transient,
273
+ )
274
+ container.register(
275
+ SessionReplanner,
276
+ factory=lambda: SessionReplanner(
277
+ file_system_manager=container.resolve(IFileSystemManager),
278
+ planning_service=container.resolve(IPlanningUseCase),
279
+ ),
280
+ scope=punq.Scope.transient,
281
+ )
282
+ container.register(
283
+ SessionPlanner,
284
+ factory=lambda: SessionPlanner(
285
+ file_system_manager=container.resolve(IFileSystemManager),
286
+ planning_service=container.resolve(IPlanningUseCase),
287
+ user_interactor=container.resolve(IUserInteractor),
288
+ session_service=container.resolve(ISessionManager),
289
+ ),
290
+ scope=punq.Scope.transient,
291
+ )
292
+
293
+ from teddy_executor.core.domain.models.planning_ports import SessionPorts
294
+
295
+ container.register(
296
+ SessionPorts,
297
+ factory=lambda: SessionPorts(
298
+ session_service=container.resolve(ISessionManager),
299
+ file_system_manager=container.resolve(IFileSystemManager),
300
+ report_formatter=container.resolve(IMarkdownReportFormatter),
301
+ user_interactor=container.resolve(IUserInteractor),
302
+ session_planner=container.resolve(SessionPlanner),
303
+ replanner=container.resolve(SessionReplanner),
304
+ ),
305
+ scope=punq.Scope.transient,
306
+ )
307
+ container.register(
308
+ SessionLifecycleManager,
309
+ factory=lambda: SessionLifecycleManager(
310
+ ports=container.resolve(SessionPorts),
311
+ ),
312
+ scope=punq.Scope.transient,
313
+ )
314
+
315
+ container.register(
316
+ IRunPlanUseCase,
317
+ factory=lambda: SessionOrchestrator(
318
+ execution_orchestrator=container.resolve(ExecutionOrchestrator),
319
+ session_service=container.resolve(ISessionManager),
320
+ file_system_manager=container.resolve(IFileSystemManager),
321
+ plan_validator=container.resolve(IPlanValidator),
322
+ plan_parser=container.resolve(IPlanParser),
323
+ user_interactor=container.resolve(IUserInteractor),
324
+ lifecycle_manager=container.resolve(SessionLifecycleManager),
325
+ replanner=container.resolve(SessionReplanner),
326
+ context_service=container.resolve(IGetContextUseCase),
327
+ config_service=container.resolve(IConfigService),
328
+ llm_client=container.resolve(ILlmClient),
329
+ prompt_manager=container.resolve(IPromptManager),
330
+ pruning_service=container.resolve(SessionPruningService),
331
+ ),
332
+ scope=punq.Scope.transient,
333
+ )
File without changes
File without changes
@@ -0,0 +1,44 @@
1
+ from .execution_report import (
2
+ ActionLog,
3
+ ActionStatus,
4
+ ExecutionReport,
5
+ RunStatus,
6
+ RunSummary,
7
+ )
8
+ from .plan import ActionData, ActionType, Plan
9
+ from .exceptions import (
10
+ FileAlreadyExistsError,
11
+ MultipleMatchesFoundError,
12
+ SearchTextNotFoundError,
13
+ WebSearchError,
14
+ )
15
+ from .web_search_results import QueryResult
16
+ from .web_search_results import SearchResult
17
+ from .web_search_results import WebSearchResults
18
+ from .change_set import ChangeSet
19
+ from .project_context import ContextItem, ProjectContext
20
+ from .report_assembly_data import ReportAssemblyData
21
+ from .action_ports import ActionPorts
22
+
23
+ __all__ = [
24
+ "ActionPorts",
25
+ "ChangeSet",
26
+ "ContextItem",
27
+ "ProjectContext",
28
+ "ReportAssemblyData",
29
+ "Plan",
30
+ "ActionData",
31
+ "ActionType",
32
+ "ExecutionReport",
33
+ "ActionLog",
34
+ "RunSummary",
35
+ "RunStatus",
36
+ "ActionStatus",
37
+ "FileAlreadyExistsError",
38
+ "MultipleMatchesFoundError",
39
+ "SearchTextNotFoundError",
40
+ "WebSearchError",
41
+ "WebSearchResults",
42
+ "QueryResult",
43
+ "SearchResult",
44
+ ]
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+ from typing import Optional, TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from teddy_executor.core.ports.outbound import (
7
+ IShellExecutor,
8
+ IFileSystemManager,
9
+ IUserInteractor,
10
+ IWebScraper,
11
+ IWebSearcher,
12
+ IConfigService,
13
+ )
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class ActionPorts:
18
+ """
19
+ A data transfer object used to group the collection of outbound ports
20
+ required by the ActionFactory.
21
+ """
22
+
23
+ shell_executor: IShellExecutor
24
+ file_system_manager: IFileSystemManager
25
+ user_interactor: IUserInteractor
26
+ web_scraper: IWebScraper
27
+ web_searcher: IWebSearcher
28
+ config_service: Optional[IConfigService] = None
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+ from pathlib import Path
3
+
4
+
5
+ @dataclass(frozen=True)
6
+ class ChangeSet:
7
+ path: Path
8
+ before_content: str
9
+ after_content: str
10
+ action_type: str # 'CREATE' or 'EDIT'
@@ -0,0 +1,40 @@
1
+ from typing import Optional
2
+
3
+
4
+ class SearchTextNotFoundError(ValueError):
5
+ """Exception for when search text is not found during an edit operation."""
6
+
7
+ def __init__(self, message: str, content: str):
8
+ super().__init__(message)
9
+ self.content = content
10
+
11
+
12
+ class FileAlreadyExistsError(FileExistsError):
13
+ """Custom exception raised when trying to create a file that already exists."""
14
+
15
+ def __init__(self, message: str, file_path: str):
16
+ super().__init__(message)
17
+ self.file_path = file_path
18
+
19
+
20
+ class MultipleMatchesFoundError(Exception):
21
+ """Custom exception for when an edit operation finds multiple matches."""
22
+
23
+ def __init__(self, message: str, content: str):
24
+ super().__init__(message)
25
+ self.content = content
26
+
27
+
28
+ class WebSearchError(Exception):
29
+ """Custom exception raised when a web search operation fails."""
30
+
31
+ def __init__(self, message: str, original_exception: Optional[Exception] = None):
32
+ super().__init__(message)
33
+ self.original_exception = original_exception
34
+
35
+
36
+ class ConfigurationError(Exception):
37
+ """Custom exception raised when system configuration is invalid or missing."""
38
+
39
+ def __init__(self, message: str):
40
+ super().__init__(message)
@@ -0,0 +1,65 @@
1
+ from dataclasses import dataclass, field
2
+ from datetime import datetime
3
+ from enum import Enum
4
+ from typing import Any, Sequence
5
+
6
+ from teddy_executor.core.domain.models.plan import ActionData
7
+
8
+
9
+ class RunStatus(str, Enum):
10
+ """Overall status for an entire plan execution."""
11
+
12
+ SUCCESS = "SUCCESS"
13
+ FAILURE = "FAILURE"
14
+ VALIDATION_FAILED = "VALIDATION_FAILED"
15
+ SKIPPED = "SKIPPED"
16
+ ABORTED = "ABORTED"
17
+
18
+
19
+ class ActionStatus(str, Enum):
20
+ """Status for a single action within a plan."""
21
+
22
+ SUCCESS = "SUCCESS"
23
+ FAILURE = "FAILURE"
24
+ SKIPPED = "SKIPPED"
25
+ PENDING = "PENDING"
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class ActionLog:
30
+ """Logs the result of a single action execution."""
31
+
32
+ status: ActionStatus
33
+ action_type: str
34
+ params: dict[str, Any]
35
+ details: Any | None = None
36
+ modified: bool = False
37
+ modified_fields: list[str] = field(default_factory=list)
38
+ failed_command: str | None = None
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class RunSummary:
43
+ """Summarizes the overall result of a plan execution."""
44
+
45
+ status: RunStatus
46
+ start_time: datetime
47
+ end_time: datetime
48
+ error: str | None = None
49
+
50
+
51
+ @dataclass(frozen=True)
52
+ class ExecutionReport:
53
+ """The comprehensive report of a plan execution."""
54
+
55
+ run_summary: RunSummary
56
+ plan_title: str | None = None
57
+ rationale: str | None = None
58
+ user_request: str | None = None
59
+ is_session: bool = False
60
+ metadata: dict[str, str] = field(default_factory=dict)
61
+ original_actions: Sequence[ActionData] = field(default_factory=list)
62
+ action_logs: Sequence[ActionLog] = field(default_factory=list)
63
+ validation_result: Sequence[str] | None = None
64
+ validation_ast: str | None = None
65
+ failed_resources: dict[str, str] | None = None
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ if TYPE_CHECKING:
6
+ from teddy_executor.core.ports.inbound.plan_parser import IPlanParser
7
+ from teddy_executor.core.ports.inbound.plan_validator import IPlanValidator
8
+ from teddy_executor.core.ports.inbound.plan_reviewer import IPlanReviewer
9
+ from teddy_executor.core.ports.outbound import IFileSystemManager, IUserInteractor
10
+ from teddy_executor.core.ports.outbound.execution_report_assembler import (
11
+ IExecutionReportAssembler,
12
+ )
13
+ from teddy_executor.core.services.action_executor import ActionExecutor
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class OrchestratorPorts:
18
+ """Groups dependencies for the ExecutionOrchestrator."""
19
+
20
+ plan_parser: IPlanParser
21
+ plan_validator: IPlanValidator
22
+ action_executor: ActionExecutor
23
+ file_system_manager: IFileSystemManager
24
+ report_assembler: IExecutionReportAssembler
25
+ user_interactor: IUserInteractor
26
+ plan_reviewer: Optional[IPlanReviewer] = None
@@ -0,0 +1,85 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass, field
3
+ from enum import Enum
4
+ from typing import TYPE_CHECKING, Any, Optional, Sequence
5
+
6
+ if TYPE_CHECKING:
7
+ from teddy_executor.core.domain.models.execution_report import ActionLog
8
+
9
+
10
+ class ActionType(str, Enum):
11
+ CREATE = "CREATE"
12
+ READ = "READ"
13
+ EDIT = "EDIT"
14
+ EXECUTE = "EXECUTE"
15
+ RESEARCH = "RESEARCH"
16
+ MESSAGE = "MESSAGE"
17
+
18
+
19
+ class ExecutionStatus(str, Enum):
20
+ """Represents the possible execution states of an action."""
21
+
22
+ PENDING = "PENDING"
23
+ RUNNING = "RUNNING"
24
+ SUCCESS = "SUCCESS"
25
+ FAILURE = "FAILURE"
26
+ SKIPPED = "SKIPPED"
27
+
28
+
29
+ @dataclass
30
+ class ActionData:
31
+ """Represents a single action from the plan."""
32
+
33
+ type: str
34
+ params: dict[str, Any]
35
+ description: str | None = None
36
+ selected: bool = True
37
+ modified: bool = False
38
+ modified_fields: list[str] = field(default_factory=list)
39
+ executed: bool = False
40
+ state: ExecutionStatus = ExecutionStatus.PENDING
41
+ action_log: Optional[ActionLog] = None
42
+ user_response: Optional[str] = None
43
+ pending_temp_file: Optional[str] = None
44
+ node: Any = None
45
+ similarity_score: float | None = None
46
+ similarity_scores: list[float] | None = None
47
+
48
+ @property
49
+ def is_terminal(self) -> bool:
50
+ """Returns True if the action is a communication action."""
51
+ return self.type == ActionType.MESSAGE
52
+
53
+
54
+ @dataclass(frozen=True)
55
+ class ValidationError:
56
+ """Represents a structured validation error."""
57
+
58
+ message: str
59
+ action_index: int = 0
60
+ file_path: str | None = None
61
+ offending_node: Any = None
62
+
63
+
64
+ DEFAULT_SIMILARITY_THRESHOLD = 0.95
65
+
66
+
67
+ @dataclass
68
+ class Plan:
69
+ """Represents a parsed and validated execution plan."""
70
+
71
+ title: str
72
+ rationale: str
73
+ actions: Sequence[ActionData]
74
+ metadata: dict[str, str] = field(default_factory=dict)
75
+ source_doc: Any = None
76
+ is_session: bool = False
77
+ plan_path: str | None = None
78
+ raw_content: str | None = None
79
+
80
+ def __post_init__(self):
81
+ assert self.actions, "Plan must contain at least one action."
82
+
83
+ def is_communication_turn(self) -> bool:
84
+ """Returns True if the plan consists only of a MESSAGE action."""
85
+ return len(self.actions) == 1 and self.actions[0].type == ActionType.MESSAGE
@@ -0,0 +1,43 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+ from typing import TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from teddy_executor.core.ports.outbound.session_manager import ISessionManager
7
+ from teddy_executor.core.ports.outbound.markdown_report_formatter import (
8
+ IMarkdownReportFormatter,
9
+ )
10
+ from teddy_executor.core.services.session_planner import SessionPlanner
11
+ from teddy_executor.core.services.session_replanner import SessionReplanner
12
+
13
+ from teddy_executor.core.ports.inbound.get_context_use_case import IGetContextUseCase
14
+ from teddy_executor.core.ports.outbound.config_service import IConfigService
15
+ from teddy_executor.core.ports.outbound.file_system_manager import IFileSystemManager
16
+ from teddy_executor.core.ports.outbound.llm_client import ILlmClient
17
+ from teddy_executor.core.ports.outbound.prompt_manager import IPromptManager
18
+ from teddy_executor.core.ports.outbound.user_interactor import IUserInteractor
19
+
20
+
21
+ @dataclass(frozen=True)
22
+ class PlanningPorts:
23
+ """Outbound ports required by the PlanningService."""
24
+
25
+ context: IGetContextUseCase
26
+ llm: ILlmClient
27
+ fs: IFileSystemManager
28
+ config: IConfigService
29
+ prompts: IPromptManager
30
+ ui: IUserInteractor
31
+ session_manager: ISessionManager
32
+
33
+
34
+ @dataclass(frozen=True)
35
+ class SessionPorts:
36
+ """Ports required by the SessionLifecycleManager."""
37
+
38
+ session_service: ISessionManager
39
+ file_system_manager: IFileSystemManager
40
+ report_formatter: IMarkdownReportFormatter
41
+ user_interactor: IUserInteractor
42
+ session_planner: SessionPlanner
43
+ replanner: SessionReplanner