@agent-native/dispatch 0.24.0 → 0.24.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/provider-api-register.d.ts +12 -12
- package/dist/components/admin-navigation.d.ts.map +1 -1
- package/dist/components/admin-navigation.js +21 -5
- package/dist/components/admin-navigation.js.map +1 -1
- package/dist/components/agents-panel.d.ts.map +1 -1
- package/dist/components/agents-panel.js +7 -2
- package/dist/components/agents-panel.js.map +1 -1
- package/dist/components/app-list-row.d.ts +1 -1
- package/dist/components/app-list-row.d.ts.map +1 -1
- package/dist/components/app-list-row.js +1 -1
- package/dist/components/app-list-row.js.map +1 -1
- package/dist/components/app-open-actions.d.ts +1 -17
- package/dist/components/app-open-actions.d.ts.map +1 -1
- package/dist/components/app-open-actions.js +1 -20
- package/dist/components/app-open-actions.js.map +1 -1
- package/dist/components/app-row-settings.d.ts +6 -0
- package/dist/components/app-row-settings.d.ts.map +1 -0
- package/dist/components/app-row-settings.js +11 -0
- package/dist/components/app-row-settings.js.map +1 -0
- package/dist/components/automation-run-history-dialog.d.ts.map +1 -1
- package/dist/components/automation-run-history-dialog.js +3 -2
- package/dist/components/automation-run-history-dialog.js.map +1 -1
- package/dist/components/connected-app-card.d.ts.map +1 -1
- package/dist/components/connected-app-card.js +1 -1
- package/dist/components/connected-app-card.js.map +1 -1
- package/dist/components/create-app-popover.js +2 -2
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-control-plane.d.ts.map +1 -1
- package/dist/components/dispatch-control-plane.js +23 -7
- package/dist/components/dispatch-control-plane.js.map +1 -1
- package/dist/components/dispatch-shell.d.ts.map +1 -1
- package/dist/components/dispatch-shell.js +5 -1
- package/dist/components/dispatch-shell.js.map +1 -1
- package/dist/components/docs-link.d.ts +16 -0
- package/dist/components/docs-link.d.ts.map +1 -0
- package/dist/components/docs-link.js +34 -0
- package/dist/components/docs-link.js.map +1 -0
- package/dist/components/layout/Layout.d.ts +1 -0
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +37 -28
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/messaging-setup-panel.d.ts.map +1 -1
- package/dist/components/messaging-setup-panel.js +3 -2
- package/dist/components/messaging-setup-panel.js.map +1 -1
- package/dist/components/usage-alerts-panel.d.ts +11 -0
- package/dist/components/usage-alerts-panel.d.ts.map +1 -0
- package/dist/components/usage-alerts-panel.js +125 -0
- package/dist/components/usage-alerts-panel.js.map +1 -0
- package/dist/components/workspace-app-card.d.ts +3 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +70 -29
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/components/workspace-app-search.d.ts +10 -0
- package/dist/components/workspace-app-search.d.ts.map +1 -0
- package/dist/components/workspace-app-search.js +27 -0
- package/dist/components/workspace-app-search.js.map +1 -0
- package/dist/components/workspace-resource-effective-stack.d.ts.map +1 -1
- package/dist/components/workspace-resource-effective-stack.js +3 -2
- package/dist/components/workspace-resource-effective-stack.js.map +1 -1
- package/dist/components/workspace-template-card.d.ts.map +1 -1
- package/dist/components/workspace-template-card.js +2 -1
- package/dist/components/workspace-template-card.js.map +1 -1
- package/dist/lib/workspace-app-layout.d.ts +19 -0
- package/dist/lib/workspace-app-layout.d.ts.map +1 -0
- package/dist/lib/workspace-app-layout.js +75 -0
- package/dist/lib/workspace-app-layout.js.map +1 -0
- package/dist/lib/workspace-apps.d.ts +10 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js +59 -0
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/lib/workspace-apps.test.js +18 -1
- package/dist/lib/workspace-apps.test.js.map +1 -1
- package/dist/routes/pages/$appId.d.ts.map +1 -1
- package/dist/routes/pages/$appId.js +4 -2
- package/dist/routes/pages/$appId.js.map +1 -1
- package/dist/routes/pages/agents.d.ts.map +1 -1
- package/dist/routes/pages/agents.js +2 -3
- package/dist/routes/pages/agents.js.map +1 -1
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +8 -3
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/apps.d.ts.map +1 -1
- package/dist/routes/pages/apps.js +31 -16
- package/dist/routes/pages/apps.js.map +1 -1
- package/dist/routes/pages/audit.d.ts.map +1 -1
- package/dist/routes/pages/audit.js +2 -1
- package/dist/routes/pages/audit.js.map +1 -1
- package/dist/routes/pages/dreams.d.ts.map +1 -1
- package/dist/routes/pages/dreams.js +14 -18
- package/dist/routes/pages/dreams.js.map +1 -1
- package/dist/routes/pages/integrations.d.ts.map +1 -1
- package/dist/routes/pages/integrations.js +51 -14
- package/dist/routes/pages/integrations.js.map +1 -1
- package/dist/routes/pages/metrics.d.ts.map +1 -1
- package/dist/routes/pages/metrics.js +4 -1
- package/dist/routes/pages/metrics.js.map +1 -1
- package/dist/routes/pages/operations.js +1 -1
- package/dist/routes/pages/operations.js.map +1 -1
- package/dist/routes/pages/settings.d.ts.map +1 -1
- package/dist/routes/pages/settings.js +7 -2
- package/dist/routes/pages/settings.js.map +1 -1
- package/dist/routes/pages/thread-debug.d.ts.map +1 -1
- package/dist/routes/pages/thread-debug.js +5 -8
- package/dist/routes/pages/thread-debug.js.map +1 -1
- package/dist/routes/pages/vault.d.ts.map +1 -1
- package/dist/routes/pages/vault.js +1 -1
- package/dist/routes/pages/vault.js.map +1 -1
- package/dist/routes/pages/workspace.d.ts.map +1 -1
- package/dist/routes/pages/workspace.js +13 -10
- package/dist/routes/pages/workspace.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/app-creation-store.d.ts.map +1 -1
- package/dist/server/lib/app-creation-store.js +12 -52
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/dist/shared/app-roles.d.ts +9 -0
- package/dist/shared/app-roles.d.ts.map +1 -0
- package/dist/shared/app-roles.js +7 -0
- package/dist/shared/app-roles.js.map +1 -0
- package/package.json +4 -3
- package/src/components/admin-navigation.tsx +57 -11
- package/src/components/agents-panel.tsx +54 -29
- package/src/components/app-list-row.tsx +1 -2
- package/src/components/app-open-actions.tsx +5 -114
- package/src/components/app-row-settings.tsx +54 -0
- package/src/components/automation-run-history-dialog.tsx +8 -4
- package/src/components/connected-app-card.tsx +0 -1
- package/src/components/create-app-popover.spec.tsx +1 -1
- package/src/components/create-app-popover.tsx +2 -2
- package/src/components/dispatch-control-plane.spec.tsx +36 -2
- package/src/components/dispatch-control-plane.tsx +83 -27
- package/src/components/dispatch-shell.tsx +7 -1
- package/src/components/docs-link.tsx +52 -0
- package/src/components/layout/Layout.spec.tsx +10 -0
- package/src/components/layout/Layout.tsx +50 -23
- package/src/components/messaging-setup-panel.tsx +10 -3
- package/src/components/usage-alerts-panel.tsx +445 -0
- package/src/components/workspace-app-card.spec.tsx +130 -9
- package/src/components/workspace-app-card.tsx +128 -71
- package/src/components/workspace-app-search.tsx +96 -0
- package/src/components/workspace-resource-effective-stack.tsx +10 -5
- package/src/components/workspace-template-card.spec.tsx +52 -23
- package/src/components/workspace-template-card.tsx +7 -10
- package/src/lib/workspace-app-layout.spec.ts +47 -0
- package/src/lib/workspace-app-layout.ts +121 -0
- package/src/lib/workspace-apps.test.ts +45 -1
- package/src/lib/workspace-apps.ts +72 -0
- package/src/routes/pages/$appId.tsx +3 -6
- package/src/routes/pages/agents.tsx +6 -3
- package/src/routes/pages/apps.$appId.tsx +6 -6
- package/src/routes/pages/apps.tsx +116 -62
- package/src/routes/pages/audit.tsx +28 -8
- package/src/routes/pages/dreams.tsx +92 -142
- package/src/routes/pages/integrations.tsx +147 -68
- package/src/routes/pages/metrics.tsx +8 -0
- package/src/routes/pages/operations.tsx +2 -2
- package/src/routes/pages/settings.tsx +14 -9
- package/src/routes/pages/thread-debug.tsx +18 -36
- package/src/routes/pages/vault.tsx +7 -2
- package/src/routes/pages/workspace.tsx +92 -56
- package/src/server/index.ts +4 -0
- package/src/server/lib/app-creation-store.spec.ts +90 -43
- package/src/server/lib/app-creation-store.ts +15 -61
- package/src/shared/app-roles.ts +8 -0
|
@@ -3,12 +3,14 @@ import {
|
|
|
3
3
|
useActionQuery,
|
|
4
4
|
} from "@agent-native/core/client/hooks";
|
|
5
5
|
import {
|
|
6
|
-
|
|
6
|
+
getDefaultMcpIntegrations,
|
|
7
|
+
McpIntegrationLogo,
|
|
8
|
+
} from "@agent-native/core/client/resources";
|
|
9
|
+
import {
|
|
7
10
|
IconChevronRight,
|
|
8
|
-
IconCircleDashed,
|
|
9
|
-
IconKey,
|
|
10
11
|
IconLink,
|
|
11
12
|
IconPlugConnected,
|
|
13
|
+
IconSearch,
|
|
12
14
|
} from "@tabler/icons-react";
|
|
13
15
|
import { useQueryClient } from "@tanstack/react-query";
|
|
14
16
|
import { useMemo, useState } from "react";
|
|
@@ -17,7 +19,6 @@ import { toast } from "sonner";
|
|
|
17
19
|
|
|
18
20
|
import { ActionQueryError } from "../../components/action-query-error";
|
|
19
21
|
import { DispatchShell } from "../../components/dispatch-shell";
|
|
20
|
-
import { Badge } from "../../components/ui/badge";
|
|
21
22
|
import { Button } from "../../components/ui/button";
|
|
22
23
|
import {
|
|
23
24
|
Collapsible,
|
|
@@ -34,11 +35,7 @@ import {
|
|
|
34
35
|
} from "../../components/ui/dialog";
|
|
35
36
|
import { Input } from "../../components/ui/input";
|
|
36
37
|
import { Label } from "../../components/ui/label";
|
|
37
|
-
import {
|
|
38
|
-
Tooltip,
|
|
39
|
-
TooltipContent,
|
|
40
|
-
TooltipTrigger,
|
|
41
|
-
} from "../../components/ui/tooltip";
|
|
38
|
+
import { Skeleton } from "../../components/ui/skeleton";
|
|
42
39
|
|
|
43
40
|
export function meta() {
|
|
44
41
|
return [{ title: "Connections — Dispatch" }];
|
|
@@ -97,6 +94,38 @@ function inferProviderFromKey(key: string, label: string): string {
|
|
|
97
94
|
return "other";
|
|
98
95
|
}
|
|
99
96
|
|
|
97
|
+
const MCP_INTEGRATIONS_BY_ID = new Map(
|
|
98
|
+
getDefaultMcpIntegrations().map((integration) => [
|
|
99
|
+
integration.id,
|
|
100
|
+
integration,
|
|
101
|
+
]),
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const CREDENTIAL_PROVIDER_LOGO_IDS: Record<string, string> = {
|
|
105
|
+
google: "google-workspace",
|
|
106
|
+
bigquery: "google-workspace",
|
|
107
|
+
jira: "atlassian",
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
function credentialLogo(service: Service) {
|
|
111
|
+
const providerId = inferProviderFromKey(service.key, service.label);
|
|
112
|
+
const integration = MCP_INTEGRATIONS_BY_ID.get(
|
|
113
|
+
CREDENTIAL_PROVIDER_LOGO_IDS[providerId] ?? providerId,
|
|
114
|
+
);
|
|
115
|
+
if (!integration?.logoUrl) {
|
|
116
|
+
return <IconPlugConnected className="size-4 text-muted-foreground" />;
|
|
117
|
+
}
|
|
118
|
+
return (
|
|
119
|
+
<McpIntegrationLogo
|
|
120
|
+
name={service.label}
|
|
121
|
+
logoUrl={integration.logoUrl}
|
|
122
|
+
integrationId={integration.id}
|
|
123
|
+
className="size-full rounded-md border-0 bg-transparent"
|
|
124
|
+
imageClassName="size-full p-1"
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
100
129
|
function ConnectDialog({
|
|
101
130
|
service,
|
|
102
131
|
open,
|
|
@@ -110,6 +139,10 @@ function ConnectDialog({
|
|
|
110
139
|
}) {
|
|
111
140
|
const [value, setValue] = useState("");
|
|
112
141
|
const qc = useQueryClient();
|
|
142
|
+
const configuredApps = service.apps.filter((app) => app.configured);
|
|
143
|
+
const configuredAppNames = configuredApps
|
|
144
|
+
.map((app) => app.appName)
|
|
145
|
+
.join(", ");
|
|
113
146
|
|
|
114
147
|
const createSecret = useActionMutation("create-vault-secret", {});
|
|
115
148
|
const createGrant = useActionMutation("create-vault-grant", {});
|
|
@@ -189,12 +222,11 @@ function ConnectDialog({
|
|
|
189
222
|
<DialogHeader>
|
|
190
223
|
<DialogTitle>Connect {service.label}</DialogTitle>
|
|
191
224
|
<DialogDescription>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
it.
|
|
225
|
+
{configuredApps.length > 0
|
|
226
|
+
? `Configured in ${configuredAppNames}. `
|
|
227
|
+
: "No app currently reports this key as configured. "}
|
|
228
|
+
Saving it creates a workspace vault entry using this exact key name.
|
|
229
|
+
Apps need the same key name to use it.
|
|
198
230
|
</DialogDescription>
|
|
199
231
|
</DialogHeader>
|
|
200
232
|
<div className="space-y-3">
|
|
@@ -240,55 +272,54 @@ function ConnectorCard({
|
|
|
240
272
|
accessMode: "all-apps" | "manual";
|
|
241
273
|
}) {
|
|
242
274
|
const [open, setOpen] = useState(false);
|
|
243
|
-
const
|
|
244
|
-
const
|
|
275
|
+
const configuredApps = service.apps.filter((app) => app.configured);
|
|
276
|
+
const vaultApps = service.apps.filter((app) => app.vaultGranted);
|
|
277
|
+
const isAvailable = configuredApps.length > 0 || vaultApps.length > 0;
|
|
278
|
+
const configuredAppNames = configuredApps
|
|
279
|
+
.map((app) => app.appName)
|
|
280
|
+
.join(", ");
|
|
281
|
+
const vaultAppNames = vaultApps.map((app) => app.appName).join(", ");
|
|
245
282
|
|
|
246
283
|
return (
|
|
247
284
|
<>
|
|
248
|
-
<
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
className="group flex flex-col items-start gap-2 rounded-2xl bg-card p-5 text-left transition-[background-color] hover:bg-card/80 cursor-pointer"
|
|
252
|
-
>
|
|
253
|
-
<div className="flex w-full items-start justify-between gap-2">
|
|
254
|
-
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-muted">
|
|
255
|
-
<IconKey size={16} className="text-muted-foreground" />
|
|
256
|
-
</div>
|
|
257
|
-
{isConnected ? (
|
|
258
|
-
<Badge
|
|
259
|
-
variant="secondary"
|
|
260
|
-
className="bg-green-500/10 text-green-700 dark:text-green-400 gap-1"
|
|
261
|
-
>
|
|
262
|
-
<IconCheck size={12} />
|
|
263
|
-
Connected
|
|
264
|
-
</Badge>
|
|
265
|
-
) : (
|
|
266
|
-
<Badge
|
|
267
|
-
variant="secondary"
|
|
268
|
-
className="bg-amber-500/10 text-amber-700 dark:text-amber-400 gap-1"
|
|
269
|
-
>
|
|
270
|
-
<IconCircleDashed size={12} />
|
|
271
|
-
Connect
|
|
272
|
-
</Badge>
|
|
273
|
-
)}
|
|
285
|
+
<article className="flex min-w-0 items-center gap-3 border-b border-border/60 py-3.5 last:border-b-0">
|
|
286
|
+
<div className="flex size-8 shrink-0 items-center justify-center rounded-md bg-muted">
|
|
287
|
+
{credentialLogo(service)}
|
|
274
288
|
</div>
|
|
275
|
-
<div className="
|
|
276
|
-
<
|
|
277
|
-
<
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
289
|
+
<div className="min-w-0 flex-1">
|
|
290
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
291
|
+
<span className="truncate text-sm font-medium text-foreground">
|
|
292
|
+
{service.label}
|
|
293
|
+
</span>
|
|
294
|
+
<span
|
|
295
|
+
className={
|
|
296
|
+
isAvailable
|
|
297
|
+
? "shrink-0 text-[11px] font-medium text-emerald-600 dark:text-emerald-400"
|
|
298
|
+
: "shrink-0 text-[11px] font-medium text-muted-foreground"
|
|
299
|
+
}
|
|
300
|
+
>
|
|
301
|
+
{vaultApps.length > 0 ? "Connected" : "App key"}
|
|
302
|
+
</span>
|
|
286
303
|
</div>
|
|
304
|
+
<p className="mt-0.5 truncate font-mono text-[11px] leading-5 text-muted-foreground/80">
|
|
305
|
+
{service.key}
|
|
306
|
+
</p>
|
|
307
|
+
<p className="mt-0.5 truncate text-xs leading-5 text-muted-foreground">
|
|
308
|
+
Declared by {service.apps.length}{" "}
|
|
309
|
+
{service.apps.length === 1 ? "app" : "apps"}
|
|
310
|
+
{configuredApps.length > 0 ? ` · ${configuredAppNames}` : ""}
|
|
311
|
+
{vaultApps.length > 0 ? ` · Vault: ${vaultAppNames}` : ""}
|
|
312
|
+
</p>
|
|
287
313
|
</div>
|
|
288
|
-
<
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
314
|
+
<button
|
|
315
|
+
type="button"
|
|
316
|
+
onClick={() => setOpen(true)}
|
|
317
|
+
className="inline-flex h-8 shrink-0 items-center justify-center gap-1 rounded-md border border-border bg-background px-2.5 text-xs font-medium text-foreground transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
318
|
+
>
|
|
319
|
+
{isAvailable ? "Manage" : "Connect"}
|
|
320
|
+
<IconChevronRight className="size-3.5 rtl:-scale-x-100" />
|
|
321
|
+
</button>
|
|
322
|
+
</article>
|
|
292
323
|
<ConnectDialog
|
|
293
324
|
service={service}
|
|
294
325
|
open={open}
|
|
@@ -326,11 +357,13 @@ function PerAppDetailRow({ app }: { app: CatalogApp }) {
|
|
|
326
357
|
export default function ConnectionsRoute() {
|
|
327
358
|
const catalogQuery = useActionQuery("list-integrations-catalog", {});
|
|
328
359
|
const accessQuery = useActionQuery("get-vault-access-settings", {});
|
|
329
|
-
const { data: catalog
|
|
360
|
+
const { data: catalog } = catalogQuery;
|
|
330
361
|
const { data: accessSettings } = accessQuery;
|
|
362
|
+
const isLoading = catalogQuery.isLoading || accessQuery.isLoading;
|
|
331
363
|
const apps = (catalog as CatalogApp[]) || [];
|
|
332
364
|
const accessMode =
|
|
333
365
|
(accessSettings as any)?.mode === "manual" ? "manual" : "all-apps";
|
|
366
|
+
const [query, setQuery] = useState("");
|
|
334
367
|
|
|
335
368
|
const services = useMemo<Service[]>(() => {
|
|
336
369
|
const map = new Map<string, Service>();
|
|
@@ -358,13 +391,26 @@ export default function ConnectionsRoute() {
|
|
|
358
391
|
);
|
|
359
392
|
}, [apps]);
|
|
360
393
|
|
|
361
|
-
const
|
|
362
|
-
|
|
394
|
+
const filteredServices = useMemo(() => {
|
|
395
|
+
const normalized = query.trim().toLowerCase();
|
|
396
|
+
if (!normalized) return services;
|
|
397
|
+
return services.filter(
|
|
398
|
+
(service) =>
|
|
399
|
+
service.label.toLowerCase().includes(normalized) ||
|
|
400
|
+
service.key.toLowerCase().includes(normalized),
|
|
401
|
+
);
|
|
402
|
+
}, [query, services]);
|
|
403
|
+
const available = filteredServices.filter(
|
|
404
|
+
(s) => !s.apps.some((a) => a.configured),
|
|
405
|
+
);
|
|
406
|
+
const connected = filteredServices.filter((s) =>
|
|
407
|
+
s.apps.some((a) => a.configured),
|
|
408
|
+
);
|
|
363
409
|
|
|
364
410
|
return (
|
|
365
411
|
<DispatchShell
|
|
366
412
|
title="Connections"
|
|
367
|
-
description="Connect
|
|
413
|
+
description="Connect workspace credentials declared by apps and manage how they are shared."
|
|
368
414
|
>
|
|
369
415
|
{catalogQuery.isError || accessQuery.isError ? (
|
|
370
416
|
<ActionQueryError
|
|
@@ -376,9 +422,40 @@ export default function ConnectionsRoute() {
|
|
|
376
422
|
/>
|
|
377
423
|
) : null}
|
|
378
424
|
|
|
425
|
+
{!catalogQuery.isError && !isLoading ? (
|
|
426
|
+
<div className="mb-5 flex items-center gap-3">
|
|
427
|
+
<div className="relative min-w-0 flex-1">
|
|
428
|
+
<IconSearch className="pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
429
|
+
<Input
|
|
430
|
+
value={query}
|
|
431
|
+
onChange={(event) => setQuery(event.target.value)}
|
|
432
|
+
placeholder="Search credentials"
|
|
433
|
+
aria-label="Search credentials"
|
|
434
|
+
className="h-9 ps-9"
|
|
435
|
+
/>
|
|
436
|
+
</div>
|
|
437
|
+
<span className="shrink-0 text-xs text-muted-foreground">
|
|
438
|
+
{filteredServices.length} credential
|
|
439
|
+
{filteredServices.length === 1 ? "" : "s"}
|
|
440
|
+
</span>
|
|
441
|
+
</div>
|
|
442
|
+
) : null}
|
|
443
|
+
|
|
379
444
|
{!catalogQuery.isError && isLoading && services.length === 0 && (
|
|
380
|
-
<div className="
|
|
381
|
-
|
|
445
|
+
<div className="overflow-hidden rounded-lg bg-card">
|
|
446
|
+
{Array.from({ length: 7 }).map((_, index) => (
|
|
447
|
+
<div
|
|
448
|
+
key={index}
|
|
449
|
+
className="flex items-center gap-3 border-b px-4 py-3 last:border-b-0"
|
|
450
|
+
>
|
|
451
|
+
<Skeleton className="size-8 rounded-md" />
|
|
452
|
+
<div className="min-w-0 flex-1">
|
|
453
|
+
<Skeleton className="h-4 w-40 max-w-full" />
|
|
454
|
+
<Skeleton className="mt-1.5 h-3 w-56 max-w-full" />
|
|
455
|
+
</div>
|
|
456
|
+
<Skeleton className="h-6 w-20 rounded-full" />
|
|
457
|
+
</div>
|
|
458
|
+
))}
|
|
382
459
|
</div>
|
|
383
460
|
)}
|
|
384
461
|
|
|
@@ -392,13 +469,13 @@ export default function ConnectionsRoute() {
|
|
|
392
469
|
<section>
|
|
393
470
|
<div className="mb-3 flex items-baseline justify-between">
|
|
394
471
|
<h2 className="text-sm font-medium text-foreground">
|
|
395
|
-
|
|
472
|
+
Not configured in apps
|
|
396
473
|
</h2>
|
|
397
474
|
<span className="text-xs text-muted-foreground">
|
|
398
475
|
{available.length}
|
|
399
476
|
</span>
|
|
400
477
|
</div>
|
|
401
|
-
<div className="
|
|
478
|
+
<div className="overflow-hidden rounded-lg bg-card">
|
|
402
479
|
{available.map((service) => (
|
|
403
480
|
<ConnectorCard
|
|
404
481
|
key={service.key}
|
|
@@ -413,12 +490,14 @@ export default function ConnectionsRoute() {
|
|
|
413
490
|
{connected.length > 0 && (
|
|
414
491
|
<section>
|
|
415
492
|
<div className="mb-3 mt-2 flex items-baseline justify-between">
|
|
416
|
-
<h2 className="text-sm font-medium text-foreground">
|
|
493
|
+
<h2 className="text-sm font-medium text-foreground">
|
|
494
|
+
Configured in apps
|
|
495
|
+
</h2>
|
|
417
496
|
<span className="text-xs text-muted-foreground">
|
|
418
497
|
{connected.length}
|
|
419
498
|
</span>
|
|
420
499
|
</div>
|
|
421
|
-
<div className="
|
|
500
|
+
<div className="overflow-hidden rounded-lg bg-card">
|
|
422
501
|
{connected.map((service) => (
|
|
423
502
|
<ConnectorCard
|
|
424
503
|
key={service.key}
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
SelectValue,
|
|
34
34
|
} from "../../components/ui/select";
|
|
35
35
|
import { Skeleton } from "../../components/ui/skeleton";
|
|
36
|
+
import { UsageAlertsPanel } from "../../components/usage-alerts-panel";
|
|
36
37
|
import { cn } from "../../lib/utils";
|
|
37
38
|
|
|
38
39
|
export function meta() {
|
|
@@ -1038,6 +1039,13 @@ export default function MetricsRoute() {
|
|
|
1038
1039
|
<ReviewUsageButton metrics={metrics} billing={billing} />
|
|
1039
1040
|
</div>
|
|
1040
1041
|
|
|
1042
|
+
<UsageAlertsPanel
|
|
1043
|
+
scope={scope === "workspace" ? "workspace" : "user"}
|
|
1044
|
+
appOptions={metrics.byApp
|
|
1045
|
+
.filter((row) => row.key && row.key !== "unattributed")
|
|
1046
|
+
.map((row) => ({ id: row.key, label: displayApp(row.key) }))}
|
|
1047
|
+
/>
|
|
1048
|
+
|
|
1041
1049
|
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-5">
|
|
1042
1050
|
<MetricCard
|
|
1043
1051
|
label={billing.label}
|
|
@@ -105,11 +105,11 @@ export default function OperationsRoute() {
|
|
|
105
105
|
>
|
|
106
106
|
<TabsList className="w-fit">
|
|
107
107
|
<TabsTrigger value="monitoring">
|
|
108
|
-
<IconActivity size={15} />
|
|
108
|
+
<IconActivity size={15} className="mr-1.5" />
|
|
109
109
|
{t("dispatch.pages.monitoring")}
|
|
110
110
|
</TabsTrigger>
|
|
111
111
|
<TabsTrigger value="database">
|
|
112
|
-
<IconDatabase size={15} />
|
|
112
|
+
<IconDatabase size={15} className="mr-1.5" />
|
|
113
113
|
{t("dispatch.pages.database")}
|
|
114
114
|
</TabsTrigger>
|
|
115
115
|
</TabsList>
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from "../../components/ui/card";
|
|
27
27
|
import { Label } from "../../components/ui/label";
|
|
28
28
|
import { Switch } from "../../components/ui/switch";
|
|
29
|
+
import { dispatchAccessDescriptor } from "../../shared/app-roles.js";
|
|
29
30
|
|
|
30
31
|
export function meta() {
|
|
31
32
|
return [{ title: "Settings - Dispatch" }];
|
|
@@ -33,7 +34,19 @@ export function meta() {
|
|
|
33
34
|
|
|
34
35
|
export default function SettingsRoute() {
|
|
35
36
|
const t = useT();
|
|
36
|
-
const agentSettingsTabs = useAgentSettingsTabs(
|
|
37
|
+
const agentSettingsTabs = useAgentSettingsTabs({
|
|
38
|
+
usageAppId: "dispatch",
|
|
39
|
+
usageViewAllHref: "/admin/metrics",
|
|
40
|
+
organizationContent: (
|
|
41
|
+
<div className="mx-auto w-full max-w-3xl">
|
|
42
|
+
<TeamPage
|
|
43
|
+
showTitle={false}
|
|
44
|
+
appRoles={dispatchAccessDescriptor}
|
|
45
|
+
createOrgDescription="Set up a team to share dispatch destinations and approvals with your colleagues."
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
48
|
+
),
|
|
49
|
+
});
|
|
37
50
|
const settingsTabs = [
|
|
38
51
|
...agentSettingsTabs.filter((tab) => tab.id !== "integrations"),
|
|
39
52
|
{
|
|
@@ -172,14 +185,6 @@ export default function SettingsRoute() {
|
|
|
172
185
|
</Card>
|
|
173
186
|
</div>
|
|
174
187
|
}
|
|
175
|
-
team={
|
|
176
|
-
<div className="mx-auto w-full max-w-3xl">
|
|
177
|
-
<TeamPage
|
|
178
|
-
showTitle={false}
|
|
179
|
-
createOrgDescription="Set up a team to share dispatch destinations and approvals with your colleagues."
|
|
180
|
-
/>
|
|
181
|
-
</div>
|
|
182
|
-
}
|
|
183
188
|
whatsNew={
|
|
184
189
|
<div className="mx-auto w-full max-w-3xl">
|
|
185
190
|
<ChangelogSettingsCard markdown={changelog} />
|
|
@@ -520,20 +520,18 @@ function ResultCard({
|
|
|
520
520
|
selected ? "bg-accent/70" : "hover:bg-muted/50",
|
|
521
521
|
)}
|
|
522
522
|
>
|
|
523
|
-
<div className="
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
</div>
|
|
529
|
-
<Badge variant="outline" className="shrink-0">
|
|
523
|
+
<div className="truncate text-sm font-medium text-foreground">
|
|
524
|
+
{title}
|
|
525
|
+
</div>
|
|
526
|
+
<div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted-foreground">
|
|
527
|
+
<span>
|
|
530
528
|
{result.messageCount}{" "}
|
|
531
529
|
{result.messageCount === 1 ? "message" : "messages"}
|
|
532
|
-
</
|
|
533
|
-
|
|
534
|
-
<div className="mt-2 flex items-center justify-between gap-3 text-[11px] text-muted-foreground">
|
|
530
|
+
</span>
|
|
531
|
+
<span aria-hidden="true">·</span>
|
|
535
532
|
<span className="min-w-0 truncate">{result.ownerEmail}</span>
|
|
536
|
-
<span
|
|
533
|
+
<span aria-hidden="true">·</span>
|
|
534
|
+
<span>{formatRelativeDate(result.updatedAt)}</span>
|
|
537
535
|
</div>
|
|
538
536
|
</button>
|
|
539
537
|
);
|
|
@@ -1621,31 +1619,6 @@ export default function ThreadDebugRoute() {
|
|
|
1621
1619
|
</SelectContent>
|
|
1622
1620
|
</Select>
|
|
1623
1621
|
</div>
|
|
1624
|
-
<div className="mt-3 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
|
|
1625
|
-
<span className="font-medium text-foreground">
|
|
1626
|
-
{failures.length} loaded{" "}
|
|
1627
|
-
{failures.length === 1 ? "run" : "runs"}
|
|
1628
|
-
</span>
|
|
1629
|
-
<span>·</span>
|
|
1630
|
-
<span>
|
|
1631
|
-
{failuresData?.access?.scope ??
|
|
1632
|
-
t("dispatch.pages.threadDebugCurrentScope", {
|
|
1633
|
-
defaultValue: "current scope",
|
|
1634
|
-
})}
|
|
1635
|
-
</span>
|
|
1636
|
-
{failurePatterns.slice(0, 3).map((pattern) => (
|
|
1637
|
-
<Badge key={pattern.label} variant="outline">
|
|
1638
|
-
{pattern.count} {pattern.label}
|
|
1639
|
-
</Badge>
|
|
1640
|
-
))}
|
|
1641
|
-
{failuresData?.partial ? (
|
|
1642
|
-
<Badge variant="outline">
|
|
1643
|
-
{t("dispatch.pages.threadDebugPartialResults", {
|
|
1644
|
-
defaultValue: "Partial results",
|
|
1645
|
-
})}
|
|
1646
|
-
</Badge>
|
|
1647
|
-
) : null}
|
|
1648
|
-
</div>
|
|
1649
1622
|
{unavailableFailureSources.length > 0 ? (
|
|
1650
1623
|
<div className="mt-2 flex items-start gap-1.5 text-xs text-muted-foreground">
|
|
1651
1624
|
<IconAlertTriangle className="mt-0.5 size-3.5 shrink-0" />
|
|
@@ -1662,6 +1635,15 @@ export default function ThreadDebugRoute() {
|
|
|
1662
1635
|
</span>
|
|
1663
1636
|
</div>
|
|
1664
1637
|
) : null}
|
|
1638
|
+
{failuresData?.partial ? (
|
|
1639
|
+
<div className="mt-2">
|
|
1640
|
+
<Badge variant="outline">
|
|
1641
|
+
{t("dispatch.pages.threadDebugPartialResults", {
|
|
1642
|
+
defaultValue: "Partial results",
|
|
1643
|
+
})}
|
|
1644
|
+
</Badge>
|
|
1645
|
+
</div>
|
|
1646
|
+
) : null}
|
|
1665
1647
|
</section>
|
|
1666
1648
|
|
|
1667
1649
|
{failuresError ? (
|
|
@@ -829,8 +829,13 @@ export default function VaultRoute() {
|
|
|
829
829
|
|
|
830
830
|
<TabsContent value="secrets" className="mt-4 space-y-3">
|
|
831
831
|
{!accessReady ? (
|
|
832
|
-
<div className="
|
|
833
|
-
|
|
832
|
+
<div className="space-y-3">
|
|
833
|
+
{Array.from({ length: 3 }).map((_, index) => (
|
|
834
|
+
<div key={index} className="rounded-lg bg-card px-4 py-4">
|
|
835
|
+
<Skeleton className="h-4 w-1/3" />
|
|
836
|
+
<Skeleton className="mt-2 h-3 w-2/3" />
|
|
837
|
+
</div>
|
|
838
|
+
))}
|
|
834
839
|
</div>
|
|
835
840
|
) : !canManageVault ? (
|
|
836
841
|
<div className="rounded-2xl border border-dashed px-6 py-12 text-center">
|