Skip to content

Commit b0e9a74

Browse files
committed
feat(ui): display loop progress with task completion status
- Add loopReason field to display task progress (e.g., "Cycle 2 - Task 5/50") - Update task verification workflow to report progress as "Task X/Y" - Pass loop reason from workflow execution to UI state - Fix bug where loopReason was cleared during agent reset
1 parent c052a43 commit b0e9a74

File tree

5 files changed

+25
-5
lines changed

5 files changed

+25
-5
lines changed

prompts/templates/codemachine/workflows/task-verification-workflow.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ You are the **StateTracker Agent**, a specialized system component. Your sole fu
2020

2121
3. **Handle Edge Case (No Tasks):** If the provided tasks array is empty (`[]`), you are to consider the project completed.
2222

23-
4. **Generate Behavior File:** Based on your final determination, your **only output** is to create or overwrite the file `.codemachine/memory/behavior.json` with the exact content specified below.
23+
4. **Count Progress:** Calculate task completion progress:
24+
* Count the total number of tasks in the array.
25+
* Count how many tasks have `"done": true`.
26+
* Use this for progress reporting in the behavior file.
27+
28+
5. **Generate Behavior File:** Based on your final determination, your **only output** is to create or overwrite the file `.codemachine/memory/behavior.json` with the exact content specified below.
2429

2530
---
2631

@@ -32,9 +37,11 @@ You are the **StateTracker Agent**, a specialized system component. Your sole fu
3237
```json
3338
{
3439
"action": "loop",
35-
"reason": "Tasks not completed"
40+
"reason": "Task X/Y"
3641
}
3742
```
43+
Where X is the number of completed tasks and Y is the total number of tasks.
44+
Example: `"reason": "Task 2/40"` means 2 out of 40 tasks are completed.
3845

3946
* **If the project IS complete (or no tasks were provided):**
4047
```json

src/ui/components/MainAgentNode.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,16 @@ export const MainAgentNode: React.FC<MainAgentNodeProps> = ({ agent, isSelected
6464

6565
// If loop round exists, show cycle on separate line below
6666
if (hasLoopRound) {
67+
// Debug: log loop reason
68+
if (process.env.LOG_LEVEL === 'debug') {
69+
console.error(`[DEBUG] MainAgentNode: loopRound=${agent.loopRound}, loopReason="${agent.loopReason}"`);
70+
}
6771
return (
6872
<Box paddingX={1} flexDirection="column">
6973
{mainLine}
7074
<Box paddingLeft={2}>
7175
<Text bold color="cyan">
72-
⎿ Cycle {agent.loopRound}
76+
⎿ Cycle {agent.loopRound}{agent.loopReason ? ` - ${agent.loopReason}` : ''}
7377
</Text>
7478
</Box>
7579
</Box>

src/ui/state/WorkflowUIState.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,15 @@ export class WorkflowUIState {
182182

183183
// Update the source agent's loop round
184184
if (loopState && loopState.active) {
185+
// Debug: log loop state
186+
if (process.env.LOG_LEVEL === 'debug') {
187+
console.error(`[DEBUG] setLoopState: sourceAgent=${loopState.sourceAgent}, iteration=${loopState.iteration}, reason="${loopState.reason}"`);
188+
}
185189
this.state = {
186190
...this.state,
187191
agents: this.state.agents.map((agent) =>
188192
agent.id === loopState.sourceAgent
189-
? { ...agent, loopRound: loopState.iteration }
193+
? { ...agent, loopRound: loopState.iteration, loopReason: loopState.reason }
190194
: agent
191195
),
192196
};
@@ -200,7 +204,7 @@ export class WorkflowUIState {
200204
...this.state,
201205
agents: this.state.agents.map((agent) =>
202206
agent.id === agentId
203-
? { ...agent, loopRound: undefined }
207+
? { ...agent, loopRound: undefined, loopReason: undefined }
204208
: agent
205209
),
206210
};
@@ -348,6 +352,8 @@ export class WorkflowUIState {
348352
startTime: Date.now(),
349353
endTime: undefined,
350354
error: undefined,
355+
// Preserve loopRound and loopReason - these are set by setLoopState and should persist
356+
// loopReason: undefined, <-- removed to preserve loop state
351357
telemetry: {
352358
tokensIn: 0,
353359
tokensOut: 0,

src/ui/state/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export interface AgentState {
3737
toolCount: number;
3838
thinkingCount: number;
3939
loopRound?: number; // Current loop iteration number (e.g., 1, 2, 3...)
40+
loopReason?: string; // Reason for the current loop iteration
4041
stepIndex?: number; // Current step index (0-based)
4142
totalSteps?: number; // Total number of steps in workflow
4243
}
@@ -66,6 +67,7 @@ export interface LoopState {
6667
iteration: number;
6768
maxIterations: number;
6869
skipList: string[];
70+
reason?: string;
6971
}
7072

7173
/**

src/workflows/execution/workflow.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ export async function runWorkflow(options: RunWorkflowOptions = {}): Promise<voi
442442
iteration,
443443
maxIterations: step.module?.behavior?.type === 'loop' ? step.module.behavior.maxIterations ?? Infinity : Infinity,
444444
skipList: loopResult.decision.skipList || [],
445+
reason: loopResult.decision.reason,
445446
});
446447

447448
// Reset all agents that will be re-executed in the loop

0 commit comments

Comments
 (0)