From ddd3878736bb1bfc4620a08a08c773c61fd45551 Mon Sep 17 00:00:00 2001 From: loop Date: Sat, 18 Apr 2026 15:39:16 +0800 Subject: [PATCH] refactor: simplify skill catalog metadata --- .../router_rules/router_rules.json | 22 ----------------- .../basic_demo/main/skills/skills_list.json | 1 - .../cap_im_feishu/skills/skills_list.json | 1 - .../cap_im_qq/skills/skills_list.json | 1 - .../cap_im_tg/skills/skills_list.json | 1 - .../cap_im_wechat/skills/skills_list.json | 1 - .../cap_llm_inspect/skills/skills_list.json | 1 - .../cap_lua/skills/skills_list.json | 1 - .../cap_router_mgr/skills/skills_list.json | 1 - .../cap_scheduler/skills/skills_list.json | 1 - .../cap_skill_mgr/src/cap_skill_mgr.c | 9 ++----- .../cap_skill_mgr/src/cmd_cap_skill.c | 11 +++------ .../claw_modules/claw_core/src/claw_core.c | 24 ++++++++++++------- .../claw_modules/claw_skill/src/claw_skill.c | 13 +++------- 14 files changed, 23 insertions(+), 65 deletions(-) diff --git a/application/basic_demo/fatfs_image/router_rules/router_rules.json b/application/basic_demo/fatfs_image/router_rules/router_rules.json index 6a5734b..ffbe477 100644 --- a/application/basic_demo/fatfs_image/router_rules/router_rules.json +++ b/application/basic_demo/fatfs_image/router_rules/router_rules.json @@ -27,28 +27,6 @@ } ] }, - { - "id": "im_hello_esp_claw", - "description": "Intercept IM hello! ESP-Claw and reply directly.Just for demonstration", - "enabled": true, - "ack": "{{event.source_channel}} hello intercepted", - "match": { - "event_type": "message", - "event_key": "text", - "content_type": "text", - "text": "hello! ESP-Claw" - }, - "actions": [ - { - "type": "send_message", - "input": { - "channel": "{{event.source_channel}}", - "chat_id": "{{event.chat_id}}", - "message": "Nice to meet you!" - } - } - ] - }, { "id": "im_any_message_working_reply", "description": "Reply to any IM text message before other automation handling.", diff --git a/application/basic_demo/main/skills/skills_list.json b/application/basic_demo/main/skills/skills_list.json index 7b72513..31af24c 100644 --- a/application/basic_demo/main/skills/skills_list.json +++ b/application/basic_demo/main/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "weather_search", "file": "weather.md", - "title": "weather", "summary": "How to answer current weather, temperature, and forecast queries through direct web search capabilities.", "cap_groups": [ "cap_time", diff --git a/components/claw_capabilities/cap_im_feishu/skills/skills_list.json b/components/claw_capabilities/cap_im_feishu/skills/skills_list.json index 5140ebe..53faf51 100644 --- a/components/claw_capabilities/cap_im_feishu/skills/skills_list.json +++ b/components/claw_capabilities/cap_im_feishu/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "cap_im_feishu", "file": "cap_im_feishu.md", - "title": "cap_im_feishu", "summary": "How to send additional text, images, and files to Feishu.", "cap_groups": [ "cap_im_feishu" diff --git a/components/claw_capabilities/cap_im_qq/skills/skills_list.json b/components/claw_capabilities/cap_im_qq/skills/skills_list.json index 219ed5a..799a900 100644 --- a/components/claw_capabilities/cap_im_qq/skills/skills_list.json +++ b/components/claw_capabilities/cap_im_qq/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "cap_im_qq", "file": "cap_im_qq.md", - "title": "cap_im_qq", "summary": "How to send additional text or send local files back to QQ.", "cap_groups": [ "cap_im_qq" diff --git a/components/claw_capabilities/cap_im_tg/skills/skills_list.json b/components/claw_capabilities/cap_im_tg/skills/skills_list.json index 9b5610c..602b575 100644 --- a/components/claw_capabilities/cap_im_tg/skills/skills_list.json +++ b/components/claw_capabilities/cap_im_tg/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "cap_im_tg", "file": "cap_im_tg.md", - "title": "cap_im_tg", "summary": "How to send additional text, images, and files to Telegram.", "cap_groups": [ "cap_im_tg" diff --git a/components/claw_capabilities/cap_im_wechat/skills/skills_list.json b/components/claw_capabilities/cap_im_wechat/skills/skills_list.json index a6867e0..3b8ecfc 100644 --- a/components/claw_capabilities/cap_im_wechat/skills/skills_list.json +++ b/components/claw_capabilities/cap_im_wechat/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "cap_im_wechat", "file": "cap_im_wechat.md", - "title": "cap_im_wechat", "summary": "How to send additional text and images to WeChat.", "cap_groups": [ "cap_im_wechat" diff --git a/components/claw_capabilities/cap_llm_inspect/skills/skills_list.json b/components/claw_capabilities/cap_llm_inspect/skills/skills_list.json index dfb7a95..1b8eb8a 100644 --- a/components/claw_capabilities/cap_llm_inspect/skills/skills_list.json +++ b/components/claw_capabilities/cap_llm_inspect/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "cap_llm_inspect_image", "file": "cap_llm_inspect.md", - "title": "cap_llm_inspect_image", "summary": "How to inspect a local image with inspect_image.", "cap_groups": [ "cap_llm_inspect" diff --git a/components/claw_capabilities/cap_lua/skills/skills_list.json b/components/claw_capabilities/cap_lua/skills/skills_list.json index 3f50b78..d040ffd 100644 --- a/components/claw_capabilities/cap_lua/skills/skills_list.json +++ b/components/claw_capabilities/cap_lua/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "cap_lua_run", "file": "cap_lua_run.md", - "title": "cap_lua_run", "summary": "This Files describes how to correctly use Lua scripts.", "cap_groups": [ "cap_lua" diff --git a/components/claw_capabilities/cap_router_mgr/skills/skills_list.json b/components/claw_capabilities/cap_router_mgr/skills/skills_list.json index b515491..f0ecb4a 100644 --- a/components/claw_capabilities/cap_router_mgr/skills/skills_list.json +++ b/components/claw_capabilities/cap_router_mgr/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "cap_router_mgr", "file": "cap_router_mgr.md", - "title": "cap_router_mgr", "summary": "Manage router automation rules: list/get/add/update/delete/reload with strict rule_json format.", "cap_groups": [ "cap_router_mgr" diff --git a/components/claw_capabilities/cap_scheduler/skills/skills_list.json b/components/claw_capabilities/cap_scheduler/skills/skills_list.json index 52df984..8b1e61d 100644 --- a/components/claw_capabilities/cap_scheduler/skills/skills_list.json +++ b/components/claw_capabilities/cap_scheduler/skills/skills_list.json @@ -3,7 +3,6 @@ { "id": "cap_scheduler", "file": "cap_scheduler.md", - "title": "cap_scheduler", "summary": "Manage scheduler rules: list/get/add/enable/disable/pause/resume/trigger/reload.", "cap_groups": [ "cap_scheduler" diff --git a/components/claw_capabilities/cap_skill_mgr/src/cap_skill_mgr.c b/components/claw_capabilities/cap_skill_mgr/src/cap_skill_mgr.c index d9e4932..f0e0646 100644 --- a/components/claw_capabilities/cap_skill_mgr/src/cap_skill_mgr.c +++ b/components/claw_capabilities/cap_skill_mgr/src/cap_skill_mgr.c @@ -558,7 +558,6 @@ static esp_err_t cap_skill_register_execute(const char *input_json, cJSON *skills = NULL; cJSON *skill_id_item = NULL; cJSON *file_item = NULL; - cJSON *title_item = NULL; cJSON *summary_item = NULL; cJSON *skill = NULL; esp_err_t err; @@ -573,14 +572,12 @@ static esp_err_t cap_skill_register_execute(const char *input_json, skill_id_item = cJSON_GetObjectItemCaseSensitive(root, "skill_id"); file_item = cJSON_GetObjectItemCaseSensitive(root, "file"); - title_item = cJSON_GetObjectItemCaseSensitive(root, "title"); summary_item = cJSON_GetObjectItemCaseSensitive(root, "summary"); if (!cJSON_IsString(skill_id_item) || !skill_id_item->valuestring || !skill_id_item->valuestring[0] || !cJSON_IsString(file_item) || !file_item->valuestring || !file_item->valuestring[0] || - !cJSON_IsString(title_item) || !title_item->valuestring || !title_item->valuestring[0] || !cJSON_IsString(summary_item) || !summary_item->valuestring || !summary_item->valuestring[0]) { cJSON_Delete(root); - cap_skill_write_error(output, output_size, "skill_id, file, title and summary are required", NULL); + cap_skill_write_error(output, output_size, "skill_id, file and summary are required", NULL); return ESP_ERR_INVALID_ARG; } @@ -642,7 +639,6 @@ static esp_err_t cap_skill_register_execute(const char *input_json, } cJSON_AddStringToObject(skill, "id", skill_id_item->valuestring); cJSON_AddStringToObject(skill, "file", file_item->valuestring); - cJSON_AddStringToObject(skill, "title", title_item->valuestring); cJSON_AddStringToObject(skill, "summary", summary_item->valuestring); cJSON_AddItemToArray(skills, skill); @@ -677,7 +673,6 @@ static esp_err_t cap_skill_register_execute(const char *input_json, } cJSON_AddStringToObject(skill, "id", skill_id_item->valuestring); cJSON_AddStringToObject(skill, "file", file_item->valuestring); - cJSON_AddStringToObject(skill, "title", title_item->valuestring); cJSON_AddStringToObject(skill, "summary", summary_item->valuestring); cJSON_Delete(root); @@ -778,7 +773,7 @@ static const claw_cap_descriptor_t s_skill_descriptors[] = { .kind = CLAW_CAP_KIND_CALLABLE, .cap_flags = CLAW_CAP_FLAG_CALLABLE_BY_LLM, .input_schema_json = - "{\"type\":\"object\",\"properties\":{\"skill_id\":{\"type\":\"string\"},\"file\":{\"type\":\"string\"},\"title\":{\"type\":\"string\"},\"summary\":{\"type\":\"string\"}},\"required\":[\"skill_id\",\"file\",\"title\",\"summary\"]}", + "{\"type\":\"object\",\"properties\":{\"skill_id\":{\"type\":\"string\"},\"file\":{\"type\":\"string\"},\"summary\":{\"type\":\"string\"}},\"required\":[\"skill_id\",\"file\",\"summary\"]}", .execute = cap_skill_register_execute, }, { diff --git a/components/claw_capabilities/cap_skill_mgr/src/cmd_cap_skill.c b/components/claw_capabilities/cap_skill_mgr/src/cmd_cap_skill.c index 1521825..c6aac1c 100644 --- a/components/claw_capabilities/cap_skill_mgr/src/cmd_cap_skill.c +++ b/components/claw_capabilities/cap_skill_mgr/src/cmd_cap_skill.c @@ -22,7 +22,6 @@ static struct { struct arg_str *register_skill; struct arg_str *unregister_skill; struct arg_str *file; - struct arg_str *title; struct arg_str *summary; struct arg_str *activate; struct arg_str *deactivate; @@ -66,7 +65,6 @@ static int call_skill_cap(const char *cap_name, const char *input_json, const ch static char *build_register_skill_json(const char *skill_id, const char *file, - const char *title, const char *summary) { cJSON *root = NULL; @@ -79,7 +77,6 @@ static char *build_register_skill_json(const char *skill_id, cJSON_AddStringToObject(root, "skill_id", skill_id); cJSON_AddStringToObject(root, "file", file); - cJSON_AddStringToObject(root, "title", title); cJSON_AddStringToObject(root, "summary", summary); rendered = cJSON_PrintUnformatted(root); cJSON_Delete(root); @@ -134,14 +131,13 @@ static int skill_func(int argc, char **argv) } if (skill_args.register_skill->count) { - if (!skill_args.file->count || !skill_args.title->count || !skill_args.summary->count) { - printf("--register requires --file, --title and --summary\n"); + if (!skill_args.file->count || !skill_args.summary->count) { + printf("--register requires --file and --summary\n"); return 1; } input_json = build_register_skill_json(skill_args.register_skill->sval[0], skill_args.file->sval[0], - skill_args.title->sval[0], skill_args.summary->sval[0]); if (!input_json) { printf("Out of memory\n"); @@ -211,7 +207,6 @@ void register_cap_skill(void) skill_args.register_skill = arg_str0("r", "register", "", "Register one skill in the catalog"); skill_args.unregister_skill = arg_str0("u", "unregister", "", "Remove one skill from the catalog"); skill_args.file = arg_str0("f", "file", "", "Skill markdown path relative to /skills"); - skill_args.title = arg_str0("t", "title", "", "Skill title for catalog registration"); skill_args.summary = arg_str0(NULL, "summary", "<summary>", "Skill summary for catalog registration"); skill_args.activate = arg_str0("a", "activate", "<skill_id>", "Activate one skill"); skill_args.deactivate = arg_str0("d", "deactivate", "<skill_id>", "Deactivate one skill"); @@ -224,7 +219,7 @@ void register_cap_skill(void) .help = "Skill operations.\n" "Examples:\n" " skill --catalog\n" - " skill --register weather_v2 --file weather_v2.md --title \"Weather V2\" --summary \"Get forecast and alerts\"\n" + " skill --register weather_v2 --file weather_v2.md --summary \"Get forecast and alerts\"\n" " skill --unregister weather_v2\n" " skill --list --session default\n" " skill --activate weather --session default\n" diff --git a/components/claw_modules/claw_core/src/claw_core.c b/components/claw_modules/claw_core/src/claw_core.c index b677bc4..aa14b18 100644 --- a/components/claw_modules/claw_core/src/claw_core.c +++ b/components/claw_modules/claw_core/src/claw_core.c @@ -352,6 +352,11 @@ static esp_err_t build_response_payload_json(const claw_core_request_t *request, cJSON_Delete(root); return ESP_ERR_NO_MEM; } + if (response->error_message && response->error_message[0] && + !cJSON_AddStringToObject(root, "error_message", response->error_message)) { + cJSON_Delete(root); + return ESP_ERR_NO_MEM; + } payload_json = cJSON_PrintUnformatted(root); cJSON_Delete(root); @@ -370,18 +375,23 @@ static esp_err_t build_agent_response_event(const claw_core_request_t *request, { const char *channel = NULL; const char *chat_id = NULL; + const char *text = NULL; int64_t now_ms; esp_err_t err; - if (!request || !response || !out_event || !out_payload_json || - response->status != CLAW_CORE_RESPONSE_STATUS_OK || - !response->text || !response->text[0]) { + if (!request || !response || !out_event || !out_payload_json) { return ESP_ERR_INVALID_ARG; } memset(out_event, 0, sizeof(*out_event)); *out_payload_json = NULL; + text = (response->status == CLAW_CORE_RESPONSE_STATUS_OK) ? + response->text : response->error_message; + if (!text || !text[0]) { + return ESP_ERR_INVALID_ARG; + } + err = build_response_payload_json(request, response, out_payload_json); if (err != ESP_OK) { return err; @@ -416,7 +426,7 @@ static esp_err_t build_agent_response_event(const claw_core_request_t *request, } out_event->timestamp_ms = now_ms; out_event->session_policy = CLAW_EVENT_SESSION_POLICY_CHAT; - out_event->text = response->text; + out_event->text = (char *)text; out_event->payload_json = *out_payload_json; return ESP_OK; @@ -433,10 +443,6 @@ static void publish_response_event_if_requested(const claw_core_request_item_t * !(request->view.flags & CLAW_CORE_REQUEST_FLAG_PUBLISH_RESPONSE_EVENT)) { return; } - if (response->view.status != CLAW_CORE_RESPONSE_STATUS_OK || - !response->view.text || !response->view.text[0]) { - return; - } err = build_agent_response_event(&request->view, &response->view, @@ -946,7 +952,7 @@ static esp_err_t build_iteration_context(const claw_core_request_item_t *request goto cleanup; } context_len = strlen(context.content); - ESP_LOGD(TAG, + ESP_LOGI(TAG, "context_loaded request=%" PRIu32 " provider=%s context_kind=%s context_len=%u", request->view.request_id, provider->name, diff --git a/components/claw_modules/claw_skill/src/claw_skill.c b/components/claw_modules/claw_skill/src/claw_skill.c index d2ca928..e52c04b 100644 --- a/components/claw_modules/claw_skill/src/claw_skill.c +++ b/components/claw_modules/claw_skill/src/claw_skill.c @@ -26,7 +26,6 @@ static const char *SKILLS_LIST_FILE = "skills_list.json"; typedef struct { char *id; char *file; - char *title; char *summary; char **cap_groups; size_t cap_group_count; @@ -113,7 +112,6 @@ static void free_registry_entry(claw_skill_registry_entry_t *entry) free(entry->id); free(entry->file); - free(entry->title); free(entry->summary); free_string_array(entry->cap_groups, entry->cap_group_count); memset(entry, 0, sizeof(*entry)); @@ -456,7 +454,7 @@ static esp_err_t validate_registry_entry(claw_skill_registry_entry_t *entry) FILE *file = NULL; size_t i; - if (!entry || !entry->id || !entry->file || !entry->title || !entry->summary) { + if (!entry || !entry->id || !entry->file || !entry->summary) { return ESP_ERR_INVALID_ARG; } if (!skill_path_is_valid(entry->file) || !is_markdown_skill_file(entry->file)) { @@ -543,9 +541,6 @@ static esp_err_t load_registry_from_json(void) if (err == ESP_OK) { err = json_dup_required_string(skill, "file", &entry->file); } - if (err == ESP_OK) { - err = json_dup_required_string(skill, "title", &entry->title); - } if (err == ESP_OK) { err = json_dup_required_string(skill, "summary", &entry->summary); } @@ -746,8 +741,7 @@ static esp_err_t claw_skill_render_skills_list(char *buf, size_t size) off += snprintf(buf + off, size - off, - "- %s (%s): %s\n", - entry->title, + "- %s: %s\n", entry->id, entry->summary); } @@ -792,7 +786,7 @@ static esp_err_t claw_skill_build_prompt_block(const char *const *skill_ids, size - off, "%s### %s\n%s\n", i == 0 ? "" : "\n", - entry->title, + entry->id, content); free(content); } @@ -1024,7 +1018,6 @@ static esp_err_t claw_skill_skills_list_collect(const claw_core_request_t *reque content_size = 64; for (size_t i = 0; i < s_skill.entry_count; i++) { - content_size += strlen(s_skill.entries[i].title ? s_skill.entries[i].title : ""); content_size += strlen(s_skill.entries[i].id ? s_skill.entries[i].id : ""); content_size += strlen(s_skill.entries[i].summary ? s_skill.entries[i].summary : ""); content_size += 16;