@agent-native/dispatch 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/app-keys-popover.d.ts.map +1 -1
- package/dist/components/app-keys-popover.js +2 -1
- package/dist/components/app-keys-popover.js.map +1 -1
- package/dist/components/create-app-popover.js +1 -1
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/layout/Layout.js +3 -3
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +5 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/pages/$appId.d.ts +8 -0
- package/dist/routes/pages/$appId.d.ts.map +1 -0
- package/dist/routes/pages/$appId.js +91 -0
- package/dist/routes/pages/$appId.js.map +1 -0
- package/dist/routes/pages/approval.d.ts.map +1 -1
- package/dist/routes/pages/approval.js +2 -1
- package/dist/routes/pages/approval.js.map +1 -1
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +2 -1
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/integrations.d.ts +1 -1
- package/dist/routes/pages/integrations.d.ts.map +1 -1
- package/dist/routes/pages/integrations.js +131 -30
- package/dist/routes/pages/integrations.js.map +1 -1
- package/dist/routes/pages/overview.d.ts.map +1 -1
- package/dist/routes/pages/overview.js +10 -1
- package/dist/routes/pages/overview.js.map +1 -1
- package/dist/routes/pages/vault.d.ts.map +1 -1
- package/dist/routes/pages/vault.js +4 -3
- 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 +5 -3
- package/dist/routes/pages/workspace.js.map +1 -1
- package/dist/server/plugins/integrations.js +1 -1
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +2 -2
- package/src/components/app-keys-popover.tsx +15 -1
- package/src/components/create-app-popover.tsx +1 -1
- package/src/components/layout/Layout.tsx +3 -3
- package/src/routes/index.ts +5 -0
- package/src/routes/pages/$appId.tsx +178 -0
- package/src/routes/pages/approval.tsx +33 -3
- package/src/routes/pages/apps.$appId.tsx +6 -1
- package/src/routes/pages/integrations.tsx +348 -215
- package/src/routes/pages/overview.tsx +58 -26
- package/src/routes/pages/vault.tsx +25 -12
- package/src/routes/pages/workspace.tsx +21 -3
- package/src/server/plugins/integrations.ts +1 -1
|
@@ -131,6 +131,60 @@ function AppCardSkeleton() {
|
|
|
131
131
|
);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
interface RecentAuditEvent {
|
|
135
|
+
id: string;
|
|
136
|
+
summary: string;
|
|
137
|
+
actor: string;
|
|
138
|
+
createdAt: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function RecentActivityList({
|
|
142
|
+
isLoading,
|
|
143
|
+
events,
|
|
144
|
+
}: {
|
|
145
|
+
isLoading: boolean;
|
|
146
|
+
events: RecentAuditEvent[];
|
|
147
|
+
}) {
|
|
148
|
+
if (isLoading && events.length === 0) {
|
|
149
|
+
return (
|
|
150
|
+
<div className="mt-4 space-y-3">
|
|
151
|
+
{Array.from({ length: 3 }).map((_, index) => (
|
|
152
|
+
<div
|
|
153
|
+
key={index}
|
|
154
|
+
className="rounded-xl border bg-muted/30 px-4 py-3 space-y-2"
|
|
155
|
+
>
|
|
156
|
+
<Skeleton className="h-4 w-3/5" />
|
|
157
|
+
<Skeleton className="h-3 w-2/5" />
|
|
158
|
+
</div>
|
|
159
|
+
))}
|
|
160
|
+
</div>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (events.length === 0) {
|
|
164
|
+
return (
|
|
165
|
+
<div className="mt-4 space-y-3">
|
|
166
|
+
<div className="rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground">
|
|
167
|
+
No activity yet.
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
return (
|
|
173
|
+
<div className="mt-4 space-y-3">
|
|
174
|
+
{events.map((event) => (
|
|
175
|
+
<div key={event.id} className="rounded-xl border bg-muted/30 px-4 py-3">
|
|
176
|
+
<div className="text-sm font-medium text-foreground">
|
|
177
|
+
{event.summary}
|
|
178
|
+
</div>
|
|
179
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
180
|
+
{event.actor} · {new Date(event.createdAt).toLocaleString()}
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
))}
|
|
184
|
+
</div>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
134
188
|
function WorkspaceAppsSection({
|
|
135
189
|
apps,
|
|
136
190
|
isLoading,
|
|
@@ -625,33 +679,11 @@ export default function OverviewRoute() {
|
|
|
625
679
|
<h2 className="text-lg font-semibold text-foreground">
|
|
626
680
|
Recent activity
|
|
627
681
|
</h2>
|
|
628
|
-
{isLoading && (
|
|
629
|
-
<span className="text-xs text-muted-foreground">
|
|
630
|
-
Loading...
|
|
631
|
-
</span>
|
|
632
|
-
)}
|
|
633
|
-
</div>
|
|
634
|
-
<div className="mt-4 space-y-3">
|
|
635
|
-
{(data?.recentAudit || []).map((event) => (
|
|
636
|
-
<div
|
|
637
|
-
key={event.id}
|
|
638
|
-
className="rounded-xl border bg-muted/30 px-4 py-3"
|
|
639
|
-
>
|
|
640
|
-
<div className="text-sm font-medium text-foreground">
|
|
641
|
-
{event.summary}
|
|
642
|
-
</div>
|
|
643
|
-
<div className="mt-1 text-xs text-muted-foreground">
|
|
644
|
-
{event.actor} ·{" "}
|
|
645
|
-
{new Date(event.createdAt).toLocaleString()}
|
|
646
|
-
</div>
|
|
647
|
-
</div>
|
|
648
|
-
))}
|
|
649
|
-
{!isLoading && (data?.recentAudit?.length || 0) === 0 && (
|
|
650
|
-
<div className="rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground">
|
|
651
|
-
No activity yet.
|
|
652
|
-
</div>
|
|
653
|
-
)}
|
|
654
682
|
</div>
|
|
683
|
+
<RecentActivityList
|
|
684
|
+
isLoading={isLoading}
|
|
685
|
+
events={data?.recentAudit ?? []}
|
|
686
|
+
/>
|
|
655
687
|
</section>
|
|
656
688
|
|
|
657
689
|
<section className="rounded-2xl border bg-card p-5">
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
} from "@/components/ui/select";
|
|
47
47
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
48
48
|
import { Textarea } from "@/components/ui/textarea";
|
|
49
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
49
50
|
|
|
50
51
|
const PROVIDERS = [
|
|
51
52
|
"google",
|
|
@@ -549,22 +550,34 @@ export default function VaultRoute() {
|
|
|
549
550
|
<div className="flex items-center justify-between">
|
|
550
551
|
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
551
552
|
<IconKey size={16} />
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
553
|
+
{secretsLoading ? (
|
|
554
|
+
<Skeleton className="h-4 w-20" />
|
|
555
|
+
) : (
|
|
556
|
+
<span>
|
|
557
|
+
{`${secrets?.length || 0} secret${(secrets?.length || 0) !== 1 ? "s" : ""}`}
|
|
558
|
+
</span>
|
|
559
|
+
)}
|
|
557
560
|
</div>
|
|
558
561
|
<AddSecretDialog />
|
|
559
562
|
</div>
|
|
560
563
|
|
|
561
|
-
{(secrets
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
564
|
+
{secretsLoading && (secrets ?? []).length === 0
|
|
565
|
+
? Array.from({ length: 3 }).map((_, index) => (
|
|
566
|
+
<div
|
|
567
|
+
key={index}
|
|
568
|
+
className="rounded-2xl border bg-card px-5 py-4 space-y-2"
|
|
569
|
+
>
|
|
570
|
+
<Skeleton className="h-4 w-1/3" />
|
|
571
|
+
<Skeleton className="h-3 w-2/3" />
|
|
572
|
+
</div>
|
|
573
|
+
))
|
|
574
|
+
: (secrets || []).map((secret: any) => (
|
|
575
|
+
<SecretRow
|
|
576
|
+
key={secret.id}
|
|
577
|
+
secret={secret}
|
|
578
|
+
grants={grantsBySecret[secret.id] || []}
|
|
579
|
+
/>
|
|
580
|
+
))}
|
|
568
581
|
|
|
569
582
|
{!secretsLoading && (secrets?.length || 0) === 0 && (
|
|
570
583
|
<div className="rounded-2xl border border-dashed px-6 py-12 text-center">
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
} from "@/components/ui/select";
|
|
48
48
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
49
49
|
import { Textarea } from "@/components/ui/textarea";
|
|
50
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
50
51
|
|
|
51
52
|
export function meta() {
|
|
52
53
|
return [{ title: "Workspace Resources — Dispatch" }];
|
|
@@ -528,6 +529,21 @@ export default function WorkspaceRoute() {
|
|
|
528
529
|
items: any[];
|
|
529
530
|
emptyText: string;
|
|
530
531
|
}) {
|
|
532
|
+
if (isLoading && (resources ?? []).length === 0) {
|
|
533
|
+
return (
|
|
534
|
+
<div className="space-y-3">
|
|
535
|
+
{Array.from({ length: 3 }).map((_, index) => (
|
|
536
|
+
<div
|
|
537
|
+
key={index}
|
|
538
|
+
className="rounded-2xl border bg-card px-5 py-4 space-y-2"
|
|
539
|
+
>
|
|
540
|
+
<Skeleton className="h-4 w-1/3" />
|
|
541
|
+
<Skeleton className="h-3 w-2/3" />
|
|
542
|
+
</div>
|
|
543
|
+
))}
|
|
544
|
+
</div>
|
|
545
|
+
);
|
|
546
|
+
}
|
|
531
547
|
if (items.length === 0) {
|
|
532
548
|
return (
|
|
533
549
|
<div className="rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground">
|
|
@@ -555,9 +571,11 @@ export default function WorkspaceRoute() {
|
|
|
555
571
|
>
|
|
556
572
|
<div className="flex items-center justify-between">
|
|
557
573
|
<div className="text-sm text-muted-foreground">
|
|
558
|
-
{isLoading
|
|
559
|
-
|
|
560
|
-
|
|
574
|
+
{isLoading ? (
|
|
575
|
+
<Skeleton className="h-4 w-24" />
|
|
576
|
+
) : (
|
|
577
|
+
`${resources?.length || 0} resource${(resources?.length || 0) !== 1 ? "s" : ""}`
|
|
578
|
+
)}
|
|
561
579
|
</div>
|
|
562
580
|
<div className="flex gap-2">
|
|
563
581
|
<Button
|
|
@@ -23,7 +23,7 @@ When a user asks for something:
|
|
|
23
23
|
- Exception: if the downstream agent reports a missing model/provider credential, do not name exact env vars, Vault keys, tokens, or secrets. Say the target app needs an LLM connection and recommend connecting Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.
|
|
24
24
|
- If the user asks to create, build, make, scaffold, or generate an "agent" from Dispatch chat or by tagging @agent-native in Slack, email, or Telegram, first classify the ask. If it is a simple Dispatch-native behavior like a reminder, digest, monitor, routing rule, saved instruction, or recurring workflow, create or update the recurring job/resource/destination in Dispatch. If it is a robust unique product or teammate that needs its own UI, data model, actions, integrations, or domain workflow, treat it as a new workspace app and call start-workspace-app-creation.
|
|
25
25
|
- If a new-app prompt asks for access to Mail, Calendar, Analytics, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized fork/copy.
|
|
26
|
-
- If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app. If the request is too vague to classify, ask one concise follow-up. If the action returns mode "builder", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() in the React Router client entry. There is no separate workspace app registry to edit. If it returns mode "local-agent", tell the user it is ready for the local code agent and include the returned app path/prompt summary. If it returns mode "coming-soon" or "builder-unavailable", explain the missing Builder setup and ask them to connect/configure Builder.
|
|
26
|
+
- If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app. If the request is too vague to classify, ask one concise follow-up. If the action returns mode "builder", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode "local-agent", tell the user it is ready for the local code agent and include the returned app path/prompt summary. If it returns mode "coming-soon" or "builder-unavailable", explain the missing Builder setup and ask them to connect/configure Builder.
|
|
27
27
|
- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.
|
|
28
28
|
- Keep responses concise and operational — messaging platforms have character limits.
|
|
29
29
|
- Use markdown sparingly (bold and lists are fine, avoid complex formatting).
|