mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-26 00:46:23 +02:00
feat: add background agents with scheduling support
- Add background task scheduling system with cron-based triggers - Add background-task-detail component for viewing agent status - Add agent schedule repo and state management - Update sidebar to show background agents section - Remove old workflow-authoring and workflow-run-ops skills - Add IPC handlers for agent schedule operations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
82db06d724
commit
c447a42d07
20 changed files with 1544 additions and 500 deletions
17
apps/x/packages/shared/src/agent-schedule-state.ts
Normal file
17
apps/x/packages/shared/src/agent-schedule-state.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import z from "zod";
|
||||
|
||||
// "triggered" is terminal state for once-schedules (will not run again)
|
||||
export const AgentScheduleStatus = z.enum(["scheduled", "running", "finished", "failed", "triggered"]);
|
||||
|
||||
export const AgentScheduleStateEntry = z.object({
|
||||
status: AgentScheduleStatus,
|
||||
startedAt: z.string().nullable(), // When current run started (for timeout detection)
|
||||
lastRunAt: z.string().nullable(), // ISO 8601 local datetime
|
||||
nextRunAt: z.string().nullable(), // ISO 8601 local datetime
|
||||
lastError: z.string().nullable(),
|
||||
runCount: z.number().default(0),
|
||||
});
|
||||
|
||||
export const AgentScheduleState = z.object({
|
||||
agents: z.record(z.string(), AgentScheduleStateEntry),
|
||||
});
|
||||
44
apps/x/packages/shared/src/agent-schedule.ts
Normal file
44
apps/x/packages/shared/src/agent-schedule.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import z from "zod";
|
||||
|
||||
// Cron schedule - runs at exact times defined by cron expression.
|
||||
// Examples:
|
||||
// - Every 5 minutes: "*/5 * * * *"
|
||||
// - Everyday at 8am: "0 8 * * *"
|
||||
// - Every Monday at 9am: "0 9 * * 1"
|
||||
export const CronSchedule = z.object({
|
||||
type: z.literal("cron"),
|
||||
expression: z.string(),
|
||||
});
|
||||
|
||||
// Window schedule - runs once during a time window.
|
||||
// The agent will run once at a random time within the specified window.
|
||||
// Examples:
|
||||
// - Daily between 8am and 10am: cron="0 0 * * *", startTime="08:00", endTime="10:00"
|
||||
// - Weekly on Monday between 9am-12pm: cron="0 0 * * 1", startTime="09:00", endTime="12:00"
|
||||
export const WindowSchedule = z.object({
|
||||
type: z.literal("window"),
|
||||
cron: z.string(), // Base frequency cron expression
|
||||
startTime: z.string(), // "HH:MM" format
|
||||
endTime: z.string(), // "HH:MM" format
|
||||
});
|
||||
|
||||
// Once schedule - runs exactly once at a specific time, then never again.
|
||||
// Examples:
|
||||
// - Run once at specific datetime: runAt="2024-02-05T10:30:00"
|
||||
export const OnceSchedule = z.object({
|
||||
type: z.literal("once"),
|
||||
runAt: z.string(), // ISO 8601 datetime (local time, e.g., "2024-02-05T10:30:00")
|
||||
});
|
||||
|
||||
export const ScheduleDefinition = z.union([CronSchedule, WindowSchedule, OnceSchedule]);
|
||||
|
||||
export const AgentScheduleEntry = z.object({
|
||||
schedule: ScheduleDefinition,
|
||||
enabled: z.boolean().optional().default(true),
|
||||
startingMessage: z.string().optional(), // Message sent to agent when run starts (defaults to "go")
|
||||
description: z.string().optional(), // Brief description of what the agent does (for UI display)
|
||||
});
|
||||
|
||||
export const AgentScheduleConfig = z.object({
|
||||
agents: z.record(z.string(), AgentScheduleEntry),
|
||||
});
|
||||
|
|
@ -4,4 +4,6 @@ export * as ipc from './ipc.js';
|
|||
export * as models from './models.js';
|
||||
export * as workspace from './workspace.js';
|
||||
export * as mcp from './mcp.js';
|
||||
export * as agentSchedule from './agent-schedule.js';
|
||||
export * as agentScheduleState from './agent-schedule-state.js';
|
||||
export { PrefixLogger };
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import { RelPath, Encoding, Stat, DirEntry, ReaddirOptions, ReadFileResult, Work
|
|||
import { ListToolsResponse } from './mcp.js';
|
||||
import { AskHumanResponsePayload, CreateRunOptions, Run, ListRunsResponse, ToolPermissionAuthorizePayload } from './runs.js';
|
||||
import { LlmModelConfig } from './models.js';
|
||||
import { AgentScheduleConfig, AgentScheduleEntry } from './agent-schedule.js';
|
||||
import { AgentScheduleState } from './agent-schedule-state.js';
|
||||
|
||||
// ============================================================================
|
||||
// Runtime Validation Schemas (Single Source of Truth)
|
||||
|
|
@ -353,6 +355,32 @@ const ipcSchemas = {
|
|||
}),
|
||||
res: z.null(),
|
||||
},
|
||||
// Agent schedule channels
|
||||
'agent-schedule:getConfig': {
|
||||
req: z.null(),
|
||||
res: AgentScheduleConfig,
|
||||
},
|
||||
'agent-schedule:getState': {
|
||||
req: z.null(),
|
||||
res: AgentScheduleState,
|
||||
},
|
||||
'agent-schedule:updateAgent': {
|
||||
req: z.object({
|
||||
agentName: z.string(),
|
||||
entry: AgentScheduleEntry,
|
||||
}),
|
||||
res: z.object({
|
||||
success: z.literal(true),
|
||||
}),
|
||||
},
|
||||
'agent-schedule:deleteAgent': {
|
||||
req: z.object({
|
||||
agentName: z.string(),
|
||||
}),
|
||||
res: z.object({
|
||||
success: z.literal(true),
|
||||
}),
|
||||
},
|
||||
} as const;
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue