@agent-native/dispatch 0.14.3 → 0.14.5
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/README.md +114 -128
- package/dist/actions/list_apps.d.ts +1 -0
- package/dist/actions/list_apps.js +16 -8
- package/dist/actions/list_apps.js.map +1 -1
- package/dist/actions/set-mcp-app-access.js +1 -4
- package/dist/actions/set-mcp-app-access.js.map +1 -1
- package/dist/components/action-query-error.d.ts +8 -0
- package/dist/components/action-query-error.d.ts.map +1 -0
- package/dist/components/action-query-error.js +10 -0
- package/dist/components/action-query-error.js.map +1 -0
- package/dist/components/app-keys-popover.d.ts +4 -0
- package/dist/components/app-keys-popover.d.ts.map +1 -1
- package/dist/components/app-keys-popover.js +26 -14
- package/dist/components/app-keys-popover.js.map +1 -1
- package/dist/components/dispatch-control-plane.d.ts.map +1 -1
- package/dist/components/dispatch-control-plane.js +31 -27
- package/dist/components/dispatch-control-plane.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- 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 +19 -21
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/task-queue-health.d.ts.map +1 -1
- package/dist/components/task-queue-health.js +9 -1
- package/dist/components/task-queue-health.js.map +1 -1
- package/dist/components/ui/sheet.js +1 -1
- package/dist/components/ui/sheet.js.map +1 -1
- package/dist/components/ui/toast.js +1 -1
- package/dist/components/ui/toast.js.map +1 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +8 -5
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/components/workspace-resource-effective-stack.d.ts.map +1 -1
- package/dist/components/workspace-resource-effective-stack.js +6 -1
- package/dist/components/workspace-resource-effective-stack.js.map +1 -1
- package/dist/components/workspace-resource-impact-preview.d.ts.map +1 -1
- package/dist/components/workspace-resource-impact-preview.js +6 -1
- package/dist/components/workspace-resource-impact-preview.js.map +1 -1
- package/dist/routes/pages/$appId.d.ts.map +1 -1
- package/dist/routes/pages/$appId.js +6 -1
- 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 +5 -8
- package/dist/routes/pages/agents.js.map +1 -1
- package/dist/routes/pages/approval.d.ts.map +1 -1
- package/dist/routes/pages/approval.js +6 -1
- package/dist/routes/pages/approval.js.map +1 -1
- package/dist/routes/pages/approvals.d.ts.map +1 -1
- package/dist/routes/pages/approvals.js +8 -5
- package/dist/routes/pages/approvals.js.map +1 -1
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +4 -2
- 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 +10 -42
- 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 +4 -2
- package/dist/routes/pages/audit.js.map +1 -1
- package/dist/routes/pages/automations.d.ts.map +1 -1
- package/dist/routes/pages/automations.js +0 -1
- package/dist/routes/pages/automations.js.map +1 -1
- package/dist/routes/pages/chat.d.ts.map +1 -1
- package/dist/routes/pages/chat.js +16 -2
- package/dist/routes/pages/chat.js.map +1 -1
- package/dist/routes/pages/destinations.d.ts.map +1 -1
- package/dist/routes/pages/destinations.js +5 -3
- package/dist/routes/pages/destinations.js.map +1 -1
- package/dist/routes/pages/identities.d.ts.map +1 -1
- package/dist/routes/pages/identities.js +5 -3
- package/dist/routes/pages/identities.js.map +1 -1
- package/dist/routes/pages/integrations.d.ts.map +1 -1
- package/dist/routes/pages/integrations.js +9 -3
- 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 +1 -1
- package/dist/routes/pages/metrics.js.map +1 -1
- package/dist/routes/pages/thread-debug.d.ts.map +1 -1
- package/dist/routes/pages/thread-debug.js +7 -6
- 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 +23 -7
- 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 +9 -3
- package/dist/routes/pages/workspace.js.map +1 -1
- package/dist/server/lib/dispatch-store.d.ts.map +1 -1
- package/dist/server/lib/dispatch-store.js +2 -2
- package/dist/server/lib/dispatch-store.js.map +1 -1
- package/dist/server/lib/mcp-access-store.d.ts.map +1 -1
- package/dist/server/lib/mcp-access-store.js +30 -2
- package/dist/server/lib/mcp-access-store.js.map +1 -1
- package/dist/server/plugins/agent-chat.d.ts +1 -1
- package/package.json +2 -2
- package/src/actions/list_apps.spec.ts +52 -0
- package/src/actions/list_apps.ts +16 -8
- package/src/actions/set-mcp-app-access.spec.ts +73 -0
- package/src/actions/set-mcp-app-access.ts +1 -5
- package/src/components/action-query-error.spec.tsx +56 -0
- package/src/components/action-query-error.tsx +32 -0
- package/src/components/app-keys-popover.spec.tsx +85 -0
- package/src/components/app-keys-popover.tsx +76 -50
- package/src/components/dispatch-control-plane.spec.tsx +106 -0
- package/src/components/dispatch-control-plane.tsx +71 -115
- package/src/components/index.ts +1 -0
- package/src/components/layout/Layout.spec.tsx +42 -2
- package/src/components/layout/Layout.tsx +22 -27
- package/src/components/task-queue-health.tsx +9 -1
- package/src/components/ui/sheet.tsx +1 -1
- package/src/components/ui/toast.tsx +1 -1
- package/src/components/workspace-app-card.spec.tsx +80 -0
- package/src/components/workspace-app-card.tsx +36 -25
- package/src/components/workspace-resource-effective-stack.tsx +13 -1
- package/src/components/workspace-resource-impact-preview.tsx +12 -1
- package/src/routes/pages/$appId.tsx +17 -1
- package/src/routes/pages/agents.tsx +24 -11
- package/src/routes/pages/approval.tsx +16 -4
- package/src/routes/pages/approvals.tsx +108 -89
- package/src/routes/pages/apps.$appId.tsx +9 -2
- package/src/routes/pages/apps.tsx +13 -177
- package/src/routes/pages/audit.tsx +29 -20
- package/src/routes/pages/automations.tsx +0 -1
- package/src/routes/pages/chat.spec.tsx +94 -0
- package/src/routes/pages/chat.tsx +30 -10
- package/src/routes/pages/destinations.tsx +75 -62
- package/src/routes/pages/identities.tsx +74 -63
- package/src/routes/pages/integrations.tsx +17 -10
- package/src/routes/pages/metrics.tsx +0 -1
- package/src/routes/pages/thread-debug.tsx +18 -12
- package/src/routes/pages/vault.tsx +59 -26
- package/src/routes/pages/workspace.tsx +69 -55
- package/src/server/lib/approval-fencing.spec.ts +113 -2
- package/src/server/lib/dispatch-store.ts +2 -0
- package/src/server/lib/mcp-access-store.spec.ts +116 -4
- package/src/server/lib/mcp-access-store.ts +37 -2
- package/src/server/lib/mcp-gateway.spec.ts +79 -3
- package/src/styles/dispatch.css +5 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
2
2
|
import { toast } from "sonner";
|
|
3
3
|
|
|
4
|
+
import { ActionQueryError } from "../../components/action-query-error";
|
|
4
5
|
import { DispatchShell } from "../../components/dispatch-shell";
|
|
5
6
|
import { Button } from "../../components/ui/button";
|
|
6
7
|
|
|
@@ -9,7 +10,8 @@ export function meta() {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export default function IdentitiesRoute() {
|
|
12
|
-
const
|
|
13
|
+
const query = useActionQuery("list-linked-identities", {});
|
|
14
|
+
const { data } = query;
|
|
13
15
|
const createToken = useActionMutation("create-link-token", {
|
|
14
16
|
onSuccess: () => toast.success("Link token created"),
|
|
15
17
|
});
|
|
@@ -19,74 +21,83 @@ export default function IdentitiesRoute() {
|
|
|
19
21
|
title="Identities"
|
|
20
22
|
description="Link external senders to workspace users."
|
|
21
23
|
>
|
|
22
|
-
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
{query.isError ? (
|
|
25
|
+
<ActionQueryError
|
|
26
|
+
error={query.error}
|
|
27
|
+
onRetry={() => void query.refetch()}
|
|
28
|
+
/>
|
|
29
|
+
) : (
|
|
30
|
+
<div className="grid gap-4 xl:grid-cols-2">
|
|
31
|
+
<section className="rounded-2xl border bg-card p-5">
|
|
32
|
+
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
33
|
+
<h2 className="text-lg font-semibold text-foreground">
|
|
34
|
+
Active links
|
|
35
|
+
</h2>
|
|
36
|
+
<div className="flex shrink-0 gap-2">
|
|
37
|
+
<Button
|
|
38
|
+
variant="outline"
|
|
39
|
+
onClick={() => createToken.mutate({ platform: "slack" })}
|
|
40
|
+
>
|
|
41
|
+
New Slack token
|
|
42
|
+
</Button>
|
|
43
|
+
<Button
|
|
44
|
+
onClick={() => createToken.mutate({ platform: "telegram" })}
|
|
45
|
+
>
|
|
46
|
+
New Telegram token
|
|
47
|
+
</Button>
|
|
48
|
+
</div>
|
|
40
49
|
</div>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
<div className="mt-4 space-y-3">
|
|
51
|
+
{(data?.links || []).map((link: any) => (
|
|
52
|
+
<div
|
|
53
|
+
key={link.id}
|
|
54
|
+
className="rounded-xl border bg-muted/30 px-4 py-3"
|
|
55
|
+
>
|
|
56
|
+
<div className="text-sm font-medium text-foreground">
|
|
57
|
+
{link.externalUserName || link.externalUserId}
|
|
58
|
+
</div>
|
|
59
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
60
|
+
{link.platform} → {link.ownerEmail}
|
|
61
|
+
</div>
|
|
50
62
|
</div>
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
))}
|
|
64
|
+
{(data?.links?.length || 0) === 0 && (
|
|
65
|
+
<div className="rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground">
|
|
66
|
+
No linked identities yet. Generate a token and ask the user to
|
|
67
|
+
send <code>/link TOKEN</code> from Slack or Telegram.
|
|
53
68
|
</div>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<div className="rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground">
|
|
58
|
-
No linked identities yet. Generate a token and ask the user to
|
|
59
|
-
send <code>/link TOKEN</code> from Slack or Telegram.
|
|
60
|
-
</div>
|
|
61
|
-
)}
|
|
62
|
-
</div>
|
|
63
|
-
</section>
|
|
69
|
+
)}
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
64
72
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
<section className="rounded-2xl border bg-card p-5">
|
|
74
|
+
<h2 className="text-lg font-semibold text-foreground">
|
|
75
|
+
Link tokens
|
|
76
|
+
</h2>
|
|
77
|
+
<div className="mt-4 space-y-3">
|
|
78
|
+
{(data?.tokens || []).map((token: any) => (
|
|
79
|
+
<div key={token.id} className="rounded-xl border px-4 py-3">
|
|
80
|
+
<div className="text-sm font-medium text-foreground">
|
|
81
|
+
/link {token.token}
|
|
82
|
+
</div>
|
|
83
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
84
|
+
{token.platform} · expires{" "}
|
|
85
|
+
{new Date(token.expiresAt).toLocaleString()}
|
|
86
|
+
{token.claimedAt
|
|
87
|
+
? ` · claimed by ${token.claimedByExternalUserName || token.claimedByExternalUserId}`
|
|
88
|
+
: " · waiting to be claimed"}
|
|
89
|
+
</div>
|
|
72
90
|
</div>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
? ` · claimed by ${token.claimedByExternalUserName || token.claimedByExternalUserId}`
|
|
78
|
-
: " · waiting to be claimed"}
|
|
91
|
+
))}
|
|
92
|
+
{(data?.tokens?.length || 0) === 0 && (
|
|
93
|
+
<div className="rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground">
|
|
94
|
+
No active link tokens.
|
|
79
95
|
</div>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
</div>
|
|
86
|
-
)}
|
|
87
|
-
</div>
|
|
88
|
-
</section>
|
|
89
|
-
</div>
|
|
96
|
+
)}
|
|
97
|
+
</div>
|
|
98
|
+
</section>
|
|
99
|
+
</div>
|
|
100
|
+
)}
|
|
90
101
|
</DispatchShell>
|
|
91
102
|
);
|
|
92
103
|
}
|
|
@@ -11,6 +11,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
|
|
11
11
|
import { useMemo, useState } from "react";
|
|
12
12
|
import { toast } from "sonner";
|
|
13
13
|
|
|
14
|
+
import { ActionQueryError } from "../../components/action-query-error";
|
|
14
15
|
import { DispatchShell } from "../../components/dispatch-shell";
|
|
15
16
|
import { Badge } from "../../components/ui/badge";
|
|
16
17
|
import { Button } from "../../components/ui/button";
|
|
@@ -319,14 +320,10 @@ function PerAppDetailRow({ app }: { app: CatalogApp }) {
|
|
|
319
320
|
}
|
|
320
321
|
|
|
321
322
|
export default function ConnectionsRoute() {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const { data: accessSettings } = useActionQuery(
|
|
327
|
-
"get-vault-access-settings",
|
|
328
|
-
{},
|
|
329
|
-
);
|
|
323
|
+
const catalogQuery = useActionQuery("list-integrations-catalog", {});
|
|
324
|
+
const accessQuery = useActionQuery("get-vault-access-settings", {});
|
|
325
|
+
const { data: catalog, isLoading } = catalogQuery;
|
|
326
|
+
const { data: accessSettings } = accessQuery;
|
|
330
327
|
const apps = (catalog as CatalogApp[]) || [];
|
|
331
328
|
const accessMode =
|
|
332
329
|
(accessSettings as any)?.mode === "manual" ? "manual" : "all-apps";
|
|
@@ -365,13 +362,23 @@ export default function ConnectionsRoute() {
|
|
|
365
362
|
title="Connections"
|
|
366
363
|
description="Connect services once. Apps that need them pick up the key automatically."
|
|
367
364
|
>
|
|
368
|
-
{
|
|
365
|
+
{catalogQuery.isError || accessQuery.isError ? (
|
|
366
|
+
<ActionQueryError
|
|
367
|
+
error={catalogQuery.error ?? accessQuery.error}
|
|
368
|
+
onRetry={() => {
|
|
369
|
+
void catalogQuery.refetch();
|
|
370
|
+
void accessQuery.refetch();
|
|
371
|
+
}}
|
|
372
|
+
/>
|
|
373
|
+
) : null}
|
|
374
|
+
|
|
375
|
+
{!catalogQuery.isError && isLoading && services.length === 0 && (
|
|
369
376
|
<div className="rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground">
|
|
370
377
|
Discovering apps and credentials…
|
|
371
378
|
</div>
|
|
372
379
|
)}
|
|
373
380
|
|
|
374
|
-
{!isLoading && services.length === 0 && (
|
|
381
|
+
{!catalogQuery.isError && !isLoading && services.length === 0 && (
|
|
375
382
|
<div className="rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground">
|
|
376
383
|
No apps with declared integrations are reachable yet.
|
|
377
384
|
</div>
|
|
@@ -643,7 +643,6 @@ export default function MetricsRoute() {
|
|
|
643
643
|
const { data, isLoading, error } = useActionQuery(
|
|
644
644
|
"list-dispatch-usage-metrics",
|
|
645
645
|
{ sinceDays },
|
|
646
|
-
{ refetchInterval: 30_000 },
|
|
647
646
|
);
|
|
648
647
|
const metrics = data as DispatchUsageMetrics | undefined;
|
|
649
648
|
const billing = metrics?.billing ?? USD_BILLING;
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
} from "@tabler/icons-react";
|
|
8
8
|
import { useEffect, useMemo, useState } from "react";
|
|
9
9
|
|
|
10
|
+
import { ActionQueryError } from "../../components/action-query-error";
|
|
10
11
|
import { DispatchShell } from "../../components/dispatch-shell";
|
|
11
|
-
import { Alert, AlertDescription, AlertTitle } from "../../components/ui/alert";
|
|
12
12
|
import { Badge } from "../../components/ui/badge";
|
|
13
13
|
import { Button } from "../../components/ui/button";
|
|
14
14
|
import { Input } from "../../components/ui/input";
|
|
@@ -430,7 +430,7 @@ export default function ThreadDebugRoute() {
|
|
|
430
430
|
ownerEmail?: string;
|
|
431
431
|
} | null>(null);
|
|
432
432
|
|
|
433
|
-
const
|
|
433
|
+
const sourcesQuery = useActionQuery<{
|
|
434
434
|
access: {
|
|
435
435
|
viewerEmail: string;
|
|
436
436
|
orgId: string | null;
|
|
@@ -441,6 +441,7 @@ export default function ThreadDebugRoute() {
|
|
|
441
441
|
};
|
|
442
442
|
sources: ThreadDebugSource[];
|
|
443
443
|
}>("list-agent-thread-sources", {});
|
|
444
|
+
const { data: sourcesData, isLoading: sourcesLoading } = sourcesQuery;
|
|
444
445
|
|
|
445
446
|
const sources: ThreadDebugSource[] = sourcesData?.sources ?? [];
|
|
446
447
|
const searchParams = useMemo(
|
|
@@ -480,6 +481,7 @@ export default function ThreadDebugRoute() {
|
|
|
480
481
|
data: detail,
|
|
481
482
|
isLoading: detailLoading,
|
|
482
483
|
error: detailError,
|
|
484
|
+
refetch: refetchDetail,
|
|
483
485
|
} = useActionQuery<ThreadDebugResponse>(
|
|
484
486
|
"get-agent-thread-debug",
|
|
485
487
|
detailParams,
|
|
@@ -515,6 +517,12 @@ export default function ThreadDebugRoute() {
|
|
|
515
517
|
description="Inspect persisted agent chat threads, run events, and AI internals."
|
|
516
518
|
>
|
|
517
519
|
<div className="space-y-4">
|
|
520
|
+
{sourcesQuery.isError ? (
|
|
521
|
+
<ActionQueryError
|
|
522
|
+
error={sourcesQuery.error}
|
|
523
|
+
onRetry={() => void sourcesQuery.refetch()}
|
|
524
|
+
/>
|
|
525
|
+
) : null}
|
|
518
526
|
<section className="rounded-lg border bg-card p-4">
|
|
519
527
|
<div className="grid gap-3 lg:grid-cols-[220px_1fr_260px_auto]">
|
|
520
528
|
<Select value={sourceId} onValueChange={setSourceId}>
|
|
@@ -600,10 +608,10 @@ export default function ThreadDebugRoute() {
|
|
|
600
608
|
</section>
|
|
601
609
|
|
|
602
610
|
{searchError ? (
|
|
603
|
-
<
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
611
|
+
<ActionQueryError
|
|
612
|
+
error={searchError}
|
|
613
|
+
onRetry={() => void refetchSearch()}
|
|
614
|
+
/>
|
|
607
615
|
) : null}
|
|
608
616
|
|
|
609
617
|
<div className="grid gap-4 xl:grid-cols-[380px_1fr]">
|
|
@@ -661,12 +669,10 @@ export default function ThreadDebugRoute() {
|
|
|
661
669
|
|
|
662
670
|
<section className="min-w-0">
|
|
663
671
|
{detailError ? (
|
|
664
|
-
<
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
</AlertDescription>
|
|
669
|
-
</Alert>
|
|
672
|
+
<ActionQueryError
|
|
673
|
+
error={detailError}
|
|
674
|
+
onRetry={() => void refetchDetail()}
|
|
675
|
+
/>
|
|
670
676
|
) : null}
|
|
671
677
|
{detailLoading ? (
|
|
672
678
|
<div className="rounded-lg border bg-card p-4">
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { useState } from "react";
|
|
15
15
|
import { toast } from "sonner";
|
|
16
16
|
|
|
17
|
+
import { ActionQueryError } from "../../components/action-query-error";
|
|
17
18
|
import { DispatchShell } from "../../components/dispatch-shell";
|
|
18
19
|
import {
|
|
19
20
|
AlertDialog,
|
|
@@ -736,17 +737,16 @@ function RequestRow({ request }: { request: any }) {
|
|
|
736
737
|
}
|
|
737
738
|
|
|
738
739
|
export default function VaultRoute() {
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
);
|
|
743
|
-
const
|
|
744
|
-
const { data:
|
|
745
|
-
const { data:
|
|
746
|
-
const { data:
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
);
|
|
740
|
+
const secretsQuery = useActionQuery("list-vault-secrets", {});
|
|
741
|
+
const grantsQuery = useActionQuery("list-vault-grants", {});
|
|
742
|
+
const requestsQuery = useActionQuery("list-vault-requests", {});
|
|
743
|
+
const auditQuery = useActionQuery("list-vault-audit", { limit: 20 });
|
|
744
|
+
const accessQuery = useActionQuery("get-vault-access-settings", {});
|
|
745
|
+
const { data: secrets, isLoading: secretsLoading } = secretsQuery;
|
|
746
|
+
const { data: grants } = grantsQuery;
|
|
747
|
+
const { data: requests } = requestsQuery;
|
|
748
|
+
const { data: audit } = auditQuery;
|
|
749
|
+
const { data: accessSettings } = accessQuery;
|
|
750
750
|
const accessMode: VaultAccessMode =
|
|
751
751
|
(accessSettings as any)?.mode === "manual" ? "manual" : "all-apps";
|
|
752
752
|
|
|
@@ -788,6 +788,20 @@ export default function VaultRoute() {
|
|
|
788
788
|
</TabsList>
|
|
789
789
|
|
|
790
790
|
<TabsContent value="secrets" className="mt-4 space-y-3">
|
|
791
|
+
{secretsQuery.isError ||
|
|
792
|
+
grantsQuery.isError ||
|
|
793
|
+
accessQuery.isError ? (
|
|
794
|
+
<ActionQueryError
|
|
795
|
+
error={
|
|
796
|
+
secretsQuery.error ?? grantsQuery.error ?? accessQuery.error
|
|
797
|
+
}
|
|
798
|
+
onRetry={() => {
|
|
799
|
+
void secretsQuery.refetch();
|
|
800
|
+
void grantsQuery.refetch();
|
|
801
|
+
void accessQuery.refetch();
|
|
802
|
+
}}
|
|
803
|
+
/>
|
|
804
|
+
) : null}
|
|
791
805
|
<VaultAccessSettingsCard mode={accessMode} />
|
|
792
806
|
|
|
793
807
|
<div className="flex items-center justify-between">
|
|
@@ -804,7 +818,9 @@ export default function VaultRoute() {
|
|
|
804
818
|
<AddSecretDialog />
|
|
805
819
|
</div>
|
|
806
820
|
|
|
807
|
-
{
|
|
821
|
+
{!secretsQuery.isError &&
|
|
822
|
+
secretsLoading &&
|
|
823
|
+
(secrets ?? []).length === 0
|
|
808
824
|
? Array.from({ length: 3 }).map((_, index) => (
|
|
809
825
|
<div
|
|
810
826
|
key={index}
|
|
@@ -823,25 +839,36 @@ export default function VaultRoute() {
|
|
|
823
839
|
/>
|
|
824
840
|
))}
|
|
825
841
|
|
|
826
|
-
{!
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
<
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
842
|
+
{!secretsQuery.isError &&
|
|
843
|
+
!secretsLoading &&
|
|
844
|
+
(secrets?.length || 0) === 0 && (
|
|
845
|
+
<div className="rounded-2xl border border-dashed px-6 py-12 text-center">
|
|
846
|
+
<IconKey
|
|
847
|
+
size={32}
|
|
848
|
+
className="mx-auto text-muted-foreground/50"
|
|
849
|
+
/>
|
|
850
|
+
<h3 className="mt-3 text-sm font-medium text-foreground">
|
|
851
|
+
No secrets yet
|
|
852
|
+
</h3>
|
|
853
|
+
<p className="mt-1 text-sm text-muted-foreground">
|
|
854
|
+
Add your first secret to start sharing credentials across
|
|
855
|
+
workspace apps.
|
|
856
|
+
</p>
|
|
857
|
+
</div>
|
|
858
|
+
)}
|
|
838
859
|
</TabsContent>
|
|
839
860
|
|
|
840
861
|
<TabsContent value="requests" className="mt-4 space-y-3">
|
|
862
|
+
{requestsQuery.isError ? (
|
|
863
|
+
<ActionQueryError
|
|
864
|
+
error={requestsQuery.error}
|
|
865
|
+
onRetry={() => void requestsQuery.refetch()}
|
|
866
|
+
/>
|
|
867
|
+
) : null}
|
|
841
868
|
{(requests || []).map((request: any) => (
|
|
842
869
|
<RequestRow key={request.id} request={request} />
|
|
843
870
|
))}
|
|
844
|
-
{(requests?.length || 0) === 0 && (
|
|
871
|
+
{!requestsQuery.isError && (requests?.length || 0) === 0 && (
|
|
845
872
|
<div className="rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground">
|
|
846
873
|
No secret requests yet.
|
|
847
874
|
</div>
|
|
@@ -849,6 +876,12 @@ export default function VaultRoute() {
|
|
|
849
876
|
</TabsContent>
|
|
850
877
|
|
|
851
878
|
<TabsContent value="audit" className="mt-4 space-y-2">
|
|
879
|
+
{auditQuery.isError ? (
|
|
880
|
+
<ActionQueryError
|
|
881
|
+
error={auditQuery.error}
|
|
882
|
+
onRetry={() => void auditQuery.refetch()}
|
|
883
|
+
/>
|
|
884
|
+
) : null}
|
|
852
885
|
{(audit || []).map((event: any) => (
|
|
853
886
|
<div
|
|
854
887
|
key={event.id}
|
|
@@ -862,7 +895,7 @@ export default function VaultRoute() {
|
|
|
862
895
|
</div>
|
|
863
896
|
</div>
|
|
864
897
|
))}
|
|
865
|
-
{(audit?.length || 0) === 0 && (
|
|
898
|
+
{!auditQuery.isError && (audit?.length || 0) === 0 && (
|
|
866
899
|
<div className="rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground">
|
|
867
900
|
No vault activity yet.
|
|
868
901
|
</div>
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import { useEffect, useState, type ReactNode } from "react";
|
|
18
18
|
import { toast } from "sonner";
|
|
19
19
|
|
|
20
|
+
import { ActionQueryError } from "../../components/action-query-error";
|
|
20
21
|
import { DispatchShell } from "../../components/dispatch-shell";
|
|
21
22
|
import {
|
|
22
23
|
AlertDialog,
|
|
@@ -1014,11 +1015,10 @@ function GlobalContextSection({ resources }: { resources: any[] }) {
|
|
|
1014
1015
|
}
|
|
1015
1016
|
|
|
1016
1017
|
export default function WorkspaceRoute() {
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
const { data: grants } = useActionQuery("list-workspace-resource-grants", {});
|
|
1018
|
+
const resourcesQuery = useActionQuery("list-workspace-resources", {});
|
|
1019
|
+
const grantsQuery = useActionQuery("list-workspace-resource-grants", {});
|
|
1020
|
+
const { data: resources, isLoading } = resourcesQuery;
|
|
1021
|
+
const { data: grants } = grantsQuery;
|
|
1022
1022
|
|
|
1023
1023
|
const grantsByResource = (grants || []).reduce(
|
|
1024
1024
|
(acc: Record<string, any[]>, g: any) => {
|
|
@@ -1088,6 +1088,15 @@ export default function WorkspaceRoute() {
|
|
|
1088
1088
|
title="Workspace Resources"
|
|
1089
1089
|
description="Manage inherited workspace skills, guardrail instructions, agent profiles, reference resources, and MCP servers. All-app resources are available to every app without syncing."
|
|
1090
1090
|
>
|
|
1091
|
+
{resourcesQuery.isError || grantsQuery.isError ? (
|
|
1092
|
+
<ActionQueryError
|
|
1093
|
+
error={resourcesQuery.error ?? grantsQuery.error}
|
|
1094
|
+
onRetry={() => {
|
|
1095
|
+
void resourcesQuery.refetch();
|
|
1096
|
+
void grantsQuery.refetch();
|
|
1097
|
+
}}
|
|
1098
|
+
/>
|
|
1099
|
+
) : null}
|
|
1091
1100
|
<div className="flex items-center justify-between">
|
|
1092
1101
|
<div className="text-sm text-muted-foreground">
|
|
1093
1102
|
{isLoading ? (
|
|
@@ -1101,62 +1110,67 @@ export default function WorkspaceRoute() {
|
|
|
1101
1110
|
</div>
|
|
1102
1111
|
</div>
|
|
1103
1112
|
|
|
1104
|
-
|
|
1113
|
+
{!resourcesQuery.isError ? (
|
|
1114
|
+
<GlobalContextSection resources={resources || []} />
|
|
1115
|
+
) : null}
|
|
1105
1116
|
|
|
1106
|
-
|
|
1107
|
-
<
|
|
1108
|
-
<
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1117
|
+
{!resourcesQuery.isError && !grantsQuery.isError ? (
|
|
1118
|
+
<Tabs defaultValue="skills">
|
|
1119
|
+
<TabsList>
|
|
1120
|
+
<TabsTrigger value="skills">
|
|
1121
|
+
Skills {skills.length > 0 && `(${skills.length})`}
|
|
1122
|
+
</TabsTrigger>
|
|
1123
|
+
<TabsTrigger value="instructions">
|
|
1124
|
+
Instructions{" "}
|
|
1125
|
+
{instructions.length > 0 && `(${instructions.length})`}
|
|
1126
|
+
</TabsTrigger>
|
|
1127
|
+
<TabsTrigger value="agents">
|
|
1128
|
+
Agents {agents.length > 0 && `(${agents.length})`}
|
|
1129
|
+
</TabsTrigger>
|
|
1130
|
+
<TabsTrigger value="knowledge">
|
|
1131
|
+
Knowledge {knowledge.length > 0 && `(${knowledge.length})`}
|
|
1132
|
+
</TabsTrigger>
|
|
1133
|
+
<TabsTrigger value="mcp">
|
|
1134
|
+
MCP {mcpServers.length > 0 && `(${mcpServers.length})`}
|
|
1135
|
+
</TabsTrigger>
|
|
1136
|
+
</TabsList>
|
|
1124
1137
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1138
|
+
<TabsContent value="skills" className="mt-4">
|
|
1139
|
+
<ResourceList
|
|
1140
|
+
items={skills}
|
|
1141
|
+
emptyText="No workspace skills yet. Add a skill to share agent guidance across apps."
|
|
1142
|
+
/>
|
|
1143
|
+
</TabsContent>
|
|
1131
1144
|
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1145
|
+
<TabsContent value="instructions" className="mt-4">
|
|
1146
|
+
<ResourceList
|
|
1147
|
+
items={instructions}
|
|
1148
|
+
emptyText="No workspace instructions yet. Add instructions to set behavioral rules across apps."
|
|
1149
|
+
/>
|
|
1150
|
+
</TabsContent>
|
|
1138
1151
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1152
|
+
<TabsContent value="agents" className="mt-4">
|
|
1153
|
+
<ResourceList
|
|
1154
|
+
items={agents}
|
|
1155
|
+
emptyText="No workspace agents yet. Add a reusable agent profile to share specialist agents across apps."
|
|
1156
|
+
/>
|
|
1157
|
+
</TabsContent>
|
|
1145
1158
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1159
|
+
<TabsContent value="knowledge" className="mt-4">
|
|
1160
|
+
<ResourceList
|
|
1161
|
+
items={knowledge}
|
|
1162
|
+
emptyText="No knowledge packs yet. Add GTM, product, or domain context that apps can reuse."
|
|
1163
|
+
/>
|
|
1164
|
+
</TabsContent>
|
|
1152
1165
|
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1166
|
+
<TabsContent value="mcp" className="mt-4">
|
|
1167
|
+
<ResourceList
|
|
1168
|
+
items={mcpServers}
|
|
1169
|
+
emptyText="No workspace MCP servers yet. Add an HTTP MCP server to share external tools across apps."
|
|
1170
|
+
/>
|
|
1171
|
+
</TabsContent>
|
|
1172
|
+
</Tabs>
|
|
1173
|
+
) : null}
|
|
1160
1174
|
</DispatchShell>
|
|
1161
1175
|
);
|
|
1162
1176
|
}
|