@agent-native/dispatch 0.1.1 → 0.2.3
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.
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +2 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/list-dispatch-usage-metrics.d.ts +3 -0
- package/dist/actions/list-dispatch-usage-metrics.d.ts.map +1 -0
- package/dist/actions/list-dispatch-usage-metrics.js +18 -0
- package/dist/actions/list-dispatch-usage-metrics.js.map +1 -0
- package/dist/actions/navigate.d.ts +1 -0
- package/dist/actions/navigate.d.ts.map +1 -1
- package/dist/actions/navigate.js +3 -17
- package/dist/actions/navigate.js.map +1 -1
- package/dist/actions/view-screen.d.ts.map +1 -1
- package/dist/actions/view-screen.js +19 -0
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/agents-panel.js +3 -3
- package/dist/components/app-keys-popover.js +2 -2
- package/dist/components/create-app-popover.js +2 -2
- package/dist/components/dispatch-shell.js +2 -2
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/layout/Header.js +5 -5
- package/dist/components/layout/Header.js.map +1 -1
- package/dist/components/layout/Layout.d.ts +28 -3
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +138 -28
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/messaging-setup-panel.js +4 -4
- package/dist/components/ui/accordion.js +1 -1
- package/dist/components/ui/alert-dialog.js +2 -2
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/avatar.js +1 -1
- package/dist/components/ui/badge.js +1 -1
- package/dist/components/ui/breadcrumb.js +1 -1
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/calendar.js +2 -2
- package/dist/components/ui/card.js +1 -1
- package/dist/components/ui/carousel.d.ts +2 -2
- package/dist/components/ui/carousel.js +2 -2
- package/dist/components/ui/chart.js +1 -1
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/command.js +2 -2
- package/dist/components/ui/context-menu.js +1 -1
- package/dist/components/ui/dialog.js +1 -1
- package/dist/components/ui/drawer.js +1 -1
- package/dist/components/ui/dropdown-menu.js +1 -1
- package/dist/components/ui/form.js +2 -2
- package/dist/components/ui/hover-card.js +1 -1
- package/dist/components/ui/input-otp.js +1 -1
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/label.js +1 -1
- package/dist/components/ui/menubar.js +1 -1
- package/dist/components/ui/navigation-menu.js +1 -1
- package/dist/components/ui/pagination.d.ts +1 -1
- package/dist/components/ui/pagination.js +2 -2
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/progress.js +1 -1
- package/dist/components/ui/radio-group.js +1 -1
- package/dist/components/ui/resizable.js +1 -1
- package/dist/components/ui/scroll-area.js +1 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/separator.js +1 -1
- package/dist/components/ui/sheet.js +1 -1
- package/dist/components/ui/sidebar.d.ts +2 -2
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/sidebar.js +9 -9
- package/dist/components/ui/sidebar.js.map +1 -1
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/slider.js +1 -1
- package/dist/components/ui/sonner.js +1 -1
- package/dist/components/ui/spinner.js +1 -1
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/table.js +1 -1
- package/dist/components/ui/tabs.js +1 -1
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/toast.js +1 -1
- package/dist/components/ui/toaster.js +2 -2
- package/dist/components/ui/toggle-group.js +2 -2
- package/dist/components/ui/toggle.js +1 -1
- package/dist/components/ui/tooltip.js +1 -1
- package/dist/components/ui/use-toast.d.ts +1 -1
- package/dist/components/ui/use-toast.js +1 -1
- package/dist/hooks/use-navigation-state.d.ts +2 -1
- package/dist/hooks/use-navigation-state.d.ts.map +1 -1
- package/dist/hooks/use-navigation-state.js +36 -8
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/hooks/use-toast.d.ts +1 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +3 -2
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/pages/_index.js +1 -1
- package/dist/routes/pages/agents.js +2 -2
- package/dist/routes/pages/approval.js +2 -2
- package/dist/routes/pages/approvals.js +4 -4
- package/dist/routes/pages/apps.$appId.js +3 -3
- package/dist/routes/pages/apps.js +5 -5
- package/dist/routes/pages/audit.js +1 -1
- package/dist/routes/pages/destinations.js +6 -6
- package/dist/routes/pages/extensions.$id.d.ts +2 -0
- package/dist/routes/pages/extensions.$id.d.ts.map +1 -0
- package/dist/routes/pages/extensions.$id.js +6 -0
- package/dist/routes/pages/extensions.$id.js.map +1 -0
- package/dist/routes/pages/extensions._index.d.ts +2 -0
- package/dist/routes/pages/extensions._index.d.ts.map +1 -0
- package/dist/routes/pages/extensions._index.js +6 -0
- package/dist/routes/pages/extensions._index.js.map +1 -0
- package/dist/routes/pages/identities.js +2 -2
- package/dist/routes/pages/integrations.js +4 -4
- package/dist/routes/pages/messaging.js +2 -2
- package/dist/routes/pages/metrics.d.ts +5 -0
- package/dist/routes/pages/metrics.d.ts.map +1 -0
- package/dist/routes/pages/metrics.js +135 -0
- package/dist/routes/pages/metrics.js.map +1 -0
- package/dist/routes/pages/new-app.js +1 -1
- package/dist/routes/pages/overview.d.ts.map +1 -1
- package/dist/routes/pages/overview.js +9 -17
- package/dist/routes/pages/overview.js.map +1 -1
- package/dist/routes/pages/team.js +1 -1
- package/dist/routes/pages/vault.js +10 -10
- package/dist/routes/pages/workspace.js +10 -10
- package/dist/server/lib/pre-auth-routing.d.ts.map +1 -1
- package/dist/server/lib/pre-auth-routing.js +9 -2
- package/dist/server/lib/pre-auth-routing.js.map +1 -1
- package/dist/server/lib/usage-metrics-store.d.ts +93 -0
- package/dist/server/lib/usage-metrics-store.d.ts.map +1 -0
- package/dist/server/lib/usage-metrics-store.js +386 -0
- package/dist/server/lib/usage-metrics-store.js.map +1 -0
- package/package.json +11 -6
- package/src/actions/index.ts +2 -0
- package/src/actions/list-dispatch-usage-metrics.ts +19 -0
- package/src/actions/navigate.ts +5 -17
- package/src/actions/view-screen.ts +18 -0
- package/src/components/index.ts +6 -0
- package/src/components/layout/Header.tsx +2 -2
- package/src/components/layout/Layout.tsx +197 -48
- package/src/components/ui/sidebar.tsx +22 -18
- package/src/hooks/use-navigation-state.ts +57 -8
- package/src/routes/index.ts +3 -2
- package/src/routes/pages/extensions.$id.tsx +5 -0
- package/src/routes/pages/extensions._index.tsx +5 -0
- package/src/routes/pages/metrics.tsx +667 -0
- package/src/routes/pages/overview.tsx +0 -10
- package/src/server/lib/pre-auth-routing.ts +10 -2
- package/src/server/lib/usage-metrics-store.ts +605 -0
- package/src/styles/dispatch-css.spec.ts +55 -0
- package/src/styles/dispatch.css +9 -0
|
@@ -2,14 +2,14 @@ import { useEffect } from "react";
|
|
|
2
2
|
import { useLocation, useNavigate } from "react-router";
|
|
3
3
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
4
|
import { agentNativePath, appBasePath, appPath, } from "@agent-native/core/client";
|
|
5
|
-
export function useNavigationState() {
|
|
5
|
+
export function useNavigationState(extensions) {
|
|
6
6
|
const location = useLocation();
|
|
7
7
|
const navigate = useNavigate();
|
|
8
8
|
const qc = useQueryClient();
|
|
9
9
|
// Sync current route to application state
|
|
10
10
|
useEffect(() => {
|
|
11
11
|
const state = {
|
|
12
|
-
view: resolveView(location.pathname),
|
|
12
|
+
view: resolveView(location.pathname, extensions),
|
|
13
13
|
path: appPath(location.pathname),
|
|
14
14
|
};
|
|
15
15
|
fetch(agentNativePath("/_agent-native/application-state/navigation"), {
|
|
@@ -18,7 +18,7 @@ export function useNavigationState() {
|
|
|
18
18
|
headers: { "Content-Type": "application/json" },
|
|
19
19
|
body: JSON.stringify(state),
|
|
20
20
|
}).catch(() => { });
|
|
21
|
-
}, [location.pathname]);
|
|
21
|
+
}, [extensions, location.pathname]);
|
|
22
22
|
// Listen for navigate commands from agent
|
|
23
23
|
const { data: navCommand } = useQuery({
|
|
24
24
|
queryKey: ["navigate-command"],
|
|
@@ -47,10 +47,10 @@ export function useNavigationState() {
|
|
|
47
47
|
}).catch(() => { });
|
|
48
48
|
const cmd = navCommand;
|
|
49
49
|
// Navigate to a specific path or resolve view name to path
|
|
50
|
-
const path = routerPath(cmd.path || resolvePath(cmd.view) || "/overview");
|
|
50
|
+
const path = routerPath(cmd.path || resolvePath(cmd.view, extensions) || "/overview");
|
|
51
51
|
navigate(path);
|
|
52
52
|
qc.setQueryData(["navigate-command"], null);
|
|
53
|
-
}, [navCommand, navigate, qc]);
|
|
53
|
+
}, [extensions, navCommand, navigate, qc]);
|
|
54
54
|
}
|
|
55
55
|
function routerPath(path) {
|
|
56
56
|
const basePath = appBasePath();
|
|
@@ -63,9 +63,34 @@ function routerPath(path) {
|
|
|
63
63
|
}
|
|
64
64
|
return path;
|
|
65
65
|
}
|
|
66
|
-
function
|
|
66
|
+
function extensionItemMatchesPath(item, pathname) {
|
|
67
|
+
if (item.match) {
|
|
68
|
+
try {
|
|
69
|
+
if (item.match(pathname))
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return pathname === item.to || pathname.startsWith(`${item.to}/`);
|
|
77
|
+
}
|
|
78
|
+
function resolveExtensionView(pathname, extensions) {
|
|
79
|
+
return extensions?.navItems?.find((item) => extensionItemMatchesPath(item, pathname))?.id;
|
|
80
|
+
}
|
|
81
|
+
function resolveExtensionPath(view, extensions) {
|
|
82
|
+
if (!view)
|
|
83
|
+
return undefined;
|
|
84
|
+
return extensions?.navItems?.find((item) => item.id === view)?.to;
|
|
85
|
+
}
|
|
86
|
+
function resolveView(pathname, extensions) {
|
|
87
|
+
const extensionView = resolveExtensionView(pathname, extensions);
|
|
88
|
+
if (extensionView)
|
|
89
|
+
return extensionView;
|
|
67
90
|
if (pathname.startsWith("/apps"))
|
|
68
91
|
return "apps";
|
|
92
|
+
if (pathname.startsWith("/metrics"))
|
|
93
|
+
return "metrics";
|
|
69
94
|
if (pathname.startsWith("/new-app"))
|
|
70
95
|
return "new-app";
|
|
71
96
|
if (pathname.startsWith("/vault"))
|
|
@@ -90,12 +115,15 @@ function resolveView(pathname) {
|
|
|
90
115
|
return "team";
|
|
91
116
|
return "overview";
|
|
92
117
|
}
|
|
93
|
-
function resolvePath(view) {
|
|
118
|
+
function resolvePath(view, extensions) {
|
|
94
119
|
switch (view) {
|
|
95
120
|
case "overview":
|
|
96
121
|
return "/overview";
|
|
97
122
|
case "apps":
|
|
98
123
|
return "/apps";
|
|
124
|
+
case "metrics":
|
|
125
|
+
case "usage":
|
|
126
|
+
return "/metrics";
|
|
99
127
|
case "new-app":
|
|
100
128
|
case "create-app":
|
|
101
129
|
return "/new-app";
|
|
@@ -123,7 +151,7 @@ function resolvePath(view) {
|
|
|
123
151
|
case "team":
|
|
124
152
|
return "/team";
|
|
125
153
|
default:
|
|
126
|
-
return
|
|
154
|
+
return resolveExtensionPath(view, extensions);
|
|
127
155
|
}
|
|
128
156
|
}
|
|
129
157
|
//# sourceMappingURL=use-navigation-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-navigation-state.js","sourceRoot":"","sources":["../../src/hooks/use-navigation-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect } from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n agentNativePath,\n appBasePath,\n appPath,\n} from \"@agent-native/core/client\";\n\nexport interface NavigationState {\n view: string;\n path?: string;\n}\n\nexport function useNavigationState() {\n const location = useLocation();\n const navigate = useNavigate();\n const qc = useQueryClient();\n\n // Sync current route to application state\n useEffect(() => {\n const state: NavigationState = {\n view: resolveView(location.pathname),\n path: appPath(location.pathname),\n };\n\n fetch(agentNativePath(\"/_agent-native/application-state/navigation\"), {\n method: \"PUT\",\n keepalive: true,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(state),\n }).catch(() => {});\n }, [location.pathname]);\n\n // Listen for navigate commands from agent\n const { data: navCommand } = useQuery({\n queryKey: [\"navigate-command\"],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(\"/_agent-native/application-state/navigate\"),\n );\n if (!res.ok) return null;\n const data = await res.json();\n if (data) {\n // Return with a timestamp to ensure uniqueness\n return { ...data, _ts: Date.now() };\n }\n return null;\n },\n refetchInterval: 2_000,\n refetchIntervalInBackground: true,\n structuralSharing: false,\n });\n\n useEffect(() => {\n if (!navCommand) return;\n // Delete the one-shot command AFTER reading it\n fetch(agentNativePath(\"/_agent-native/application-state/navigate\"), {\n method: \"DELETE\",\n headers: { \"X-Agent-Native-CSRF\": \"1\" },\n }).catch(() => {});\n const cmd = navCommand as NavigationState;\n\n // Navigate to a specific path or resolve view name to path\n const path = routerPath(cmd.path || resolvePath(cmd.view) || \"/overview\");\n navigate(path);\n qc.setQueryData([\"navigate-command\"], null);\n }, [navCommand, navigate, qc]);\n}\n\nfunction routerPath(path: string): string {\n const basePath = appBasePath();\n if (!basePath) return path;\n if (path === basePath) return \"/\";\n if (path.startsWith(`${basePath}/`)) {\n return path.slice(basePath.length) || \"/\";\n }\n return path;\n}\n\nfunction resolveView(pathname: string): string {\n if (pathname.startsWith(\"/apps\")) return \"apps\";\n if (pathname.startsWith(\"/new-app\")) return \"new-app\";\n if (pathname.startsWith(\"/vault\")) return \"vault\";\n if (pathname.startsWith(\"/integrations\")) return \"integrations\";\n if (pathname.startsWith(\"/workspace\")) return \"workspace\";\n if (pathname.startsWith(\"/agents\")) return \"agents\";\n if (pathname.startsWith(\"/messaging\")) return \"messaging\";\n if (pathname.startsWith(\"/destinations\")) return \"destinations\";\n if (pathname.startsWith(\"/identities\")) return \"identities\";\n if (pathname.startsWith(\"/approvals\")) return \"approvals\";\n if (pathname.startsWith(\"/audit\")) return \"audit\";\n if (pathname.startsWith(\"/team\")) return \"team\";\n return \"overview\";\n}\n\nfunction resolvePath(view?: string): string | undefined {\n switch (view) {\n case \"overview\":\n return \"/overview\";\n case \"apps\":\n return \"/apps\";\n case \"new-app\":\n case \"create-app\":\n return \"/new-app\";\n case \"vault\":\n case \"secrets\":\n return \"/vault\";\n case \"integrations\":\n return \"/integrations\";\n case \"workspace\":\n case \"resources\":\n return \"/workspace\";\n case \"agents\":\n return \"/agents\";\n case \"messaging\":\n return \"/messaging\";\n case \"destinations\":\n case \"routes\":\n return \"/destinations\";\n case \"identities\":\n return \"/identities\";\n case \"approvals\":\n return \"/approvals\";\n case \"audit\":\n return \"/audit\";\n case \"team\":\n return \"/team\";\n default:\n return undefined;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-navigation-state.js","sourceRoot":"","sources":["../../src/hooks/use-navigation-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect } from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport {\n agentNativePath,\n appBasePath,\n appPath,\n} from \"@agent-native/core/client\";\nimport type {\n DispatchExtensionConfig,\n DispatchNavItem,\n} from \"../components/index.js\";\n\nexport interface NavigationState {\n view: string;\n path?: string;\n}\n\nexport function useNavigationState(extensions?: DispatchExtensionConfig) {\n const location = useLocation();\n const navigate = useNavigate();\n const qc = useQueryClient();\n\n // Sync current route to application state\n useEffect(() => {\n const state: NavigationState = {\n view: resolveView(location.pathname, extensions),\n path: appPath(location.pathname),\n };\n\n fetch(agentNativePath(\"/_agent-native/application-state/navigation\"), {\n method: \"PUT\",\n keepalive: true,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(state),\n }).catch(() => {});\n }, [extensions, location.pathname]);\n\n // Listen for navigate commands from agent\n const { data: navCommand } = useQuery({\n queryKey: [\"navigate-command\"],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(\"/_agent-native/application-state/navigate\"),\n );\n if (!res.ok) return null;\n const data = await res.json();\n if (data) {\n // Return with a timestamp to ensure uniqueness\n return { ...data, _ts: Date.now() };\n }\n return null;\n },\n refetchInterval: 2_000,\n refetchIntervalInBackground: true,\n structuralSharing: false,\n });\n\n useEffect(() => {\n if (!navCommand) return;\n // Delete the one-shot command AFTER reading it\n fetch(agentNativePath(\"/_agent-native/application-state/navigate\"), {\n method: \"DELETE\",\n headers: { \"X-Agent-Native-CSRF\": \"1\" },\n }).catch(() => {});\n const cmd = navCommand as NavigationState;\n\n // Navigate to a specific path or resolve view name to path\n const path = routerPath(\n cmd.path || resolvePath(cmd.view, extensions) || \"/overview\",\n );\n navigate(path);\n qc.setQueryData([\"navigate-command\"], null);\n }, [extensions, navCommand, navigate, qc]);\n}\n\nfunction routerPath(path: string): string {\n const basePath = appBasePath();\n if (!basePath) return path;\n if (path === basePath) return \"/\";\n if (path.startsWith(`${basePath}/`)) {\n return path.slice(basePath.length) || \"/\";\n }\n return path;\n}\n\nfunction extensionItemMatchesPath(\n item: DispatchNavItem,\n pathname: string,\n): boolean {\n if (item.match) {\n try {\n if (item.match(pathname)) return true;\n } catch {\n return false;\n }\n }\n return pathname === item.to || pathname.startsWith(`${item.to}/`);\n}\n\nfunction resolveExtensionView(\n pathname: string,\n extensions?: DispatchExtensionConfig,\n): string | undefined {\n return extensions?.navItems?.find((item) =>\n extensionItemMatchesPath(item, pathname),\n )?.id;\n}\n\nfunction resolveExtensionPath(\n view: string | undefined,\n extensions?: DispatchExtensionConfig,\n): string | undefined {\n if (!view) return undefined;\n return extensions?.navItems?.find((item) => item.id === view)?.to;\n}\n\nfunction resolveView(\n pathname: string,\n extensions?: DispatchExtensionConfig,\n): string {\n const extensionView = resolveExtensionView(pathname, extensions);\n if (extensionView) return extensionView;\n if (pathname.startsWith(\"/apps\")) return \"apps\";\n if (pathname.startsWith(\"/metrics\")) return \"metrics\";\n if (pathname.startsWith(\"/new-app\")) return \"new-app\";\n if (pathname.startsWith(\"/vault\")) return \"vault\";\n if (pathname.startsWith(\"/integrations\")) return \"integrations\";\n if (pathname.startsWith(\"/workspace\")) return \"workspace\";\n if (pathname.startsWith(\"/agents\")) return \"agents\";\n if (pathname.startsWith(\"/messaging\")) return \"messaging\";\n if (pathname.startsWith(\"/destinations\")) return \"destinations\";\n if (pathname.startsWith(\"/identities\")) return \"identities\";\n if (pathname.startsWith(\"/approvals\")) return \"approvals\";\n if (pathname.startsWith(\"/audit\")) return \"audit\";\n if (pathname.startsWith(\"/team\")) return \"team\";\n return \"overview\";\n}\n\nfunction resolvePath(\n view?: string,\n extensions?: DispatchExtensionConfig,\n): string | undefined {\n switch (view) {\n case \"overview\":\n return \"/overview\";\n case \"apps\":\n return \"/apps\";\n case \"metrics\":\n case \"usage\":\n return \"/metrics\";\n case \"new-app\":\n case \"create-app\":\n return \"/new-app\";\n case \"vault\":\n case \"secrets\":\n return \"/vault\";\n case \"integrations\":\n return \"/integrations\";\n case \"workspace\":\n case \"resources\":\n return \"/workspace\";\n case \"agents\":\n return \"/agents\";\n case \"messaging\":\n return \"/messaging\";\n case \"destinations\":\n case \"routes\":\n return \"/destinations\";\n case \"identities\":\n return \"/identities\";\n case \"approvals\":\n return \"/approvals\";\n case \"audit\":\n return \"/audit\";\n case \"team\":\n return \"/team\";\n default:\n return resolveExtensionPath(view, extensions);\n }\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type { ToastActionElement, ToastProps } from "../components/ui/toast";
|
|
2
|
+
import type { ToastActionElement, ToastProps } from "../components/ui/toast.js";
|
|
3
3
|
type ToasterToast = ToastProps & {
|
|
4
4
|
id: string;
|
|
5
5
|
title?: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,0BAA0B,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,0BAA0B,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,cAAc,EAAE,WAoB5B,CAAC"}
|
package/dist/routes/index.js
CHANGED
|
@@ -31,6 +31,7 @@ import { route, index } from "@react-router/dev/routes";
|
|
|
31
31
|
export const dispatchRoutes = [
|
|
32
32
|
index("./pages/_index.js"),
|
|
33
33
|
route("overview", "./pages/overview.js"),
|
|
34
|
+
route("metrics", "./pages/metrics.js"),
|
|
34
35
|
route("apps", "./pages/apps.js"),
|
|
35
36
|
route("apps/:appId", "./pages/apps.$appId.js"),
|
|
36
37
|
route("new-app", "./pages/new-app.js"),
|
|
@@ -45,7 +46,7 @@ export const dispatchRoutes = [
|
|
|
45
46
|
route("approvals", "./pages/approvals.js"),
|
|
46
47
|
route("audit", "./pages/audit.js"),
|
|
47
48
|
route("team", "./pages/team.js"),
|
|
48
|
-
route("
|
|
49
|
-
route("
|
|
49
|
+
route("extensions", "./pages/extensions._index.js"),
|
|
50
|
+
route("extensions/:id", "./pages/extensions.$id.js"),
|
|
50
51
|
];
|
|
51
52
|
//# sourceMappingURL=index.js.map
|
package/dist/routes/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,KAAK,CAAC,mBAAmB,CAAC;IAC1B,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC;IACxC,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAChC,KAAK,CAAC,aAAa,EAAE,wBAAwB,CAAC;IAC9C,KAAK,CAAC,SAAS,EAAE,oBAAoB,CAAC;IACtC,KAAK,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAClC,KAAK,CAAC,cAAc,EAAE,yBAAyB,CAAC;IAChD,KAAK,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACpC,KAAK,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC1C,KAAK,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC1C,KAAK,CAAC,cAAc,EAAE,yBAAyB,CAAC;IAChD,KAAK,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC5C,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC;IACxC,KAAK,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC1C,KAAK,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAClC,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAChC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,KAAK,CAAC,mBAAmB,CAAC;IAC1B,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC;IACxC,KAAK,CAAC,SAAS,EAAE,oBAAoB,CAAC;IACtC,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAChC,KAAK,CAAC,aAAa,EAAE,wBAAwB,CAAC;IAC9C,KAAK,CAAC,SAAS,EAAE,oBAAoB,CAAC;IACtC,KAAK,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAClC,KAAK,CAAC,cAAc,EAAE,yBAAyB,CAAC;IAChD,KAAK,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACpC,KAAK,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC1C,KAAK,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC1C,KAAK,CAAC,cAAc,EAAE,yBAAyB,CAAC;IAChD,KAAK,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC5C,KAAK,CAAC,UAAU,EAAE,qBAAqB,CAAC;IACxC,KAAK,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC1C,KAAK,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAClC,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAChC,KAAK,CAAC,YAAY,EAAE,8BAA8B,CAAC;IACnD,KAAK,CAAC,gBAAgB,EAAE,2BAA2B,CAAC;CACrD,CAAC","sourcesContent":["import { type RouteConfig, route, index } from \"@react-router/dev/routes\";\n\n/**\n * Dispatch's routes as a programmatic `RouteConfig[]`. Splat into the\n * consumer's `app/routes.ts`:\n *\n * ```ts\n * import { type RouteConfig } from \"@react-router/dev/routes\";\n * import { dispatchRoutes } from \"@agent-native/dispatch/routes\";\n *\n * export default [\n * ...localRoutes, // consumer's own routes win on collision\n * ...dispatchRoutes, // dispatch fills in everything else\n * ] satisfies RouteConfig;\n * ```\n *\n * Route precedence: React Router 7 matches in declaration order, so\n * placing `dispatchRoutes` LAST means consumer-defined routes with the\n * same path take precedence. To override a single dispatch route, define\n * it in your local routes; to keep it, omit it.\n *\n * The `file` paths below resolve relative to this file at runtime — they\n * point into `packages/dispatch/dist/routes/pages/*.js` after build.\n *\n * Naming maps the original flatRoutes file conventions:\n * `_index.tsx` → `index(...)`\n * `<name>.tsx` → `route(\"<name>\", ...)`\n * `<a>.$<param>.tsx` → `route(\"<a>/:<param>\", ...)`\n * `<a>._index.tsx` → flattened as `route(\"<a>\", ...)` (workspace\n * versions are bare and don't wrap a parent layout)\n */\nexport const dispatchRoutes: RouteConfig = [\n index(\"./pages/_index.js\"),\n route(\"overview\", \"./pages/overview.js\"),\n route(\"metrics\", \"./pages/metrics.js\"),\n route(\"apps\", \"./pages/apps.js\"),\n route(\"apps/:appId\", \"./pages/apps.$appId.js\"),\n route(\"new-app\", \"./pages/new-app.js\"),\n route(\"vault\", \"./pages/vault.js\"),\n route(\"integrations\", \"./pages/integrations.js\"),\n route(\"agents\", \"./pages/agents.js\"),\n route(\"workspace\", \"./pages/workspace.js\"),\n route(\"messaging\", \"./pages/messaging.js\"),\n route(\"destinations\", \"./pages/destinations.js\"),\n route(\"identities\", \"./pages/identities.js\"),\n route(\"approval\", \"./pages/approval.js\"),\n route(\"approvals\", \"./pages/approvals.js\"),\n route(\"audit\", \"./pages/audit.js\"),\n route(\"team\", \"./pages/team.js\"),\n route(\"extensions\", \"./pages/extensions._index.js\"),\n route(\"extensions/:id\", \"./pages/extensions.$id.js\"),\n];\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { redirect } from "react-router";
|
|
3
3
|
import { appPath } from "@agent-native/core/client";
|
|
4
|
-
import { Spinner } from "../../components/ui/spinner";
|
|
4
|
+
import { Spinner } from "../../components/ui/spinner.js";
|
|
5
5
|
export function meta() {
|
|
6
6
|
return [
|
|
7
7
|
{ title: "Agent-Native Dispatch" },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useActionQuery } from "@agent-native/core/client";
|
|
3
|
-
import { AgentsPanel } from "../../components/agents-panel";
|
|
4
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
3
|
+
import { AgentsPanel } from "../../components/agents-panel.js";
|
|
4
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
5
5
|
export function meta() {
|
|
6
6
|
return [{ title: "Agents — Dispatch" }];
|
|
7
7
|
}
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useSearchParams } from "react-router";
|
|
3
3
|
import { useActionMutation, useActionQuery, isInAgentEmbed, postNavigate, appPath, } from "@agent-native/core/client";
|
|
4
4
|
import { toast } from "sonner";
|
|
5
|
-
import { Button } from "../../components/ui/button";
|
|
6
|
-
import { Badge } from "../../components/ui/badge";
|
|
5
|
+
import { Button } from "../../components/ui/button.js";
|
|
6
|
+
import { Badge } from "../../components/ui/badge.js";
|
|
7
7
|
import { IconCheck, IconX, IconArrowUpRight, IconShieldCheck, IconClock, IconAlertCircle, } from "@tabler/icons-react";
|
|
8
8
|
export function meta() {
|
|
9
9
|
return [{ title: "Approval — Dispatch" }];
|
|
@@ -3,10 +3,10 @@ import { useMemo, useState } from "react";
|
|
|
3
3
|
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
4
4
|
import { useOrg } from "@agent-native/core/client/org";
|
|
5
5
|
import { toast } from "sonner";
|
|
6
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
7
|
-
import { Button } from "../../components/ui/button";
|
|
8
|
-
import { Input } from "../../components/ui/input";
|
|
9
|
-
import { Switch } from "../../components/ui/switch";
|
|
6
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
7
|
+
import { Button } from "../../components/ui/button.js";
|
|
8
|
+
import { Input } from "../../components/ui/input.js";
|
|
9
|
+
import { Switch } from "../../components/ui/switch.js";
|
|
10
10
|
export function meta() {
|
|
11
11
|
return [{ title: "Approvals — Dispatch" }];
|
|
12
12
|
}
|
|
@@ -3,9 +3,9 @@ import { useEffect, useMemo } from "react";
|
|
|
3
3
|
import { Link, useParams } from "react-router";
|
|
4
4
|
import { useActionQuery } from "@agent-native/core/client";
|
|
5
5
|
import { IconArrowLeft, IconArrowUpRight, IconClockHour4, } from "@tabler/icons-react";
|
|
6
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
7
|
-
import { Badge } from "../../components/ui/badge";
|
|
8
|
-
import { Button } from "../../components/ui/button";
|
|
6
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
7
|
+
import { Badge } from "../../components/ui/badge.js";
|
|
8
|
+
import { Button } from "../../components/ui/button.js";
|
|
9
9
|
function workspaceAppHref(app) {
|
|
10
10
|
if (app.status === "pending")
|
|
11
11
|
return app.builderUrl || null;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useActionQuery } from "@agent-native/core/client";
|
|
3
3
|
import { IconArrowUpRight, IconApps, IconClockHour4, IconPlus, } from "@tabler/icons-react";
|
|
4
|
-
import { AppKeysPopover } from "../../components/app-keys-popover";
|
|
5
|
-
import { CreateAppPopover } from "../../components/create-app-popover";
|
|
6
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
7
|
-
import { Badge } from "../../components/ui/badge";
|
|
8
|
-
import { Button } from "../../components/ui/button";
|
|
4
|
+
import { AppKeysPopover } from "../../components/app-keys-popover.js";
|
|
5
|
+
import { CreateAppPopover } from "../../components/create-app-popover.js";
|
|
6
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
7
|
+
import { Badge } from "../../components/ui/badge.js";
|
|
8
|
+
import { Button } from "../../components/ui/button.js";
|
|
9
9
|
function workspaceAppHref(app) {
|
|
10
10
|
if (app.status === "pending")
|
|
11
11
|
return app.builderUrl || null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useActionQuery } from "@agent-native/core/client";
|
|
3
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
3
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
4
4
|
export function meta() {
|
|
5
5
|
return [{ title: "Audit — Dispatch" }];
|
|
6
6
|
}
|
|
@@ -2,12 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
4
4
|
import { toast } from "sonner";
|
|
5
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
6
|
-
import { Button } from "../../components/ui/button";
|
|
7
|
-
import { Input } from "../../components/ui/input";
|
|
8
|
-
import { Textarea } from "../../components/ui/textarea";
|
|
9
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../../components/ui/select";
|
|
10
|
-
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "../../components/ui/alert-dialog";
|
|
5
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
6
|
+
import { Button } from "../../components/ui/button.js";
|
|
7
|
+
import { Input } from "../../components/ui/input.js";
|
|
8
|
+
import { Textarea } from "../../components/ui/textarea.js";
|
|
9
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../../components/ui/select.js";
|
|
10
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "../../components/ui/alert-dialog.js";
|
|
11
11
|
export function meta() {
|
|
12
12
|
return [{ title: "Destinations — Dispatch" }];
|
|
13
13
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.$id.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/extensions.$id.tsx"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,UAAU,oBAAoB,4CAE3C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.$id.js","sourceRoot":"","sources":["../../../src/routes/pages/extensions.$id.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,MAAM,CAAC,OAAO,UAAU,oBAAoB;IAC1C,OAAO,KAAC,cAAc,KAAG,CAAC;AAC5B,CAAC","sourcesContent":["import { ToolViewerPage } from \"@agent-native/core/client/tools\";\n\nexport default function ExtensionViewerRoute() {\n return <ToolViewerPage />;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions._index.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/extensions._index.tsx"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,UAAU,eAAe,4CAEtC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions._index.js","sourceRoot":"","sources":["../../../src/routes/pages/extensions._index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,MAAM,CAAC,OAAO,UAAU,eAAe;IACrC,OAAO,KAAC,aAAa,KAAG,CAAC;AAC3B,CAAC","sourcesContent":["import { ToolsListPage } from \"@agent-native/core/client/tools\";\n\nexport default function ExtensionsRoute() {\n return <ToolsListPage />;\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
3
3
|
import { toast } from "sonner";
|
|
4
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
5
|
-
import { Button } from "../../components/ui/button";
|
|
4
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
5
|
+
import { Button } from "../../components/ui/button.js";
|
|
6
6
|
export function meta() {
|
|
7
7
|
return [{ title: "Identities — Dispatch" }];
|
|
8
8
|
}
|
|
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
3
3
|
import { toast } from "sonner";
|
|
4
4
|
import { IconCheck, IconCircleDashed, IconKey, IconRefresh, IconShieldCheck, IconWifi, IconWifiOff, } from "@tabler/icons-react";
|
|
5
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
6
|
-
import { Badge } from "../../components/ui/badge";
|
|
7
|
-
import { Button } from "../../components/ui/button";
|
|
8
|
-
import { Progress } from "../../components/ui/progress";
|
|
5
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
6
|
+
import { Badge } from "../../components/ui/badge.js";
|
|
7
|
+
import { Button } from "../../components/ui/button.js";
|
|
8
|
+
import { Progress } from "../../components/ui/progress.js";
|
|
9
9
|
export function meta() {
|
|
10
10
|
return [{ title: "Integrations — Dispatch" }];
|
|
11
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { MessagingSetupPanel } from "../../components/messaging-setup-panel";
|
|
3
|
-
import { DispatchShell } from "../../components/dispatch-shell";
|
|
2
|
+
import { MessagingSetupPanel } from "../../components/messaging-setup-panel.js";
|
|
3
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
4
4
|
export function meta() {
|
|
5
5
|
return [{ title: "Messaging — Dispatch" }];
|
|
6
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/metrics.tsx"],"names":[],"mappings":"AAmBA,wBAAgB,IAAI;;IAEnB;AA6gBD,MAAM,CAAC,OAAO,UAAU,YAAY,4CAwHnC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import { useActionQuery } from "@agent-native/core/client";
|
|
4
|
+
import { IconActivity, IconAlertTriangle, IconApps, IconChartBar, IconClockHour4, IconCoin, IconMessages, IconUsersGroup, } from "@tabler/icons-react";
|
|
5
|
+
import { DispatchShell } from "../../components/dispatch-shell.js";
|
|
6
|
+
import { Alert, AlertDescription, AlertTitle } from "../../components/ui/alert.js";
|
|
7
|
+
import { Badge } from "../../components/ui/badge.js";
|
|
8
|
+
import { Button } from "../../components/ui/button.js";
|
|
9
|
+
import { Skeleton } from "../../components/ui/skeleton.js";
|
|
10
|
+
import { cn } from "../../lib/utils.js";
|
|
11
|
+
export function meta() {
|
|
12
|
+
return [{ title: "Metrics — Dispatch" }];
|
|
13
|
+
}
|
|
14
|
+
const RANGES = [7, 30, 90];
|
|
15
|
+
function formatCost(cents) {
|
|
16
|
+
if (!Number.isFinite(cents) || cents === 0)
|
|
17
|
+
return "$0.00";
|
|
18
|
+
if (Math.abs(cents) < 1)
|
|
19
|
+
return `${cents.toFixed(3)}¢`;
|
|
20
|
+
if (Math.abs(cents) < 100)
|
|
21
|
+
return `${cents.toFixed(2)}¢`;
|
|
22
|
+
return (cents / 100).toLocaleString(undefined, {
|
|
23
|
+
style: "currency",
|
|
24
|
+
currency: "USD",
|
|
25
|
+
maximumFractionDigits: 2,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function formatNumber(value) {
|
|
29
|
+
return new Intl.NumberFormat(undefined, {
|
|
30
|
+
notation: value >= 10_000 ? "compact" : "standard",
|
|
31
|
+
maximumFractionDigits: value >= 10_000 ? 1 : 0,
|
|
32
|
+
}).format(value);
|
|
33
|
+
}
|
|
34
|
+
function formatTokens(value) {
|
|
35
|
+
return new Intl.NumberFormat(undefined, {
|
|
36
|
+
notation: "compact",
|
|
37
|
+
maximumFractionDigits: 1,
|
|
38
|
+
}).format(value);
|
|
39
|
+
}
|
|
40
|
+
function timeAgo(timestamp) {
|
|
41
|
+
if (!timestamp)
|
|
42
|
+
return "No activity";
|
|
43
|
+
const diff = Date.now() - timestamp;
|
|
44
|
+
if (diff < 60_000)
|
|
45
|
+
return "just now";
|
|
46
|
+
if (diff < 3_600_000)
|
|
47
|
+
return `${Math.floor(diff / 60_000)}m ago`;
|
|
48
|
+
if (diff < 86_400_000)
|
|
49
|
+
return `${Math.floor(diff / 3_600_000)}h ago`;
|
|
50
|
+
return `${Math.floor(diff / 86_400_000)}d ago`;
|
|
51
|
+
}
|
|
52
|
+
function displayApp(value) {
|
|
53
|
+
const trimmed = value?.trim();
|
|
54
|
+
if (!trimmed || trimmed === "unattributed")
|
|
55
|
+
return "Unattributed";
|
|
56
|
+
return trimmed;
|
|
57
|
+
}
|
|
58
|
+
function maxCost(rows) {
|
|
59
|
+
return rows.reduce((max, row) => Math.max(max, row.costCents), 0);
|
|
60
|
+
}
|
|
61
|
+
function barWidth(value, max) {
|
|
62
|
+
if (max <= 0 || value <= 0)
|
|
63
|
+
return "0%";
|
|
64
|
+
return `${Math.max(4, Math.round((value / max) * 100))}%`;
|
|
65
|
+
}
|
|
66
|
+
function RangeSelector({ value, onChange, }) {
|
|
67
|
+
return (_jsx("div", { className: "flex rounded-md border bg-card p-0.5", children: RANGES.map((range) => (_jsxs(Button, { type: "button", variant: value === range ? "secondary" : "ghost", size: "sm", className: "h-7 px-3 text-xs", onClick: () => onChange(range), children: [range, "d"] }, range))) }));
|
|
68
|
+
}
|
|
69
|
+
function MetricCard({ label, value, detail, icon, }) {
|
|
70
|
+
return (_jsxs("div", { className: "rounded-lg border bg-card p-4", children: [_jsxs("div", { className: "mb-3 flex items-center justify-between gap-3", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: label }), _jsx("span", { className: "text-muted-foreground", children: icon })] }), _jsx("div", { className: "text-2xl font-semibold tabular-nums text-foreground", children: value }), _jsx("div", { className: "mt-1 truncate text-xs text-muted-foreground", children: detail })] }));
|
|
71
|
+
}
|
|
72
|
+
function Panel({ title, icon, children, action, }) {
|
|
73
|
+
return (_jsxs("section", { className: "rounded-lg border bg-card", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 border-b px-4 py-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: "text-muted-foreground", children: icon }), _jsx("h2", { className: "truncate text-sm font-semibold text-foreground", children: title })] }), action] }), _jsx("div", { className: "p-4", children: children })] }));
|
|
74
|
+
}
|
|
75
|
+
function LoadingMetrics() {
|
|
76
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-5", children: Array.from({ length: 5 }).map((_, index) => (_jsxs("div", { className: "rounded-lg border bg-card p-4", children: [_jsx(Skeleton, { className: "mb-4 h-4 w-24" }), _jsx(Skeleton, { className: "h-7 w-20" }), _jsx(Skeleton, { className: "mt-3 h-3 w-28" })] }, index))) }), _jsx(Skeleton, { className: "h-80 rounded-lg" })] }));
|
|
77
|
+
}
|
|
78
|
+
function AppSpendRows({ rows }) {
|
|
79
|
+
const max = maxCost(rows);
|
|
80
|
+
if (rows.length === 0) {
|
|
81
|
+
return (_jsx("div", { className: "rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground", children: "No LLM usage recorded for this window." }));
|
|
82
|
+
}
|
|
83
|
+
return (_jsx("div", { className: "space-y-3", children: rows.map((row) => (_jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate font-medium text-foreground", children: displayApp(row.key) }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [formatNumber(row.chatCalls), " chats \u00B7", " ", formatNumber(row.activeUsers), " users"] })] }), _jsxs("div", { className: "shrink-0 text-right", children: [_jsx("div", { className: "font-medium tabular-nums text-foreground", children: formatCost(row.costCents) }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [formatNumber(row.calls), " calls"] })] })] }), _jsx("div", { className: "h-2 overflow-hidden rounded-full bg-muted", children: _jsx("div", { className: "h-full rounded-full bg-foreground", style: { width: barWidth(row.costCents, max) } }) })] }, row.key))) }));
|
|
84
|
+
}
|
|
85
|
+
function DailyActivity({ rows }) {
|
|
86
|
+
const max = Math.max(1, rows.reduce((value, row) => Math.max(value, row.calls), 0));
|
|
87
|
+
if (rows.length === 0) {
|
|
88
|
+
return (_jsx("div", { className: "rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground", children: "No activity in this window." }));
|
|
89
|
+
}
|
|
90
|
+
return (_jsx("div", { className: "flex h-44 items-end gap-1", children: rows.map((row) => (_jsxs("div", { className: "group flex min-w-0 flex-1 flex-col items-center gap-2", children: [_jsx("div", { className: "relative flex h-36 w-full items-end rounded-sm bg-muted/60", children: _jsx("div", { className: "w-full rounded-sm bg-foreground transition group-hover:bg-primary", style: { height: `${Math.max(4, (row.calls / max) * 100)}%` } }) }), _jsx("div", { className: "hidden text-[10px] text-muted-foreground sm:block", children: row.date.slice(5) })] }, row.date))) }));
|
|
91
|
+
}
|
|
92
|
+
function AppAccessTable({ rows }) {
|
|
93
|
+
const visibleRows = rows.filter((row) => !row.isDispatch);
|
|
94
|
+
if (visibleRows.length === 0) {
|
|
95
|
+
return (_jsx("div", { className: "rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground", children: "No workspace apps discovered yet." }));
|
|
96
|
+
}
|
|
97
|
+
return (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full min-w-[720px] text-left text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b text-muted-foreground", children: [_jsx("th", { className: "px-2 py-2 font-medium", children: "App" }), _jsx("th", { className: "px-2 py-2 font-medium", children: "Access" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Users" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Chats" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Cost" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Last activity" })] }) }), _jsx("tbody", { children: visibleRows.map((row) => (_jsxs("tr", { className: "border-b last:border-0", children: [_jsxs("td", { className: "px-2 py-3", children: [_jsx("div", { className: "font-medium text-foreground", children: row.name }), _jsx("div", { className: "font-mono text-[11px] text-muted-foreground", children: row.path })] }), _jsx("td", { className: "px-2 py-3", children: _jsx(Badge, { variant: "outline", className: cn(row.status === "pending" &&
|
|
98
|
+
"border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300"), children: row.status === "pending" ? "Building" : row.accessLabel }) }), _jsxs("td", { className: "px-2 py-3 text-right tabular-nums", children: [formatNumber(row.usersWithUsage), " /", " ", formatNumber(row.accessUsers)] }), _jsx("td", { className: "px-2 py-3 text-right tabular-nums", children: formatNumber(row.chatCalls) }), _jsx("td", { className: "px-2 py-3 text-right tabular-nums", children: formatCost(row.costCents) }), _jsx("td", { className: "px-2 py-3 text-right text-muted-foreground", children: timeAgo(row.lastActiveAt) })] }, row.id))) })] }) }));
|
|
99
|
+
}
|
|
100
|
+
function UserTable({ rows }) {
|
|
101
|
+
if (rows.length === 0) {
|
|
102
|
+
return (_jsx("div", { className: "rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground", children: "No users have triggered LLM usage in this window." }));
|
|
103
|
+
}
|
|
104
|
+
return (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full min-w-[760px] text-left text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b text-muted-foreground", children: [_jsx("th", { className: "px-2 py-2 font-medium", children: "User" }), _jsx("th", { className: "px-2 py-2 font-medium", children: "Role" }), _jsx("th", { className: "px-2 py-2 font-medium", children: "Top app" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Chats" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Threads" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Tokens" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Cost" })] }) }), _jsx("tbody", { children: rows.slice(0, 12).map((row) => (_jsxs("tr", { className: "border-b last:border-0", children: [_jsxs("td", { className: "max-w-64 px-2 py-3", children: [_jsx("div", { className: "truncate font-medium text-foreground", children: row.ownerEmail }), _jsx("div", { className: "text-muted-foreground", children: timeAgo(row.lastActiveAt ?? row.lastChatAt) })] }), _jsx("td", { className: "px-2 py-3", children: _jsx(Badge, { variant: "secondary", children: row.role ?? "user" }) }), _jsx("td", { className: "px-2 py-3 text-muted-foreground", children: displayApp(row.topApp) }), _jsx("td", { className: "px-2 py-3 text-right tabular-nums", children: formatNumber(row.chatCalls) }), _jsx("td", { className: "px-2 py-3 text-right tabular-nums", children: formatNumber(row.chatThreads) }), _jsx("td", { className: "px-2 py-3 text-right tabular-nums", children: formatTokens(row.inputTokens + row.outputTokens) }), _jsx("td", { className: "px-2 py-3 text-right tabular-nums", children: formatCost(row.costCents) })] }, row.ownerEmail))) })] }) }));
|
|
105
|
+
}
|
|
106
|
+
function CompactBreakdown({ rows, empty, }) {
|
|
107
|
+
const max = maxCost(rows);
|
|
108
|
+
if (rows.length === 0) {
|
|
109
|
+
return _jsx("div", { className: "text-sm text-muted-foreground", children: empty });
|
|
110
|
+
}
|
|
111
|
+
return (_jsx("div", { className: "space-y-3", children: rows.slice(0, 6).map((row) => (_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-xs", children: [_jsx("span", { className: "truncate font-medium text-foreground", children: row.label }), _jsx("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: formatCost(row.costCents) })] }), _jsx("div", { className: "h-1.5 overflow-hidden rounded-full bg-muted", children: _jsx("div", { className: "h-full rounded-full bg-muted-foreground", style: { width: barWidth(row.costCents, max) } }) })] }, row.key))) }));
|
|
112
|
+
}
|
|
113
|
+
function RecentTable({ rows }) {
|
|
114
|
+
if (rows.length === 0) {
|
|
115
|
+
return (_jsx("div", { className: "rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground", children: "No recent LLM calls." }));
|
|
116
|
+
}
|
|
117
|
+
return (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full min-w-[760px] text-left text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b text-muted-foreground", children: [_jsx("th", { className: "px-2 py-2 font-medium", children: "When" }), _jsx("th", { className: "px-2 py-2 font-medium", children: "User" }), _jsx("th", { className: "px-2 py-2 font-medium", children: "App" }), _jsx("th", { className: "px-2 py-2 font-medium", children: "Label" }), _jsx("th", { className: "px-2 py-2 font-medium", children: "Model" }), _jsx("th", { className: "px-2 py-2 text-right font-medium", children: "Cost" })] }) }), _jsx("tbody", { children: rows.slice(0, 10).map((row) => (_jsxs("tr", { className: "border-b last:border-0", children: [_jsx("td", { className: "px-2 py-3 text-muted-foreground", children: timeAgo(row.createdAt) }), _jsx("td", { className: "max-w-56 px-2 py-3", children: _jsx("div", { className: "truncate text-foreground", children: row.ownerEmail }) }), _jsx("td", { className: "px-2 py-3 text-muted-foreground", children: displayApp(row.app) }), _jsx("td", { className: "px-2 py-3", children: _jsx(Badge, { variant: "outline", children: row.label }) }), _jsx("td", { className: "max-w-48 px-2 py-3", children: _jsx("div", { className: "truncate text-muted-foreground", children: row.model }) }), _jsx("td", { className: "px-2 py-3 text-right tabular-nums", children: formatCost(row.costCents) })] }, row.id))) })] }) }));
|
|
118
|
+
}
|
|
119
|
+
export default function MetricsRoute() {
|
|
120
|
+
const [sinceDays, setSinceDays] = useState(30);
|
|
121
|
+
const { data, isLoading, error } = useActionQuery("list-dispatch-usage-metrics", { sinceDays }, { refetchInterval: 30_000 });
|
|
122
|
+
const metrics = data;
|
|
123
|
+
const totalTokens = useMemo(() => {
|
|
124
|
+
if (!metrics)
|
|
125
|
+
return 0;
|
|
126
|
+
return (metrics.totals.inputTokens +
|
|
127
|
+
metrics.totals.outputTokens +
|
|
128
|
+
metrics.totals.cacheReadTokens +
|
|
129
|
+
metrics.totals.cacheWriteTokens);
|
|
130
|
+
}, [metrics]);
|
|
131
|
+
return (_jsx(DispatchShell, { title: "Metrics", description: "Workspace-wide LLM spend, chat volume, user activity, and app access.", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx("div", { className: "text-sm text-muted-foreground", children: metrics?.access.scope === "organization"
|
|
132
|
+
? `${metrics.access.totalUsers} workspace users`
|
|
133
|
+
: `${metrics?.access.totalUsers ?? 0} signed-in users` }), _jsx(RangeSelector, { value: sinceDays, onChange: setSinceDays })] }), error ? (_jsxs(Alert, { variant: "destructive", children: [_jsx(IconAlertTriangle, { className: "h-4 w-4" }), _jsx(AlertTitle, { children: "Metrics unavailable" }), _jsx(AlertDescription, { children: error instanceof Error ? error.message : "Unable to load usage." })] })) : null, isLoading && !metrics ? _jsx(LoadingMetrics, {}) : null, metrics ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-5", children: [_jsx(MetricCard, { label: "Estimated spend", value: formatCost(metrics.totals.costCents), detail: `${formatTokens(totalTokens)} total tokens`, icon: _jsx(IconCoin, { size: 17 }) }), _jsx(MetricCard, { label: "LLM calls", value: formatNumber(metrics.totals.calls), detail: `${formatNumber(metrics.totals.chatCalls)} chat turns`, icon: _jsx(IconActivity, { size: 17 }) }), _jsx(MetricCard, { label: "Active users", value: formatNumber(metrics.totals.activeUsers), detail: `${formatNumber(metrics.access.totalUsers)} users with access`, icon: _jsx(IconUsersGroup, { size: 17 }) }), _jsx(MetricCard, { label: "Workspace apps", value: formatNumber(metrics.totals.workspaceApps), detail: `${formatNumber(metrics.byApp.length)} with usage`, icon: _jsx(IconApps, { size: 17 }) }), _jsx(MetricCard, { label: "Chat threads", value: formatNumber(metrics.totals.chatThreads), detail: `${formatNumber(metrics.totals.chatMessages)} messages`, icon: _jsx(IconMessages, { size: 17 }) })] }), _jsxs("div", { className: "grid gap-4 xl:grid-cols-[minmax(0,1.35fr)_minmax(320px,0.65fr)]", children: [_jsx(Panel, { title: "Spend By App", icon: _jsx(IconChartBar, { size: 16 }), children: _jsx(AppSpendRows, { rows: metrics.byApp }) }), _jsx(Panel, { title: "Daily Activity", icon: _jsx(IconClockHour4, { size: 16 }), children: _jsx(DailyActivity, { rows: metrics.daily }) })] }), _jsx(Panel, { title: "Access By App", icon: _jsx(IconApps, { size: 16 }), children: _jsx(AppAccessTable, { rows: metrics.appAccess }) }), _jsx(Panel, { title: "Users", icon: _jsx(IconUsersGroup, { size: 16 }), children: _jsx(UserTable, { rows: metrics.byUser }) }), _jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [_jsx(Panel, { title: "Models", icon: _jsx(IconChartBar, { size: 16 }), children: _jsx(CompactBreakdown, { rows: metrics.byModel, empty: "No model usage in this window." }) }), _jsx(Panel, { title: "Work Types", icon: _jsx(IconActivity, { size: 16 }), children: _jsx(CompactBreakdown, { rows: metrics.byLabel, empty: "No labeled usage in this window." }) })] }), _jsx(Panel, { title: "Recent LLM Calls", icon: _jsx(IconActivity, { size: 16 }), children: _jsx(RecentTable, { rows: metrics.recent }) })] })) : null] }) }));
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=metrics.js.map
|