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.
- teddy_cli-0.1.0.dist-info/LICENSE +677 -0
- teddy_cli-0.1.0.dist-info/METADATA +33 -0
- teddy_cli-0.1.0.dist-info/RECORD +143 -0
- teddy_cli-0.1.0.dist-info/WHEEL +4 -0
- teddy_cli-0.1.0.dist-info/entry_points.txt +3 -0
- teddy_executor/__init__.py +1 -0
- teddy_executor/__main__.py +335 -0
- teddy_executor/adapters/__init__.py +0 -0
- teddy_executor/adapters/inbound/__init__.py +0 -0
- teddy_executor/adapters/inbound/cli_formatter.py +107 -0
- teddy_executor/adapters/inbound/cli_helpers.py +249 -0
- teddy_executor/adapters/inbound/console_plan_reviewer.py +69 -0
- teddy_executor/adapters/inbound/session_cli_handlers.py +366 -0
- teddy_executor/adapters/inbound/textual_plan_reviewer.py +78 -0
- teddy_executor/adapters/inbound/textual_plan_reviewer_app.py +367 -0
- teddy_executor/adapters/inbound/textual_plan_reviewer_editor.py +281 -0
- teddy_executor/adapters/inbound/textual_plan_reviewer_execution.py +213 -0
- teddy_executor/adapters/inbound/textual_plan_reviewer_helpers.py +308 -0
- teddy_executor/adapters/inbound/textual_plan_reviewer_logic.py +345 -0
- teddy_executor/adapters/inbound/textual_plan_reviewer_previews.py +227 -0
- teddy_executor/adapters/inbound/textual_plan_reviewer_widgets.py +246 -0
- teddy_executor/adapters/outbound/__init__.py +7 -0
- teddy_executor/adapters/outbound/console_interactor.py +212 -0
- teddy_executor/adapters/outbound/console_interactor_ask_loop.py +121 -0
- teddy_executor/adapters/outbound/console_interactor_helpers.py +95 -0
- teddy_executor/adapters/outbound/console_tooling.py +62 -0
- teddy_executor/adapters/outbound/filesystem_helpers.py +61 -0
- teddy_executor/adapters/outbound/litellm_adapter.py +462 -0
- teddy_executor/adapters/outbound/local_file_system_adapter.py +300 -0
- teddy_executor/adapters/outbound/local_repo_tree_generator.py +96 -0
- teddy_executor/adapters/outbound/openrouter_hydrator.py +89 -0
- teddy_executor/adapters/outbound/shell_adapter.py +344 -0
- teddy_executor/adapters/outbound/shell_command_builder.py +105 -0
- teddy_executor/adapters/outbound/system_environment_adapter.py +62 -0
- teddy_executor/adapters/outbound/system_environment_inspector.py +54 -0
- teddy_executor/adapters/outbound/system_time_adapter.py +22 -0
- teddy_executor/adapters/outbound/web_scraper_adapter.py +346 -0
- teddy_executor/adapters/outbound/web_searcher_adapter.py +122 -0
- teddy_executor/adapters/outbound/yaml_config_adapter.py +105 -0
- teddy_executor/container.py +333 -0
- teddy_executor/core/__init__.py +0 -0
- teddy_executor/core/domain/__init__.py +0 -0
- teddy_executor/core/domain/models/__init__.py +44 -0
- teddy_executor/core/domain/models/action_ports.py +28 -0
- teddy_executor/core/domain/models/change_set.py +10 -0
- teddy_executor/core/domain/models/exceptions.py +40 -0
- teddy_executor/core/domain/models/execution_report.py +65 -0
- teddy_executor/core/domain/models/orchestrator_ports.py +26 -0
- teddy_executor/core/domain/models/plan.py +85 -0
- teddy_executor/core/domain/models/planning_ports.py +43 -0
- teddy_executor/core/domain/models/project_context.py +56 -0
- teddy_executor/core/domain/models/report_assembly_data.py +18 -0
- teddy_executor/core/domain/models/session.py +17 -0
- teddy_executor/core/domain/models/shell_output.py +12 -0
- teddy_executor/core/domain/models/web_search_results.py +26 -0
- teddy_executor/core/ports/__init__.py +0 -0
- teddy_executor/core/ports/inbound/__init__.py +0 -0
- teddy_executor/core/ports/inbound/edit_simulator.py +33 -0
- teddy_executor/core/ports/inbound/get_context_use_case.py +32 -0
- teddy_executor/core/ports/inbound/init.py +15 -0
- teddy_executor/core/ports/inbound/plan_parser.py +52 -0
- teddy_executor/core/ports/inbound/plan_reviewer.py +44 -0
- teddy_executor/core/ports/inbound/plan_validator.py +26 -0
- teddy_executor/core/ports/inbound/planning_use_case.py +30 -0
- teddy_executor/core/ports/inbound/run_plan_use_case.py +60 -0
- teddy_executor/core/ports/outbound/__init__.py +34 -0
- teddy_executor/core/ports/outbound/config_service.py +29 -0
- teddy_executor/core/ports/outbound/environment_inspector.py +30 -0
- teddy_executor/core/ports/outbound/execution_report_assembler.py +19 -0
- teddy_executor/core/ports/outbound/file_system_manager.py +131 -0
- teddy_executor/core/ports/outbound/llm_client.py +90 -0
- teddy_executor/core/ports/outbound/markdown_report_formatter.py +26 -0
- teddy_executor/core/ports/outbound/prompt_manager.py +55 -0
- teddy_executor/core/ports/outbound/repo_tree_generator.py +17 -0
- teddy_executor/core/ports/outbound/session_loop_guard.py +16 -0
- teddy_executor/core/ports/outbound/session_manager.py +97 -0
- teddy_executor/core/ports/outbound/session_repository.py +65 -0
- teddy_executor/core/ports/outbound/shell_executor.py +24 -0
- teddy_executor/core/ports/outbound/system_environment.py +25 -0
- teddy_executor/core/ports/outbound/time_service.py +28 -0
- teddy_executor/core/ports/outbound/user_interactor.py +126 -0
- teddy_executor/core/ports/outbound/web_scraper.py +24 -0
- teddy_executor/core/ports/outbound/web_searcher.py +25 -0
- teddy_executor/core/services/__init__.py +0 -0
- teddy_executor/core/services/action_changeset_builder.py +90 -0
- teddy_executor/core/services/action_diff_manager.py +110 -0
- teddy_executor/core/services/action_dispatcher.py +142 -0
- teddy_executor/core/services/action_executor.py +209 -0
- teddy_executor/core/services/action_factory.py +197 -0
- teddy_executor/core/services/action_parser_complex.py +216 -0
- teddy_executor/core/services/action_parser_strategies.py +84 -0
- teddy_executor/core/services/context_service.py +437 -0
- teddy_executor/core/services/edit_simulator.py +128 -0
- teddy_executor/core/services/execution_orchestrator.py +295 -0
- teddy_executor/core/services/execution_report_assembler.py +62 -0
- teddy_executor/core/services/init_service.py +80 -0
- teddy_executor/core/services/markdown_plan_parser.py +309 -0
- teddy_executor/core/services/markdown_report_formatter.py +143 -0
- teddy_executor/core/services/parser_infrastructure.py +222 -0
- teddy_executor/core/services/parser_metadata.py +153 -0
- teddy_executor/core/services/parser_reporting.py +267 -0
- teddy_executor/core/services/plan_validator.py +82 -0
- teddy_executor/core/services/planning_service.py +242 -0
- teddy_executor/core/services/prompt_manager.py +146 -0
- teddy_executor/core/services/session_lifecycle_manager.py +228 -0
- teddy_executor/core/services/session_loop_guard.py +46 -0
- teddy_executor/core/services/session_orchestrator.py +538 -0
- teddy_executor/core/services/session_planner.py +43 -0
- teddy_executor/core/services/session_pruning_service.py +438 -0
- teddy_executor/core/services/session_replanner.py +105 -0
- teddy_executor/core/services/session_repository.py +194 -0
- teddy_executor/core/services/session_service.py +529 -0
- teddy_executor/core/services/templates/execution_report.md.j2 +290 -0
- teddy_executor/core/services/validation_rules/__init__.py +4 -0
- teddy_executor/core/services/validation_rules/edit.py +207 -0
- teddy_executor/core/services/validation_rules/edit_matcher.py +247 -0
- teddy_executor/core/services/validation_rules/edit_matcher_heuristics.py +84 -0
- teddy_executor/core/services/validation_rules/execute.py +37 -0
- teddy_executor/core/services/validation_rules/filesystem.py +73 -0
- teddy_executor/core/services/validation_rules/helpers.py +178 -0
- teddy_executor/core/services/validation_rules/message.py +29 -0
- teddy_executor/core/utils/__init__.py +1 -0
- teddy_executor/core/utils/diff.py +57 -0
- teddy_executor/core/utils/io.py +75 -0
- teddy_executor/core/utils/markdown.py +131 -0
- teddy_executor/core/utils/serialization.py +39 -0
- teddy_executor/core/utils/string.py +351 -0
- teddy_executor/prompts.py +45 -0
- teddy_executor/registries/__init__.py +1 -0
- teddy_executor/registries/infrastructure.py +147 -0
- teddy_executor/registries/reviewer.py +57 -0
- teddy_executor/registries/validators.py +47 -0
- teddy_executor/resources/__init__.py +1 -0
- teddy_executor/resources/config/.gitignore +2 -0
- teddy_executor/resources/config/__init__.py +1 -0
- teddy_executor/resources/config/config.yaml +49 -0
- teddy_executor/resources/config/init.context +5 -0
- teddy_executor/resources/config/prompts/architect.xml +462 -0
- teddy_executor/resources/config/prompts/assistant.xml +336 -0
- teddy_executor/resources/config/prompts/debugger.xml +456 -0
- teddy_executor/resources/config/prompts/developer.xml +481 -0
- teddy_executor/resources/config/prompts/pathfinder.xml +502 -0
- 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,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
|