Add a Schedules screen to manage recurring agents (#1246)
* feat: add Schedules screen to manage scheduled agents Adds a Schedules section in the sidebar header (below Sessions) for viewing and managing new-agent schedules: recurring jobs that spawn an agent on a cron or interval cadence. - Borderless table showing provider icon, model, cadence, next run, and status, with row actions to edit, pause/resume, run now, and delete. - Create/edit sheet that reuses the agent provider/model/mode/working- directory pickers, plus an interval/cron cadence editor with presets, validation, and a UTC preview. - Responsive: hover-revealed row actions on desktop, an always-visible action menu on mobile. - Data layer over the existing schedule RPCs (list/create/update/pause/ resume/delete/run-once) with optimistic pause, resume, and delete. Scope is limited to new-agent schedules for now. * Make the schedule form controls visually consistent Merge the provider and model pickers into the single nested selector the draft screen uses, render it as a full-width field, mute the placeholder, proportion the cadence segmented controls, unify the cron preset chips, and route the sheet scroll through the themed scrollbar. * Address schedules review feedback * Translate schedule hook client fallback errors * Make schedules global and project scoped * Stabilize project settings transport E2E * Reset schedule model on cross-host project change * Reject malformed cron step expressions * Tighten schedules project query freshness * refactor(schedules): clean up review feedback * test(schedules): extract fake host setup * refactor(schedules): share cron expression parsing Use one structural cron parser for app previews and daemon cadence validation so the accepted grammar cannot drift between surfaces. Remove the unused host-scoped schedules redirect while keeping the global schedules route.
This commit is contained in:
@@ -76,6 +76,7 @@ export interface UseAgentFormStateResult {
|
||||
refreshProviderModels: (provider?: AgentProvider) => void;
|
||||
refetchProviderModelsIfStale: () => void;
|
||||
setProviderAndModelFromUser: (provider: AgentProvider, modelId: string) => void;
|
||||
clearProviderSelectionFromUser: () => void;
|
||||
workingDirIsEmpty: boolean;
|
||||
persistFormPreferences: () => Promise<void>;
|
||||
}
|
||||
@@ -404,6 +405,10 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
|
||||
],
|
||||
);
|
||||
|
||||
const clearProviderSelectionFromUser = useCallback(() => {
|
||||
dispatch({ type: "CLEAR_PROVIDER_SELECTION_FROM_USER" });
|
||||
}, []);
|
||||
|
||||
const setModeFromUser = useCallback(
|
||||
(modeId: string) => {
|
||||
dispatch({ type: "SET_MODE_FROM_USER", modeId });
|
||||
@@ -547,6 +552,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
|
||||
refreshProviderModels,
|
||||
refetchProviderModelsIfStale,
|
||||
setProviderAndModelFromUser,
|
||||
clearProviderSelectionFromUser,
|
||||
workingDirIsEmpty,
|
||||
persistFormPreferences,
|
||||
}),
|
||||
@@ -581,6 +587,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
|
||||
refreshProviderModels,
|
||||
refetchProviderModelsIfStale,
|
||||
setProviderAndModelFromUser,
|
||||
clearProviderSelectionFromUser,
|
||||
workingDirIsEmpty,
|
||||
persistFormPreferences,
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user