Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions console/src/api/modules/skill.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { request } from "../request";
import type { HubSkillSpec, SkillSpec } from "../types";
import type {
HubSkillSpec,
InstallMarketplacePayload,
InstallSkillResult,
MarketplaceResponse,
SkillSpec,
SkillsMarketSpec,
SkillsMarketsPayload,
ValidateMarketResponse,
} from "../types";

// Declare BASE_URL as global (injected by Vite)
declare const BASE_URL: string;
Expand Down Expand Up @@ -54,12 +63,32 @@ export const skillApi = {
enable?: boolean;
overwrite?: boolean;
}) =>
request<{
installed: boolean;
name: string;
enabled: boolean;
source_url: string;
}>("/skills/hub/install", {
request<InstallSkillResult>("/skills/hub/install", {
method: "POST",
body: JSON.stringify(payload),
}),

getSkillsMarkets: () => request<SkillsMarketsPayload>("/skills/markets"),

updateSkillsMarkets: (payload: SkillsMarketsPayload) =>
request<SkillsMarketsPayload>("/skills/markets", {
method: "PUT",
body: JSON.stringify(payload),
}),

validateSkillsMarket: (payload: SkillsMarketSpec) =>
request<ValidateMarketResponse>("/skills/markets/validate", {
method: "POST",
body: JSON.stringify(payload),
}),

getMarketplace: (refresh = false) =>
request<MarketplaceResponse>(
`/skills/marketplace?refresh=${refresh ? "true" : "false"}`,
),

installMarketplaceSkill: (payload: InstallMarketplacePayload) =>
request<InstallSkillResult>("/skills/marketplace/install", {
method: "POST",
body: JSON.stringify(payload),
}),
Expand Down
72 changes: 72 additions & 0 deletions console/src/api/types/skill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,78 @@ export interface HubSkillSpec {
source_url: string;
}

export interface SkillsMarketSpec {
id: string;
name: string;
url: string;
branch?: string;
path: string;
enabled: boolean;
order: number;
}

export interface SkillsMarketsPayload {
version: number;
cache: {
ttl_sec: number;
};
install: {
overwrite_default: boolean;
};
markets: SkillsMarketSpec[];
}

export interface ValidateMarketResponse {
ok: boolean;
normalized: SkillsMarketSpec;
warnings: string[];
}

export interface MarketError {
market_id: string;
code: string;
message: string;
retryable: boolean;
}

export interface MarketplaceItem {
market_id: string;
skill_id: string;
name: string;
description: string;
version: string;
source_url: string;
install_url: string;
tags: string[];
}

export interface MarketplaceMeta {
refreshed_at: number;
cache_hit: boolean;
enabled_market_count: number;
success_market_count: number;
}

export interface MarketplaceResponse {
items: MarketplaceItem[];
market_errors: MarketError[];
meta: MarketplaceMeta;
}

export interface InstallMarketplacePayload {
market_id: string;
skill_id: string;
enable?: boolean;
overwrite?: boolean;
}

export interface InstallSkillResult {
installed: boolean;
name: string;
enabled: boolean;
source_url: string;
}

// Legacy Skill interface for backward compatibility
export interface Skill {
id: string;
Expand Down
45 changes: 44 additions & 1 deletion console/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,50 @@
"stopOptimize": "Stop",
"optimizeSuccess": "Skill optimized successfully",
"optimizeFailed": "Failed to optimize skill",
"noContentToOptimize": "No content to optimize"
"noContentToOptimize": "No content to optimize",
"localSkillsTab": "Local Skills",
"marketplaceTab": "Marketplace",
"refreshMarketplace": "Refresh Marketplace",
"searchMarketplacePlaceholder": "Search by name, id, or tag",
"marketplaceEmpty": "No marketplace skills available",
"installFromMarketplace": "Install",
"viewSource": "View Source",
"marketCount": "Enabled markets {{enabled}} / {{total}}",
"marketRefreshSummary": "Fetched successfully {{success}} / {{total}}",
"manageMarkets": "Manage Markets",
"addMarket": "Add Market",
"removeMarket": "Remove",
"validateMarket": "Validate",
"noMarketsConfigured": "No markets configured",
"marketId": "Market ID",
"marketName": "Market Name",
"marketUrl": "Repository URL",
"marketBranch": "Branch (Optional)",
"marketPath": "Index Path",
"marketOrder": "Order",
"marketEnabled": "Enable this market",
"marketValidated": "Validated",
"marketPendingValidation": "Pending Validation",
"marketSaveRequiresValidation": "Validate all market entries before saving.",
"marketSaveRequiresFields": "Fill in market ID, name, and repository URL before saving.",
"marketSaveRequiresUniqueId": "Market IDs must be unique before saving.",
"marketUrlPlaceholder": "Supports owner/repo, .git URLs, or GitHub tree URLs",
"marketUrlExamples": "Examples: openclaw/openclaw or https://github.com/openclaw/openclaw/tree/main/skills",
"marketAutoParse": "Auto Parse",
"marketUrlAutoParsed": "URL auto-parsed. Branch: {{branch}}, Path: {{path}}",
"refreshingMarketplace": "Refreshing marketplace {{progress}}%",
"loadMarketsFailed": "Failed to load skill markets",
"validateMarketSuccess": "Validated market: {{name}}",
"validateMarketFailed": "Market validation failed",
"saveMarketsSuccess": "Skill markets updated",
"saveMarketsFailed": "Failed to update skill markets",
"loadMarketplaceFailed": "Failed to load marketplace",
"installMarketplaceSuccess": "Installed skill: {{name}}",
"installMarketplaceFailed": "Install failed",
"overwriteConfirmTitle": "Skill Already Installed",
"overwriteConfirmContent": "Skill \"{{name}}\" is already installed. Do you want to overwrite it?",
"overwriteConfirmOk": "Overwrite",
"overwriteConfirmCancel": "Cancel"
},
"mcp": {
"title": "MCP Clients",
Expand Down
45 changes: 44 additions & 1 deletion console/src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,50 @@
"stopOptimize": "停止",
"optimizeSuccess": "技能优化成功",
"optimizeFailed": "技能优化失败",
"noContentToOptimize": "没有可优化的内容"
"noContentToOptimize": "没有可优化的内容",
"localSkillsTab": "本地技能",
"marketplaceTab": "技能市场",
"refreshMarketplace": "刷新市场",
"searchMarketplacePlaceholder": "搜索技能名称、标识或标签",
"marketplaceEmpty": "当前没有可用的市场技能",
"installFromMarketplace": "安装",
"viewSource": "查看源码",
"marketCount": "已启用市场 {{enabled}} / {{total}}",
"marketRefreshSummary": "成功拉取 {{success}} / {{total}}",
"manageMarkets": "管理市场",
"addMarket": "新增市场",
"removeMarket": "移除",
"validateMarket": "校验",
"noMarketsConfigured": "尚未配置市场",
"marketId": "市场 ID",
"marketName": "市场名称",
"marketUrl": "仓库地址",
"marketBranch": "分支(可选)",
"marketPath": "索引路径",
"marketOrder": "排序",
"marketEnabled": "启用此市场",
"marketValidated": "已校验",
"marketPendingValidation": "待校验",
"marketSaveRequiresValidation": "保存前需要先校验所有市场配置。",
"marketSaveRequiresFields": "请先填写完整的市场 ID、名称和仓库地址。",
"marketSaveRequiresUniqueId": "市场 ID 不能重复,请修改后再保存。",
"marketUrlPlaceholder": "支持 owner/repo、.git 地址,或 GitHub tree URL",
"marketUrlExamples": "示例:openclaw/openclaw 或 https://github.com/openclaw/openclaw/tree/main/skills",
"marketAutoParse": "自动解析",
"marketUrlAutoParsed": "已自动解析 URL,分支:{{branch}},路径:{{path}}",
"refreshingMarketplace": "市场刷新中 {{progress}}%",
"loadMarketsFailed": "加载技能市场配置失败",
"validateMarketSuccess": "市场校验成功:{{name}}",
"validateMarketFailed": "市场校验失败",
"saveMarketsSuccess": "技能市场配置已更新",
"saveMarketsFailed": "更新技能市场配置失败",
"loadMarketplaceFailed": "加载技能市场失败",
"installMarketplaceSuccess": "技能安装成功:{{name}}",
"installMarketplaceFailed": "安装失败",
"overwriteConfirmTitle": "技能已安装",
"overwriteConfirmContent": "技能「{{name}}」已存在,是否强制覆盖安装?",
"overwriteConfirmOk": "强制安装",
"overwriteConfirmCancel": "取消"
},
"mcp": {
"title": "MCP 客户端",
Expand Down
Loading
Loading