@agent-native/dispatch 0.15.18 → 0.15.20

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 (81) hide show
  1. package/dist/components/agents-panel.js +1 -1
  2. package/dist/components/agents-panel.js.map +1 -1
  3. package/dist/components/dispatch-control-plane.d.ts.map +1 -1
  4. package/dist/components/dispatch-control-plane.js +1 -1
  5. package/dist/components/dispatch-control-plane.js.map +1 -1
  6. package/dist/components/layout/Layout.d.ts.map +1 -1
  7. package/dist/components/layout/Layout.js +11 -7
  8. package/dist/components/layout/Layout.js.map +1 -1
  9. package/dist/components/messaging-setup-panel.js +1 -1
  10. package/dist/components/messaging-setup-panel.js.map +1 -1
  11. package/dist/components/task-queue-health.js +1 -1
  12. package/dist/components/task-queue-health.js.map +1 -1
  13. package/dist/components/ui/button.d.ts.map +1 -1
  14. package/dist/components/ui/button.js +1 -1
  15. package/dist/components/ui/button.js.map +1 -1
  16. package/dist/components/ui/card.js +1 -1
  17. package/dist/components/ui/card.js.map +1 -1
  18. package/dist/components/workspace-app-card.js +1 -1
  19. package/dist/components/workspace-app-card.js.map +1 -1
  20. package/dist/components/workspace-template-card.js +1 -1
  21. package/dist/components/workspace-template-card.js.map +1 -1
  22. package/dist/routes/pages/$appId.js +1 -1
  23. package/dist/routes/pages/$appId.js.map +1 -1
  24. package/dist/routes/pages/agents.js +1 -1
  25. package/dist/routes/pages/agents.js.map +1 -1
  26. package/dist/routes/pages/approval.js +4 -4
  27. package/dist/routes/pages/approval.js.map +1 -1
  28. package/dist/routes/pages/approvals.js +2 -2
  29. package/dist/routes/pages/approvals.js.map +1 -1
  30. package/dist/routes/pages/apps.$appId.js +1 -1
  31. package/dist/routes/pages/apps.$appId.js.map +1 -1
  32. package/dist/routes/pages/apps.js +3 -3
  33. package/dist/routes/pages/apps.js.map +1 -1
  34. package/dist/routes/pages/audit.js +1 -1
  35. package/dist/routes/pages/audit.js.map +1 -1
  36. package/dist/routes/pages/automations.js +1 -1
  37. package/dist/routes/pages/automations.js.map +1 -1
  38. package/dist/routes/pages/destinations.js +2 -2
  39. package/dist/routes/pages/destinations.js.map +1 -1
  40. package/dist/routes/pages/dreams.js +5 -5
  41. package/dist/routes/pages/dreams.js.map +1 -1
  42. package/dist/routes/pages/identities.js +1 -1
  43. package/dist/routes/pages/identities.js.map +1 -1
  44. package/dist/routes/pages/integrations.js +2 -2
  45. package/dist/routes/pages/integrations.js.map +1 -1
  46. package/dist/routes/pages/metrics.js +4 -4
  47. package/dist/routes/pages/metrics.js.map +1 -1
  48. package/dist/routes/pages/thread-debug.js +5 -5
  49. package/dist/routes/pages/thread-debug.js.map +1 -1
  50. package/dist/routes/pages/vault.js +3 -3
  51. package/dist/routes/pages/vault.js.map +1 -1
  52. package/dist/routes/pages/workspace.d.ts.map +1 -1
  53. package/dist/routes/pages/workspace.js +3 -3
  54. package/dist/routes/pages/workspace.js.map +1 -1
  55. package/package.json +3 -3
  56. package/src/components/agents-panel.tsx +1 -1
  57. package/src/components/dispatch-control-plane.tsx +1 -4
  58. package/src/components/layout/Layout.spec.tsx +5 -0
  59. package/src/components/layout/Layout.tsx +62 -32
  60. package/src/components/messaging-setup-panel.tsx +1 -1
  61. package/src/components/task-queue-health.tsx +1 -1
  62. package/src/components/ui/button.tsx +1 -2
  63. package/src/components/ui/card.tsx +1 -1
  64. package/src/components/workspace-app-card.tsx +1 -1
  65. package/src/components/workspace-template-card.tsx +2 -2
  66. package/src/routes/pages/$appId.tsx +1 -1
  67. package/src/routes/pages/agents.tsx +1 -1
  68. package/src/routes/pages/approval.tsx +4 -4
  69. package/src/routes/pages/approvals.tsx +2 -2
  70. package/src/routes/pages/apps.$appId.tsx +1 -1
  71. package/src/routes/pages/apps.tsx +3 -3
  72. package/src/routes/pages/audit.tsx +1 -1
  73. package/src/routes/pages/automations.tsx +1 -1
  74. package/src/routes/pages/destinations.tsx +2 -2
  75. package/src/routes/pages/dreams.tsx +5 -5
  76. package/src/routes/pages/identities.tsx +2 -2
  77. package/src/routes/pages/integrations.tsx +2 -2
  78. package/src/routes/pages/metrics.tsx +4 -4
  79. package/src/routes/pages/thread-debug.tsx +6 -6
  80. package/src/routes/pages/vault.tsx +3 -3
  81. package/src/routes/pages/workspace.tsx +3 -6
@@ -1 +1 @@
1
- {"version":3,"file":"approval.js","sourceRoot":"","sources":["../../../src/routes/pages/approval.tsx"],"names":[],"mappings":"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","sourcesContent":["import { appPath } from \"@agent-native/core/client/api-path\";\nimport {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport {\n isInAgentEmbed,\n postNavigate,\n} from \"@agent-native/core/client/navigation\";\nimport {\n IconCheck,\n IconX,\n IconArrowUpRight,\n IconShieldCheck,\n IconClock,\n IconAlertCircle,\n} from \"@tabler/icons-react\";\nimport { useSearchParams } from \"react-router\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport {\n ApprovalValueBlock,\n parseApprovalValue,\n} from \"../../components/approval-value-block\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\n\nexport function meta() {\n return [{ title: \"Approval — Dispatch\" }];\n}\n\nfunction StatusBadge({ status }: { status: string }) {\n if (status === \"pending\") {\n return (\n <Badge\n variant=\"outline\"\n className=\"gap-1.5 border-amber-500/40 bg-amber-500/10 text-amber-600 dark:text-amber-400\"\n >\n <IconClock size={11} />\n Pending\n </Badge>\n );\n }\n if (status === \"approved\") {\n return (\n <Badge\n variant=\"outline\"\n className=\"gap-1.5 border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400\"\n >\n <IconCheck size={11} />\n Approved\n </Badge>\n );\n }\n return (\n <Badge\n variant=\"outline\"\n className=\"gap-1.5 border-red-500/40 bg-red-500/10 text-red-600 dark:text-red-400\"\n >\n <IconX size={11} />\n Rejected\n </Badge>\n );\n}\n\nexport default function ApprovalPreviewRoute() {\n const [searchParams] = useSearchParams();\n const id = searchParams.get(\"id\") ?? \"\";\n\n const approvalsQuery = useActionQuery(\"list-dispatch-approvals\", {});\n const { data: approvals, isLoading } = approvalsQuery;\n\n const approve = useActionMutation(\"approve-dispatch-change\", {\n onSuccess: () => toast.success(\"Change approved\"),\n });\n const reject = useActionMutation(\"reject-dispatch-change\", {\n onSuccess: () => toast.success(\"Change rejected\"),\n });\n\n const inEmbed = isInAgentEmbed();\n\n const approval = approvals?.find((item: any) => item.id === id) ?? null;\n\n if (!id) {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-background p-6\">\n <div className=\"w-full max-w-md rounded-2xl border bg-card p-6 text-center\">\n <IconAlertCircle\n size={32}\n className=\"mx-auto mb-3 text-muted-foreground\"\n />\n <p className=\"text-sm font-medium text-foreground\">\n No approval id provided\n </p>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n Add <code className=\"rounded bg-muted px-1\">?id=&lt;id&gt;</code> to\n the URL.\n </p>\n </div>\n </div>\n );\n }\n\n if (isLoading) {\n return (\n <div className=\"flex min-h-screen items-start justify-center bg-background p-6\">\n <div className=\"w-full max-w-md space-y-4\">\n <div className=\"rounded-2xl border bg-card p-5\">\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"h-9 w-9 shrink-0 rounded-xl\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Skeleton className=\"h-4 w-40\" />\n <Skeleton className=\"h-5 w-20 rounded-full\" />\n </div>\n <Skeleton className=\"h-3 w-32\" />\n </div>\n </div>\n <div className=\"mt-4 space-y-2 rounded-xl border bg-muted/30 px-4 py-3\">\n <div className=\"flex justify-between gap-4\">\n <Skeleton className=\"h-3 w-20\" />\n <Skeleton className=\"h-3 w-24\" />\n </div>\n <div className=\"flex justify-between gap-4\">\n <Skeleton className=\"h-3 w-20\" />\n <Skeleton className=\"h-3 w-28\" />\n </div>\n <div className=\"flex justify-between gap-4\">\n <Skeleton className=\"h-3 w-16\" />\n <Skeleton className=\"h-3 w-32\" />\n </div>\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Skeleton className=\"h-8 flex-1 rounded-md\" />\n <Skeleton className=\"h-8 flex-1 rounded-md\" />\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n if (approvalsQuery.isError) {\n return (\n <div className=\"flex min-h-screen items-start justify-center bg-background p-6\">\n <div className=\"w-full max-w-md\">\n <ActionQueryError\n error={approvalsQuery.error}\n onRetry={() => void approvalsQuery.refetch()}\n />\n </div>\n </div>\n );\n }\n\n if (!approval) {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-background p-6\">\n <div className=\"w-full max-w-md rounded-2xl border bg-card p-6 text-center\">\n <IconAlertCircle\n size={32}\n className=\"mx-auto mb-3 text-muted-foreground\"\n />\n <p className=\"text-sm font-medium text-foreground\">\n Approval not found\n </p>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n The approval with id{\" \"}\n <code className=\"rounded bg-muted px-1\">{id}</code> does not exist.\n </p>\n {inEmbed && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"mt-4 gap-1.5\"\n onClick={() => postNavigate(appPath(\"/approvals\"))}\n >\n <IconArrowUpRight size={14} />\n View all approvals\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n const isPending = approval.status === \"pending\";\n const beforeValue = parseApprovalValue(approval.beforeValue);\n const afterValue = parseApprovalValue(approval.afterValue);\n\n return (\n <div className=\"flex min-h-screen items-start justify-center bg-background p-6\">\n <div className=\"w-full max-w-2xl space-y-4\">\n <div className=\"rounded-2xl border bg-card p-5\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-xl border bg-muted text-foreground\">\n <IconShieldCheck size={17} />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">\n {approval.summary}\n </span>\n <StatusBadge status={approval.status} />\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n Requested by{\" \"}\n <span className=\"font-medium text-foreground\">\n {approval.requestedBy}\n </span>\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 space-y-2 rounded-xl border bg-muted/30 px-4 py-3 text-xs\">\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">Change type</span>\n <span className=\"font-mono font-medium text-foreground\">\n {approval.changeType}\n </span>\n </div>\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">Target type</span>\n <span className=\"font-mono font-medium text-foreground\">\n {approval.targetType}\n </span>\n </div>\n {approval.targetId && (\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">Target id</span>\n <span className=\"truncate font-mono font-medium text-foreground\">\n {approval.targetId}\n </span>\n </div>\n )}\n {approval.reviewedBy && (\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">Reviewed by</span>\n <span className=\"font-medium text-foreground\">\n {approval.reviewedBy}\n </span>\n </div>\n )}\n </div>\n\n {(beforeValue !== null || afterValue !== null) && (\n <div className=\"mt-4 grid gap-3 md:grid-cols-2\">\n <ApprovalValueBlock label=\"Before\" value={beforeValue} />\n <ApprovalValueBlock label=\"After\" value={afterValue} />\n </div>\n )}\n\n {isPending && (\n <div className=\"mt-4 flex gap-2\">\n <Button\n size=\"sm\"\n className=\"flex-1\"\n disabled={approve.isPending || reject.isPending}\n onClick={() => approve.mutate({ id: approval.id })}\n >\n <IconCheck size={14} className=\"mr-1.5\" />\n Approve\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"flex-1\"\n disabled={approve.isPending || reject.isPending}\n onClick={() =>\n reject.mutate({\n id: approval.id,\n reason: \"Rejected in dispatch UI\",\n })\n }\n >\n <IconX size={14} className=\"mr-1.5\" />\n Reject\n </Button>\n </div>\n )}\n </div>\n\n {inEmbed && (\n <div className=\"flex justify-end\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"gap-1.5 text-muted-foreground\"\n onClick={() => postNavigate(appPath(\"/approvals\"))}\n >\n <IconArrowUpRight size={14} />\n Open in app\n </Button>\n </div>\n )}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"approval.js","sourceRoot":"","sources":["../../../src/routes/pages/approval.tsx"],"names":[],"mappings":"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","sourcesContent":["import { appPath } from \"@agent-native/core/client/api-path\";\nimport {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport {\n isInAgentEmbed,\n postNavigate,\n} from \"@agent-native/core/client/navigation\";\nimport {\n IconCheck,\n IconX,\n IconArrowUpRight,\n IconShieldCheck,\n IconClock,\n IconAlertCircle,\n} from \"@tabler/icons-react\";\nimport { useSearchParams } from \"react-router\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport {\n ApprovalValueBlock,\n parseApprovalValue,\n} from \"../../components/approval-value-block\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\n\nexport function meta() {\n return [{ title: \"Approval — Dispatch\" }];\n}\n\nfunction StatusBadge({ status }: { status: string }) {\n if (status === \"pending\") {\n return (\n <Badge\n variant=\"outline\"\n className=\"gap-1.5 border-amber-500/40 bg-amber-500/10 text-amber-600 dark:text-amber-400\"\n >\n <IconClock size={11} />\n Pending\n </Badge>\n );\n }\n if (status === \"approved\") {\n return (\n <Badge\n variant=\"outline\"\n className=\"gap-1.5 border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400\"\n >\n <IconCheck size={11} />\n Approved\n </Badge>\n );\n }\n return (\n <Badge\n variant=\"outline\"\n className=\"gap-1.5 border-red-500/40 bg-red-500/10 text-red-600 dark:text-red-400\"\n >\n <IconX size={11} />\n Rejected\n </Badge>\n );\n}\n\nexport default function ApprovalPreviewRoute() {\n const [searchParams] = useSearchParams();\n const id = searchParams.get(\"id\") ?? \"\";\n\n const approvalsQuery = useActionQuery(\"list-dispatch-approvals\", {});\n const { data: approvals, isLoading } = approvalsQuery;\n\n const approve = useActionMutation(\"approve-dispatch-change\", {\n onSuccess: () => toast.success(\"Change approved\"),\n });\n const reject = useActionMutation(\"reject-dispatch-change\", {\n onSuccess: () => toast.success(\"Change rejected\"),\n });\n\n const inEmbed = isInAgentEmbed();\n\n const approval = approvals?.find((item: any) => item.id === id) ?? null;\n\n if (!id) {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-background p-6\">\n <div className=\"w-full max-w-md rounded-2xl bg-card p-6 text-center\">\n <IconAlertCircle\n size={32}\n className=\"mx-auto mb-3 text-muted-foreground\"\n />\n <p className=\"text-sm font-medium text-foreground\">\n No approval id provided\n </p>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n Add <code className=\"rounded bg-muted px-1\">?id=&lt;id&gt;</code> to\n the URL.\n </p>\n </div>\n </div>\n );\n }\n\n if (isLoading) {\n return (\n <div className=\"flex min-h-screen items-start justify-center bg-background p-6\">\n <div className=\"w-full max-w-md space-y-4\">\n <div className=\"rounded-2xl bg-card p-5\">\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"h-9 w-9 shrink-0 rounded-xl\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Skeleton className=\"h-4 w-40\" />\n <Skeleton className=\"h-5 w-20 rounded-full\" />\n </div>\n <Skeleton className=\"h-3 w-32\" />\n </div>\n </div>\n <div className=\"mt-4 space-y-2 rounded-xl border bg-muted/30 px-4 py-3\">\n <div className=\"flex justify-between gap-4\">\n <Skeleton className=\"h-3 w-20\" />\n <Skeleton className=\"h-3 w-24\" />\n </div>\n <div className=\"flex justify-between gap-4\">\n <Skeleton className=\"h-3 w-20\" />\n <Skeleton className=\"h-3 w-28\" />\n </div>\n <div className=\"flex justify-between gap-4\">\n <Skeleton className=\"h-3 w-16\" />\n <Skeleton className=\"h-3 w-32\" />\n </div>\n </div>\n <div className=\"mt-4 flex gap-2\">\n <Skeleton className=\"h-8 flex-1 rounded-md\" />\n <Skeleton className=\"h-8 flex-1 rounded-md\" />\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n if (approvalsQuery.isError) {\n return (\n <div className=\"flex min-h-screen items-start justify-center bg-background p-6\">\n <div className=\"w-full max-w-md\">\n <ActionQueryError\n error={approvalsQuery.error}\n onRetry={() => void approvalsQuery.refetch()}\n />\n </div>\n </div>\n );\n }\n\n if (!approval) {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-background p-6\">\n <div className=\"w-full max-w-md rounded-2xl bg-card p-6 text-center\">\n <IconAlertCircle\n size={32}\n className=\"mx-auto mb-3 text-muted-foreground\"\n />\n <p className=\"text-sm font-medium text-foreground\">\n Approval not found\n </p>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n The approval with id{\" \"}\n <code className=\"rounded bg-muted px-1\">{id}</code> does not exist.\n </p>\n {inEmbed && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"mt-4 gap-1.5\"\n onClick={() => postNavigate(appPath(\"/approvals\"))}\n >\n <IconArrowUpRight size={14} />\n View all approvals\n </Button>\n )}\n </div>\n </div>\n );\n }\n\n const isPending = approval.status === \"pending\";\n const beforeValue = parseApprovalValue(approval.beforeValue);\n const afterValue = parseApprovalValue(approval.afterValue);\n\n return (\n <div className=\"flex min-h-screen items-start justify-center bg-background p-6\">\n <div className=\"w-full max-w-2xl space-y-4\">\n <div className=\"rounded-2xl bg-card p-5\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-xl border bg-muted text-foreground\">\n <IconShieldCheck size={17} />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">\n {approval.summary}\n </span>\n <StatusBadge status={approval.status} />\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n Requested by{\" \"}\n <span className=\"font-medium text-foreground\">\n {approval.requestedBy}\n </span>\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 space-y-2 rounded-xl border bg-muted/30 px-4 py-3 text-xs\">\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">Change type</span>\n <span className=\"font-mono font-medium text-foreground\">\n {approval.changeType}\n </span>\n </div>\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">Target type</span>\n <span className=\"font-mono font-medium text-foreground\">\n {approval.targetType}\n </span>\n </div>\n {approval.targetId && (\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">Target id</span>\n <span className=\"truncate font-mono font-medium text-foreground\">\n {approval.targetId}\n </span>\n </div>\n )}\n {approval.reviewedBy && (\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">Reviewed by</span>\n <span className=\"font-medium text-foreground\">\n {approval.reviewedBy}\n </span>\n </div>\n )}\n </div>\n\n {(beforeValue !== null || afterValue !== null) && (\n <div className=\"mt-4 grid gap-3 md:grid-cols-2\">\n <ApprovalValueBlock label=\"Before\" value={beforeValue} />\n <ApprovalValueBlock label=\"After\" value={afterValue} />\n </div>\n )}\n\n {isPending && (\n <div className=\"mt-4 flex gap-2\">\n <Button\n size=\"sm\"\n className=\"flex-1\"\n disabled={approve.isPending || reject.isPending}\n onClick={() => approve.mutate({ id: approval.id })}\n >\n <IconCheck size={14} className=\"mr-1.5\" />\n Approve\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"flex-1\"\n disabled={approve.isPending || reject.isPending}\n onClick={() =>\n reject.mutate({\n id: approval.id,\n reason: \"Rejected in dispatch UI\",\n })\n }\n >\n <IconX size={14} className=\"mr-1.5\" />\n Reject\n </Button>\n </div>\n )}\n </div>\n\n {inEmbed && (\n <div className=\"flex justify-end\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"gap-1.5 text-muted-foreground\"\n onClick={() => postNavigate(appPath(\"/approvals\"))}\n >\n <IconArrowUpRight size={14} />\n Open in app\n </Button>\n </div>\n )}\n </div>\n </div>\n );\n}\n"]}
@@ -37,7 +37,7 @@ export default function ApprovalsRoute() {
37
37
  onSuccess: () => toast.success("Change rejected"),
38
38
  onError: (err) => toast.error(String(err)),
39
39
  });
40
- return (_jsx(DispatchShell, { title: "Approvals", description: "Review durable dispatch changes before they apply.", children: _jsxs("div", { className: "grid gap-4 xl:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)]", children: [_jsxs(Collapsible, { className: "rounded-2xl border bg-card", children: [_jsxs(CollapsibleTrigger, { className: "group flex w-full cursor-pointer items-center justify-between gap-3 p-5 text-left hover:bg-muted/20", children: [_jsxs("span", { children: [_jsx("span", { className: "block text-lg font-semibold text-foreground", children: "Approval policy" }), _jsx("span", { className: "mt-1 block text-sm text-muted-foreground", children: settings?.enabled
40
+ return (_jsx(DispatchShell, { title: "Approvals", description: "Review durable dispatch changes before they apply.", children: _jsxs("div", { className: "grid gap-4 xl:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)]", children: [_jsxs(Collapsible, { className: "rounded-2xl bg-card", children: [_jsxs(CollapsibleTrigger, { className: "group flex w-full cursor-pointer items-center justify-between gap-3 p-5 text-left hover:bg-muted/20", children: [_jsxs("span", { children: [_jsx("span", { className: "block text-lg font-semibold text-foreground", children: "Approval policy" }), _jsx("span", { className: "mt-1 block text-sm text-muted-foreground", children: settings?.enabled
41
41
  ? "Durable changes require approval."
42
42
  : "Durable changes do not require approval." })] }), _jsx(IconChevronRight, { className: "h-5 w-5 shrink-0 text-muted-foreground transition-transform group-data-[state=open]:rotate-90" })] }), _jsx(CollapsibleContent, { className: "border-t px-5 pb-5 pt-4", children: settingsQuery.isError ? (_jsx(ActionQueryError, { error: settingsQuery.error, onRetry: () => void settingsQuery.refetch() })) : (_jsxs("div", { className: "space-y-4", children: [_jsxs("label", { className: "flex items-center justify-between rounded-xl border px-4 py-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Require approval for durable changes" }), _jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: hasOrg
43
43
  ? "Applies to saved destinations, shared dream proposals, All-app agent resources, and dispatch settings."
@@ -47,7 +47,7 @@ export default function ApprovalsRoute() {
47
47
  }) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Approver emails" }), _jsx(Input, { value: emails, onChange: (event) => setEmails(event.target.value), placeholder: (settings?.approverEmails || []).join(", "), disabled: !hasOrg }), _jsx(Button, { className: "w-full", variant: "outline", disabled: !hasOrg || savePolicy.isPending, onClick: () => savePolicy.mutate({
48
48
  enabled: settings?.enabled || false,
49
49
  approverEmails: approverList,
50
- }), children: "Save approvers" })] })] })) })] }), _jsxs("section", { className: "rounded-2xl border bg-card p-5", children: [_jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Pending and recent requests" }), approvalsQuery.isError ? (_jsx(ActionQueryError, { className: "mt-4", error: approvalsQuery.error, onRetry: () => void approvalsQuery.refetch() })) : (_jsxs("div", { className: "mt-4 space-y-3", children: [(approvals || []).map((approval) => (_jsx("div", { className: "rounded-xl border bg-muted/30 px-4 py-3", children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: approval.summary }), _jsxs("div", { className: "mt-1 text-xs text-muted-foreground", children: [approval.status, " \u00B7 requested by ", approval.requestedBy] })] }), approval.status === "pending" && (_jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { size: "sm", onClick: () => approve.mutate({ id: approval.id }), children: "Approve" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => reject.mutate({
50
+ }), children: "Save approvers" })] })] })) })] }), _jsxs("section", { className: "rounded-2xl bg-card p-5", children: [_jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Pending and recent requests" }), approvalsQuery.isError ? (_jsx(ActionQueryError, { className: "mt-4", error: approvalsQuery.error, onRetry: () => void approvalsQuery.refetch() })) : (_jsxs("div", { className: "mt-4 space-y-3", children: [(approvals || []).map((approval) => (_jsx("div", { className: "rounded-xl border bg-muted/30 px-4 py-3", children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: approval.summary }), _jsxs("div", { className: "mt-1 text-xs text-muted-foreground", children: [approval.status, " \u00B7 requested by ", approval.requestedBy] })] }), approval.status === "pending" && (_jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { size: "sm", onClick: () => approve.mutate({ id: approval.id }), children: "Approve" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => reject.mutate({
51
51
  id: approval.id,
52
52
  reason: "Rejected in dispatch UI",
53
53
  }), children: "Reject" })] }))] }) }, approval.id))), (approvals?.length || 0) === 0 && (_jsx("div", { className: "rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground", children: "No approval requests yet." }))] }))] })] }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../../src/routes/pages/approvals.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { useOrg } from \"@agent-native/core/client/org\";\nimport { IconChevronRight } from \"@tabler/icons-react\";\nimport { useMemo, useState } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../../components/ui/collapsible\";\nimport { Input } from \"../../components/ui/input\";\nimport { Switch } from \"../../components/ui/switch\";\n\nexport function meta() {\n return [{ title: \"Approvals — Dispatch\" }];\n}\n\nexport default function ApprovalsRoute() {\n const settingsQuery = useActionQuery(\"get-dispatch-settings\", {});\n const approvalsQuery = useActionQuery(\"list-dispatch-approvals\", {});\n const { data: settings } = settingsQuery;\n const { data: approvals } = approvalsQuery;\n const { data: org } = useOrg();\n const hasOrg = !!org?.orgId;\n const [emails, setEmails] = useState(\"\");\n\n const approverList = useMemo(\n () =>\n emails\n .split(\",\")\n .map((value) => value.trim())\n .filter(Boolean),\n [emails],\n );\n\n const savePolicy = useActionMutation(\"set-dispatch-approval-policy\", {\n onSuccess: () => toast.success(\"Approval policy updated\"),\n onError: (err) => toast.error(String(err)),\n });\n const approve = useActionMutation(\"approve-dispatch-change\", {\n onSuccess: () => toast.success(\"Change approved\"),\n onError: (err) => toast.error(String(err)),\n });\n const reject = useActionMutation(\"reject-dispatch-change\", {\n onSuccess: () => toast.success(\"Change rejected\"),\n onError: (err) => toast.error(String(err)),\n });\n\n return (\n <DispatchShell\n title=\"Approvals\"\n description=\"Review durable dispatch changes before they apply.\"\n >\n <div className=\"grid gap-4 xl:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)]\">\n <Collapsible className=\"rounded-2xl border bg-card\">\n <CollapsibleTrigger className=\"group flex w-full cursor-pointer items-center justify-between gap-3 p-5 text-left hover:bg-muted/20\">\n <span>\n <span className=\"block text-lg font-semibold text-foreground\">\n Approval policy\n </span>\n <span className=\"mt-1 block text-sm text-muted-foreground\">\n {settings?.enabled\n ? \"Durable changes require approval.\"\n : \"Durable changes do not require approval.\"}\n </span>\n </span>\n <IconChevronRight className=\"h-5 w-5 shrink-0 text-muted-foreground transition-transform group-data-[state=open]:rotate-90\" />\n </CollapsibleTrigger>\n <CollapsibleContent className=\"border-t px-5 pb-5 pt-4\">\n {settingsQuery.isError ? (\n <ActionQueryError\n error={settingsQuery.error}\n onRetry={() => void settingsQuery.refetch()}\n />\n ) : (\n <div className=\"space-y-4\">\n <label className=\"flex items-center justify-between rounded-xl border px-4 py-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n Require approval for durable changes\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {hasOrg\n ? \"Applies to saved destinations, shared dream proposals, All-app agent resources, and dispatch settings.\"\n : \"Requires a team workspace. Set one up on the Team page.\"}\n </div>\n </div>\n <Switch\n checked={settings?.enabled || false}\n disabled={!hasOrg || savePolicy.isPending}\n onCheckedChange={(checked) =>\n savePolicy.mutate({\n enabled: checked,\n approverEmails:\n settings?.approverEmails || approverList,\n })\n }\n />\n </label>\n <div className=\"space-y-2\">\n <div className=\"text-sm font-medium text-foreground\">\n Approver emails\n </div>\n <Input\n value={emails}\n onChange={(event) => setEmails(event.target.value)}\n placeholder={(settings?.approverEmails || []).join(\", \")}\n disabled={!hasOrg}\n />\n <Button\n className=\"w-full\"\n variant=\"outline\"\n disabled={!hasOrg || savePolicy.isPending}\n onClick={() =>\n savePolicy.mutate({\n enabled: settings?.enabled || false,\n approverEmails: approverList,\n })\n }\n >\n Save approvers\n </Button>\n </div>\n </div>\n )}\n </CollapsibleContent>\n </Collapsible>\n\n <section className=\"rounded-2xl border bg-card p-5\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Pending and recent requests\n </h2>\n {approvalsQuery.isError ? (\n <ActionQueryError\n className=\"mt-4\"\n error={approvalsQuery.error}\n onRetry={() => void approvalsQuery.refetch()}\n />\n ) : (\n <div className=\"mt-4 space-y-3\">\n {(approvals || []).map((approval: any) => (\n <div\n key={approval.id}\n className=\"rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n {approval.summary}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {approval.status} · requested by {approval.requestedBy}\n </div>\n </div>\n {approval.status === \"pending\" && (\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n onClick={() => approve.mutate({ id: approval.id })}\n >\n Approve\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() =>\n reject.mutate({\n id: approval.id,\n reason: \"Rejected in dispatch UI\",\n })\n }\n >\n Reject\n </Button>\n </div>\n )}\n </div>\n </div>\n ))}\n {(approvals?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No approval requests yet.\n </div>\n )}\n </div>\n )}\n </section>\n </div>\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../../src/routes/pages/approvals.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { useOrg } from \"@agent-native/core/client/org\";\nimport { IconChevronRight } from \"@tabler/icons-react\";\nimport { useMemo, useState } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../../components/ui/collapsible\";\nimport { Input } from \"../../components/ui/input\";\nimport { Switch } from \"../../components/ui/switch\";\n\nexport function meta() {\n return [{ title: \"Approvals — Dispatch\" }];\n}\n\nexport default function ApprovalsRoute() {\n const settingsQuery = useActionQuery(\"get-dispatch-settings\", {});\n const approvalsQuery = useActionQuery(\"list-dispatch-approvals\", {});\n const { data: settings } = settingsQuery;\n const { data: approvals } = approvalsQuery;\n const { data: org } = useOrg();\n const hasOrg = !!org?.orgId;\n const [emails, setEmails] = useState(\"\");\n\n const approverList = useMemo(\n () =>\n emails\n .split(\",\")\n .map((value) => value.trim())\n .filter(Boolean),\n [emails],\n );\n\n const savePolicy = useActionMutation(\"set-dispatch-approval-policy\", {\n onSuccess: () => toast.success(\"Approval policy updated\"),\n onError: (err) => toast.error(String(err)),\n });\n const approve = useActionMutation(\"approve-dispatch-change\", {\n onSuccess: () => toast.success(\"Change approved\"),\n onError: (err) => toast.error(String(err)),\n });\n const reject = useActionMutation(\"reject-dispatch-change\", {\n onSuccess: () => toast.success(\"Change rejected\"),\n onError: (err) => toast.error(String(err)),\n });\n\n return (\n <DispatchShell\n title=\"Approvals\"\n description=\"Review durable dispatch changes before they apply.\"\n >\n <div className=\"grid gap-4 xl:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)]\">\n <Collapsible className=\"rounded-2xl bg-card\">\n <CollapsibleTrigger className=\"group flex w-full cursor-pointer items-center justify-between gap-3 p-5 text-left hover:bg-muted/20\">\n <span>\n <span className=\"block text-lg font-semibold text-foreground\">\n Approval policy\n </span>\n <span className=\"mt-1 block text-sm text-muted-foreground\">\n {settings?.enabled\n ? \"Durable changes require approval.\"\n : \"Durable changes do not require approval.\"}\n </span>\n </span>\n <IconChevronRight className=\"h-5 w-5 shrink-0 text-muted-foreground transition-transform group-data-[state=open]:rotate-90\" />\n </CollapsibleTrigger>\n <CollapsibleContent className=\"border-t px-5 pb-5 pt-4\">\n {settingsQuery.isError ? (\n <ActionQueryError\n error={settingsQuery.error}\n onRetry={() => void settingsQuery.refetch()}\n />\n ) : (\n <div className=\"space-y-4\">\n <label className=\"flex items-center justify-between rounded-xl border px-4 py-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n Require approval for durable changes\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {hasOrg\n ? \"Applies to saved destinations, shared dream proposals, All-app agent resources, and dispatch settings.\"\n : \"Requires a team workspace. Set one up on the Team page.\"}\n </div>\n </div>\n <Switch\n checked={settings?.enabled || false}\n disabled={!hasOrg || savePolicy.isPending}\n onCheckedChange={(checked) =>\n savePolicy.mutate({\n enabled: checked,\n approverEmails:\n settings?.approverEmails || approverList,\n })\n }\n />\n </label>\n <div className=\"space-y-2\">\n <div className=\"text-sm font-medium text-foreground\">\n Approver emails\n </div>\n <Input\n value={emails}\n onChange={(event) => setEmails(event.target.value)}\n placeholder={(settings?.approverEmails || []).join(\", \")}\n disabled={!hasOrg}\n />\n <Button\n className=\"w-full\"\n variant=\"outline\"\n disabled={!hasOrg || savePolicy.isPending}\n onClick={() =>\n savePolicy.mutate({\n enabled: settings?.enabled || false,\n approverEmails: approverList,\n })\n }\n >\n Save approvers\n </Button>\n </div>\n </div>\n )}\n </CollapsibleContent>\n </Collapsible>\n\n <section className=\"rounded-2xl bg-card p-5\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Pending and recent requests\n </h2>\n {approvalsQuery.isError ? (\n <ActionQueryError\n className=\"mt-4\"\n error={approvalsQuery.error}\n onRetry={() => void approvalsQuery.refetch()}\n />\n ) : (\n <div className=\"mt-4 space-y-3\">\n {(approvals || []).map((approval: any) => (\n <div\n key={approval.id}\n className=\"rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n {approval.summary}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {approval.status} · requested by {approval.requestedBy}\n </div>\n </div>\n {approval.status === \"pending\" && (\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n onClick={() => approve.mutate({ id: approval.id })}\n >\n Approve\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() =>\n reject.mutate({\n id: approval.id,\n reason: \"Rejected in dispatch UI\",\n })\n }\n >\n Reject\n </Button>\n </div>\n )}\n </div>\n </div>\n ))}\n {(approvals?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No approval requests yet.\n </div>\n )}\n </div>\n )}\n </section>\n </div>\n </DispatchShell>\n );\n}\n"]}
@@ -28,7 +28,7 @@ export default function WorkspaceAppRoute() {
28
28
  return;
29
29
  window.location.assign(href);
30
30
  }, [app, href]);
31
- return (_jsx(DispatchShell, { title: app?.name || t("dispatch.pages.workspaceAppFallback"), description: t("dispatch.pages.workspaceAppDescription"), children: _jsxs("div", { className: "max-w-2xl rounded-lg border bg-card p-5", children: [_jsx(Button, { asChild: true, size: "sm", variant: "ghost", className: "-ml-2 mb-4", children: _jsxs(Link, { to: "/apps", children: [_jsx(IconArrowLeft, { size: 15, className: "mr-1.5" }), t("dispatch.nav.apps")] }) }), appsQuery.isError ? (_jsx(ActionQueryError, { error: appsQuery.error, onRetry: () => void appsQuery.refetch() })) : isLoading && !app ? (_jsxs("div", { className: "space-y-3", children: [_jsx(Skeleton, { className: "h-5 w-48" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-2/3" })] })) : !app ? (_jsxs("div", { className: "space-y-3", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: t("dispatch.pages.appNotFound") }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("dispatch.pages.pageNotFoundDescription") })] })) : app.status === "pending" ? (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: app.name }), _jsxs(Badge, { variant: "outline", className: "gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300", children: [_jsx(IconClockHour4, { size: 12 }), t("dispatch.pages.building")] })] }), _jsxs("p", { className: "text-sm text-muted-foreground", children: [t("dispatch.pages.appBuildingPrefix"), " ", _jsx("span", { className: "font-mono text-foreground", children: app.path }), " ", t("dispatch.pages.appBuildingSuffix")] }), app.branchName ? (_jsx("p", { className: "text-xs text-muted-foreground", children: t("dispatch.pages.branch", { branch: app.branchName }) })) : null, app.builderUrl ? (_jsx(Button, { asChild: true, children: _jsxs("a", { href: withBuilderUtmTrackingParams(app.builderUrl, {
31
+ return (_jsx(DispatchShell, { title: app?.name || t("dispatch.pages.workspaceAppFallback"), description: t("dispatch.pages.workspaceAppDescription"), children: _jsxs("div", { className: "max-w-2xl rounded-lg bg-card p-5", children: [_jsx(Button, { asChild: true, size: "sm", variant: "ghost", className: "-ml-2 mb-4", children: _jsxs(Link, { to: "/apps", children: [_jsx(IconArrowLeft, { size: 15, className: "mr-1.5" }), t("dispatch.nav.apps")] }) }), appsQuery.isError ? (_jsx(ActionQueryError, { error: appsQuery.error, onRetry: () => void appsQuery.refetch() })) : isLoading && !app ? (_jsxs("div", { className: "space-y-3", children: [_jsx(Skeleton, { className: "h-5 w-48" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-2/3" })] })) : !app ? (_jsxs("div", { className: "space-y-3", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: t("dispatch.pages.appNotFound") }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("dispatch.pages.pageNotFoundDescription") })] })) : app.status === "pending" ? (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: app.name }), _jsxs(Badge, { variant: "outline", className: "gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300", children: [_jsx(IconClockHour4, { size: 12 }), t("dispatch.pages.building")] })] }), _jsxs("p", { className: "text-sm text-muted-foreground", children: [t("dispatch.pages.appBuildingPrefix"), " ", _jsx("span", { className: "font-mono text-foreground", children: app.path }), " ", t("dispatch.pages.appBuildingSuffix")] }), app.branchName ? (_jsx("p", { className: "text-xs text-muted-foreground", children: t("dispatch.pages.branch", { branch: app.branchName }) })) : null, app.builderUrl ? (_jsx(Button, { asChild: true, children: _jsxs("a", { href: withBuilderUtmTrackingParams(app.builderUrl, {
32
32
  campaign: "product",
33
33
  content: "dispatch_branch",
34
34
  }), target: "_blank", rel: "noreferrer", children: [t("dispatch.pages.openBuilderBranch"), _jsx(IconArrowUpRight, { size: 15, className: "ml-1.5" })] }) })) : null] })) : (_jsxs("div", { className: "space-y-3", children: [_jsx("h2", { className: "text-base font-semibold text-foreground", children: t("dispatch.pages.openingApp", { name: app.name }) }), _jsxs("p", { className: "text-sm text-muted-foreground", children: [t("dispatch.pages.redirectingTo"), " ", _jsx("span", { className: "font-mono text-foreground", children: app.path }), "."] }), href ? (_jsx(Button, { asChild: true, children: _jsxs("a", { href: href, children: [t("dispatch.pages.openApp"), _jsx(IconArrowUpRight, { size: 15, className: "ml-1.5" })] }) })) : null] }))] }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"apps.$appId.js","sourceRoot":"","sources":["../../../src/routes/pages/apps.$appId.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\nimport {\n IconArrowLeft,\n IconArrowUpRight,\n IconClockHour4,\n} from \"@tabler/icons-react\";\nimport { useEffect, useMemo } from \"react\";\nimport { Link, useParams } from \"react-router\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport {\n workspaceAppHref,\n type WorkspaceAppSummary,\n} from \"../../lib/workspace-apps\";\n\nexport function meta() {\n return [{ title: \"Workspace app - Dispatch\" }];\n}\n\nexport default function WorkspaceAppRoute() {\n const t = useT();\n const { appId } = useParams();\n const appsQuery = useActionQuery(\"list-workspace-apps\", {\n includeAgentCards: false,\n });\n const { data: apps = [], isLoading } = appsQuery;\n const app = useMemo(\n () =>\n (apps as WorkspaceAppSummary[]).find((item) => item.id === appId) ?? null,\n [appId, apps],\n );\n const href = app ? workspaceAppHref(app) : null;\n\n useEffect(() => {\n if (!app || app.status === \"pending\" || !href) return;\n window.location.assign(href);\n }, [app, href]);\n\n return (\n <DispatchShell\n title={app?.name || t(\"dispatch.pages.workspaceAppFallback\")}\n description={t(\"dispatch.pages.workspaceAppDescription\")}\n >\n <div className=\"max-w-2xl rounded-lg border bg-card p-5\">\n <Button asChild size=\"sm\" variant=\"ghost\" className=\"-ml-2 mb-4\">\n <Link to=\"/apps\">\n <IconArrowLeft size={15} className=\"mr-1.5\" />\n {t(\"dispatch.nav.apps\")}\n </Link>\n </Button>\n\n {appsQuery.isError ? (\n <ActionQueryError\n error={appsQuery.error}\n onRetry={() => void appsQuery.refetch()}\n />\n ) : isLoading && !app ? (\n <div className=\"space-y-3\">\n <Skeleton className=\"h-5 w-48\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n ) : !app ? (\n <div className=\"space-y-3\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {t(\"dispatch.pages.appNotFound\")}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.pageNotFoundDescription\")}\n </p>\n </div>\n ) : app.status === \"pending\" ? (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {app.name}\n </h2>\n <Badge\n variant=\"outline\"\n className=\"gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300\"\n >\n <IconClockHour4 size={12} />\n {t(\"dispatch.pages.building\")}\n </Badge>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.appBuildingPrefix\")}{\" \"}\n <span className=\"font-mono text-foreground\">{app.path}</span>{\" \"}\n {t(\"dispatch.pages.appBuildingSuffix\")}\n </p>\n {app.branchName ? (\n <p className=\"text-xs text-muted-foreground\">\n {t(\"dispatch.pages.branch\", { branch: app.branchName })}\n </p>\n ) : null}\n {app.builderUrl ? (\n <Button asChild>\n <a\n href={withBuilderUtmTrackingParams(app.builderUrl, {\n campaign: \"product\",\n content: \"dispatch_branch\",\n })}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {t(\"dispatch.pages.openBuilderBranch\")}\n <IconArrowUpRight size={15} className=\"ml-1.5\" />\n </a>\n </Button>\n ) : null}\n </div>\n ) : (\n <div className=\"space-y-3\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {t(\"dispatch.pages.openingApp\", { name: app.name })}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.redirectingTo\")}{\" \"}\n <span className=\"font-mono text-foreground\">{app.path}</span>.\n </p>\n {href ? (\n <Button asChild>\n <a href={href}>\n {t(\"dispatch.pages.openApp\")}\n <IconArrowUpRight size={15} className=\"ml-1.5\" />\n </a>\n </Button>\n ) : null}\n </div>\n )}\n </div>\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"apps.$appId.js","sourceRoot":"","sources":["../../../src/routes/pages/apps.$appId.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\nimport {\n IconArrowLeft,\n IconArrowUpRight,\n IconClockHour4,\n} from \"@tabler/icons-react\";\nimport { useEffect, useMemo } from \"react\";\nimport { Link, useParams } from \"react-router\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport {\n workspaceAppHref,\n type WorkspaceAppSummary,\n} from \"../../lib/workspace-apps\";\n\nexport function meta() {\n return [{ title: \"Workspace app - Dispatch\" }];\n}\n\nexport default function WorkspaceAppRoute() {\n const t = useT();\n const { appId } = useParams();\n const appsQuery = useActionQuery(\"list-workspace-apps\", {\n includeAgentCards: false,\n });\n const { data: apps = [], isLoading } = appsQuery;\n const app = useMemo(\n () =>\n (apps as WorkspaceAppSummary[]).find((item) => item.id === appId) ?? null,\n [appId, apps],\n );\n const href = app ? workspaceAppHref(app) : null;\n\n useEffect(() => {\n if (!app || app.status === \"pending\" || !href) return;\n window.location.assign(href);\n }, [app, href]);\n\n return (\n <DispatchShell\n title={app?.name || t(\"dispatch.pages.workspaceAppFallback\")}\n description={t(\"dispatch.pages.workspaceAppDescription\")}\n >\n <div className=\"max-w-2xl rounded-lg bg-card p-5\">\n <Button asChild size=\"sm\" variant=\"ghost\" className=\"-ml-2 mb-4\">\n <Link to=\"/apps\">\n <IconArrowLeft size={15} className=\"mr-1.5\" />\n {t(\"dispatch.nav.apps\")}\n </Link>\n </Button>\n\n {appsQuery.isError ? (\n <ActionQueryError\n error={appsQuery.error}\n onRetry={() => void appsQuery.refetch()}\n />\n ) : isLoading && !app ? (\n <div className=\"space-y-3\">\n <Skeleton className=\"h-5 w-48\" />\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n ) : !app ? (\n <div className=\"space-y-3\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {t(\"dispatch.pages.appNotFound\")}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.pageNotFoundDescription\")}\n </p>\n </div>\n ) : app.status === \"pending\" ? (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {app.name}\n </h2>\n <Badge\n variant=\"outline\"\n className=\"gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300\"\n >\n <IconClockHour4 size={12} />\n {t(\"dispatch.pages.building\")}\n </Badge>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.appBuildingPrefix\")}{\" \"}\n <span className=\"font-mono text-foreground\">{app.path}</span>{\" \"}\n {t(\"dispatch.pages.appBuildingSuffix\")}\n </p>\n {app.branchName ? (\n <p className=\"text-xs text-muted-foreground\">\n {t(\"dispatch.pages.branch\", { branch: app.branchName })}\n </p>\n ) : null}\n {app.builderUrl ? (\n <Button asChild>\n <a\n href={withBuilderUtmTrackingParams(app.builderUrl, {\n campaign: \"product\",\n content: \"dispatch_branch\",\n })}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {t(\"dispatch.pages.openBuilderBranch\")}\n <IconArrowUpRight size={15} className=\"ml-1.5\" />\n </a>\n </Button>\n ) : null}\n </div>\n ) : (\n <div className=\"space-y-3\">\n <h2 className=\"text-base font-semibold text-foreground\">\n {t(\"dispatch.pages.openingApp\", { name: app.name })}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.redirectingTo\")}{\" \"}\n <span className=\"font-mono text-foreground\">{app.path}</span>.\n </p>\n {href ? (\n <Button asChild>\n <a href={href}>\n {t(\"dispatch.pages.openApp\")}\n <IconArrowUpRight size={15} className=\"ml-1.5\" />\n </a>\n </Button>\n ) : null}\n </div>\n )}\n </div>\n </DispatchShell>\n );\n}\n"]}
@@ -79,17 +79,17 @@ function OtherAppsHeading({ count }) {
79
79
  : ""] })] })] }));
80
80
  }
81
81
  function OtherAppsSkeletonGrid() {
82
- return (_jsx("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-3", children: Array.from({ length: 3 }).map((_, index) => (_jsx("div", { className: "rounded-lg border bg-card p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(Skeleton, { className: "size-8 rounded-md" }), _jsxs("div", { className: "flex-1 space-y-3", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-3 w-full" }), _jsx(Skeleton, { className: "h-3 w-2/3" })] })] }) }, index))) }));
82
+ return (_jsx("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-3", children: Array.from({ length: 3 }).map((_, index) => (_jsx("div", { className: "rounded-lg bg-card p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(Skeleton, { className: "size-8 rounded-md" }), _jsxs("div", { className: "flex-1 space-y-3", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-3 w-full" }), _jsx(Skeleton, { className: "h-3 w-2/3" })] })] }) }, index))) }));
83
83
  }
84
84
  function OtherAppCard({ app }) {
85
85
  const t = useT();
86
86
  return (_jsxs("a", { href: withBuilderUtmTrackingParams(app.url, {
87
87
  campaign: "product",
88
88
  content: "dispatch_app",
89
- }), target: "_blank", rel: "noopener noreferrer", className: "group flex min-h-[116px] items-start gap-3 rounded-xl border border-border/60 bg-card/40 p-4 transition-[background-color,border-color] hover:border-foreground/20 hover:bg-accent/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-xs font-semibold text-muted-foreground", children: app.name.charAt(0).toUpperCase() }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "flex items-start justify-between gap-3", children: [_jsx("span", { className: "truncate text-sm font-semibold text-foreground", children: app.name }), _jsx(IconArrowUpRight, { size: 15, className: "shrink-0 text-muted-foreground transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5" })] }), _jsx("span", { className: "mt-2 line-clamp-2 block text-[13px] leading-5 text-muted-foreground", children: app.description || app.url }), _jsx("span", { className: "mt-3 block text-xs font-medium text-foreground", children: t("dispatch.pages.openApp") })] })] }));
89
+ }), target: "_blank", rel: "noopener noreferrer", className: "group flex min-h-[116px] items-start gap-3 rounded-xl bg-card/40 p-4 transition-[background-color] hover:bg-accent/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-xs font-semibold text-muted-foreground", children: app.name.charAt(0).toUpperCase() }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "flex items-start justify-between gap-3", children: [_jsx("span", { className: "truncate text-sm font-semibold text-foreground", children: app.name }), _jsx(IconArrowUpRight, { size: 15, className: "shrink-0 text-muted-foreground transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5" })] }), _jsx("span", { className: "mt-2 line-clamp-2 block text-[13px] leading-5 text-muted-foreground", children: app.description || app.url }), _jsx("span", { className: "mt-3 block text-xs font-medium text-foreground", children: t("dispatch.pages.openApp") })] })] }));
90
90
  }
91
91
  function AppsSkeletonGrid() {
92
- return (_jsx("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-3", children: Array.from({ length: 3 }).map((_, index) => (_jsx("div", { className: "rounded-lg border bg-card p-4", children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1 space-y-3", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-3 w-24" }), _jsxs("div", { className: "space-y-2 pt-1", children: [_jsx(Skeleton, { className: "h-3 w-full" }), _jsx(Skeleton, { className: "h-3 w-2/3" })] })] }), _jsx(Skeleton, { className: "h-7 w-7 rounded-md" })] }) }, index))) }));
92
+ return (_jsx("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-3", children: Array.from({ length: 3 }).map((_, index) => (_jsx("div", { className: "rounded-lg bg-card p-4", children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1 space-y-3", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-3 w-24" }), _jsxs("div", { className: "space-y-2 pt-1", children: [_jsx(Skeleton, { className: "h-3 w-full" }), _jsx(Skeleton, { className: "h-3 w-2/3" })] })] }), _jsx(Skeleton, { className: "h-7 w-7 rounded-md" })] }) }, index))) }));
93
93
  }
94
94
  function EmptyAppsState() {
95
95
  const t = useT();
@@ -1 +1 @@
1
- {"version":3,"file":"apps.js","sourceRoot":"","sources":["../../../src/routes/pages/apps.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\nimport {\n IconApps,\n IconArrowUpRight,\n IconChevronDown,\n IconEyeOff,\n IconPlus,\n IconStack2,\n} from \"@tabler/icons-react\";\nimport { useState } from \"react\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { CreateAppPopover } from \"../../components/create-app-popover\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../../components/ui/collapsible\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { WorkspaceAppCard } from \"../../components/workspace-app-card\";\nimport {\n WorkspaceTemplatesSection,\n type CuratedWorkspaceTemplatesResult,\n type WorkspaceTemplateLabels,\n} from \"../../components/workspace-template-card\";\nimport {\n filterOtherApps,\n type ConnectedAppSummary,\n} from \"../../lib/other-apps\";\nimport { cn } from \"../../lib/utils\";\nimport type { WorkspaceAppSummary } from \"../../lib/workspace-apps\";\n\nexport function meta() {\n return [{ title: \"Apps — Dispatch\" }];\n}\n\ninterface WorkspaceInfo {\n name: string | null;\n displayName: string | null;\n appCount: number;\n}\n\nexport default function AppsRoute() {\n const t = useT();\n const [showHidden, setShowHidden] = useState(false);\n const appsQuery = useActionQuery(\"list-workspace-apps\", {\n includeAgentCards: false,\n includeArchived: true,\n });\n const connectedAppsQuery = useActionQuery(\"list-connected-agents\", {});\n const curatedTemplatesQuery = useActionQuery(\n \"list-curated-workspace-templates\",\n {},\n );\n const { data: apps = [], isLoading: appsLoading } = appsQuery;\n const { data: workspace } = useActionQuery(\n \"get-workspace-info\",\n {},\n { staleTime: 60_000 },\n );\n const ws = workspace as WorkspaceInfo | undefined;\n const workspaceLabel = ws?.displayName ?? ws?.name ?? null;\n const allApps = (apps as WorkspaceAppSummary[]).filter(\n (app) => !app.isDispatch,\n );\n const visibleApps = allApps.filter((app) => !app.archived);\n const archivedApps = allApps.filter((app) => app.archived);\n const otherApps = filterOtherApps(\n (connectedAppsQuery.data || []) as ConnectedAppSummary[],\n allApps,\n );\n const showAppSkeletons = appsLoading && allApps.length === 0;\n const templateLabels: WorkspaceTemplateLabels = {\n appId: t(\"dispatch.pages.remixAppIdLabel\"),\n appIdDescription: t(\"dispatch.pages.remixAppIdDescription\"),\n cancel: t(\"dispatch.pages.cancel\"),\n integrationSetup: t(\"dispatch.pages.integrationSetup\"),\n installed: t(\"dispatch.pages.alreadyInWorkspace\"),\n remix: t(\"dispatch.pages.remix\"),\n remixing: t(\"dispatch.pages.remixing\"),\n remixSuccess: t(\"dispatch.pages.remixSuccess\"),\n remixError: t(\"dispatch.pages.remixError\"),\n appIdRequired: t(\"dispatch.pages.appIdRequired\"),\n source: t(\"dispatch.pages.source\"),\n viewLiveApp: t(\"dispatch.pages.viewLiveApp\"),\n };\n\n return (\n <DispatchShell\n title={t(\"dispatch.nav.apps\")}\n description={\n workspaceLabel\n ? t(\"dispatch.pages.appsDescriptionWithWorkspace\", {\n workspace: workspaceLabel,\n })\n : t(\"dispatch.pages.appsDescription\")\n }\n >\n <div className=\"space-y-8\">\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div className=\"flex min-w-0 items-start gap-2\">\n <IconApps\n size={16}\n className=\"mt-0.5 shrink-0 text-muted-foreground\"\n />\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-sm font-semibold text-foreground\">\n {workspaceLabel\n ? t(\"dispatch.pages.appsInWorkspace\", {\n workspace: workspaceLabel,\n })\n : t(\"dispatch.pages.workspaceApps\")}\n </h2>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {t(\"dispatch.pages.activeCount\", {\n count: visibleApps.length,\n })}\n {archivedApps.length > 0\n ? ` · ${t(\"dispatch.pages.hiddenCount\", {\n count: archivedApps.length,\n })}`\n : \"\"}\n </p>\n </div>\n </div>\n {visibleApps.length > 0 ? (\n <CreateAppPopover\n align=\"end\"\n trigger={\n <Button size=\"sm\">\n <IconPlus size={15} className=\"mr-1.5\" />\n {t(\"dispatch.pages.createApp\")}\n </Button>\n }\n />\n ) : null}\n </div>\n\n {appsQuery.isError ? (\n <ActionQueryError\n error={appsQuery.error}\n onRetry={() => void appsQuery.refetch()}\n />\n ) : showAppSkeletons ? (\n <AppsSkeletonGrid />\n ) : visibleApps.length > 0 ? (\n <div className=\"grid auto-rows-fr gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {visibleApps.map((app) => (\n <WorkspaceAppCard key={app.id} app={app} className=\"h-full\" />\n ))}\n </div>\n ) : (\n <EmptyAppsState />\n )}\n </section>\n\n {curatedTemplatesQuery.isError ? (\n <section className=\"space-y-3 border-t pt-4\">\n <ActionQueryError\n error={curatedTemplatesQuery.error}\n onRetry={() => void curatedTemplatesQuery.refetch()}\n />\n </section>\n ) : curatedTemplatesQuery.data ? (\n <section className=\"space-y-3 border-t pt-4\">\n <div className=\"flex min-w-0 items-start gap-2\">\n <IconStack2\n size={16}\n className=\"mt-0.5 shrink-0 text-muted-foreground\"\n />\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.curatedTemplates\")}\n </h2>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {t(\"dispatch.pages.curatedTemplatesDescription\")}\n </p>\n </div>\n </div>\n <WorkspaceTemplatesSection\n templates={\n curatedTemplatesQuery.data as CuratedWorkspaceTemplatesResult\n }\n labels={templateLabels}\n onRemixSuccess={() => {\n void appsQuery.refetch();\n void curatedTemplatesQuery.refetch();\n }}\n />\n </section>\n ) : null}\n\n {connectedAppsQuery.isError ? (\n <section className=\"space-y-3 border-t pt-4\">\n <OtherAppsHeading count={0} />\n <ActionQueryError\n error={connectedAppsQuery.error}\n onRetry={() => void connectedAppsQuery.refetch()}\n />\n </section>\n ) : connectedAppsQuery.isLoading || otherApps.length > 0 ? (\n <section className=\"space-y-3 border-t pt-4\">\n <OtherAppsHeading count={otherApps.length} />\n {connectedAppsQuery.isLoading ? (\n <OtherAppsSkeletonGrid />\n ) : (\n <div className=\"grid auto-rows-fr gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {otherApps.map((app) => (\n <OtherAppCard key={app.id} app={app} />\n ))}\n </div>\n )}\n </section>\n ) : null}\n\n {archivedApps.length > 0 ? (\n <Collapsible open={showHidden} onOpenChange={setShowHidden}>\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-t pt-4\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <IconEyeOff\n size={16}\n className=\"shrink-0 text-muted-foreground\"\n />\n <div className=\"min-w-0\">\n <h2 className=\"text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.hiddenApps\")}\n </h2>\n <p className=\"text-xs text-muted-foreground\">\n {t(\"dispatch.pages.hiddenAppCount\", {\n count: archivedApps.length,\n })}\n </p>\n </div>\n </div>\n <CollapsibleTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"gap-1.5\"\n >\n {showHidden\n ? t(\"dispatch.pages.hide\")\n : t(\"dispatch.pages.show\")}\n <IconChevronDown\n size={14}\n className={cn(\n \"transition-transform\",\n showHidden && \"rotate-180\",\n )}\n />\n </Button>\n </CollapsibleTrigger>\n </div>\n <CollapsibleContent>\n <div className=\"grid auto-rows-fr gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {archivedApps.map((app) => (\n <WorkspaceAppCard\n key={app.id}\n app={app}\n className=\"h-full\"\n />\n ))}\n </div>\n </CollapsibleContent>\n </section>\n </Collapsible>\n ) : null}\n </div>\n </DispatchShell>\n );\n}\n\nfunction OtherAppsHeading({ count }: { count: number }) {\n const t = useT();\n return (\n <div className=\"flex min-w-0 items-start gap-2\">\n <IconStack2 size={16} className=\"mt-0.5 shrink-0 text-muted-foreground\" />\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.otherApps\")}\n </h2>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {t(\"dispatch.pages.otherAppsDescription\")}\n {count > 0\n ? ` · ${t(\"dispatch.pages.availableCount\", { count })}`\n : \"\"}\n </p>\n </div>\n </div>\n );\n}\n\nfunction OtherAppsSkeletonGrid() {\n return (\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {Array.from({ length: 3 }).map((_, index) => (\n <div key={index} className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"size-8 rounded-md\" />\n <div className=\"flex-1 space-y-3\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-full\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction OtherAppCard({ app }: { app: ConnectedAppSummary }) {\n const t = useT();\n return (\n <a\n href={withBuilderUtmTrackingParams(app.url, {\n campaign: \"product\",\n content: \"dispatch_app\",\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"group flex min-h-[116px] items-start gap-3 rounded-xl border border-border/60 bg-card/40 p-4 transition-[background-color,border-color] hover:border-foreground/20 hover:bg-accent/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <span className=\"flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-xs font-semibold text-muted-foreground\">\n {app.name.charAt(0).toUpperCase()}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-start justify-between gap-3\">\n <span className=\"truncate text-sm font-semibold text-foreground\">\n {app.name}\n </span>\n <IconArrowUpRight\n size={15}\n className=\"shrink-0 text-muted-foreground transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5\"\n />\n </span>\n <span className=\"mt-2 line-clamp-2 block text-[13px] leading-5 text-muted-foreground\">\n {app.description || app.url}\n </span>\n <span className=\"mt-3 block text-xs font-medium text-foreground\">\n {t(\"dispatch.pages.openApp\")}\n </span>\n </span>\n </a>\n );\n}\n\nfunction AppsSkeletonGrid() {\n return (\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {Array.from({ length: 3 }).map((_, index) => (\n <div key={index} className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1 space-y-3\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-24\" />\n <div className=\"space-y-2 pt-1\">\n <Skeleton className=\"h-3 w-full\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n </div>\n <Skeleton className=\"h-7 w-7 rounded-md\" />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction EmptyAppsState() {\n const t = useT();\n return (\n <div className=\"rounded-lg border border-dashed bg-card px-4 py-10 text-center\">\n <div className=\"mx-auto flex size-10 items-center justify-center rounded-lg bg-muted text-muted-foreground\">\n <IconApps size={18} />\n </div>\n <h3 className=\"mt-3 text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.noWorkspaceApps\")}\n </h3>\n <p className=\"mx-auto mt-1 max-w-sm text-sm text-muted-foreground\">\n {t(\"dispatch.pages.noWorkspaceAppsDescription\")}\n </p>\n <div className=\"mt-4\">\n <CreateAppPopover\n trigger={\n <Button size=\"sm\">\n <IconPlus size={15} className=\"mr-1.5\" />\n {t(\"dispatch.pages.createApp\")}\n </Button>\n }\n />\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"apps.js","sourceRoot":"","sources":["../../../src/routes/pages/apps.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\nimport {\n IconApps,\n IconArrowUpRight,\n IconChevronDown,\n IconEyeOff,\n IconPlus,\n IconStack2,\n} from \"@tabler/icons-react\";\nimport { useState } from \"react\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { CreateAppPopover } from \"../../components/create-app-popover\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../../components/ui/collapsible\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { WorkspaceAppCard } from \"../../components/workspace-app-card\";\nimport {\n WorkspaceTemplatesSection,\n type CuratedWorkspaceTemplatesResult,\n type WorkspaceTemplateLabels,\n} from \"../../components/workspace-template-card\";\nimport {\n filterOtherApps,\n type ConnectedAppSummary,\n} from \"../../lib/other-apps\";\nimport { cn } from \"../../lib/utils\";\nimport type { WorkspaceAppSummary } from \"../../lib/workspace-apps\";\n\nexport function meta() {\n return [{ title: \"Apps — Dispatch\" }];\n}\n\ninterface WorkspaceInfo {\n name: string | null;\n displayName: string | null;\n appCount: number;\n}\n\nexport default function AppsRoute() {\n const t = useT();\n const [showHidden, setShowHidden] = useState(false);\n const appsQuery = useActionQuery(\"list-workspace-apps\", {\n includeAgentCards: false,\n includeArchived: true,\n });\n const connectedAppsQuery = useActionQuery(\"list-connected-agents\", {});\n const curatedTemplatesQuery = useActionQuery(\n \"list-curated-workspace-templates\",\n {},\n );\n const { data: apps = [], isLoading: appsLoading } = appsQuery;\n const { data: workspace } = useActionQuery(\n \"get-workspace-info\",\n {},\n { staleTime: 60_000 },\n );\n const ws = workspace as WorkspaceInfo | undefined;\n const workspaceLabel = ws?.displayName ?? ws?.name ?? null;\n const allApps = (apps as WorkspaceAppSummary[]).filter(\n (app) => !app.isDispatch,\n );\n const visibleApps = allApps.filter((app) => !app.archived);\n const archivedApps = allApps.filter((app) => app.archived);\n const otherApps = filterOtherApps(\n (connectedAppsQuery.data || []) as ConnectedAppSummary[],\n allApps,\n );\n const showAppSkeletons = appsLoading && allApps.length === 0;\n const templateLabels: WorkspaceTemplateLabels = {\n appId: t(\"dispatch.pages.remixAppIdLabel\"),\n appIdDescription: t(\"dispatch.pages.remixAppIdDescription\"),\n cancel: t(\"dispatch.pages.cancel\"),\n integrationSetup: t(\"dispatch.pages.integrationSetup\"),\n installed: t(\"dispatch.pages.alreadyInWorkspace\"),\n remix: t(\"dispatch.pages.remix\"),\n remixing: t(\"dispatch.pages.remixing\"),\n remixSuccess: t(\"dispatch.pages.remixSuccess\"),\n remixError: t(\"dispatch.pages.remixError\"),\n appIdRequired: t(\"dispatch.pages.appIdRequired\"),\n source: t(\"dispatch.pages.source\"),\n viewLiveApp: t(\"dispatch.pages.viewLiveApp\"),\n };\n\n return (\n <DispatchShell\n title={t(\"dispatch.nav.apps\")}\n description={\n workspaceLabel\n ? t(\"dispatch.pages.appsDescriptionWithWorkspace\", {\n workspace: workspaceLabel,\n })\n : t(\"dispatch.pages.appsDescription\")\n }\n >\n <div className=\"space-y-8\">\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div className=\"flex min-w-0 items-start gap-2\">\n <IconApps\n size={16}\n className=\"mt-0.5 shrink-0 text-muted-foreground\"\n />\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-sm font-semibold text-foreground\">\n {workspaceLabel\n ? t(\"dispatch.pages.appsInWorkspace\", {\n workspace: workspaceLabel,\n })\n : t(\"dispatch.pages.workspaceApps\")}\n </h2>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {t(\"dispatch.pages.activeCount\", {\n count: visibleApps.length,\n })}\n {archivedApps.length > 0\n ? ` · ${t(\"dispatch.pages.hiddenCount\", {\n count: archivedApps.length,\n })}`\n : \"\"}\n </p>\n </div>\n </div>\n {visibleApps.length > 0 ? (\n <CreateAppPopover\n align=\"end\"\n trigger={\n <Button size=\"sm\">\n <IconPlus size={15} className=\"mr-1.5\" />\n {t(\"dispatch.pages.createApp\")}\n </Button>\n }\n />\n ) : null}\n </div>\n\n {appsQuery.isError ? (\n <ActionQueryError\n error={appsQuery.error}\n onRetry={() => void appsQuery.refetch()}\n />\n ) : showAppSkeletons ? (\n <AppsSkeletonGrid />\n ) : visibleApps.length > 0 ? (\n <div className=\"grid auto-rows-fr gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {visibleApps.map((app) => (\n <WorkspaceAppCard key={app.id} app={app} className=\"h-full\" />\n ))}\n </div>\n ) : (\n <EmptyAppsState />\n )}\n </section>\n\n {curatedTemplatesQuery.isError ? (\n <section className=\"space-y-3 border-t pt-4\">\n <ActionQueryError\n error={curatedTemplatesQuery.error}\n onRetry={() => void curatedTemplatesQuery.refetch()}\n />\n </section>\n ) : curatedTemplatesQuery.data ? (\n <section className=\"space-y-3 border-t pt-4\">\n <div className=\"flex min-w-0 items-start gap-2\">\n <IconStack2\n size={16}\n className=\"mt-0.5 shrink-0 text-muted-foreground\"\n />\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.curatedTemplates\")}\n </h2>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {t(\"dispatch.pages.curatedTemplatesDescription\")}\n </p>\n </div>\n </div>\n <WorkspaceTemplatesSection\n templates={\n curatedTemplatesQuery.data as CuratedWorkspaceTemplatesResult\n }\n labels={templateLabels}\n onRemixSuccess={() => {\n void appsQuery.refetch();\n void curatedTemplatesQuery.refetch();\n }}\n />\n </section>\n ) : null}\n\n {connectedAppsQuery.isError ? (\n <section className=\"space-y-3 border-t pt-4\">\n <OtherAppsHeading count={0} />\n <ActionQueryError\n error={connectedAppsQuery.error}\n onRetry={() => void connectedAppsQuery.refetch()}\n />\n </section>\n ) : connectedAppsQuery.isLoading || otherApps.length > 0 ? (\n <section className=\"space-y-3 border-t pt-4\">\n <OtherAppsHeading count={otherApps.length} />\n {connectedAppsQuery.isLoading ? (\n <OtherAppsSkeletonGrid />\n ) : (\n <div className=\"grid auto-rows-fr gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {otherApps.map((app) => (\n <OtherAppCard key={app.id} app={app} />\n ))}\n </div>\n )}\n </section>\n ) : null}\n\n {archivedApps.length > 0 ? (\n <Collapsible open={showHidden} onOpenChange={setShowHidden}>\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-t pt-4\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <IconEyeOff\n size={16}\n className=\"shrink-0 text-muted-foreground\"\n />\n <div className=\"min-w-0\">\n <h2 className=\"text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.hiddenApps\")}\n </h2>\n <p className=\"text-xs text-muted-foreground\">\n {t(\"dispatch.pages.hiddenAppCount\", {\n count: archivedApps.length,\n })}\n </p>\n </div>\n </div>\n <CollapsibleTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"gap-1.5\"\n >\n {showHidden\n ? t(\"dispatch.pages.hide\")\n : t(\"dispatch.pages.show\")}\n <IconChevronDown\n size={14}\n className={cn(\n \"transition-transform\",\n showHidden && \"rotate-180\",\n )}\n />\n </Button>\n </CollapsibleTrigger>\n </div>\n <CollapsibleContent>\n <div className=\"grid auto-rows-fr gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {archivedApps.map((app) => (\n <WorkspaceAppCard\n key={app.id}\n app={app}\n className=\"h-full\"\n />\n ))}\n </div>\n </CollapsibleContent>\n </section>\n </Collapsible>\n ) : null}\n </div>\n </DispatchShell>\n );\n}\n\nfunction OtherAppsHeading({ count }: { count: number }) {\n const t = useT();\n return (\n <div className=\"flex min-w-0 items-start gap-2\">\n <IconStack2 size={16} className=\"mt-0.5 shrink-0 text-muted-foreground\" />\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.otherApps\")}\n </h2>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {t(\"dispatch.pages.otherAppsDescription\")}\n {count > 0\n ? ` · ${t(\"dispatch.pages.availableCount\", { count })}`\n : \"\"}\n </p>\n </div>\n </div>\n );\n}\n\nfunction OtherAppsSkeletonGrid() {\n return (\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {Array.from({ length: 3 }).map((_, index) => (\n <div key={index} className=\"rounded-lg bg-card p-4\">\n <div className=\"flex items-start gap-3\">\n <Skeleton className=\"size-8 rounded-md\" />\n <div className=\"flex-1 space-y-3\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-full\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction OtherAppCard({ app }: { app: ConnectedAppSummary }) {\n const t = useT();\n return (\n <a\n href={withBuilderUtmTrackingParams(app.url, {\n campaign: \"product\",\n content: \"dispatch_app\",\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"group flex min-h-[116px] items-start gap-3 rounded-xl bg-card/40 p-4 transition-[background-color] hover:bg-accent/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <span className=\"flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-xs font-semibold text-muted-foreground\">\n {app.name.charAt(0).toUpperCase()}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-start justify-between gap-3\">\n <span className=\"truncate text-sm font-semibold text-foreground\">\n {app.name}\n </span>\n <IconArrowUpRight\n size={15}\n className=\"shrink-0 text-muted-foreground transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5\"\n />\n </span>\n <span className=\"mt-2 line-clamp-2 block text-[13px] leading-5 text-muted-foreground\">\n {app.description || app.url}\n </span>\n <span className=\"mt-3 block text-xs font-medium text-foreground\">\n {t(\"dispatch.pages.openApp\")}\n </span>\n </span>\n </a>\n );\n}\n\nfunction AppsSkeletonGrid() {\n return (\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {Array.from({ length: 3 }).map((_, index) => (\n <div key={index} className=\"rounded-lg bg-card p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1 space-y-3\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-24\" />\n <div className=\"space-y-2 pt-1\">\n <Skeleton className=\"h-3 w-full\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n </div>\n <Skeleton className=\"h-7 w-7 rounded-md\" />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction EmptyAppsState() {\n const t = useT();\n return (\n <div className=\"rounded-lg border border-dashed bg-card px-4 py-10 text-center\">\n <div className=\"mx-auto flex size-10 items-center justify-center rounded-lg bg-muted text-muted-foreground\">\n <IconApps size={18} />\n </div>\n <h3 className=\"mt-3 text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.noWorkspaceApps\")}\n </h3>\n <p className=\"mx-auto mt-1 max-w-sm text-sm text-muted-foreground\">\n {t(\"dispatch.pages.noWorkspaceAppsDescription\")}\n </p>\n <div className=\"mt-4\">\n <CreateAppPopover\n trigger={\n <Button size=\"sm\">\n <IconPlus size={15} className=\"mr-1.5\" />\n {t(\"dispatch.pages.createApp\")}\n </Button>\n }\n />\n </div>\n </div>\n );\n}\n"]}
@@ -8,6 +8,6 @@ export function meta() {
8
8
  export default function AuditRoute() {
9
9
  const query = useActionQuery("list-dispatch-audit", { limit: 100 });
10
10
  const { data } = query;
11
- return (_jsx(DispatchShell, { title: "Audit", description: "Change history for routes, settings, and approvals.", children: _jsx("section", { className: "rounded-2xl border bg-card p-5", children: query.isError ? (_jsx(ActionQueryError, { error: query.error, onRetry: () => void query.refetch() })) : (_jsxs("div", { className: "space-y-3", children: [(data || []).map((event) => (_jsxs("div", { className: "rounded-xl border bg-muted/30 px-4 py-3", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: event.summary }), _jsxs("div", { className: "mt-1 text-xs text-muted-foreground", children: [event.actor, " \u00B7 ", event.action, " \u00B7", " ", new Date(event.createdAt).toLocaleString()] })] }, event.id))), (data?.length || 0) === 0 && (_jsx("div", { className: "rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground", children: "No audit entries yet." }))] })) }) }));
11
+ return (_jsx(DispatchShell, { title: "Audit", description: "Change history for routes, settings, and approvals.", children: _jsx("section", { className: "rounded-2xl bg-card p-5", children: query.isError ? (_jsx(ActionQueryError, { error: query.error, onRetry: () => void query.refetch() })) : (_jsxs("div", { className: "space-y-3", children: [(data || []).map((event) => (_jsxs("div", { className: "rounded-xl border bg-muted/30 px-4 py-3", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: event.summary }), _jsxs("div", { className: "mt-1 text-xs text-muted-foreground", children: [event.actor, " \u00B7 ", event.action, " \u00B7", " ", new Date(event.createdAt).toLocaleString()] })] }, event.id))), (data?.length || 0) === 0 && (_jsx("div", { className: "rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground", children: "No audit entries yet." }))] })) }) }));
12
12
  }
13
13
  //# sourceMappingURL=audit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/routes/pages/audit.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,UAAU;IAChC,MAAM,KAAK,GAAG,cAAc,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACpE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAEvB,OAAO,CACL,KAAC,aAAa,IACZ,KAAK,EAAC,OAAO,EACb,WAAW,EAAC,qDAAqD,YAEjE,kBAAS,SAAS,EAAC,gCAAgC,YAChD,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CACf,KAAC,gBAAgB,IACf,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,GACnC,CACH,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,WAAW,aACvB,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,CAChC,eAEE,SAAS,EAAC,yCAAyC,aAEnD,cAAK,SAAS,EAAC,qCAAqC,YACjD,KAAK,CAAC,OAAO,GACV,EACN,eAAK,SAAS,EAAC,oCAAoC,aAChD,KAAK,CAAC,KAAK,cAAK,KAAK,CAAC,MAAM,aAAI,GAAG,EACnC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,IACvC,KATD,KAAK,CAAC,EAAE,CAUT,CACP,CAAC,EACD,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAC5B,cAAK,SAAS,EAAC,yEAAyE,sCAElF,CACP,IACG,CACP,GACO,GACI,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { useActionQuery } from \"@agent-native/core/client/hooks\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\n\nexport function meta() {\n return [{ title: \"Audit — Dispatch\" }];\n}\n\nexport default function AuditRoute() {\n const query = useActionQuery(\"list-dispatch-audit\", { limit: 100 });\n const { data } = query;\n\n return (\n <DispatchShell\n title=\"Audit\"\n description=\"Change history for routes, settings, and approvals.\"\n >\n <section className=\"rounded-2xl border bg-card p-5\">\n {query.isError ? (\n <ActionQueryError\n error={query.error}\n onRetry={() => void query.refetch()}\n />\n ) : (\n <div className=\"space-y-3\">\n {(data || []).map((event: any) => (\n <div\n key={event.id}\n className=\"rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"text-sm font-medium text-foreground\">\n {event.summary}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {event.actor} · {event.action} ·{\" \"}\n {new Date(event.createdAt).toLocaleString()}\n </div>\n </div>\n ))}\n {(data?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No audit entries yet.\n </div>\n )}\n </div>\n )}\n </section>\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/routes/pages/audit.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,UAAU;IAChC,MAAM,KAAK,GAAG,cAAc,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACpE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAEvB,OAAO,CACL,KAAC,aAAa,IACZ,KAAK,EAAC,OAAO,EACb,WAAW,EAAC,qDAAqD,YAEjE,kBAAS,SAAS,EAAC,yBAAyB,YACzC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CACf,KAAC,gBAAgB,IACf,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,GACnC,CACH,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,WAAW,aACvB,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,CAChC,eAEE,SAAS,EAAC,yCAAyC,aAEnD,cAAK,SAAS,EAAC,qCAAqC,YACjD,KAAK,CAAC,OAAO,GACV,EACN,eAAK,SAAS,EAAC,oCAAoC,aAChD,KAAK,CAAC,KAAK,cAAK,KAAK,CAAC,MAAM,aAAI,GAAG,EACnC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,IACvC,KATD,KAAK,CAAC,EAAE,CAUT,CACP,CAAC,EACD,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAC5B,cAAK,SAAS,EAAC,yEAAyE,sCAElF,CACP,IACG,CACP,GACO,GACI,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { useActionQuery } from \"@agent-native/core/client/hooks\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\n\nexport function meta() {\n return [{ title: \"Audit — Dispatch\" }];\n}\n\nexport default function AuditRoute() {\n const query = useActionQuery(\"list-dispatch-audit\", { limit: 100 });\n const { data } = query;\n\n return (\n <DispatchShell\n title=\"Audit\"\n description=\"Change history for routes, settings, and approvals.\"\n >\n <section className=\"rounded-2xl bg-card p-5\">\n {query.isError ? (\n <ActionQueryError\n error={query.error}\n onRetry={() => void query.refetch()}\n />\n ) : (\n <div className=\"space-y-3\">\n {(data || []).map((event: any) => (\n <div\n key={event.id}\n className=\"rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"text-sm font-medium text-foreground\">\n {event.summary}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {event.actor} · {event.action} ·{\" \"}\n {new Date(event.createdAt).toLocaleString()}\n </div>\n </div>\n ))}\n {(data?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No audit entries yet.\n </div>\n )}\n </div>\n )}\n </section>\n </DispatchShell>\n );\n}\n"]}
@@ -94,7 +94,7 @@ export default function AutomationsRoute() {
94
94
  ? automationIdentity(toggleAutomation.variables)
95
95
  : null
96
96
  : null;
97
- return (_jsx(DispatchShell, { title: "Automations", description: "See scheduled and event-triggered jobs, pause them, or ask the agent to create one.", children: _jsxs("section", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2 text-sm text-muted-foreground", children: [_jsx(IconSettingsAutomation, { size: 16, className: "shrink-0" }), _jsxs("span", { children: [enabledCount, " enabled", errorCount > 0 ? ` · ${errorCount} errors` : ""] })] }), _jsx(CreateAutomationButton, {})] }), _jsx("div", { className: "divide-y rounded-lg border bg-card", children: automationsQuery.isLoading && ordered.length === 0 ? (Array.from({ length: 4 }).map((_, index) => (_jsxs("div", { className: "px-4 py-3", children: [_jsx(Skeleton, { className: "h-4 w-40" }), _jsx(Skeleton, { className: "mt-2 h-3 w-28" })] }, index)))) : ordered.length > 0 ? (ordered.map((item) => {
97
+ return (_jsx(DispatchShell, { title: "Automations", description: "See scheduled and event-triggered jobs, pause them, or ask the agent to create one.", children: _jsxs("section", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2 text-sm text-muted-foreground", children: [_jsx(IconSettingsAutomation, { size: 16, className: "shrink-0" }), _jsxs("span", { children: [enabledCount, " enabled", errorCount > 0 ? ` · ${errorCount} errors` : ""] })] }), _jsx(CreateAutomationButton, {})] }), _jsx("div", { className: "divide-y rounded-lg bg-card", children: automationsQuery.isLoading && ordered.length === 0 ? (Array.from({ length: 4 }).map((_, index) => (_jsxs("div", { className: "px-4 py-3", children: [_jsx(Skeleton, { className: "h-4 w-40" }), _jsx(Skeleton, { className: "mt-2 h-3 w-28" })] }, index)))) : ordered.length > 0 ? (ordered.map((item) => {
98
98
  const status = automationStatus(item);
99
99
  const canUpdate = item.canUpdate !== false;
100
100
  const isToggling = pendingToggleIdentity === automationIdentity(item);
@@ -1 +1 @@
1
- {"version":3,"file":"automations.js","sourceRoot":"","sources":["../../../src/routes/pages/automations.tsx"],"names":[],"mappings":"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","sourcesContent":["import { sendToAgentChat } from \"@agent-native/core/client/agent-chat\";\nimport { PromptComposer } from \"@agent-native/core/client/composer\";\nimport { useChangeVersions } from \"@agent-native/core/client/hooks\";\nimport {\n IconFileSearch,\n IconPlus,\n IconSettingsAutomation,\n} from \"@tabler/icons-react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMemo, useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { toast } from \"sonner\";\n\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../../components/ui/popover\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { Switch } from \"../../components/ui/switch\";\nimport {\n automationIdentity,\n automationLastRun,\n automationNextRun,\n automationStatus,\n automationTarget,\n automationTroubleshootPath,\n sortAutomations,\n type AutomationStatusTone,\n} from \"../../lib/automation-display\";\nimport {\n listDispatchAutomations,\n setDispatchAutomationEnabled,\n type DispatchAutomationItem,\n type SetDispatchAutomationEnabledInput,\n} from \"../../lib/automations\";\nimport { cn } from \"../../lib/utils\";\n\nconst AUTOMATIONS_QUERY_KEY = [\"dispatch-automations\"] as const;\n\nexport function meta() {\n return [{ title: \"Automations — Dispatch\" }];\n}\n\nfunction StatusDot({ tone }: { tone: AutomationStatusTone }) {\n return (\n <span\n className={cn(\n \"size-2 shrink-0 rounded-full\",\n tone === \"success\" && \"bg-emerald-500\",\n tone === \"warning\" && \"bg-amber-500\",\n tone === \"danger\" && \"bg-destructive\",\n tone === \"muted\" && \"bg-muted-foreground/35\",\n tone === \"default\" && \"bg-primary\",\n )}\n />\n );\n}\n\nfunction useAutomations() {\n const version = useChangeVersions([\"action\", \"screen-refresh\"]);\n return useQuery<DispatchAutomationItem[]>({\n queryKey: [...AUTOMATIONS_QUERY_KEY, version],\n queryFn: listDispatchAutomations,\n placeholderData: (prev) => prev,\n staleTime: 5_000,\n });\n}\n\nfunction useToggleAutomation() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: setDispatchAutomationEnabled,\n onMutate: async (input: SetDispatchAutomationEnabledInput) => {\n await queryClient.cancelQueries({ queryKey: AUTOMATIONS_QUERY_KEY });\n const snapshots = queryClient.getQueriesData<DispatchAutomationItem[]>({\n queryKey: AUTOMATIONS_QUERY_KEY,\n });\n\n queryClient.setQueriesData<DispatchAutomationItem[]>(\n { queryKey: AUTOMATIONS_QUERY_KEY },\n (rows) =>\n rows?.map((item) =>\n automationIdentity(item) === automationIdentity(input)\n ? { ...item, enabled: input.enabled }\n : item,\n ),\n );\n\n return { snapshots };\n },\n onError: (err, _input, context) => {\n for (const [queryKey, data] of context?.snapshots ?? []) {\n queryClient.setQueryData(queryKey, data);\n }\n toast.error(\n `Could not update automation: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n },\n onSuccess: (updated) => {\n queryClient.setQueriesData<DispatchAutomationItem[]>(\n { queryKey: AUTOMATIONS_QUERY_KEY },\n (rows) =>\n rows?.map((item) =>\n automationIdentity(item) === automationIdentity(updated)\n ? updated\n : item,\n ),\n );\n },\n onSettled: () => {\n void queryClient.invalidateQueries({ queryKey: AUTOMATIONS_QUERY_KEY });\n },\n });\n}\n\nfunction CreateAutomationButton() {\n const [open, setOpen] = useState(false);\n const [scope, setScope] = useState<\"personal\" | \"organization\">(\"personal\");\n\n function handleSubmit(text: string) {\n const trimmed = text.trim();\n if (!trimmed) return;\n window.dispatchEvent(\n new CustomEvent(\"agent-panel:set-mode\", {\n detail: { mode: \"chat\" },\n }),\n );\n sendToAgentChat({\n message: trimmed,\n 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.`,\n submit: true,\n newTab: true,\n });\n setOpen(false);\n }\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button size=\"sm\">\n <IconPlus size={14} />\n New automation\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-[min(100vw-2rem,24rem)] p-3\">\n <p className=\"pb-2 text-sm font-semibold text-foreground\">\n New automation\n </p>\n <PromptComposer\n autoFocus\n placeholder=\"Describe what you want to automate...\"\n draftScope=\"dispatch-automations:create\"\n onSubmit={handleSubmit}\n />\n <select\n value={scope}\n onChange={(event) =>\n setScope(event.target.value as \"personal\" | \"organization\")\n }\n className=\"mt-2 w-full cursor-pointer rounded-md border border-input bg-background px-3 py-1.5 text-xs text-foreground\"\n >\n <option value=\"personal\">Personal</option>\n <option value=\"organization\">Organization</option>\n </select>\n </PopoverContent>\n </Popover>\n );\n}\n\nexport default function AutomationsRoute() {\n const automationsQuery = useAutomations();\n const toggleAutomation = useToggleAutomation();\n const automations = automationsQuery.data ?? [];\n const ordered = useMemo(() => sortAutomations(automations), [automations]);\n const enabledCount = automations.filter((item) => item.enabled).length;\n const errorCount = automations.filter(\n (item) => item.enabled && item.lastStatus === \"error\",\n ).length;\n const pendingToggleIdentity = toggleAutomation.isPending\n ? toggleAutomation.variables\n ? automationIdentity(toggleAutomation.variables)\n : null\n : null;\n\n return (\n <DispatchShell\n title=\"Automations\"\n description=\"See scheduled and event-triggered jobs, pause them, or ask the agent to create one.\"\n >\n <section className=\"flex flex-col gap-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-2 text-sm text-muted-foreground\">\n <IconSettingsAutomation size={16} className=\"shrink-0\" />\n <span>\n {enabledCount} enabled\n {errorCount > 0 ? ` · ${errorCount} errors` : \"\"}\n </span>\n </div>\n <CreateAutomationButton />\n </div>\n\n <div className=\"divide-y rounded-lg border bg-card\">\n {automationsQuery.isLoading && ordered.length === 0 ? (\n Array.from({ length: 4 }).map((_, index) => (\n <div key={index} className=\"px-4 py-3\">\n <Skeleton className=\"h-4 w-40\" />\n <Skeleton className=\"mt-2 h-3 w-28\" />\n </div>\n ))\n ) : ordered.length > 0 ? (\n ordered.map((item) => {\n const status = automationStatus(item);\n const canUpdate = item.canUpdate !== false;\n const isToggling =\n pendingToggleIdentity === automationIdentity(item);\n return (\n <div\n key={item.id}\n className=\"grid grid-cols-[minmax(0,1fr)_auto] gap-3 px-4 py-3\"\n >\n <div className=\"min-w-0\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <StatusDot tone={status.tone} />\n <span className=\"truncate text-sm font-medium text-foreground\">\n {item.name}\n </span>\n </div>\n <div className=\"mt-1 truncate text-xs text-muted-foreground\">\n {automationTarget(item)}\n </div>\n <div className=\"mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground\">\n <span>Last {automationLastRun(item)}</span>\n <span>Next {automationNextRun(item)}</span>\n </div>\n {item.lastError ? (\n <div className=\"mt-1 flex flex-wrap items-baseline gap-x-2 gap-y-1 text-xs text-destructive\">\n <span className=\"min-w-0 break-words\">\n {item.lastError}\n </span>\n <Link\n to={automationTroubleshootPath(item)}\n className=\"inline-flex shrink-0 items-center gap-1 font-medium text-foreground underline-offset-4 hover:underline\"\n aria-label={`Troubleshoot ${item.name} in Thread Debug`}\n >\n <IconFileSearch size={13} aria-hidden=\"true\" />\n Troubleshoot in Thread Debug\n </Link>\n </div>\n ) : null}\n </div>\n <div className=\"flex flex-col items-end gap-2\">\n <Badge\n variant={\n status.tone === \"danger\" ? \"destructive\" : \"outline\"\n }\n className=\"h-5\"\n >\n {status.label}\n </Badge>\n <Switch\n checked={!!item.enabled}\n disabled={!canUpdate || isToggling}\n aria-label={`${item.enabled ? \"Disable\" : \"Enable\"} automation ${item.name}`}\n onCheckedChange={(checked) =>\n toggleAutomation.mutate({\n owner: item.owner,\n path: item.path,\n enabled: checked,\n })\n }\n />\n </div>\n </div>\n );\n })\n ) : (\n <div className=\"px-4 py-10 text-center text-sm text-muted-foreground\">\n No automations yet. Create one here, or ask Dispatch to set up a\n scheduled or event-triggered job.\n </div>\n )}\n </div>\n </section>\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"automations.js","sourceRoot":"","sources":["../../../src/routes/pages/automations.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EACL,cAAc,EACd,QAAQ,EACR,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,0BAA0B,EAC1B,eAAe,GAEhB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,uBAAuB,EACvB,4BAA4B,GAG7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAErC,MAAM,qBAAqB,GAAG,CAAC,sBAAsB,CAAU,CAAC;AAEhE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,IAAI,EAAkC;IACzD,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,8BAA8B,EAC9B,IAAI,KAAK,SAAS,IAAI,gBAAgB,EACtC,IAAI,KAAK,SAAS,IAAI,cAAc,EACpC,IAAI,KAAK,QAAQ,IAAI,gBAAgB,EACrC,IAAI,KAAK,OAAO,IAAI,wBAAwB,EAC5C,IAAI,KAAK,SAAS,IAAI,YAAY,CACnC,GACD,CACH,CAAC;AACJ,CAAC;AAED,SAAS,cAAc;IACrB,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAChE,OAAO,QAAQ,CAA2B;QACxC,QAAQ,EAAE,CAAC,GAAG,qBAAqB,EAAE,OAAO,CAAC;QAC7C,OAAO,EAAE,uBAAuB;QAChC,eAAe,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI;QAC/B,SAAS,EAAE,KAAK;KACjB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,4BAA4B;QACxC,QAAQ,EAAE,KAAK,EAAE,KAAwC,EAAE,EAAE;YAC3D,MAAM,WAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,qBAAqB,EAAE,CAAC,CAAC;YACrE,MAAM,SAAS,GAAG,WAAW,CAAC,cAAc,CAA2B;gBACrE,QAAQ,EAAE,qBAAqB;aAChC,CAAC,CAAC;YAEH,WAAW,CAAC,cAAc,CACxB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,EACnC,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACjB,kBAAkB,CAAC,IAAI,CAAC,KAAK,kBAAkB,CAAC,KAAK,CAAC;gBACpD,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;gBACrC,CAAC,CAAC,IAAI,CACT,CACJ,CAAC;YAEF,OAAO,EAAE,SAAS,EAAE,CAAC;QACvB,CAAC;QACD,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;YAChC,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,SAAS,IAAI,EAAE,EAAE,CAAC;gBACxD,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC3C,CAAC;YACD,KAAK,CAAC,KAAK,CACT,gCACE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,EAAE,CACH,CAAC;QACJ,CAAC;QACD,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;YACrB,WAAW,CAAC,cAAc,CACxB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,EACnC,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACjB,kBAAkB,CAAC,IAAI,CAAC,KAAK,kBAAkB,CAAC,OAAO,CAAC;gBACtD,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,IAAI,CACT,CACJ,CAAC;QACJ,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,KAAK,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC1E,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,sBAAsB;IAC7B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAA8B,UAAU,CAAC,CAAC;IAE5E,SAAS,YAAY,CAAC,IAAY;QAChC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,CAAC,aAAa,CAClB,IAAI,WAAW,CAAC,sBAAsB,EAAE;YACtC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;SACzB,CAAC,CACH,CAAC;QACF,eAAe,CAAC;YACd,OAAO,EAAE,OAAO;YAChB,OAAO,EAAE,qDAAqD,KAAK,oKAAoK;YACvO,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,CACL,MAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,aACxC,KAAC,cAAc,IAAC,OAAO,kBACrB,MAAC,MAAM,IAAC,IAAI,EAAC,IAAI,aACf,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,GAAI,sBAEf,GACM,EACjB,MAAC,cAAc,IAAC,KAAK,EAAC,KAAK,EAAC,SAAS,EAAC,+BAA+B,aACnE,YAAG,SAAS,EAAC,4CAA4C,+BAErD,EACJ,KAAC,cAAc,IACb,SAAS,QACT,WAAW,EAAC,uCAAuC,EACnD,UAAU,EAAC,6BAA6B,EACxC,QAAQ,EAAE,YAAY,GACtB,EACF,kBACE,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAoC,CAAC,EAE7D,SAAS,EAAC,6GAA6G,aAEvH,iBAAQ,KAAK,EAAC,UAAU,yBAAkB,EAC1C,iBAAQ,KAAK,EAAC,cAAc,6BAAsB,IAC3C,IACM,IACT,CACX,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB;IACtC,MAAM,gBAAgB,GAAG,cAAc,EAAE,CAAC;IAC1C,MAAM,gBAAgB,GAAG,mBAAmB,EAAE,CAAC;IAC/C,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,IAAI,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IACvE,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CACnC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO,CACtD,CAAC,MAAM,CAAC;IACT,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,SAAS;QACtD,CAAC,CAAC,gBAAgB,CAAC,SAAS;YAC1B,CAAC,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAChD,CAAC,CAAC,IAAI;QACR,CAAC,CAAC,IAAI,CAAC;IAET,OAAO,CACL,KAAC,aAAa,IACZ,KAAK,EAAC,aAAa,EACnB,WAAW,EAAC,qFAAqF,YAEjG,mBAAS,SAAS,EAAC,qBAAqB,aACtC,eAAK,SAAS,EAAC,mDAAmD,aAChE,eAAK,SAAS,EAAC,+DAA+D,aAC5E,KAAC,sBAAsB,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,UAAU,GAAG,EACzD,2BACG,YAAY,cACZ,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,UAAU,SAAS,CAAC,CAAC,CAAC,EAAE,IAC3C,IACH,EACN,KAAC,sBAAsB,KAAG,IACtB,EAEN,cAAK,SAAS,EAAC,6BAA6B,YACzC,gBAAgB,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACpD,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1C,eAAiB,SAAS,EAAC,WAAW,aACpC,KAAC,QAAQ,IAAC,SAAS,EAAC,UAAU,GAAG,EACjC,KAAC,QAAQ,IAAC,SAAS,EAAC,eAAe,GAAG,KAF9B,KAAK,CAGT,CACP,CAAC,CACH,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACvB,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;wBACnB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;wBACtC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;wBAC3C,MAAM,UAAU,GACd,qBAAqB,KAAK,kBAAkB,CAAC,IAAI,CAAC,CAAC;wBACrD,OAAO,CACL,eAEE,SAAS,EAAC,qDAAqD,aAE/D,eAAK,SAAS,EAAC,SAAS,aACtB,eAAK,SAAS,EAAC,iCAAiC,aAC9C,KAAC,SAAS,IAAC,IAAI,EAAE,MAAM,CAAC,IAAI,GAAI,EAChC,eAAM,SAAS,EAAC,8CAA8C,YAC3D,IAAI,CAAC,IAAI,GACL,IACH,EACN,cAAK,SAAS,EAAC,6CAA6C,YACzD,gBAAgB,CAAC,IAAI,CAAC,GACnB,EACN,eAAK,SAAS,EAAC,uEAAuE,aACpF,oCAAY,iBAAiB,CAAC,IAAI,CAAC,IAAQ,EAC3C,oCAAY,iBAAiB,CAAC,IAAI,CAAC,IAAQ,IACvC,EACL,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAChB,eAAK,SAAS,EAAC,6EAA6E,aAC1F,eAAM,SAAS,EAAC,qBAAqB,YAClC,IAAI,CAAC,SAAS,GACV,EACP,MAAC,IAAI,IACH,EAAE,EAAE,0BAA0B,CAAC,IAAI,CAAC,EACpC,SAAS,EAAC,wGAAwG,gBACtG,gBAAgB,IAAI,CAAC,IAAI,kBAAkB,aAEvD,KAAC,cAAc,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,oCAE1C,IACH,CACP,CAAC,CAAC,CAAC,IAAI,IACJ,EACN,eAAK,SAAS,EAAC,+BAA+B,aAC5C,KAAC,KAAK,IACJ,OAAO,EACL,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,EAEtD,SAAS,EAAC,KAAK,YAEd,MAAM,CAAC,KAAK,GACP,EACR,KAAC,MAAM,IACL,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,EACvB,QAAQ,EAAE,CAAC,SAAS,IAAI,UAAU,gBACtB,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,eAAe,IAAI,CAAC,IAAI,EAAE,EAC5E,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE,CAC3B,gBAAgB,CAAC,MAAM,CAAC;gDACtB,KAAK,EAAE,IAAI,CAAC,KAAK;gDACjB,IAAI,EAAE,IAAI,CAAC,IAAI;gDACf,OAAO,EAAE,OAAO;6CACjB,CAAC,GAEJ,IACE,KAtDD,IAAI,CAAC,EAAE,CAuDR,CACP,CAAC;oBACJ,CAAC,CAAC,CACH,CAAC,CAAC,CAAC,CACF,cAAK,SAAS,EAAC,sDAAsD,mHAG/D,CACP,GACG,IACE,GACI,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { sendToAgentChat } from \"@agent-native/core/client/agent-chat\";\nimport { PromptComposer } from \"@agent-native/core/client/composer\";\nimport { useChangeVersions } from \"@agent-native/core/client/hooks\";\nimport {\n IconFileSearch,\n IconPlus,\n IconSettingsAutomation,\n} from \"@tabler/icons-react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMemo, useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { toast } from \"sonner\";\n\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../../components/ui/popover\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { Switch } from \"../../components/ui/switch\";\nimport {\n automationIdentity,\n automationLastRun,\n automationNextRun,\n automationStatus,\n automationTarget,\n automationTroubleshootPath,\n sortAutomations,\n type AutomationStatusTone,\n} from \"../../lib/automation-display\";\nimport {\n listDispatchAutomations,\n setDispatchAutomationEnabled,\n type DispatchAutomationItem,\n type SetDispatchAutomationEnabledInput,\n} from \"../../lib/automations\";\nimport { cn } from \"../../lib/utils\";\n\nconst AUTOMATIONS_QUERY_KEY = [\"dispatch-automations\"] as const;\n\nexport function meta() {\n return [{ title: \"Automations — Dispatch\" }];\n}\n\nfunction StatusDot({ tone }: { tone: AutomationStatusTone }) {\n return (\n <span\n className={cn(\n \"size-2 shrink-0 rounded-full\",\n tone === \"success\" && \"bg-emerald-500\",\n tone === \"warning\" && \"bg-amber-500\",\n tone === \"danger\" && \"bg-destructive\",\n tone === \"muted\" && \"bg-muted-foreground/35\",\n tone === \"default\" && \"bg-primary\",\n )}\n />\n );\n}\n\nfunction useAutomations() {\n const version = useChangeVersions([\"action\", \"screen-refresh\"]);\n return useQuery<DispatchAutomationItem[]>({\n queryKey: [...AUTOMATIONS_QUERY_KEY, version],\n queryFn: listDispatchAutomations,\n placeholderData: (prev) => prev,\n staleTime: 5_000,\n });\n}\n\nfunction useToggleAutomation() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: setDispatchAutomationEnabled,\n onMutate: async (input: SetDispatchAutomationEnabledInput) => {\n await queryClient.cancelQueries({ queryKey: AUTOMATIONS_QUERY_KEY });\n const snapshots = queryClient.getQueriesData<DispatchAutomationItem[]>({\n queryKey: AUTOMATIONS_QUERY_KEY,\n });\n\n queryClient.setQueriesData<DispatchAutomationItem[]>(\n { queryKey: AUTOMATIONS_QUERY_KEY },\n (rows) =>\n rows?.map((item) =>\n automationIdentity(item) === automationIdentity(input)\n ? { ...item, enabled: input.enabled }\n : item,\n ),\n );\n\n return { snapshots };\n },\n onError: (err, _input, context) => {\n for (const [queryKey, data] of context?.snapshots ?? []) {\n queryClient.setQueryData(queryKey, data);\n }\n toast.error(\n `Could not update automation: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n },\n onSuccess: (updated) => {\n queryClient.setQueriesData<DispatchAutomationItem[]>(\n { queryKey: AUTOMATIONS_QUERY_KEY },\n (rows) =>\n rows?.map((item) =>\n automationIdentity(item) === automationIdentity(updated)\n ? updated\n : item,\n ),\n );\n },\n onSettled: () => {\n void queryClient.invalidateQueries({ queryKey: AUTOMATIONS_QUERY_KEY });\n },\n });\n}\n\nfunction CreateAutomationButton() {\n const [open, setOpen] = useState(false);\n const [scope, setScope] = useState<\"personal\" | \"organization\">(\"personal\");\n\n function handleSubmit(text: string) {\n const trimmed = text.trim();\n if (!trimmed) return;\n window.dispatchEvent(\n new CustomEvent(\"agent-panel:set-mode\", {\n detail: { mode: \"chat\" },\n }),\n );\n sendToAgentChat({\n message: trimmed,\n 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.`,\n submit: true,\n newTab: true,\n });\n setOpen(false);\n }\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button size=\"sm\">\n <IconPlus size={14} />\n New automation\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-[min(100vw-2rem,24rem)] p-3\">\n <p className=\"pb-2 text-sm font-semibold text-foreground\">\n New automation\n </p>\n <PromptComposer\n autoFocus\n placeholder=\"Describe what you want to automate...\"\n draftScope=\"dispatch-automations:create\"\n onSubmit={handleSubmit}\n />\n <select\n value={scope}\n onChange={(event) =>\n setScope(event.target.value as \"personal\" | \"organization\")\n }\n className=\"mt-2 w-full cursor-pointer rounded-md border border-input bg-background px-3 py-1.5 text-xs text-foreground\"\n >\n <option value=\"personal\">Personal</option>\n <option value=\"organization\">Organization</option>\n </select>\n </PopoverContent>\n </Popover>\n );\n}\n\nexport default function AutomationsRoute() {\n const automationsQuery = useAutomations();\n const toggleAutomation = useToggleAutomation();\n const automations = automationsQuery.data ?? [];\n const ordered = useMemo(() => sortAutomations(automations), [automations]);\n const enabledCount = automations.filter((item) => item.enabled).length;\n const errorCount = automations.filter(\n (item) => item.enabled && item.lastStatus === \"error\",\n ).length;\n const pendingToggleIdentity = toggleAutomation.isPending\n ? toggleAutomation.variables\n ? automationIdentity(toggleAutomation.variables)\n : null\n : null;\n\n return (\n <DispatchShell\n title=\"Automations\"\n description=\"See scheduled and event-triggered jobs, pause them, or ask the agent to create one.\"\n >\n <section className=\"flex flex-col gap-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-2 text-sm text-muted-foreground\">\n <IconSettingsAutomation size={16} className=\"shrink-0\" />\n <span>\n {enabledCount} enabled\n {errorCount > 0 ? ` · ${errorCount} errors` : \"\"}\n </span>\n </div>\n <CreateAutomationButton />\n </div>\n\n <div className=\"divide-y rounded-lg bg-card\">\n {automationsQuery.isLoading && ordered.length === 0 ? (\n Array.from({ length: 4 }).map((_, index) => (\n <div key={index} className=\"px-4 py-3\">\n <Skeleton className=\"h-4 w-40\" />\n <Skeleton className=\"mt-2 h-3 w-28\" />\n </div>\n ))\n ) : ordered.length > 0 ? (\n ordered.map((item) => {\n const status = automationStatus(item);\n const canUpdate = item.canUpdate !== false;\n const isToggling =\n pendingToggleIdentity === automationIdentity(item);\n return (\n <div\n key={item.id}\n className=\"grid grid-cols-[minmax(0,1fr)_auto] gap-3 px-4 py-3\"\n >\n <div className=\"min-w-0\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <StatusDot tone={status.tone} />\n <span className=\"truncate text-sm font-medium text-foreground\">\n {item.name}\n </span>\n </div>\n <div className=\"mt-1 truncate text-xs text-muted-foreground\">\n {automationTarget(item)}\n </div>\n <div className=\"mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground\">\n <span>Last {automationLastRun(item)}</span>\n <span>Next {automationNextRun(item)}</span>\n </div>\n {item.lastError ? (\n <div className=\"mt-1 flex flex-wrap items-baseline gap-x-2 gap-y-1 text-xs text-destructive\">\n <span className=\"min-w-0 break-words\">\n {item.lastError}\n </span>\n <Link\n to={automationTroubleshootPath(item)}\n className=\"inline-flex shrink-0 items-center gap-1 font-medium text-foreground underline-offset-4 hover:underline\"\n aria-label={`Troubleshoot ${item.name} in Thread Debug`}\n >\n <IconFileSearch size={13} aria-hidden=\"true\" />\n Troubleshoot in Thread Debug\n </Link>\n </div>\n ) : null}\n </div>\n <div className=\"flex flex-col items-end gap-2\">\n <Badge\n variant={\n status.tone === \"danger\" ? \"destructive\" : \"outline\"\n }\n className=\"h-5\"\n >\n {status.label}\n </Badge>\n <Switch\n checked={!!item.enabled}\n disabled={!canUpdate || isToggling}\n aria-label={`${item.enabled ? \"Disable\" : \"Enable\"} automation ${item.name}`}\n onCheckedChange={(checked) =>\n toggleAutomation.mutate({\n owner: item.owner,\n path: item.path,\n enabled: checked,\n })\n }\n />\n </div>\n </div>\n );\n })\n ) : (\n <div className=\"px-4 py-10 text-center text-sm text-muted-foreground\">\n No automations yet. Create one here, or ask Dispatch to set up a\n scheduled or event-triggered job.\n </div>\n )}\n </div>\n </section>\n </DispatchShell>\n );\n}\n"]}