+
+
+
+ {t('market.section.installed')}
+
+ {!isLoading && (
+
+ {skills.length}
+
+ )}
+
+
+
+
+
+
+
+ {
+ setQuery(event.target.value)
+ setExpanded(false)
+ }}
+ placeholder={t('market.installedSkills.searchPlaceholder')}
+ aria-label={t('market.installedSkills.searchPlaceholder')}
+ className="min-w-0 flex-1 bg-transparent text-sm text-[var(--color-text-primary)] outline-none placeholder:text-[var(--color-text-tertiary)]"
+ />
+ {query && (
+
+ )}
+
+
+
+ {(['all', 'personal', 'system'] as const).map((value) => (
+
+ ))}
+
+
+
+ {isLoading && skills.length === 0 && (
+
+ {Array.from({ length: 6 }, (_, index) => (
+
+ ))}
+
+ )}
+
+ {!isLoading && error && skills.length === 0 && (
+
+
{error}
+
+
+ )}
+
+ {!isLoading && !error && skills.length === 0 && (
+
+
+
{t('settings.skills.empty')}
+
{t('settings.skills.emptyHint')}
+
+ )}
+
+ {!isLoading && skills.length > 0 && filteredSkills.length === 0 && (
+
+
{t('settings.skills.noSearchResults')}
+
+ )}
+
+ {visibleSkills.length > 0 && (
+
+ {visibleSkills.map((skill) => {
+ const Icon = SOURCE_ICONS[skill.source]
+ const name = skill.displayName || skill.name
+ return (
+
+ )
+ })}
+
+ )}
+
+ {shouldCollapse && (
+
+ )}
+
+ )
+}
diff --git a/desktop/src/components/market/MarketHome.test.tsx b/desktop/src/components/market/MarketHome.test.tsx
index fce15341..b689136a 100644
--- a/desktop/src/components/market/MarketHome.test.tsx
+++ b/desktop/src/components/market/MarketHome.test.tsx
@@ -7,6 +7,10 @@ import { useMarketStore } from '../../stores/marketStore'
import type { NormalizedSkill } from '../../types/market'
import { MarketHome } from './MarketHome'
+vi.mock('./InstalledSkillsOverview', () => ({
+ InstalledSkillsOverview: () => = {}): NormalizedSkill {
return {
id: 'clawhub:demo',
@@ -48,6 +52,7 @@ describe('MarketHome', () => {
it('renders the compact catalog header, command bar, sources and semantic cards', () => {
render()
+ expect(screen.getByText('Installed skills overview')).toBeInTheDocument()
expect(screen.getByRole('heading', { name: 'Skills Market' })).toBeInTheDocument()
expect(screen.getByTestId('market-search-input')).toBeInTheDocument()
expect(screen.getByTestId('market-search-input')).toHaveAttribute('data-slot', 'input')
diff --git a/desktop/src/components/market/MarketHome.tsx b/desktop/src/components/market/MarketHome.tsx
index 5bcd98da..0e0e22ad 100644
--- a/desktop/src/components/market/MarketHome.tsx
+++ b/desktop/src/components/market/MarketHome.tsx
@@ -14,6 +14,7 @@ import { FilterBar } from './FilterBar'
import { MarketDisclaimer } from './MarketDisclaimer'
import { SkillCard } from './SkillCard'
import { SourceStatusBar } from './SourceStatusBar'
+import { InstalledSkillsOverview } from './InstalledSkillsOverview'
export function MarketHome({
onRequestInstall,
@@ -72,6 +73,8 @@ export function MarketHome({
+
+
diff --git a/desktop/src/i18n/locales/en.ts b/desktop/src/i18n/locales/en.ts
index 9aeab018..73bfebab 100644
--- a/desktop/src/i18n/locales/en.ts
+++ b/desktop/src/i18n/locales/en.ts
@@ -2409,6 +2409,15 @@ export const en = {
'sidebar.market': 'Skills Market',
'market.title': 'Skills Market',
'market.subtitle': 'Browse, preview and install skills from ClawHub and SkillHub.',
+ 'market.section.installed': 'Installed',
+ 'market.installedSkills.refresh': 'Refresh installed skills',
+ 'market.installedSkills.searchPlaceholder': 'Search installed skills',
+ 'market.installedSkills.filterLabel': 'Filter installed skills',
+ 'market.installedSkills.filter.all': 'All',
+ 'market.installedSkills.filter.personal': 'Personal',
+ 'market.installedSkills.filter.system': 'System',
+ 'market.installedSkills.showMore': 'View {count} more',
+ 'market.installedSkills.showLess': 'Show less',
'market.searchPlaceholder': 'Search skills by name, keyword…',
'market.clearSearch': 'Clear search',
'market.resultCount': '{count} skills',
diff --git a/desktop/src/i18n/locales/jp.ts b/desktop/src/i18n/locales/jp.ts
index 76bf2171..d448fc1a 100644
--- a/desktop/src/i18n/locales/jp.ts
+++ b/desktop/src/i18n/locales/jp.ts
@@ -2411,6 +2411,15 @@ export const jp: Record = {
'sidebar.market': 'スキルマーケット',
'market.title': 'スキルマーケット',
'market.subtitle': 'ClawHub と SkillHub のスキルを閲覧・プレビュー・インストールできます。',
+ 'market.section.installed': 'インストール済み',
+ 'market.installedSkills.refresh': 'インストール済みスキルを更新',
+ 'market.installedSkills.searchPlaceholder': 'インストール済みスキルを検索',
+ 'market.installedSkills.filterLabel': 'インストール済みスキルを絞り込む',
+ 'market.installedSkills.filter.all': 'すべて',
+ 'market.installedSkills.filter.personal': '個人',
+ 'market.installedSkills.filter.system': 'システム',
+ 'market.installedSkills.showMore': '他 {count} 件を表示',
+ 'market.installedSkills.showLess': '折りたたむ',
'market.searchPlaceholder': 'スキル名・キーワードで検索…',
'market.clearSearch': '検索をクリア',
'market.resultCount': '{count} 件のスキル',
diff --git a/desktop/src/i18n/locales/kr.ts b/desktop/src/i18n/locales/kr.ts
index 0bff4c3a..4ac57eaa 100644
--- a/desktop/src/i18n/locales/kr.ts
+++ b/desktop/src/i18n/locales/kr.ts
@@ -2411,6 +2411,15 @@ export const kr: Record = {
'sidebar.market': '스킬 마켓',
'market.title': '스킬 마켓',
'market.subtitle': 'ClawHub와 SkillHub의 스킬을 탐색·미리보기·설치할 수 있습니다.',
+ 'market.section.installed': '설치됨',
+ 'market.installedSkills.refresh': '설치된 스킬 새로고침',
+ 'market.installedSkills.searchPlaceholder': '설치된 스킬 검색',
+ 'market.installedSkills.filterLabel': '설치된 스킬 필터',
+ 'market.installedSkills.filter.all': '전체',
+ 'market.installedSkills.filter.personal': '개인',
+ 'market.installedSkills.filter.system': '시스템',
+ 'market.installedSkills.showMore': '{count}개 더 보기',
+ 'market.installedSkills.showLess': '접기',
'market.searchPlaceholder': '스킬 이름, 키워드로 검색…',
'market.clearSearch': '검색 지우기',
'market.resultCount': '{count}개의 스킬',
diff --git a/desktop/src/i18n/locales/zh-TW.ts b/desktop/src/i18n/locales/zh-TW.ts
index 4e736b04..16df2a9f 100644
--- a/desktop/src/i18n/locales/zh-TW.ts
+++ b/desktop/src/i18n/locales/zh-TW.ts
@@ -2411,6 +2411,15 @@ export const zh: Record = {
'sidebar.market': '技能市集',
'market.title': '技能市集',
'market.subtitle': '瀏覽、預覽並安裝來自 ClawHub 與 SkillHub 的技能。',
+ 'market.section.installed': '已安裝',
+ 'market.installedSkills.refresh': '重新整理已安裝技能',
+ 'market.installedSkills.searchPlaceholder': '搜尋已安裝技能',
+ 'market.installedSkills.filterLabel': '篩選已安裝技能',
+ 'market.installedSkills.filter.all': '全部',
+ 'market.installedSkills.filter.personal': '個人',
+ 'market.installedSkills.filter.system': '系統',
+ 'market.installedSkills.showMore': '查看另外 {count} 項',
+ 'market.installedSkills.showLess': '收合',
'market.searchPlaceholder': '依名稱、關鍵字搜尋技能…',
'market.clearSearch': '清除搜尋',
'market.resultCount': '{count} 個技能',
diff --git a/desktop/src/i18n/locales/zh.ts b/desktop/src/i18n/locales/zh.ts
index d8c932b5..4188a7e4 100644
--- a/desktop/src/i18n/locales/zh.ts
+++ b/desktop/src/i18n/locales/zh.ts
@@ -2411,6 +2411,15 @@ export const zh: Record = {
'sidebar.market': '技能市场',
'market.title': '技能市场',
'market.subtitle': '浏览、预览并安装来自 ClawHub 与 SkillHub 的技能。',
+ 'market.section.installed': '已安装',
+ 'market.installedSkills.refresh': '刷新已安装技能',
+ 'market.installedSkills.searchPlaceholder': '搜索已安装技能',
+ 'market.installedSkills.filterLabel': '筛选已安装技能',
+ 'market.installedSkills.filter.all': '全部',
+ 'market.installedSkills.filter.personal': '个人',
+ 'market.installedSkills.filter.system': '系统',
+ 'market.installedSkills.showMore': '查看另外 {count} 项',
+ 'market.installedSkills.showLess': '收起',
'market.searchPlaceholder': '按名称、关键词搜索技能…',
'market.clearSearch': '清除搜索',
'market.resultCount': '{count} 个技能',