@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/routes/pages/workspace.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport { useActionMutation, useActionQuery } from \"@agent-native/core/client\";\nimport { toast } from \"sonner\";\nimport {\n IconBook,\n IconChevronDown,\n IconChevronRight,\n IconCode,\n IconFileText,\n IconPlus,\n IconRefresh,\n IconTrash,\n IconUser,\n IconX,\n} from \"@tabler/icons-react\";\nimport { DispatchShell } from \"@/components/dispatch-shell\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/components/ui/alert-dialog\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { Textarea } from \"@/components/ui/textarea\";\n\nexport function meta() {\n return [{ title: \"Workspace Resources — Dispatch\" }];\n}\n\nconst KIND_CONFIG = {\n skill: {\n label: \"Skill\",\n icon: IconCode,\n pathPrefix: \"skills/\",\n description: \"Agent skills — detailed guidance for patterns and workflows\",\n },\n instruction: {\n label: \"Instruction\",\n icon: IconBook,\n pathPrefix: \"\",\n description:\n \"Agent instructions — operational rules and behavioral guidance\",\n },\n agent: {\n label: \"Agent\",\n icon: IconUser,\n pathPrefix: \"agents/\",\n description:\n \"Reusable agent profiles — specialist agents shared across apps\",\n },\n knowledge: {\n label: \"Knowledge\",\n icon: IconFileText,\n pathPrefix: \"context/\",\n description:\n \"Knowledge packs — reusable GTM, product, and domain context for apps\",\n },\n} as const;\n\nfunction AddResourceDialog() {\n const [open, setOpen] = useState(false);\n const [kind, setKind] = useState<string>(\"skill\");\n const [name, setName] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [path, setPath] = useState(\"\");\n const [content, setContent] = useState(\"\");\n const [scope, setScope] = useState<string>(\"all\");\n\n const create = useActionMutation(\"create-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Resource created\");\n setOpen(false);\n setKind(\"skill\");\n setName(\"\");\n setDescription(\"\");\n setPath(\"\");\n setContent(\"\");\n setScope(\"all\");\n },\n onError: (err) => toast.error(String(err)),\n });\n\n const kindInfo = KIND_CONFIG[kind as keyof typeof KIND_CONFIG];\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger asChild>\n <Button>\n <IconPlus size={16} className=\"mr-1.5\" />\n Add resource\n </Button>\n </DialogTrigger>\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>Add workspace resource</DialogTitle>\n <DialogDescription>\n Create a skill, instruction, or agent profile that can be shared\n across workspace apps.\n </DialogDescription>\n </DialogHeader>\n <div className=\"space-y-4 py-2\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label>Kind</Label>\n <Select value={kind} onValueChange={setKind}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"skill\">Skill</SelectItem>\n <SelectItem value=\"instruction\">Instruction</SelectItem>\n <SelectItem value=\"agent\">Agent</SelectItem>\n <SelectItem value=\"knowledge\">Knowledge pack</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Scope</Label>\n <Select value={scope} onValueChange={setScope}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All apps</SelectItem>\n <SelectItem value=\"selected\">Selected apps only</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Name</Label>\n <Input\n placeholder={\n kind === \"skill\"\n ? \"Frontend Designer\"\n : kind === \"agent\"\n ? \"Research Specialist\"\n : kind === \"knowledge\"\n ? \"Core GTM Messaging\"\n : \"Code Style Guide\"\n }\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Path</Label>\n <Input\n placeholder={`${kindInfo?.pathPrefix || \"\"}${name.toLowerCase().replace(/\\s+/g, \"-\") || \"example\"}.md`}\n value={path}\n onChange={(e) => setPath(e.target.value)}\n className=\"font-mono text-sm\"\n />\n <p className=\"text-xs text-muted-foreground\">\n Resource path in target apps. Skills go in skills/, agents in\n agents/, knowledge packs in context/.\n </p>\n </div>\n <div className=\"space-y-2\">\n <Label>Description (optional)</Label>\n <Input\n placeholder=\"Short description of what this resource does\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Content</Label>\n <Textarea\n placeholder={\n kind === \"skill\"\n ? \"---\\nname: my-skill\\ndescription: What this skill teaches\\n---\\n\\n# My Skill\\n\\n...\"\n : kind === \"agent\"\n ? \"---\\nname: Research Specialist\\ndescription: Handles research tasks\\n---\\n\\n# Instructions\\n\\n...\"\n : kind === \"knowledge\"\n ? \"# Core GTM Messaging\\n\\n## Positioning\\n\\n## ICP\\n\\n## Proof points\\n\\n## Source\\n\\n\"\n : \"# Instructions\\n\\nBehavioral rules and guidance for agents across apps...\"\n }\n value={content}\n onChange={(e) => setContent(e.target.value)}\n rows={12}\n className=\"font-mono text-sm\"\n />\n </div>\n </div>\n <DialogFooter>\n <Button\n onClick={() =>\n create.mutate({\n kind: kind as \"skill\" | \"instruction\" | \"agent\" | \"knowledge\",\n name,\n description: description || undefined,\n path:\n path ||\n `${kindInfo?.pathPrefix || \"\"}${name.toLowerCase().replace(/\\s+/g, \"-\")}.md`,\n content,\n scope: scope as \"all\" | \"selected\",\n })\n }\n disabled={!name || !content || create.isPending}\n >\n {create.isPending ? \"Creating...\" : \"Create resource\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction GrantDialog({\n resourceId,\n resourceName,\n}: {\n resourceId: string;\n resourceName: string;\n}) {\n const [open, setOpen] = useState(false);\n const [appId, setAppId] = useState(\"\");\n const { data: catalog } = useActionQuery(\"list-integrations-catalog\", {});\n\n const grant = useActionMutation(\"create-workspace-resource-grant\", {\n onSuccess: () => {\n toast.success(`Granted to ${appId}`);\n setOpen(false);\n setAppId(\"\");\n },\n onError: (err) => toast.error(String(err)),\n });\n\n const apps = (catalog || []).map((a: any) => ({\n id: a.appId,\n name: a.appName,\n }));\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <IconPlus size={14} className=\"mr-1\" />\n Grant\n </Button>\n </DialogTrigger>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Grant \"{resourceName}\" to an app</DialogTitle>\n <DialogDescription>\n Choose which app should receive this resource.\n </DialogDescription>\n </DialogHeader>\n <div className=\"py-2\">\n <Select value={appId} onValueChange={setAppId}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select an app...\" />\n </SelectTrigger>\n <SelectContent>\n {apps.map((app: any) => (\n <SelectItem key={app.id} value={app.id}>\n {app.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <DialogFooter>\n <Button\n onClick={() => grant.mutate({ resourceId, appId })}\n disabled={!appId || grant.isPending}\n >\n {grant.isPending ? \"Granting...\" : \"Grant access\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction ResourceRow({ resource, grants }: { resource: any; grants: any[] }) {\n const [expanded, setExpanded] = useState(false);\n\n const deleteResource = useActionMutation(\"delete-workspace-resource\", {\n onSuccess: () => toast.success(\"Resource deleted\"),\n onError: (err) => toast.error(String(err)),\n });\n const revokeGrant = useActionMutation(\"revoke-workspace-resource-grant\", {\n onSuccess: () => toast.success(\"Grant revoked\"),\n onError: (err) => toast.error(String(err)),\n });\n const syncToApp = useActionMutation(\"sync-workspace-resources-to-app\", {\n onSuccess: (data: any) =>\n toast.success(`Synced ${data.synced} resource(s) to ${data.appId}`),\n onError: (err) => toast.error(String(err)),\n });\n\n const kindInfo = KIND_CONFIG[resource.kind as keyof typeof KIND_CONFIG];\n const KindIcon = kindInfo?.icon || IconCode;\n const activeGrants = grants.filter((g) => g.status === \"active\");\n\n return (\n <div className=\"rounded-xl border bg-card\">\n <button\n type=\"button\"\n className=\"flex w-full items-center gap-3 px-4 py-3 text-left cursor-pointer\"\n onClick={() => setExpanded(!expanded)}\n >\n {expanded ? (\n <IconChevronDown size={16} className=\"text-muted-foreground\" />\n ) : (\n <IconChevronRight size={16} className=\"text-muted-foreground\" />\n )}\n <KindIcon size={16} className=\"text-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {resource.name}\n </span>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {kindInfo?.label || resource.kind}\n </Badge>\n <Badge\n variant=\"outline\"\n className={\n resource.scope === \"all\"\n ? \"text-xs bg-green-500/10 text-green-700 dark:text-green-400\"\n : \"text-xs\"\n }\n >\n {resource.scope === \"all\" ? \"All apps\" : \"Selected\"}\n </Badge>\n </div>\n <div className=\"mt-0.5 font-mono text-xs text-muted-foreground\">\n {resource.path}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {resource.scope === \"selected\" && (\n <Badge variant=\"outline\" className=\"text-xs\">\n {activeGrants.length} grant\n {activeGrants.length !== 1 ? \"s\" : \"\"}\n </Badge>\n )}\n </div>\n </button>\n\n {expanded && (\n <div className=\"border-t px-4 py-3 space-y-3\">\n {resource.description && (\n <p className=\"text-sm text-muted-foreground\">\n {resource.description}\n </p>\n )}\n\n <div className=\"rounded-lg border bg-muted/30 p-3\">\n <pre className=\"whitespace-pre-wrap text-xs font-mono text-foreground max-h-64 overflow-y-auto\">\n {resource.content}\n </pre>\n </div>\n\n {resource.scope === \"selected\" && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs font-medium text-foreground\">\n Grants\n </span>\n <GrantDialog\n resourceId={resource.id}\n resourceName={resource.name}\n />\n </div>\n {activeGrants.length > 0 ? (\n <div className=\"space-y-1.5\">\n {activeGrants.map((grant: any) => (\n <div\n key={grant.id}\n className=\"flex items-center justify-between rounded-lg border px-3 py-2\"\n >\n <div>\n <span className=\"text-sm font-medium text-foreground\">\n {grant.appId}\n </span>\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {grant.syncedAt\n ? `synced ${new Date(grant.syncedAt).toLocaleString()}`\n : \"not synced\"}\n </span>\n </div>\n <div className=\"flex gap-1.5\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() =>\n syncToApp.mutate({ appId: grant.appId })\n }\n disabled={syncToApp.isPending}\n >\n <IconRefresh size={14} />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() =>\n revokeGrant.mutate({ grantId: grant.id })\n }\n disabled={revokeGrant.isPending}\n >\n <IconX size={14} />\n </Button>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"rounded-lg border border-dashed px-3 py-4 text-center text-xs text-muted-foreground\">\n No grants yet. Grant this resource to specific apps.\n </div>\n )}\n </div>\n )}\n\n <div className=\"flex justify-between border-t pt-3\">\n <div className=\"text-xs text-muted-foreground\">\n Created by {resource.createdBy} ·{\" \"}\n {new Date(resource.createdAt).toLocaleString()}\n </div>\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={deleteResource.isPending}\n >\n <IconTrash size={14} className=\"mr-1\" />\n Delete\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete this resource?</AlertDialogTitle>\n <AlertDialogDescription>\n Removing \"{resource.name}\" revokes all of its grants. Apps\n that depended on this resource will lose access on the next\n sync. This cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => deleteResource.mutate({ id: resource.id })}\n >\n Delete resource\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport default function WorkspaceRoute() {\n const { data: resources, isLoading } = useActionQuery(\n \"list-workspace-resources\",\n {},\n );\n const { data: grants } = useActionQuery(\"list-workspace-resource-grants\", {});\n\n const syncAll = useActionMutation(\"sync-workspace-resources-to-all\", {\n onSuccess: (data: any) => {\n const total = (data || []).reduce(\n (sum: number, r: any) => sum + r.synced,\n 0,\n );\n toast.success(\n `Synced resources to ${data?.length || 0} apps (${total} total pushes)`,\n );\n },\n onError: (err) => toast.error(String(err)),\n });\n\n const grantsByResource = (grants || []).reduce(\n (acc: Record<string, any[]>, g: any) => {\n if (!acc[g.resourceId]) acc[g.resourceId] = [];\n acc[g.resourceId].push(g);\n return acc;\n },\n {} as Record<string, any[]>,\n );\n\n const skills = (resources || []).filter((r: any) => r.kind === \"skill\");\n const instructions = (resources || []).filter(\n (r: any) => r.kind === \"instruction\",\n );\n const agents = (resources || []).filter((r: any) => r.kind === \"agent\");\n const knowledge = (resources || []).filter(\n (r: any) => r.kind === \"knowledge\",\n );\n\n function ResourceList({\n items,\n emptyText,\n }: {\n items: any[];\n emptyText: string;\n }) {\n if (items.length === 0) {\n return (\n <div className=\"rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground\">\n {emptyText}\n </div>\n );\n }\n return (\n <div className=\"space-y-3\">\n {items.map((resource: any) => (\n <ResourceRow\n key={resource.id}\n resource={resource}\n grants={grantsByResource[resource.id] || []}\n />\n ))}\n </div>\n );\n }\n\n return (\n <DispatchShell\n title=\"Workspace Resources\"\n description=\"Share skills, instructions, agent profiles, and knowledge packs across workspace apps. Scope to all apps or grant per-app.\"\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm text-muted-foreground\">\n {isLoading\n ? \"Loading...\"\n : `${resources?.length || 0} resource${(resources?.length || 0) !== 1 ? \"s\" : \"\"}`}\n </div>\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n onClick={() => syncAll.mutate({})}\n disabled={syncAll.isPending || (resources?.length || 0) === 0}\n >\n <IconRefresh\n size={16}\n className={syncAll.isPending ? \"mr-1.5 animate-spin\" : \"mr-1.5\"}\n />\n Sync all\n </Button>\n <AddResourceDialog />\n </div>\n </div>\n\n <Tabs defaultValue=\"skills\">\n <TabsList>\n <TabsTrigger value=\"skills\">\n Skills {skills.length > 0 && `(${skills.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"instructions\">\n Instructions {instructions.length > 0 && `(${instructions.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"agents\">\n Agents {agents.length > 0 && `(${agents.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"knowledge\">\n Knowledge {knowledge.length > 0 && `(${knowledge.length})`}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"skills\" className=\"mt-4\">\n <ResourceList\n items={skills}\n emptyText=\"No workspace skills yet. Add a skill to share agent guidance across apps.\"\n />\n </TabsContent>\n\n <TabsContent value=\"instructions\" className=\"mt-4\">\n <ResourceList\n items={instructions}\n emptyText=\"No workspace instructions yet. Add instructions to set behavioral rules across apps.\"\n />\n </TabsContent>\n\n <TabsContent value=\"agents\" className=\"mt-4\">\n <ResourceList\n items={agents}\n emptyText=\"No workspace agents yet. Add a reusable agent profile to share specialist agents across apps.\"\n />\n </TabsContent>\n\n <TabsContent value=\"knowledge\" className=\"mt-4\">\n <ResourceList\n items={knowledge}\n emptyText=\"No knowledge packs yet. Add GTM, product, or domain context that apps can reuse.\"\n />\n </TabsContent>\n </Tabs>\n </DispatchShell>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/routes/pages/workspace.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport { useActionMutation, useActionQuery } from \"@agent-native/core/client\";\nimport { toast } from \"sonner\";\nimport {\n IconBook,\n IconChevronDown,\n IconChevronRight,\n IconCode,\n IconFileText,\n IconPlus,\n IconRefresh,\n IconTrash,\n IconUser,\n IconX,\n} from \"@tabler/icons-react\";\nimport { DispatchShell } from \"@/components/dispatch-shell\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/components/ui/alert-dialog\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\n\nexport function meta() {\n return [{ title: \"Workspace Resources — Dispatch\" }];\n}\n\nconst KIND_CONFIG = {\n skill: {\n label: \"Skill\",\n icon: IconCode,\n pathPrefix: \"skills/\",\n description: \"Agent skills — detailed guidance for patterns and workflows\",\n },\n instruction: {\n label: \"Instruction\",\n icon: IconBook,\n pathPrefix: \"\",\n description:\n \"Agent instructions — operational rules and behavioral guidance\",\n },\n agent: {\n label: \"Agent\",\n icon: IconUser,\n pathPrefix: \"agents/\",\n description:\n \"Reusable agent profiles — specialist agents shared across apps\",\n },\n knowledge: {\n label: \"Knowledge\",\n icon: IconFileText,\n pathPrefix: \"context/\",\n description:\n \"Knowledge packs — reusable GTM, product, and domain context for apps\",\n },\n} as const;\n\nfunction AddResourceDialog() {\n const [open, setOpen] = useState(false);\n const [kind, setKind] = useState<string>(\"skill\");\n const [name, setName] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [path, setPath] = useState(\"\");\n const [content, setContent] = useState(\"\");\n const [scope, setScope] = useState<string>(\"all\");\n\n const create = useActionMutation(\"create-workspace-resource\", {\n onSuccess: () => {\n toast.success(\"Resource created\");\n setOpen(false);\n setKind(\"skill\");\n setName(\"\");\n setDescription(\"\");\n setPath(\"\");\n setContent(\"\");\n setScope(\"all\");\n },\n onError: (err) => toast.error(String(err)),\n });\n\n const kindInfo = KIND_CONFIG[kind as keyof typeof KIND_CONFIG];\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger asChild>\n <Button>\n <IconPlus size={16} className=\"mr-1.5\" />\n Add resource\n </Button>\n </DialogTrigger>\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>Add workspace resource</DialogTitle>\n <DialogDescription>\n Create a skill, instruction, or agent profile that can be shared\n across workspace apps.\n </DialogDescription>\n </DialogHeader>\n <div className=\"space-y-4 py-2\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <Label>Kind</Label>\n <Select value={kind} onValueChange={setKind}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"skill\">Skill</SelectItem>\n <SelectItem value=\"instruction\">Instruction</SelectItem>\n <SelectItem value=\"agent\">Agent</SelectItem>\n <SelectItem value=\"knowledge\">Knowledge pack</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label>Scope</Label>\n <Select value={scope} onValueChange={setScope}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All apps</SelectItem>\n <SelectItem value=\"selected\">Selected apps only</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n <div className=\"space-y-2\">\n <Label>Name</Label>\n <Input\n placeholder={\n kind === \"skill\"\n ? \"Frontend Designer\"\n : kind === \"agent\"\n ? \"Research Specialist\"\n : kind === \"knowledge\"\n ? \"Core GTM Messaging\"\n : \"Code Style Guide\"\n }\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Path</Label>\n <Input\n placeholder={`${kindInfo?.pathPrefix || \"\"}${name.toLowerCase().replace(/\\s+/g, \"-\") || \"example\"}.md`}\n value={path}\n onChange={(e) => setPath(e.target.value)}\n className=\"font-mono text-sm\"\n />\n <p className=\"text-xs text-muted-foreground\">\n Resource path in target apps. Skills go in skills/, agents in\n agents/, knowledge packs in context/.\n </p>\n </div>\n <div className=\"space-y-2\">\n <Label>Description (optional)</Label>\n <Input\n placeholder=\"Short description of what this resource does\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <Label>Content</Label>\n <Textarea\n placeholder={\n kind === \"skill\"\n ? \"---\\nname: my-skill\\ndescription: What this skill teaches\\n---\\n\\n# My Skill\\n\\n...\"\n : kind === \"agent\"\n ? \"---\\nname: Research Specialist\\ndescription: Handles research tasks\\n---\\n\\n# Instructions\\n\\n...\"\n : kind === \"knowledge\"\n ? \"# Core GTM Messaging\\n\\n## Positioning\\n\\n## ICP\\n\\n## Proof points\\n\\n## Source\\n\\n\"\n : \"# Instructions\\n\\nBehavioral rules and guidance for agents across apps...\"\n }\n value={content}\n onChange={(e) => setContent(e.target.value)}\n rows={12}\n className=\"font-mono text-sm\"\n />\n </div>\n </div>\n <DialogFooter>\n <Button\n onClick={() =>\n create.mutate({\n kind: kind as \"skill\" | \"instruction\" | \"agent\" | \"knowledge\",\n name,\n description: description || undefined,\n path:\n path ||\n `${kindInfo?.pathPrefix || \"\"}${name.toLowerCase().replace(/\\s+/g, \"-\")}.md`,\n content,\n scope: scope as \"all\" | \"selected\",\n })\n }\n disabled={!name || !content || create.isPending}\n >\n {create.isPending ? \"Creating...\" : \"Create resource\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction GrantDialog({\n resourceId,\n resourceName,\n}: {\n resourceId: string;\n resourceName: string;\n}) {\n const [open, setOpen] = useState(false);\n const [appId, setAppId] = useState(\"\");\n const { data: catalog } = useActionQuery(\"list-integrations-catalog\", {});\n\n const grant = useActionMutation(\"create-workspace-resource-grant\", {\n onSuccess: () => {\n toast.success(`Granted to ${appId}`);\n setOpen(false);\n setAppId(\"\");\n },\n onError: (err) => toast.error(String(err)),\n });\n\n const apps = (catalog || []).map((a: any) => ({\n id: a.appId,\n name: a.appName,\n }));\n\n return (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n <IconPlus size={14} className=\"mr-1\" />\n Grant\n </Button>\n </DialogTrigger>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Grant \"{resourceName}\" to an app</DialogTitle>\n <DialogDescription>\n Choose which app should receive this resource.\n </DialogDescription>\n </DialogHeader>\n <div className=\"py-2\">\n <Select value={appId} onValueChange={setAppId}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select an app...\" />\n </SelectTrigger>\n <SelectContent>\n {apps.map((app: any) => (\n <SelectItem key={app.id} value={app.id}>\n {app.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <DialogFooter>\n <Button\n onClick={() => grant.mutate({ resourceId, appId })}\n disabled={!appId || grant.isPending}\n >\n {grant.isPending ? \"Granting...\" : \"Grant access\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction ResourceRow({ resource, grants }: { resource: any; grants: any[] }) {\n const [expanded, setExpanded] = useState(false);\n\n const deleteResource = useActionMutation(\"delete-workspace-resource\", {\n onSuccess: () => toast.success(\"Resource deleted\"),\n onError: (err) => toast.error(String(err)),\n });\n const revokeGrant = useActionMutation(\"revoke-workspace-resource-grant\", {\n onSuccess: () => toast.success(\"Grant revoked\"),\n onError: (err) => toast.error(String(err)),\n });\n const syncToApp = useActionMutation(\"sync-workspace-resources-to-app\", {\n onSuccess: (data: any) =>\n toast.success(`Synced ${data.synced} resource(s) to ${data.appId}`),\n onError: (err) => toast.error(String(err)),\n });\n\n const kindInfo = KIND_CONFIG[resource.kind as keyof typeof KIND_CONFIG];\n const KindIcon = kindInfo?.icon || IconCode;\n const activeGrants = grants.filter((g) => g.status === \"active\");\n\n return (\n <div className=\"rounded-xl border bg-card\">\n <button\n type=\"button\"\n className=\"flex w-full items-center gap-3 px-4 py-3 text-left cursor-pointer\"\n onClick={() => setExpanded(!expanded)}\n >\n {expanded ? (\n <IconChevronDown size={16} className=\"text-muted-foreground\" />\n ) : (\n <IconChevronRight size={16} className=\"text-muted-foreground\" />\n )}\n <KindIcon size={16} className=\"text-muted-foreground\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {resource.name}\n </span>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {kindInfo?.label || resource.kind}\n </Badge>\n <Badge\n variant=\"outline\"\n className={\n resource.scope === \"all\"\n ? \"text-xs bg-green-500/10 text-green-700 dark:text-green-400\"\n : \"text-xs\"\n }\n >\n {resource.scope === \"all\" ? \"All apps\" : \"Selected\"}\n </Badge>\n </div>\n <div className=\"mt-0.5 font-mono text-xs text-muted-foreground\">\n {resource.path}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {resource.scope === \"selected\" && (\n <Badge variant=\"outline\" className=\"text-xs\">\n {activeGrants.length} grant\n {activeGrants.length !== 1 ? \"s\" : \"\"}\n </Badge>\n )}\n </div>\n </button>\n\n {expanded && (\n <div className=\"border-t px-4 py-3 space-y-3\">\n {resource.description && (\n <p className=\"text-sm text-muted-foreground\">\n {resource.description}\n </p>\n )}\n\n <div className=\"rounded-lg border bg-muted/30 p-3\">\n <pre className=\"whitespace-pre-wrap text-xs font-mono text-foreground max-h-64 overflow-y-auto\">\n {resource.content}\n </pre>\n </div>\n\n {resource.scope === \"selected\" && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs font-medium text-foreground\">\n Grants\n </span>\n <GrantDialog\n resourceId={resource.id}\n resourceName={resource.name}\n />\n </div>\n {activeGrants.length > 0 ? (\n <div className=\"space-y-1.5\">\n {activeGrants.map((grant: any) => (\n <div\n key={grant.id}\n className=\"flex items-center justify-between rounded-lg border px-3 py-2\"\n >\n <div>\n <span className=\"text-sm font-medium text-foreground\">\n {grant.appId}\n </span>\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {grant.syncedAt\n ? `synced ${new Date(grant.syncedAt).toLocaleString()}`\n : \"not synced\"}\n </span>\n </div>\n <div className=\"flex gap-1.5\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() =>\n syncToApp.mutate({ appId: grant.appId })\n }\n disabled={syncToApp.isPending}\n >\n <IconRefresh size={14} />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() =>\n revokeGrant.mutate({ grantId: grant.id })\n }\n disabled={revokeGrant.isPending}\n >\n <IconX size={14} />\n </Button>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"rounded-lg border border-dashed px-3 py-4 text-center text-xs text-muted-foreground\">\n No grants yet. Grant this resource to specific apps.\n </div>\n )}\n </div>\n )}\n\n <div className=\"flex justify-between border-t pt-3\">\n <div className=\"text-xs text-muted-foreground\">\n Created by {resource.createdBy} ·{\" \"}\n {new Date(resource.createdAt).toLocaleString()}\n </div>\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n disabled={deleteResource.isPending}\n >\n <IconTrash size={14} className=\"mr-1\" />\n Delete\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete this resource?</AlertDialogTitle>\n <AlertDialogDescription>\n Removing \"{resource.name}\" revokes all of its grants. Apps\n that depended on this resource will lose access on the next\n sync. This cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => deleteResource.mutate({ id: resource.id })}\n >\n Delete resource\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport default function WorkspaceRoute() {\n const { data: resources, isLoading } = useActionQuery(\n \"list-workspace-resources\",\n {},\n );\n const { data: grants } = useActionQuery(\"list-workspace-resource-grants\", {});\n\n const syncAll = useActionMutation(\"sync-workspace-resources-to-all\", {\n onSuccess: (data: any) => {\n const total = (data || []).reduce(\n (sum: number, r: any) => sum + r.synced,\n 0,\n );\n toast.success(\n `Synced resources to ${data?.length || 0} apps (${total} total pushes)`,\n );\n },\n onError: (err) => toast.error(String(err)),\n });\n\n const grantsByResource = (grants || []).reduce(\n (acc: Record<string, any[]>, g: any) => {\n if (!acc[g.resourceId]) acc[g.resourceId] = [];\n acc[g.resourceId].push(g);\n return acc;\n },\n {} as Record<string, any[]>,\n );\n\n const skills = (resources || []).filter((r: any) => r.kind === \"skill\");\n const instructions = (resources || []).filter(\n (r: any) => r.kind === \"instruction\",\n );\n const agents = (resources || []).filter((r: any) => r.kind === \"agent\");\n const knowledge = (resources || []).filter(\n (r: any) => r.kind === \"knowledge\",\n );\n\n function ResourceList({\n items,\n emptyText,\n }: {\n items: any[];\n emptyText: string;\n }) {\n if (isLoading && (resources ?? []).length === 0) {\n return (\n <div className=\"space-y-3\">\n {Array.from({ length: 3 }).map((_, index) => (\n <div\n key={index}\n className=\"rounded-2xl border bg-card px-5 py-4 space-y-2\"\n >\n <Skeleton className=\"h-4 w-1/3\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n ))}\n </div>\n );\n }\n if (items.length === 0) {\n return (\n <div className=\"rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground\">\n {emptyText}\n </div>\n );\n }\n return (\n <div className=\"space-y-3\">\n {items.map((resource: any) => (\n <ResourceRow\n key={resource.id}\n resource={resource}\n grants={grantsByResource[resource.id] || []}\n />\n ))}\n </div>\n );\n }\n\n return (\n <DispatchShell\n title=\"Workspace Resources\"\n description=\"Share skills, instructions, agent profiles, and knowledge packs across workspace apps. Scope to all apps or grant per-app.\"\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm text-muted-foreground\">\n {isLoading ? (\n <Skeleton className=\"h-4 w-24\" />\n ) : (\n `${resources?.length || 0} resource${(resources?.length || 0) !== 1 ? \"s\" : \"\"}`\n )}\n </div>\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n onClick={() => syncAll.mutate({})}\n disabled={syncAll.isPending || (resources?.length || 0) === 0}\n >\n <IconRefresh\n size={16}\n className={syncAll.isPending ? \"mr-1.5 animate-spin\" : \"mr-1.5\"}\n />\n Sync all\n </Button>\n <AddResourceDialog />\n </div>\n </div>\n\n <Tabs defaultValue=\"skills\">\n <TabsList>\n <TabsTrigger value=\"skills\">\n Skills {skills.length > 0 && `(${skills.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"instructions\">\n Instructions {instructions.length > 0 && `(${instructions.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"agents\">\n Agents {agents.length > 0 && `(${agents.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"knowledge\">\n Knowledge {knowledge.length > 0 && `(${knowledge.length})`}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"skills\" className=\"mt-4\">\n <ResourceList\n items={skills}\n emptyText=\"No workspace skills yet. Add a skill to share agent guidance across apps.\"\n />\n </TabsContent>\n\n <TabsContent value=\"instructions\" className=\"mt-4\">\n <ResourceList\n items={instructions}\n emptyText=\"No workspace instructions yet. Add instructions to set behavioral rules across apps.\"\n />\n </TabsContent>\n\n <TabsContent value=\"agents\" className=\"mt-4\">\n <ResourceList\n items={agents}\n emptyText=\"No workspace agents yet. Add a reusable agent profile to share specialist agents across apps.\"\n />\n </TabsContent>\n\n <TabsContent value=\"knowledge\" className=\"mt-4\">\n <ResourceList\n items={knowledge}\n emptyText=\"No knowledge packs yet. Add GTM, product, or domain context that apps can reuse.\"\n />\n </TabsContent>\n </Tabs>\n </DispatchShell>\n );\n}\n"]}
|
|
@@ -19,7 +19,7 @@ When a user asks for something:
|
|
|
19
19
|
- 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.
|
|
20
20
|
- 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.
|
|
21
21
|
- 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.
|
|
22
|
-
- 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.
|
|
22
|
+
- 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.
|
|
23
23
|
- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.
|
|
24
24
|
- Keep responses concise and operational — messaging platforms have character limits.
|
|
25
25
|
- Use markdown sparingly (bold and lists are fine, avoid complex formatting).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;4FAqBiD,CAAC;AAE7F;;;;GAIG;AACH,MAAM,0BAA0B,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE;IACzD,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC;IACjD,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,OAAO,cAAc,KAAK,UAAU;YACpC,CAAC,CAAC,cAAc,CAAC,kCAAkC,CAAC;YACpD,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,eAAe;QACxB,YAAY,EAAE,oBAAoB;QAClC,aAAa,EAAE,qBAAqB;QACpC,YAAY;QACZ,wDAAwD;QACxD,yEAAyE;QACzE,+DAA+D;QAC/D,6EAA6E;KAC9E,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,eAAe,0BAA0B,CAAC","sourcesContent":["import { createIntegrationsPlugin } from \"@agent-native/core/server\";\nimport {\n beforeDispatchProcess,\n resolveDispatchOwner,\n} from \"../lib/dispatch-integrations.js\";\nimport { getDispatchConfig } from \"../index.js\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nconst DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).\n\nDefault posture:\n- Treat Slack, Telegram, and email as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A (call-agent) when another app owns the job. Apps you can delegate to include slides (decks/presentations), analytics (data/dashboards), content (docs/articles), videos (Remotion compositions), forms (form builder), clips (screen recordings), design (visual designs), and images (brand image libraries and generated raster imagery).\n- Use list-connected-agents to see what agents are available before assuming a request must be handled locally.\n- When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.\n- Treat first-party apps such as Mail, Calendar, Analytics, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.\n\nWhen a user asks for something:\n- If it belongs to analytics, content, slides, videos, images, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.\n- After call-agent returns an answer, RELAY IT DIRECTLY to the user with at most a one-line preface — do not rephrase, summarize, or add commentary. The downstream agent already crafted the answer; your job is delivery, not editing. This minimizes round-trips and keeps the user-visible reply fast.\n- 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.\n- 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.\n- 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.\n- 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.\n- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.\n- Keep responses concise and operational — messaging platforms have character limits.\n- Use markdown sparingly (bold and lists are fine, avoid complex formatting).\n- If a task requires many steps, summarize what you did rather than streaming every detail.`;\n\n/**\n * Defer plugin construction until the Nitro plugin actually fires so the\n * config-aware system prompt resolves AFTER `setupDispatch(config)` has\n * stamped the active config (plugin module load order is not guaranteed).\n */\nconst dispatchIntegrationsPlugin = async (nitroApp: any) => {\n const { integrations = {} } = getDispatchConfig();\n const promptOverride = integrations.systemPrompt;\n const systemPrompt =\n typeof promptOverride === \"string\"\n ? promptOverride\n : typeof promptOverride === \"function\"\n ? promptOverride(DISPATCH_INTEGRATION_SYSTEM_PROMPT)\n : DISPATCH_INTEGRATION_SYSTEM_PROMPT;\n\n const plugin = createIntegrationsPlugin({\n appId: \"dispatch\",\n actions: dispatchActions,\n resolveOwner: resolveDispatchOwner,\n beforeProcess: beforeDispatchProcess,\n systemPrompt,\n // Inherit the framework default (claude-sonnet-4-6 from\n // packages/core/src/integrations/plugin.ts). Haiku was tried for latency\n // but hallucinated URLs/IDs after delegated call-agent results\n // (e.g. inventing `https://slides.workspace.com/deck/builder-io-deck-2024`).\n });\n\n return plugin(nitroApp);\n};\n\nexport default dispatchIntegrationsPlugin;\n"]}
|
|
1
|
+
{"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;4FAqBiD,CAAC;AAE7F;;;;GAIG;AACH,MAAM,0BAA0B,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE;IACzD,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC;IACjD,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,OAAO,cAAc,KAAK,UAAU;YACpC,CAAC,CAAC,cAAc,CAAC,kCAAkC,CAAC;YACpD,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,eAAe;QACxB,YAAY,EAAE,oBAAoB;QAClC,aAAa,EAAE,qBAAqB;QACpC,YAAY;QACZ,wDAAwD;QACxD,yEAAyE;QACzE,+DAA+D;QAC/D,6EAA6E;KAC9E,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,eAAe,0BAA0B,CAAC","sourcesContent":["import { createIntegrationsPlugin } from \"@agent-native/core/server\";\nimport {\n beforeDispatchProcess,\n resolveDispatchOwner,\n} from \"../lib/dispatch-integrations.js\";\nimport { getDispatchConfig } from \"../index.js\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nconst DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).\n\nDefault posture:\n- Treat Slack, Telegram, and email as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A (call-agent) when another app owns the job. Apps you can delegate to include slides (decks/presentations), analytics (data/dashboards), content (docs/articles), videos (Remotion compositions), forms (form builder), clips (screen recordings), design (visual designs), and images (brand image libraries and generated raster imagery).\n- Use list-connected-agents to see what agents are available before assuming a request must be handled locally.\n- When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.\n- Treat first-party apps such as Mail, Calendar, Analytics, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.\n\nWhen a user asks for something:\n- If it belongs to analytics, content, slides, videos, images, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.\n- After call-agent returns an answer, RELAY IT DIRECTLY to the user with at most a one-line preface — do not rephrase, summarize, or add commentary. The downstream agent already crafted the answer; your job is delivery, not editing. This minimizes round-trips and keeps the user-visible reply fast.\n- 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.\n- 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.\n- 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.\n- 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.\n- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.\n- Keep responses concise and operational — messaging platforms have character limits.\n- Use markdown sparingly (bold and lists are fine, avoid complex formatting).\n- If a task requires many steps, summarize what you did rather than streaming every detail.`;\n\n/**\n * Defer plugin construction until the Nitro plugin actually fires so the\n * config-aware system prompt resolves AFTER `setupDispatch(config)` has\n * stamped the active config (plugin module load order is not guaranteed).\n */\nconst dispatchIntegrationsPlugin = async (nitroApp: any) => {\n const { integrations = {} } = getDispatchConfig();\n const promptOverride = integrations.systemPrompt;\n const systemPrompt =\n typeof promptOverride === \"string\"\n ? promptOverride\n : typeof promptOverride === \"function\"\n ? promptOverride(DISPATCH_INTEGRATION_SYSTEM_PROMPT)\n : DISPATCH_INTEGRATION_SYSTEM_PROMPT;\n\n const plugin = createIntegrationsPlugin({\n appId: \"dispatch\",\n actions: dispatchActions,\n resolveOwner: resolveDispatchOwner,\n beforeProcess: beforeDispatchProcess,\n systemPrompt,\n // Inherit the framework default (claude-sonnet-4-6 from\n // packages/core/src/integrations/plugin.ts). Haiku was tried for latency\n // but hallucinated URLs/IDs after delegated call-agent results\n // (e.g. inventing `https://slides.workspace.com/deck/builder-io-deck-2024`).\n });\n\n return plugin(nitroApp);\n};\n\nexport default dispatchIntegrationsPlugin;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/dispatch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"typescript": "^6.0.3",
|
|
97
97
|
"vite": "8.0.3",
|
|
98
98
|
"vitest": "^4.1.5",
|
|
99
|
-
"@agent-native/core": "0.
|
|
99
|
+
"@agent-native/core": "0.14.2"
|
|
100
100
|
},
|
|
101
101
|
"scripts": {
|
|
102
102
|
"build": "tsc && tsc-alias --resolve-full-paths",
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
PopoverTrigger,
|
|
14
14
|
} from "@/components/ui/popover";
|
|
15
15
|
import { Button } from "@/components/ui/button";
|
|
16
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
16
17
|
|
|
17
18
|
interface VaultSecret {
|
|
18
19
|
id: string;
|
|
@@ -180,7 +181,20 @@ function AppKeysPanel({ appId, appName }: { appId: string; appName: string }) {
|
|
|
180
181
|
|
|
181
182
|
<div className="max-h-[320px] space-y-1.5 overflow-y-auto rounded-md border border-border bg-card p-1.5">
|
|
182
183
|
{isLoading ? (
|
|
183
|
-
<
|
|
184
|
+
<div className="space-y-1.5 p-1.5">
|
|
185
|
+
{Array.from({ length: 3 }).map((_, index) => (
|
|
186
|
+
<div
|
|
187
|
+
key={index}
|
|
188
|
+
className="flex items-start gap-3 rounded-md px-2.5 py-2"
|
|
189
|
+
>
|
|
190
|
+
<Skeleton className="mt-0.5 h-4 w-4 shrink-0 rounded" />
|
|
191
|
+
<div className="flex-1 space-y-1.5">
|
|
192
|
+
<Skeleton className="h-3 w-1/2" />
|
|
193
|
+
<Skeleton className="h-3 w-3/4" />
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
))}
|
|
197
|
+
</div>
|
|
184
198
|
) : typedSecrets.length === 0 ? (
|
|
185
199
|
<p className="rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground">
|
|
186
200
|
No vault keys yet. Add one from the Vault page.
|
|
@@ -124,7 +124,7 @@ function buildAppCreationPrompt(input: {
|
|
|
124
124
|
`- Update the app manifest/package/deploy metadata needed by the existing workspace deployment model.`,
|
|
125
125
|
`- Ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() so /${input.appId} hydrates correctly.`,
|
|
126
126
|
`- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment.`,
|
|
127
|
-
`When it is ready, start or update the workspace dev server and navigate the user to /${input.appId}.`,
|
|
127
|
+
`When it is ready, start or update the workspace dev server and navigate the user to the absolute path /${input.appId} on the workspace origin. Do not prefix with /dispatch/, /apps/, /workspace/, or any other Dispatch tab — the new app is mounted at the workspace root, not under Dispatch. If you have a navigate tool available, pass /${input.appId} verbatim; if you only have a window.location-style escape hatch, set it to /${input.appId}.`,
|
|
128
128
|
].join("\n");
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -170,9 +170,9 @@ const OPERATIONS_NAV_ITEMS = [
|
|
|
170
170
|
const EMPTY_NAV_ITEMS: readonly DispatchNavItem[] = [];
|
|
171
171
|
|
|
172
172
|
const SIDEBAR_SUGGESTIONS = [
|
|
173
|
-
"
|
|
174
|
-
"
|
|
175
|
-
"
|
|
173
|
+
"Build a workspace app for X",
|
|
174
|
+
"Route Slack mentions to my analytics app",
|
|
175
|
+
"Grant my OpenAI key to this app",
|
|
176
176
|
];
|
|
177
177
|
|
|
178
178
|
const CHROMELESS_PATHS = ["/approval"];
|
package/src/routes/index.ts
CHANGED
|
@@ -50,4 +50,9 @@ export const dispatchRoutes: RouteConfig = [
|
|
|
50
50
|
route("team", "./pages/team.js"),
|
|
51
51
|
route("extensions", "./pages/extensions._index.js"),
|
|
52
52
|
route("extensions/:id", "./pages/extensions.$id.js"),
|
|
53
|
+
// Catch-all for /:appId — bounces /dispatch/<appId> to /<appId> when the
|
|
54
|
+
// segment names a workspace app sibling (e.g. Builder.io routing a "go to
|
|
55
|
+
// /todo" call through Dispatch's mount). Declared last so React Router 7's
|
|
56
|
+
// specificity ranking still matches explicit static routes above first.
|
|
57
|
+
route(":appId", "./pages/$appId.js"),
|
|
53
58
|
];
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { useEffect, useMemo } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Link,
|
|
4
|
+
Navigate,
|
|
5
|
+
redirect,
|
|
6
|
+
useParams,
|
|
7
|
+
type LoaderFunctionArgs,
|
|
8
|
+
} from "react-router";
|
|
9
|
+
import { useActionQuery, appPath } from "@agent-native/core/client";
|
|
10
|
+
import { loadWorkspaceAppsManifest } from "@agent-native/core/server/agent-discovery";
|
|
11
|
+
import {
|
|
12
|
+
IconArrowLeft,
|
|
13
|
+
IconArrowUpRight,
|
|
14
|
+
IconClockHour4,
|
|
15
|
+
} from "@tabler/icons-react";
|
|
16
|
+
import { DispatchShell } from "@/components/dispatch-shell";
|
|
17
|
+
import { Spinner } from "@/components/ui/spinner";
|
|
18
|
+
import { Badge } from "@/components/ui/badge";
|
|
19
|
+
import { Button } from "@/components/ui/button";
|
|
20
|
+
import {
|
|
21
|
+
workspaceAppHref,
|
|
22
|
+
type WorkspaceAppSummary,
|
|
23
|
+
} from "@/lib/workspace-apps";
|
|
24
|
+
|
|
25
|
+
export function meta() {
|
|
26
|
+
return [{ title: "Workspace app - Dispatch" }];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Catch-all for `/dispatch/<segment>` paths that don't match an explicit
|
|
31
|
+
* Dispatch route. When `<segment>` is the id of a workspace app sibling
|
|
32
|
+
* (e.g. `/dispatch/todo` after Builder.io routes a "navigate to /todo"
|
|
33
|
+
* call through Dispatch's mount point), bounce to the absolute `/<appId>`
|
|
34
|
+
* so the user lands on the actual app instead of a 404 inside Dispatch.
|
|
35
|
+
*
|
|
36
|
+
* Server-side redirect: we resolve the workspace app manifest via the
|
|
37
|
+
* shared `loadWorkspaceAppsManifest()` helper, which checks the
|
|
38
|
+
* `AGENT_NATIVE_WORKSPACE_APPS_JSON` env var, then the
|
|
39
|
+
* `.agent-native/workspace-apps.json` file written by `workspace-deploy.ts`,
|
|
40
|
+
* then a live filesystem scan of `apps/` for local dev. We then throw
|
|
41
|
+
* `redirect("/<appId>")`. React Router 7 does not prepend the basename to
|
|
42
|
+
* absolute paths returned from a loader, so the redirect escapes Dispatch's
|
|
43
|
+
* `/dispatch` mount cleanly.
|
|
44
|
+
*
|
|
45
|
+
* Why a catch-all instead of fixing the agent prompt: Builder.io currently
|
|
46
|
+
* resolves "navigate to /todo" relative to Dispatch's mount, sending the
|
|
47
|
+
* user to /dispatch/todo. The same wrong path then gets captured as the
|
|
48
|
+
* OAuth callbackURL, so Google sign-in completes back at /dispatch/todo
|
|
49
|
+
* and looks broken. This route fixes both the post-creation navigation
|
|
50
|
+
* and the OAuth round-trip from a single place.
|
|
51
|
+
*
|
|
52
|
+
* `appId === "dispatch"` short-circuit: when the segment matches Dispatch
|
|
53
|
+
* itself (e.g. `/dispatch/dispatch`), we go straight to the overview rather
|
|
54
|
+
* than chaining through `/dispatch` (which polled `useActionQuery` re-fired
|
|
55
|
+
* `window.location.assign` against and looped forever in production).
|
|
56
|
+
*/
|
|
57
|
+
function dispatchSelfRedirect(appId: string | undefined): string | null {
|
|
58
|
+
if (appId === "dispatch") return appPath("/overview");
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function loader({ params }: LoaderFunctionArgs) {
|
|
63
|
+
const appId = params.appId;
|
|
64
|
+
if (!appId) return null;
|
|
65
|
+
const selfTarget = dispatchSelfRedirect(appId);
|
|
66
|
+
if (selfTarget) throw redirect(selfTarget);
|
|
67
|
+
const apps = loadWorkspaceAppsManifest();
|
|
68
|
+
if (!apps) return null;
|
|
69
|
+
const app = apps.find((entry) => entry?.id === appId);
|
|
70
|
+
const target =
|
|
71
|
+
app?.path && app.path.startsWith("/") ? app.path : app ? `/${appId}` : null;
|
|
72
|
+
if (target) throw redirect(target);
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function clientLoader({ params }: LoaderFunctionArgs) {
|
|
77
|
+
const selfTarget = dispatchSelfRedirect(params.appId);
|
|
78
|
+
if (selfTarget) throw redirect(selfTarget);
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default function WorkspaceAppCatchAllRoute() {
|
|
83
|
+
const { appId } = useParams();
|
|
84
|
+
const { data: apps = [], isLoading } = useActionQuery(
|
|
85
|
+
"list-workspace-apps",
|
|
86
|
+
{ includeAgentCards: false },
|
|
87
|
+
{ refetchInterval: 2_000 },
|
|
88
|
+
);
|
|
89
|
+
const app = useMemo(
|
|
90
|
+
() =>
|
|
91
|
+
(apps as WorkspaceAppSummary[]).find((item) => item.id === appId) ?? null,
|
|
92
|
+
[appId, apps],
|
|
93
|
+
);
|
|
94
|
+
const href = app ? workspaceAppHref(app) : null;
|
|
95
|
+
const isSelfReference = appId === "dispatch";
|
|
96
|
+
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (isSelfReference) return;
|
|
99
|
+
if (!app || app.status === "pending" || !href) return;
|
|
100
|
+
window.location.assign(href);
|
|
101
|
+
}, [app, href, isSelfReference]);
|
|
102
|
+
|
|
103
|
+
if (isSelfReference) {
|
|
104
|
+
return <Navigate to={appPath("/overview")} replace />;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if ((isLoading && !app) || (app && app.status !== "pending" && href)) {
|
|
108
|
+
return (
|
|
109
|
+
<div className="flex h-screen w-full items-center justify-center">
|
|
110
|
+
<Spinner className="size-8" />
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<DispatchShell
|
|
117
|
+
title={app?.name || "Page not found"}
|
|
118
|
+
description="This route is not in the workspace app list yet."
|
|
119
|
+
>
|
|
120
|
+
<div className="max-w-2xl rounded-lg border bg-card p-5">
|
|
121
|
+
<Button asChild size="sm" variant="ghost" className="-ml-2 mb-4">
|
|
122
|
+
<Link to={appPath("/overview")}>
|
|
123
|
+
<IconArrowLeft size={15} className="mr-1.5" />
|
|
124
|
+
Overview
|
|
125
|
+
</Link>
|
|
126
|
+
</Button>
|
|
127
|
+
|
|
128
|
+
{app?.status === "pending" ? (
|
|
129
|
+
<div className="space-y-4">
|
|
130
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
131
|
+
<h2 className="text-base font-semibold text-foreground">
|
|
132
|
+
{app.name}
|
|
133
|
+
</h2>
|
|
134
|
+
<Badge
|
|
135
|
+
variant="outline"
|
|
136
|
+
className="gap-1 border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300"
|
|
137
|
+
>
|
|
138
|
+
<IconClockHour4 size={12} />
|
|
139
|
+
Building
|
|
140
|
+
</Badge>
|
|
141
|
+
</div>
|
|
142
|
+
<p className="text-sm text-muted-foreground">
|
|
143
|
+
This app is being created. It will be available at{" "}
|
|
144
|
+
<span className="font-mono text-foreground">{app.path}</span>{" "}
|
|
145
|
+
after its branch is merged and the workspace deploy finishes.
|
|
146
|
+
</p>
|
|
147
|
+
{app.branchName ? (
|
|
148
|
+
<p className="text-xs text-muted-foreground">
|
|
149
|
+
Branch: {app.branchName}
|
|
150
|
+
</p>
|
|
151
|
+
) : null}
|
|
152
|
+
{app.builderUrl ? (
|
|
153
|
+
<Button asChild>
|
|
154
|
+
<a href={app.builderUrl} target="_blank" rel="noreferrer">
|
|
155
|
+
Open Builder branch
|
|
156
|
+
<IconArrowUpRight size={15} className="ml-1.5" />
|
|
157
|
+
</a>
|
|
158
|
+
</Button>
|
|
159
|
+
) : null}
|
|
160
|
+
</div>
|
|
161
|
+
) : (
|
|
162
|
+
<div className="space-y-3">
|
|
163
|
+
<h2 className="text-base font-semibold text-foreground">
|
|
164
|
+
Page not found
|
|
165
|
+
</h2>
|
|
166
|
+
<p className="text-sm text-muted-foreground">
|
|
167
|
+
<span className="font-mono text-foreground">/{appId}</span> isn't
|
|
168
|
+
a Dispatch tab or a workspace app in this workspace.
|
|
169
|
+
</p>
|
|
170
|
+
<Button asChild>
|
|
171
|
+
<Link to={appPath("/apps")}>Browse apps</Link>
|
|
172
|
+
</Button>
|
|
173
|
+
</div>
|
|
174
|
+
)}
|
|
175
|
+
</div>
|
|
176
|
+
</DispatchShell>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { toast } from "sonner";
|
|
10
10
|
import { Button } from "@/components/ui/button";
|
|
11
11
|
import { Badge } from "@/components/ui/badge";
|
|
12
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
12
13
|
import {
|
|
13
14
|
IconCheck,
|
|
14
15
|
IconX,
|
|
@@ -98,9 +99,38 @@ export default function ApprovalPreviewRoute() {
|
|
|
98
99
|
|
|
99
100
|
if (isLoading) {
|
|
100
101
|
return (
|
|
101
|
-
<div className="flex min-h-screen items-
|
|
102
|
-
<div className="w-full max-w-md
|
|
103
|
-
<
|
|
102
|
+
<div className="flex min-h-screen items-start justify-center bg-background p-6">
|
|
103
|
+
<div className="w-full max-w-md space-y-4">
|
|
104
|
+
<div className="rounded-2xl border bg-card p-5">
|
|
105
|
+
<div className="flex items-start gap-3">
|
|
106
|
+
<Skeleton className="h-9 w-9 shrink-0 rounded-xl" />
|
|
107
|
+
<div className="min-w-0 flex-1 space-y-2">
|
|
108
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
109
|
+
<Skeleton className="h-4 w-40" />
|
|
110
|
+
<Skeleton className="h-5 w-20 rounded-full" />
|
|
111
|
+
</div>
|
|
112
|
+
<Skeleton className="h-3 w-32" />
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
<div className="mt-4 space-y-2 rounded-xl border bg-muted/30 px-4 py-3">
|
|
116
|
+
<div className="flex justify-between gap-4">
|
|
117
|
+
<Skeleton className="h-3 w-20" />
|
|
118
|
+
<Skeleton className="h-3 w-24" />
|
|
119
|
+
</div>
|
|
120
|
+
<div className="flex justify-between gap-4">
|
|
121
|
+
<Skeleton className="h-3 w-20" />
|
|
122
|
+
<Skeleton className="h-3 w-28" />
|
|
123
|
+
</div>
|
|
124
|
+
<div className="flex justify-between gap-4">
|
|
125
|
+
<Skeleton className="h-3 w-16" />
|
|
126
|
+
<Skeleton className="h-3 w-32" />
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
<div className="mt-4 flex gap-2">
|
|
130
|
+
<Skeleton className="h-8 flex-1 rounded-md" />
|
|
131
|
+
<Skeleton className="h-8 flex-1 rounded-md" />
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
104
134
|
</div>
|
|
105
135
|
</div>
|
|
106
136
|
);
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { DispatchShell } from "@/components/dispatch-shell";
|
|
10
10
|
import { Badge } from "@/components/ui/badge";
|
|
11
11
|
import { Button } from "@/components/ui/button";
|
|
12
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
12
13
|
import {
|
|
13
14
|
workspaceAppHref,
|
|
14
15
|
type WorkspaceAppSummary,
|
|
@@ -53,7 +54,11 @@ export default function WorkspaceAppRoute() {
|
|
|
53
54
|
</Button>
|
|
54
55
|
|
|
55
56
|
{isLoading && !app ? (
|
|
56
|
-
<
|
|
57
|
+
<div className="space-y-3">
|
|
58
|
+
<Skeleton className="h-5 w-48" />
|
|
59
|
+
<Skeleton className="h-4 w-full" />
|
|
60
|
+
<Skeleton className="h-4 w-2/3" />
|
|
61
|
+
</div>
|
|
57
62
|
) : !app ? (
|
|
58
63
|
<div className="space-y-3">
|
|
59
64
|
<h2 className="text-base font-semibold text-foreground">
|