@agent-native/dispatch 0.13.10 → 0.13.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/dist/actions/navigate.js +1 -1
  2. package/dist/actions/navigate.js.map +1 -1
  3. package/dist/components/agents-panel.js +3 -3
  4. package/dist/components/agents-panel.js.map +1 -1
  5. package/dist/components/app-keys-popover.d.ts.map +1 -1
  6. package/dist/components/app-keys-popover.js +3 -3
  7. package/dist/components/app-keys-popover.js.map +1 -1
  8. package/dist/components/create-app-popover.d.ts.map +1 -1
  9. package/dist/components/create-app-popover.js +2 -2
  10. package/dist/components/create-app-popover.js.map +1 -1
  11. package/dist/components/dispatch-control-plane.d.ts.map +1 -1
  12. package/dist/components/dispatch-control-plane.js +19 -7
  13. package/dist/components/dispatch-control-plane.js.map +1 -1
  14. package/dist/components/dispatch-shell.d.ts.map +1 -1
  15. package/dist/components/dispatch-shell.js +2 -2
  16. package/dist/components/dispatch-shell.js.map +1 -1
  17. package/dist/components/layout/Header.js +2 -1
  18. package/dist/components/layout/Header.js.map +1 -1
  19. package/dist/components/layout/Layout.d.ts.map +1 -1
  20. package/dist/components/layout/Layout.js +12 -5
  21. package/dist/components/layout/Layout.js.map +1 -1
  22. package/dist/components/messaging-setup-panel.d.ts.map +1 -1
  23. package/dist/components/messaging-setup-panel.js +4 -4
  24. package/dist/components/messaging-setup-panel.js.map +1 -1
  25. package/dist/components/task-queue-health.d.ts +2 -0
  26. package/dist/components/task-queue-health.d.ts.map +1 -0
  27. package/dist/components/task-queue-health.js +49 -0
  28. package/dist/components/task-queue-health.js.map +1 -0
  29. package/dist/components/ui/accordion.js.map +1 -1
  30. package/dist/components/ui/alert-dialog.js +1 -1
  31. package/dist/components/ui/alert-dialog.js.map +1 -1
  32. package/dist/components/ui/alert.js.map +1 -1
  33. package/dist/components/ui/avatar.js.map +1 -1
  34. package/dist/components/ui/badge.js.map +1 -1
  35. package/dist/components/ui/breadcrumb.js.map +1 -1
  36. package/dist/components/ui/button.js.map +1 -1
  37. package/dist/components/ui/calendar.js +1 -1
  38. package/dist/components/ui/calendar.js.map +1 -1
  39. package/dist/components/ui/card.js.map +1 -1
  40. package/dist/components/ui/carousel.d.ts +2 -2
  41. package/dist/components/ui/carousel.d.ts.map +1 -1
  42. package/dist/components/ui/carousel.js +1 -1
  43. package/dist/components/ui/carousel.js.map +1 -1
  44. package/dist/components/ui/chart.js.map +1 -1
  45. package/dist/components/ui/checkbox.js.map +1 -1
  46. package/dist/components/ui/command.js +1 -1
  47. package/dist/components/ui/command.js.map +1 -1
  48. package/dist/components/ui/context-menu.js.map +1 -1
  49. package/dist/components/ui/dialog.js.map +1 -1
  50. package/dist/components/ui/drawer.js.map +1 -1
  51. package/dist/components/ui/dropdown-menu.js.map +1 -1
  52. package/dist/components/ui/form.js +1 -1
  53. package/dist/components/ui/form.js.map +1 -1
  54. package/dist/components/ui/hover-card.js.map +1 -1
  55. package/dist/components/ui/input-otp.js.map +1 -1
  56. package/dist/components/ui/input.js.map +1 -1
  57. package/dist/components/ui/label.js.map +1 -1
  58. package/dist/components/ui/menubar.js.map +1 -1
  59. package/dist/components/ui/navigation-menu.js.map +1 -1
  60. package/dist/components/ui/pagination.d.ts +1 -1
  61. package/dist/components/ui/pagination.d.ts.map +1 -1
  62. package/dist/components/ui/pagination.js +1 -1
  63. package/dist/components/ui/pagination.js.map +1 -1
  64. package/dist/components/ui/popover.js.map +1 -1
  65. package/dist/components/ui/progress.js.map +1 -1
  66. package/dist/components/ui/radio-group.js.map +1 -1
  67. package/dist/components/ui/resizable.js.map +1 -1
  68. package/dist/components/ui/scroll-area.js.map +1 -1
  69. package/dist/components/ui/select.js.map +1 -1
  70. package/dist/components/ui/separator.js.map +1 -1
  71. package/dist/components/ui/sheet.js.map +1 -1
  72. package/dist/components/ui/sidebar.d.ts +2 -2
  73. package/dist/components/ui/sidebar.d.ts.map +1 -1
  74. package/dist/components/ui/sidebar.js +6 -6
  75. package/dist/components/ui/sidebar.js.map +1 -1
  76. package/dist/components/ui/skeleton.js.map +1 -1
  77. package/dist/components/ui/slider.js.map +1 -1
  78. package/dist/components/ui/sonner.js.map +1 -1
  79. package/dist/components/ui/spinner.js.map +1 -1
  80. package/dist/components/ui/switch.js.map +1 -1
  81. package/dist/components/ui/table.js.map +1 -1
  82. package/dist/components/ui/tabs.js.map +1 -1
  83. package/dist/components/ui/textarea.js.map +1 -1
  84. package/dist/components/ui/toast.js.map +1 -1
  85. package/dist/components/ui/toaster.js +1 -1
  86. package/dist/components/ui/toaster.js.map +1 -1
  87. package/dist/components/ui/toggle-group.js +1 -1
  88. package/dist/components/ui/toggle-group.js.map +1 -1
  89. package/dist/components/ui/toggle.js.map +1 -1
  90. package/dist/components/ui/tooltip.js.map +1 -1
  91. package/dist/components/ui/use-toast.d.ts.map +1 -1
  92. package/dist/components/ui/use-toast.js.map +1 -1
  93. package/dist/components/workspace-app-card.d.ts.map +1 -1
  94. package/dist/components/workspace-app-card.js +10 -10
  95. package/dist/components/workspace-app-card.js.map +1 -1
  96. package/dist/components/workspace-resource-effective-stack.js +1 -1
  97. package/dist/components/workspace-resource-effective-stack.js.map +1 -1
  98. package/dist/components/workspace-resource-impact-preview.d.ts.map +1 -1
  99. package/dist/components/workspace-resource-impact-preview.js +2 -2
  100. package/dist/components/workspace-resource-impact-preview.js.map +1 -1
  101. package/dist/hooks/use-navigation-state.js +5 -0
  102. package/dist/hooks/use-navigation-state.js.map +1 -1
  103. package/dist/hooks/use-toast.d.ts.map +1 -1
  104. package/dist/hooks/use-toast.js.map +1 -1
  105. package/dist/lib/automation-display.d.ts +13 -0
  106. package/dist/lib/automation-display.d.ts.map +1 -0
  107. package/dist/lib/automation-display.js +62 -0
  108. package/dist/lib/automation-display.js.map +1 -0
  109. package/dist/lib/task-queue.d.ts +19 -0
  110. package/dist/lib/task-queue.d.ts.map +1 -0
  111. package/dist/lib/task-queue.js +54 -0
  112. package/dist/lib/task-queue.js.map +1 -0
  113. package/dist/routes/index.d.ts.map +1 -1
  114. package/dist/routes/index.js +1 -0
  115. package/dist/routes/index.js.map +1 -1
  116. package/dist/routes/pages/_index.js.map +1 -1
  117. package/dist/routes/pages/agents.d.ts.map +1 -1
  118. package/dist/routes/pages/agents.js +1 -1
  119. package/dist/routes/pages/agents.js.map +1 -1
  120. package/dist/routes/pages/approval.js.map +1 -1
  121. package/dist/routes/pages/approvals.js.map +1 -1
  122. package/dist/routes/pages/apps.$appId.js.map +1 -1
  123. package/dist/routes/pages/apps.js.map +1 -1
  124. package/dist/routes/pages/audit.js.map +1 -1
  125. package/dist/routes/pages/automations.d.ts +5 -0
  126. package/dist/routes/pages/automations.d.ts.map +1 -0
  127. package/dist/routes/pages/automations.js +106 -0
  128. package/dist/routes/pages/automations.js.map +1 -0
  129. package/dist/routes/pages/chat.js.map +1 -1
  130. package/dist/routes/pages/destinations.d.ts.map +1 -1
  131. package/dist/routes/pages/destinations.js +31 -27
  132. package/dist/routes/pages/destinations.js.map +1 -1
  133. package/dist/routes/pages/dreams.d.ts.map +1 -1
  134. package/dist/routes/pages/dreams.js +1 -1
  135. package/dist/routes/pages/dreams.js.map +1 -1
  136. package/dist/routes/pages/identities.js.map +1 -1
  137. package/dist/routes/pages/integrations.js.map +1 -1
  138. package/dist/routes/pages/messaging.js.map +1 -1
  139. package/dist/routes/pages/metrics.js.map +1 -1
  140. package/dist/routes/pages/new-app.js.map +1 -1
  141. package/dist/routes/pages/overview.d.ts +2 -2
  142. package/dist/routes/pages/overview.js.map +1 -1
  143. package/dist/routes/pages/settings.d.ts.map +1 -1
  144. package/dist/routes/pages/settings.js +2 -2
  145. package/dist/routes/pages/settings.js.map +1 -1
  146. package/dist/routes/pages/thread-debug.d.ts.map +1 -1
  147. package/dist/routes/pages/thread-debug.js +1 -1
  148. package/dist/routes/pages/thread-debug.js.map +1 -1
  149. package/dist/routes/pages/vault.d.ts.map +1 -1
  150. package/dist/routes/pages/vault.js +1 -1
  151. package/dist/routes/pages/vault.js.map +1 -1
  152. package/dist/routes/pages/workspace.d.ts.map +1 -1
  153. package/dist/routes/pages/workspace.js +1 -1
  154. package/dist/routes/pages/workspace.js.map +1 -1
  155. package/dist/server/lib/pre-auth-routing.d.ts.map +1 -1
  156. package/dist/server/lib/pre-auth-routing.js +1 -0
  157. package/dist/server/lib/pre-auth-routing.js.map +1 -1
  158. package/package.json +7 -7
  159. package/src/actions/navigate.ts +1 -1
  160. package/src/components/agents-panel.tsx +3 -3
  161. package/src/components/app-keys-popover.tsx +3 -7
  162. package/src/components/create-app-popover.tsx +2 -6
  163. package/src/components/dispatch-control-plane.tsx +48 -7
  164. package/src/components/dispatch-shell.tsx +2 -6
  165. package/src/components/layout/Header.tsx +2 -2
  166. package/src/components/layout/Layout.tsx +13 -15
  167. package/src/components/messaging-setup-panel.tsx +4 -8
  168. package/src/components/task-queue-health.tsx +166 -0
  169. package/src/components/ui/accordion.tsx +1 -1
  170. package/src/components/ui/alert-dialog.tsx +2 -2
  171. package/src/components/ui/alert.tsx +1 -1
  172. package/src/components/ui/avatar.tsx +1 -1
  173. package/src/components/ui/badge.tsx +1 -1
  174. package/src/components/ui/breadcrumb.tsx +1 -1
  175. package/src/components/ui/button.tsx +1 -1
  176. package/src/components/ui/calendar.tsx +2 -2
  177. package/src/components/ui/card.tsx +1 -1
  178. package/src/components/ui/carousel.tsx +2 -2
  179. package/src/components/ui/chart.tsx +1 -1
  180. package/src/components/ui/checkbox.tsx +1 -1
  181. package/src/components/ui/command.tsx +2 -2
  182. package/src/components/ui/context-menu.tsx +1 -1
  183. package/src/components/ui/dialog.tsx +1 -1
  184. package/src/components/ui/drawer.tsx +1 -1
  185. package/src/components/ui/dropdown-menu.tsx +1 -1
  186. package/src/components/ui/form.tsx +2 -2
  187. package/src/components/ui/hover-card.tsx +1 -1
  188. package/src/components/ui/input-otp.tsx +1 -1
  189. package/src/components/ui/input.tsx +1 -1
  190. package/src/components/ui/label.tsx +1 -1
  191. package/src/components/ui/menubar.tsx +1 -1
  192. package/src/components/ui/navigation-menu.tsx +1 -1
  193. package/src/components/ui/pagination.tsx +2 -2
  194. package/src/components/ui/popover.tsx +1 -1
  195. package/src/components/ui/progress.tsx +1 -1
  196. package/src/components/ui/radio-group.tsx +1 -1
  197. package/src/components/ui/resizable.tsx +1 -1
  198. package/src/components/ui/scroll-area.tsx +1 -1
  199. package/src/components/ui/select.tsx +1 -1
  200. package/src/components/ui/separator.tsx +1 -1
  201. package/src/components/ui/sheet.tsx +1 -1
  202. package/src/components/ui/sidebar.tsx +8 -13
  203. package/src/components/ui/skeleton.tsx +1 -1
  204. package/src/components/ui/slider.tsx +1 -1
  205. package/src/components/ui/sonner.tsx +1 -1
  206. package/src/components/ui/spinner.tsx +1 -1
  207. package/src/components/ui/switch.tsx +1 -1
  208. package/src/components/ui/table.tsx +1 -1
  209. package/src/components/ui/tabs.tsx +1 -1
  210. package/src/components/ui/textarea.tsx +1 -1
  211. package/src/components/ui/toast.tsx +1 -1
  212. package/src/components/ui/toaster.tsx +2 -2
  213. package/src/components/ui/toggle-group.tsx +2 -2
  214. package/src/components/ui/toggle.tsx +1 -1
  215. package/src/components/ui/tooltip.tsx +1 -1
  216. package/src/components/ui/use-toast.ts +1 -1
  217. package/src/components/workspace-app-card.tsx +16 -20
  218. package/src/components/workspace-resource-effective-stack.tsx +2 -2
  219. package/src/components/workspace-resource-impact-preview.tsx +2 -3
  220. package/src/hooks/use-navigation-state.spec.ts +7 -0
  221. package/src/hooks/use-navigation-state.ts +4 -0
  222. package/src/hooks/use-toast.ts +1 -1
  223. package/src/lib/automation-display.spec.ts +95 -0
  224. package/src/lib/automation-display.ts +70 -0
  225. package/src/lib/task-queue.spec.ts +57 -0
  226. package/src/lib/task-queue.ts +72 -0
  227. package/src/routes/index.ts +1 -0
  228. package/src/routes/pages/_index.tsx +1 -1
  229. package/src/routes/pages/agents.tsx +8 -5
  230. package/src/routes/pages/approval.tsx +4 -4
  231. package/src/routes/pages/approvals.tsx +4 -4
  232. package/src/routes/pages/apps.$appId.tsx +5 -5
  233. package/src/routes/pages/apps.tsx +8 -8
  234. package/src/routes/pages/audit.tsx +1 -1
  235. package/src/routes/pages/automations.tsx +280 -0
  236. package/src/routes/pages/chat.tsx +1 -1
  237. package/src/routes/pages/destinations.tsx +163 -154
  238. package/src/routes/pages/dreams.tsx +22 -18
  239. package/src/routes/pages/identities.tsx +2 -2
  240. package/src/routes/pages/integrations.tsx +8 -8
  241. package/src/routes/pages/messaging.tsx +2 -2
  242. package/src/routes/pages/metrics.tsx +6 -6
  243. package/src/routes/pages/new-app.tsx +1 -1
  244. package/src/routes/pages/overview.tsx +1 -1
  245. package/src/routes/pages/settings.tsx +37 -6
  246. package/src/routes/pages/thread-debug.tsx +14 -9
  247. package/src/routes/pages/vault.tsx +17 -12
  248. package/src/routes/pages/workspace.tsx +17 -12
  249. package/src/server/lib/pre-auth-routing.ts +1 -0
@@ -7,14 +7,14 @@ import {
7
7
  import { useEffect, useMemo } from "react";
8
8
  import { Link, useParams } from "react-router";
9
9
 
10
- import { DispatchShell } from "@/components/dispatch-shell";
11
- import { Badge } from "@/components/ui/badge";
12
- import { Button } from "@/components/ui/button";
13
- import { Skeleton } from "@/components/ui/skeleton";
10
+ import { DispatchShell } from "../../components/dispatch-shell";
11
+ import { Badge } from "../../components/ui/badge";
12
+ import { Button } from "../../components/ui/button";
13
+ import { Skeleton } from "../../components/ui/skeleton";
14
14
  import {
15
15
  workspaceAppHref,
16
16
  type WorkspaceAppSummary,
17
- } from "@/lib/workspace-apps";
17
+ } from "../../lib/workspace-apps";
18
18
 
19
19
  export function meta() {
20
20
  return [{ title: "Workspace app - Dispatch" }];
@@ -25,18 +25,18 @@ import {
25
25
  import { useState } from "react";
26
26
  import { toast } from "sonner";
27
27
 
28
- import { CreateAppPopover } from "@/components/create-app-popover";
29
- import { DispatchShell } from "@/components/dispatch-shell";
30
- import { Button } from "@/components/ui/button";
28
+ import { CreateAppPopover } from "../../components/create-app-popover";
29
+ import { DispatchShell } from "../../components/dispatch-shell";
30
+ import { Button } from "../../components/ui/button";
31
31
  import {
32
32
  Collapsible,
33
33
  CollapsibleContent,
34
34
  CollapsibleTrigger,
35
- } from "@/components/ui/collapsible";
36
- import { Skeleton } from "@/components/ui/skeleton";
37
- import { WorkspaceAppCard } from "@/components/workspace-app-card";
38
- import { cn } from "@/lib/utils";
39
- import type { WorkspaceAppSummary } from "@/lib/workspace-apps";
35
+ } from "../../components/ui/collapsible";
36
+ import { Skeleton } from "../../components/ui/skeleton";
37
+ import { WorkspaceAppCard } from "../../components/workspace-app-card";
38
+ import { cn } from "../../lib/utils";
39
+ import type { WorkspaceAppSummary } from "../../lib/workspace-apps";
40
40
 
41
41
  export function meta() {
42
42
  return [{ title: "Apps — Dispatch" }];
@@ -1,6 +1,6 @@
1
1
  import { useActionQuery } from "@agent-native/core/client";
2
2
 
3
- import { DispatchShell } from "@/components/dispatch-shell";
3
+ import { DispatchShell } from "../../components/dispatch-shell";
4
4
 
5
5
  export function meta() {
6
6
  return [{ title: "Audit — Dispatch" }];
@@ -0,0 +1,280 @@
1
+ import {
2
+ PromptComposer,
3
+ sendToAgentChat,
4
+ useChangeVersions,
5
+ } from "@agent-native/core/client";
6
+ import { IconPlus, IconSettingsAutomation } from "@tabler/icons-react";
7
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
8
+ import { useMemo, useState } from "react";
9
+ import { toast } from "sonner";
10
+
11
+ import { DispatchShell } from "../../components/dispatch-shell";
12
+ import { Badge } from "../../components/ui/badge";
13
+ import { Button } from "../../components/ui/button";
14
+ import {
15
+ Popover,
16
+ PopoverContent,
17
+ PopoverTrigger,
18
+ } from "../../components/ui/popover";
19
+ import { Skeleton } from "../../components/ui/skeleton";
20
+ import { Switch } from "../../components/ui/switch";
21
+ import {
22
+ automationIdentity,
23
+ automationLastRun,
24
+ automationNextRun,
25
+ automationStatus,
26
+ automationTarget,
27
+ sortAutomations,
28
+ type AutomationStatusTone,
29
+ } from "../../lib/automation-display";
30
+ import {
31
+ listDispatchAutomations,
32
+ setDispatchAutomationEnabled,
33
+ type DispatchAutomationItem,
34
+ type SetDispatchAutomationEnabledInput,
35
+ } from "../../lib/automations";
36
+ import { cn } from "../../lib/utils";
37
+
38
+ const AUTOMATIONS_QUERY_KEY = ["dispatch-automations"] as const;
39
+
40
+ export function meta() {
41
+ return [{ title: "Automations — Dispatch" }];
42
+ }
43
+
44
+ function StatusDot({ tone }: { tone: AutomationStatusTone }) {
45
+ return (
46
+ <span
47
+ className={cn(
48
+ "size-2 shrink-0 rounded-full",
49
+ tone === "success" && "bg-emerald-500",
50
+ tone === "warning" && "bg-amber-500",
51
+ tone === "danger" && "bg-destructive",
52
+ tone === "muted" && "bg-muted-foreground/35",
53
+ tone === "default" && "bg-primary",
54
+ )}
55
+ />
56
+ );
57
+ }
58
+
59
+ function useAutomations() {
60
+ const version = useChangeVersions(["action", "screen-refresh"]);
61
+ return useQuery<DispatchAutomationItem[]>({
62
+ queryKey: [...AUTOMATIONS_QUERY_KEY, version],
63
+ queryFn: listDispatchAutomations,
64
+ placeholderData: (prev) => prev,
65
+ refetchInterval: 15_000,
66
+ staleTime: 5_000,
67
+ });
68
+ }
69
+
70
+ function useToggleAutomation() {
71
+ const queryClient = useQueryClient();
72
+
73
+ return useMutation({
74
+ mutationFn: setDispatchAutomationEnabled,
75
+ onMutate: async (input: SetDispatchAutomationEnabledInput) => {
76
+ await queryClient.cancelQueries({ queryKey: AUTOMATIONS_QUERY_KEY });
77
+ const snapshots = queryClient.getQueriesData<DispatchAutomationItem[]>({
78
+ queryKey: AUTOMATIONS_QUERY_KEY,
79
+ });
80
+
81
+ queryClient.setQueriesData<DispatchAutomationItem[]>(
82
+ { queryKey: AUTOMATIONS_QUERY_KEY },
83
+ (rows) =>
84
+ rows?.map((item) =>
85
+ automationIdentity(item) === automationIdentity(input)
86
+ ? { ...item, enabled: input.enabled }
87
+ : item,
88
+ ),
89
+ );
90
+
91
+ return { snapshots };
92
+ },
93
+ onError: (err, _input, context) => {
94
+ for (const [queryKey, data] of context?.snapshots ?? []) {
95
+ queryClient.setQueryData(queryKey, data);
96
+ }
97
+ toast.error(
98
+ `Could not update automation: ${
99
+ err instanceof Error ? err.message : String(err)
100
+ }`,
101
+ );
102
+ },
103
+ onSuccess: (updated) => {
104
+ queryClient.setQueriesData<DispatchAutomationItem[]>(
105
+ { queryKey: AUTOMATIONS_QUERY_KEY },
106
+ (rows) =>
107
+ rows?.map((item) =>
108
+ automationIdentity(item) === automationIdentity(updated)
109
+ ? updated
110
+ : item,
111
+ ),
112
+ );
113
+ },
114
+ onSettled: () => {
115
+ void queryClient.invalidateQueries({ queryKey: AUTOMATIONS_QUERY_KEY });
116
+ },
117
+ });
118
+ }
119
+
120
+ function CreateAutomationButton() {
121
+ const [open, setOpen] = useState(false);
122
+ const [scope, setScope] = useState<"personal" | "organization">("personal");
123
+
124
+ function handleSubmit(text: string) {
125
+ const trimmed = text.trim();
126
+ if (!trimmed) return;
127
+ window.dispatchEvent(
128
+ new CustomEvent("agent-panel:set-mode", {
129
+ detail: { mode: "chat" },
130
+ }),
131
+ );
132
+ sendToAgentChat({
133
+ message: trimmed,
134
+ context: `The user wants to create a new automation. Scope: ${scope}. Use manage-automations with action=define to create it. Ask clarifying questions if needed about what event to trigger on, conditions, and what actions to take.`,
135
+ submit: true,
136
+ newTab: true,
137
+ });
138
+ setOpen(false);
139
+ }
140
+
141
+ return (
142
+ <Popover open={open} onOpenChange={setOpen}>
143
+ <PopoverTrigger asChild>
144
+ <Button size="sm">
145
+ <IconPlus size={14} />
146
+ New automation
147
+ </Button>
148
+ </PopoverTrigger>
149
+ <PopoverContent align="end" className="w-[min(100vw-2rem,24rem)] p-3">
150
+ <p className="pb-2 text-sm font-semibold text-foreground">
151
+ New automation
152
+ </p>
153
+ <PromptComposer
154
+ autoFocus
155
+ placeholder="Describe what you want to automate..."
156
+ draftScope="dispatch-automations:create"
157
+ onSubmit={handleSubmit}
158
+ />
159
+ <select
160
+ value={scope}
161
+ onChange={(event) =>
162
+ setScope(event.target.value as "personal" | "organization")
163
+ }
164
+ className="mt-2 w-full cursor-pointer rounded-md border border-input bg-background px-3 py-1.5 text-xs text-foreground"
165
+ >
166
+ <option value="personal">Personal</option>
167
+ <option value="organization">Organization</option>
168
+ </select>
169
+ </PopoverContent>
170
+ </Popover>
171
+ );
172
+ }
173
+
174
+ export default function AutomationsRoute() {
175
+ const automationsQuery = useAutomations();
176
+ const toggleAutomation = useToggleAutomation();
177
+ const automations = automationsQuery.data ?? [];
178
+ const ordered = useMemo(() => sortAutomations(automations), [automations]);
179
+ const enabledCount = automations.filter((item) => item.enabled).length;
180
+ const errorCount = automations.filter(
181
+ (item) => item.enabled && item.lastStatus === "error",
182
+ ).length;
183
+ const pendingToggleIdentity = toggleAutomation.isPending
184
+ ? toggleAutomation.variables
185
+ ? automationIdentity(toggleAutomation.variables)
186
+ : null
187
+ : null;
188
+
189
+ return (
190
+ <DispatchShell
191
+ title="Automations"
192
+ description="See scheduled and event-triggered jobs, pause them, or ask the agent to create one."
193
+ >
194
+ <section className="flex flex-col gap-4">
195
+ <div className="flex flex-wrap items-center justify-between gap-3">
196
+ <div className="flex min-w-0 items-center gap-2 text-sm text-muted-foreground">
197
+ <IconSettingsAutomation size={16} className="shrink-0" />
198
+ <span>
199
+ {enabledCount} enabled
200
+ {errorCount > 0 ? ` · ${errorCount} errors` : ""}
201
+ </span>
202
+ </div>
203
+ <CreateAutomationButton />
204
+ </div>
205
+
206
+ <div className="divide-y rounded-lg border bg-card">
207
+ {automationsQuery.isLoading && ordered.length === 0 ? (
208
+ Array.from({ length: 4 }).map((_, index) => (
209
+ <div key={index} className="px-4 py-3">
210
+ <Skeleton className="h-4 w-40" />
211
+ <Skeleton className="mt-2 h-3 w-28" />
212
+ </div>
213
+ ))
214
+ ) : ordered.length > 0 ? (
215
+ ordered.map((item) => {
216
+ const status = automationStatus(item);
217
+ const canUpdate = item.canUpdate !== false;
218
+ const isToggling =
219
+ pendingToggleIdentity === automationIdentity(item);
220
+ return (
221
+ <div
222
+ key={item.id}
223
+ className="grid grid-cols-[minmax(0,1fr)_auto] gap-3 px-4 py-3"
224
+ >
225
+ <div className="min-w-0">
226
+ <div className="flex min-w-0 items-center gap-2">
227
+ <StatusDot tone={status.tone} />
228
+ <span className="truncate text-sm font-medium text-foreground">
229
+ {item.name}
230
+ </span>
231
+ </div>
232
+ <div className="mt-1 truncate text-xs text-muted-foreground">
233
+ {automationTarget(item)}
234
+ </div>
235
+ <div className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground">
236
+ <span>Last {automationLastRun(item)}</span>
237
+ <span>Next {automationNextRun(item)}</span>
238
+ </div>
239
+ {item.lastError ? (
240
+ <div className="mt-1 truncate text-xs text-destructive">
241
+ {item.lastError}
242
+ </div>
243
+ ) : null}
244
+ </div>
245
+ <div className="flex flex-col items-end gap-2">
246
+ <Badge
247
+ variant={
248
+ status.tone === "danger" ? "destructive" : "outline"
249
+ }
250
+ className="h-5"
251
+ >
252
+ {status.label}
253
+ </Badge>
254
+ <Switch
255
+ checked={!!item.enabled}
256
+ disabled={!canUpdate || isToggling}
257
+ aria-label={`${item.enabled ? "Disable" : "Enable"} automation ${item.name}`}
258
+ onCheckedChange={(checked) =>
259
+ toggleAutomation.mutate({
260
+ owner: item.owner,
261
+ path: item.path,
262
+ enabled: checked,
263
+ })
264
+ }
265
+ />
266
+ </div>
267
+ </div>
268
+ );
269
+ })
270
+ ) : (
271
+ <div className="px-4 py-10 text-center text-sm text-muted-foreground">
272
+ No automations yet. Create one here, or ask Dispatch to set up a
273
+ scheduled or event-triggered job.
274
+ </div>
275
+ )}
276
+ </div>
277
+ </section>
278
+ </DispatchShell>
279
+ );
280
+ }
@@ -13,7 +13,7 @@ import {
13
13
  } from "react";
14
14
  import { useLocation, useNavigate } from "react-router";
15
15
 
16
- import { submitOverviewPrompt } from "@/lib/overview-chat";
16
+ import { submitOverviewPrompt } from "../../lib/overview-chat";
17
17
 
18
18
  function chatThreadPath(threadId: string | null): string {
19
19
  return threadId ? `/chat/${encodeURIComponent(threadId)}` : "/chat";