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,33 @@
1
+ Metadata-Version: 2.1
2
+ Name: teddy-cli
3
+ Version: 0.1.0
4
+ Summary: A local-first, file-based AI coding workflow that applies the UNIX philosophy to AI collaboration.
5
+ License: AGPL-3.0-only
6
+ Author: Raphael Atteritano
7
+ Requires-Python: >=3.11,<3.14
8
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Requires-Dist: aiohttp (>=3.14.0)
13
+ Requires-Dist: bandit (>=1.7.9,<1.8.0)
14
+ Requires-Dist: beautifulsoup4 (>=4.14.3,<5.0.0)
15
+ Requires-Dist: ddgs (>=9.10.0,<10.0.0)
16
+ Requires-Dist: detect-secrets (>=1.4,<2.0)
17
+ Requires-Dist: httpx (>=0.28.1,<0.29.0)
18
+ Requires-Dist: jinja2 (>=3.1.6,<4.0.0)
19
+ Requires-Dist: litellm (>=1.83.7,<2.0.0)
20
+ Requires-Dist: lxml (>=6.1.0,<7.0.0)
21
+ Requires-Dist: mistletoe (>=1.3.0,<2.0.0)
22
+ Requires-Dist: pathspec (>=0.12.1,<0.13.0)
23
+ Requires-Dist: pip-audit (>=2.7.3,<2.8.0)
24
+ Requires-Dist: playwright
25
+ Requires-Dist: punq (>=0.7.0,<0.8.0)
26
+ Requires-Dist: pyperclip
27
+ Requires-Dist: python-dotenv (>=1.0.1)
28
+ Requires-Dist: pyyaml (>=6.0,<7.0)
29
+ Requires-Dist: requests (>=2.33.0,<3.0.0)
30
+ Requires-Dist: textual (>=8.1.0,<9.0.0)
31
+ Requires-Dist: trafilatura (>=2.0.0,<3.0.0)
32
+ Requires-Dist: typer[all]
33
+ Requires-Dist: urllib3 (>=2.7.0,<3.0.0)
@@ -0,0 +1,143 @@
1
+ teddy_executor/__init__.py,sha256=xZ4r3lFwNLQ4C4vOl7Q_-5dh3TlWw3-nXR8O8yjV2o0,58
2
+ teddy_executor/__main__.py,sha256=Zt--RYeJI2SAaZVkhmZ35dXfKPfb_rYzCzvPrY1OqZw,11242
3
+ teddy_executor/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ teddy_executor/adapters/inbound/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ teddy_executor/adapters/inbound/cli_formatter.py,sha256=9bWL2S-3vZFBJZPd4RG2xTBYWu1Tim6U0AMGRjcUHB8,3548
6
+ teddy_executor/adapters/inbound/cli_helpers.py,sha256=xDJgnHijkA-iTXS10mx5FTrOMlk1iI1Vsn4eDPMNGcQ,8392
7
+ teddy_executor/adapters/inbound/console_plan_reviewer.py,sha256=Zi8wwxJNOHiB7iVeX346r6XHJDUWTukVGqEMHFQvDE8,2173
8
+ teddy_executor/adapters/inbound/session_cli_handlers.py,sha256=3hG8fl7z51JnvidXlJMbSW3X0kBrqCCyYbL2mD2IGLU,14155
9
+ teddy_executor/adapters/inbound/textual_plan_reviewer.py,sha256=YszopR-mQpatQi79ssOtw5XfKTKiYsOCWxyVBOMgd6U,2774
10
+ teddy_executor/adapters/inbound/textual_plan_reviewer_app.py,sha256=zrLTDRXApsrorOp6vBjNioiPSD98fkwa0xzp6R0cfMs,13755
11
+ teddy_executor/adapters/inbound/textual_plan_reviewer_editor.py,sha256=NV2zCDIMwKqbizmWHM_gLPSBigp4h7lz8msgCeuEUTM,9649
12
+ teddy_executor/adapters/inbound/textual_plan_reviewer_execution.py,sha256=LvMvPn5qiwf25dN5XnA-bEgkgBqOl7pkAy-FfnOQl9E,7222
13
+ teddy_executor/adapters/inbound/textual_plan_reviewer_helpers.py,sha256=tayFz5r2PLRlVxfbYo-TGKpJTM9i6yroc5bTtUmt8B8,11647
14
+ teddy_executor/adapters/inbound/textual_plan_reviewer_logic.py,sha256=dYJQ-pQhSeECeSuGAadhzBTpSJmG9bGLj-ZQk7UMids,11374
15
+ teddy_executor/adapters/inbound/textual_plan_reviewer_previews.py,sha256=D6ZG3pibkr69SetNknJrwD9ROWQvyGieS77Oy3qfU-Y,8203
16
+ teddy_executor/adapters/inbound/textual_plan_reviewer_widgets.py,sha256=_-pfFY_71m0s3tDKzqH_l28fF563V0h3cZXYPKvS2kI,7356
17
+ teddy_executor/adapters/outbound/__init__.py,sha256=YN-oxkFQlMVrj3YdAJoLKXA_uo91cSU4llc3UHJ1Ckg,157
18
+ teddy_executor/adapters/outbound/console_interactor.py,sha256=Pl7FeV2I3Lo2K7EbWuwZV5FML3FsbsibouYFazaTfb4,8381
19
+ teddy_executor/adapters/outbound/console_interactor_ask_loop.py,sha256=FC6RA1vg5DPN8Lm6vvKPTzu0W3ms3nC39WsWArw8kpM,4189
20
+ teddy_executor/adapters/outbound/console_interactor_helpers.py,sha256=JkLIfAmd9u9DcXh-MDy_KZLrgnZM5J9QoiE_dg10_uQ,3033
21
+ teddy_executor/adapters/outbound/console_tooling.py,sha256=oyCgf0E5rFnqcL6DN46H5W2DUi10HA8Wwk1JmPPgh9U,2361
22
+ teddy_executor/adapters/outbound/filesystem_helpers.py,sha256=09CUnJtrl2EVmqhC0mwJ5VA1kcZJc53ntoj9ttvZuw8,1780
23
+ teddy_executor/adapters/outbound/litellm_adapter.py,sha256=xpLGNA0W18GDFEHZg_w3UMTqAEWjzsQIIS-h85MqWfA,18194
24
+ teddy_executor/adapters/outbound/local_file_system_adapter.py,sha256=hi32bvYNVz2tgLjEjTOPL9JVj_sq55-BrKR5SN6O9Oc,11063
25
+ teddy_executor/adapters/outbound/local_repo_tree_generator.py,sha256=8SRQmQf1UX4ucwOh8_5vrbGjZnJKX6cY93Cic4LZnZs,3264
26
+ teddy_executor/adapters/outbound/openrouter_hydrator.py,sha256=5WycqzprvuAR6tsKc6Yke_iCSO3r1bhMCm3CfVfh3tI,3496
27
+ teddy_executor/adapters/outbound/shell_adapter.py,sha256=72P-MvkEno1E2ZbmQqLtBCc_d5Qgj5anpbbaabPB_v4,13183
28
+ teddy_executor/adapters/outbound/shell_command_builder.py,sha256=HnnAHRj7pBk-V2grjVy7ZMvMkmBlZY0gWpP1EX73B7k,3960
29
+ teddy_executor/adapters/outbound/system_environment_adapter.py,sha256=4tE-rwVWHMQ_9spJBZc3-3WFGXehOWcZKQ3yz-hvFic,2179
30
+ teddy_executor/adapters/outbound/system_environment_inspector.py,sha256=7JORQnENa9NNJBF-YvRyvxzZR_elMVCdDQyI1CCmqPQ,1629
31
+ teddy_executor/adapters/outbound/system_time_adapter.py,sha256=q2Kbe1kMk4mybijYaMZFrjqo7Bff9AQUUKXZ2Ei7Siw,627
32
+ teddy_executor/adapters/outbound/web_scraper_adapter.py,sha256=HePgcVaE0lG-X2S_ZLLoudv3sp5ZEPu27XMebY7EChs,13243
33
+ teddy_executor/adapters/outbound/web_searcher_adapter.py,sha256=XHkIN9RvbzHkiVzQZYbdI3KJavO0zFNGW7jgC4gHrz0,4546
34
+ teddy_executor/adapters/outbound/yaml_config_adapter.py,sha256=1qs73GUj6JvHZ-LWFnoYzBGgTVG3_ogVFbSkBHCVlsI,3716
35
+ teddy_executor/container.py,sha256=xek1ZR7Xc-z95XnIpTl_h87na-4KXWUZcC0OHGPThW8,13423
36
+ teddy_executor/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ teddy_executor/core/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ teddy_executor/core/domain/models/__init__.py,sha256=yok7EZ3_cUwVGPGjBwTLg-zL4XTyQs2xAi_4VPKdKCk,1062
39
+ teddy_executor/core/domain/models/action_ports.py,sha256=vCMBtLS1thqT1YcGRScwapQ9MXKbvKg3zWeEGpJ5IhE,733
40
+ teddy_executor/core/domain/models/change_set.py,sha256=FgR553--lmcX-3tqjEkRhpwPpvEnLXWZ14Vkc2XgV_k,207
41
+ teddy_executor/core/domain/models/exceptions.py,sha256=kR6-vUECe06kVem0KoeHo9OEdQIFFB2AP58eWNo9qYs,1243
42
+ teddy_executor/core/domain/models/execution_report.py,sha256=QH-vku88XQ6FrHuV_d4_IbCXrSeg7WK9ybNlr35wqtE,1737
43
+ teddy_executor/core/domain/models/orchestrator_ports.py,sha256=zdfPXOUFmN9Zicwn5YI6sTWpcHeaCyABBoLKl-w2zNk,1039
44
+ teddy_executor/core/domain/models/plan.py,sha256=J2fgkY2OOOJ2HXHmfrey0O8rDPCezw-047us-3V3qGc,2284
45
+ teddy_executor/core/domain/models/planning_ports.py,sha256=qFz_177i8HkUmzwMNDLzuS3W7aCmkyVERdpSCKfQ_AE,1592
46
+ teddy_executor/core/domain/models/project_context.py,sha256=5uXtnjm9EUp3uLCxxWKwVEAhwOlXgUcbiUxhS35FbzA,1694
47
+ teddy_executor/core/domain/models/report_assembly_data.py,sha256=HuLqpha3cZ_V7BZ8pdsdIxnxVvCJ8_-o30PQVdkydrE,432
48
+ teddy_executor/core/domain/models/session.py,sha256=TlzoMHr5J4qd2QHrS5K1YXvt5g4xjYNQjSMfWdx4sVY,419
49
+ teddy_executor/core/domain/models/shell_output.py,sha256=wmOqFzIKETAzyWFUc0smZ8N-hh3OBQsy5VHqIhitKbA,267
50
+ teddy_executor/core/domain/models/web_search_results.py,sha256=ZugVr76XB2QdS-vumtPxY5h9Y5EP8bctn7tefIIWkhw,578
51
+ teddy_executor/core/ports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ teddy_executor/core/ports/inbound/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ teddy_executor/core/ports/inbound/edit_simulator.py,sha256=Pu4tBJxK4ensZO1gH_YE_NuVMG99qzy6v5Q4pN_VT5s,1087
54
+ teddy_executor/core/ports/inbound/get_context_use_case.py,sha256=aqVSP-XsSuQa4tDLUdThHGjJr2Q8MPTYhs34MZbo-Ec,1098
55
+ teddy_executor/core/ports/inbound/init.py,sha256=eJ8W_hcSeggZBt1vZ87pvDKfMCFnOJh9NpBHY5-h9_4,349
56
+ teddy_executor/core/ports/inbound/plan_parser.py,sha256=BaH1XQM23ys6l4YMcb2VTXs7IjW2TgklUqQ-8dthSYQ,1603
57
+ teddy_executor/core/ports/inbound/plan_reviewer.py,sha256=iHJfl4P7P6kOr2QERBAuXRaQwtgE7eiqOdQDpeMotmY,1247
58
+ teddy_executor/core/ports/inbound/plan_validator.py,sha256=hKwpYeAHVf04mFvG8ofN9jkItxiCsW1mB4Er6lqFIPY,732
59
+ teddy_executor/core/ports/inbound/planning_use_case.py,sha256=-33ypPVn__rcPzz3E0nJc_jIfAxcPc5VK9dYkoqJEMc,899
60
+ teddy_executor/core/ports/inbound/run_plan_use_case.py,sha256=EKLdQUqJE0sSZnuLiUWdk5hHEYPlE-i_9eY4vd9fAvs,2166
61
+ teddy_executor/core/ports/outbound/__init__.py,sha256=9jIaHAj9TPwR91-6CHskktKjsnEJHjXltZoZUwf2T54,1109
62
+ teddy_executor/core/ports/outbound/config_service.py,sha256=zfrSM9sUMprBmGavcEsU2n040TS0Vv3zkQ2iOtEKyBI,777
63
+ teddy_executor/core/ports/outbound/environment_inspector.py,sha256=q9UGud-2IAu1esBI3P95_tduEu8EZ6a1TDh1JjKjfu0,822
64
+ teddy_executor/core/ports/outbound/execution_report_assembler.py,sha256=dKfnE5dvUy_tlpJOIti307KfQEa2FIByZqpYK6TmBPs,521
65
+ teddy_executor/core/ports/outbound/file_system_manager.py,sha256=r2HcbU5dFyas4y9pjPGRWWBNmQZvMDDLRqEFc8bVlz4,3674
66
+ teddy_executor/core/ports/outbound/llm_client.py,sha256=CD4ix9tw91NLffSGJsEyyiGSrrX-z8jOFps417c4aO0,2625
67
+ teddy_executor/core/ports/outbound/markdown_report_formatter.py,sha256=KPfNxO0-Nmpsd6GrZe17jMcc78ND6h87rOolBC5vtrE,708
68
+ teddy_executor/core/ports/outbound/prompt_manager.py,sha256=7aLP7vg0rPt_j7BUif9q9TD4nGQ1Oe83ulDDwIbfAhk,1572
69
+ teddy_executor/core/ports/outbound/repo_tree_generator.py,sha256=DqicSWf8fHlsGOagFMTgpqO3IIPq2-spYmzELSrovTY,387
70
+ teddy_executor/core/ports/outbound/session_loop_guard.py,sha256=0XtUCG0i05M7ZroNzr8dcM73cUdD4SqdDlaVwyDQHv0,412
71
+ teddy_executor/core/ports/outbound/session_manager.py,sha256=JQVlvh_jS8Ng1EP_JqB21ZZz67k_sa9aLaucGAVkqQ8,2894
72
+ teddy_executor/core/ports/outbound/session_repository.py,sha256=mv0WQ_l0BsjRRASdt5Zngjpm9g9lRcJ1eLoMrXCB0W8,2182
73
+ teddy_executor/core/ports/outbound/shell_executor.py,sha256=8PYG2GFC7Xph_RNH_IDNA8JtZF09TZZ0p9Rb2RoU77Y,629
74
+ teddy_executor/core/ports/outbound/system_environment.py,sha256=OACTKSr8_XLKcTtqUEFCrvMx2Hf9N8Xr0jIXfdgOyms,720
75
+ teddy_executor/core/ports/outbound/time_service.py,sha256=67gJ_HAclRoeDBAa2IFuznahd3DZ2cwVWidzeSGcSsk,651
76
+ teddy_executor/core/ports/outbound/user_interactor.py,sha256=sSIReHedwQQy7AQuVGD2A69d6_5CIzfi4ao6u5QHjkM,3556
77
+ teddy_executor/core/ports/outbound/web_scraper.py,sha256=PYjc2Pkvw89hEtfjwUcTJ1256Phok6xG6RhqyQvOy9Q,611
78
+ teddy_executor/core/ports/outbound/web_searcher.py,sha256=6S0h_PRn5VmRxbnpHmGVotHfFNuYsec-zcs9qlZSs-E,663
79
+ teddy_executor/core/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
+ teddy_executor/core/services/action_changeset_builder.py,sha256=HDbTANTVa-XugTQpMBgi4Q2be-WiXcm-oPUD7Nt13Cw,3092
81
+ teddy_executor/core/services/action_diff_manager.py,sha256=9i4N0vdbCAAvCEMzRUPN_mb73nXFbG7rhA_SQuUthk0,3702
82
+ teddy_executor/core/services/action_dispatcher.py,sha256=2nB8x3dkNO0g3iThEUL2DBYwdV-Zsaigo0FpBiU9CPU,4962
83
+ teddy_executor/core/services/action_executor.py,sha256=SZWX5LdERuI2fe5KkUnUm21LfzezkkibYQ50vRoemDs,8153
84
+ teddy_executor/core/services/action_factory.py,sha256=B_b64ZqjzeWOkQmg5_monlD9a5UrirwqxACOyTIqTZ0,8539
85
+ teddy_executor/core/services/action_parser_complex.py,sha256=k3cbYPqdnrCRGXHTH9hjpa6hgFkh4P88_7wOi9jW0z0,6795
86
+ teddy_executor/core/services/action_parser_strategies.py,sha256=4yzjmpN_Vj76ag9jz2ZkFTu7bWbssUFhrAGNmUwKtP8,2601
87
+ teddy_executor/core/services/context_service.py,sha256=2Y8IitrzoKG44xQqMQ6V_Ed4ejJaflGJmK9_uLm8jII,16706
88
+ teddy_executor/core/services/edit_simulator.py,sha256=5L-Ji3dPkiW7qea0f5LTqY92xa0blLrC2_paK_PvhTY,4861
89
+ teddy_executor/core/services/execution_orchestrator.py,sha256=JX_-AxhMbOYOOjoa28t8oK58ihzMOLvw1UwWwt5fpGE,11118
90
+ teddy_executor/core/services/execution_report_assembler.py,sha256=QuperPp8GjQyky6eMm2oS7qyJnDYJqMWBBi4XkUV2-k,2041
91
+ teddy_executor/core/services/init_service.py,sha256=L_tlL4TptDMMSTlXOKI1bUtT0mfOC7uYgIjwS4Wmb5s,3252
92
+ teddy_executor/core/services/markdown_plan_parser.py,sha256=Owj1GJccUCH6XfO4ry95IQSytGmLFFyOTqXjpQuVjAo,11850
93
+ teddy_executor/core/services/markdown_report_formatter.py,sha256=xQRg_tkIRKVXUzmjcvkjYz3A-v4ecj9VfHaLRHDjIjw,5244
94
+ teddy_executor/core/services/parser_infrastructure.py,sha256=_2OwbA8KzLZ_3qaz-PG0NxVv-Xx_qbFooQtkqJClHDY,7461
95
+ teddy_executor/core/services/parser_metadata.py,sha256=KZY0nPz3NGogzY4ZfBQV9a-R0cwqoG3U3kdXaqpdXf0,5335
96
+ teddy_executor/core/services/parser_reporting.py,sha256=3Mw9mJdlaccdXOKZwgh98XdWLzTDZy91D50k2V6fgXo,9478
97
+ teddy_executor/core/services/plan_validator.py,sha256=fHCuMo3ETkJgP5Nbcy0JuFGucUyk5Pgo-GoQB7XPiT0,2906
98
+ teddy_executor/core/services/planning_service.py,sha256=QCIJ1z4gWtViwFgS9zCItrOhzzlimX0qBSxXfGUdEfM,9593
99
+ teddy_executor/core/services/prompt_manager.py,sha256=_PBL6lmeyi3DlMaw158mqRZRCmEbKP4-zrwsVefvJ4c,5905
100
+ teddy_executor/core/services/session_lifecycle_manager.py,sha256=XqmjSS64bFrMXTZEuZp8r6RDLGFYglk5ildLp3KL_kc,8822
101
+ teddy_executor/core/services/session_loop_guard.py,sha256=6RUg2Nb7rjf6VSybouyWc_qbKQ0n-JDAGrm-zd7_6Eg,1354
102
+ teddy_executor/core/services/session_orchestrator.py,sha256=saDgG4veoNYHYinAkGtCTKOdaXG8nISKQ4DGRa2UBVo,20595
103
+ teddy_executor/core/services/session_planner.py,sha256=8zGmkAXHeblpX6WxJybB2_RKXMw0-2pKtrL7aNv0fIs,1420
104
+ teddy_executor/core/services/session_pruning_service.py,sha256=K-9SWr8urQE62XrrbnK4V14ylRIPxrCLGHnNYf6nu8c,16056
105
+ teddy_executor/core/services/session_replanner.py,sha256=HzXQz64RtXucB2tH8JbF6HPGGlAIMOnahcnLlAdG8Cs,3651
106
+ teddy_executor/core/services/session_repository.py,sha256=csKYPelvaZlehI54TZdfUE7SCq000EQ6M8U6VbiZ6Ss,7966
107
+ teddy_executor/core/services/session_service.py,sha256=I-I7lwmcSmrvp6U7RxzmDlcVG8N233ZjhPXYHVWGr8Q,21724
108
+ teddy_executor/core/services/templates/execution_report.md.j2,sha256=7sTvelTNwXmEx245gu33f5LsRrcbLPvzSNnf9qCMjGo,10706
109
+ teddy_executor/core/services/validation_rules/__init__.py,sha256=Pe0dCWgssakypne3Yi0R1UK_T7gn6WZjjAk7YHcLUT8,128
110
+ teddy_executor/core/services/validation_rules/edit.py,sha256=ab4RCrfr9PswBSwy9pAuA2MJO5W85VqeuJWAhd6mbzM,7536
111
+ teddy_executor/core/services/validation_rules/edit_matcher.py,sha256=3bTbpnd76ot1YjbHmGGbut1nlug6JCoYjdXNvPsHp_0,8509
112
+ teddy_executor/core/services/validation_rules/edit_matcher_heuristics.py,sha256=5rQ4B2Er0fR3DkdJEn5bjChUHaikIZ3oNlNgdtYGVPw,3007
113
+ teddy_executor/core/services/validation_rules/execute.py,sha256=EPCqsL-tWIC9VGezAxq-L52Nq1Mdi12CyeKM2n054sM,1023
114
+ teddy_executor/core/services/validation_rules/filesystem.py,sha256=lak5wr15Lox5DMznzkZ3ePKd7UszHwf5b_gEMe54BOI,2428
115
+ teddy_executor/core/services/validation_rules/helpers.py,sha256=RaL0_fIqxXWPNZYAqP2bq53wo9hVRoQ8Gs1rfMxy0dw,5889
116
+ teddy_executor/core/services/validation_rules/message.py,sha256=PiPpW5l9QDc_ojNxB98DKRvs4H9C9tht_uVo3iSWdik,838
117
+ teddy_executor/core/utils/__init__.py,sha256=4BK6udEIDfmM0CaTGO6kKHr1LbLChRfblcqBt44mekc,22
118
+ teddy_executor/core/utils/diff.py,sha256=7hhLIvETTbGJddNB7yx_12S0IJDekc6OzzfUesJRG4A,1786
119
+ teddy_executor/core/utils/io.py,sha256=XsmNajZ_Z30xbtArFlceMhggNQi8tH0nuw1dR4NeKdc,2502
120
+ teddy_executor/core/utils/markdown.py,sha256=kVa4SuP3x7ofESnPvAXPwlJf79C0k1LpDgnuwEJPMDI,3864
121
+ teddy_executor/core/utils/serialization.py,sha256=V_1jyPeRm670HlbIKhrW8LP1s6O4UCc8xo0kmky9EDs,1237
122
+ teddy_executor/core/utils/string.py,sha256=zYKR6XCipHsIXn15rTz9XR5CMwy02fcEXBcYQqQIFUo,7769
123
+ teddy_executor/prompts.py,sha256=dT5dJLt8Mp1h1XYo023C1kxMnUjWKSfdBSIT2BRBwvk,1749
124
+ teddy_executor/registries/__init__.py,sha256=Y9luGTza-JjAZCHGX7VJpyj55ijfrSJFrwYKgk0iwkE,52
125
+ teddy_executor/registries/infrastructure.py,sha256=-ViJA0UnvbSMrlvlaGkNi1pBk_wNc5u66jC6e2XQ91A,4875
126
+ teddy_executor/registries/reviewer.py,sha256=7LAqZ6wAqTpp4n1jOIfcwRa8MKueLJa9S_J2nrsGIC4,2200
127
+ teddy_executor/registries/validators.py,sha256=82SNpawuzWV2dtJcMAVP7wOpjoJ0hViR2a3kOwgIyIA,1907
128
+ teddy_executor/resources/__init__.py,sha256=h835ykuoc9Xv0E4UIaHmi8iVnhPKYqhwkLzHV5jRQEs,45
129
+ teddy_executor/resources/config/.gitignore,sha256=X8MZtMI-F4Ca0w-t5yVZ0UluMDow8tculFbbyZ4VDAk,57
130
+ teddy_executor/resources/config/__init__.py,sha256=R96a_JS3GOty_5vsGg8AcR3cQYotYXCELrIzWFhn4kE,61
131
+ teddy_executor/resources/config/config.yaml,sha256=aBwmlmq8Jfd9tcLptneLNtWD3SRlh2vMfgxY51vIcl4,1895
132
+ teddy_executor/resources/config/init.context,sha256=9J70exhvHAzqHX8kin2PuVtPi2JZp-TAzZr-PV8EYSg,87
133
+ teddy_executor/resources/config/prompts/architect.xml,sha256=hIPXgB4_Sd9HoXYn9xm9Slm6yG4q2567aqa3RBhMLvc,32574
134
+ teddy_executor/resources/config/prompts/assistant.xml,sha256=YkJ2zKI730ow4dze-ryi-SGn3lLSUCNlLMOslJRDWwM,20670
135
+ teddy_executor/resources/config/prompts/debugger.xml,sha256=Bwmwuc4jZ9H-474Q7V_onCcisYr__fLhGlNaesqrEPk,36369
136
+ teddy_executor/resources/config/prompts/developer.xml,sha256=hoQlHNSkNlr0HGHUbF8px_VnzsoKTkOuhE0KqI-uRk4,35366
137
+ teddy_executor/resources/config/prompts/pathfinder.xml,sha256=DMCJ0KuIAMy9f98dbCcft82qmGKSrin06VF_8EnEGC4,35603
138
+ teddy_executor/resources/config/prompts/prototyper.xml,sha256=YUKRaSUAkDxd_fQN_OWqEDWtKrNFyW_rOTXLhWntUYc,32900
139
+ teddy_cli-0.1.0.dist-info/LICENSE,sha256=HBL2C3ynq_mk-EYtJI7aXEc6gXnXgKJ-K6KZ13N0Ojs,35270
140
+ teddy_cli-0.1.0.dist-info/METADATA,sha256=CDKuOCsyzq5vz7MZpvFwt1bV8eXjU58UkYfEBSMgunc,1308
141
+ teddy_cli-0.1.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
142
+ teddy_cli-0.1.0.dist-info/entry_points.txt,sha256=M-SJf8_LfQpBkkx0RAk8jLEbz-lShhh-48vqMQXpK1k,53
143
+ teddy_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ teddy=teddy_executor.__main__:app
3
+
@@ -0,0 +1 @@
1
+ # This file makes the 'teddy' directory a Python package.
@@ -0,0 +1,335 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ import sys
5
+ from datetime import datetime, timezone
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING, Optional
8
+
9
+ import typer
10
+
11
+ from teddy_executor.core.domain.models import (
12
+ ExecutionReport,
13
+ )
14
+
15
+ if TYPE_CHECKING:
16
+ from teddy_executor.core.ports.inbound.plan_parser import IPlanParser
17
+
18
+
19
+ app = typer.Typer()
20
+
21
+
22
+ def get_container():
23
+ from teddy_executor.container import get_container as _get_container
24
+
25
+ return _get_container()
26
+
27
+
28
+ def _apply_ui_mode_override(container, ui_mode_bool: bool) -> None:
29
+ from teddy_executor.container import register_reviewer
30
+
31
+ mode = "tui" if ui_mode_bool else "console"
32
+ register_reviewer(container, ui_mode=mode)
33
+
34
+
35
+ logging.basicConfig(
36
+ level=logging.INFO,
37
+ format="%(message)s",
38
+ handlers=[logging.StreamHandler(sys.stderr)],
39
+ force=True,
40
+ )
41
+
42
+
43
+ def _ensure_project_initialized(container) -> None:
44
+ """Lazily performs project anchoring and initialization."""
45
+ from teddy_executor.adapters.inbound.cli_helpers import find_project_root
46
+ from teddy_executor.core.ports.outbound.file_system_manager import (
47
+ IFileSystemManager,
48
+ )
49
+ from teddy_executor.core.ports.outbound.repo_tree_generator import (
50
+ IRepoTreeGenerator,
51
+ )
52
+ from teddy_executor.adapters.outbound.local_file_system_adapter import (
53
+ LocalFileSystemAdapter,
54
+ )
55
+ from teddy_executor.adapters.outbound.local_repo_tree_generator import (
56
+ LocalRepoTreeGenerator,
57
+ )
58
+ from teddy_executor.core.ports.inbound.init import IInitUseCase
59
+ from teddy_executor.core.ports.outbound.config_service import IConfigService
60
+ from teddy_executor.adapters.outbound.yaml_config_adapter import YamlConfigAdapter
61
+ from punq import Scope
62
+
63
+ root = str(find_project_root())
64
+ c = container
65
+
66
+ regs = getattr(c.registrations, "_Registry__registrations", {})
67
+
68
+ def is_override(service_type) -> bool:
69
+ reg_list = regs.get(service_type)
70
+ return any(
71
+ reg.scope == Scope.singleton or hasattr(reg, "instance")
72
+ for reg in (reg_list or [])
73
+ )
74
+
75
+ if not is_override(IFileSystemManager):
76
+ c.register(IFileSystemManager, LocalFileSystemAdapter, root_dir=root)
77
+ if not is_override(IRepoTreeGenerator):
78
+ c.register(IRepoTreeGenerator, LocalRepoTreeGenerator, root_dir=root)
79
+ if not is_override(IConfigService):
80
+ c.register(IConfigService, YamlConfigAdapter, root_dir=root)
81
+
82
+ c.resolve(IInitUseCase).ensure_initialized()
83
+
84
+
85
+ # Shared Typer options to reduce duplication for jscpd
86
+ OPT_NO_COPY = typer.Option(
87
+ False, "--no-copy", help="Do not copy the output to the clipboard."
88
+ )
89
+ OPT_UI_MODE = typer.Option(
90
+ None, "--tui/--console", help="Force TUI or Console mode.", show_default=False
91
+ )
92
+
93
+
94
+ @app.command()
95
+ def start( # noqa: PLR0913
96
+ name: Optional[str] = typer.Argument(None, help="The name of the new session."),
97
+ agent: str = typer.Option(
98
+ "pathfinder", "--agent", "-a", help="Agent prompt to use."
99
+ ),
100
+ yolo: bool = typer.Option(
101
+ False, "--yolo", "-y", help="Auto-approve all actions (non-interactive mode)."
102
+ ),
103
+ yes: bool = typer.Option(False, "--yes", hidden=True),
104
+ no_interactive: bool = typer.Option(False, "--no-interactive", hidden=True),
105
+ non_interactive: bool = typer.Option(False, "--non-interactive", hidden=True),
106
+ no_copy: bool = OPT_NO_COPY,
107
+ ui_mode: Optional[bool] = OPT_UI_MODE,
108
+ message: Optional[str] = typer.Option(
109
+ None, "-m", "--message", help="Instruction for the first turn."
110
+ ),
111
+ context: Optional[str] = typer.Option(
112
+ None,
113
+ "--context",
114
+ "-c",
115
+ help="Comma-separated list of additional files/dirs for context.",
116
+ ),
117
+ model: Optional[str] = typer.Option(None, "--model", help="LLM model override."),
118
+ provider: Optional[str] = typer.Option(
119
+ None, "--provider", help="LLM provider override."
120
+ ),
121
+ api_key: Optional[str] = typer.Option(
122
+ None, "--api-key", help="LLM API key override."
123
+ ),
124
+ ):
125
+ """
126
+ Initializes a new session directory and bootstraps it for Turn 1.
127
+ """
128
+ from teddy_executor.adapters.inbound.session_cli_handlers import handle_new_session
129
+
130
+ container = get_container()
131
+ _ensure_project_initialized(container)
132
+ if ui_mode is not None:
133
+ _apply_ui_mode_override(container, ui_mode)
134
+
135
+ additional_context = context.split(",") if context else None
136
+
137
+ handle_new_session(
138
+ container=container,
139
+ name=name,
140
+ agent=agent,
141
+ interactive=not (yolo or yes or no_interactive or non_interactive),
142
+ no_copy=no_copy,
143
+ message=message,
144
+ additional_context=additional_context,
145
+ model=model,
146
+ provider=provider,
147
+ api_key=api_key,
148
+ )
149
+
150
+
151
+ @app.command()
152
+ def init():
153
+ """
154
+ Initializes the .teddy directory and pre-warms heavy imports for faster startup.
155
+ """
156
+ container = get_container()
157
+ _ensure_project_initialized(container)
158
+ # Pre-warm heavy imports to reduce first-run latency
159
+ try:
160
+ import litellm # noqa: F401
161
+ import trafilatura # noqa: F401
162
+ import pyperclip # noqa: F401
163
+ from bs4 import BeautifulSoup # noqa: F401
164
+ from ddgs import DDGS # noqa: F401
165
+ except ImportError:
166
+ pass # Some optional dependencies may not be installed
167
+ # Auto-login would trigger here once `teddy login` is implemented (no-op for now)
168
+ typer.echo("TeDDy initialized in .teddy folder.")
169
+
170
+
171
+ @app.command()
172
+ def context(
173
+ no_copy: bool = typer.Option(
174
+ False,
175
+ "--no-copy",
176
+ help="Do not copy the output to the clipboard.",
177
+ ),
178
+ ):
179
+ """
180
+ Gathers and displays project context (file tree + file contents).
181
+
182
+ All operations respect the project's root-relative path conventions.
183
+ """
184
+ from teddy_executor.adapters.inbound.session_cli_handlers import (
185
+ handle_context_gathering,
186
+ )
187
+
188
+ container = get_container()
189
+ _ensure_project_initialized(container)
190
+ handle_context_gathering(container, no_copy)
191
+
192
+
193
+ @app.command(name="get-prompt")
194
+ def get_prompt(
195
+ prompt_name: str = typer.Argument(..., help="The name of the prompt to retrieve."),
196
+ no_copy: bool = typer.Option(
197
+ False, "--no-copy", help="Do not copy the output to the clipboard."
198
+ ),
199
+ ):
200
+ """
201
+ Retrieves and displays the content of a specified prompt.
202
+
203
+ Searches for root-relative overrides in ./.teddy/prompts/ before falling back to defaults.
204
+ """
205
+ from teddy_executor.adapters.inbound.cli_helpers import echo_and_copy
206
+ from teddy_executor.prompts import find_prompt_content, list_prompt_names
207
+
208
+ prompt_content = find_prompt_content(prompt_name)
209
+
210
+ if prompt_content:
211
+ echo_and_copy(prompt_content, no_copy)
212
+ else:
213
+ available = list_prompt_names()
214
+ if available:
215
+ msg = f"Error: Prompt '{prompt_name}' not found. Available prompts: {', '.join(available)}"
216
+ else:
217
+ msg = f"Error: Prompt '{prompt_name}' not found."
218
+ typer.echo(msg, err=True)
219
+ raise typer.Exit(code=1)
220
+
221
+
222
+ def create_parser_for_plan(plan_content: str) -> IPlanParser:
223
+ """
224
+ Factory function to determine which plan parser to use.
225
+ """
226
+ # Legacy YAML plans are deprecated. Only Markdown is supported.
227
+ return get_container().resolve(IPlanParser)
228
+
229
+
230
+ @app.command()
231
+ def resume( # noqa: PLR0913
232
+ path: Optional[str] = typer.Argument(None, help="Path to session or turn."),
233
+ yolo: bool = typer.Option(
234
+ False, "--yolo", "-y", help="Auto-approve all actions (non-interactive mode)."
235
+ ),
236
+ yes: bool = typer.Option(False, "--yes", hidden=True),
237
+ no_interactive: bool = typer.Option(False, "--no-interactive", hidden=True),
238
+ non_interactive: bool = typer.Option(False, "--non-interactive", hidden=True),
239
+ no_copy: bool = OPT_NO_COPY,
240
+ ui_mode: Optional[bool] = OPT_UI_MODE,
241
+ model: Optional[str] = typer.Option(None, "--model", help="LLM model override."),
242
+ provider: Optional[str] = typer.Option(
243
+ None, "--provider", help="LLM provider override."
244
+ ),
245
+ api_key: Optional[str] = typer.Option(
246
+ None, "--api-key", help="LLM API key override."
247
+ ),
248
+ ):
249
+ """
250
+ Intelligently resumes the last turn of a session or starts a new one.
251
+ """
252
+ from teddy_executor.adapters.inbound.cli_helpers import apply_ui_mode_override
253
+ from teddy_executor.adapters.inbound.session_cli_handlers import (
254
+ handle_resume_session,
255
+ )
256
+
257
+ container = get_container()
258
+ _ensure_project_initialized(container)
259
+ if ui_mode is not None:
260
+ apply_ui_mode_override(container, ui_mode)
261
+
262
+ handle_resume_session(
263
+ container=container,
264
+ path=path,
265
+ interactive=not (yolo or yes or no_interactive or non_interactive),
266
+ no_copy=no_copy,
267
+ model=model,
268
+ provider=provider,
269
+ api_key=api_key,
270
+ )
271
+
272
+
273
+ @app.command()
274
+ def execute( # noqa: PLR0913
275
+ plan_file: Optional[Path] = typer.Argument(
276
+ None, help="Root-relative path to the plan file (.md).", show_default=False
277
+ ),
278
+ yolo: bool = typer.Option(
279
+ False, "--yolo", "-y", help="Auto-approve all actions (non-interactive mode)."
280
+ ),
281
+ yes: bool = typer.Option(False, "--yes", hidden=True),
282
+ no_interactive: bool = typer.Option(False, "--no-interactive", hidden=True),
283
+ non_interactive: bool = typer.Option(False, "--non-interactive", hidden=True),
284
+ no_copy: bool = OPT_NO_COPY,
285
+ plan_content: Optional[str] = typer.Option(
286
+ None, "--plan-content", help="Plan content.", show_default=False
287
+ ),
288
+ ui_mode: Optional[bool] = OPT_UI_MODE,
289
+ message: Optional[str] = typer.Option(
290
+ None, "-m", "--message", help="Optional instruction for the report."
291
+ ),
292
+ ):
293
+ """
294
+ Executes a Markdown plan file (from path or clipboard) and generates an execution report.
295
+ """
296
+ from teddy_executor.adapters.inbound.cli_helpers import (
297
+ apply_ui_mode_override,
298
+ get_plan_content,
299
+ handle_report_output,
300
+ )
301
+ from teddy_executor.core.ports.inbound.plan_parser import InvalidPlanError
302
+ from teddy_executor.core.ports.inbound.run_plan_use_case import IRunPlanUseCase
303
+
304
+ report: Optional[ExecutionReport] = None
305
+ interactive_mode = not (yolo or yes or no_interactive or non_interactive)
306
+ start_time = datetime.now(timezone.utc)
307
+
308
+ container = get_container()
309
+ _ensure_project_initialized(container)
310
+ if ui_mode is not None:
311
+ apply_ui_mode_override(container, ui_mode)
312
+
313
+ try:
314
+ final_plan_content = get_plan_content(plan_content, plan_file)
315
+ orchestrator = container.resolve(IRunPlanUseCase)
316
+
317
+ report = orchestrator.execute(
318
+ plan_content=final_plan_content,
319
+ plan_path=str(plan_file) if plan_file else None,
320
+ interactive=interactive_mode,
321
+ message=message,
322
+ )
323
+
324
+ except (InvalidPlanError, NotImplementedError) as e:
325
+ from teddy_executor.adapters.inbound.cli_helpers import create_failure_report
326
+
327
+ report = create_failure_report(
328
+ e, start_time, container, plan_content=final_plan_content
329
+ )
330
+
331
+ handle_report_output(container, report, no_copy)
332
+
333
+
334
+ if __name__ == "__main__":
335
+ app()
File without changes
File without changes
@@ -0,0 +1,107 @@
1
+ import difflib
2
+ from typing import List, Optional
3
+
4
+ import typer
5
+
6
+ from teddy_executor.core.domain.models import (
7
+ ActionData,
8
+ ChangeSet,
9
+ Plan,
10
+ ProjectContext,
11
+ )
12
+
13
+
14
+ def format_project_context(context: ProjectContext) -> str:
15
+ """
16
+ Formats the ProjectContext DTO into a single string for display.
17
+ The actual formatting is now done in the ContextService. This function
18
+ simply combines the pre-formatted parts.
19
+ """
20
+ return f"{context.header}\n{context.content}"
21
+
22
+
23
+ def echo_handoff_details(
24
+ action_type: str,
25
+ target_agent: Optional[str],
26
+ resources: List[str],
27
+ message: str,
28
+ ):
29
+ """Prints formatted handoff details to the terminal."""
30
+ if action_type == "INVOKE":
31
+ typer.secho("--- HANDOFF REQUEST ---", fg=typer.colors.CYAN, err=True)
32
+ typer.echo(
33
+ "The current agent is requesting a handoff to the agent below.\n",
34
+ err=True,
35
+ )
36
+ if target_agent:
37
+ typer.echo(f"▶ Target Agent: {target_agent}", err=True)
38
+ typer.echo(f"▶ Handoff Message:\n{message}\n", err=True)
39
+ else: # RETURN
40
+ typer.secho("--- HANDOFF NOTIFICATION ---", fg=typer.colors.CYAN, err=True)
41
+ typer.echo(
42
+ "The current agent has completed its task and is returning control.\n",
43
+ err=True,
44
+ )
45
+ typer.echo(f"▶ Return Message:\n{message}\n", err=True)
46
+
47
+ if resources:
48
+ typer.echo("▶ Reference Files:", err=True)
49
+ typer.echo("\n".join(resources), err=True)
50
+ typer.echo("", err=True)
51
+
52
+
53
+ def echo_diff_preview(change_set: ChangeSet):
54
+ """Prints a terminal-formatted diff or file preview."""
55
+ if change_set.action_type == "CREATE":
56
+ typer.echo("--- New File Preview ---", err=True)
57
+ typer.echo(f"Path: {change_set.path}", err=True)
58
+ typer.echo("Content:", err=True)
59
+ typer.echo(change_set.after_content, err=True)
60
+ typer.echo("------------------------", err=True)
61
+ return
62
+
63
+ diff_generator = difflib.unified_diff(
64
+ change_set.before_content.splitlines(keepends=True),
65
+ change_set.after_content.splitlines(keepends=True),
66
+ fromfile=f"a/{change_set.path.name}",
67
+ tofile=f"b/{change_set.path.name}",
68
+ )
69
+
70
+ diff_lines = []
71
+ for line in diff_generator:
72
+ diff_lines.append(line)
73
+ if not line.endswith("\n"):
74
+ diff_lines.append("\n")
75
+
76
+ typer.echo("--- Diff ---", err=True)
77
+ typer.echo("".join(diff_lines).rstrip(), err=True)
78
+ typer.echo("------------", err=True)
79
+
80
+
81
+ def echo_plan_summary(plan: Plan):
82
+ """Prints a summary of the plan's actions to the terminal."""
83
+ header = f'\n▶ Reviewing Plan: "{plan.title}"'
84
+ typer.secho(header, fg=typer.colors.CYAN, bold=True, err=True)
85
+ typer.echo("-" * 68, err=True)
86
+
87
+ counts: dict[str, int] = {}
88
+ for action in plan.actions:
89
+ counts[action.type] = counts.get(action.type, 0) + 1
90
+
91
+ typer.echo("\n Action Plan:", err=True)
92
+ for action_type in sorted(counts.keys()):
93
+ count = counts[action_type]
94
+ label = "action" if count == 1 else "actions"
95
+ typer.echo(f" - {action_type}: {count} {label}", err=True)
96
+ typer.echo("\n" + "-" * 68, err=True)
97
+
98
+
99
+ def echo_skipped_action(action: ActionData, reason: str):
100
+ """Prints a colorized skip notification."""
101
+ message = f"[SKIPPED] {action.type}: {reason}"
102
+ typer.secho(message, fg=typer.colors.YELLOW, err=True)
103
+
104
+
105
+ def style_text(text: str, style: str) -> str:
106
+ """Wraps text in Rich style tags."""
107
+ return f"[{style}]{text}[/]"