From dee82177d39f219a6ce0c42e70fd7586fcea950b Mon Sep 17 00:00:00 2001 From: Chrys <53332481+ChrAlpha@users.noreply.github.com> Date: Fri, 17 Apr 2026 16:05:00 +0800 Subject: [PATCH] feat: add bot-level skill paths configuration (#383) --- apps/web/src/i18n/locales/en.json | 35 +- apps/web/src/i18n/locales/zh.json | 35 +- .../src/pages/bots/components/bot-skills.vue | 335 +++++++++++++++++- internal/handlers/skills.go | 32 +- internal/handlers/skills_test.go | 55 ++- internal/skills/skills.go | 82 ++++- internal/skills/skills_test.go | 62 +++- internal/workspace/image_preference.go | 140 +++++++- internal/workspace/image_preference_test.go | 71 ++++ internal/workspace/manager.go | 13 +- internal/workspace/versioning.go | 4 +- 11 files changed, 780 insertions(+), 84 deletions(-) diff --git a/apps/web/src/i18n/locales/en.json b/apps/web/src/i18n/locales/en.json index b5b211b4..131e92d8 100644 --- a/apps/web/src/i18n/locales/en.json +++ b/apps/web/src/i18n/locales/en.json @@ -1120,28 +1120,49 @@ }, "skills": { "title": "Skills", + "discoveryTitle": "Skill Paths", + "discoveryDescription": "Manage where this bot stores managed skills and which external paths are scanned.", + "managedPathLabel": "Managed Path", + "managedPathDescription": "Memoh-managed skills are stored here.", + "managedPathHint": "\"Copy to Managed Path\" copies an external skill here. Managed copies take precedence.", + "discoveryPathsLabel": "External Skill Paths", + "discoveryPathsDescription": "Memoh scans these absolute paths for compatible external skills. One path per line.", + "discoveryPathPlaceholder": "/root/.agents/skills", + "discoveryAddPath": "Add Path", + "discoveryEmpty": "No external skill paths. Only managed and legacy skills will be scanned.", + "discoveryDefaultHint": "Default external paths: {paths}", + "discoveryReset": "Reset", + "discoverySummaryDefault": "Default", + "discoverySummaryCustom": "{count} paths", + "discoverySummaryUnsaved": "Unsaved changes", + "discoveryPathRequired": "Path is required", + "discoveryPathAbsolute": "Path must be absolute", + "discoveryPathReserved": "This path is reserved for Memoh-managed or legacy skills", + "discoveryPathDuplicate": "Duplicate path", + "discoverySaveSuccess": "Skill paths saved", + "discoverySaveFailed": "Failed to save skill paths", "addSkill": "New Skill", "emptyTitle": "No Skills", "emptyDescription": "Click above to create a new skill", "managedBadge": "Managed", - "discoveredBadge": "Discovered", + "discoveredBadge": "External", "effectiveBadge": "Effective", "shadowedBadge": "Shadowed", "disabledBadge": "Disabled", "legacyBadge": "Legacy", - "compatBadge": "Compatible", + "compatBadge": "External", "description": "Description", "descriptionPlaceholder": "Enter skill description", "content": "Content", "contentPlaceholder": "Enter skill content/prompt", "deleteConfirm": "Are you sure you want to delete this skill?", - "overrideTitle": "Edit to create a managed override", - "adoptAction": "Adopt into Memoh-managed skills", - "adoptBlocked": "A higher-priority skill already exists", + "overrideTitle": "Edit to create a managed copy", + "adoptAction": "Copy to Managed Path", + "adoptBlocked": "A managed copy already exists", "disableAction": "Disable this skill source", "enableAction": "Enable this skill source", - "adoptSuccess": "Skill adopted", - "adoptFailed": "Failed to adopt skill", + "adoptSuccess": "Skill copied to managed path", + "adoptFailed": "Failed to copy skill to managed path", "disableSuccess": "Skill disabled", "disableFailed": "Failed to disable skill", "enableSuccess": "Skill enabled", diff --git a/apps/web/src/i18n/locales/zh.json b/apps/web/src/i18n/locales/zh.json index 3840439b..055bbd2e 100644 --- a/apps/web/src/i18n/locales/zh.json +++ b/apps/web/src/i18n/locales/zh.json @@ -1116,28 +1116,49 @@ }, "skills": { "title": "技能", + "discoveryTitle": "技能路径", + "discoveryDescription": "管理这个 Bot 的托管技能保存位置,以及会扫描哪些外部技能路径。", + "managedPathLabel": "托管路径", + "managedPathDescription": "Memoh 托管技能会保存在这里。", + "managedPathHint": "“复制到托管路径”会把外部技能复制到这里。托管副本会优先生效。", + "discoveryPathsLabel": "外部技能路径", + "discoveryPathsDescription": "Memoh 会扫描这些绝对路径中的兼容外部技能。每行填写一个路径。", + "discoveryPathPlaceholder": "/root/.agents/skills", + "discoveryAddPath": "添加路径", + "discoveryEmpty": "当前没有外部技能路径,仅会扫描托管技能和旧版技能。", + "discoveryDefaultHint": "默认外部路径:{paths}", + "discoveryReset": "重置", + "discoverySummaryDefault": "默认", + "discoverySummaryCustom": "{count} 个路径", + "discoverySummaryUnsaved": "有未保存修改", + "discoveryPathRequired": "路径不能为空", + "discoveryPathAbsolute": "路径必须是绝对路径", + "discoveryPathReserved": "这个路径已被 Memoh 托管技能或旧版技能占用", + "discoveryPathDuplicate": "路径重复", + "discoverySaveSuccess": "技能路径已保存", + "discoverySaveFailed": "保存技能路径失败", "addSkill": "新建技能", "emptyTitle": "暂无技能", "emptyDescription": "点击上方按钮创建新技能", "managedBadge": "托管", - "discoveredBadge": "发现", + "discoveredBadge": "外部", "effectiveBadge": "生效中", "shadowedBadge": "被覆盖", "disabledBadge": "已禁用", "legacyBadge": "旧版", - "compatBadge": "兼容", + "compatBadge": "外部", "description": "描述", "descriptionPlaceholder": "输入技能描述", "content": "内容", "contentPlaceholder": "输入技能内容/提示词", "deleteConfirm": "确定要删除这个技能吗?", - "overrideTitle": "编辑后将创建托管覆盖版本", - "adoptAction": "纳入 Memoh 托管", - "adoptBlocked": "已有更高优先级的技能副本", + "overrideTitle": "编辑后将创建托管副本", + "adoptAction": "复制到托管路径", + "adoptBlocked": "已有托管副本", "disableAction": "禁用这个技能来源", "enableAction": "启用这个技能来源", - "adoptSuccess": "技能已纳入托管", - "adoptFailed": "纳入托管失败", + "adoptSuccess": "技能已复制到托管路径", + "adoptFailed": "复制到托管路径失败", "disableSuccess": "技能已禁用", "disableFailed": "禁用技能失败", "enableSuccess": "技能已启用", diff --git a/apps/web/src/pages/bots/components/bot-skills.vue b/apps/web/src/pages/bots/components/bot-skills.vue index 60ee6ed1..421d9203 100644 --- a/apps/web/src/pages/bots/components/bot-skills.vue +++ b/apps/web/src/pages/bots/components/bot-skills.vue @@ -7,15 +7,31 @@ {{ $t('bots.skills.title') }} - +
+ + +
@@ -230,26 +246,109 @@ + + + + + {{ $t('bots.skills.discoveryTitle') }} + + {{ $t('bots.skills.discoveryDescription') }} + + + +
+
+ +

+ {{ $t('bots.skills.managedPathDescription') }} +

+
+ {{ MANAGED_SKILL_PATH }} +
+

+ {{ $t('bots.skills.managedPathHint') }} +

+
+ +
+ +

+ {{ $t('bots.skills.discoveryPathsDescription') }} +

+