feat(KB-229): add multi-step scheduled tasks

- Add Step types to core data model (command, validation, approval steps)
- Update AutomationStore CRUD operations for step management
- Refactor CronRunner for sequential step execution with per-step config
- Add Dashboard API routes for step CRUD and step-aware schedule updates
- Create ScheduleStepsEditor component for visual step configuration
- Add StepTypeBadge component for step type visualization
- Update ScheduleCard and ScheduleForm to display and manage steps
- Add comprehensive test coverage for stores, runner, and components
- Add changeset for patch release
This commit is contained in:
gsxdsm
2026-03-31 05:14:30 -07:00
parent 62f87947f6
commit 7569af8a93
16 changed files with 2127 additions and 131 deletions

View File

@@ -18,7 +18,7 @@ import type {
WorkflowStepInput,
} from "@kb/core";
import type { PlanningQuestion, PlanningSummary, PlanningResponse } from "@kb/core";
import type { ScheduledTask, ScheduledTaskCreateInput, ScheduledTaskUpdateInput, AutomationRunResult } from "@kb/core";
import type { ScheduledTask, ScheduledTaskCreateInput, ScheduledTaskUpdateInput, AutomationRunResult, AutomationStep } from "@kb/core";
function looksLikeHtml(body: string): boolean {
const trimmed = body.trim();
@@ -1093,18 +1093,18 @@ export function fetchAutomation(id: string): Promise<ScheduledTask> {
}
export function createAutomation(input: ScheduledTaskCreateInput): Promise<ScheduledTask> {
const { name, description, scheduleType, cronExpression, command, enabled, timeoutMs } = input;
const { name, description, scheduleType, cronExpression, command, enabled, timeoutMs, steps } = input;
return api<ScheduledTask>("/automations", {
method: "POST",
body: JSON.stringify({ name, description, scheduleType, cronExpression, command, enabled, timeoutMs }),
body: JSON.stringify({ name, description, scheduleType, cronExpression, command, enabled, timeoutMs, steps }),
});
}
export function updateAutomation(id: string, updates: ScheduledTaskUpdateInput): Promise<ScheduledTask> {
const { name, description, scheduleType, cronExpression, command, enabled, timeoutMs } = updates;
const { name, description, scheduleType, cronExpression, command, enabled, timeoutMs, steps } = updates;
return api<ScheduledTask>(`/automations/${id}`, {
method: "PATCH",
body: JSON.stringify({ name, description, scheduleType, cronExpression, command, enabled, timeoutMs }),
body: JSON.stringify({ name, description, scheduleType, cronExpression, command, enabled, timeoutMs, steps }),
});
}
@@ -1126,6 +1126,13 @@ export function toggleAutomation(id: string): Promise<ScheduledTask> {
});
}
export function reorderAutomationSteps(id: string, stepIds: string[]): Promise<ScheduledTask> {
return api<ScheduledTask>(`/automations/${id}/steps/reorder`, {
method: "POST",
body: JSON.stringify({ stepIds }),
});
}
// ── Activity Log API ────────────────────────────────────────────
/** Re-export ActivityLogEntry type from core for convenience */