Skip to content

Commit 6e052b8

Browse files
fix: Fixed issue with openclaw skill page return empty (#12347)
1 parent 1d40bdc commit 6e052b8

2 files changed

Lines changed: 52 additions & 31 deletions

File tree

agent/app/service/agents_overview.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func countOpenclawConfiguredChannels(conf map[string]interface{}) int {
103103

104104
func loadOpenclawOverviewSkillStats(containerName string) (int, error) {
105105
output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(
106-
"docker exec %s openclaw gateway call skills.status --json 2>&1",
106+
"docker exec %s openclaw skills list --json 2>&1",
107107
30*time.Second,
108108
containerName,
109109
)

agent/app/service/agents_skills.go

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ type openclawSkillListItem struct {
2323
Source string `json:"source"`
2424
Bundled bool `json:"bundled"`
2525
Disabled bool `json:"disabled"`
26-
SkillKey string `json:"skillKey"`
26+
}
27+
28+
type openclawSkillInfo struct {
29+
SkillKey string `json:"skillKey"`
2730
}
2831

2932
type skillhubSearchPayload struct {
@@ -32,6 +35,7 @@ type skillhubSearchPayload struct {
3235
}
3336

3437
var clawhubSearchLinePattern = regexp.MustCompile(`^(\S+)\s+(.+?)\s+\(([\d.]+)\)$`)
38+
var ansiEscapePattern = regexp.MustCompile(`\x1b\[[0-9;?]*[ -/]*[@-~]`)
3539

3640
func (a AgentService) ListSkills(req dto.AgentIDReq) ([]dto.AgentSkillItem, error) {
3741
_, install, err := a.loadOpenclawAgentAndInstall(req.AgentID)
@@ -41,7 +45,11 @@ func (a AgentService) ListSkills(req dto.AgentIDReq) ([]dto.AgentSkillItem, erro
4145
if err := ensureContainerRunning(install.ContainerName); err != nil {
4246
return nil, err
4347
}
44-
output, err := loadOpenclawSkillsStatus(install.ContainerName)
48+
output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(
49+
"docker exec %s openclaw skills list --json 2>&1",
50+
30*time.Second,
51+
install.ContainerName,
52+
)
4553
if err != nil {
4654
return nil, err
4755
}
@@ -86,7 +94,7 @@ func (a AgentService) UpdateSkill(req dto.AgentSkillUpdateReq) error {
8694
if err != nil {
8795
return err
8896
}
89-
skillKey, err := getOpenclawSkillKeyFromStatus(install.ContainerName, req.Name)
97+
skillKey, err := getOpenclawSkillKey(install.ContainerName, req.Name)
9098
if err != nil {
9199
return err
92100
}
@@ -119,12 +127,15 @@ func (a AgentService) InstallSkill(req dto.AgentSkillInstallReq) error {
119127
}
120128

121129
func parseOpenclawSkillsList(output string) ([]dto.AgentSkillItem, error) {
122-
trimmed := strings.TrimSpace(output)
123-
if trimmed == "" {
130+
payloadBytes, err := extractEmbeddedJSON(output)
131+
if err != nil {
132+
return nil, err
133+
}
134+
if len(payloadBytes) == 0 {
124135
return nil, nil
125136
}
126137
var payload openclawSkillsList
127-
if err := json.Unmarshal([]byte(trimmed), &payload); err != nil {
138+
if err := json.Unmarshal(payloadBytes, &payload); err != nil {
128139
return nil, err
129140
}
130141
items := make([]dto.AgentSkillItem, 0, len(payload.Skills))
@@ -140,14 +151,6 @@ func parseOpenclawSkillsList(output string) ([]dto.AgentSkillItem, error) {
140151
return items, nil
141152
}
142153

143-
func loadOpenclawSkillsStatus(containerName string) (string, error) {
144-
return cmd.RunDefaultWithStdoutBashCfAndTimeOut(
145-
"docker exec %s openclaw gateway call skills.status --json 2>&1",
146-
30*time.Second,
147-
containerName,
148-
)
149-
}
150-
151154
func loadOpenclawSkillSearchOutput(containerName, source, keyword string) (string, error) {
152155
switch source {
153156
case "skillhub":
@@ -229,32 +232,50 @@ func buildOpenclawSkillInstallCommand(source, slug string) string {
229232
}
230233
}
231234

232-
func getOpenclawSkillKeyFromStatus(containerName, name string) (string, error) {
233-
output, err := loadOpenclawSkillsStatus(containerName)
235+
func getOpenclawSkillKey(containerName, name string) (string, error) {
236+
output, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(
237+
"docker exec %s openclaw skills info %q --json 2>&1",
238+
30*time.Second,
239+
containerName,
240+
name,
241+
)
234242
if err != nil {
235243
return "", err
236244
}
237-
return parseOpenclawSkillKeyFromStatus(name, output)
245+
return parseOpenclawSkillKey(name, output)
238246
}
239247

240-
func parseOpenclawSkillKeyFromStatus(name, output string) (string, error) {
241-
trimmed := strings.TrimSpace(output)
242-
if trimmed == "" {
243-
return "", fmt.Errorf("skill %s does not have a skillKey", name)
248+
func parseOpenclawSkillKey(name, output string) (string, error) {
249+
payloadBytes, err := extractEmbeddedJSON(output)
250+
if err != nil {
251+
return "", err
244252
}
245-
var payload openclawSkillsList
246-
if err := json.Unmarshal([]byte(trimmed), &payload); err != nil {
253+
var payload openclawSkillInfo
254+
if err := json.Unmarshal(payloadBytes, &payload); err != nil {
247255
return "", err
248256
}
249-
for _, item := range payload.Skills {
250-
if item.Name == name {
251-
if item.SkillKey == "" {
252-
return "", fmt.Errorf("skill %s does not have a skillKey", name)
253-
}
254-
return item.SkillKey, nil
257+
if payload.SkillKey == "" {
258+
return "", fmt.Errorf("skill %s does not have a skillKey", name)
259+
}
260+
return payload.SkillKey, nil
261+
}
262+
263+
func extractEmbeddedJSON(output string) ([]byte, error) {
264+
trimmed := strings.TrimSpace(ansiEscapePattern.ReplaceAllString(output, ""))
265+
if trimmed == "" {
266+
return nil, nil
267+
}
268+
for i := 0; i < len(trimmed); i++ {
269+
if trimmed[i] != '{' && trimmed[i] != '[' {
270+
continue
271+
}
272+
decoder := json.NewDecoder(strings.NewReader(trimmed[i:]))
273+
var raw json.RawMessage
274+
if err := decoder.Decode(&raw); err == nil {
275+
return raw, nil
255276
}
256277
}
257-
return "", fmt.Errorf("skill %s not found", name)
278+
return nil, fmt.Errorf("json payload not found")
258279
}
259280

260281
func setOpenclawSkillEnabled(conf map[string]interface{}, skillKey string, enabled bool) {

0 commit comments

Comments
 (0)