@@ -60,6 +60,7 @@ interface CategoryInfo {
6060 labelKey : string ;
6161 titleKey : string ;
6262 descKey : string ;
63+ sourceLabel ?: string ;
6364}
6465
6566const CATEGORIES : CategoryInfo [ ] = [
@@ -245,9 +246,28 @@ const SkillsScene: React.FC = () => {
245246 return list ;
246247 } , [ hideDuplicates , installed . filteredSkills ] ) ;
247248
248- const activeInstalledCategory = CATEGORIES . find ( ( category ) => category . id === installedFilter )
249+ const installedCategories : CategoryInfo [ ] = [
250+ ...CATEGORIES . filter ( ( category ) => category . id !== 'suite' ) ,
251+ ...installed . sourceGroups . map ( ( group ) => ( {
252+ id : group . id ,
253+ icon : < Icon name = "extension" size = "sm" /> ,
254+ labelKey : 'filters.source' ,
255+ titleKey : 'installed.titleSource' ,
256+ descKey : 'categories.source' ,
257+ sourceLabel : group . label ,
258+ } ) ) ,
259+ ...CATEGORIES . filter ( ( category ) => category . id === 'suite' ) ,
260+ ] ;
261+ const activeInstalledCategory = installedCategories . find ( ( category ) => category . id === installedFilter )
249262 ?? CATEGORIES [ 0 ] ;
250263
264+ useEffect ( ( ) => {
265+ if ( ! installed . loading && ! installed . error && installedFilter . startsWith ( 'source:' )
266+ && ! installed . sourceGroups . some ( ( group ) => group . id === installedFilter ) ) {
267+ setInstalledFilter ( 'all' ) ;
268+ }
269+ } , [ installed . loading , installed . error , installed . sourceGroups , installedFilter , setInstalledFilter ] ) ;
270+
251271 return (
252272 < div className = "openbitfun-skills-scene" data-testid = "agent-skill-panel" data-openbitfun-scene = "skills" data-openbitfun-part = "root" data-openbitfun-tab = { activeTab } >
253273 < GalleryPageHeader
@@ -303,8 +323,8 @@ const SkillsScene: React.FC = () => {
303323 < h2 className = "skills-sidebar__title" data-openbitfun-scene = "skills" data-openbitfun-part = "sidebarTitle" > { t ( 'installed.titleAll' ) } </ h2 >
304324 </ div >
305325 < nav className = "skills-sidebar__nav" aria-label = { t ( 'installed.titleAll' ) } data-openbitfun-scene = "skills" data-openbitfun-part = "sidebarNav" >
306- { CATEGORIES . map ( ( cat ) => {
307- const count = installed . counts [ cat . id ] ;
326+ { installedCategories . map ( ( cat ) => {
327+ const count = installed . counts [ cat . id ] ?? 0 ;
308328 const isEmpty = count === 0 ;
309329 return (
310330 < div
@@ -321,23 +341,23 @@ const SkillsScene: React.FC = () => {
321341 < NavigationPanelItem
322342 selected = { installedFilter === cat . id }
323343 onClick = { ( ) => setInstalledFilter ( cat . id ) }
324- title = { t ( cat . descKey ) }
344+ title = { t ( cat . descKey , { source : cat . sourceLabel } ) }
325345 leading = { < span data-openbitfun-scene = "skills" data-openbitfun-part = "sidebarItemIcon" > { cat . icon } </ span > }
326346 metadata = { (
327347 < span className = "skills-sidebar__item-count" data-openbitfun-scene = "skills" data-openbitfun-part = "sidebarItemCount" >
328348 { formatNumber ( count ) }
329349 </ span >
330350 ) }
331351 >
332- < span data-openbitfun-scene = "skills" data-openbitfun-part = "sidebarItemLabel" > { t ( cat . labelKey ) } </ span >
352+ < span data-openbitfun-scene = "skills" data-openbitfun-part = "sidebarItemLabel" > { t ( cat . labelKey , { source : cat . sourceLabel } ) } </ span >
333353 </ NavigationPanelItem >
334354 </ div >
335355 ) ;
336356 } ) }
337357 </ nav >
338358 < div className = "skills-sidebar__footer" data-openbitfun-scene = "skills" data-openbitfun-part = "sidebarFooter" >
339359 < p className = "skills-sidebar__hint" data-openbitfun-scene = "skills" data-openbitfun-part = "sidebarHint" >
340- { t ( CATEGORIES . find ( ( c ) => c . id === installedFilter ) ?. descKey ?? 'categories.all' ) }
360+ { t ( activeInstalledCategory . descKey , { source : activeInstalledCategory . sourceLabel } ) }
341361 </ p >
342362 </ div >
343363 </ ScrollArea > }
@@ -387,7 +407,7 @@ const SkillsScene: React.FC = () => {
387407 >
388408 < div className = "skills-main__list-heading" >
389409 < span data-openbitfun-scene = "skills" data-openbitfun-part = "installedListTitle" >
390- { t ( activeInstalledCategory . titleKey ) }
410+ { t ( activeInstalledCategory . titleKey , { source : activeInstalledCategory . sourceLabel } ) }
391411 </ span >
392412 < span
393413 className = "skills-main__list-count"
@@ -499,7 +519,7 @@ const SkillsScene: React.FC = () => {
499519 </ div >
500520 < div className = "skills-card__info" data-openbitfun-scene = "skills" data-openbitfun-part = "installedCardInfo" >
501521 < span className = "skills-card__name" data-testid = "skill-list-item-title" data-openbitfun-scene = "skills" data-openbitfun-part = "installedCardName" >
502- < OverflowText behavior = "marquee" > { skill . name } </ OverflowText >
522+ < OverflowText behavior = "marquee" title = "" > { skill . name } </ OverflowText >
503523 </ span >
504524 { skill . description ?. trim ( ) && (
505525 < OverflowText lines = { 2 } className = "skills-card__desc" data-testid = "skill-list-item-description" data-openbitfun-scene = "skills" data-openbitfun-part = "installedCardDescription" > { skill . description } </ OverflowText >
@@ -517,14 +537,9 @@ const SkillsScene: React.FC = () => {
517537 </ StatusPill >
518538 ) }
519539 { skill . isShadowed && (
520- < span title = { t ( 'list.item.shadowedTooltip' , {
521- source : coverageSourceBySkillKey . get ( skill . key )
522- ?? t ( 'list.item.unknownSource' ) ,
523- } ) } >
524- < StatusPill tone = "warning" leading = { < Icon glyph = { ShieldAlert } /> } >
525- { t ( 'list.item.shadowed' ) }
526- </ StatusPill >
527- </ span >
540+ < StatusPill tone = "warning" leading = { < Icon glyph = { ShieldAlert } /> } >
541+ { t ( 'list.item.shadowed' ) }
542+ </ StatusPill >
528543 ) }
529544 </ div >
530545 </ div >
@@ -554,7 +569,7 @@ const SkillsScene: React.FC = () => {
554569 { skill . level === 'user'
555570 ? < Icon name = "user" size = "xs" />
556571 : < Icon glyph = { FolderOpen } size = "xs" /> }
557- < OverflowText >
572+ < OverflowText title = "" >
558573 { market . isRemoteWorkspace
559574 ? skill . level === 'user'
560575 ? t ( 'list.item.localUser' )
0 commit comments