Skip to content

Commit 3c1a144

Browse files
authored
fix(tools): align Plan tool handler with schema definition (#23)
* fix(tools): align Plan tool handler with schema definition The Plan tool had a critical mismatch between its schema definition and handler implementation: - Schema expected: title, description, tasks, agent_analyses (required) - Handler processed: only 'todos' string parameter This caused function calls to fail when LLMs generated Plan tool calls based on the schema but the handler couldn't process the rich parameters. Changes: - Updated PlanHandler to properly parse all schema parameters - Added support for architecture, tech_stack, use_cases, risks, success_criteria, timeline, and estimated_changes fields - Convert tasks and agent_analyses to internal formats - Generate rich markdown output with all plan sections - Aligned app-server definitions to match engine schema This ensures consistent Plan tool behavior across the codebase. * fix(app-server): update planning.rs to handle Plan tool schema Address Greptile review feedback - the container mode Plan implementation in planning.rs was missing support for the new required field agent_analyses and other optional fields. Changes: - Added agent_analyses parameter handling (required) - Added optional fields: architecture, tech_stack, use_cases, risks, success_criteria, timeline - Build plan_data JSON with all fields for consistency * fix(batch): address unused variable clippy warnings
1 parent feb26a8 commit 3c1a144

3 files changed

Lines changed: 401 additions & 43 deletions

File tree

src/cortex-app-server/src/tools/definitions.rs

Lines changed: 108 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
337337
},
338338
ToolDefinition {
339339
name: "Plan".to_string(),
340-
description: "Present an implementation plan for user approval before coding. Use this to outline approach, list tasks, and get confirmation.".to_string(),
340+
description: "Present a comprehensive implementation plan with multi-agent expert analysis for user approval. Include security, architecture, performance, and other expert perspectives.".to_string(),
341341
parameters: json!({
342342
"type": "object",
343343
"properties": {
@@ -347,7 +347,16 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
347347
},
348348
"description": {
349349
"type": "string",
350-
"description": "Detailed description of what will be implemented and how"
350+
"description": "Detailed description of what will be implemented and the overall approach"
351+
},
352+
"architecture": {
353+
"type": "string",
354+
"description": "High-level architecture description"
355+
},
356+
"tech_stack": {
357+
"type": "array",
358+
"items": { "type": "string" },
359+
"description": "Technologies, frameworks, and tools to be used"
351360
},
352361
"tasks": {
353362
"type": "array",
@@ -357,21 +366,115 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
357366
"id": { "type": "string" },
358367
"title": { "type": "string" },
359368
"description": { "type": "string" },
369+
"subtasks": {
370+
"type": "array",
371+
"items": { "type": "string" }
372+
},
373+
"dependencies": {
374+
"type": "array",
375+
"items": { "type": "string" },
376+
"description": "IDs of tasks this depends on"
377+
},
378+
"complexity": {
379+
"type": "string",
380+
"enum": ["low", "medium", "high", "critical"]
381+
},
382+
"estimated_time": { "type": "string" },
360383
"status": {
361384
"type": "string",
362385
"enum": ["pending", "in_progress", "completed"]
363386
}
364387
},
365388
"required": ["id", "title"]
366389
},
367-
"description": "List of tasks to complete"
390+
"description": "List of tasks with subtasks and dependencies"
391+
},
392+
"use_cases": {
393+
"type": "array",
394+
"items": {
395+
"oneOf": [
396+
{ "type": "string" },
397+
{
398+
"type": "object",
399+
"properties": {
400+
"name": { "type": "string" },
401+
"description": { "type": "string" },
402+
"actors": { "type": "array", "items": { "type": "string" } },
403+
"flow": { "type": "array", "items": { "type": "string" } }
404+
}
405+
}
406+
]
407+
},
408+
"description": "User stories and use cases"
409+
},
410+
"agent_analyses": {
411+
"type": "array",
412+
"items": {
413+
"type": "object",
414+
"properties": {
415+
"agent": {
416+
"type": "string",
417+
"description": "Name of the expert agent (e.g., 'Security Analyst', 'Performance Engineer')"
418+
},
419+
"role": {
420+
"type": "string",
421+
"description": "Role description"
422+
},
423+
"findings": {
424+
"type": "array",
425+
"items": { "type": "string" },
426+
"description": "Key findings from analysis"
427+
},
428+
"recommendations": {
429+
"type": "array",
430+
"items": { "type": "string" },
431+
"description": "Recommendations and best practices"
432+
},
433+
"risk_level": {
434+
"type": "string",
435+
"enum": ["low", "medium", "high", "critical"]
436+
},
437+
"priority_items": {
438+
"type": "array",
439+
"items": { "type": "string" }
440+
}
441+
},
442+
"required": ["agent", "role", "findings", "recommendations"]
443+
},
444+
"description": "Expert analyses from different perspectives (security, performance, UX, etc.)"
445+
},
446+
"risks": {
447+
"type": "array",
448+
"items": {
449+
"oneOf": [
450+
{ "type": "string" },
451+
{
452+
"type": "object",
453+
"properties": {
454+
"risk": { "type": "string" },
455+
"level": { "type": "string", "enum": ["low", "medium", "high", "critical"] },
456+
"mitigation": { "type": "string" }
457+
}
458+
}
459+
]
460+
},
461+
"description": "Identified risks and mitigation strategies"
462+
},
463+
"success_criteria": {
464+
"type": "array",
465+
"items": { "type": "string" },
466+
"description": "Criteria to determine if implementation is successful"
467+
},
468+
"timeline": {
469+
"type": "string",
470+
"description": "Estimated timeline for completion"
368471
},
369472
"estimated_changes": {
370473
"type": "string",
371-
"description": "Brief estimate of scope (e.g., 'Small: ~50 lines', 'Medium: ~200 lines')"
474+
"description": "Brief estimate of scope (e.g., 'Small: ~50 lines', 'Large: ~1000 lines')"
372475
}
373476
},
374-
"required": ["title", "description", "tasks"]
477+
"required": ["title", "description", "tasks", "agent_analyses"]
375478
}),
376479
category: "workflow".to_string(),
377480
},

src/cortex-app-server/src/tools/planning.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,50 @@ pub async fn plan(args: Value) -> ToolResult {
7070
.get("description")
7171
.and_then(|v| v.as_str())
7272
.unwrap_or("");
73+
let architecture = args.get("architecture").and_then(|v| v.as_str());
74+
let tech_stack = args.get("tech_stack").cloned();
7375
let tasks = args.get("tasks").cloned().unwrap_or(json!([]));
76+
let use_cases = args.get("use_cases").cloned();
77+
let agent_analyses = args.get("agent_analyses").cloned().unwrap_or(json!([]));
78+
let risks = args.get("risks").cloned();
79+
let success_criteria = args.get("success_criteria").cloned();
80+
let timeline = args.get("timeline").and_then(|v| v.as_str());
7481
let estimate = args
7582
.get("estimated_changes")
7683
.and_then(|v| v.as_str())
7784
.unwrap_or("");
7885

79-
let plan_data = json!({
86+
// Build the plan data with all fields
87+
let mut plan_data = json!({
8088
"type": "plan",
8189
"title": title,
8290
"description": description,
8391
"tasks": tasks,
92+
"agent_analyses": agent_analyses,
8493
"estimated_changes": estimate,
8594
"status": "pending_approval"
8695
});
8796

97+
// Add optional fields if present
98+
if let Some(arch) = architecture {
99+
plan_data["architecture"] = json!(arch);
100+
}
101+
if let Some(stack) = tech_stack {
102+
plan_data["tech_stack"] = stack;
103+
}
104+
if let Some(cases) = use_cases {
105+
plan_data["use_cases"] = cases;
106+
}
107+
if let Some(risk_list) = risks {
108+
plan_data["risks"] = risk_list;
109+
}
110+
if let Some(criteria) = success_criteria {
111+
plan_data["success_criteria"] = criteria;
112+
}
113+
if let Some(tl) = timeline {
114+
plan_data["timeline"] = json!(tl);
115+
}
116+
88117
ToolResult {
89118
success: true,
90119
output: serde_json::to_string_pretty(&plan_data).unwrap_or_default(),

0 commit comments

Comments
 (0)