|
17 | 17 | import { tool } from 'ai'; |
18 | 18 | import { z } from 'zod'; |
19 | 19 | import { CopilotEventHandler } from '../event'; |
20 | | -import { Task, TaskStatus, TaskTypes, Plan, AIChatMachineEventType, SourceFiles } from '@wso2/ballerina-core'; |
| 20 | +import { Task, TaskStatus, TaskTypes, Plan, AIChatMachineEventType, SourceFiles, AIChatMachineContext } from '@wso2/ballerina-core'; |
21 | 21 | import { AIChatStateMachine } from '../../../../views/ai-panel/aiChatMachine'; |
22 | 22 | import { integrateCodeToWorkspace } from '../design/utils'; |
| 23 | +import { checkCompilationErrors } from './diagnostics_utils'; |
| 24 | +import { DIAGNOSTICS_TOOL_NAME } from './diagnostics_tool'; |
23 | 25 |
|
24 | 26 | export const TASK_WRITE_TOOL_NAME = "TaskWrite"; |
25 | 27 |
|
@@ -134,11 +136,11 @@ Rules: |
134 | 136 |
|
135 | 137 | const taskCategories = categorizeTasks(allTasks); |
136 | 138 |
|
137 | | - // TODO: Fix issue where agent updates to existing plan trigger new approval |
138 | | - // Problem: When agent continues chat with plan updates, currentPlan state is empty |
139 | | - // causing it to be identified as new plan and triggering approval unnecessarily. |
140 | | - // Need to preserve plan state across chat continuations or use chat history to |
141 | | - // detect if this is a continuation of an existing conversation with a plan. |
| 139 | + // TODO: Add tests for plan modification detection in the middle of execution |
| 140 | + // Fixed: Plan state is now preserved in the state machine across chat continuations, |
| 141 | + // preventing unnecessary approval requests when agent continues with existing plan. |
| 142 | + // Still need comprehensive tests for: mid-execution plan modifications, task reordering, |
| 143 | + // task additions/removals, and edge cases where plan changes should trigger re-approval. |
142 | 144 | const isNewPlan = !existingPlan || existingPlan.tasks.length === 0; |
143 | 145 | const isPlanRemodification = existingPlan && ( |
144 | 146 | allTasks.length !== existingPlan.tasks.length || |
@@ -304,18 +306,32 @@ async function handlePlanApproval( |
304 | 306 | async function handleTaskCompletion( |
305 | 307 | allTasks: Task[], |
306 | 308 | newlyCompletedTasks: Task[], |
307 | | - currentContext: any, |
| 309 | + currentContext: AIChatMachineContext, |
308 | 310 | eventHandler: CopilotEventHandler, |
309 | 311 | tempProjectPath?: string, |
310 | 312 | modifiedFiles?: string[] |
311 | 313 | ): Promise<{ approved: boolean; comment?: string; approvedTaskDescription: string }> { |
312 | 314 | const lastCompletedTask = newlyCompletedTasks[newlyCompletedTasks.length - 1]; |
313 | 315 | console.log(`[TaskWrite Tool] Detected ${newlyCompletedTasks.length} newly completed task(s)`); |
314 | 316 |
|
| 317 | + const diagnosticResult = await checkCompilationErrors(tempProjectPath!); |
| 318 | + |
| 319 | + if (diagnosticResult.diagnostics.length > 0) { |
| 320 | + const errorCount = diagnosticResult.diagnostics.length; |
| 321 | + console.error(`[TaskWrite Tool] Found ${errorCount} compilation error(s), blocking task completion`); |
| 322 | + |
| 323 | + return { |
| 324 | + approved: false, |
| 325 | + comment: `Cannot complete task: ${errorCount} compilation error(s) detected. Use the ${DIAGNOSTICS_TOOL_NAME} tool to check the errors and fix them before marking the task as completed.`, |
| 326 | + approvedTaskDescription: lastCompletedTask.description |
| 327 | + }; |
| 328 | + } |
| 329 | + |
315 | 330 | if (tempProjectPath && modifiedFiles) { |
316 | 331 | const modifiedFilesSet = new Set(modifiedFiles); |
317 | 332 | console.log(`[TaskWrite Tool] Integrating ${modifiedFilesSet.size} modified file(s)`); |
318 | 333 | await integrateCodeToWorkspace(tempProjectPath, modifiedFilesSet); |
| 334 | + modifiedFiles.length = 0; |
319 | 335 | } |
320 | 336 |
|
321 | 337 | AIChatStateMachine.sendEvent({ |
|
0 commit comments