diff --git a/electron/gateway/clawhub.ts b/electron/gateway/clawhub.ts
index cbb7912eb..044d1a2c6 100644
--- a/electron/gateway/clawhub.ts
+++ b/electron/gateway/clawhub.ts
@@ -181,7 +181,7 @@ export class ClawHubService {
}).filter((s): s is ClawHubSkillResult => s !== null);
} catch (error) {
console.error('ClawHub search error:', error);
- return [];
+ throw error;
}
}
@@ -217,7 +217,7 @@ export class ClawHubService {
}).filter((s): s is ClawHubSkillResult => s !== null);
} catch (error) {
console.error('ClawHub explore error:', error);
- return [];
+ throw error;
}
}
diff --git a/src/i18n/locales/en/skills.json b/src/i18n/locales/en/skills.json
index 85f91af6b..8d39bc872 100644
--- a/src/i18n/locales/en/skills.json
+++ b/src/i18n/locales/en/skills.json
@@ -57,11 +57,18 @@
"failedOpenFolder": "Failed to open skills folder",
"failedInstall": "Failed to install",
"failedUninstall": "Failed to uninstall",
- "failedFolderNotFound": "Skills folder does not exist yet. Install a skill first."
+ "failedFolderNotFound": "Skills folder does not exist yet. Install a skill first.",
+ "searchTimeoutError": "Search timed out, check network. You can also search on ClawHub.ai, download the ZIP, and extract it to \"{{path}}\"",
+ "installTimeoutError": "Installation timed out, check network. You can also download the ZIP from ClawHub.ai and extract it to \"{{path}}\"",
+ "searchRateLimitError": "Search rate limit exceeded. You can also search on ClawHub.ai, download the ZIP, and extract it to \"{{path}}\"",
+ "installRateLimitError": "Installation rate limit exceeded. You can also download the ZIP from ClawHub.ai and extract it to \"{{path}}\"",
+ "fetchTimeoutError": "Fetching skills timed out, please check your network connection.",
+ "fetchRateLimitError": "Fetching skills rate limit exceeded, please try again later."
},
"marketplace": {
"title": "Marketplace",
"securityNote": "Click skill card to view its documentation and security information on ClawHub before installation.",
+ "manualInstallHint": "Network issues? You can always download skill ZIP archives from ClawHub.ai and extract them manually into \"{{path}}\".",
"searching": "Searching ClawHub...",
"noResults": "No skills found matching your search.",
"emptyPrompt": "Search for new skills to expand your capabilities.",
diff --git a/src/i18n/locales/ja/skills.json b/src/i18n/locales/ja/skills.json
index 9181273ac..8a6eff8a1 100644
--- a/src/i18n/locales/ja/skills.json
+++ b/src/i18n/locales/ja/skills.json
@@ -57,11 +57,18 @@
"failedOpenFolder": "スキルフォルダを開けませんでした",
"failedInstall": "インストールに失敗しました",
"failedUninstall": "アンインストールに失敗しました",
- "failedFolderNotFound": "スキルフォルダがまだ存在しません。先にスキルをインストールしてください。"
+ "failedFolderNotFound": "スキルフォルダがまだ存在しません。先にスキルをインストールしてください。",
+ "searchTimeoutError": "検索がタイムアウトしました。ClawHub.aiで検索してZIPをダウンロードし、\"{{path}}\" に展開することも可能です",
+ "installTimeoutError": "インストールがタイムアウトしました。ClawHub.aiでZIPをダウンロードし、\"{{path}}\" に展開することも可能です",
+ "searchRateLimitError": "検索リクエストの制限を超過しました。ClawHub.aiで検索してZIPをダウンロードし、\"{{path}}\" に展開することも可能です",
+ "installRateLimitError": "インストールリクエストの制限を超過しました。ClawHub.aiからZIPをダウンロードし、\"{{path}}\" に展開することも可能です",
+ "fetchTimeoutError": "スキルリストの取得がタイムアウトしました。ネットワークを確認してください。",
+ "fetchRateLimitError": "スキルリスト取得のリクエスト制限を超過しました。後でお試しください。"
},
"marketplace": {
"title": "マーケットプレイス",
"securityNote": "インストール前にスキルカードをクリックして、ClawHubでドキュメントとセキュリティ情報を確認してください。",
+ "manualInstallHint": "ネットワークに問題がありますか?いつでもClawHub.aiからスキルのZIPをダウンロードし、手動で \"{{path}}\" に展開してインストールできます。",
"searching": "ClawHubを検索中...",
"noResults": "検索に一致するスキルが見つかりません。",
"emptyPrompt": "新しいスキルを検索して機能を拡張しましょう。",
diff --git a/src/i18n/locales/zh/skills.json b/src/i18n/locales/zh/skills.json
index 9e9b3693c..abebc2f9c 100644
--- a/src/i18n/locales/zh/skills.json
+++ b/src/i18n/locales/zh/skills.json
@@ -57,11 +57,18 @@
"failedOpenFolder": "无法打开技能文件夹",
"failedInstall": "安装失败",
"failedUninstall": "卸载失败",
- "failedFolderNotFound": "技能文件夹尚不存在,请先安装一个技能。"
+ "failedFolderNotFound": "技能文件夹尚不存在,请先安装一个技能。",
+ "searchTimeoutError": "搜索超时,请检查网络。您也可访问 ClawHub.ai 搜索并下载压缩包,解压到 \"{{path}}\"",
+ "installTimeoutError": "安装超时,请检查网络。您也可在 ClawHub.ai 下载该技能压缩包,解压到 \"{{path}}\"",
+ "searchRateLimitError": "搜索请求过于频繁。您也可访问 ClawHub.ai 搜索并下载压缩包,解压到 \"{{path}}\"",
+ "installRateLimitError": "安装请求过于频繁。您也可在 ClawHub.ai 下载该技能压缩包,解压到 \"{{path}}\"",
+ "fetchTimeoutError": "获取技能列表超时,请检查网络。",
+ "fetchRateLimitError": "获取技能列表请求过于频繁,请稍后再试。"
},
"marketplace": {
"title": "市场",
"securityNote": "安装前请点击技能卡片,在 ClawHub 上查看其文档和安全信息。",
+ "manualInstallHint": "遇到网络问题?您可以随时从 ClawHub.ai 下载技能压缩包,并将其解压至 \"{{path}}\" 目录来完成手动安装。",
"searching": "正在搜索 ClawHub...",
"noResults": "未找到匹配的技能。",
"emptyPrompt": "搜索新技能以扩展您的能力。",
diff --git a/src/pages/Skills/index.tsx b/src/pages/Skills/index.tsx
index 46f719553..0a79c0ea6 100644
--- a/src/pages/Skills/index.tsx
+++ b/src/pages/Skills/index.tsx
@@ -637,6 +637,14 @@ export function Skills() {
}
}, [t]);
+ const [skillsDirPath, setSkillsDirPath] = useState('~/.openclaw/skills');
+
+ useEffect(() => {
+ window.electron.ipcRenderer.invoke('openclaw:getSkillsDir')
+ .then((dir) => setSkillsDirPath(dir as string))
+ .catch(console.error);
+ }, []);
+
// Handle marketplace search
const handleMarketplaceSearch = useCallback((e: React.FormEvent) => {
e.preventDefault();
@@ -659,9 +667,14 @@ export function Skills() {
await enableSkill(slug);
toast.success(t('toast.installed'));
} catch (err) {
- toast.error(t('toast.failedInstall') + ': ' + String(err));
+ const errorMessage = err instanceof Error ? err.message : String(err);
+ if (['installTimeoutError', 'installRateLimitError'].includes(errorMessage)) {
+ toast.error(t(`toast.${errorMessage}`, { path: skillsDirPath }), { duration: 10000 });
+ } else {
+ toast.error(t('toast.failedInstall') + ': ' + errorMessage);
+ }
}
- }, [installSkill, enableSkill, t]);
+ }, [installSkill, enableSkill, t, skillsDirPath]);
// Initial marketplace load (Discovery)
useEffect(() => {
@@ -798,8 +811,12 @@ export function Skills() {
{error && (