Skip to content

Commit 72516d3

Browse files
ryaneggzclaude
andcommitted
fix: address planner review — error handling, prompt validation, input guards, scope_level
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: ryaneggz <kre8mymedia@gmail.com>
1 parent 06bba64 commit 72516d3

2 files changed

Lines changed: 19 additions & 5 deletions

File tree

backend/src/schemas/entities/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
PatchDefaultsRequest as PatchDefaultsRequest,
2525
UpsertProviderKeyRequest as UpsertProviderKeyRequest,
2626
)
27+
from src.schemas.entities.planner import PlannerConfig as PlannerConfig
2728
from src.schemas.entities.hitl import (
2829
DecisionType as DecisionType,
2930
HumanDecision as HumanDecision,

backend/src/utils/planner.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
# Load the planner system prompt
1313
_PLANNER_PROMPT_PATH = Path(__file__).parent.parent / "static" / "prompts" / "md" / "planner.md"
14-
_PLANNER_PROMPT = ""
15-
if _PLANNER_PROMPT_PATH.exists():
16-
_PLANNER_PROMPT = _PLANNER_PROMPT_PATH.read_text()
14+
if not _PLANNER_PROMPT_PATH.exists():
15+
raise RuntimeError(f"Planner prompt file not found: {_PLANNER_PROMPT_PATH}")
16+
_PLANNER_PROMPT = _PLANNER_PROMPT_PATH.read_text()
1717

1818

1919
async def run_planner(
@@ -44,11 +44,19 @@ async def run_planner(
4444
"\n\nIMPORTANT: Keep the scope conservative. "
4545
"Only include features explicitly requested by the user. Do not add extras."
4646
)
47-
else:
47+
elif planner_config.scope_level == "ambitious":
4848
scope_instruction = (
4949
"\n\nBe ambitious about scope. Include features that would make this product impressive, "
5050
"even if the user didn't explicitly request them."
5151
)
52+
else:
53+
scope_instruction = ""
54+
logger.warning(f"planner_unknown_scope scope_level={planner_config.scope_level}")
55+
56+
MAX_PLANNER_INPUT = 10_000 # characters
57+
if len(user_message) > MAX_PLANNER_INPUT:
58+
logger.warning(f"planner_input_truncated original_length={len(user_message)}")
59+
user_message = user_message[:MAX_PLANNER_INPUT]
5260

5361
system_prompt = _PLANNER_PROMPT + scope_instruction
5462

@@ -59,7 +67,12 @@ async def run_planner(
5967

6068
logger.info(f"planner_phase model={model_name} scope={planner_config.scope_level}")
6169

62-
response = await llm.ainvoke(messages)
70+
try:
71+
response = await llm.ainvoke(messages)
72+
except Exception as e:
73+
logger.error(f"planner_phase_failed model={model_name} error={e}")
74+
raise RuntimeError(f"Planner failed to generate plan: {e}") from e
75+
6376
plan_text = response.content if isinstance(response.content, str) else str(response.content)
6477

6578
logger.info(f"planner_phase_complete plan_length={len(plan_text)}")

0 commit comments

Comments
 (0)