Files
fusion/packages/core/src/routine.ts

208 lines
7.7 KiB
TypeScript

/**
* Routine domain types for first-class recurring task automation.
*
* Routines are similar to ScheduledTasks but support multiple trigger modes
* (cron, webhook, API, manual) with configurable execution and catch-up policies.
*/
import type { AutomationRunResult, AutomationStep } from "./automation.js";
// ── Trigger Types ─────────────────────────────────────────────────────
/** Supported trigger modes for routines. */
export type RoutineTriggerType = "cron" | "webhook" | "api" | "manual";
/** Cron-based trigger with timezone support. */
export interface RoutineCronTrigger {
type: "cron";
/** Valid 5-field cron expression. */
cronExpression: string;
/** Optional IANA timezone (e.g., "America/New_York"). Defaults to UTC. */
timezone?: string;
}
/** Webhook trigger for external invocation. */
export interface RoutineWebhookTrigger {
type: "webhook";
/** URL path for the webhook (e.g., "/trigger/my-routine"). */
webhookPath: string;
/** Optional HMAC secret for signature verification. */
secret?: string;
}
/** API-triggered routine. */
export interface RoutineApiTrigger {
type: "api";
/** API endpoint that triggers this routine. */
endpoint: string;
}
/** Manually triggered routine. */
export interface RoutineManualTrigger {
type: "manual";
}
/** Union of all trigger types. */
export type RoutineTrigger =
| RoutineCronTrigger
| RoutineWebhookTrigger
| RoutineApiTrigger
| RoutineManualTrigger;
/** Discriminant helper for trigger type narrowing. */
export function isCronTrigger(trigger: RoutineTrigger): trigger is RoutineCronTrigger {
return trigger.type === "cron";
}
export function isWebhookTrigger(trigger: RoutineTrigger): trigger is RoutineWebhookTrigger {
return trigger.type === "webhook";
}
export function isApiTrigger(trigger: RoutineTrigger): trigger is RoutineApiTrigger {
return trigger.type === "api";
}
export function isManualTrigger(trigger: RoutineTrigger): trigger is RoutineManualTrigger {
return trigger.type === "manual";
}
// ── Execution Policies ─────────────────────────────────────────────────
/**
* Catch-up policy: what to do when a routine misses its scheduled run.
* - `run`: Execute the routine for each missed occurrence (catch-up runs).
* - `skip`: Skip missed occurrences entirely.
* - `run_one`: Execute once for the most recent missed occurrence only.
*/
export type RoutineCatchUpPolicy = "run" | "skip" | "run_one";
/**
* Execution policy: how to handle concurrent runs of the same routine.
* - `parallel`: Allow multiple concurrent executions.
* - `queue`: Queue subsequent runs, execute one at a time.
* - `reject`: Reject new runs if one is already in progress.
*/
export type RoutineExecutionPolicy = "parallel" | "queue" | "reject";
// ── Execution Result ───────────────────────────────────────────────────
/**
* Result of a single routine execution.
* Extends AutomationRunResult with routine-specific fields.
*/
export interface RoutineExecutionResult extends AutomationRunResult {
/** ID of the routine that was executed. */
routineId: string;
/** Whether a catch-up run was triggered. */
isCatchUp?: boolean;
/** Trigger type that fired this execution. */
triggerType?: RoutineTriggerType;
}
// ── Routine ───────────────────────────────────────────────────────────
/**
* A routine is a recurring automation with configurable triggers and policies.
*/
export interface Routine {
/** Unique identifier (UUID). */
id: string;
/** ID of the agent that executes this routine. */
agentId: string;
/** Human-readable name. */
name: string;
/** Optional description of what this routine does. */
description?: string;
/** The trigger configuration. */
trigger: RoutineTrigger;
/** Shell command to execute when this routine uses command action mode. */
command?: string;
/** Multi-step workflow to execute when present. */
steps?: AutomationStep[];
/** Per-routine execution timeout in milliseconds. */
timeoutMs?: number;
/** Catch-up policy for missed runs. Default: "run_one". */
catchUpPolicy: RoutineCatchUpPolicy;
/** Execution policy for concurrent runs. Default: "queue". */
executionPolicy: RoutineExecutionPolicy;
/** Whether this routine is currently enabled. */
enabled: boolean;
/** ISO-8601 timestamp of the last run start, if any. */
lastRunAt?: string;
/** Result of the most recent run, if any. */
lastRunResult?: RoutineExecutionResult;
/** ISO-8601 timestamp of the next scheduled run (for cron triggers). */
nextRunAt?: string;
/** Total number of runs executed. */
runCount: number;
/** History of recent run results (most recent first, capped at MAX_ROUTINE_RUN_HISTORY). */
runHistory: RoutineExecutionResult[];
/** Maximum number of catch-up executions when policy is "run". */
catchUpLimit?: number;
/** Optional cron expression stored directly for due-routine queries (derived from trigger). */
cronExpression?: string;
/** Scope of this routine: "global" (shared) or "project" (isolated). */
scope?: "global" | "project";
/** ISO-8601 timestamp of when this routine was created. */
createdAt: string;
/** ISO-8601 timestamp of when this routine was last updated. */
updatedAt: string;
}
// ── Input Types ───────────────────────────────────────────────────────
/** Input for creating a new routine. */
export interface RoutineCreateInput {
/** Human-readable name. Required. */
name: string;
/** ID of the agent that executes this routine. Required. */
agentId: string;
/** Optional description. */
description?: string;
/** Trigger configuration. Required. */
trigger: RoutineTrigger;
/** Shell command action. Required when `steps` is omitted and no agent is assigned. */
command?: string;
/** Multi-step workflow action. When provided, `command` is ignored. */
steps?: AutomationStep[];
/** Per-routine execution timeout in milliseconds. */
timeoutMs?: number;
/** Catch-up policy. Default: "run_one". */
catchUpPolicy?: RoutineCatchUpPolicy;
/** Execution policy. Default: "queue". */
executionPolicy?: RoutineExecutionPolicy;
/** Whether enabled. Default: true. */
enabled?: boolean;
/** Scope of this routine: "global" (shared) or "project" (isolated). Default: "project". */
scope?: "global" | "project";
}
/** Input for updating an existing routine. */
export interface RoutineUpdateInput {
/** Human-readable name. */
name?: string;
/** Optional description. */
description?: string;
/** Trigger configuration. */
trigger?: RoutineTrigger;
/** Shell command action. */
command?: string;
/** Multi-step workflow action. */
steps?: AutomationStep[];
/** Per-routine execution timeout in milliseconds. */
timeoutMs?: number;
/** Catch-up policy. */
catchUpPolicy?: RoutineCatchUpPolicy;
/** Execution policy. */
executionPolicy?: RoutineExecutionPolicy;
/** Whether enabled. */
enabled?: boolean;
/** Scope of this routine: "global" (shared) or "project" (isolated). */
scope?: "global" | "project";
}
// ── Constants ─────────────────────────────────────────────────────────
/** Maximum number of run history entries to retain per routine. */
export const MAX_ROUTINE_RUN_HISTORY = 50;