agent-relay-server 0.101.0 → 0.101.2
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/docs/openapi.json +1 -1
- package/package.json +2 -2
- package/public/assets/{MessageBubble-BEjK1-bi.js → MessageBubble-05wP_Pp7.js} +2 -2
- package/public/assets/{MessageBubble-BEjK1-bi.js.map → MessageBubble-05wP_Pp7.js.map} +1 -1
- package/public/assets/{PlanGraphPanel-AqFEg7Yg.js → PlanGraphPanel-DqcWnJh2.js} +2 -2
- package/public/assets/{PlanGraphPanel-AqFEg7Yg.js.map → PlanGraphPanel-DqcWnJh2.js.map} +1 -1
- package/public/assets/{activity-D5EZw4bj.js → activity-CvlOK6RA.js} +2 -2
- package/public/assets/{activity-D5EZw4bj.js.map → activity-CvlOK6RA.js.map} +1 -1
- package/public/assets/{agent-profiles-CSISRm_L.js → agent-profiles-wKBBSTPf.js} +2 -2
- package/public/assets/{agent-profiles-CSISRm_L.js.map → agent-profiles-wKBBSTPf.js.map} +1 -1
- package/public/assets/{agents-szyYnkgD.js → agents-D8ou97l0.js} +2 -2
- package/public/assets/{agents-szyYnkgD.js.map → agents-D8ou97l0.js.map} +1 -1
- package/public/assets/{automation-DVSq4A1b.js → automation-CobkOV2I.js} +2 -2
- package/public/assets/{automation-DVSq4A1b.js.map → automation-CobkOV2I.js.map} +1 -1
- package/public/assets/{chat-patMKjsi.js → chat-_qMuKtFW.js} +2 -2
- package/public/assets/chat-_qMuKtFW.js.map +1 -0
- package/public/assets/{formatted-body-impl-Csr2DuEk.js → formatted-body-impl-BuWtx_vR.js} +2 -2
- package/public/assets/{formatted-body-impl-Csr2DuEk.js.map → formatted-body-impl-BuWtx_vR.js.map} +1 -1
- package/public/assets/{index-D3woTUwp.js → index-DOWwt3I7.js} +5 -5
- package/public/assets/{index-D3woTUwp.js.map → index-DOWwt3I7.js.map} +1 -1
- package/public/assets/index-bX1jet7G.css +2 -0
- package/public/assets/{insights-D2_Qry06.js → insights-KgUoMByj.js} +2 -2
- package/public/assets/{insights-D2_Qry06.js.map → insights-KgUoMByj.js.map} +1 -1
- package/public/assets/{maintenance-Dm56u8F9.js → maintenance-Cv_YMPiT.js} +2 -2
- package/public/assets/{maintenance-Dm56u8F9.js.map → maintenance-Cv_YMPiT.js.map} +1 -1
- package/public/assets/{managed-agents-DpX-cHsm.js → managed-agents-BbvZ4oxi.js} +2 -2
- package/public/assets/{managed-agents-DpX-cHsm.js.map → managed-agents-BbvZ4oxi.js.map} +1 -1
- package/public/assets/{markdown-preview-impl-Df6EWwbg.js → markdown-preview-impl-BObVveTR.js} +2 -2
- package/public/assets/{markdown-preview-impl-Df6EWwbg.js.map → markdown-preview-impl-BObVveTR.js.map} +1 -1
- package/public/assets/{memory-b2AgvV7H.js → memory-Dwf1cHOH.js} +2 -2
- package/public/assets/{memory-b2AgvV7H.js.map → memory-Dwf1cHOH.js.map} +1 -1
- package/public/assets/{messages-C5yDD_oq.js → messages-qazt4dRu.js} +2 -2
- package/public/assets/{messages-C5yDD_oq.js.map → messages-qazt4dRu.js.map} +1 -1
- package/public/assets/{orchestrators-D3LecmEw.js → orchestrators-DLkTocP_.js} +2 -2
- package/public/assets/{orchestrators-D3LecmEw.js.map → orchestrators-DLkTocP_.js.map} +1 -1
- package/public/assets/{overview-CnGkrBNe.js → overview-BJXNLoFX.js} +2 -2
- package/public/assets/{overview-CnGkrBNe.js.map → overview-BJXNLoFX.js.map} +1 -1
- package/public/assets/{pairs-DXUdZOqn.js → pairs-BPuYuK-j.js} +2 -2
- package/public/assets/{pairs-DXUdZOqn.js.map → pairs-BPuYuK-j.js.map} +1 -1
- package/public/assets/{registry-BeGP37ot.js → registry-ApGTbK4L.js} +2 -2
- package/public/assets/{registry-BeGP37ot.js.map → registry-ApGTbK4L.js.map} +1 -1
- package/public/assets/{security-BMh_y43L.js → security-BriPtiFR.js} +2 -2
- package/public/assets/{security-BMh_y43L.js.map → security-BriPtiFR.js.map} +1 -1
- package/public/assets/{select-Cvi5OHz0.js → select-BUzGDcc7.js} +2 -2
- package/public/assets/{select-Cvi5OHz0.js.map → select-BUzGDcc7.js.map} +1 -1
- package/public/assets/{settings-DKSEwIVG.js → settings-BILEdrKT.js} +2 -2
- package/public/assets/{settings-DKSEwIVG.js.map → settings-BILEdrKT.js.map} +1 -1
- package/public/assets/{tasks-BybIAX-y.js → tasks-DffSH-VO.js} +2 -2
- package/public/assets/{tasks-BybIAX-y.js.map → tasks-DffSH-VO.js.map} +1 -1
- package/public/assets/{teams-CMteOToR.js → teams-Ch3oFlaf.js} +2 -2
- package/public/assets/{teams-CMteOToR.js.map → teams-Ch3oFlaf.js.map} +1 -1
- package/public/assets/{terminal-viewer-impl-DanOi7lh.js → terminal-viewer-impl-FZncaUAS.js} +2 -2
- package/public/assets/{terminal-viewer-impl-DanOi7lh.js.map → terminal-viewer-impl-FZncaUAS.js.map} +1 -1
- package/public/assets/{user-avatar-DG629icI.js → user-avatar-CnpJGcXz.js} +2 -2
- package/public/assets/{user-avatar-DG629icI.js.map → user-avatar-CnpJGcXz.js.map} +1 -1
- package/public/assets/{work-queue-DqW80DIy.js → work-queue-C7i6TDbJ.js} +2 -2
- package/public/assets/{work-queue-DqW80DIy.js.map → work-queue-C7i6TDbJ.js.map} +1 -1
- package/public/index.html +2 -2
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/src/adapter.ts +5 -0
- package/src/quota-band-transition.ts +5 -2
- package/src/routes/_shared.ts +15 -0
- package/src/routes/routing-policy.ts +3 -2
- package/src/routing-policy-store.ts +8 -0
- package/src/spawn-targets.ts +13 -5
- package/public/assets/chat-patMKjsi.js.map +0 -1
- package/public/assets/index-B95vV-dd.css +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overview-CnGkrBNe.js","names":[],"sources":["../../dashboard/src/components/views/overview.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { useRelayStore, useNow } from '@/store'\nimport { useAttentionSummary, useOnlineCount, useBusyCount } from '@/hooks/use-selectors'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport { Separator } from '@/components/ui/separator'\nimport { StatusDot } from '@/components/shared/status-dot'\nimport { AgentTypeIcon } from '@/components/shared/agent-type-icon'\nimport {\n displayName, displayTarget, timeAgo, messagePreview, healthDiagnostics,\n toneToColor, visibleAgents, toTimestamp,\n} from '@/lib/display'\nimport { STATUS_SORT_ORDER } from '@/lib/constants'\nimport {\n Bot, Mail, Link, Inbox, AlertTriangle, Activity,\n Users, MessageSquare, ListChecks,\n} from 'lucide-react'\nimport type { ViewName } from '@/types'\n\nexport function OverviewView() {\n const stats = useRelayStore((s) => s.stats)\n const agents = useRelayStore((s) => s.agents)\n const messages = useRelayStore((s) => s.messages)\n const health = useRelayStore((s) => s.health)\n const now = useNow()\n const agentsById = useRelayStore((s) => s.agentsById)\n const switchView = useRelayStore((s) => s.switchView)\n const runHealthAction = useRelayStore((s) => s.runHealthAction)\n const managedPolicies = useRelayStore((s) => s.managedPolicies)\n\n const showOffline = useRelayStore((s) => s.showOffline)\n\n const onlineCount = useOnlineCount()\n const busyCount = useBusyCount()\n const attention = useAttentionSummary()\n\n const filteredAgents = useMemo(() => {\n let list = visibleAgents(agents, false, managedPolicies)\n if (!showOffline) list = list.filter((a) => a.status !== 'offline')\n return [...list].sort((a, b) => {\n const s = (STATUS_SORT_ORDER[a.status] ?? 9) - (STATUS_SORT_ORDER[b.status] ?? 9)\n return s || toTimestamp(b.lastSeen) - toTimestamp(a.lastSeen)\n })\n }, [agents, showOffline, managedPolicies])\n const recentAgents = filteredAgents.slice(0, 20)\n const recentMessages = [...messages].sort((a, b) => b.id - a.id).slice(0, 15)\n\n const healthIssues =\n health && health.status !== 'ok'\n ? healthDiagnostics(health.checks || [])\n : []\n\n function nav(view: ViewName) {\n switchView(view)\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Stat cards */}\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card className=\"cursor-pointer hover:border-zinc-600 transition-colors\" onClick={() => nav('agents')}>\n <CardHeader className=\"pb-1 pt-4 px-4\">\n <CardTitle className=\"text-xs font-medium text-muted-foreground flex items-center gap-1.5\">\n <Users className=\"w-3.5 h-3.5\" />\n Agents\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-2xl font-bold\">{filteredAgents.length}</div>\n <div className=\"text-xs text-muted-foreground mt-0.5\">{onlineCount} online</div>\n </CardContent>\n </Card>\n\n <Card className=\"cursor-pointer hover:border-zinc-600 transition-colors\" onClick={() => nav('agents')}>\n <CardHeader className=\"pb-1 pt-4 px-4\">\n <CardTitle className=\"text-xs font-medium text-muted-foreground flex items-center gap-1.5\">\n <Activity className=\"w-3.5 h-3.5\" />\n Busy\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-2xl font-bold\">{busyCount}</div>\n <div className=\"text-xs text-muted-foreground mt-0.5\">in a turn now</div>\n </CardContent>\n </Card>\n\n <Card className=\"cursor-pointer hover:border-zinc-600 transition-colors\" onClick={() => nav('messages')}>\n <CardHeader className=\"pb-1 pt-4 px-4\">\n <CardTitle className=\"text-xs font-medium text-muted-foreground flex items-center gap-1.5\">\n <MessageSquare className=\"w-3.5 h-3.5\" />\n Messages 24h\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-2xl font-bold\">{stats.messagesLast24h ?? '—'}</div>\n <div className=\"text-xs text-muted-foreground mt-0.5\">last 24 hours</div>\n </CardContent>\n </Card>\n\n <Card className=\"cursor-pointer hover:border-zinc-600 transition-colors\" onClick={() => nav('messages')}>\n <CardHeader className=\"pb-1 pt-4 px-4\">\n <CardTitle className=\"text-xs font-medium text-muted-foreground flex items-center gap-1.5\">\n <Mail className=\"w-3.5 h-3.5\" />\n Total Messages\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-2xl font-bold\">{stats.messages ?? '—'}</div>\n <div className=\"text-xs text-muted-foreground mt-0.5\">all time</div>\n </CardContent>\n </Card>\n </div>\n\n {/* Health alert banner */}\n {healthIssues.length > 0 && (\n <Card className=\"border-yellow-500/40 bg-yellow-500/5\">\n <CardHeader className=\"pb-2 pt-4 px-4\">\n <CardTitle className=\"text-sm font-medium text-yellow-400 flex items-center gap-2\">\n <AlertTriangle className=\"w-4 h-4\" />\n Health Alerts ({healthIssues.length})\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4 space-y-2\">\n {healthIssues.map((issue) => (\n <div key={issue.name} className=\"text-sm space-y-1\">\n <div className=\"flex items-center gap-2\">\n <Badge\n variant=\"outline\"\n className={issue.status === 'error' ? 'border-red-500/40 text-red-400' : 'border-yellow-500/40 text-yellow-400'}\n >\n {issue.status}\n </Badge>\n <span className=\"font-medium\">{issue.name}</span>\n </div>\n <p className=\"text-xs text-muted-foreground\">{issue.detail}</p>\n {issue.subjects.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {issue.subjects.map((subject) => (\n <Badge key={subject.id} variant=\"secondary\" className=\"max-w-full truncate text-[11px]\" title={[subject.id, subject.status, subject.detail].filter(Boolean).join(' · ')}>\n {subject.label || subject.id}\n {subject.status ? ` · ${subject.status}` : ''}\n {subject.detail ? ` · ${subject.detail}` : ''}\n </Badge>\n ))}\n </div>\n )}\n {issue.actions.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 pt-0.5\">\n {issue.actions.slice(0, 3).map((action) => (\n <button\n key={action.label}\n onClick={() => runHealthAction(action)}\n className=\"text-xs text-blue-400 hover:text-blue-300 underline underline-offset-2\"\n >\n {action.label}\n </button>\n ))}\n </div>\n )}\n </div>\n ))}\n </CardContent>\n </Card>\n )}\n\n {/* Attention shortcuts */}\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\n <Card\n className={`cursor-pointer hover:border-zinc-600 transition-colors ${attention.unreadInbox > 0 ? 'border-red-500/40' : ''}`}\n onClick={() => nav('chat')}\n >\n <CardContent className=\"p-4 flex items-center gap-3\">\n <div className={`p-2 rounded-lg ${attention.unreadInbox > 0 ? 'bg-red-500/15' : 'bg-zinc-800'}`}>\n <Inbox className={`w-4 h-4 ${attention.unreadInbox > 0 ? 'text-red-400' : 'text-zinc-400'}`} />\n </div>\n <div>\n <div className=\"text-lg font-bold\">{attention.unreadInbox}</div>\n <div className=\"text-xs text-muted-foreground\">Unread</div>\n </div>\n </CardContent>\n </Card>\n\n <Card\n className={`cursor-pointer hover:border-zinc-600 transition-colors ${attention.pendingPairInvites > 0 ? 'border-yellow-500/40' : ''}`}\n onClick={() => nav('pairs')}\n >\n <CardContent className=\"p-4 flex items-center gap-3\">\n <div className={`p-2 rounded-lg ${attention.pendingPairInvites > 0 ? 'bg-yellow-500/15' : 'bg-zinc-800'}`}>\n <Link className={`w-4 h-4 ${attention.pendingPairInvites > 0 ? 'text-yellow-400' : 'text-zinc-400'}`} />\n </div>\n <div>\n <div className=\"text-lg font-bold\">{attention.pendingPairInvites}</div>\n <div className=\"text-xs text-muted-foreground\">Pair invites</div>\n </div>\n </CardContent>\n </Card>\n\n <Card\n className={`cursor-pointer hover:border-zinc-600 transition-colors ${attention.claimableTasks > 0 ? 'border-orange-500/40' : ''}`}\n onClick={() => nav('work')}\n >\n <CardContent className=\"p-4 flex items-center gap-3\">\n <div className={`p-2 rounded-lg ${attention.claimableTasks > 0 ? 'bg-orange-500/15' : 'bg-zinc-800'}`}>\n <ListChecks className={`w-4 h-4 ${attention.claimableTasks > 0 ? 'text-orange-400' : 'text-zinc-400'}`} />\n </div>\n <div>\n <div className=\"text-lg font-bold\">{attention.claimableTasks}</div>\n <div className=\"text-xs text-muted-foreground\">Claimable waiting</div>\n </div>\n </CardContent>\n </Card>\n </div>\n\n {/* Two-column: agents + recent activity */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n {/* Top agents */}\n <Card>\n <CardHeader className=\"pb-2 pt-4 px-4\">\n <CardTitle className=\"text-sm font-medium flex items-center gap-2\">\n <Bot className=\"w-4 h-4 text-muted-foreground\" />\n Agents\n <span className=\"ml-auto text-xs text-muted-foreground font-normal\">{recentAgents.length}</span>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-0 pb-0\">\n <ScrollArea className=\"h-[340px]\">\n {recentAgents.length === 0 ? (\n <div className=\"px-4 pb-4 text-sm text-muted-foreground\">No agents registered.</div>\n ) : (\n <div className=\"space-y-0\">\n {recentAgents.map((agent, i) => (\n <div key={agent.id}>\n {i > 0 && <Separator />}\n <div className=\"flex items-center gap-2.5 px-4 py-2.5 hover:bg-zinc-800/50 transition-colors cursor-pointer\" onClick={() => useRelayStore.getState().openAgentDetail(agent)}>\n <StatusDot agent={agent} now={now} />\n <AgentTypeIcon agent={agent} />\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium truncate\">{displayName(agent)}</div>\n {agent.tags.length > 0 && (\n <div className=\"flex gap-1 mt-0.5 flex-wrap\">\n {agent.tags.slice(0, 2).map((t) => (\n <Badge key={t} variant=\"outline\" className=\"text-[9px] px-1 py-0 h-4\">{t}</Badge>\n ))}\n </div>\n )}\n </div>\n <span className=\"text-xs text-muted-foreground shrink-0\">{timeAgo(now, agent.lastSeen)}</span>\n </div>\n </div>\n ))}\n </div>\n )}\n </ScrollArea>\n </CardContent>\n </Card>\n\n {/* Recent activity */}\n <Card>\n <CardHeader className=\"pb-2 pt-4 px-4\">\n <CardTitle className=\"text-sm font-medium flex items-center gap-2\">\n <Activity className=\"w-4 h-4 text-muted-foreground\" />\n Recent Activity\n <span className=\"ml-auto text-xs text-muted-foreground font-normal\">{recentMessages.length}</span>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-0 pb-0\">\n <ScrollArea className=\"h-[340px]\">\n {recentMessages.length === 0 ? (\n <div className=\"px-4 pb-4 text-sm text-muted-foreground\">No recent messages.</div>\n ) : (\n <div className=\"space-y-0\">\n {recentMessages.map((msg, i) => (\n <div key={msg.id}>\n {i > 0 && <Separator />}\n <div className=\"px-4 py-2.5 hover:bg-zinc-800/50 transition-colors\">\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground mb-0.5\">\n <span className=\"text-foreground font-medium truncate max-w-[100px]\">{displayTarget(msg.from, agentsById)}</span>\n <span>→</span>\n <span className=\"truncate max-w-[100px]\">{displayTarget(msg.to, agentsById)}</span>\n <span className=\"ml-auto shrink-0 tabular-nums\"><span className=\"opacity-40 mr-1\">#{msg.id}</span>{timeAgo(now, msg.createdAt)}</span>\n </div>\n <div className=\"text-xs text-foreground line-clamp-2 leading-snug\">{messagePreview(msg)}</div>\n </div>\n </div>\n ))}\n </div>\n )}\n </ScrollArea>\n </CardContent>\n </Card>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"overview-BJXNLoFX.js","names":[],"sources":["../../dashboard/src/components/views/overview.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { useRelayStore, useNow } from '@/store'\nimport { useAttentionSummary, useOnlineCount, useBusyCount } from '@/hooks/use-selectors'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport { Separator } from '@/components/ui/separator'\nimport { StatusDot } from '@/components/shared/status-dot'\nimport { AgentTypeIcon } from '@/components/shared/agent-type-icon'\nimport {\n displayName, displayTarget, timeAgo, messagePreview, healthDiagnostics,\n toneToColor, visibleAgents, toTimestamp,\n} from '@/lib/display'\nimport { STATUS_SORT_ORDER } from '@/lib/constants'\nimport {\n Bot, Mail, Link, Inbox, AlertTriangle, Activity,\n Users, MessageSquare, ListChecks,\n} from 'lucide-react'\nimport type { ViewName } from '@/types'\n\nexport function OverviewView() {\n const stats = useRelayStore((s) => s.stats)\n const agents = useRelayStore((s) => s.agents)\n const messages = useRelayStore((s) => s.messages)\n const health = useRelayStore((s) => s.health)\n const now = useNow()\n const agentsById = useRelayStore((s) => s.agentsById)\n const switchView = useRelayStore((s) => s.switchView)\n const runHealthAction = useRelayStore((s) => s.runHealthAction)\n const managedPolicies = useRelayStore((s) => s.managedPolicies)\n\n const showOffline = useRelayStore((s) => s.showOffline)\n\n const onlineCount = useOnlineCount()\n const busyCount = useBusyCount()\n const attention = useAttentionSummary()\n\n const filteredAgents = useMemo(() => {\n let list = visibleAgents(agents, false, managedPolicies)\n if (!showOffline) list = list.filter((a) => a.status !== 'offline')\n return [...list].sort((a, b) => {\n const s = (STATUS_SORT_ORDER[a.status] ?? 9) - (STATUS_SORT_ORDER[b.status] ?? 9)\n return s || toTimestamp(b.lastSeen) - toTimestamp(a.lastSeen)\n })\n }, [agents, showOffline, managedPolicies])\n const recentAgents = filteredAgents.slice(0, 20)\n const recentMessages = [...messages].sort((a, b) => b.id - a.id).slice(0, 15)\n\n const healthIssues =\n health && health.status !== 'ok'\n ? healthDiagnostics(health.checks || [])\n : []\n\n function nav(view: ViewName) {\n switchView(view)\n }\n\n return (\n <div className=\"space-y-6\">\n {/* Stat cards */}\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\n <Card className=\"cursor-pointer hover:border-zinc-600 transition-colors\" onClick={() => nav('agents')}>\n <CardHeader className=\"pb-1 pt-4 px-4\">\n <CardTitle className=\"text-xs font-medium text-muted-foreground flex items-center gap-1.5\">\n <Users className=\"w-3.5 h-3.5\" />\n Agents\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-2xl font-bold\">{filteredAgents.length}</div>\n <div className=\"text-xs text-muted-foreground mt-0.5\">{onlineCount} online</div>\n </CardContent>\n </Card>\n\n <Card className=\"cursor-pointer hover:border-zinc-600 transition-colors\" onClick={() => nav('agents')}>\n <CardHeader className=\"pb-1 pt-4 px-4\">\n <CardTitle className=\"text-xs font-medium text-muted-foreground flex items-center gap-1.5\">\n <Activity className=\"w-3.5 h-3.5\" />\n Busy\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-2xl font-bold\">{busyCount}</div>\n <div className=\"text-xs text-muted-foreground mt-0.5\">in a turn now</div>\n </CardContent>\n </Card>\n\n <Card className=\"cursor-pointer hover:border-zinc-600 transition-colors\" onClick={() => nav('messages')}>\n <CardHeader className=\"pb-1 pt-4 px-4\">\n <CardTitle className=\"text-xs font-medium text-muted-foreground flex items-center gap-1.5\">\n <MessageSquare className=\"w-3.5 h-3.5\" />\n Messages 24h\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-2xl font-bold\">{stats.messagesLast24h ?? '—'}</div>\n <div className=\"text-xs text-muted-foreground mt-0.5\">last 24 hours</div>\n </CardContent>\n </Card>\n\n <Card className=\"cursor-pointer hover:border-zinc-600 transition-colors\" onClick={() => nav('messages')}>\n <CardHeader className=\"pb-1 pt-4 px-4\">\n <CardTitle className=\"text-xs font-medium text-muted-foreground flex items-center gap-1.5\">\n <Mail className=\"w-3.5 h-3.5\" />\n Total Messages\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-2xl font-bold\">{stats.messages ?? '—'}</div>\n <div className=\"text-xs text-muted-foreground mt-0.5\">all time</div>\n </CardContent>\n </Card>\n </div>\n\n {/* Health alert banner */}\n {healthIssues.length > 0 && (\n <Card className=\"border-yellow-500/40 bg-yellow-500/5\">\n <CardHeader className=\"pb-2 pt-4 px-4\">\n <CardTitle className=\"text-sm font-medium text-yellow-400 flex items-center gap-2\">\n <AlertTriangle className=\"w-4 h-4\" />\n Health Alerts ({healthIssues.length})\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4 space-y-2\">\n {healthIssues.map((issue) => (\n <div key={issue.name} className=\"text-sm space-y-1\">\n <div className=\"flex items-center gap-2\">\n <Badge\n variant=\"outline\"\n className={issue.status === 'error' ? 'border-red-500/40 text-red-400' : 'border-yellow-500/40 text-yellow-400'}\n >\n {issue.status}\n </Badge>\n <span className=\"font-medium\">{issue.name}</span>\n </div>\n <p className=\"text-xs text-muted-foreground\">{issue.detail}</p>\n {issue.subjects.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {issue.subjects.map((subject) => (\n <Badge key={subject.id} variant=\"secondary\" className=\"max-w-full truncate text-[11px]\" title={[subject.id, subject.status, subject.detail].filter(Boolean).join(' · ')}>\n {subject.label || subject.id}\n {subject.status ? ` · ${subject.status}` : ''}\n {subject.detail ? ` · ${subject.detail}` : ''}\n </Badge>\n ))}\n </div>\n )}\n {issue.actions.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 pt-0.5\">\n {issue.actions.slice(0, 3).map((action) => (\n <button\n key={action.label}\n onClick={() => runHealthAction(action)}\n className=\"text-xs text-blue-400 hover:text-blue-300 underline underline-offset-2\"\n >\n {action.label}\n </button>\n ))}\n </div>\n )}\n </div>\n ))}\n </CardContent>\n </Card>\n )}\n\n {/* Attention shortcuts */}\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\n <Card\n className={`cursor-pointer hover:border-zinc-600 transition-colors ${attention.unreadInbox > 0 ? 'border-red-500/40' : ''}`}\n onClick={() => nav('chat')}\n >\n <CardContent className=\"p-4 flex items-center gap-3\">\n <div className={`p-2 rounded-lg ${attention.unreadInbox > 0 ? 'bg-red-500/15' : 'bg-zinc-800'}`}>\n <Inbox className={`w-4 h-4 ${attention.unreadInbox > 0 ? 'text-red-400' : 'text-zinc-400'}`} />\n </div>\n <div>\n <div className=\"text-lg font-bold\">{attention.unreadInbox}</div>\n <div className=\"text-xs text-muted-foreground\">Unread</div>\n </div>\n </CardContent>\n </Card>\n\n <Card\n className={`cursor-pointer hover:border-zinc-600 transition-colors ${attention.pendingPairInvites > 0 ? 'border-yellow-500/40' : ''}`}\n onClick={() => nav('pairs')}\n >\n <CardContent className=\"p-4 flex items-center gap-3\">\n <div className={`p-2 rounded-lg ${attention.pendingPairInvites > 0 ? 'bg-yellow-500/15' : 'bg-zinc-800'}`}>\n <Link className={`w-4 h-4 ${attention.pendingPairInvites > 0 ? 'text-yellow-400' : 'text-zinc-400'}`} />\n </div>\n <div>\n <div className=\"text-lg font-bold\">{attention.pendingPairInvites}</div>\n <div className=\"text-xs text-muted-foreground\">Pair invites</div>\n </div>\n </CardContent>\n </Card>\n\n <Card\n className={`cursor-pointer hover:border-zinc-600 transition-colors ${attention.claimableTasks > 0 ? 'border-orange-500/40' : ''}`}\n onClick={() => nav('work')}\n >\n <CardContent className=\"p-4 flex items-center gap-3\">\n <div className={`p-2 rounded-lg ${attention.claimableTasks > 0 ? 'bg-orange-500/15' : 'bg-zinc-800'}`}>\n <ListChecks className={`w-4 h-4 ${attention.claimableTasks > 0 ? 'text-orange-400' : 'text-zinc-400'}`} />\n </div>\n <div>\n <div className=\"text-lg font-bold\">{attention.claimableTasks}</div>\n <div className=\"text-xs text-muted-foreground\">Claimable waiting</div>\n </div>\n </CardContent>\n </Card>\n </div>\n\n {/* Two-column: agents + recent activity */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n {/* Top agents */}\n <Card>\n <CardHeader className=\"pb-2 pt-4 px-4\">\n <CardTitle className=\"text-sm font-medium flex items-center gap-2\">\n <Bot className=\"w-4 h-4 text-muted-foreground\" />\n Agents\n <span className=\"ml-auto text-xs text-muted-foreground font-normal\">{recentAgents.length}</span>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-0 pb-0\">\n <ScrollArea className=\"h-[340px]\">\n {recentAgents.length === 0 ? (\n <div className=\"px-4 pb-4 text-sm text-muted-foreground\">No agents registered.</div>\n ) : (\n <div className=\"space-y-0\">\n {recentAgents.map((agent, i) => (\n <div key={agent.id}>\n {i > 0 && <Separator />}\n <div className=\"flex items-center gap-2.5 px-4 py-2.5 hover:bg-zinc-800/50 transition-colors cursor-pointer\" onClick={() => useRelayStore.getState().openAgentDetail(agent)}>\n <StatusDot agent={agent} now={now} />\n <AgentTypeIcon agent={agent} />\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium truncate\">{displayName(agent)}</div>\n {agent.tags.length > 0 && (\n <div className=\"flex gap-1 mt-0.5 flex-wrap\">\n {agent.tags.slice(0, 2).map((t) => (\n <Badge key={t} variant=\"outline\" className=\"text-[9px] px-1 py-0 h-4\">{t}</Badge>\n ))}\n </div>\n )}\n </div>\n <span className=\"text-xs text-muted-foreground shrink-0\">{timeAgo(now, agent.lastSeen)}</span>\n </div>\n </div>\n ))}\n </div>\n )}\n </ScrollArea>\n </CardContent>\n </Card>\n\n {/* Recent activity */}\n <Card>\n <CardHeader className=\"pb-2 pt-4 px-4\">\n <CardTitle className=\"text-sm font-medium flex items-center gap-2\">\n <Activity className=\"w-4 h-4 text-muted-foreground\" />\n Recent Activity\n <span className=\"ml-auto text-xs text-muted-foreground font-normal\">{recentMessages.length}</span>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"px-0 pb-0\">\n <ScrollArea className=\"h-[340px]\">\n {recentMessages.length === 0 ? (\n <div className=\"px-4 pb-4 text-sm text-muted-foreground\">No recent messages.</div>\n ) : (\n <div className=\"space-y-0\">\n {recentMessages.map((msg, i) => (\n <div key={msg.id}>\n {i > 0 && <Separator />}\n <div className=\"px-4 py-2.5 hover:bg-zinc-800/50 transition-colors\">\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground mb-0.5\">\n <span className=\"text-foreground font-medium truncate max-w-[100px]\">{displayTarget(msg.from, agentsById)}</span>\n <span>→</span>\n <span className=\"truncate max-w-[100px]\">{displayTarget(msg.to, agentsById)}</span>\n <span className=\"ml-auto shrink-0 tabular-nums\"><span className=\"opacity-40 mr-1\">#{msg.id}</span>{timeAgo(now, msg.createdAt)}</span>\n </div>\n <div className=\"text-xs text-foreground line-clamp-2 leading-snug\">{messagePreview(msg)}</div>\n </div>\n </div>\n ))}\n </div>\n )}\n </ScrollArea>\n </CardContent>\n </Card>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Hn as e,Qn as t,d as n,gt as r,mt as i,ot as a}from"./lucide-react-BYZuAhQs.js";import{d as o,t as s}from"./store-Ch-QzxPq.js";import{K as c,d as l,h as u,st as d}from"./display-DRiGi1zj.js";import{t as f}from"./badge-BLar6FjP.js";import{t as p}from"./button-BrIB69qd.js";import{u as m}from"./index-
|
|
2
|
-
//# sourceMappingURL=pairs-
|
|
1
|
+
import{Hn as e,Qn as t,d as n,gt as r,mt as i,ot as a}from"./lucide-react-BYZuAhQs.js";import{d as o,t as s}from"./store-Ch-QzxPq.js";import{K as c,d as l,h as u,st as d}from"./display-DRiGi1zj.js";import{t as f}from"./badge-BLar6FjP.js";import{t as p}from"./button-BrIB69qd.js";import{u as m}from"./index-DOWwt3I7.js";import{a as h,r as g,t as _}from"./card-lhnFnBoz.js";var v=t(),y=[{value:`open`,label:`Active & Pending`},{value:`active`,label:`Active`},{value:`pending`,label:`Pending`},{value:`ended`,label:`Ended`},{value:`rejected`,label:`Rejected`},{value:`expired`,label:`Expired`},{value:``,label:`All`}];function b(){let e=o(),t=s(e=>e.pairs),r=s(e=>e.agentsById),a=s(e=>e.pairStatusFilter),c=s(e=>e.set),u=s(e=>e.fetchPairs),d=s(e=>e.openPairInvite),h=s(e=>e.openPairMessage),g=s(e=>e.doAcceptPair),_=s(e=>e.doRejectPair),b=s(e=>e.doHangupPair),S=t.filter(e=>e.status===`pending`).length;function C(e){c({pairStatusFilter:e}),setTimeout(()=>u(),0)}function w(e){return r[e]?l(r[e]):e.slice(-10)}return(0,v.jsxs)(`div`,{className:`space-y-4`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(i,{className:`w-5 h-5 text-muted-foreground`}),(0,v.jsx)(`h2`,{className:`text-lg font-semibold`,children:`Pair Sessions`}),S>0&&(0,v.jsxs)(f,{className:`bg-yellow-500/20 text-yellow-400 border-yellow-500/30 border`,children:[S,` pending`]})]}),(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:a,onChange:e=>C(e.target.value),children:y.map(e=>(0,v.jsx)(`option`,{value:e.value,children:e.label},e.value))}),(0,v.jsxs)(p,{size:`sm`,onClick:()=>d(),children:[(0,v.jsx)(n,{className:`w-4 h-4 mr-1`}),` Pair agents`]})]})]}),(0,v.jsx)(m,{className:`h-[calc(100dvh-11rem)]`,children:(0,v.jsxs)(`div`,{className:`space-y-3 pr-2`,children:[t.length===0&&(0,v.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No pair sessions`}),t.map(t=>(0,v.jsx)(x,{pair:t,now:e,agentName:w,onAccept:()=>g(t),onReject:()=>_(t),onMessage:()=>h(t),onHangup:()=>b(t)},t.id))]})})]})}function x({pair:t,now:n,agentName:i,onAccept:o,onReject:s,onMessage:l,onHangup:m}){let y=d[t.status]||`bg-zinc-500/20 text-zinc-400`,b=t.status===`pending`,x=t.status===`active`;return(0,v.jsxs)(_,{children:[(0,v.jsx)(h,{className:`py-3 px-4 pb-0`,children:(0,v.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap flex-1 min-w-0`,children:[(0,v.jsx)(f,{className:`${y} border text-xs`,children:t.status}),(0,v.jsxs)(`div`,{className:`flex items-center gap-1.5 text-sm min-w-0`,children:[(0,v.jsx)(`span`,{className:`font-medium truncate max-w-[120px]`,title:t.requesterId,children:i(t.requesterId)}),(0,v.jsx)(e,{className:`w-3.5 h-3.5 text-muted-foreground shrink-0`}),(0,v.jsx)(`span`,{className:`font-medium truncate max-w-[120px]`,title:t.targetId,children:i(t.targetId)})]})]}),(0,v.jsxs)(`div`,{className:`text-right shrink-0`,children:[(0,v.jsx)(`div`,{className:`text-xs font-mono text-muted-foreground/60 truncate max-w-[100px]`,children:t.id.slice(-10)}),(0,v.jsx)(`div`,{className:`text-xs text-muted-foreground`,title:u(t.updatedAt),children:c(n,t.updatedAt)})]})]})}),(0,v.jsxs)(g,{className:`px-4 py-3`,children:[t.objective&&(0,v.jsx)(`p`,{className:`text-xs text-muted-foreground mb-3 line-clamp-2`,children:t.objective}),(0,v.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[b&&(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(p,{size:`sm`,className:`bg-emerald-600 hover:bg-emerald-700 text-white h-7 text-xs`,onClick:o,children:`Accept`}),(0,v.jsx)(p,{size:`sm`,variant:`outline`,className:`h-7 text-xs text-red-400 hover:text-red-300`,onClick:s,children:`Reject`})]}),x&&(0,v.jsxs)(v.Fragment,{children:[(0,v.jsxs)(p,{size:`sm`,variant:`outline`,className:`h-7 text-xs`,onClick:l,children:[(0,v.jsx)(a,{className:`w-3.5 h-3.5 mr-1`}),` Message`]}),(0,v.jsxs)(p,{size:`sm`,variant:`outline`,className:`h-7 text-xs text-red-400 hover:text-red-300`,onClick:m,children:[(0,v.jsx)(r,{className:`w-3.5 h-3.5 mr-1`}),` Hang up`]})]})]})]})]})}export{b as PairsView};
|
|
2
|
+
//# sourceMappingURL=pairs-BPuYuK-j.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairs-
|
|
1
|
+
{"version":3,"file":"pairs-BPuYuK-j.js","names":[],"sources":["../../dashboard/src/components/views/pairs.tsx"],"sourcesContent":["import { useRelayStore, useNow } from '@/store'\nimport { Card, CardContent, CardHeader } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport { Link, Link2Off, Mail, UserPlus, ArrowRight } from 'lucide-react'\nimport { displayName, timeAgo, fmtTime } from '@/lib/display'\nimport { PAIR_STATUS_COLORS } from '@/lib/constants'\nimport type { PairSession } from '@/types'\n\nconst STATUS_OPTIONS = [\n { value: 'open', label: 'Active & Pending' },\n { value: 'active', label: 'Active' },\n { value: 'pending', label: 'Pending' },\n { value: 'ended', label: 'Ended' },\n { value: 'rejected', label: 'Rejected' },\n { value: 'expired', label: 'Expired' },\n { value: '', label: 'All' },\n]\n\nexport function PairsView() {\n const now = useNow()\n const pairs = useRelayStore((s) => s.pairs)\n const agentsById = useRelayStore((s) => s.agentsById)\n const pairStatusFilter = useRelayStore((s) => s.pairStatusFilter)\n const set = useRelayStore((s) => s.set)\n const fetchPairs = useRelayStore((s) => s.fetchPairs)\n const openPairInvite = useRelayStore((s) => s.openPairInvite)\n const openPairMessage = useRelayStore((s) => s.openPairMessage)\n const doAcceptPair = useRelayStore((s) => s.doAcceptPair)\n const doRejectPair = useRelayStore((s) => s.doRejectPair)\n const doHangupPair = useRelayStore((s) => s.doHangupPair)\n\n const pendingCount = pairs.filter((p) => p.status === 'pending').length\n\n function handleStatusChange(value: string) {\n set({ pairStatusFilter: value })\n setTimeout(() => fetchPairs(), 0)\n }\n\n function agentName(id: string) {\n return agentsById[id] ? displayName(agentsById[id]) : id.slice(-10)\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2\">\n <Link className=\"w-5 h-5 text-muted-foreground\" />\n <h2 className=\"text-lg font-semibold\">Pair Sessions</h2>\n {pendingCount > 0 && (\n <Badge className=\"bg-yellow-500/20 text-yellow-400 border-yellow-500/30 border\">\n {pendingCount} pending\n </Badge>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n <select\n className=\"rounded-md border border-input bg-background px-3 py-1.5 text-sm\"\n value={pairStatusFilter}\n onChange={(e) => handleStatusChange(e.target.value)}\n >\n {STATUS_OPTIONS.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}\n </select>\n <Button size=\"sm\" onClick={() => openPairInvite()}>\n <UserPlus className=\"w-4 h-4 mr-1\" /> Pair agents\n </Button>\n </div>\n </div>\n\n <ScrollArea className=\"h-[calc(100dvh-11rem)]\">\n <div className=\"space-y-3 pr-2\">\n {pairs.length === 0 && (\n <div className=\"text-center text-muted-foreground py-16 text-sm\">No pair sessions</div>\n )}\n {pairs.map((pair) => (\n <PairCard\n key={pair.id}\n pair={pair}\n now={now}\n agentName={agentName}\n onAccept={() => doAcceptPair(pair)}\n onReject={() => doRejectPair(pair)}\n onMessage={() => openPairMessage(pair)}\n onHangup={() => doHangupPair(pair)}\n />\n ))}\n </div>\n </ScrollArea>\n </div>\n )\n}\n\nfunction PairCard({\n pair, now, agentName, onAccept, onReject, onMessage, onHangup,\n}: {\n pair: PairSession\n now: number\n agentName: (id: string) => string\n onAccept: () => void\n onReject: () => void\n onMessage: () => void\n onHangup: () => void\n}) {\n const colorClass = PAIR_STATUS_COLORS[pair.status] || 'bg-zinc-500/20 text-zinc-400'\n const isPending = pair.status === 'pending'\n const isActive = pair.status === 'active'\n\n return (\n <Card>\n <CardHeader className=\"py-3 px-4 pb-0\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-center gap-2 flex-wrap flex-1 min-w-0\">\n <Badge className={`${colorClass} border text-xs`}>{pair.status}</Badge>\n <div className=\"flex items-center gap-1.5 text-sm min-w-0\">\n <span className=\"font-medium truncate max-w-[120px]\" title={pair.requesterId}>{agentName(pair.requesterId)}</span>\n <ArrowRight className=\"w-3.5 h-3.5 text-muted-foreground shrink-0\" />\n <span className=\"font-medium truncate max-w-[120px]\" title={pair.targetId}>{agentName(pair.targetId)}</span>\n </div>\n </div>\n <div className=\"text-right shrink-0\">\n <div className=\"text-xs font-mono text-muted-foreground/60 truncate max-w-[100px]\">{pair.id.slice(-10)}</div>\n <div className=\"text-xs text-muted-foreground\" title={fmtTime(pair.updatedAt)}>\n {timeAgo(now, pair.updatedAt)}\n </div>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"px-4 py-3\">\n {pair.objective && (\n <p className=\"text-xs text-muted-foreground mb-3 line-clamp-2\">{pair.objective}</p>\n )}\n <div className=\"flex items-center gap-2 flex-wrap\">\n {isPending && (\n <>\n <Button size=\"sm\" className=\"bg-emerald-600 hover:bg-emerald-700 text-white h-7 text-xs\" onClick={onAccept}>\n Accept\n </Button>\n <Button size=\"sm\" variant=\"outline\" className=\"h-7 text-xs text-red-400 hover:text-red-300\" onClick={onReject}>\n Reject\n </Button>\n </>\n )}\n {isActive && (\n <>\n <Button size=\"sm\" variant=\"outline\" className=\"h-7 text-xs\" onClick={onMessage}>\n <Mail className=\"w-3.5 h-3.5 mr-1\" /> Message\n </Button>\n <Button size=\"sm\" variant=\"outline\" className=\"h-7 text-xs text-red-400 hover:text-red-300\" onClick={onHangup}>\n <Link2Off className=\"w-3.5 h-3.5 mr-1\" /> Hang up\n </Button>\n </>\n )}\n </div>\n </CardContent>\n </Card>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,B as n,H as r,I as i,Qn as a,Qt as o,Y as s,_n as c,dr as l,mn as u,on as d}from"./lucide-react-BYZuAhQs.js";import{a as f}from"./types-Tv67voFu.js";import{t as p}from"./badge-BLar6FjP.js";import{t as m}from"./button-BrIB69qd.js";import{t as h}from"./input-B_fUHtLD.js";import{n as g,z as _}from"./index-D3woTUwp.js";import{a as v,o as y,r as b,t as x}from"./card-lhnFnBoz.js";var S=e(l(),1),C=a(),w=[{value:`all`,label:`All`},{value:`skill`,label:`Skills`},{value:`plugin`,label:`Plugins`},{value:`mcp`,label:`MCP`}],T=[`any`,`claude`,`codex`];function E(e){return e===`skill`?`bg-blue-500/10 text-blue-400 border-blue-500/30`:e===`plugin`?`bg-violet-500/10 text-violet-400 border-violet-500/30`:`bg-emerald-500/10 text-emerald-400 border-emerald-500/30`}function D(e){return e===`claude`?`bg-amber-500/10 text-amber-400 border-amber-500/30`:e===`codex`?`bg-sky-500/10 text-sky-400 border-sky-500/30`:`bg-zinc-500/10 text-zinc-400 border-zinc-500/30`}function O(e){return e===`approved`?`bg-emerald-500/10 text-emerald-400 border-emerald-500/30`:e===`rejected`?`bg-red-500/10 text-red-400 border-red-500/30`:`bg-yellow-500/10 text-yellow-400 border-yellow-500/30`}function k({status:e}){return e===`valid`?(0,C.jsx)(u,{className:`h-3.5 w-3.5 text-emerald-400`}):e===`invalid`?(0,C.jsx)(c,{className:`h-3.5 w-3.5 text-red-400`}):(0,C.jsx)(d,{className:`h-3.5 w-3.5 text-zinc-400`})}var A={kind:`skill`,slug:``,title:``},j={githubUrl:``,ref:`main`,subpath:``,provider:`any`,versionConstraint:``},M={command:``,args:``,url:``,approvalStatus:`pending`,versionConstraint:``};function N({variant:e,onToggle:t,onUpdate:n,onValidate:i,busy:a}){let s=a===e.id;return(0,C.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-3 space-y-2`,children:[(0,C.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,C.jsx)(p,{variant:`outline`,className:`text-[10px] ${D(e.provider)}`,children:e.provider}),(0,C.jsx)(`span`,{className:`text-xs font-medium font-mono`,children:e.name}),e.approvalStatus&&(0,C.jsx)(p,{variant:`outline`,className:`text-[10px] ${O(e.approvalStatus)}`,children:e.approvalStatus}),(0,C.jsxs)(`span`,{className:`text-[10px] text-muted-foreground flex items-center gap-1 ml-auto`,children:[(0,C.jsx)(k,{status:e.validationStatus}),e.validationStatus??`unvalidated`]}),(0,C.jsx)(_,{size:`sm`,checked:e.enabled,disabled:s,onCheckedChange:n=>t(e.id,n)})]}),(e.sourceUrl||e.sourceRef)&&(0,C.jsxs)(`div`,{className:`text-[10px] text-muted-foreground font-mono truncate`,title:e.sourceUrl,children:[e.sourceUrl,e.sourceRef?`@${e.resolvedRef??e.sourceRef}`:``,e.sourceSubpath?` · ${e.sourceSubpath}`:``]}),(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsxs)(m,{variant:`outline`,size:`sm`,className:`h-6 text-xs`,disabled:s||!e.sourceRef,onClick:()=>n(e.id),title:`Pull latest from source ref`,children:[(0,C.jsx)(o,{className:`h-3 w-3 mr-1`}),`Update ref`]}),(0,C.jsxs)(m,{variant:`outline`,size:`sm`,className:`h-6 text-xs`,disabled:s,onClick:()=>i(e.id),children:[(0,C.jsx)(r,{className:`h-3 w-3 mr-1`}),`Validate`]})]})]})}function P({form:e,onChange:t,onSubmit:n,onCancel:r,busy:i,error:a}){return(0,C.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-3 space-y-3`,children:[(0,C.jsx)(`div`,{className:`text-sm font-medium`,children:`New Capability`}),a&&(0,C.jsx)(`div`,{className:`text-xs text-destructive`,children:a}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Kind`}),(0,C.jsxs)(`select`,{className:`mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:e.kind,onChange:e=>t({kind:e.target.value}),children:[(0,C.jsx)(`option`,{value:`skill`,children:`Skill`}),(0,C.jsx)(`option`,{value:`plugin`,children:`Plugin`}),(0,C.jsx)(`option`,{value:`mcp`,children:`MCP Server`})]})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Slug`}),(0,C.jsx)(h,{value:e.slug,onChange:e=>t({slug:e.target.value}),placeholder:`my-capability`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Title (optional)`}),(0,C.jsx)(h,{value:e.title,onChange:e=>t({title:e.target.value}),placeholder:`My Capability`,className:`mt-1 text-sm`})]}),(0,C.jsxs)(`div`,{className:`flex gap-2`,children:[(0,C.jsx)(m,{size:`sm`,onClick:n,disabled:i||!e.slug.trim(),children:i?`Creating…`:`Create`}),(0,C.jsx)(m,{size:`sm`,variant:`outline`,onClick:r,children:`Cancel`})]})]})}function F({form:e,onChange:t,onSubmit:n,onCancel:r,busy:i,error:a}){return(0,C.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-3 space-y-3`,children:[(0,C.jsx)(`div`,{className:`text-sm font-medium`,children:`Import from GitHub`}),a&&(0,C.jsx)(`div`,{className:`text-xs text-destructive`,children:a}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`GitHub URL`}),(0,C.jsx)(h,{value:e.githubUrl,onChange:e=>t({githubUrl:e.target.value}),placeholder:`https://github.com/owner/repo`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Ref`}),(0,C.jsx)(h,{value:e.ref,onChange:e=>t({ref:e.target.value}),placeholder:`main`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Subpath (optional)`}),(0,C.jsx)(h,{value:e.subpath,onChange:e=>t({subpath:e.target.value}),placeholder:`skills/my-skill`,className:`mt-1 text-sm font-mono`})]})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Provider`}),(0,C.jsx)(`select`,{className:`mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:e.provider,onChange:e=>t({provider:e.target.value}),children:T.map(e=>(0,C.jsx)(`option`,{value:e,children:e},e))})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Version constraint (optional)`}),(0,C.jsx)(h,{value:e.versionConstraint,onChange:e=>t({versionConstraint:e.target.value}),placeholder:`>=1.0.0`,className:`mt-1 text-sm font-mono`})]})]}),(0,C.jsxs)(`div`,{className:`flex gap-2`,children:[(0,C.jsx)(m,{size:`sm`,onClick:n,disabled:i||!e.githubUrl.trim()||!e.ref.trim(),children:i?`Importing…`:`Import`}),(0,C.jsx)(m,{size:`sm`,variant:`outline`,onClick:r,children:`Cancel`})]})]})}function I({form:e,onChange:t,onSubmit:n,onCancel:r,busy:i,error:a}){return(0,C.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-3 space-y-3`,children:[(0,C.jsx)(`div`,{className:`text-sm font-medium`,children:`Add MCP Server Variant`}),a&&(0,C.jsx)(`div`,{className:`text-xs text-destructive`,children:a}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Command (for stdio type)`}),(0,C.jsx)(h,{value:e.command,onChange:e=>t({command:e.target.value}),placeholder:`npx -y @modelcontextprotocol/server-foo`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Args (space-separated, overrides command split)`}),(0,C.jsx)(h,{value:e.args,onChange:e=>t({args:e.target.value}),placeholder:`--port 3000`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`URL (for http/sse type)`}),(0,C.jsx)(h,{value:e.url,onChange:e=>t({url:e.target.value}),placeholder:`http://localhost:3000/mcp`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Approval status`}),(0,C.jsxs)(`select`,{className:`mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:e.approvalStatus,onChange:e=>t({approvalStatus:e.target.value}),children:[(0,C.jsx)(`option`,{value:`pending`,children:`Pending`}),(0,C.jsx)(`option`,{value:`approved`,children:`Approved`})]})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Version constraint (optional)`}),(0,C.jsx)(h,{value:e.versionConstraint,onChange:e=>t({versionConstraint:e.target.value}),placeholder:`>=1.0.0`,className:`mt-1 text-sm font-mono`})]})]}),(0,C.jsxs)(`div`,{className:`flex gap-2`,children:[(0,C.jsx)(m,{size:`sm`,onClick:n,disabled:i||!e.command.trim()&&!e.url.trim(),children:i?`Adding…`:`Add MCP Variant`}),(0,C.jsx)(m,{size:`sm`,variant:`outline`,onClick:r,children:`Cancel`})]})]})}function L(){let[e,r]=(0,S.useState)([]),[a,o]=(0,S.useState)(`all`),[c,l]=(0,S.useState)(``),[u,d]=(0,S.useState)(!0),[h,g]=(0,S.useState)(null),[_,T]=(0,S.useState)(`none`),[D,O]=(0,S.useState)(!1),[k,L]=(0,S.useState)(null),[R,z]=(0,S.useState)(null),[B,V]=(0,S.useState)(A),[H,U]=(0,S.useState)(j),[W,G]=(0,S.useState)(M);async function K(){g(null);try{let e=await t(`GET`,`/provisioning/capabilities${a===`all`?``:`?kind=${a}`}`);r(e.capabilities),!c&&e.capabilities.length>0&&l(e.capabilities[0].capability.id)}catch(e){g(f(e))}finally{d(!1)}}(0,S.useEffect)(()=>{d(!0),K()},[a]);let q=e.find(e=>e.capability.id===c)??null;function J(e){T(e),L(null),O(!1),V(A),U(j),G(M)}async function Y(){O(!0),L(null);try{await t(`POST`,`/provisioning/capabilities`,{kind:B.kind,slug:B.slug.trim(),title:B.title.trim()||void 0}),T(`none`),await K()}catch(e){L(f(e))}finally{O(!1)}}async function X(){if(q){O(!0),L(null);try{await t(`POST`,`/provisioning/capabilities/${encodeURIComponent(q.capability.id)}/variants/import`,{githubUrl:H.githubUrl.trim(),ref:H.ref.trim(),subpath:H.subpath.trim()||void 0,provider:H.provider,versionConstraint:H.versionConstraint.trim()||void 0}),T(`none`),await K()}catch(e){L(f(e))}finally{O(!1)}}}async function Z(){if(q){O(!0),L(null);try{let e={};if(W.url.trim())e.type=`http`,e.url=W.url.trim();else{e.type=`stdio`;let t=W.command.trim().split(/\s+/);e.command=t[0];let n=W.args.trim()?W.args.trim().split(/\s+/):t.slice(1);n.length>0&&(e.args=n)}await t(`POST`,`/provisioning/capabilities/${encodeURIComponent(q.capability.id)}/variants/mcp`,{server:e,approvalStatus:W.approvalStatus,versionConstraint:W.versionConstraint.trim()||void 0}),T(`none`),await K()}catch(e){L(f(e))}finally{O(!1)}}}async function Q(e,n){z(e);try{await t(`PATCH`,`/provisioning/variants/${encodeURIComponent(e)}`,{enabled:n}),r(t=>t.map(t=>({...t,variants:t.variants.map(t=>t.id===e?{...t,enabled:n}:t)})))}catch(e){g(f(e))}finally{z(null)}}async function ee(e){let n=q?.variants.find(t=>t.id===e);if(n?.sourceRef){z(e);try{await t(`POST`,`/provisioning/variants/${encodeURIComponent(e)}/update`,{ref:n.sourceRef,subpath:n.sourceSubpath}),await K()}catch(e){g(f(e))}finally{z(null)}}}async function te(e){z(e);try{await t(`POST`,`/provisioning/variants/${encodeURIComponent(e)}/validate`,{}),await K()}catch(e){g(f(e))}finally{z(null)}}let $=q?.capability;return(0,C.jsxs)(`div`,{className:`space-y-4 p-4`,children:[(0,C.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,C.jsx)(s,{className:`size-5 text-primary`}),(0,C.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Registry`}),(0,C.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`provisioning capability registry · #561`}),(0,C.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[w.map(e=>(0,C.jsx)(`button`,{type:`button`,onClick:()=>o(e.value),className:`rounded-md border px-2.5 py-1 text-xs transition-colors ${a===e.value?`border-primary/40 bg-primary/10 text-primary`:`border-border text-muted-foreground hover:bg-accent`}`,children:e.label},e.value)),(0,C.jsx)(m,{variant:`outline`,size:`sm`,onClick:()=>void K(),children:(0,C.jsx)(i,{className:`size-4`})})]})]}),h&&(0,C.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:h}),(0,C.jsxs)(`div`,{className:`grid grid-cols-1 gap-4 xl:grid-cols-[300px_1fr]`,children:[(0,C.jsxs)(`div`,{className:`space-y-2`,children:[(0,C.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,C.jsxs)(`span`,{className:`text-xs text-muted-foreground font-medium`,children:[e.length,` capabilities`]}),(0,C.jsxs)(m,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1`,onClick:()=>J(`new-capability`),children:[(0,C.jsx)(n,{className:`h-3 w-3`}),`New`]})]}),_===`new-capability`&&(0,C.jsx)(P,{form:B,onChange:e=>V(t=>({...t,...e})),onSubmit:()=>void Y(),onCancel:()=>T(`none`),busy:D,error:k}),u&&e.length===0&&(0,C.jsx)(`div`,{className:`py-8 text-center text-sm text-muted-foreground`,children:`Loading…`}),!u&&e.length===0&&(0,C.jsx)(x,{children:(0,C.jsx)(b,{className:`py-10 text-center text-sm text-muted-foreground`,children:`No capabilities yet. Click New to create one.`})}),e.map(({capability:e,variants:t})=>(0,C.jsxs)(`button`,{type:`button`,onClick:()=>{l(e.id),T(`none`)},className:`w-full rounded-md border p-3 text-left transition-colors ${c===e.id?`border-primary/50 bg-primary/5`:`border-border bg-card/60 hover:bg-accent`}`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(p,{variant:`outline`,className:`text-[10px] ${E(e.kind)}`,children:e.kind}),(0,C.jsx)(`span`,{className:`text-xs font-medium font-mono truncate flex-1`,children:e.slug}),(0,C.jsxs)(`span`,{className:`text-[10px] text-muted-foreground shrink-0`,children:[t.length,`v`]})]}),e.title&&(0,C.jsx)(`div`,{className:`mt-1 text-xs text-muted-foreground truncate`,children:e.title}),(0,C.jsxs)(`div`,{className:`mt-1 flex items-center gap-1.5`,children:[(0,C.jsx)(`span`,{className:`inline-block h-1.5 w-1.5 rounded-full ${e.status===`active`?`bg-emerald-500`:`bg-zinc-500`}`}),(0,C.jsx)(`span`,{className:`text-[10px] text-muted-foreground`,children:e.status})]})]},e.id))]}),$?(0,C.jsxs)(`div`,{className:`space-y-3`,children:[(0,C.jsxs)(x,{children:[(0,C.jsx)(v,{children:(0,C.jsxs)(y,{className:`flex flex-wrap items-center gap-2`,children:[(0,C.jsx)(p,{variant:`outline`,className:E($.kind),children:$.kind}),(0,C.jsx)(`span`,{className:`font-mono text-base`,children:$.slug}),$.title&&(0,C.jsxs)(`span`,{className:`text-sm font-normal text-muted-foreground`,children:[`· `,$.title]}),(0,C.jsx)(p,{variant:$.status===`active`?`secondary`:`outline`,className:`ml-auto text-[10px]`,children:$.status})]})}),$.description&&(0,C.jsx)(b,{className:`pt-0 text-sm text-muted-foreground`,children:$.description})]}),(0,C.jsxs)(x,{children:[(0,C.jsx)(v,{children:(0,C.jsxs)(y,{className:`flex items-center gap-2 text-base`,children:[`Variants`,(0,C.jsxs)(`span`,{className:`text-xs font-normal text-muted-foreground`,children:[`(`,q?.variants.length??0,`)`]}),(0,C.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,C.jsxs)(m,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1`,onClick:()=>J(_===`import-github`?`none`:`import-github`),children:[(0,C.jsx)(n,{className:`h-3 w-3`}),`GitHub`]}),$.kind===`mcp`&&(0,C.jsxs)(m,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1`,onClick:()=>J(_===`import-mcp`?`none`:`import-mcp`),children:[(0,C.jsx)(n,{className:`h-3 w-3`}),`MCP Server`]})]})]})}),(0,C.jsxs)(b,{className:`space-y-3`,children:[_===`import-github`&&(0,C.jsx)(F,{form:H,onChange:e=>U(t=>({...t,...e})),onSubmit:()=>void X(),onCancel:()=>T(`none`),busy:D,error:k}),_===`import-mcp`&&(0,C.jsx)(I,{form:W,onChange:e=>G(t=>({...t,...e})),onSubmit:()=>void Z(),onCancel:()=>T(`none`),busy:D,error:k}),q&&q.variants.length===0&&_===`none`&&(0,C.jsxs)(`div`,{className:`py-6 text-center text-sm text-muted-foreground`,children:[`No variants yet. Add one via GitHub import`,$.kind===`mcp`?` or MCP Server`:``,`.`]}),q?.variants.map(e=>(0,C.jsx)(N,{variant:e,onToggle:(e,t)=>void Q(e,t),onUpdate:e=>void ee(e),onValidate:e=>void te(e),busy:R},e.id))]})]})]}):!u&&(0,C.jsx)(x,{children:(0,C.jsx)(b,{className:`py-16 text-center text-sm text-muted-foreground`,children:`Select a capability to view details and variants.`})})]})]})}export{L as RegistryView};
|
|
2
|
-
//# sourceMappingURL=registry-
|
|
1
|
+
import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,B as n,H as r,I as i,Qn as a,Qt as o,Y as s,_n as c,dr as l,mn as u,on as d}from"./lucide-react-BYZuAhQs.js";import{a as f}from"./types-Tv67voFu.js";import{t as p}from"./badge-BLar6FjP.js";import{t as m}from"./button-BrIB69qd.js";import{t as h}from"./input-B_fUHtLD.js";import{n as g,z as _}from"./index-DOWwt3I7.js";import{a as v,o as y,r as b,t as x}from"./card-lhnFnBoz.js";var S=e(l(),1),C=a(),w=[{value:`all`,label:`All`},{value:`skill`,label:`Skills`},{value:`plugin`,label:`Plugins`},{value:`mcp`,label:`MCP`}],T=[`any`,`claude`,`codex`];function E(e){return e===`skill`?`bg-blue-500/10 text-blue-400 border-blue-500/30`:e===`plugin`?`bg-violet-500/10 text-violet-400 border-violet-500/30`:`bg-emerald-500/10 text-emerald-400 border-emerald-500/30`}function D(e){return e===`claude`?`bg-amber-500/10 text-amber-400 border-amber-500/30`:e===`codex`?`bg-sky-500/10 text-sky-400 border-sky-500/30`:`bg-zinc-500/10 text-zinc-400 border-zinc-500/30`}function O(e){return e===`approved`?`bg-emerald-500/10 text-emerald-400 border-emerald-500/30`:e===`rejected`?`bg-red-500/10 text-red-400 border-red-500/30`:`bg-yellow-500/10 text-yellow-400 border-yellow-500/30`}function k({status:e}){return e===`valid`?(0,C.jsx)(u,{className:`h-3.5 w-3.5 text-emerald-400`}):e===`invalid`?(0,C.jsx)(c,{className:`h-3.5 w-3.5 text-red-400`}):(0,C.jsx)(d,{className:`h-3.5 w-3.5 text-zinc-400`})}var A={kind:`skill`,slug:``,title:``},j={githubUrl:``,ref:`main`,subpath:``,provider:`any`,versionConstraint:``},M={command:``,args:``,url:``,approvalStatus:`pending`,versionConstraint:``};function N({variant:e,onToggle:t,onUpdate:n,onValidate:i,busy:a}){let s=a===e.id;return(0,C.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-3 space-y-2`,children:[(0,C.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,C.jsx)(p,{variant:`outline`,className:`text-[10px] ${D(e.provider)}`,children:e.provider}),(0,C.jsx)(`span`,{className:`text-xs font-medium font-mono`,children:e.name}),e.approvalStatus&&(0,C.jsx)(p,{variant:`outline`,className:`text-[10px] ${O(e.approvalStatus)}`,children:e.approvalStatus}),(0,C.jsxs)(`span`,{className:`text-[10px] text-muted-foreground flex items-center gap-1 ml-auto`,children:[(0,C.jsx)(k,{status:e.validationStatus}),e.validationStatus??`unvalidated`]}),(0,C.jsx)(_,{size:`sm`,checked:e.enabled,disabled:s,onCheckedChange:n=>t(e.id,n)})]}),(e.sourceUrl||e.sourceRef)&&(0,C.jsxs)(`div`,{className:`text-[10px] text-muted-foreground font-mono truncate`,title:e.sourceUrl,children:[e.sourceUrl,e.sourceRef?`@${e.resolvedRef??e.sourceRef}`:``,e.sourceSubpath?` · ${e.sourceSubpath}`:``]}),(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsxs)(m,{variant:`outline`,size:`sm`,className:`h-6 text-xs`,disabled:s||!e.sourceRef,onClick:()=>n(e.id),title:`Pull latest from source ref`,children:[(0,C.jsx)(o,{className:`h-3 w-3 mr-1`}),`Update ref`]}),(0,C.jsxs)(m,{variant:`outline`,size:`sm`,className:`h-6 text-xs`,disabled:s,onClick:()=>i(e.id),children:[(0,C.jsx)(r,{className:`h-3 w-3 mr-1`}),`Validate`]})]})]})}function P({form:e,onChange:t,onSubmit:n,onCancel:r,busy:i,error:a}){return(0,C.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-3 space-y-3`,children:[(0,C.jsx)(`div`,{className:`text-sm font-medium`,children:`New Capability`}),a&&(0,C.jsx)(`div`,{className:`text-xs text-destructive`,children:a}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Kind`}),(0,C.jsxs)(`select`,{className:`mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:e.kind,onChange:e=>t({kind:e.target.value}),children:[(0,C.jsx)(`option`,{value:`skill`,children:`Skill`}),(0,C.jsx)(`option`,{value:`plugin`,children:`Plugin`}),(0,C.jsx)(`option`,{value:`mcp`,children:`MCP Server`})]})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Slug`}),(0,C.jsx)(h,{value:e.slug,onChange:e=>t({slug:e.target.value}),placeholder:`my-capability`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Title (optional)`}),(0,C.jsx)(h,{value:e.title,onChange:e=>t({title:e.target.value}),placeholder:`My Capability`,className:`mt-1 text-sm`})]}),(0,C.jsxs)(`div`,{className:`flex gap-2`,children:[(0,C.jsx)(m,{size:`sm`,onClick:n,disabled:i||!e.slug.trim(),children:i?`Creating…`:`Create`}),(0,C.jsx)(m,{size:`sm`,variant:`outline`,onClick:r,children:`Cancel`})]})]})}function F({form:e,onChange:t,onSubmit:n,onCancel:r,busy:i,error:a}){return(0,C.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-3 space-y-3`,children:[(0,C.jsx)(`div`,{className:`text-sm font-medium`,children:`Import from GitHub`}),a&&(0,C.jsx)(`div`,{className:`text-xs text-destructive`,children:a}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`GitHub URL`}),(0,C.jsx)(h,{value:e.githubUrl,onChange:e=>t({githubUrl:e.target.value}),placeholder:`https://github.com/owner/repo`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Ref`}),(0,C.jsx)(h,{value:e.ref,onChange:e=>t({ref:e.target.value}),placeholder:`main`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Subpath (optional)`}),(0,C.jsx)(h,{value:e.subpath,onChange:e=>t({subpath:e.target.value}),placeholder:`skills/my-skill`,className:`mt-1 text-sm font-mono`})]})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Provider`}),(0,C.jsx)(`select`,{className:`mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:e.provider,onChange:e=>t({provider:e.target.value}),children:T.map(e=>(0,C.jsx)(`option`,{value:e,children:e},e))})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Version constraint (optional)`}),(0,C.jsx)(h,{value:e.versionConstraint,onChange:e=>t({versionConstraint:e.target.value}),placeholder:`>=1.0.0`,className:`mt-1 text-sm font-mono`})]})]}),(0,C.jsxs)(`div`,{className:`flex gap-2`,children:[(0,C.jsx)(m,{size:`sm`,onClick:n,disabled:i||!e.githubUrl.trim()||!e.ref.trim(),children:i?`Importing…`:`Import`}),(0,C.jsx)(m,{size:`sm`,variant:`outline`,onClick:r,children:`Cancel`})]})]})}function I({form:e,onChange:t,onSubmit:n,onCancel:r,busy:i,error:a}){return(0,C.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-3 space-y-3`,children:[(0,C.jsx)(`div`,{className:`text-sm font-medium`,children:`Add MCP Server Variant`}),a&&(0,C.jsx)(`div`,{className:`text-xs text-destructive`,children:a}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Command (for stdio type)`}),(0,C.jsx)(h,{value:e.command,onChange:e=>t({command:e.target.value}),placeholder:`npx -y @modelcontextprotocol/server-foo`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Args (space-separated, overrides command split)`}),(0,C.jsx)(h,{value:e.args,onChange:e=>t({args:e.target.value}),placeholder:`--port 3000`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`URL (for http/sse type)`}),(0,C.jsx)(h,{value:e.url,onChange:e=>t({url:e.target.value}),placeholder:`http://localhost:3000/mcp`,className:`mt-1 text-sm font-mono`})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Approval status`}),(0,C.jsxs)(`select`,{className:`mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:e.approvalStatus,onChange:e=>t({approvalStatus:e.target.value}),children:[(0,C.jsx)(`option`,{value:`pending`,children:`Pending`}),(0,C.jsx)(`option`,{value:`approved`,children:`Approved`})]})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(g,{className:`text-xs`,children:`Version constraint (optional)`}),(0,C.jsx)(h,{value:e.versionConstraint,onChange:e=>t({versionConstraint:e.target.value}),placeholder:`>=1.0.0`,className:`mt-1 text-sm font-mono`})]})]}),(0,C.jsxs)(`div`,{className:`flex gap-2`,children:[(0,C.jsx)(m,{size:`sm`,onClick:n,disabled:i||!e.command.trim()&&!e.url.trim(),children:i?`Adding…`:`Add MCP Variant`}),(0,C.jsx)(m,{size:`sm`,variant:`outline`,onClick:r,children:`Cancel`})]})]})}function L(){let[e,r]=(0,S.useState)([]),[a,o]=(0,S.useState)(`all`),[c,l]=(0,S.useState)(``),[u,d]=(0,S.useState)(!0),[h,g]=(0,S.useState)(null),[_,T]=(0,S.useState)(`none`),[D,O]=(0,S.useState)(!1),[k,L]=(0,S.useState)(null),[R,z]=(0,S.useState)(null),[B,V]=(0,S.useState)(A),[H,U]=(0,S.useState)(j),[W,G]=(0,S.useState)(M);async function K(){g(null);try{let e=await t(`GET`,`/provisioning/capabilities${a===`all`?``:`?kind=${a}`}`);r(e.capabilities),!c&&e.capabilities.length>0&&l(e.capabilities[0].capability.id)}catch(e){g(f(e))}finally{d(!1)}}(0,S.useEffect)(()=>{d(!0),K()},[a]);let q=e.find(e=>e.capability.id===c)??null;function J(e){T(e),L(null),O(!1),V(A),U(j),G(M)}async function Y(){O(!0),L(null);try{await t(`POST`,`/provisioning/capabilities`,{kind:B.kind,slug:B.slug.trim(),title:B.title.trim()||void 0}),T(`none`),await K()}catch(e){L(f(e))}finally{O(!1)}}async function X(){if(q){O(!0),L(null);try{await t(`POST`,`/provisioning/capabilities/${encodeURIComponent(q.capability.id)}/variants/import`,{githubUrl:H.githubUrl.trim(),ref:H.ref.trim(),subpath:H.subpath.trim()||void 0,provider:H.provider,versionConstraint:H.versionConstraint.trim()||void 0}),T(`none`),await K()}catch(e){L(f(e))}finally{O(!1)}}}async function Z(){if(q){O(!0),L(null);try{let e={};if(W.url.trim())e.type=`http`,e.url=W.url.trim();else{e.type=`stdio`;let t=W.command.trim().split(/\s+/);e.command=t[0];let n=W.args.trim()?W.args.trim().split(/\s+/):t.slice(1);n.length>0&&(e.args=n)}await t(`POST`,`/provisioning/capabilities/${encodeURIComponent(q.capability.id)}/variants/mcp`,{server:e,approvalStatus:W.approvalStatus,versionConstraint:W.versionConstraint.trim()||void 0}),T(`none`),await K()}catch(e){L(f(e))}finally{O(!1)}}}async function Q(e,n){z(e);try{await t(`PATCH`,`/provisioning/variants/${encodeURIComponent(e)}`,{enabled:n}),r(t=>t.map(t=>({...t,variants:t.variants.map(t=>t.id===e?{...t,enabled:n}:t)})))}catch(e){g(f(e))}finally{z(null)}}async function ee(e){let n=q?.variants.find(t=>t.id===e);if(n?.sourceRef){z(e);try{await t(`POST`,`/provisioning/variants/${encodeURIComponent(e)}/update`,{ref:n.sourceRef,subpath:n.sourceSubpath}),await K()}catch(e){g(f(e))}finally{z(null)}}}async function te(e){z(e);try{await t(`POST`,`/provisioning/variants/${encodeURIComponent(e)}/validate`,{}),await K()}catch(e){g(f(e))}finally{z(null)}}let $=q?.capability;return(0,C.jsxs)(`div`,{className:`space-y-4 p-4`,children:[(0,C.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,C.jsx)(s,{className:`size-5 text-primary`}),(0,C.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Registry`}),(0,C.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`provisioning capability registry · #561`}),(0,C.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[w.map(e=>(0,C.jsx)(`button`,{type:`button`,onClick:()=>o(e.value),className:`rounded-md border px-2.5 py-1 text-xs transition-colors ${a===e.value?`border-primary/40 bg-primary/10 text-primary`:`border-border text-muted-foreground hover:bg-accent`}`,children:e.label},e.value)),(0,C.jsx)(m,{variant:`outline`,size:`sm`,onClick:()=>void K(),children:(0,C.jsx)(i,{className:`size-4`})})]})]}),h&&(0,C.jsx)(`div`,{className:`rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:h}),(0,C.jsxs)(`div`,{className:`grid grid-cols-1 gap-4 xl:grid-cols-[300px_1fr]`,children:[(0,C.jsxs)(`div`,{className:`space-y-2`,children:[(0,C.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,C.jsxs)(`span`,{className:`text-xs text-muted-foreground font-medium`,children:[e.length,` capabilities`]}),(0,C.jsxs)(m,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1`,onClick:()=>J(`new-capability`),children:[(0,C.jsx)(n,{className:`h-3 w-3`}),`New`]})]}),_===`new-capability`&&(0,C.jsx)(P,{form:B,onChange:e=>V(t=>({...t,...e})),onSubmit:()=>void Y(),onCancel:()=>T(`none`),busy:D,error:k}),u&&e.length===0&&(0,C.jsx)(`div`,{className:`py-8 text-center text-sm text-muted-foreground`,children:`Loading…`}),!u&&e.length===0&&(0,C.jsx)(x,{children:(0,C.jsx)(b,{className:`py-10 text-center text-sm text-muted-foreground`,children:`No capabilities yet. Click New to create one.`})}),e.map(({capability:e,variants:t})=>(0,C.jsxs)(`button`,{type:`button`,onClick:()=>{l(e.id),T(`none`)},className:`w-full rounded-md border p-3 text-left transition-colors ${c===e.id?`border-primary/50 bg-primary/5`:`border-border bg-card/60 hover:bg-accent`}`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,C.jsx)(p,{variant:`outline`,className:`text-[10px] ${E(e.kind)}`,children:e.kind}),(0,C.jsx)(`span`,{className:`text-xs font-medium font-mono truncate flex-1`,children:e.slug}),(0,C.jsxs)(`span`,{className:`text-[10px] text-muted-foreground shrink-0`,children:[t.length,`v`]})]}),e.title&&(0,C.jsx)(`div`,{className:`mt-1 text-xs text-muted-foreground truncate`,children:e.title}),(0,C.jsxs)(`div`,{className:`mt-1 flex items-center gap-1.5`,children:[(0,C.jsx)(`span`,{className:`inline-block h-1.5 w-1.5 rounded-full ${e.status===`active`?`bg-emerald-500`:`bg-zinc-500`}`}),(0,C.jsx)(`span`,{className:`text-[10px] text-muted-foreground`,children:e.status})]})]},e.id))]}),$?(0,C.jsxs)(`div`,{className:`space-y-3`,children:[(0,C.jsxs)(x,{children:[(0,C.jsx)(v,{children:(0,C.jsxs)(y,{className:`flex flex-wrap items-center gap-2`,children:[(0,C.jsx)(p,{variant:`outline`,className:E($.kind),children:$.kind}),(0,C.jsx)(`span`,{className:`font-mono text-base`,children:$.slug}),$.title&&(0,C.jsxs)(`span`,{className:`text-sm font-normal text-muted-foreground`,children:[`· `,$.title]}),(0,C.jsx)(p,{variant:$.status===`active`?`secondary`:`outline`,className:`ml-auto text-[10px]`,children:$.status})]})}),$.description&&(0,C.jsx)(b,{className:`pt-0 text-sm text-muted-foreground`,children:$.description})]}),(0,C.jsxs)(x,{children:[(0,C.jsx)(v,{children:(0,C.jsxs)(y,{className:`flex items-center gap-2 text-base`,children:[`Variants`,(0,C.jsxs)(`span`,{className:`text-xs font-normal text-muted-foreground`,children:[`(`,q?.variants.length??0,`)`]}),(0,C.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,C.jsxs)(m,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1`,onClick:()=>J(_===`import-github`?`none`:`import-github`),children:[(0,C.jsx)(n,{className:`h-3 w-3`}),`GitHub`]}),$.kind===`mcp`&&(0,C.jsxs)(m,{size:`sm`,variant:`outline`,className:`h-7 text-xs gap-1`,onClick:()=>J(_===`import-mcp`?`none`:`import-mcp`),children:[(0,C.jsx)(n,{className:`h-3 w-3`}),`MCP Server`]})]})]})}),(0,C.jsxs)(b,{className:`space-y-3`,children:[_===`import-github`&&(0,C.jsx)(F,{form:H,onChange:e=>U(t=>({...t,...e})),onSubmit:()=>void X(),onCancel:()=>T(`none`),busy:D,error:k}),_===`import-mcp`&&(0,C.jsx)(I,{form:W,onChange:e=>G(t=>({...t,...e})),onSubmit:()=>void Z(),onCancel:()=>T(`none`),busy:D,error:k}),q&&q.variants.length===0&&_===`none`&&(0,C.jsxs)(`div`,{className:`py-6 text-center text-sm text-muted-foreground`,children:[`No variants yet. Add one via GitHub import`,$.kind===`mcp`?` or MCP Server`:``,`.`]}),q?.variants.map(e=>(0,C.jsx)(N,{variant:e,onToggle:(e,t)=>void Q(e,t),onUpdate:e=>void ee(e),onValidate:e=>void te(e),busy:R},e.id))]})]})]}):!u&&(0,C.jsx)(x,{children:(0,C.jsx)(b,{className:`py-16 text-center text-sm text-muted-foreground`,children:`Select a capability to view details and variants.`})})]})]})}export{L as RegistryView};
|
|
2
|
+
//# sourceMappingURL=registry-ApGTbK4L.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-BeGP37ot.js","names":[],"sources":["../../dashboard/src/components/views/registry.tsx"],"sourcesContent":["import { useEffect, useState } from 'react'\nimport { errMessage } from 'agent-relay-sdk/types'\nimport { api } from '@/lib/api'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { Switch } from '@/components/ui/switch'\nimport { PackagePlus, RefreshCw, Plus, Trash2, CheckCircle, AlertCircle, Clock, Download, Play } from 'lucide-react'\nimport type { ProvisioningAssetKind, ProvisioningCapability, ProvisioningAsset, ProvisioningCapabilityWithVariants } from '@/types'\n\n// Registry view (#561) — browse and manage the provisioning capability registry.\n// Two-pane: left = capability list + filters, right = selected capability detail + variants.\n\ntype KindFilter = 'all' | ProvisioningAssetKind\n\nconst KIND_OPTIONS: Array<{ value: KindFilter; label: string }> = [\n { value: 'all', label: 'All' },\n { value: 'skill', label: 'Skills' },\n { value: 'plugin', label: 'Plugins' },\n { value: 'mcp', label: 'MCP' },\n]\n\nconst PROVIDER_OPTIONS = ['any', 'claude', 'codex'] as const\ntype Provider = typeof PROVIDER_OPTIONS[number]\n\nfunction kindBadgeClass(kind: ProvisioningAssetKind): string {\n if (kind === 'skill') return 'bg-blue-500/10 text-blue-400 border-blue-500/30'\n if (kind === 'plugin') return 'bg-violet-500/10 text-violet-400 border-violet-500/30'\n return 'bg-emerald-500/10 text-emerald-400 border-emerald-500/30'\n}\n\nfunction providerBadgeClass(provider: Provider): string {\n if (provider === 'claude') return 'bg-amber-500/10 text-amber-400 border-amber-500/30'\n if (provider === 'codex') return 'bg-sky-500/10 text-sky-400 border-sky-500/30'\n return 'bg-zinc-500/10 text-zinc-400 border-zinc-500/30'\n}\n\nfunction approvalBadgeClass(status?: string): string {\n if (status === 'approved') return 'bg-emerald-500/10 text-emerald-400 border-emerald-500/30'\n if (status === 'rejected') return 'bg-red-500/10 text-red-400 border-red-500/30'\n return 'bg-yellow-500/10 text-yellow-400 border-yellow-500/30'\n}\n\nfunction ValidationIcon({ status }: { status?: string }) {\n if (status === 'valid') return <CheckCircle className=\"h-3.5 w-3.5 text-emerald-400\" />\n if (status === 'invalid') return <AlertCircle className=\"h-3.5 w-3.5 text-red-400\" />\n return <Clock className=\"h-3.5 w-3.5 text-zinc-400\" />\n}\n\n// Form state for creating a new capability\ninterface NewCapabilityForm {\n kind: ProvisioningAssetKind\n slug: string\n title: string\n}\n\n// Form state for GitHub import wizard\ninterface ImportGithubForm {\n githubUrl: string\n ref: string\n subpath: string\n provider: Provider\n versionConstraint: string\n}\n\n// Form state for MCP server variant\ninterface ImportMcpForm {\n command: string\n args: string\n url: string\n approvalStatus: string\n versionConstraint: string\n}\n\nconst DEFAULT_NEW_CAP: NewCapabilityForm = { kind: 'skill', slug: '', title: '' }\nconst DEFAULT_IMPORT_GH: ImportGithubForm = { githubUrl: '', ref: 'main', subpath: '', provider: 'any', versionConstraint: '' }\nconst DEFAULT_IMPORT_MCP: ImportMcpForm = { command: '', args: '', url: '', approvalStatus: 'pending', versionConstraint: '' }\n\ntype InlineWizard = 'none' | 'new-capability' | 'import-github' | 'import-mcp'\n\nfunction VariantRow({\n variant,\n onToggle,\n onUpdate,\n onValidate,\n busy,\n}: {\n variant: ProvisioningAsset\n onToggle: (id: string, enabled: boolean) => void\n onUpdate: (id: string) => void\n onValidate: (id: string) => void\n busy: string | null\n}) {\n const isBusy = busy === variant.id\n\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3 space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\" className={`text-[10px] ${providerBadgeClass(variant.provider as Provider)}`}>\n {variant.provider}\n </Badge>\n <span className=\"text-xs font-medium font-mono\">{variant.name}</span>\n {variant.approvalStatus && (\n <Badge variant=\"outline\" className={`text-[10px] ${approvalBadgeClass(variant.approvalStatus)}`}>\n {variant.approvalStatus}\n </Badge>\n )}\n <span className=\"text-[10px] text-muted-foreground flex items-center gap-1 ml-auto\">\n <ValidationIcon status={variant.validationStatus} />\n {variant.validationStatus ?? 'unvalidated'}\n </span>\n <Switch\n size=\"sm\"\n checked={variant.enabled}\n disabled={isBusy}\n onCheckedChange={(v) => onToggle(variant.id, v)}\n />\n </div>\n {(variant.sourceUrl || variant.sourceRef) && (\n <div className=\"text-[10px] text-muted-foreground font-mono truncate\" title={variant.sourceUrl}>\n {variant.sourceUrl}{variant.sourceRef ? `@${variant.resolvedRef ?? variant.sourceRef}` : ''}\n {variant.sourceSubpath ? ` · ${variant.sourceSubpath}` : ''}\n </div>\n )}\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-6 text-xs\"\n disabled={isBusy || !variant.sourceRef}\n onClick={() => onUpdate(variant.id)}\n title=\"Pull latest from source ref\"\n >\n <Download className=\"h-3 w-3 mr-1\" />\n Update ref\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-6 text-xs\"\n disabled={isBusy}\n onClick={() => onValidate(variant.id)}\n >\n <Play className=\"h-3 w-3 mr-1\" />\n Validate\n </Button>\n </div>\n </div>\n )\n}\n\nfunction NewCapabilityForm({\n form,\n onChange,\n onSubmit,\n onCancel,\n busy,\n error,\n}: {\n form: NewCapabilityForm\n onChange: (patch: Partial<NewCapabilityForm>) => void\n onSubmit: () => void\n onCancel: () => void\n busy: boolean\n error: string | null\n}) {\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3 space-y-3\">\n <div className=\"text-sm font-medium\">New Capability</div>\n {error && <div className=\"text-xs text-destructive\">{error}</div>}\n <div>\n <Label className=\"text-xs\">Kind</Label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm\"\n value={form.kind}\n onChange={(e) => onChange({ kind: e.target.value as ProvisioningAssetKind })}\n >\n <option value=\"skill\">Skill</option>\n <option value=\"plugin\">Plugin</option>\n <option value=\"mcp\">MCP Server</option>\n </select>\n </div>\n <div>\n <Label className=\"text-xs\">Slug</Label>\n <Input\n value={form.slug}\n onChange={(e) => onChange({ slug: e.target.value })}\n placeholder=\"my-capability\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div>\n <Label className=\"text-xs\">Title (optional)</Label>\n <Input\n value={form.title}\n onChange={(e) => onChange({ title: e.target.value })}\n placeholder=\"My Capability\"\n className=\"mt-1 text-sm\"\n />\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={onSubmit} disabled={busy || !form.slug.trim()}>\n {busy ? 'Creating…' : 'Create'}\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={onCancel}>Cancel</Button>\n </div>\n </div>\n )\n}\n\nfunction ImportGithubForm({\n form,\n onChange,\n onSubmit,\n onCancel,\n busy,\n error,\n}: {\n form: ImportGithubForm\n onChange: (patch: Partial<ImportGithubForm>) => void\n onSubmit: () => void\n onCancel: () => void\n busy: boolean\n error: string | null\n}) {\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3 space-y-3\">\n <div className=\"text-sm font-medium\">Import from GitHub</div>\n {error && <div className=\"text-xs text-destructive\">{error}</div>}\n <div>\n <Label className=\"text-xs\">GitHub URL</Label>\n <Input\n value={form.githubUrl}\n onChange={(e) => onChange({ githubUrl: e.target.value })}\n placeholder=\"https://github.com/owner/repo\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <Label className=\"text-xs\">Ref</Label>\n <Input\n value={form.ref}\n onChange={(e) => onChange({ ref: e.target.value })}\n placeholder=\"main\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div>\n <Label className=\"text-xs\">Subpath (optional)</Label>\n <Input\n value={form.subpath}\n onChange={(e) => onChange({ subpath: e.target.value })}\n placeholder=\"skills/my-skill\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <Label className=\"text-xs\">Provider</Label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm\"\n value={form.provider}\n onChange={(e) => onChange({ provider: e.target.value as Provider })}\n >\n {PROVIDER_OPTIONS.map((p) => <option key={p} value={p}>{p}</option>)}\n </select>\n </div>\n <div>\n <Label className=\"text-xs\">Version constraint (optional)</Label>\n <Input\n value={form.versionConstraint}\n onChange={(e) => onChange({ versionConstraint: e.target.value })}\n placeholder=\">=1.0.0\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={onSubmit} disabled={busy || !form.githubUrl.trim() || !form.ref.trim()}>\n {busy ? 'Importing…' : 'Import'}\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={onCancel}>Cancel</Button>\n </div>\n </div>\n )\n}\n\nfunction ImportMcpForm({\n form,\n onChange,\n onSubmit,\n onCancel,\n busy,\n error,\n}: {\n form: ImportMcpForm\n onChange: (patch: Partial<ImportMcpForm>) => void\n onSubmit: () => void\n onCancel: () => void\n busy: boolean\n error: string | null\n}) {\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3 space-y-3\">\n <div className=\"text-sm font-medium\">Add MCP Server Variant</div>\n {error && <div className=\"text-xs text-destructive\">{error}</div>}\n <div>\n <Label className=\"text-xs\">Command (for stdio type)</Label>\n <Input\n value={form.command}\n onChange={(e) => onChange({ command: e.target.value })}\n placeholder=\"npx -y @modelcontextprotocol/server-foo\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div>\n <Label className=\"text-xs\">Args (space-separated, overrides command split)</Label>\n <Input\n value={form.args}\n onChange={(e) => onChange({ args: e.target.value })}\n placeholder=\"--port 3000\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div>\n <Label className=\"text-xs\">URL (for http/sse type)</Label>\n <Input\n value={form.url}\n onChange={(e) => onChange({ url: e.target.value })}\n placeholder=\"http://localhost:3000/mcp\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <Label className=\"text-xs\">Approval status</Label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm\"\n value={form.approvalStatus}\n onChange={(e) => onChange({ approvalStatus: e.target.value })}\n >\n <option value=\"pending\">Pending</option>\n <option value=\"approved\">Approved</option>\n </select>\n </div>\n <div>\n <Label className=\"text-xs\">Version constraint (optional)</Label>\n <Input\n value={form.versionConstraint}\n onChange={(e) => onChange({ versionConstraint: e.target.value })}\n placeholder=\">=1.0.0\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={onSubmit} disabled={busy || (!form.command.trim() && !form.url.trim())}>\n {busy ? 'Adding…' : 'Add MCP Variant'}\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={onCancel}>Cancel</Button>\n </div>\n </div>\n )\n}\n\nexport function RegistryView() {\n const [items, setItems] = useState<ProvisioningCapabilityWithVariants[]>([])\n const [kindFilter, setKindFilter] = useState<KindFilter>('all')\n const [selectedId, setSelectedId] = useState<string>('')\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [wizard, setWizard] = useState<InlineWizard>('none')\n const [wizardBusy, setWizardBusy] = useState(false)\n const [wizardError, setWizardError] = useState<string | null>(null)\n const [variantBusy, setVariantBusy] = useState<string | null>(null)\n const [newCap, setNewCap] = useState<NewCapabilityForm>(DEFAULT_NEW_CAP)\n const [importGh, setImportGh] = useState<ImportGithubForm>(DEFAULT_IMPORT_GH)\n const [importMcp, setImportMcp] = useState<ImportMcpForm>(DEFAULT_IMPORT_MCP)\n\n async function load() {\n setError(null)\n try {\n const params = kindFilter !== 'all' ? `?kind=${kindFilter}` : ''\n const res = await api<{ capabilities: ProvisioningCapabilityWithVariants[] }>('GET', `/provisioning/capabilities${params}`)\n setItems(res.capabilities)\n if (!selectedId && res.capabilities.length > 0) {\n setSelectedId(res.capabilities[0]!.capability.id)\n }\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setLoading(false)\n }\n }\n\n // Initial load + kind filter changes\n useEffect(() => {\n setLoading(true)\n void load()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [kindFilter])\n\n const selected = items.find((i) => i.capability.id === selectedId) ?? null\n\n function openWizard(w: InlineWizard) {\n setWizard(w)\n setWizardError(null)\n setWizardBusy(false)\n setNewCap(DEFAULT_NEW_CAP)\n setImportGh(DEFAULT_IMPORT_GH)\n setImportMcp(DEFAULT_IMPORT_MCP)\n }\n\n async function createCapability() {\n setWizardBusy(true)\n setWizardError(null)\n try {\n await api<ProvisioningCapability>('POST', '/provisioning/capabilities', {\n kind: newCap.kind,\n slug: newCap.slug.trim(),\n title: newCap.title.trim() || undefined,\n })\n setWizard('none')\n await load()\n } catch (e) {\n setWizardError(errMessage(e))\n } finally {\n setWizardBusy(false)\n }\n }\n\n async function importFromGithub() {\n if (!selected) return\n setWizardBusy(true)\n setWizardError(null)\n try {\n await api('POST', `/provisioning/capabilities/${encodeURIComponent(selected.capability.id)}/variants/import`, {\n githubUrl: importGh.githubUrl.trim(),\n ref: importGh.ref.trim(),\n subpath: importGh.subpath.trim() || undefined,\n provider: importGh.provider,\n versionConstraint: importGh.versionConstraint.trim() || undefined,\n })\n setWizard('none')\n await load()\n } catch (e) {\n setWizardError(errMessage(e))\n } finally {\n setWizardBusy(false)\n }\n }\n\n async function importMcpServer() {\n if (!selected) return\n setWizardBusy(true)\n setWizardError(null)\n try {\n // Build server spec: command/args or url\n const server: Record<string, unknown> = {}\n if (importMcp.url.trim()) {\n server.type = 'http'\n server.url = importMcp.url.trim()\n } else {\n server.type = 'stdio'\n const parts = importMcp.command.trim().split(/\\s+/)\n server.command = parts[0]\n const extraArgs = importMcp.args.trim() ? importMcp.args.trim().split(/\\s+/) : parts.slice(1)\n if (extraArgs.length > 0) server.args = extraArgs\n }\n await api('POST', `/provisioning/capabilities/${encodeURIComponent(selected.capability.id)}/variants/mcp`, {\n server,\n approvalStatus: importMcp.approvalStatus,\n versionConstraint: importMcp.versionConstraint.trim() || undefined,\n })\n setWizard('none')\n await load()\n } catch (e) {\n setWizardError(errMessage(e))\n } finally {\n setWizardBusy(false)\n }\n }\n\n async function toggleVariant(id: string, enabled: boolean) {\n setVariantBusy(id)\n try {\n await api('PATCH', `/provisioning/variants/${encodeURIComponent(id)}`, { enabled })\n setItems((prev) =>\n prev.map((item) => ({\n ...item,\n variants: item.variants.map((v) => (v.id === id ? { ...v, enabled } : v)),\n }))\n )\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setVariantBusy(null)\n }\n }\n\n async function updateVariantRef(id: string) {\n const variant = selected?.variants.find((v) => v.id === id)\n if (!variant?.sourceRef) return\n setVariantBusy(id)\n try {\n await api('POST', `/provisioning/variants/${encodeURIComponent(id)}/update`, {\n ref: variant.sourceRef,\n subpath: variant.sourceSubpath,\n })\n await load()\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setVariantBusy(null)\n }\n }\n\n async function validateVariant(id: string) {\n setVariantBusy(id)\n try {\n await api('POST', `/provisioning/variants/${encodeURIComponent(id)}/validate`, {})\n await load()\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setVariantBusy(null)\n }\n }\n\n const cap = selected?.capability\n\n return (\n <div className=\"space-y-4 p-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <PackagePlus className=\"size-5 text-primary\" />\n <h1 className=\"text-lg font-semibold\">Registry</h1>\n <span className=\"text-xs text-muted-foreground\">provisioning capability registry · #561</span>\n <div className=\"ml-auto flex items-center gap-2\">\n {KIND_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => setKindFilter(opt.value)}\n className={`rounded-md border px-2.5 py-1 text-xs transition-colors ${kindFilter === opt.value ? 'border-primary/40 bg-primary/10 text-primary' : 'border-border text-muted-foreground hover:bg-accent'}`}\n >\n {opt.label}\n </button>\n ))}\n <Button variant=\"outline\" size=\"sm\" onClick={() => void load()}>\n <RefreshCw className=\"size-4\" />\n </Button>\n </div>\n </div>\n\n {error && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">{error}</div>\n )}\n\n <div className=\"grid grid-cols-1 gap-4 xl:grid-cols-[300px_1fr]\">\n {/* Left pane: capability list */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-muted-foreground font-medium\">{items.length} capabilities</span>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => openWizard('new-capability')}\n >\n <Plus className=\"h-3 w-3\" />\n New\n </Button>\n </div>\n\n {wizard === 'new-capability' && (\n <NewCapabilityForm\n form={newCap}\n onChange={(p) => setNewCap((f) => ({ ...f, ...p }))}\n onSubmit={() => void createCapability()}\n onCancel={() => setWizard('none')}\n busy={wizardBusy}\n error={wizardError}\n />\n )}\n\n {loading && items.length === 0 && (\n <div className=\"py-8 text-center text-sm text-muted-foreground\">Loading…</div>\n )}\n\n {!loading && items.length === 0 && (\n <Card>\n <CardContent className=\"py-10 text-center text-sm text-muted-foreground\">\n No capabilities yet. Click New to create one.\n </CardContent>\n </Card>\n )}\n\n {items.map(({ capability, variants }) => (\n <button\n key={capability.id}\n type=\"button\"\n onClick={() => { setSelectedId(capability.id); setWizard('none') }}\n className={`w-full rounded-md border p-3 text-left transition-colors ${selectedId === capability.id ? 'border-primary/50 bg-primary/5' : 'border-border bg-card/60 hover:bg-accent'}`}\n >\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"outline\" className={`text-[10px] ${kindBadgeClass(capability.kind)}`}>\n {capability.kind}\n </Badge>\n <span className=\"text-xs font-medium font-mono truncate flex-1\">{capability.slug}</span>\n <span className=\"text-[10px] text-muted-foreground shrink-0\">{variants.length}v</span>\n </div>\n {capability.title && (\n <div className=\"mt-1 text-xs text-muted-foreground truncate\">{capability.title}</div>\n )}\n <div className=\"mt-1 flex items-center gap-1.5\">\n <span className={`inline-block h-1.5 w-1.5 rounded-full ${capability.status === 'active' ? 'bg-emerald-500' : 'bg-zinc-500'}`} />\n <span className=\"text-[10px] text-muted-foreground\">{capability.status}</span>\n </div>\n </button>\n ))}\n </div>\n\n {/* Right pane: selected capability detail */}\n {cap ? (\n <div className=\"space-y-3\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\" className={kindBadgeClass(cap.kind)}>{cap.kind}</Badge>\n <span className=\"font-mono text-base\">{cap.slug}</span>\n {cap.title && <span className=\"text-sm font-normal text-muted-foreground\">· {cap.title}</span>}\n <Badge variant={cap.status === 'active' ? 'secondary' : 'outline'} className=\"ml-auto text-[10px]\">\n {cap.status}\n </Badge>\n </CardTitle>\n </CardHeader>\n {cap.description && (\n <CardContent className=\"pt-0 text-sm text-muted-foreground\">{cap.description}</CardContent>\n )}\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n Variants\n <span className=\"text-xs font-normal text-muted-foreground\">({selected?.variants.length ?? 0})</span>\n <div className=\"ml-auto flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => openWizard(wizard === 'import-github' ? 'none' : 'import-github')}\n >\n <Plus className=\"h-3 w-3\" />\n GitHub\n </Button>\n {cap.kind === 'mcp' && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => openWizard(wizard === 'import-mcp' ? 'none' : 'import-mcp')}\n >\n <Plus className=\"h-3 w-3\" />\n MCP Server\n </Button>\n )}\n </div>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {wizard === 'import-github' && (\n <ImportGithubForm\n form={importGh}\n onChange={(p) => setImportGh((f) => ({ ...f, ...p }))}\n onSubmit={() => void importFromGithub()}\n onCancel={() => setWizard('none')}\n busy={wizardBusy}\n error={wizardError}\n />\n )}\n {wizard === 'import-mcp' && (\n <ImportMcpForm\n form={importMcp}\n onChange={(p) => setImportMcp((f) => ({ ...f, ...p }))}\n onSubmit={() => void importMcpServer()}\n onCancel={() => setWizard('none')}\n busy={wizardBusy}\n error={wizardError}\n />\n )}\n {selected && selected.variants.length === 0 && wizard === 'none' && (\n <div className=\"py-6 text-center text-sm text-muted-foreground\">\n No variants yet. Add one via GitHub import{cap.kind === 'mcp' ? ' or MCP Server' : ''}.\n </div>\n )}\n {selected?.variants.map((variant) => (\n <VariantRow\n key={variant.id}\n variant={variant}\n onToggle={(id, enabled) => void toggleVariant(id, enabled)}\n onUpdate={(id) => void updateVariantRef(id)}\n onValidate={(id) => void validateVariant(id)}\n busy={variantBusy}\n />\n ))}\n </CardContent>\n </Card>\n </div>\n ) : (\n !loading && (\n <Card>\n <CardContent className=\"py-16 text-center text-sm text-muted-foreground\">\n Select a capability to view details and variants.\n </CardContent>\n </Card>\n )\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registry-ApGTbK4L.js","names":[],"sources":["../../dashboard/src/components/views/registry.tsx"],"sourcesContent":["import { useEffect, useState } from 'react'\nimport { errMessage } from 'agent-relay-sdk/types'\nimport { api } from '@/lib/api'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { Switch } from '@/components/ui/switch'\nimport { PackagePlus, RefreshCw, Plus, Trash2, CheckCircle, AlertCircle, Clock, Download, Play } from 'lucide-react'\nimport type { ProvisioningAssetKind, ProvisioningCapability, ProvisioningAsset, ProvisioningCapabilityWithVariants } from '@/types'\n\n// Registry view (#561) — browse and manage the provisioning capability registry.\n// Two-pane: left = capability list + filters, right = selected capability detail + variants.\n\ntype KindFilter = 'all' | ProvisioningAssetKind\n\nconst KIND_OPTIONS: Array<{ value: KindFilter; label: string }> = [\n { value: 'all', label: 'All' },\n { value: 'skill', label: 'Skills' },\n { value: 'plugin', label: 'Plugins' },\n { value: 'mcp', label: 'MCP' },\n]\n\nconst PROVIDER_OPTIONS = ['any', 'claude', 'codex'] as const\ntype Provider = typeof PROVIDER_OPTIONS[number]\n\nfunction kindBadgeClass(kind: ProvisioningAssetKind): string {\n if (kind === 'skill') return 'bg-blue-500/10 text-blue-400 border-blue-500/30'\n if (kind === 'plugin') return 'bg-violet-500/10 text-violet-400 border-violet-500/30'\n return 'bg-emerald-500/10 text-emerald-400 border-emerald-500/30'\n}\n\nfunction providerBadgeClass(provider: Provider): string {\n if (provider === 'claude') return 'bg-amber-500/10 text-amber-400 border-amber-500/30'\n if (provider === 'codex') return 'bg-sky-500/10 text-sky-400 border-sky-500/30'\n return 'bg-zinc-500/10 text-zinc-400 border-zinc-500/30'\n}\n\nfunction approvalBadgeClass(status?: string): string {\n if (status === 'approved') return 'bg-emerald-500/10 text-emerald-400 border-emerald-500/30'\n if (status === 'rejected') return 'bg-red-500/10 text-red-400 border-red-500/30'\n return 'bg-yellow-500/10 text-yellow-400 border-yellow-500/30'\n}\n\nfunction ValidationIcon({ status }: { status?: string }) {\n if (status === 'valid') return <CheckCircle className=\"h-3.5 w-3.5 text-emerald-400\" />\n if (status === 'invalid') return <AlertCircle className=\"h-3.5 w-3.5 text-red-400\" />\n return <Clock className=\"h-3.5 w-3.5 text-zinc-400\" />\n}\n\n// Form state for creating a new capability\ninterface NewCapabilityForm {\n kind: ProvisioningAssetKind\n slug: string\n title: string\n}\n\n// Form state for GitHub import wizard\ninterface ImportGithubForm {\n githubUrl: string\n ref: string\n subpath: string\n provider: Provider\n versionConstraint: string\n}\n\n// Form state for MCP server variant\ninterface ImportMcpForm {\n command: string\n args: string\n url: string\n approvalStatus: string\n versionConstraint: string\n}\n\nconst DEFAULT_NEW_CAP: NewCapabilityForm = { kind: 'skill', slug: '', title: '' }\nconst DEFAULT_IMPORT_GH: ImportGithubForm = { githubUrl: '', ref: 'main', subpath: '', provider: 'any', versionConstraint: '' }\nconst DEFAULT_IMPORT_MCP: ImportMcpForm = { command: '', args: '', url: '', approvalStatus: 'pending', versionConstraint: '' }\n\ntype InlineWizard = 'none' | 'new-capability' | 'import-github' | 'import-mcp'\n\nfunction VariantRow({\n variant,\n onToggle,\n onUpdate,\n onValidate,\n busy,\n}: {\n variant: ProvisioningAsset\n onToggle: (id: string, enabled: boolean) => void\n onUpdate: (id: string) => void\n onValidate: (id: string) => void\n busy: string | null\n}) {\n const isBusy = busy === variant.id\n\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3 space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\" className={`text-[10px] ${providerBadgeClass(variant.provider as Provider)}`}>\n {variant.provider}\n </Badge>\n <span className=\"text-xs font-medium font-mono\">{variant.name}</span>\n {variant.approvalStatus && (\n <Badge variant=\"outline\" className={`text-[10px] ${approvalBadgeClass(variant.approvalStatus)}`}>\n {variant.approvalStatus}\n </Badge>\n )}\n <span className=\"text-[10px] text-muted-foreground flex items-center gap-1 ml-auto\">\n <ValidationIcon status={variant.validationStatus} />\n {variant.validationStatus ?? 'unvalidated'}\n </span>\n <Switch\n size=\"sm\"\n checked={variant.enabled}\n disabled={isBusy}\n onCheckedChange={(v) => onToggle(variant.id, v)}\n />\n </div>\n {(variant.sourceUrl || variant.sourceRef) && (\n <div className=\"text-[10px] text-muted-foreground font-mono truncate\" title={variant.sourceUrl}>\n {variant.sourceUrl}{variant.sourceRef ? `@${variant.resolvedRef ?? variant.sourceRef}` : ''}\n {variant.sourceSubpath ? ` · ${variant.sourceSubpath}` : ''}\n </div>\n )}\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-6 text-xs\"\n disabled={isBusy || !variant.sourceRef}\n onClick={() => onUpdate(variant.id)}\n title=\"Pull latest from source ref\"\n >\n <Download className=\"h-3 w-3 mr-1\" />\n Update ref\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-6 text-xs\"\n disabled={isBusy}\n onClick={() => onValidate(variant.id)}\n >\n <Play className=\"h-3 w-3 mr-1\" />\n Validate\n </Button>\n </div>\n </div>\n )\n}\n\nfunction NewCapabilityForm({\n form,\n onChange,\n onSubmit,\n onCancel,\n busy,\n error,\n}: {\n form: NewCapabilityForm\n onChange: (patch: Partial<NewCapabilityForm>) => void\n onSubmit: () => void\n onCancel: () => void\n busy: boolean\n error: string | null\n}) {\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3 space-y-3\">\n <div className=\"text-sm font-medium\">New Capability</div>\n {error && <div className=\"text-xs text-destructive\">{error}</div>}\n <div>\n <Label className=\"text-xs\">Kind</Label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm\"\n value={form.kind}\n onChange={(e) => onChange({ kind: e.target.value as ProvisioningAssetKind })}\n >\n <option value=\"skill\">Skill</option>\n <option value=\"plugin\">Plugin</option>\n <option value=\"mcp\">MCP Server</option>\n </select>\n </div>\n <div>\n <Label className=\"text-xs\">Slug</Label>\n <Input\n value={form.slug}\n onChange={(e) => onChange({ slug: e.target.value })}\n placeholder=\"my-capability\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div>\n <Label className=\"text-xs\">Title (optional)</Label>\n <Input\n value={form.title}\n onChange={(e) => onChange({ title: e.target.value })}\n placeholder=\"My Capability\"\n className=\"mt-1 text-sm\"\n />\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={onSubmit} disabled={busy || !form.slug.trim()}>\n {busy ? 'Creating…' : 'Create'}\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={onCancel}>Cancel</Button>\n </div>\n </div>\n )\n}\n\nfunction ImportGithubForm({\n form,\n onChange,\n onSubmit,\n onCancel,\n busy,\n error,\n}: {\n form: ImportGithubForm\n onChange: (patch: Partial<ImportGithubForm>) => void\n onSubmit: () => void\n onCancel: () => void\n busy: boolean\n error: string | null\n}) {\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3 space-y-3\">\n <div className=\"text-sm font-medium\">Import from GitHub</div>\n {error && <div className=\"text-xs text-destructive\">{error}</div>}\n <div>\n <Label className=\"text-xs\">GitHub URL</Label>\n <Input\n value={form.githubUrl}\n onChange={(e) => onChange({ githubUrl: e.target.value })}\n placeholder=\"https://github.com/owner/repo\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <Label className=\"text-xs\">Ref</Label>\n <Input\n value={form.ref}\n onChange={(e) => onChange({ ref: e.target.value })}\n placeholder=\"main\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div>\n <Label className=\"text-xs\">Subpath (optional)</Label>\n <Input\n value={form.subpath}\n onChange={(e) => onChange({ subpath: e.target.value })}\n placeholder=\"skills/my-skill\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <Label className=\"text-xs\">Provider</Label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm\"\n value={form.provider}\n onChange={(e) => onChange({ provider: e.target.value as Provider })}\n >\n {PROVIDER_OPTIONS.map((p) => <option key={p} value={p}>{p}</option>)}\n </select>\n </div>\n <div>\n <Label className=\"text-xs\">Version constraint (optional)</Label>\n <Input\n value={form.versionConstraint}\n onChange={(e) => onChange({ versionConstraint: e.target.value })}\n placeholder=\">=1.0.0\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={onSubmit} disabled={busy || !form.githubUrl.trim() || !form.ref.trim()}>\n {busy ? 'Importing…' : 'Import'}\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={onCancel}>Cancel</Button>\n </div>\n </div>\n )\n}\n\nfunction ImportMcpForm({\n form,\n onChange,\n onSubmit,\n onCancel,\n busy,\n error,\n}: {\n form: ImportMcpForm\n onChange: (patch: Partial<ImportMcpForm>) => void\n onSubmit: () => void\n onCancel: () => void\n busy: boolean\n error: string | null\n}) {\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3 space-y-3\">\n <div className=\"text-sm font-medium\">Add MCP Server Variant</div>\n {error && <div className=\"text-xs text-destructive\">{error}</div>}\n <div>\n <Label className=\"text-xs\">Command (for stdio type)</Label>\n <Input\n value={form.command}\n onChange={(e) => onChange({ command: e.target.value })}\n placeholder=\"npx -y @modelcontextprotocol/server-foo\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div>\n <Label className=\"text-xs\">Args (space-separated, overrides command split)</Label>\n <Input\n value={form.args}\n onChange={(e) => onChange({ args: e.target.value })}\n placeholder=\"--port 3000\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div>\n <Label className=\"text-xs\">URL (for http/sse type)</Label>\n <Input\n value={form.url}\n onChange={(e) => onChange({ url: e.target.value })}\n placeholder=\"http://localhost:3000/mcp\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-2\">\n <div>\n <Label className=\"text-xs\">Approval status</Label>\n <select\n className=\"mt-1 w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm\"\n value={form.approvalStatus}\n onChange={(e) => onChange({ approvalStatus: e.target.value })}\n >\n <option value=\"pending\">Pending</option>\n <option value=\"approved\">Approved</option>\n </select>\n </div>\n <div>\n <Label className=\"text-xs\">Version constraint (optional)</Label>\n <Input\n value={form.versionConstraint}\n onChange={(e) => onChange({ versionConstraint: e.target.value })}\n placeholder=\">=1.0.0\"\n className=\"mt-1 text-sm font-mono\"\n />\n </div>\n </div>\n <div className=\"flex gap-2\">\n <Button size=\"sm\" onClick={onSubmit} disabled={busy || (!form.command.trim() && !form.url.trim())}>\n {busy ? 'Adding…' : 'Add MCP Variant'}\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={onCancel}>Cancel</Button>\n </div>\n </div>\n )\n}\n\nexport function RegistryView() {\n const [items, setItems] = useState<ProvisioningCapabilityWithVariants[]>([])\n const [kindFilter, setKindFilter] = useState<KindFilter>('all')\n const [selectedId, setSelectedId] = useState<string>('')\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [wizard, setWizard] = useState<InlineWizard>('none')\n const [wizardBusy, setWizardBusy] = useState(false)\n const [wizardError, setWizardError] = useState<string | null>(null)\n const [variantBusy, setVariantBusy] = useState<string | null>(null)\n const [newCap, setNewCap] = useState<NewCapabilityForm>(DEFAULT_NEW_CAP)\n const [importGh, setImportGh] = useState<ImportGithubForm>(DEFAULT_IMPORT_GH)\n const [importMcp, setImportMcp] = useState<ImportMcpForm>(DEFAULT_IMPORT_MCP)\n\n async function load() {\n setError(null)\n try {\n const params = kindFilter !== 'all' ? `?kind=${kindFilter}` : ''\n const res = await api<{ capabilities: ProvisioningCapabilityWithVariants[] }>('GET', `/provisioning/capabilities${params}`)\n setItems(res.capabilities)\n if (!selectedId && res.capabilities.length > 0) {\n setSelectedId(res.capabilities[0]!.capability.id)\n }\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setLoading(false)\n }\n }\n\n // Initial load + kind filter changes\n useEffect(() => {\n setLoading(true)\n void load()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [kindFilter])\n\n const selected = items.find((i) => i.capability.id === selectedId) ?? null\n\n function openWizard(w: InlineWizard) {\n setWizard(w)\n setWizardError(null)\n setWizardBusy(false)\n setNewCap(DEFAULT_NEW_CAP)\n setImportGh(DEFAULT_IMPORT_GH)\n setImportMcp(DEFAULT_IMPORT_MCP)\n }\n\n async function createCapability() {\n setWizardBusy(true)\n setWizardError(null)\n try {\n await api<ProvisioningCapability>('POST', '/provisioning/capabilities', {\n kind: newCap.kind,\n slug: newCap.slug.trim(),\n title: newCap.title.trim() || undefined,\n })\n setWizard('none')\n await load()\n } catch (e) {\n setWizardError(errMessage(e))\n } finally {\n setWizardBusy(false)\n }\n }\n\n async function importFromGithub() {\n if (!selected) return\n setWizardBusy(true)\n setWizardError(null)\n try {\n await api('POST', `/provisioning/capabilities/${encodeURIComponent(selected.capability.id)}/variants/import`, {\n githubUrl: importGh.githubUrl.trim(),\n ref: importGh.ref.trim(),\n subpath: importGh.subpath.trim() || undefined,\n provider: importGh.provider,\n versionConstraint: importGh.versionConstraint.trim() || undefined,\n })\n setWizard('none')\n await load()\n } catch (e) {\n setWizardError(errMessage(e))\n } finally {\n setWizardBusy(false)\n }\n }\n\n async function importMcpServer() {\n if (!selected) return\n setWizardBusy(true)\n setWizardError(null)\n try {\n // Build server spec: command/args or url\n const server: Record<string, unknown> = {}\n if (importMcp.url.trim()) {\n server.type = 'http'\n server.url = importMcp.url.trim()\n } else {\n server.type = 'stdio'\n const parts = importMcp.command.trim().split(/\\s+/)\n server.command = parts[0]\n const extraArgs = importMcp.args.trim() ? importMcp.args.trim().split(/\\s+/) : parts.slice(1)\n if (extraArgs.length > 0) server.args = extraArgs\n }\n await api('POST', `/provisioning/capabilities/${encodeURIComponent(selected.capability.id)}/variants/mcp`, {\n server,\n approvalStatus: importMcp.approvalStatus,\n versionConstraint: importMcp.versionConstraint.trim() || undefined,\n })\n setWizard('none')\n await load()\n } catch (e) {\n setWizardError(errMessage(e))\n } finally {\n setWizardBusy(false)\n }\n }\n\n async function toggleVariant(id: string, enabled: boolean) {\n setVariantBusy(id)\n try {\n await api('PATCH', `/provisioning/variants/${encodeURIComponent(id)}`, { enabled })\n setItems((prev) =>\n prev.map((item) => ({\n ...item,\n variants: item.variants.map((v) => (v.id === id ? { ...v, enabled } : v)),\n }))\n )\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setVariantBusy(null)\n }\n }\n\n async function updateVariantRef(id: string) {\n const variant = selected?.variants.find((v) => v.id === id)\n if (!variant?.sourceRef) return\n setVariantBusy(id)\n try {\n await api('POST', `/provisioning/variants/${encodeURIComponent(id)}/update`, {\n ref: variant.sourceRef,\n subpath: variant.sourceSubpath,\n })\n await load()\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setVariantBusy(null)\n }\n }\n\n async function validateVariant(id: string) {\n setVariantBusy(id)\n try {\n await api('POST', `/provisioning/variants/${encodeURIComponent(id)}/validate`, {})\n await load()\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setVariantBusy(null)\n }\n }\n\n const cap = selected?.capability\n\n return (\n <div className=\"space-y-4 p-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <PackagePlus className=\"size-5 text-primary\" />\n <h1 className=\"text-lg font-semibold\">Registry</h1>\n <span className=\"text-xs text-muted-foreground\">provisioning capability registry · #561</span>\n <div className=\"ml-auto flex items-center gap-2\">\n {KIND_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => setKindFilter(opt.value)}\n className={`rounded-md border px-2.5 py-1 text-xs transition-colors ${kindFilter === opt.value ? 'border-primary/40 bg-primary/10 text-primary' : 'border-border text-muted-foreground hover:bg-accent'}`}\n >\n {opt.label}\n </button>\n ))}\n <Button variant=\"outline\" size=\"sm\" onClick={() => void load()}>\n <RefreshCw className=\"size-4\" />\n </Button>\n </div>\n </div>\n\n {error && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">{error}</div>\n )}\n\n <div className=\"grid grid-cols-1 gap-4 xl:grid-cols-[300px_1fr]\">\n {/* Left pane: capability list */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-muted-foreground font-medium\">{items.length} capabilities</span>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => openWizard('new-capability')}\n >\n <Plus className=\"h-3 w-3\" />\n New\n </Button>\n </div>\n\n {wizard === 'new-capability' && (\n <NewCapabilityForm\n form={newCap}\n onChange={(p) => setNewCap((f) => ({ ...f, ...p }))}\n onSubmit={() => void createCapability()}\n onCancel={() => setWizard('none')}\n busy={wizardBusy}\n error={wizardError}\n />\n )}\n\n {loading && items.length === 0 && (\n <div className=\"py-8 text-center text-sm text-muted-foreground\">Loading…</div>\n )}\n\n {!loading && items.length === 0 && (\n <Card>\n <CardContent className=\"py-10 text-center text-sm text-muted-foreground\">\n No capabilities yet. Click New to create one.\n </CardContent>\n </Card>\n )}\n\n {items.map(({ capability, variants }) => (\n <button\n key={capability.id}\n type=\"button\"\n onClick={() => { setSelectedId(capability.id); setWizard('none') }}\n className={`w-full rounded-md border p-3 text-left transition-colors ${selectedId === capability.id ? 'border-primary/50 bg-primary/5' : 'border-border bg-card/60 hover:bg-accent'}`}\n >\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"outline\" className={`text-[10px] ${kindBadgeClass(capability.kind)}`}>\n {capability.kind}\n </Badge>\n <span className=\"text-xs font-medium font-mono truncate flex-1\">{capability.slug}</span>\n <span className=\"text-[10px] text-muted-foreground shrink-0\">{variants.length}v</span>\n </div>\n {capability.title && (\n <div className=\"mt-1 text-xs text-muted-foreground truncate\">{capability.title}</div>\n )}\n <div className=\"mt-1 flex items-center gap-1.5\">\n <span className={`inline-block h-1.5 w-1.5 rounded-full ${capability.status === 'active' ? 'bg-emerald-500' : 'bg-zinc-500'}`} />\n <span className=\"text-[10px] text-muted-foreground\">{capability.status}</span>\n </div>\n </button>\n ))}\n </div>\n\n {/* Right pane: selected capability detail */}\n {cap ? (\n <div className=\"space-y-3\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\" className={kindBadgeClass(cap.kind)}>{cap.kind}</Badge>\n <span className=\"font-mono text-base\">{cap.slug}</span>\n {cap.title && <span className=\"text-sm font-normal text-muted-foreground\">· {cap.title}</span>}\n <Badge variant={cap.status === 'active' ? 'secondary' : 'outline'} className=\"ml-auto text-[10px]\">\n {cap.status}\n </Badge>\n </CardTitle>\n </CardHeader>\n {cap.description && (\n <CardContent className=\"pt-0 text-sm text-muted-foreground\">{cap.description}</CardContent>\n )}\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n Variants\n <span className=\"text-xs font-normal text-muted-foreground\">({selected?.variants.length ?? 0})</span>\n <div className=\"ml-auto flex items-center gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => openWizard(wizard === 'import-github' ? 'none' : 'import-github')}\n >\n <Plus className=\"h-3 w-3\" />\n GitHub\n </Button>\n {cap.kind === 'mcp' && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs gap-1\"\n onClick={() => openWizard(wizard === 'import-mcp' ? 'none' : 'import-mcp')}\n >\n <Plus className=\"h-3 w-3\" />\n MCP Server\n </Button>\n )}\n </div>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {wizard === 'import-github' && (\n <ImportGithubForm\n form={importGh}\n onChange={(p) => setImportGh((f) => ({ ...f, ...p }))}\n onSubmit={() => void importFromGithub()}\n onCancel={() => setWizard('none')}\n busy={wizardBusy}\n error={wizardError}\n />\n )}\n {wizard === 'import-mcp' && (\n <ImportMcpForm\n form={importMcp}\n onChange={(p) => setImportMcp((f) => ({ ...f, ...p }))}\n onSubmit={() => void importMcpServer()}\n onCancel={() => setWizard('none')}\n busy={wizardBusy}\n error={wizardError}\n />\n )}\n {selected && selected.variants.length === 0 && wizard === 'none' && (\n <div className=\"py-6 text-center text-sm text-muted-foreground\">\n No variants yet. Add one via GitHub import{cap.kind === 'mcp' ? ' or MCP Server' : ''}.\n </div>\n )}\n {selected?.variants.map((variant) => (\n <VariantRow\n key={variant.id}\n variant={variant}\n onToggle={(id, enabled) => void toggleVariant(id, enabled)}\n onUpdate={(id) => void updateVariantRef(id)}\n onValidate={(id) => void validateVariant(id)}\n busy={variantBusy}\n />\n ))}\n </CardContent>\n </Card>\n </div>\n ) : (\n !loading && (\n <Card>\n <CardContent className=\"py-16 text-center text-sm text-muted-foreground\">\n Select a capability to view details and variants.\n </CardContent>\n </Card>\n )\n )}\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,A as n,B as r,C as i,N as a,Qn as o,dr as s,h as c,xt as l}from"./lucide-react-BYZuAhQs.js";import{t as u}from"./badge-BLar6FjP.js";import{t as d}from"./button-BrIB69qd.js";import{t as f}from"./input-B_fUHtLD.js";import{t as p}from"./copy-button-Cd-LbSbg.js";import{r as m}from"./index-D3woTUwp.js";import{a as h,o as g,r as _,t as v}from"./card-lhnFnBoz.js";var y=e(s(),1),b=o(),x=[`admin:*`,`token:read`,`token:write`,`agent:read`,`agent:write`,`message:read`,`message:send`,`task:read`,`task:write`,`command:read`,`command:write`,`memory:read`,`memory:write`,`memory:admin`,`mcp:use`,`terminal:attach`,`logs:read`,`integration:read`,`integration:write`,`channel:read`,`channel:write`,`stats:read`,`health:read`,`events:read`],S={agents:``,policies:``,targets:``,channels:``,orchestrators:``,cwdPrefixes:``,memoryScopes:``,spawnRequestIds:``,terminalAttach:!1,logsRead:!1},C={id:``,name:``,description:``,role:`provider`,scope:[`agent:read`,`message:read`,`message:send`],ttlSeconds:`86400`,constraints:{...S}};function w(){let[e,o]=(0,y.useState)([]),[s,w]=(0,y.useState)([]),[k,j]=(0,y.useState)(``),[M,F]=(0,y.useState)(C),[I,L]=(0,y.useState)(``),[R,z]=(0,y.useState)(``),[B,V]=(0,y.useState)({...S}),[H,U]=(0,y.useState)(``),[W,G]=(0,y.useState)(``),[K,q]=(0,y.useState)(`profiles`),J=(0,y.useMemo)(()=>e.find(e=>e.id===k),[e,k]);(0,y.useEffect)(()=>{Y()},[]);async function Y(){let[e,n]=await Promise.all([t(`GET`,`/token-profiles`),t(`GET`,`/tokens`)]);o(e),w(n),!k&&e[0]&&(j(e[0].id),F(D(e[0])),L(e[0].id))}function X(e){j(e.id),F(D(e)),U(``)}function Z(){j(``),F({...C,constraints:{...S}}),G(``)}async function Q(){let e=O(M),n=k?await t(`PATCH`,`/token-profiles/${encodeURIComponent(k)}`,e):await t(`POST`,`/token-profiles`,e);await Y(),j(n.id),F(D(n)),L(n.id),G(`${n.name} saved`)}async function $(e){await t(`DELETE`,`/token-profiles/${encodeURIComponent(e.id)}`),Z(),await Y()}async function ee(){let n=e.find(e=>e.id===I);U((await t(`POST`,`/tokens`,{profileId:I,sub:R||n?.role||`component`,constraints:A(B),createdBy:`dashboard`})).token),z(``),V({...S}),await Y()}async function te(e){await t(`POST`,`/tokens/${encodeURIComponent(e.jti)}/revoke`),await Y()}return(0,b.jsxs)(`div`,{className:`space-y-4`,children:[(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Security`}),(0,b.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Token profiles and scoped component tokens`})]}),(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsxs)(`div`,{className:`inline-flex rounded-md border border-border overflow-hidden`,children:[(0,b.jsxs)(`button`,{type:`button`,onClick:()=>q(`profiles`),className:`flex items-center gap-1.5 px-3 py-1.5 text-sm transition-colors ${K===`profiles`?`bg-primary/15 text-primary`:`text-muted-foreground hover:bg-accent`}`,children:[(0,b.jsx)(i,{className:`h-3.5 w-3.5`}),`Profiles`]}),(0,b.jsxs)(`button`,{type:`button`,onClick:()=>q(`tokens`),className:`flex items-center gap-1.5 px-3 py-1.5 text-sm border-l border-border transition-colors ${K===`tokens`?`bg-primary/15 text-primary`:`text-muted-foreground hover:bg-accent`}`,children:[(0,b.jsx)(l,{className:`h-3.5 w-3.5`}),`Tokens`]})]}),(0,b.jsxs)(d,{variant:`outline`,onClick:()=>void Y(),children:[(0,b.jsx)(a,{className:`h-4 w-4`}),`Refresh`]}),K===`profiles`&&(0,b.jsxs)(d,{onClick:Z,children:[(0,b.jsx)(r,{className:`h-4 w-4`}),`New profile`]})]})]}),K===`profiles`&&(0,b.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[340px_minmax(0,1fr)]`,children:[(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsxs)(g,{className:`flex items-center gap-2 text-sm`,children:[(0,b.jsx)(i,{className:`h-4 w-4`}),`Profiles`]})}),(0,b.jsx)(_,{className:`space-y-2`,children:e.map(e=>(0,b.jsxs)(`button`,{type:`button`,onClick:()=>X(e),className:`w-full rounded-md border px-3 py-2 text-left transition-colors ${e.id===k?`border-primary bg-primary/10`:`border-border hover:bg-accent`}`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-sm font-medium`,children:e.name}),e.builtIn&&(0,b.jsx)(u,{variant:`secondary`,className:`text-[10px]`,children:`built-in`})]}),(0,b.jsxs)(`div`,{className:`mt-1 flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,b.jsx)(`span`,{children:e.role}),(0,b.jsxs)(`span`,{children:[e.scope.length,` scopes`]}),e.ttlSeconds&&(0,b.jsx)(`span`,{children:P(e.ttlSeconds)})]})]},e.id))})]}),(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsx)(g,{className:`text-sm`,children:J?J.name:`New profile`})}),(0,b.jsxs)(_,{className:`space-y-4`,children:[(0,b.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[(0,b.jsx)(T,{label:`Profile id`,children:(0,b.jsx)(f,{disabled:!!k,value:M.id,onChange:e=>F({...M,id:e.target.value})})}),(0,b.jsx)(T,{label:`Name`,children:(0,b.jsx)(f,{value:M.name,onChange:e=>F({...M,name:e.target.value})})}),(0,b.jsx)(T,{label:`Role`,children:(0,b.jsx)(f,{value:M.role,onChange:e=>F({...M,role:e.target.value})})}),(0,b.jsx)(T,{label:`TTL seconds`,children:(0,b.jsx)(f,{inputMode:`numeric`,value:M.ttlSeconds,onChange:e=>F({...M,ttlSeconds:e.target.value})})})]}),(0,b.jsx)(T,{label:`Description`,children:(0,b.jsx)(m,{rows:2,value:M.description,onChange:e=>F({...M,description:e.target.value})})}),(0,b.jsxs)(`div`,{className:`space-y-2`,children:[(0,b.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Scopes`}),(0,b.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:x.map(e=>(0,b.jsx)(`button`,{type:`button`,onClick:()=>F({...M,scope:N(M.scope,e)}),className:`rounded border px-2 py-1 text-xs ${M.scope.includes(e)?`border-primary/50 bg-primary/15 text-primary`:`border-border text-muted-foreground hover:bg-accent`}`,children:e},e))})]}),(0,b.jsx)(E,{value:M.constraints,onChange:e=>F({...M,constraints:e})}),(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,b.jsxs)(d,{disabled:J?.builtIn,onClick:()=>void Q(),children:[(0,b.jsx)(n,{className:`h-4 w-4`}),`Save`]}),J&&!J.builtIn&&(0,b.jsxs)(d,{variant:`destructive`,onClick:()=>void $(J),children:[(0,b.jsx)(c,{className:`h-4 w-4`}),`Delete`]}),J?.builtIn&&(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Built-in profiles are managed by Relay.`})]})]})]})]}),K===`tokens`&&(0,b.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[380px_minmax(0,1fr)]`,children:[(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsxs)(g,{className:`flex items-center gap-2 text-sm`,children:[(0,b.jsx)(l,{className:`h-4 w-4`}),`Issue token`]})}),(0,b.jsxs)(_,{className:`space-y-3`,children:[(0,b.jsx)(T,{label:`Profile`,children:(0,b.jsx)(`select`,{className:`h-9 w-full rounded-md border border-input bg-background px-3 text-sm`,value:I,onChange:e=>L(e.target.value),children:e.map(e=>(0,b.jsx)(`option`,{value:e.id,children:e.name},e.id))})}),(0,b.jsx)(T,{label:`Subject`,children:(0,b.jsx)(f,{value:R,onChange:e=>z(e.target.value),placeholder:`component id`})}),(0,b.jsx)(E,{compact:!0,value:B,onChange:V}),(0,b.jsxs)(d,{className:`w-full`,disabled:!I,onClick:()=>void ee(),children:[(0,b.jsx)(l,{className:`h-4 w-4`}),`Issue`]}),H&&(0,b.jsxs)(`div`,{className:`rounded-md border border-border bg-muted/30 p-2`,children:[(0,b.jsxs)(`div`,{className:`mb-1 flex items-center justify-between gap-2`,children:[(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`New token`}),(0,b.jsx)(p,{value:H,label:`Copy token`,size:`sm`,variant:`ghost`,onCopied:()=>G(`Copied`)})]}),(0,b.jsx)(`code`,{className:`block max-h-24 overflow-auto break-all text-xs`,children:H})]}),W&&(0,b.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:W})]})]}),(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsx)(g,{className:`text-sm`,children:`Issued tokens`})}),(0,b.jsxs)(_,{className:`space-y-2`,children:[s.length===0&&(0,b.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`No tokens issued yet`}),s.slice(0,20).map(e=>(0,b.jsxs)(`div`,{className:`rounded-md border border-border p-2`,children:[(0,b.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.sub}),(0,b.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[e.role,` `,e.profileId?`· ${e.profileId}`:``]})]}),e.revokedAt?(0,b.jsx)(u,{variant:`destructive`,children:`revoked`}):(0,b.jsx)(d,{variant:`ghost`,size:`sm`,onClick:()=>void te(e),children:(0,b.jsx)(c,{className:`h-3.5 w-3.5`})})]}),(0,b.jsxs)(`div`,{className:`mt-1 flex flex-wrap gap-1`,children:[e.scope.slice(0,4).map(e=>(0,b.jsx)(u,{variant:`outline`,className:`text-[10px]`,children:e},e)),e.scope.length>4&&(0,b.jsxs)(u,{variant:`secondary`,className:`text-[10px]`,children:[`+`,e.scope.length-4]})]})]},e.jti))]})]})]})]})}function T({label:e,children:t}){return(0,b.jsxs)(`label`,{className:`block space-y-1.5 text-sm`,children:[(0,b.jsx)(`span`,{className:`text-muted-foreground`,children:e}),t]})}function E({value:e,onChange:t,compact:n=!1}){return(0,b.jsxs)(`div`,{className:`space-y-3`,children:[!n&&(0,b.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Constraints`}),(0,b.jsx)(`div`,{className:`grid gap-3 ${n?``:`md:grid-cols-2`}`,children:[[`agents`,`Agents`],[`policies`,`Policies`],[`targets`,`Targets`],[`channels`,`Channels`],[`orchestrators`,`Orchestrators`],[`cwdPrefixes`,`CWD prefixes`],[`memoryScopes`,`Memory scopes`],[`spawnRequestIds`,`Spawn requests`]].map(([r,i])=>(0,b.jsx)(T,{label:i,children:(0,b.jsx)(m,{rows:n?2:3,value:String(e[r]||``),onChange:n=>t({...e,[r]:n.target.value}),placeholder:`one per line`})},r))}),(0,b.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,b.jsxs)(`label`,{className:`flex items-center gap-2 rounded border border-border px-2 py-1 text-xs`,children:[(0,b.jsx)(`input`,{type:`checkbox`,checked:e.terminalAttach,onChange:n=>t({...e,terminalAttach:n.target.checked})}),`Terminal attach`]}),(0,b.jsxs)(`label`,{className:`flex items-center gap-2 rounded border border-border px-2 py-1 text-xs`,children:[(0,b.jsx)(`input`,{type:`checkbox`,checked:e.logsRead,onChange:n=>t({...e,logsRead:n.target.checked})}),`Log read`]})]})]})}function D(e){return{id:e.id,name:e.name,description:e.description||``,role:e.role,scope:e.scope,ttlSeconds:e.ttlSeconds?String(e.ttlSeconds):``,constraints:k(e.constraints)}}function O(e){return{id:e.id||void 0,name:e.name,description:e.description||void 0,role:e.role,scope:e.scope,ttlSeconds:e.ttlSeconds?Number(e.ttlSeconds):void 0,constraints:A(e.constraints)}}function k(e){return{agents:M(e?.agents),policies:M(e?.policies),targets:M(e?.targets),channels:M(e?.channels),orchestrators:M(e?.orchestrators),cwdPrefixes:M(e?.cwdPrefixes),memoryScopes:M(e?.memoryScopes),spawnRequestIds:M(e?.spawnRequestIds),terminalAttach:e?.terminalAttach===!0,logsRead:e?.logsRead===!0}}function A(e){let t={};for(let n of[`agents`,`policies`,`targets`,`channels`,`orchestrators`,`cwdPrefixes`,`memoryScopes`,`spawnRequestIds`]){let r=j(String(e[n]||``));r.length&&Object.assign(t,{[n]:r})}return e.terminalAttach&&(t.terminalAttach=!0),e.logsRead&&(t.logsRead=!0),Object.keys(t).length?t:void 0}function j(e){return e.split(/\r?\n|,/).map(e=>e.trim()).filter(Boolean)}function M(e){return(e??[]).join(`
|
|
1
|
+
import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,A as n,B as r,C as i,N as a,Qn as o,dr as s,h as c,xt as l}from"./lucide-react-BYZuAhQs.js";import{t as u}from"./badge-BLar6FjP.js";import{t as d}from"./button-BrIB69qd.js";import{t as f}from"./input-B_fUHtLD.js";import{t as p}from"./copy-button-Cd-LbSbg.js";import{r as m}from"./index-DOWwt3I7.js";import{a as h,o as g,r as _,t as v}from"./card-lhnFnBoz.js";var y=e(s(),1),b=o(),x=[`admin:*`,`token:read`,`token:write`,`agent:read`,`agent:write`,`message:read`,`message:send`,`task:read`,`task:write`,`command:read`,`command:write`,`memory:read`,`memory:write`,`memory:admin`,`mcp:use`,`terminal:attach`,`logs:read`,`integration:read`,`integration:write`,`channel:read`,`channel:write`,`stats:read`,`health:read`,`events:read`],S={agents:``,policies:``,targets:``,channels:``,orchestrators:``,cwdPrefixes:``,memoryScopes:``,spawnRequestIds:``,terminalAttach:!1,logsRead:!1},C={id:``,name:``,description:``,role:`provider`,scope:[`agent:read`,`message:read`,`message:send`],ttlSeconds:`86400`,constraints:{...S}};function w(){let[e,o]=(0,y.useState)([]),[s,w]=(0,y.useState)([]),[k,j]=(0,y.useState)(``),[M,F]=(0,y.useState)(C),[I,L]=(0,y.useState)(``),[R,z]=(0,y.useState)(``),[B,V]=(0,y.useState)({...S}),[H,U]=(0,y.useState)(``),[W,G]=(0,y.useState)(``),[K,q]=(0,y.useState)(`profiles`),J=(0,y.useMemo)(()=>e.find(e=>e.id===k),[e,k]);(0,y.useEffect)(()=>{Y()},[]);async function Y(){let[e,n]=await Promise.all([t(`GET`,`/token-profiles`),t(`GET`,`/tokens`)]);o(e),w(n),!k&&e[0]&&(j(e[0].id),F(D(e[0])),L(e[0].id))}function X(e){j(e.id),F(D(e)),U(``)}function Z(){j(``),F({...C,constraints:{...S}}),G(``)}async function Q(){let e=O(M),n=k?await t(`PATCH`,`/token-profiles/${encodeURIComponent(k)}`,e):await t(`POST`,`/token-profiles`,e);await Y(),j(n.id),F(D(n)),L(n.id),G(`${n.name} saved`)}async function $(e){await t(`DELETE`,`/token-profiles/${encodeURIComponent(e.id)}`),Z(),await Y()}async function ee(){let n=e.find(e=>e.id===I);U((await t(`POST`,`/tokens`,{profileId:I,sub:R||n?.role||`component`,constraints:A(B),createdBy:`dashboard`})).token),z(``),V({...S}),await Y()}async function te(e){await t(`POST`,`/tokens/${encodeURIComponent(e.jti)}/revoke`),await Y()}return(0,b.jsxs)(`div`,{className:`space-y-4`,children:[(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Security`}),(0,b.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Token profiles and scoped component tokens`})]}),(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsxs)(`div`,{className:`inline-flex rounded-md border border-border overflow-hidden`,children:[(0,b.jsxs)(`button`,{type:`button`,onClick:()=>q(`profiles`),className:`flex items-center gap-1.5 px-3 py-1.5 text-sm transition-colors ${K===`profiles`?`bg-primary/15 text-primary`:`text-muted-foreground hover:bg-accent`}`,children:[(0,b.jsx)(i,{className:`h-3.5 w-3.5`}),`Profiles`]}),(0,b.jsxs)(`button`,{type:`button`,onClick:()=>q(`tokens`),className:`flex items-center gap-1.5 px-3 py-1.5 text-sm border-l border-border transition-colors ${K===`tokens`?`bg-primary/15 text-primary`:`text-muted-foreground hover:bg-accent`}`,children:[(0,b.jsx)(l,{className:`h-3.5 w-3.5`}),`Tokens`]})]}),(0,b.jsxs)(d,{variant:`outline`,onClick:()=>void Y(),children:[(0,b.jsx)(a,{className:`h-4 w-4`}),`Refresh`]}),K===`profiles`&&(0,b.jsxs)(d,{onClick:Z,children:[(0,b.jsx)(r,{className:`h-4 w-4`}),`New profile`]})]})]}),K===`profiles`&&(0,b.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[340px_minmax(0,1fr)]`,children:[(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsxs)(g,{className:`flex items-center gap-2 text-sm`,children:[(0,b.jsx)(i,{className:`h-4 w-4`}),`Profiles`]})}),(0,b.jsx)(_,{className:`space-y-2`,children:e.map(e=>(0,b.jsxs)(`button`,{type:`button`,onClick:()=>X(e),className:`w-full rounded-md border px-3 py-2 text-left transition-colors ${e.id===k?`border-primary bg-primary/10`:`border-border hover:bg-accent`}`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-sm font-medium`,children:e.name}),e.builtIn&&(0,b.jsx)(u,{variant:`secondary`,className:`text-[10px]`,children:`built-in`})]}),(0,b.jsxs)(`div`,{className:`mt-1 flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,b.jsx)(`span`,{children:e.role}),(0,b.jsxs)(`span`,{children:[e.scope.length,` scopes`]}),e.ttlSeconds&&(0,b.jsx)(`span`,{children:P(e.ttlSeconds)})]})]},e.id))})]}),(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsx)(g,{className:`text-sm`,children:J?J.name:`New profile`})}),(0,b.jsxs)(_,{className:`space-y-4`,children:[(0,b.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[(0,b.jsx)(T,{label:`Profile id`,children:(0,b.jsx)(f,{disabled:!!k,value:M.id,onChange:e=>F({...M,id:e.target.value})})}),(0,b.jsx)(T,{label:`Name`,children:(0,b.jsx)(f,{value:M.name,onChange:e=>F({...M,name:e.target.value})})}),(0,b.jsx)(T,{label:`Role`,children:(0,b.jsx)(f,{value:M.role,onChange:e=>F({...M,role:e.target.value})})}),(0,b.jsx)(T,{label:`TTL seconds`,children:(0,b.jsx)(f,{inputMode:`numeric`,value:M.ttlSeconds,onChange:e=>F({...M,ttlSeconds:e.target.value})})})]}),(0,b.jsx)(T,{label:`Description`,children:(0,b.jsx)(m,{rows:2,value:M.description,onChange:e=>F({...M,description:e.target.value})})}),(0,b.jsxs)(`div`,{className:`space-y-2`,children:[(0,b.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Scopes`}),(0,b.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:x.map(e=>(0,b.jsx)(`button`,{type:`button`,onClick:()=>F({...M,scope:N(M.scope,e)}),className:`rounded border px-2 py-1 text-xs ${M.scope.includes(e)?`border-primary/50 bg-primary/15 text-primary`:`border-border text-muted-foreground hover:bg-accent`}`,children:e},e))})]}),(0,b.jsx)(E,{value:M.constraints,onChange:e=>F({...M,constraints:e})}),(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,b.jsxs)(d,{disabled:J?.builtIn,onClick:()=>void Q(),children:[(0,b.jsx)(n,{className:`h-4 w-4`}),`Save`]}),J&&!J.builtIn&&(0,b.jsxs)(d,{variant:`destructive`,onClick:()=>void $(J),children:[(0,b.jsx)(c,{className:`h-4 w-4`}),`Delete`]}),J?.builtIn&&(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Built-in profiles are managed by Relay.`})]})]})]})]}),K===`tokens`&&(0,b.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[380px_minmax(0,1fr)]`,children:[(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsxs)(g,{className:`flex items-center gap-2 text-sm`,children:[(0,b.jsx)(l,{className:`h-4 w-4`}),`Issue token`]})}),(0,b.jsxs)(_,{className:`space-y-3`,children:[(0,b.jsx)(T,{label:`Profile`,children:(0,b.jsx)(`select`,{className:`h-9 w-full rounded-md border border-input bg-background px-3 text-sm`,value:I,onChange:e=>L(e.target.value),children:e.map(e=>(0,b.jsx)(`option`,{value:e.id,children:e.name},e.id))})}),(0,b.jsx)(T,{label:`Subject`,children:(0,b.jsx)(f,{value:R,onChange:e=>z(e.target.value),placeholder:`component id`})}),(0,b.jsx)(E,{compact:!0,value:B,onChange:V}),(0,b.jsxs)(d,{className:`w-full`,disabled:!I,onClick:()=>void ee(),children:[(0,b.jsx)(l,{className:`h-4 w-4`}),`Issue`]}),H&&(0,b.jsxs)(`div`,{className:`rounded-md border border-border bg-muted/30 p-2`,children:[(0,b.jsxs)(`div`,{className:`mb-1 flex items-center justify-between gap-2`,children:[(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`New token`}),(0,b.jsx)(p,{value:H,label:`Copy token`,size:`sm`,variant:`ghost`,onCopied:()=>G(`Copied`)})]}),(0,b.jsx)(`code`,{className:`block max-h-24 overflow-auto break-all text-xs`,children:H})]}),W&&(0,b.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:W})]})]}),(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsx)(g,{className:`text-sm`,children:`Issued tokens`})}),(0,b.jsxs)(_,{className:`space-y-2`,children:[s.length===0&&(0,b.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`No tokens issued yet`}),s.slice(0,20).map(e=>(0,b.jsxs)(`div`,{className:`rounded-md border border-border p-2`,children:[(0,b.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.sub}),(0,b.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[e.role,` `,e.profileId?`· ${e.profileId}`:``]})]}),e.revokedAt?(0,b.jsx)(u,{variant:`destructive`,children:`revoked`}):(0,b.jsx)(d,{variant:`ghost`,size:`sm`,onClick:()=>void te(e),children:(0,b.jsx)(c,{className:`h-3.5 w-3.5`})})]}),(0,b.jsxs)(`div`,{className:`mt-1 flex flex-wrap gap-1`,children:[e.scope.slice(0,4).map(e=>(0,b.jsx)(u,{variant:`outline`,className:`text-[10px]`,children:e},e)),e.scope.length>4&&(0,b.jsxs)(u,{variant:`secondary`,className:`text-[10px]`,children:[`+`,e.scope.length-4]})]})]},e.jti))]})]})]})]})}function T({label:e,children:t}){return(0,b.jsxs)(`label`,{className:`block space-y-1.5 text-sm`,children:[(0,b.jsx)(`span`,{className:`text-muted-foreground`,children:e}),t]})}function E({value:e,onChange:t,compact:n=!1}){return(0,b.jsxs)(`div`,{className:`space-y-3`,children:[!n&&(0,b.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Constraints`}),(0,b.jsx)(`div`,{className:`grid gap-3 ${n?``:`md:grid-cols-2`}`,children:[[`agents`,`Agents`],[`policies`,`Policies`],[`targets`,`Targets`],[`channels`,`Channels`],[`orchestrators`,`Orchestrators`],[`cwdPrefixes`,`CWD prefixes`],[`memoryScopes`,`Memory scopes`],[`spawnRequestIds`,`Spawn requests`]].map(([r,i])=>(0,b.jsx)(T,{label:i,children:(0,b.jsx)(m,{rows:n?2:3,value:String(e[r]||``),onChange:n=>t({...e,[r]:n.target.value}),placeholder:`one per line`})},r))}),(0,b.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,b.jsxs)(`label`,{className:`flex items-center gap-2 rounded border border-border px-2 py-1 text-xs`,children:[(0,b.jsx)(`input`,{type:`checkbox`,checked:e.terminalAttach,onChange:n=>t({...e,terminalAttach:n.target.checked})}),`Terminal attach`]}),(0,b.jsxs)(`label`,{className:`flex items-center gap-2 rounded border border-border px-2 py-1 text-xs`,children:[(0,b.jsx)(`input`,{type:`checkbox`,checked:e.logsRead,onChange:n=>t({...e,logsRead:n.target.checked})}),`Log read`]})]})]})}function D(e){return{id:e.id,name:e.name,description:e.description||``,role:e.role,scope:e.scope,ttlSeconds:e.ttlSeconds?String(e.ttlSeconds):``,constraints:k(e.constraints)}}function O(e){return{id:e.id||void 0,name:e.name,description:e.description||void 0,role:e.role,scope:e.scope,ttlSeconds:e.ttlSeconds?Number(e.ttlSeconds):void 0,constraints:A(e.constraints)}}function k(e){return{agents:M(e?.agents),policies:M(e?.policies),targets:M(e?.targets),channels:M(e?.channels),orchestrators:M(e?.orchestrators),cwdPrefixes:M(e?.cwdPrefixes),memoryScopes:M(e?.memoryScopes),spawnRequestIds:M(e?.spawnRequestIds),terminalAttach:e?.terminalAttach===!0,logsRead:e?.logsRead===!0}}function A(e){let t={};for(let n of[`agents`,`policies`,`targets`,`channels`,`orchestrators`,`cwdPrefixes`,`memoryScopes`,`spawnRequestIds`]){let r=j(String(e[n]||``));r.length&&Object.assign(t,{[n]:r})}return e.terminalAttach&&(t.terminalAttach=!0),e.logsRead&&(t.logsRead=!0),Object.keys(t).length?t:void 0}function j(e){return e.split(/\r?\n|,/).map(e=>e.trim()).filter(Boolean)}function M(e){return(e??[]).join(`
|
|
2
2
|
`)}function N(e,t){return e.includes(t)?e.filter(e=>e!==t):[...e,t]}function P(e){return e%86400==0?`${e/86400}d`:e%3600==0?`${e/3600}h`:`${e}s`}export{w as SecurityView};
|
|
3
|
-
//# sourceMappingURL=security-
|
|
3
|
+
//# sourceMappingURL=security-BriPtiFR.js.map
|