teddy-cli 0.1.4__tar.gz → 0.1.6__tar.gz
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.4 → teddy_cli-0.1.6}/PKG-INFO +2 -1
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/pyproject.toml +2 -1
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/__main__.py +119 -16
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/cli_helpers.py +15 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/session_cli_handlers.py +149 -2
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_execution.py +3 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/system_environment_inspector.py +17 -1
- teddy_cli-0.1.6/src/teddy_executor/core/ports/inbound/init.py +47 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/environment_inspector.py +10 -1
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/context_service.py +7 -10
- teddy_cli-0.1.6/src/teddy_executor/core/services/init_service.py +138 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/markdown_plan_parser.py +5 -3
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/parser_infrastructure.py +3 -1
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/parser_metadata.py +76 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/planning_service.py +1 -0
- teddy_cli-0.1.6/src/teddy_executor/core/services/update_checker.py +212 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/validation_rules/helpers.py +1 -1
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/config.yaml +0 -4
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/prompts/architect.xml +23 -8
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/prompts/debugger.xml +4 -4
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/prompts/developer.xml +9 -6
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/prompts/pathfinder.xml +5 -5
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/prompts/prototyper.xml +23 -18
- teddy_cli-0.1.4/src/teddy_executor/core/ports/inbound/init.py +0 -15
- teddy_cli-0.1.4/src/teddy_executor/core/services/init_service.py +0 -80
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/LICENSE +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/cli_formatter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/console_plan_reviewer.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/textual_plan_reviewer.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_app.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_editor.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_helpers.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_logic.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_previews.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/textual_plan_reviewer_widgets.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/console_interactor.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/console_interactor_ask_loop.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/console_interactor_helpers.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/console_tooling.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/filesystem_helpers.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/litellm_adapter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/local_file_system_adapter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/local_repo_tree_generator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/openrouter_hydrator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/shell_adapter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/shell_command_builder.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/system_environment_adapter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/system_time_adapter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/web_scraper_adapter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/web_searcher_adapter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/outbound/yaml_config_adapter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/container.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/action_ports.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/change_set.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/exceptions.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/execution_report.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/orchestrator_ports.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/plan.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/planning_ports.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/project_context.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/report_assembly_data.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/session.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/shell_output.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/domain/models/web_search_results.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/inbound/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/inbound/edit_simulator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/inbound/get_context_use_case.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/inbound/plan_parser.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/inbound/plan_reviewer.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/inbound/plan_validator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/inbound/planning_use_case.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/inbound/run_plan_use_case.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/config_service.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/execution_report_assembler.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/file_system_manager.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/llm_client.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/markdown_report_formatter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/prompt_manager.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/repo_tree_generator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/session_loop_guard.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/session_manager.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/session_repository.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/shell_executor.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/system_environment.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/time_service.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/user_interactor.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/web_scraper.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/web_searcher.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/action_changeset_builder.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/action_diff_manager.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/action_dispatcher.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/action_executor.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/action_factory.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/action_parser_complex.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/action_parser_strategies.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/edit_simulator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/execution_orchestrator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/execution_report_assembler.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/markdown_report_formatter.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/parser_reporting.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/plan_validator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/prompt_manager.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/session_lifecycle_manager.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/session_loop_guard.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/session_orchestrator.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/session_planner.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/session_pruning_service.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/session_replanner.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/session_repository.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/session_service.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/templates/execution_report.md.j2 +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/validation_rules/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/validation_rules/edit.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/validation_rules/edit_matcher.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/validation_rules/edit_matcher_heuristics.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/validation_rules/execute.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/validation_rules/filesystem.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/services/validation_rules/message.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/utils/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/utils/diff.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/utils/io.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/utils/markdown.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/utils/serialization.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/utils/string.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/prompts.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/registries/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/registries/infrastructure.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/registries/reviewer.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/registries/validators.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/.gitignore +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/__init__.py +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/init.context +0 -0
- {teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/resources/config/prompts/assistant.xml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: teddy-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: A local-first, file-based AI coding workflow that applies the UNIX philosophy to AI collaboration.
|
|
5
5
|
License: AGPL-3.0-only
|
|
6
6
|
License-File: LICENSE
|
|
@@ -30,6 +30,7 @@ Requires-Dist: python-dotenv (>=1.0.1)
|
|
|
30
30
|
Requires-Dist: pyyaml (>=6.0,<7.0)
|
|
31
31
|
Requires-Dist: requests (>=2.33.0,<3.0.0)
|
|
32
32
|
Requires-Dist: textual (>=8.1.0,<9.0.0)
|
|
33
|
+
Requires-Dist: tld (>=0.10,<1.0)
|
|
33
34
|
Requires-Dist: trafilatura (>=2.0.0,<3.0.0)
|
|
34
35
|
Requires-Dist: typer[all]
|
|
35
36
|
Requires-Dist: urllib3 (>=2.7.0,<3.0.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "teddy-cli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.6"
|
|
4
4
|
description = "A local-first, file-based AI coding workflow that applies the UNIX philosophy to AI collaboration."
|
|
5
5
|
authors = ["Raphael Atteritano"]
|
|
6
6
|
license = "AGPL-3.0-only"
|
|
@@ -29,6 +29,7 @@ bandit = ">=1.7.9,<1.8.0"
|
|
|
29
29
|
pip-audit = ">=2.7.3,<2.8.0"
|
|
30
30
|
textual = "^8.1.0"
|
|
31
31
|
urllib3 = "^2.7.0"
|
|
32
|
+
tld = ">=0.10,<1.0"
|
|
32
33
|
|
|
33
34
|
[tool.poetry.group.dev.dependencies]
|
|
34
35
|
pytest = "^9.0.3"
|
|
@@ -57,8 +57,12 @@ logging.basicConfig(
|
|
|
57
57
|
)
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def _ensure_project_initialized(container) -> None:
|
|
61
|
-
"""Lazily performs project anchoring and initialization.
|
|
60
|
+
def _ensure_project_initialized(container, root_dir: str | None = None) -> None:
|
|
61
|
+
"""Lazily performs project anchoring and initialization.
|
|
62
|
+
|
|
63
|
+
If root_dir is provided, uses that path as the root. Otherwise, finds
|
|
64
|
+
the nearest parent containing .teddy/ via find_project_root().
|
|
65
|
+
"""
|
|
62
66
|
from teddy_executor.adapters.inbound.cli_helpers import find_project_root
|
|
63
67
|
from teddy_executor.core.ports.outbound.file_system_manager import (
|
|
64
68
|
IFileSystemManager,
|
|
@@ -77,7 +81,10 @@ def _ensure_project_initialized(container) -> None:
|
|
|
77
81
|
from teddy_executor.adapters.outbound.yaml_config_adapter import YamlConfigAdapter
|
|
78
82
|
from punq import Scope
|
|
79
83
|
|
|
80
|
-
|
|
84
|
+
if root_dir is None:
|
|
85
|
+
root = str(find_project_root())
|
|
86
|
+
else:
|
|
87
|
+
root = root_dir
|
|
81
88
|
c = container
|
|
82
89
|
|
|
83
90
|
regs = getattr(c.registrations, "_Registry__registrations", {})
|
|
@@ -165,24 +172,61 @@ def start( # noqa: PLR0913
|
|
|
165
172
|
)
|
|
166
173
|
|
|
167
174
|
|
|
168
|
-
|
|
169
|
-
|
|
175
|
+
init_app = typer.Typer()
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@init_app.callback(invoke_without_command=True)
|
|
179
|
+
def init_callback(ctx: typer.Context):
|
|
170
180
|
"""
|
|
171
181
|
Initializes the .teddy directory and pre-warms heavy imports for faster startup.
|
|
172
182
|
"""
|
|
183
|
+
from teddy_executor.adapters.inbound.cli_helpers import prewarm_imports
|
|
184
|
+
from teddy_executor.core.ports.inbound.init import IInitUseCase
|
|
185
|
+
|
|
173
186
|
container = get_container()
|
|
174
|
-
_ensure_project_initialized(container)
|
|
175
|
-
|
|
176
|
-
try:
|
|
177
|
-
import litellm # noqa: F401
|
|
178
|
-
import trafilatura # noqa: F401
|
|
179
|
-
import pyperclip # noqa: F401
|
|
180
|
-
from bs4 import BeautifulSoup # noqa: F401
|
|
181
|
-
from ddgs import DDGS # noqa: F401
|
|
182
|
-
except ImportError:
|
|
183
|
-
pass # Some optional dependencies may not be installed
|
|
187
|
+
_ensure_project_initialized(container, root_dir=str(Path.cwd()))
|
|
188
|
+
prewarm_imports()
|
|
184
189
|
# Auto-login would trigger here once `teddy login` is implemented (no-op for now)
|
|
185
|
-
|
|
190
|
+
if ctx.invoked_subcommand is not None:
|
|
191
|
+
# A subcommand (e.g., prompts, config) will handle its own initialization
|
|
192
|
+
# and output. Skip the full summary to avoid conflicting messages.
|
|
193
|
+
return
|
|
194
|
+
init_use_case = container.resolve(IInitUseCase)
|
|
195
|
+
summary = init_use_case.ensure_initialized()
|
|
196
|
+
typer.echo(f"TeDDy initialized in .teddy folder. {summary}")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@init_app.command()
|
|
200
|
+
def prompts():
|
|
201
|
+
"""
|
|
202
|
+
Overwrites bundled prompt XMLs in .teddy/prompts/ with defaults.
|
|
203
|
+
"""
|
|
204
|
+
from teddy_executor.core.ports.inbound.init import IInitUseCase
|
|
205
|
+
|
|
206
|
+
container = get_container()
|
|
207
|
+
init_use_case = container.resolve(IInitUseCase)
|
|
208
|
+
status = init_use_case.ensure_prompts_initialized(overwrite=True)
|
|
209
|
+
typer.echo(status)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@init_app.command()
|
|
213
|
+
def config():
|
|
214
|
+
"""
|
|
215
|
+
Overwrites config.yaml, .gitignore, and init.context with defaults.
|
|
216
|
+
"""
|
|
217
|
+
from teddy_executor.core.ports.inbound.init import IInitUseCase
|
|
218
|
+
|
|
219
|
+
container = get_container()
|
|
220
|
+
init_use_case = container.resolve(IInitUseCase)
|
|
221
|
+
status = init_use_case.ensure_config_initialized(overwrite=True)
|
|
222
|
+
typer.echo(status)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
app.add_typer(
|
|
226
|
+
init_app,
|
|
227
|
+
name="init",
|
|
228
|
+
help="Initialize .teddy directory, prompts, or configuration.",
|
|
229
|
+
)
|
|
186
230
|
|
|
187
231
|
|
|
188
232
|
@app.command()
|
|
@@ -194,6 +238,65 @@ def version() -> None:
|
|
|
194
238
|
typer.echo(f"TeDDy v{installed}")
|
|
195
239
|
|
|
196
240
|
|
|
241
|
+
@app.command()
|
|
242
|
+
def update(
|
|
243
|
+
experimental: bool = typer.Option(
|
|
244
|
+
False,
|
|
245
|
+
"--experimental",
|
|
246
|
+
help="Check and upgrade from TestPyPI instead of PyPI.",
|
|
247
|
+
),
|
|
248
|
+
):
|
|
249
|
+
"""Checks PyPI for the latest version of TeDDy and displays upgrade
|
|
250
|
+
instructions. Does not upgrade automatically."""
|
|
251
|
+
from teddy_executor.core.services.update_checker import (
|
|
252
|
+
get_current_version,
|
|
253
|
+
fetch_latest_version,
|
|
254
|
+
compare_versions,
|
|
255
|
+
is_prerelease,
|
|
256
|
+
PYPI_URL,
|
|
257
|
+
TEST_PYPI_URL,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
index_url = TEST_PYPI_URL if experimental else PYPI_URL
|
|
261
|
+
# When experimental, include prerelease versions (TestPyPI only has dev releases)
|
|
262
|
+
latest = fetch_latest_version(index_url, stable_only=not experimental)
|
|
263
|
+
|
|
264
|
+
if latest is None:
|
|
265
|
+
typer.echo("Could not check for updates: network error.")
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
current = get_current_version()
|
|
269
|
+
|
|
270
|
+
needs_update = compare_versions(current, latest)
|
|
271
|
+
is_channel_switch = False
|
|
272
|
+
if not needs_update:
|
|
273
|
+
# If current is a pre-release and the latest is stable, allow downgrade
|
|
274
|
+
# to the stable channel
|
|
275
|
+
if is_prerelease(current) and not is_prerelease(latest):
|
|
276
|
+
is_channel_switch = True
|
|
277
|
+
|
|
278
|
+
if not needs_update and not is_channel_switch:
|
|
279
|
+
typer.echo(f"You are already running the latest version ({current}).")
|
|
280
|
+
return
|
|
281
|
+
|
|
282
|
+
if is_channel_switch:
|
|
283
|
+
typer.echo(f"You are running the latest experimental version ({current}).")
|
|
284
|
+
typer.echo(
|
|
285
|
+
"To switch to the stable release, run: pip uninstall -y teddy-cli && pip install teddy-cli"
|
|
286
|
+
)
|
|
287
|
+
typer.echo("To apply prompt updates, run: teddy init prompts")
|
|
288
|
+
elif experimental:
|
|
289
|
+
typer.echo(f"A new experimental version {latest} is available.")
|
|
290
|
+
typer.echo(
|
|
291
|
+
"To upgrade, run: pip install --upgrade teddy-cli --index-url https://test.pypi.org/simple/"
|
|
292
|
+
)
|
|
293
|
+
typer.echo("To apply prompt updates, run: teddy init prompts")
|
|
294
|
+
else:
|
|
295
|
+
typer.echo(f"A new version {latest} is available.")
|
|
296
|
+
typer.echo("To upgrade, run: pip install --upgrade teddy-cli")
|
|
297
|
+
typer.echo("To apply prompt updates, run: teddy init prompts")
|
|
298
|
+
|
|
299
|
+
|
|
197
300
|
@app.command()
|
|
198
301
|
def context(
|
|
199
302
|
no_copy: bool = typer.Option(
|
|
@@ -247,3 +247,18 @@ def apply_ui_mode_override(container: Container, ui_mode_bool: bool) -> None:
|
|
|
247
247
|
|
|
248
248
|
mode = "tui" if ui_mode_bool else "console"
|
|
249
249
|
register_reviewer(container, ui_mode=mode)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def prewarm_imports() -> None:
|
|
253
|
+
"""
|
|
254
|
+
Pre-warm heavy imports to reduce first-run latency.
|
|
255
|
+
Extracted from __main__.py init command for reuse by update command.
|
|
256
|
+
"""
|
|
257
|
+
try:
|
|
258
|
+
import litellm # noqa: F401
|
|
259
|
+
import trafilatura # noqa: F401
|
|
260
|
+
import pyperclip # noqa: F401
|
|
261
|
+
from bs4 import BeautifulSoup # noqa: F401
|
|
262
|
+
from ddgs import DDGS # noqa: F401
|
|
263
|
+
except ImportError:
|
|
264
|
+
pass
|
{teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/adapters/inbound/session_cli_handlers.py
RENAMED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess # nosec B404
|
|
1
4
|
from pathlib import Path
|
|
2
5
|
from typing import Dict, Optional, Sequence
|
|
6
|
+
|
|
3
7
|
import typer
|
|
4
8
|
from punq import Container
|
|
5
9
|
|
|
@@ -17,9 +21,94 @@ from teddy_executor.core.utils.string import slugify
|
|
|
17
21
|
from teddy_executor.adapters.inbound.cli_formatter import format_project_context
|
|
18
22
|
from teddy_executor.adapters.inbound.cli_helpers import (
|
|
19
23
|
echo_and_copy,
|
|
24
|
+
find_project_root,
|
|
25
|
+
)
|
|
26
|
+
from teddy_executor.core.services.update_checker import (
|
|
27
|
+
background_check,
|
|
28
|
+
compare_versions,
|
|
29
|
+
get_current_version,
|
|
30
|
+
read_update_cache,
|
|
20
31
|
)
|
|
21
32
|
|
|
22
33
|
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _ensure_commit_hooks() -> None:
|
|
38
|
+
"""Install pre-commit hooks if config exists and CLI is available.
|
|
39
|
+
Shows green notification on success, yellow warning if config missing
|
|
40
|
+
or CLI not found."""
|
|
41
|
+
config_path = Path.cwd() / ".pre-commit-config.yaml"
|
|
42
|
+
if not config_path.exists():
|
|
43
|
+
typer.secho(
|
|
44
|
+
"⚠ No pre-commit hooks configured",
|
|
45
|
+
fg=typer.colors.YELLOW,
|
|
46
|
+
err=True,
|
|
47
|
+
)
|
|
48
|
+
return
|
|
49
|
+
if not shutil.which("pre-commit"):
|
|
50
|
+
typer.secho(
|
|
51
|
+
"⚠ pre-commit CLI not found",
|
|
52
|
+
fg=typer.colors.YELLOW,
|
|
53
|
+
err=True,
|
|
54
|
+
)
|
|
55
|
+
return
|
|
56
|
+
try:
|
|
57
|
+
subprocess.run( # nosec B603 B607
|
|
58
|
+
["pre-commit", "install", "-t", "pre-commit", "-t", "post-commit"],
|
|
59
|
+
check=True,
|
|
60
|
+
capture_output=True,
|
|
61
|
+
)
|
|
62
|
+
except subprocess.CalledProcessError:
|
|
63
|
+
logger.debug("pre-commit install failed", exc_info=True)
|
|
64
|
+
return
|
|
65
|
+
typer.secho(
|
|
66
|
+
"✓ pre-commit hooks installed",
|
|
67
|
+
fg=typer.colors.GREEN,
|
|
68
|
+
err=True,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _check_git_initialized() -> None:
|
|
73
|
+
"""Verify git repository status. Auto-initializes if not a repo.
|
|
74
|
+
Shows green notification if already a repo or freshly initialized,
|
|
75
|
+
yellow warning if git CLI not found.
|
|
76
|
+
Only checks the current working directory for a `.git` marker.
|
|
77
|
+
Does NOT walk up parent directories."""
|
|
78
|
+
if not shutil.which("git"):
|
|
79
|
+
typer.secho(
|
|
80
|
+
"⚠ Git CLI not found",
|
|
81
|
+
fg=typer.colors.YELLOW,
|
|
82
|
+
err=True,
|
|
83
|
+
)
|
|
84
|
+
return
|
|
85
|
+
# Check if CWD itself contains a .git marker (directory or file)
|
|
86
|
+
if (Path.cwd() / ".git").exists():
|
|
87
|
+
typer.secho(
|
|
88
|
+
"✓ Git repository detected",
|
|
89
|
+
fg=typer.colors.GREEN,
|
|
90
|
+
err=True,
|
|
91
|
+
)
|
|
92
|
+
return
|
|
93
|
+
# No local .git found – auto-initialize
|
|
94
|
+
try:
|
|
95
|
+
subprocess.run(["git", "init"], check=True, capture_output=True) # nosec B603 B607
|
|
96
|
+
except subprocess.CalledProcessError:
|
|
97
|
+
logger.debug("git init failed", exc_info=True)
|
|
98
|
+
return
|
|
99
|
+
typer.secho(
|
|
100
|
+
"✓ Git repository initialized",
|
|
101
|
+
fg=typer.colors.GREEN,
|
|
102
|
+
err=True,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _run_health_checks() -> None:
|
|
107
|
+
"""Run all startup health checks and display notifications if needed."""
|
|
108
|
+
_ensure_commit_hooks()
|
|
109
|
+
_check_git_initialized()
|
|
110
|
+
|
|
111
|
+
|
|
23
112
|
def _determine_session_name(name: Optional[str], message: Optional[str]) -> str:
|
|
24
113
|
"""Determine session name (slugify message if name is missing)."""
|
|
25
114
|
if name:
|
|
@@ -78,6 +167,34 @@ def _orchestrate_session_loop(
|
|
|
78
167
|
break
|
|
79
168
|
|
|
80
169
|
|
|
170
|
+
def _display_update_notification(cache_path: Path) -> None:
|
|
171
|
+
"""Check the update cache and display a non-blocking notification
|
|
172
|
+
if a newer version is available. Called on session startup, after
|
|
173
|
+
the background check thread has been started."""
|
|
174
|
+
try:
|
|
175
|
+
cache = read_update_cache(cache_path)
|
|
176
|
+
if cache is None:
|
|
177
|
+
return
|
|
178
|
+
latest = cache.get("latest_version", "")
|
|
179
|
+
if not latest:
|
|
180
|
+
return
|
|
181
|
+
current = get_current_version()
|
|
182
|
+
if compare_versions(current, latest):
|
|
183
|
+
typer.echo(
|
|
184
|
+
typer.style(
|
|
185
|
+
f"ℹ A new version {latest} is available. "
|
|
186
|
+
"To upgrade, run: pip install --upgrade teddy-cli\n"
|
|
187
|
+
" To apply prompt updates: delete .teddy/prompts/ and run 'teddy init'",
|
|
188
|
+
fg=typer.colors.YELLOW,
|
|
189
|
+
)
|
|
190
|
+
)
|
|
191
|
+
except Exception:
|
|
192
|
+
import logging
|
|
193
|
+
|
|
194
|
+
logger = logging.getLogger(__name__)
|
|
195
|
+
logger.debug("Failed to display update notification", exc_info=True)
|
|
196
|
+
|
|
197
|
+
|
|
81
198
|
def handle_new_session( # noqa: PLR0913
|
|
82
199
|
container: Container,
|
|
83
200
|
name: Optional[str],
|
|
@@ -91,11 +208,26 @@ def handle_new_session( # noqa: PLR0913
|
|
|
91
208
|
api_key: Optional[str] = None,
|
|
92
209
|
):
|
|
93
210
|
"""Logic for the 'start' command."""
|
|
211
|
+
import threading
|
|
212
|
+
|
|
213
|
+
# Start non-blocking background version check
|
|
214
|
+
cache_path = find_project_root() / ".teddy" / ".update_cache.json"
|
|
215
|
+
thread = threading.Thread(
|
|
216
|
+
target=background_check,
|
|
217
|
+
args=(cache_path,),
|
|
218
|
+
daemon=True,
|
|
219
|
+
)
|
|
220
|
+
thread.start()
|
|
221
|
+
_display_update_notification(cache_path)
|
|
222
|
+
|
|
94
223
|
try:
|
|
95
224
|
# 0. Ensure project is initialized
|
|
96
225
|
container.resolve(IInitUseCase).ensure_initialized()
|
|
97
226
|
|
|
98
|
-
# 1.
|
|
227
|
+
# 1. Health checks (advisory, non-blocking)
|
|
228
|
+
_run_health_checks()
|
|
229
|
+
|
|
230
|
+
# 2. Pre-flight checks (Fail-fast before user interaction)
|
|
99
231
|
typer.echo("Checking configurations...", err=True)
|
|
100
232
|
_run_cli_preflight_check(container, agent=agent)
|
|
101
233
|
_echo_config_success(container, agent, model=model)
|
|
@@ -326,8 +458,23 @@ def handle_resume_session( # noqa: PLR0913
|
|
|
326
458
|
api_key: Optional[str] = None,
|
|
327
459
|
):
|
|
328
460
|
"""Logic for the 'resume' command."""
|
|
461
|
+
import threading
|
|
462
|
+
|
|
463
|
+
# Start non-blocking background version check
|
|
464
|
+
cache_path = find_project_root() / ".teddy" / ".update_cache.json"
|
|
465
|
+
thread = threading.Thread(
|
|
466
|
+
target=background_check,
|
|
467
|
+
args=(cache_path,),
|
|
468
|
+
daemon=True,
|
|
469
|
+
)
|
|
470
|
+
thread.start()
|
|
471
|
+
_display_update_notification(cache_path)
|
|
472
|
+
|
|
329
473
|
try:
|
|
330
|
-
# 1.
|
|
474
|
+
# 1. Health checks (advisory, non-blocking)
|
|
475
|
+
_run_health_checks()
|
|
476
|
+
|
|
477
|
+
# 2. Pre-flight checks
|
|
331
478
|
typer.echo("Checking configurations...", err=True)
|
|
332
479
|
_run_cli_preflight_check(container)
|
|
333
480
|
|
|
@@ -154,6 +154,9 @@ async def orchestrate_execution(app: ReviewerApp, node: Any, update_fn: Any) ->
|
|
|
154
154
|
action.state = ExecutionStatus.RUNNING
|
|
155
155
|
app._refresh_node(node)
|
|
156
156
|
|
|
157
|
+
# Harvest modified content from pending_temp_file before execution
|
|
158
|
+
harvest_action_content(action, app.INSTRUCTION_MARKER)
|
|
159
|
+
|
|
157
160
|
try:
|
|
158
161
|
import anyio
|
|
159
162
|
|
|
@@ -39,7 +39,7 @@ class SystemEnvironmentInspector(IEnvironmentInspector):
|
|
|
39
39
|
|
|
40
40
|
def get_git_status(self) -> Optional[str]:
|
|
41
41
|
"""
|
|
42
|
-
Gathers the current Git status of the working directory.
|
|
42
|
+
Gathers the current Git status of the working directory (short format).
|
|
43
43
|
"""
|
|
44
44
|
try:
|
|
45
45
|
result = self._run_func( # nosec B603 B607
|
|
@@ -52,3 +52,19 @@ class SystemEnvironmentInspector(IEnvironmentInspector):
|
|
|
52
52
|
return result.stdout.rstrip() if result.stdout else ""
|
|
53
53
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
54
54
|
return None
|
|
55
|
+
|
|
56
|
+
def get_full_git_status(self) -> Optional[str]:
|
|
57
|
+
"""
|
|
58
|
+
Gathers the full Git status of the working directory (including branch info).
|
|
59
|
+
"""
|
|
60
|
+
try:
|
|
61
|
+
result = self._run_func( # nosec B603 B607
|
|
62
|
+
["git", "status"],
|
|
63
|
+
capture_output=True,
|
|
64
|
+
text=True,
|
|
65
|
+
check=True,
|
|
66
|
+
stdin=subprocess.DEVNULL,
|
|
67
|
+
)
|
|
68
|
+
return result.stdout.rstrip() if result.stdout else ""
|
|
69
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
70
|
+
return None
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class IInitUseCase(ABC):
|
|
5
|
+
"""
|
|
6
|
+
Inbound port for project initialization.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def ensure_initialized(self) -> str:
|
|
11
|
+
"""
|
|
12
|
+
Ensures the .teddy/ directory and its essential configuration
|
|
13
|
+
files are present in the current project root.
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
A human-readable summary string (e.g., "Config: unchanged. Prompts: updated (3 files).").
|
|
17
|
+
"""
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def ensure_prompts_initialized(self, overwrite: bool = False) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Ensures prompt XML files are present in the .teddy/prompts/ directory.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
overwrite: If True, always overwrite existing prompt files with defaults.
|
|
27
|
+
If False (default), only write missing files.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
A human-readable status string (e.g., "Prompts overwritten (6 files).").
|
|
31
|
+
"""
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def ensure_config_initialized(self, overwrite: bool = False) -> str:
|
|
36
|
+
"""
|
|
37
|
+
Ensures configuration files (config.yaml, .gitignore, init.context) are present
|
|
38
|
+
in the .teddy/ directory.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
overwrite: If True, always overwrite existing config files with defaults.
|
|
42
|
+
If False (default), only write missing files.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
A human-readable status string (e.g., "Configuration files overwritten (3 files).").
|
|
46
|
+
"""
|
|
47
|
+
pass
|
{teddy_cli-0.1.4 → teddy_cli-0.1.6}/src/teddy_executor/core/ports/outbound/environment_inspector.py
RENAMED
|
@@ -22,9 +22,18 @@ class IEnvironmentInspector(Protocol):
|
|
|
22
22
|
|
|
23
23
|
def get_git_status(self) -> Optional[str]:
|
|
24
24
|
"""
|
|
25
|
-
Gathers the current Git status of the working directory.
|
|
25
|
+
Gathers the current Git status of the working directory (short format).
|
|
26
26
|
|
|
27
27
|
Returns:
|
|
28
28
|
Optional[str]: The output of 'git status -s' or None if not a git repo.
|
|
29
29
|
"""
|
|
30
30
|
...
|
|
31
|
+
|
|
32
|
+
def get_full_git_status(self) -> Optional[str]:
|
|
33
|
+
"""
|
|
34
|
+
Gathers the full Git status of the working directory (including branch info).
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Optional[str]: The output of 'git status' or None if not a git repo.
|
|
38
|
+
"""
|
|
39
|
+
...
|
|
@@ -39,7 +39,7 @@ class ContextService(IGetContextUseCase):
|
|
|
39
39
|
self._llm_client = llm_client
|
|
40
40
|
self._web_scraper = web_scraper
|
|
41
41
|
|
|
42
|
-
def get_context(
|
|
42
|
+
def get_context( # noqa: PLR0913
|
|
43
43
|
self,
|
|
44
44
|
context_files: Optional[Dict[str, Sequence[str]]] = None,
|
|
45
45
|
include_tokens: bool = True,
|
|
@@ -53,7 +53,8 @@ class ContextService(IGetContextUseCase):
|
|
|
53
53
|
Gathers all project context information by orchestrating its dependencies.
|
|
54
54
|
"""
|
|
55
55
|
system_info = self._environment_inspector.get_environment_info()
|
|
56
|
-
|
|
56
|
+
short_git_status = self._environment_inspector.get_git_status()
|
|
57
|
+
full_git_status = self._environment_inspector.get_full_git_status()
|
|
57
58
|
repo_tree = self._repo_tree_generator.generate_tree()
|
|
58
59
|
|
|
59
60
|
scoped_paths, all_resolved_paths = self._resolve_scoped_paths(context_files)
|
|
@@ -79,7 +80,7 @@ class ContextService(IGetContextUseCase):
|
|
|
79
80
|
file_contents[url] = None
|
|
80
81
|
|
|
81
82
|
content = self._format_content(
|
|
82
|
-
repo_tree, scoped_paths, file_contents,
|
|
83
|
+
repo_tree, scoped_paths, file_contents, full_git_status
|
|
83
84
|
)
|
|
84
85
|
content_tokens = (
|
|
85
86
|
self._llm_client.get_text_token_count(content) if include_tokens else 0
|
|
@@ -89,9 +90,9 @@ class ContextService(IGetContextUseCase):
|
|
|
89
90
|
header=self._format_header(system_info, current_turn),
|
|
90
91
|
content=content,
|
|
91
92
|
scoped_paths=scoped_paths,
|
|
92
|
-
git_status=
|
|
93
|
+
git_status=full_git_status,
|
|
93
94
|
items=self._collect_items(
|
|
94
|
-
scoped_paths, file_contents,
|
|
95
|
+
scoped_paths, file_contents, short_git_status, include_tokens
|
|
95
96
|
),
|
|
96
97
|
agent_name=agent_name,
|
|
97
98
|
total_window=total_window,
|
|
@@ -303,10 +304,6 @@ class ContextService(IGetContextUseCase):
|
|
|
303
304
|
git_status: Optional[str] = None,
|
|
304
305
|
) -> str:
|
|
305
306
|
"""Formats the main content section of the context report."""
|
|
306
|
-
display_status = git_status
|
|
307
|
-
if git_status == "":
|
|
308
|
-
display_status = "nothing to commit, working tree clean"
|
|
309
|
-
|
|
310
307
|
# Gather all unique paths
|
|
311
308
|
all_paths: List[str] = []
|
|
312
309
|
for paths in scoped_paths.values():
|
|
@@ -320,7 +317,7 @@ class ContextService(IGetContextUseCase):
|
|
|
320
317
|
|
|
321
318
|
content_parts = [
|
|
322
319
|
"\n## Git Status",
|
|
323
|
-
|
|
320
|
+
git_status if isinstance(git_status, str) else "",
|
|
324
321
|
"\n## Project Structure",
|
|
325
322
|
f"```\n{repo_tree}\n```",
|
|
326
323
|
]
|