From 4a3d4e5b23ceec4718e90835d127dd5a11ee91fc Mon Sep 17 00:00:00 2001 From: icodelife Date: Sat, 21 Mar 2026 02:27:58 +0800 Subject: [PATCH] feat: support workspace skills in dashboard --- app/skills/page.tsx | 10 ++++++++-- lib/i18n.tsx | 4 ++++ lib/openclaw-skills.ts | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/app/skills/page.tsx b/app/skills/page.tsx index 7371eb0..4cd4cdc 100644 --- a/app/skills/page.tsx +++ b/app/skills/page.tsx @@ -173,6 +173,7 @@ export default function SkillsPage() { const filtered = skills.filter((skill) => { if (filter === "builtin" && skill.source !== "builtin") return false; if (filter === "extension" && !skill.source.startsWith("extension:")) return false; + if (filter === "workspace" && skill.source !== "workspace") return false; if (filter === "custom" && skill.source !== "custom") return false; if (!search) return true; @@ -188,12 +189,14 @@ export default function SkillsPage() { const sourceLabel = (source: string) => { if (source === "builtin") return t("skills.source.builtin"); if (source.startsWith("extension:")) return source.replace("extension:", `${t("skills.extension")}:`); + if (source === "workspace") return t("skills.workspace"); return t("skills.source.custom"); }; const sourceBadgeClass = (source: string) => { if (source === "builtin") return "bg-blue-500/20 text-blue-400"; if (source.startsWith("extension:")) return "bg-purple-500/20 text-purple-400"; + if (source === "workspace") return "bg-orange-500/20 text-orange-400"; return "bg-green-500/20 text-green-400"; }; @@ -218,6 +221,7 @@ export default function SkillsPage() { const builtinCount = skills.filter((skill) => skill.source === "builtin").length; const extensionCount = skills.filter((skill) => skill.source.startsWith("extension:")).length; + const workspaceCount = skills.filter((skill) => skill.source === "workspace").length; const customCount = skills.filter((skill) => skill.source === "custom").length; return ( @@ -226,7 +230,7 @@ export default function SkillsPage() {

{t("skills.title")}

- 共 {skills.length} {t("skills.count")}({t("skills.builtin")} {builtinCount} / {t("skills.extension")} {extensionCount} / {t("skills.custom")} {customCount}) + 共 {skills.length} {t("skills.count")}({t("skills.builtin")} {builtinCount} / {t("skills.extension")} {extensionCount} / {t("skills.workspace")} {workspaceCount} / {t("skills.custom")} {customCount})

@@ -241,7 +245,7 @@ export default function SkillsPage() {
- {(["all", "builtin", "extension", "custom"] as const).map((nextFilter) => ( + {(["all", "builtin", "extension", "workspace", "custom"] as const).map((nextFilter) => ( ))} diff --git a/lib/i18n.tsx b/lib/i18n.tsx index 5e960fd..13b9579 100644 --- a/lib/i18n.tsx +++ b/lib/i18n.tsx @@ -232,6 +232,7 @@ const translations: Record> = { "skills.count": "個技能", "skills.builtin": "內建", "skills.extension": "擴充", + "skills.workspace": "工作區", "skills.custom": "自訂", "skills.all": "全部", "skills.search": "搜尋技能...", @@ -239,6 +240,7 @@ const translations: Record> = { "skills.unit": "個", "skills.noDesc": "無描述", "skills.source.builtin": "內建", + "skills.source.workspace": "工作區", "skills.source.custom": "自訂", "skills.viewSource": "查看 SKILL.md", "skills.contentTitle": "SKILL.md 內容", @@ -520,6 +522,7 @@ const translations: Record> = { "skills.count": "个技能", "skills.builtin": "内置", "skills.extension": "扩展", + "skills.workspace": "工作区", "skills.custom": "自定义", "skills.all": "全部", "skills.search": "搜索技能...", @@ -527,6 +530,7 @@ const translations: Record> = { "skills.unit": "个", "skills.noDesc": "无描述", "skills.source.builtin": "内置", + "skills.source.workspace": "工作区", "skills.source.custom": "自定义", "skills.viewSource": "查看 SKILL.md", "skills.contentTitle": "SKILL.md 内容", diff --git a/lib/openclaw-skills.ts b/lib/openclaw-skills.ts index 842f315..6d6db07 100644 --- a/lib/openclaw-skills.ts +++ b/lib/openclaw-skills.ts @@ -126,7 +126,8 @@ export function listOpenclawSkills(): { skills: SkillInfo[]; agents: Record