diff --git a/ui/src/components/SkillCard.tsx b/ui/src/components/SkillCard.tsx index 38cbaf70..4c4bb161 100644 --- a/ui/src/components/SkillCard.tsx +++ b/ui/src/components/SkillCard.tsx @@ -20,6 +20,8 @@ export interface SkillCardProps { onRollback?: () => void; onUninstall?: () => void; isLoading?: boolean; + isReadOnly?: boolean; + source?: "managed" | "native"; className?: string; } @@ -32,13 +34,15 @@ export function SkillCard({ onRollback, onUninstall, isLoading = false, + isReadOnly = false, + source, className, }: SkillCardProps) { return ( - {/* Row 1: name link (primary visual anchor) + update badge */} + {/* Row 1: name link (primary visual anchor) + update badge + native badge */}
{skill.name} - {hasUpdate && ( - - Update - - )} +
+ {(isReadOnly || source === "native") && ( + + Native + + )} + {hasUpdate && !isReadOnly && ( + + Update + + )} +
{/* Row 2: description (2-line clamp) */} @@ -72,7 +87,7 @@ export function SkillCard({ )}
- {isInstalled && onRollback && ( + {!isReadOnly && isInstalled && onRollback && (
@@ -364,34 +394,106 @@ export function SkillBrowser() { {/* Installed tab */} - {installedGroups.length === 0 && ( + {/* Agent selector for installed tab */} + {agents.length === 0 && ( setTab("browse")} + message="No agents found in this workspace." /> )} - {installedGroups.map((group) => ( -
-
- - {group.skills.length} -
-
- {group.skills.map((skill) => ( - handleRollback(skill.id)} - onUninstall={() => setUninstallDialog({ skillId: skill.id })} - /> + {agents.length > 0 && !selectedAgentId && ( +
+

Select an agent to view installed skills:

+
+ {agents.map((agent) => ( + ))}
- ))} + )} + {selectedAgentId && ( +
+ {/* Back to agent selector */} +
+ + + {agents.find((a) => a.id === selectedAgentId)?.name ?? selectedAgentId} + +
+ + {agentInstalledSkills.length === 0 && ( + setTab("browse")} + /> + )} + + {/* Managed skills section */} + {managedSkills.length > 0 && ( + <> + {nativeSkills.length > 0 && ( +

Managed

+ )} +
+ {managedSkills.map((entry) => { + const skill = skillById.get(entry.skillId); + if (!skill) return null; + return ( + handleRollback(entry.skillId)} + onUninstall={() => setUninstallDialog({ skillId: entry.skillId, agentId: selectedAgentId })} + /> + ); + })} +
+ + )} + + {/* Native skills section */} + {nativeSkills.length > 0 && ( + <> +

Native

+
+ {nativeSkills.map((entry) => { + const skill = skillById.get(entry.skillId); + if (!skill) return null; + return ( + + ); + })} +
+ + )} +
+ )} {/* Trending tab */} @@ -418,7 +520,7 @@ export function SkillBrowser() { onInstall={() => setInstallDialog({ skillId: skill.id })} onUpdate={() => setInstallDialog({ skillId: skill.id, isUpdate: true })} onRollback={() => handleRollback(skill.id)} - onUninstall={() => setUninstallDialog({ skillId: skill.id })} + onUninstall={() => void skill.id} /> ))}
@@ -437,7 +539,7 @@ export function SkillBrowser() { onInstall={() => setInstallDialog({ skillId: skill.id })} onUpdate={() => setInstallDialog({ skillId: skill.id, isUpdate: true })} onRollback={() => handleRollback(skill.id)} - onUninstall={() => setUninstallDialog({ skillId: skill.id })} + onUninstall={() => void skill.id} /> ))}
@@ -456,7 +558,7 @@ export function SkillBrowser() { onInstall={() => setInstallDialog({ skillId: skill.id })} onUpdate={() => setInstallDialog({ skillId: skill.id, isUpdate: true })} onRollback={() => handleRollback(skill.id)} - onUninstall={() => setUninstallDialog({ skillId: skill.id })} + onUninstall={() => void skill.id} /> ))} @@ -471,10 +573,7 @@ export function SkillBrowser() { { - if (!open) { - setInstallDialog(null); - setAgentSkillsDir(""); - } + if (!open) setInstallDialog(null); }} > @@ -485,17 +584,6 @@ export function SkillBrowser() {
-
- - setAgentSkillsDir(e.target.value)} - /> -
{agents.length === 0 && (

No agents found in this workspace.

@@ -516,10 +604,7 @@ export function SkillBrowser() { @@ -548,7 +633,7 @@ export function SkillBrowser() { disabled={removeMutation.isPending} onClick={() => { if (uninstallDialog) { - removeMutation.mutate(uninstallDialog.skillId); + removeMutation.mutate({ skillId: uninstallDialog.skillId, agentId: uninstallDialog.agentId }); setUninstallDialog(null); } }}