diff --git a/src/cleveragents/application/services/llm_actors.py b/src/cleveragents/application/services/llm_actors.py index 7c6f67c9f..1019cc82f 100644 --- a/src/cleveragents/application/services/llm_actors.py +++ b/src/cleveragents/application/services/llm_actors.py @@ -384,7 +384,10 @@ class LLMExecuteActor: f"Steps:\n{steps_text}\n\n" f"{context_section}" "For each file you create or modify, output a block:\n" - "FILE: \n<<<<<<< CLEVERAGENTS_FILE_START >>>>>>>\n\n<<<<<<< CLEVERAGENTS_FILE_END >>>>>>>\n\n" + "FILE: \n" + "<<<<<<< CLEVERAGENTS_FILE_START >>>>>>>\n" + "\n" + "<<<<<<< CLEVERAGENTS_FILE_END >>>>>>>\n\n" "Only output file blocks. Do not add commentary." ) @@ -461,9 +464,11 @@ class LLMExecuteActor: def _parse_file_blocks(llm_output: str, plan_id: str) -> list[ChangeSetEntry]: """Extract ``FILE: `` + content between delimiters.""" entries: list[ChangeSetEntry] = [] - # Pattern: FILE: followed by unique delimiters that won't collide with code + # Pattern: FILE: followed by unique delimiters + _DELIM_START = "<<<<<<< CLEVERAGENTS_FILE_START >>>>>>>" + _DELIM_END = "<<<<<<< CLEVERAGENTS_FILE_END >>>>>>>" pattern = re.compile( - r"FILE:\s*(.+?)\s*\n<<<<<<< CLEVERAGENTS_FILE_START >>>>>>>\n(.*?)\n<<<<<<< CLEVERAGENTS_FILE_END >>>>>>>", + rf"FILE:\s*(.+?)\s*\n{_DELIM_START}\n(.*?)\n{_DELIM_END}", re.DOTALL, ) for match in pattern.finditer(llm_output): @@ -487,9 +492,10 @@ class LLMExecuteActor: llm_output: str, ) -> None: """Write generated file contents to the sandbox directory.""" - + _DELIM_START = "<<<<<<< CLEVERAGENTS_FILE_START >>>>>>>" + _DELIM_END = "<<<<<<< CLEVERAGENTS_FILE_END >>>>>>>" pattern = re.compile( - r"FILE:\s*(.+?)\s*\n<<<<<<< CLEVERAGENTS_FILE_START >>>>>>>\n(.*?)\n<<<<<<< CLEVERAGENTS_FILE_END >>>>>>>", + rf"FILE:\s*(.+?)\s*\n{_DELIM_START}\n(.*?)\n{_DELIM_END}", re.DOTALL, ) for match in pattern.finditer(llm_output): diff --git a/src/cleveragents/application/services/plan_executor.py b/src/cleveragents/application/services/plan_executor.py index b8416153f..d3b6dd077 100644 --- a/src/cleveragents/application/services/plan_executor.py +++ b/src/cleveragents/application/services/plan_executor.py @@ -29,6 +29,12 @@ from ulid import ULID from cleveragents.application.services.autonomy_guardrail_service import ( AutonomyGuardrailService, ) +from cleveragents.application.services.context_tier_hydrator import ( + hydrate_tiers_for_plan, +) +from cleveragents.application.services.context_tiers import ( + ContextTierService, +) from cleveragents.application.services.fix_then_revalidate import ( FixThenRevalidateOrchestrator, ) @@ -37,6 +43,9 @@ from cleveragents.application.services.plan_execution_context import ( RuntimeExecuteActor, RuntimeExecuteResult, ) +from cleveragents.application.services.resource_registry_service import ( + ResourceRegistryService, +) from cleveragents.application.services.strategy_models import StrategyTree from cleveragents.core.exceptions import PlanError, ValidationError from cleveragents.domain.models.core.change import ChangeSetStore @@ -51,24 +60,15 @@ from cleveragents.domain.models.observability.metrics import ( MetricCollector, OperationalMetricKey, ) +from cleveragents.infrastructure.database.repositories import ( + NamespacedProjectRepository, +) from cleveragents.infrastructure.sandbox.checkpoint import ( CheckpointManager, SandboxCheckpoint, ) from cleveragents.tool.builtins.changeset import ChangeSet, ChangeSetCapture from cleveragents.tool.runner import ToolRunner -from cleveragents.application.services.context_tier_hydrator import ( - hydrate_tiers_for_plan, -) -from cleveragents.application.services.context_tiers import ( - ContextTierService, -) -from cleveragents.infrastructure.database.repositories import ( - NamespacedProjectRepository, -) -from cleveragents.application.services.resource_registry_service import ( - ResourceRegistryService, -) if TYPE_CHECKING: from cleveragents.application.services.error_recovery_service import ( @@ -792,26 +792,26 @@ class PlanExecutor: ) hydrate_tiers_for_plan( - tier_service=self._tier_service, - project_names=resources, - project_repository=self._project_repository, - resource_registry=self._resource_registry, - ) + tier_service=self._tier_service, + project_names=resources, + project_repository=self._project_repository, + resource_registry=self._resource_registry, + ) - # Check what's in the tier service after hydration - hot_frags = self._tier_service.get_hot_fragments() - self._logger.info( - "tier_hydration_complete", - plan_id=plan_id, - fragment_count=len(hot_frags) if hot_frags else 0, - ) - except Exception as hydration_exc: - self._logger.warning( - "strategize_context_hydration_failed", - error=str(hydration_exc), - plan_id=plan_id, - exc_info=True, - ) + # Check what's in the tier service after hydration + hot_frags = self._tier_service.get_hot_fragments() + self._logger.info( + "tier_hydration_complete", + plan_id=plan_id, + fragment_count=len(hot_frags) if hot_frags else 0, + ) + except Exception as hydration_exc: + self._logger.warning( + "strategize_context_hydration_failed", + error=str(hydration_exc), + plan_id=plan_id, + exc_info=True, + ) # StrategyActor.execute() accepts resources/project_context; # StrategizeStubActor.execute() ignores unknown kwargs via diff --git a/src/cleveragents/application/services/strategy_actor.py b/src/cleveragents/application/services/strategy_actor.py index dd44e8730..58f49386f 100644 --- a/src/cleveragents/application/services/strategy_actor.py +++ b/src/cleveragents/application/services/strategy_actor.py @@ -33,13 +33,14 @@ from langchain_core.messages import HumanMessage, SystemMessage from pydantic import ValidationError as PydanticValidationError from ulid import ULID -from cleveragents.application.services.plan_executor import ( - StrategyDecision, - StrategizeResult, -) from cleveragents.application.services.context_tiers import ( ContextTierService, ) +from cleveragents.application.services.plan_executor import ( + StrategizeResult, + StrategyDecision, + StreamCallback, +) from cleveragents.application.services.strategy_models import ( StrategyAction, StrategyTree, @@ -498,22 +499,32 @@ class StrategyActor: # Build context with actual file content, not just metadata context_parts = [ - f"Available context: {file_count} files, ~{total_tokens} tokens.", + f"Available context: {file_count} files, " + f"~{total_tokens} tokens.", f"File types: {lang_summary}", "", "--- Source Files (hot tier) ---", ] - # Include actual file content for key files (limit to prevent token overflow) - # Take up to 20 fragments with their content + # Include actual file content for key files (limit to prevent + # token overflow). Take up to 20 fragments with their content. for frag in all_fragments[:20]: - path = frag.metadata.get("path", "unknown") if frag.metadata else "unknown" - content = frag.content[:2000] if frag.content else "" # Truncate long files + path = ( + frag.metadata.get("path", "unknown") + if frag.metadata + else "unknown" + ) + # Truncate long files + content = frag.content[:2000] if frag.content else "" if content: - context_parts.append(f"\n### {path}\n```\n{content}\n```") + context_parts.append( + f"\n### {path}\n```\n{content}\n```" + ) if len(all_fragments) > 20: - context_parts.append(f"\n... and {len(all_fragments) - 20} more files") + context_parts.append( + f"\n... and {len(all_fragments) - 20} more files" + ) acms_context = "\n".join(context_parts) except Exception: diff --git a/src/cleveragents/application/services/strategy_resolution.py b/src/cleveragents/application/services/strategy_resolution.py index a9f85b6c5..dd7eabfdd 100644 --- a/src/cleveragents/application/services/strategy_resolution.py +++ b/src/cleveragents/application/services/strategy_resolution.py @@ -11,10 +11,10 @@ from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable import structlog -from cleveragents.core.exceptions import PlanError from cleveragents.application.services.context_tiers import ( ContextTierService, ) +from cleveragents.core.exceptions import PlanError if TYPE_CHECKING: from cleveragents.providers.registry import ProviderRegistry diff --git a/src/cleveragents/cli/commands/plan.py b/src/cleveragents/cli/commands/plan.py index 08368dbf9..4916e25d9 100644 --- a/src/cleveragents/cli/commands/plan.py +++ b/src/cleveragents/cli/commands/plan.py @@ -2924,9 +2924,12 @@ def execute_plan( plan = service.get_plan(plan_id) # Route files to correct per-resource worktrees (spec ยง19310) - # then commit each worktree branch. Pass sandbox_root (plan-output path) - # so it can copy files from the discoverable location to worktrees. - _route_sandbox_files_to_worktrees(sandbox_infos, plan_output_path=sandbox_root) + # then commit each worktree branch. Pass sandbox_root + # (plan-output path) so it can copy files from the discoverable + # location to worktrees. + _route_sandbox_files_to_worktrees( + sandbox_infos, plan_output_path=sandbox_root + ) for sinfo in sandbox_infos: _commit_worktree_changes(sinfo.sandbox_path, plan_id)