From d5a17cfad93833166d7ff8607d331bd73eff024b Mon Sep 17 00:00:00 2001 From: lancefoever Date: Thu, 4 Jun 2026 10:50:05 +0800 Subject: [PATCH 1/3] Fix Nacos skill marketplace latest label resolution --- .../marketplace/NacosBuilderMarketplace.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java b/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java index 851dfa7f9b..86dd594a56 100644 --- a/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java +++ b/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java @@ -17,6 +17,7 @@ import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.ai.model.skills.Skill; +import com.alibaba.nacos.api.ai.model.skills.SkillMeta; import com.alibaba.nacos.api.ai.model.skills.SkillResource; import com.alibaba.nacos.api.ai.model.skills.SkillSummary; import com.alibaba.nacos.api.exception.NacosException; @@ -156,8 +157,24 @@ public MarketSkillContent fetch(String name) { return null; } try { - Skill skill = - service.skill().getSkillVersionDetail(namespaceId, name.trim(), LATEST_VERSION); + String skillName = name.trim(); + SkillMeta skillMeta = service.skill().getSkillMeta(namespaceId, skillName); + String version = + skillMeta != null && skillMeta.getLabels() != null + ? skillMeta.getLabels().get(LATEST_VERSION) + : null; + + if (version == null || version.isBlank()) { + throw new IllegalStateException( + "Cannot resolve Nacos skill version from label " + + LATEST_VERSION + + " for " + + namespaceId + + "/" + + skillName); + } + + Skill skill = service.skill().getSkillVersionDetail(namespaceId, skillName, version); if (skill == null || skill.getSkillMd() == null || skill.getSkillMd().isEmpty()) { return null; } From 147995cbcb68d1d818a98fb41a6911e3ff3b8f1d Mon Sep 17 00:00:00 2001 From: lancefoever Date: Thu, 4 Jun 2026 13:01:57 +0800 Subject: [PATCH 2/3] fix(builder): resolve Nacos latest skill version from metadata label --- .../marketplace/NacosBuilderMarketplace.java | 94 ++++++++++++++----- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java b/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java index 86dd594a56..6e2a4497c5 100644 --- a/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java +++ b/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java @@ -25,18 +25,16 @@ import com.alibaba.nacos.maintainer.client.ai.AiMaintainerFactory; import com.alibaba.nacos.maintainer.client.ai.AiMaintainerService; import com.alibaba.nacos.maintainer.client.ai.SkillMaintainerService; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.*; + /** * Nacos-backed marketplace. Uses the maintainer client (not the regular AiService client, - * which only exposes downloads) to drive the paged {@code listSkills} API and pull SKILL.md - * via {@code getSkillVersionDetail(..., "LATEST")}. + * which only exposes downloads) to drive the paged {@code listSkills} API. Skill content is + * fetched by resolving the real version from the skill metadata's {@code latest} label, then + * calling {@code getSkillVersionDetail(..., resolvedVersion)}. * *

Pagination: builder is a multi-tenant platform — but we still expect skill counts on the order of 100s per user, not millions. We page through * the upstream result in batches of {@link #PAGE_SIZE} until the server reports we have all @@ -48,7 +46,8 @@ public class NacosBuilderMarketplace implements BuilderMarketplace { private static final int PAGE_SIZE = 100; private static final int MAX_PAGES = 50; - private static final String LATEST_VERSION = "LATEST"; + private static final String LATEST_LABEL = "latest"; + private static final String ONLINE_STATUS = "online"; private final String id; private final String serverAddr; @@ -158,23 +157,12 @@ public MarketSkillContent fetch(String name) { } try { String skillName = name.trim(); - SkillMeta skillMeta = service.skill().getSkillMeta(namespaceId, skillName); - String version = - skillMeta != null && skillMeta.getLabels() != null - ? skillMeta.getLabels().get(LATEST_VERSION) - : null; + SkillMaintainerService skillService = service.skill(); + SkillMeta skillMeta = skillService.getSkillMeta(namespaceId, skillName); + String resolvedVersion = resolveLatestSkillVersion(namespaceId, skillName, skillMeta); - if (version == null || version.isBlank()) { - throw new IllegalStateException( - "Cannot resolve Nacos skill version from label " - + LATEST_VERSION - + " for " - + namespaceId - + "/" - + skillName); - } - - Skill skill = service.skill().getSkillVersionDetail(namespaceId, skillName, version); + Skill skill = + skillService.getSkillVersionDetail(namespaceId, skillName, resolvedVersion); if (skill == null || skill.getSkillMd() == null || skill.getSkillMd().isEmpty()) { return null; } @@ -219,4 +207,62 @@ public void close() { private static String blankToNull(String v) { return (v == null || v.isBlank()) ? null : v.trim(); } + + private static String resolveLatestSkillVersion( + String namespaceId, String skillName, SkillMeta skillMeta) { + String version = + skillMeta != null && skillMeta.getLabels() != null + ? skillMeta.getLabels().get(LATEST_LABEL) + : null; + if (version == null || version.isBlank()) { + throw new IllegalStateException( + "Nacos skill metadata is missing a '" + + LATEST_LABEL + + "' label for " + + namespaceId + + "/" + + skillName + + "; cannot resolve latest version"); + } + + if (skillMeta.getVersions() == null || skillMeta.getVersions().isEmpty()) { + throw new IllegalStateException( + "Nacos skill latest label points to unknown version '" + + version + + "' for " + + namespaceId + + "/" + + skillName + + "; metadata versions are empty"); + } + + for (SkillMeta.SkillVersionSummary summary : skillMeta.getVersions()) { + if (summary == null || !version.equals(summary.getVersion())) { + continue; + } + String status = summary.getStatus(); + if (!ONLINE_STATUS.equalsIgnoreCase(status)) { + throw new IllegalStateException( + "Nacos skill latest version '" + + version + + "' for " + + namespaceId + + "/" + + skillName + + " is not online" + + " (status=" + + status + + ")"); + } + return version; + } + + throw new IllegalStateException( + "Nacos skill latest label points to unknown version '" + + version + + "' for " + + namespaceId + + "/" + + skillName); + } } From dc6f8559947b4751245f57da31844c7cef7f5267 Mon Sep 17 00:00:00 2001 From: lancefoever Date: Thu, 4 Jun 2026 14:37:31 +0800 Subject: [PATCH 3/3] style(builder): replace wildcard import in Nacos marketplace --- .../runtime/marketplace/NacosBuilderMarketplace.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java b/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java index 6e2a4497c5..af3507c9ce 100644 --- a/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java +++ b/agentscope-examples/agents/agentscope-builder/src/main/java/io/agentscope/builder/runtime/marketplace/NacosBuilderMarketplace.java @@ -25,11 +25,14 @@ import com.alibaba.nacos.maintainer.client.ai.AiMaintainerFactory; import com.alibaba.nacos.maintainer.client.ai.AiMaintainerService; import com.alibaba.nacos.maintainer.client.ai.SkillMaintainerService; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; - /** * Nacos-backed marketplace. Uses the maintainer client (not the regular AiService client, * which only exposes downloads) to drive the paged {@code listSkills} API. Skill content is