Compare commits

...

2 Commits

Author SHA1 Message Date
6c398eef64 live reporting commit requests, resume prints batching 2026-06-23 13:31:37 -04:00
496d1554be version bump 2026-06-21 13:30:39 -04:00
3 changed files with 123 additions and 11 deletions

View File

@@ -885,6 +885,20 @@ async function handleResume(
const mode = await selectExecutionMode(ctx, project, taskFile, config); const mode = await selectExecutionMode(ctx, project, taskFile, config);
const plan = buildPlanByMode(mode, project, completed); const plan = buildPlanByMode(mode, project, completed);
// Print remaining batches before executing
const formattedPlan = formatExecutionPlan(plan);
if (mode === "parallel") {
ctx.ui.notify(
`${formattedPlan}\n\nResuming parallel execution...`,
"info",
);
} else {
ctx.ui.notify(
`${formattedPlan}\n\nResuming sequential execution...`,
"info",
);
}
await executePlanBatches( await executePlanBatches(
plan, plan,
project, project,

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mikefreno/ralpi", "name": "@mikefreno/ralpi",
"version": "0.2.3", "version": "0.2.5",
"description": "Execute tasks from task files/PRD's using DAG-based dependency resolution with persistent progress tracking", "description": "Execute tasks from task files/PRD's using DAG-based dependency resolution with persistent progress tracking",
"keywords": [ "keywords": [
"pi-package", "pi-package",

View File

@@ -706,20 +706,115 @@ async function executeTask(
"```", "```",
].join("\n"); ].join("\n");
// ── Commit widget setup ──
const commitWidgetKey = `ralpi-commit-${task.id}`;
let commitFrameIndex = 0;
const commitToolCalls: ToolCallEntry[] = [];
let commitWidgetTui: { requestRender(): void } | null = null;
const commitHeader = `commit for ${task.id} · ${task.title}`;
const buildCommitLines = (
t: typeof ctx.ui.theme,
width?: number,
): string[] => {
const effectiveWidth = width || 74;
const frame = t.fg(
"accent",
SPINNER_FRAMES[commitFrameIndex % SPINNER_FRAMES.length],
);
const lines = [
truncateToWidth(`~ ${frame} ${commitHeader}`, effectiveWidth),
];
if (commitToolCalls.length > 0) {
if (commitToolCalls.length <= MAX_COLLAPSED) {
for (let i = 0; i < commitToolCalls.length; i++) {
const entry = commitToolCalls[i];
const isLast = i === commitToolCalls.length - 1;
const branch = isLast ? " └── " : " ├── ";
const tag = t.fg("accent", `[${entry.name}]`);
lines.push(
truncateToWidth(
`${branch}${tag} ${entry.label}`,
effectiveWidth,
),
);
}
} else {
const shown = commitToolCalls.slice(-MAX_COLLAPSED);
const remaining = commitToolCalls.length - shown.length;
lines.push(
truncateToWidth(
t.fg("dim", ` ├── …${remaining} earlier`),
effectiveWidth,
),
);
for (let i = 0; i < shown.length; i++) {
const entry = shown[i];
const isLast = i === shown.length - 1;
const branch = isLast ? " └── " : " ├── ";
const tag = t.fg("accent", `[${entry.name}]`);
lines.push(
truncateToWidth(
`${branch}${tag} ${entry.label}`,
effectiveWidth,
),
);
}
}
}
return lines;
};
ctx.ui.setWidget(commitWidgetKey, (tui, t) => {
commitWidgetTui = tui;
return {
render: (width?: number) => buildCommitLines(t, width),
invalidate: () => commitWidgetTui?.requestRender(),
};
});
const requestCommitRender = () =>
commitWidgetTui?.requestRender();
const commitSpinnerTimer = setInterval(() => {
commitFrameIndex =
(commitFrameIndex + 1) % SPINNER_FRAMES.length;
requestCommitRender();
}, 100);
// Use a short timeout for the commit session (60s should be enough) // Use a short timeout for the commit session (60s should be enough)
const commitTimeout = Math.min( const commitTimeout = Math.min(
60_000, 60_000,
config.execution.timeoutMs, config.execution.timeoutMs,
); );
const commitResult = await runAgentSession(
commitPrompt, let commitResult: Awaited<ReturnType<typeof runAgentSession>>;
projectDir,
commitTimeout, try {
undefined, commitResult = await runAgentSession(
undefined, commitPrompt,
currentModel, projectDir,
config.thinkingLevel, commitTimeout,
); (event) => {
if (event.type === "tool_execution_start") {
const label = formatToolArg(event.toolName, event.args);
commitToolCalls.push({
name: event.toolName,
label,
});
requestCommitRender();
}
},
undefined,
currentModel,
config.thinkingLevel,
);
} finally {
clearInterval(commitSpinnerTimer);
ctx.ui.setWidget(commitWidgetKey, undefined);
}
if (commitResult.success) { if (commitResult.success) {
// Re-capture commits made during this follow-up session // Re-capture commits made during this follow-up session
@@ -733,10 +828,13 @@ async function executeTask(
? `${finalCommitSummary}; ${newCommits.commitSummary}` ? `${finalCommitSummary}; ${newCommits.commitSummary}`
: newCommits.commitSummary; : newCommits.commitSummary;
} }
sendChatMessage?.(`✓ commit for ${task.id} · ${task.title}`); sendChatMessage?.(`✓ commit for ${task.id} · ${task.title}`, {
toolCalls: commitToolCalls,
});
} else { } else {
sendChatMessage?.( sendChatMessage?.(
`~ commit for ${task.id} · ${task.title} — follow-up commit session failed: ${commitResult.error}`, `~ commit for ${task.id} · ${task.title} — follow-up commit session failed: ${commitResult.error}`,
{ toolCalls: commitToolCalls },
); );
} }
} }