@agent-native/dispatch 0.30.5 → 0.31.1

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 (31) hide show
  1. package/dist/actions/provider-api-register.d.ts +11 -11
  2. package/dist/components/automation-details-panel.d.ts +8 -0
  3. package/dist/components/automation-details-panel.d.ts.map +1 -0
  4. package/dist/components/automation-details-panel.js +80 -0
  5. package/dist/components/automation-details-panel.js.map +1 -0
  6. package/dist/lib/automations.d.ts +12 -0
  7. package/dist/lib/automations.d.ts.map +1 -1
  8. package/dist/lib/automations.js +9 -0
  9. package/dist/lib/automations.js.map +1 -1
  10. package/dist/routes/pages/admin.d.ts.map +1 -1
  11. package/dist/routes/pages/admin.js +6 -1
  12. package/dist/routes/pages/admin.js.map +1 -1
  13. package/dist/routes/pages/automations.d.ts.map +1 -1
  14. package/dist/routes/pages/automations.js +59 -21
  15. package/dist/routes/pages/automations.js.map +1 -1
  16. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  17. package/dist/server/lib/app-creation-store.js +178 -14
  18. package/dist/server/lib/app-creation-store.js.map +1 -1
  19. package/package.json +3 -3
  20. package/src/components/automation-details-panel.tsx +420 -0
  21. package/src/lib/automations.spec.ts +19 -1
  22. package/src/lib/automations.ts +23 -0
  23. package/src/routes/pages/admin.tsx +8 -1
  24. package/src/routes/pages/automations.tsx +177 -97
  25. package/src/server/lib/app-creation-store.spec.ts +296 -19
  26. package/src/server/lib/app-creation-store.ts +218 -14
  27. package/dist/components/automation-run-history-dialog.d.ts +0 -9
  28. package/dist/components/automation-run-history-dialog.d.ts.map +0 -1
  29. package/dist/components/automation-run-history-dialog.js +0 -63
  30. package/dist/components/automation-run-history-dialog.js.map +0 -1
  31. package/src/components/automation-run-history-dialog.tsx +0 -247
@@ -1,247 +0,0 @@
1
- import { useActionQuery } from "@agent-native/core/client/hooks";
2
- import {
3
- IconAlertTriangle,
4
- IconClock,
5
- IconExternalLink,
6
- } from "@tabler/icons-react";
7
- import { Link } from "react-router";
8
-
9
- import {
10
- automationScopeLabel,
11
- automationTarget,
12
- } from "../lib/automation-display";
13
- import type { DispatchAutomationItem } from "../lib/automations";
14
- import { ActionQueryError } from "./action-query-error";
15
- import { Badge } from "./ui/badge";
16
- import {
17
- Dialog,
18
- DialogContent,
19
- DialogDescription,
20
- DialogHeader,
21
- DialogTitle,
22
- } from "./ui/dialog";
23
- import { Skeleton } from "./ui/skeleton";
24
-
25
- interface AutomationRun {
26
- id: string;
27
- runId: string | null;
28
- threadId: string | null;
29
- status: "running" | "success" | "error" | "interrupted";
30
- startedAt: number;
31
- finishedAt: number | null;
32
- error: string | null;
33
- }
34
-
35
- interface AutomationRunHistoryDialogProps {
36
- automation: DispatchAutomationItem | null;
37
- open: boolean;
38
- onOpenChange: (open: boolean) => void;
39
- }
40
-
41
- function runStatusVariant(
42
- status: AutomationRun["status"],
43
- ): "default" | "destructive" | "outline" {
44
- if (status === "error") return "destructive";
45
- if (status === "success") return "default";
46
- return "outline";
47
- }
48
-
49
- function formatTimestamp(value: number): string {
50
- const date = new Date(value);
51
- return Number.isNaN(date.getTime()) ? "Unknown time" : date.toLocaleString();
52
- }
53
-
54
- function formatDuration(run: AutomationRun): string | null {
55
- if (!run.finishedAt) return null;
56
- const seconds = Math.max(
57
- 0,
58
- Math.round((run.finishedAt - run.startedAt) / 1000),
59
- );
60
- return `${seconds}s`;
61
- }
62
-
63
- function runDebugPath(run: AutomationRun): string | null {
64
- const params = new URLSearchParams();
65
- if (run.runId) params.set("runId", run.runId);
66
- else if (run.threadId) params.set("threadId", run.threadId);
67
- else return null;
68
- return `/admin/thread-debug?${params.toString()}`;
69
- }
70
-
71
- export function AutomationRunHistoryDialog({
72
- automation,
73
- open,
74
- onOpenChange,
75
- }: AutomationRunHistoryDialogProps) {
76
- const scope =
77
- automation?.scope === "organization" ||
78
- automation?.owner.startsWith("__organization__:") ||
79
- automation?.owner === "__shared__"
80
- ? "organization"
81
- : "personal";
82
- const runsQuery = useActionQuery<AutomationRun[]>(
83
- "list-automation-runs",
84
- {
85
- name: automation?.name ?? "",
86
- scope,
87
- appId: automation?.appId ?? "dispatch",
88
- },
89
- {
90
- enabled: open && Boolean(automation),
91
- staleTime: 5_000,
92
- },
93
- );
94
- const runs = runsQuery.data ?? [];
95
-
96
- return (
97
- <Dialog open={open} onOpenChange={onOpenChange}>
98
- <DialogContent className="max-h-[85vh] max-w-2xl overflow-y-auto">
99
- <DialogHeader>
100
- <DialogTitle>{automation?.name ?? "Automation details"}</DialogTitle>
101
- <DialogDescription>
102
- {automation
103
- ? `${automationTarget(automation)} · ${automationScopeLabel(automation)}`
104
- : "Execution history"}
105
- </DialogDescription>
106
- </DialogHeader>
107
-
108
- {automation ? (
109
- <div className="space-y-4">
110
- <div className="grid grid-cols-2 gap-x-4 gap-y-3 rounded-lg border bg-muted/20 p-3 text-sm">
111
- <div>
112
- <div className="text-[11px] uppercase tracking-wide text-muted-foreground">
113
- Status
114
- </div>
115
- <div className="mt-1 font-medium">
116
- {automation.lastStatus ??
117
- (automation.enabled ? "ready" : "paused")}
118
- </div>
119
- </div>
120
- <div>
121
- <div className="text-[11px] uppercase tracking-wide text-muted-foreground">
122
- Last check
123
- </div>
124
- <div className="mt-1 font-medium">
125
- {automation.lastCheck
126
- ? formatTimestamp(new Date(automation.lastCheck).getTime())
127
- : "Not recorded"}
128
- </div>
129
- </div>
130
- <div>
131
- <div className="text-[11px] uppercase tracking-wide text-muted-foreground">
132
- Created by
133
- </div>
134
- <div className="mt-1 break-words font-medium">
135
- {automation.createdBy ?? "Unknown"}
136
- </div>
137
- </div>
138
- <div>
139
- <div className="text-[11px] uppercase tracking-wide text-muted-foreground">
140
- Timezone
141
- </div>
142
- <div className="mt-1 font-medium">
143
- {automation.timezone ?? "Account default"}
144
- </div>
145
- </div>
146
- </div>
147
-
148
- {automation.lastError ? (
149
- <div className="flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 p-3">
150
- <IconAlertTriangle className="mt-0.5 size-4 shrink-0 text-destructive" />
151
- <div className="min-w-0">
152
- <p className="text-sm font-medium text-destructive">
153
- Latest scheduler result
154
- </p>
155
- <p className="mt-1 break-words text-sm text-muted-foreground">
156
- {automation.lastError}
157
- </p>
158
- </div>
159
- </div>
160
- ) : null}
161
-
162
- <div>
163
- <div className="flex items-center justify-between gap-3">
164
- <div>
165
- <h3 className="text-sm font-semibold text-foreground">
166
- Past runs
167
- </h3>
168
- <p className="mt-1 text-xs text-muted-foreground">
169
- Only executions that actually started appear here. Blocked
170
- or skipped scheduler checks are shown above, not as fake
171
- runs.
172
- </p>
173
- </div>
174
- {runs.length > 0 ? (
175
- <Badge variant="outline">{runs.length} shown</Badge>
176
- ) : null}
177
- </div>
178
-
179
- <div className="mt-3">
180
- {runsQuery.isLoading ? (
181
- <div className="space-y-3 rounded-lg border p-4">
182
- {Array.from({ length: 3 }).map((_, index) => (
183
- <div key={index} className="space-y-2">
184
- <Skeleton className="h-4 w-2/3" />
185
- <Skeleton className="h-3 w-1/2" />
186
- </div>
187
- ))}
188
- </div>
189
- ) : runsQuery.isError ? (
190
- <ActionQueryError
191
- error={runsQuery.error}
192
- onRetry={() => void runsQuery.refetch()}
193
- />
194
- ) : runs.length === 0 ? (
195
- <div className="rounded-lg border border-dashed p-4 text-sm text-muted-foreground">
196
- This automation has not recorded an execution yet. If it is
197
- enabled but shows no runs, inspect the latest scheduler
198
- result and last check above.
199
- </div>
200
- ) : (
201
- <ul className="divide-y rounded-lg border">
202
- {runs.map((run) => {
203
- const debugPath = runDebugPath(run);
204
- const duration = formatDuration(run);
205
- return (
206
- <li key={run.id} className="space-y-2 p-3">
207
- <div className="flex flex-wrap items-center gap-2 text-sm">
208
- <Badge variant={runStatusVariant(run.status)}>
209
- {run.status}
210
- </Badge>
211
- <span className="text-muted-foreground">
212
- {formatTimestamp(run.startedAt)}
213
- </span>
214
- {duration ? (
215
- <span className="inline-flex items-center gap-1 text-xs text-muted-foreground">
216
- <IconClock className="size-3.5" />
217
- {duration}
218
- </span>
219
- ) : null}
220
- {debugPath ? (
221
- <Link
222
- to={debugPath}
223
- className="ml-auto inline-flex items-center gap-1 text-xs font-medium text-foreground underline-offset-4 hover:underline"
224
- >
225
- <IconExternalLink className="size-3.5" />
226
- Open debug
227
- </Link>
228
- ) : null}
229
- </div>
230
- {run.error ? (
231
- <p className="break-words text-sm text-destructive">
232
- {run.error}
233
- </p>
234
- ) : null}
235
- </li>
236
- );
237
- })}
238
- </ul>
239
- )}
240
- </div>
241
- </div>
242
- </div>
243
- ) : null}
244
- </DialogContent>
245
- </Dialog>
246
- );
247
- }