feat(app): schedules screen - recurring agent spawns on mobile

A new Schedules tab lists every schedule across projects with its
interval, prompt, next/last run, and role/model badges; the operator
can create one (project, name prefix, interval, role, model backend,
prompt), pause/resume with a switch, and delete with confirmation.
Mirrors the web dashboard's Schedules page, including the model picker
added there. New clock/brain icons join the Lucide subset and the tab
bar grows to four tabs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01731mKtVzsfeT4Vi3TvkR48
This commit is contained in:
Claude
2026-08-13 13:12:26 +00:00
parent 41915b1a33
commit 31de11c07c
5 changed files with 443 additions and 3 deletions
+20
View File
@@ -12,6 +12,8 @@ export type IconName =
| "chevronDown"
| "home"
| "file"
| "clock"
| "brain"
| "settings"
| "x";
@@ -30,6 +32,24 @@ const paths: Record<IconName, React.ReactNode> = {
<Path d="M14 2v4a2 2 0 0 0 2 2h4" />
</>
),
clock: (
<>
<Circle cx="12" cy="12" r="10" />
<Path d="M12 6v6l4 2" />
</>
),
/* Lucide waypoints — the memory note graph. */
brain: (
<>
<Circle cx="12" cy="4.5" r="2.5" />
<Path d="m10.2 6.3-3.9 3.9" />
<Circle cx="4.5" cy="12" r="2.5" />
<Path d="M7 12h10" />
<Circle cx="19.5" cy="12" r="2.5" />
<Path d="m13.8 17.7 3.9-3.9" />
<Circle cx="12" cy="19.5" r="2.5" />
</>
),
settings: (
<>
<Path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" />
+4 -3
View File
@@ -7,13 +7,14 @@ import { Icon, type IconName } from "./Icon";
import { useAppState, type Screen } from "../state/AppState";
/**
* Bottom tab bar shown on the three primary screens (Fleet / Log / Settings).
* The design's fixed 24px bottom inset is replaced by the real home-indicator
* safe-area inset.
* Bottom tab bar shown on the primary screens (Fleet / Schedules / Log /
* Settings). The design's fixed 24px bottom inset is replaced by the real
* home-indicator safe-area inset.
*/
const TABS: { key: Screen; label: string; icon: IconName }[] = [
{ key: "fleet", label: "Fleet", icon: "home" },
{ key: "schedules", label: "Schedules", icon: "clock" },
{ key: "log", label: "Log", icon: "file" },
{ key: "settings", label: "Settings", icon: "settings" },
];