From c61a1e86846dd7efb49ac3afc1dc94ed4a87ecf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E9=A3=8E?= Date: Wed, 14 Jan 2026 13:35:21 +0800 Subject: [PATCH 1/4] =?UTF-8?q?refactor(CodeactAgentConfig):=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E9=85=8D=E7=BD=AE=E7=B1=BB=E7=BB=93=E6=9E=84=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=90=9C=E7=B4=A2=E5=B7=A5=E5=85=B7=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tools/UnifiedSearchCodeactTool.java | 93 ++++++++++++++----- .../start/config}/CodeactAgentConfig.java | 21 +++-- 2 files changed, 81 insertions(+), 33 deletions(-) rename {assistant-agent-autoconfigure/src/main/java/com/alibaba/assistant/agent/autoconfigure => assistant-agent-start/src/main/java/com/alibaba/assistant/agent/start/config}/CodeactAgentConfig.java (96%) diff --git a/assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/UnifiedSearchCodeactTool.java b/assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/UnifiedSearchCodeactTool.java index 24a18f2..d5b9927 100644 --- a/assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/UnifiedSearchCodeactTool.java +++ b/assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/UnifiedSearchCodeactTool.java @@ -148,19 +148,48 @@ private SearchResultSet executeUnifiedSearch(Map params, ToolCon String query = (String) params.get("query"); Integer limit = params.containsKey("limit") ? ((Number) params.get("limit")).intValue() : 10; - // 解析要搜索的源类型列表 - List sourceTypes = parseSourceTypes(params); + // 解析要搜索的源 keys (可以是类型名,也可以是 provider 名) + List sourceKeys = parseSourceKeys(params); - log.info("UnifiedSearchCodeactTool#executeUnifiedSearch - reason=开始统一搜索, query={}, sourceTypes={}, limit={}", - query, sourceTypes, limit); + log.info("UnifiedSearchCodeactTool#executeUnifiedSearch - reason=开始统一搜索, query={}, sources={}, limit={}", + query, sourceKeys, limit); // 并行搜索多个数据源 List allItems = new ArrayList<>(); int successCount = 0; int failureCount = 0; - for (SearchSourceType sourceType : sourceTypes) { + for (String key : sourceKeys) { try { + // 1. 尝试作为 Provider Name 匹配 + Optional namedProvider = searchProviders.stream() + .filter(p -> p.getName().equalsIgnoreCase(key)) + .findFirst(); + + if (namedProvider.isPresent()) { + // 按指定 Provider 名称搜索 + SearchProvider provider = namedProvider.get(); + // 当指定具体 Provider 时,尝试使用 CUSTOM 类型,或者该 Provider 支持的第一个类型 + // 这里为了简单,我们传递 CUSTOM 类型,如果 Provider 不处理 SourceType 也没关系 + SearchRequest request = buildSearchRequest(query, SearchSourceType.CUSTOM, limit); + + List items = provider.search(request); + allItems.addAll(items); + successCount++; + log.debug("UnifiedSearchCodeactTool#executeUnifiedSearch - reason=指定Provider搜索成功, provider={}, resultCount={}", + provider.getName(), items.size()); + continue; + } + + // 2. 尝试作为 SourceType 匹配 + SearchSourceType sourceType; + try { + sourceType = SearchSourceType.valueOf(key.toUpperCase()); + } catch (IllegalArgumentException e) { + log.warn("UnifiedSearchCodeactTool#executeUnifiedSearch - reason=无效的源类型或Provider名称, key={}", key); + continue; + } + // 查找支持该源类型的 provider List providers = searchProviders.stream() .filter(p -> p.supports(sourceType)) @@ -185,8 +214,8 @@ private SearchResultSet executeUnifiedSearch(Map params, ToolCon } catch (Exception e) { failureCount++; - log.error("UnifiedSearchCodeactTool#executeUnifiedSearch - reason=单源搜索失败, sourceType={}, error={}", - sourceType, e.getMessage(), e); + log.error("UnifiedSearchCodeactTool#executeUnifiedSearch - reason=搜索执行失败, sourceKey={}, error={}", + key, e.getMessage(), e); } } @@ -208,10 +237,10 @@ private SearchResultSet executeUnifiedSearch(Map params, ToolCon } /** - * 解析要搜索的源类型列表。 + * 解析要搜索的源列表(字符串)。 */ - private List parseSourceTypes(Map params) { - List sourceTypes = new ArrayList<>(); + private List parseSourceKeys(Map params) { + List keys = new ArrayList<>(); // 如果指定了 sources 参数 if (params.containsKey("sources")) { @@ -219,24 +248,38 @@ private List parseSourceTypes(Map params) { if (sourcesObj instanceof List) { List sourcesList = (List) sourcesObj; for (Object source : sourcesList) { - try { - SearchSourceType type = SearchSourceType.valueOf(source.toString().toUpperCase()); - sourceTypes.add(type); - } - catch (Exception e) { - log.warn("UnifiedSearchCodeactTool#parseSourceTypes - reason=无效的源类型, source={}", source); + if (source != null) { + keys.add(source.toString()); } } } } - // 如果没有指定或解析失败,使用默认的源类型 - if (sourceTypes.isEmpty()) { - sourceTypes.add(SearchSourceType.PROJECT); - sourceTypes.add(SearchSourceType.KNOWLEDGE); + // 如果没有指定,使用默认的源类型 + if (keys.isEmpty()) { + keys.add(SearchSourceType.PROJECT.name()); + keys.add(SearchSourceType.KNOWLEDGE.name()); } - return sourceTypes; + return keys; + } + + /** + * 获取所有可用的源名称(包括标准类型和Provider名称)。 + */ + private List getAvailableSourceNames() { + List names = new ArrayList<>(); + // 添加标准类型 + for (SearchSourceType type : SearchSourceType.values()) { + names.add(type.name().toLowerCase()); + } + // 添加 Provider 名称 + if (searchProviders != null) { + for (SearchProvider p : searchProviders) { + names.add(p.getName()); + } + } + return names; } /** @@ -265,9 +308,9 @@ private CodeactToolDefinition buildCodeactDefinition() { .addParameter(ParameterNode.builder() .name("sources") .type(ParameterType.ARRAY) - .description("要搜索的数据源列表,默认搜索 project 和 knowledge") + .description("要搜索的数据源列表,支持标准类型(project, knowledge, web等)或指定Provider名称") .required(false) - .enumValues(Arrays.asList("project", "knowledge", "web", "experience")) + .enumValues(getAvailableSourceNames()) .build()) .addParameter(ParameterNode.builder() .name("limit") @@ -335,9 +378,9 @@ private String buildInputSchema() { sourcesProp.put("type", "array"); Map itemsProp = new LinkedHashMap<>(); itemsProp.put("type", "string"); - itemsProp.put("enum", Arrays.asList("project", "knowledge", "web", "experience")); + itemsProp.put("enum", getAvailableSourceNames()); sourcesProp.put("items", itemsProp); - sourcesProp.put("description", "要搜索的数据源列表,默认搜索 project 和 knowledge"); + sourcesProp.put("description", "要搜索的数据源列表,支持标准类型或Provider名称"); properties.put("sources", sourcesProp); // limit 参数(可选) diff --git a/assistant-agent-autoconfigure/src/main/java/com/alibaba/assistant/agent/autoconfigure/CodeactAgentConfig.java b/assistant-agent-start/src/main/java/com/alibaba/assistant/agent/start/config/CodeactAgentConfig.java similarity index 96% rename from assistant-agent-autoconfigure/src/main/java/com/alibaba/assistant/agent/autoconfigure/CodeactAgentConfig.java rename to assistant-agent-start/src/main/java/com/alibaba/assistant/agent/start/config/CodeactAgentConfig.java index 18bb715..94e1f14 100644 --- a/assistant-agent-autoconfigure/src/main/java/com/alibaba/assistant/agent/autoconfigure/CodeactAgentConfig.java +++ b/assistant-agent-start/src/main/java/com/alibaba/assistant/agent/start/config/CodeactAgentConfig.java @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.assistant.agent.autoconfigure; +package com.alibaba.assistant.agent.start.config; +import com.alibaba.assistant.agent.autoconfigure.CodeactAgent; import com.alibaba.assistant.agent.common.tools.CodeactTool; import com.alibaba.assistant.agent.common.tools.ReplyCodeactTool; import com.alibaba.assistant.agent.common.tools.SearchCodeactTool; @@ -26,6 +27,7 @@ import com.alibaba.assistant.agent.extension.experience.fastintent.FastIntentService; import com.alibaba.assistant.agent.extension.experience.hook.FastIntentReactHook; import com.alibaba.assistant.agent.extension.experience.spi.ExperienceProvider; +import com.alibaba.assistant.agent.extension.search.tools.SearchCodeactToolFactory; import com.alibaba.assistant.agent.extension.search.tools.UnifiedSearchCodeactTool; import com.alibaba.assistant.agent.common.enums.Language; import com.alibaba.cloud.ai.graph.agent.hook.Hook; @@ -245,7 +247,7 @@ def subscribe_medicine_reminder(): * * @param chatModel Spring AI的ChatModel * @param replyCodeactTools Reply模块的工具列表(可选) - * @param searchCodeactTools Search模块的工具列表(可选) + * @param searchCodeactToolFactory Search模块的工具工厂(可选) * @param triggerCodeactTools Trigger模块的工具列表(可选) * @param unifiedSearchCodeactTool 统一搜索工具(可选) * @param mcpToolCallbackProvider MCP工具提供者(由MCP Client Boot Starter自动注入,可选) @@ -254,7 +256,7 @@ def subscribe_medicine_reminder(): public CodeactAgent grayscaleCodeactAgent( ChatModel chatModel, @Autowired(required = false) List replyCodeactTools, - @Autowired(required = false) List searchCodeactTools, + @Autowired(required = false) SearchCodeactToolFactory searchCodeactToolFactory, @Autowired(required = false) List triggerCodeactTools, @Autowired(required = false) UnifiedSearchCodeactTool unifiedSearchCodeactTool, @Autowired(required = false) ToolCallbackProvider mcpToolCallbackProvider, @@ -277,9 +279,12 @@ public CodeactAgent grayscaleCodeactAgent( } // 添加Search工具 - if (searchCodeactTools != null && !searchCodeactTools.isEmpty()) { - allCodeactTools.addAll(searchCodeactTools); - logger.info("CodeactAgentConfig#grayscaleCodeactAgent - reason=添加SearchCodeactTools, count={}", searchCodeactTools.size()); + if (searchCodeactToolFactory != null) { + List searchTools = searchCodeactToolFactory.createTools(); + if (!searchTools.isEmpty()) { + allCodeactTools.addAll(searchTools); + logger.info("CodeactAgentConfig#grayscaleCodeactAgent - reason=添加SearchCodeactTools, count={}", searchTools.size()); + } } // 添加Reply工具 @@ -359,12 +364,12 @@ public CodeactAgent grayscaleCodeactAgent( .codingChatModel(chatModel) .language(Language.PYTHON) // CodeactAgentBuilder特有方法 // 使用 qwen-coder-plus 模型进行代码生成 - .codeGenerationModelName("qwen3-coder-plus") + .codeGenerationModelName("aliyun-qwen3-coder-plus") .enableInitialCodeGen(true) .allowIO(false) .allowNativeAccess(false) .executionTimeout(30000) - .tools(replyCodeactTools.toArray(new ToolCallback[0])) + .tools(replyCodeactTools != null ? replyCodeactTools.toArray(new ToolCallback[0]) : new ToolCallback[0]) .codeactTools(allCodeactTools) .hooks(reactHooks) .subAgentHooks(codeactHooks) From bb46da3935ed84098d2beefc686fec6545645630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E9=A3=8E?= Date: Wed, 14 Jan 2026 13:37:07 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix(CodeactAgentConfig):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assistant/agent/start/config/CodeactAgentConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assistant-agent-start/src/main/java/com/alibaba/assistant/agent/start/config/CodeactAgentConfig.java b/assistant-agent-start/src/main/java/com/alibaba/assistant/agent/start/config/CodeactAgentConfig.java index 94e1f14..092d2be 100644 --- a/assistant-agent-start/src/main/java/com/alibaba/assistant/agent/start/config/CodeactAgentConfig.java +++ b/assistant-agent-start/src/main/java/com/alibaba/assistant/agent/start/config/CodeactAgentConfig.java @@ -364,7 +364,7 @@ public CodeactAgent grayscaleCodeactAgent( .codingChatModel(chatModel) .language(Language.PYTHON) // CodeactAgentBuilder特有方法 // 使用 qwen-coder-plus 模型进行代码生成 - .codeGenerationModelName("aliyun-qwen3-coder-plus") + .codeGenerationModelName("qwen3-coder-plus") .enableInitialCodeGen(true) .allowIO(false) .allowNativeAccess(false) From 004cb9d52e728888fadb0cefe108e9557bcfa83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E9=A3=8E?= Date: Wed, 14 Jan 2026 14:11:32 +0800 Subject: [PATCH 3/4] =?UTF-8?q?docs(ISSUE=5FTEMPLATE):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=BC=BA=E9=99=B7=E6=8A=A5=E5=91=8A=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E4=B8=BA=E4=B8=AD=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新了缺陷报告模板的语言为中文,使其更易于中文用户理解和填写。增加了“修复方式”部分以便更好地指导用户选择合适的处理方式。 --- .github/ISSUE_TEMPLATE/bug_report.md | 61 ++++++++++++++++------------ .github/ISSUE_TEMPLATE/config.yml | 6 +++ 2 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 40dfe58..cce040d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,47 +1,55 @@ --- -name: Bug Report -about: Report a bug to help us improve +name: 缺陷报告 (Bug) +about: 提交缺陷以帮助我们改进 title: '[BUG] ' labels: bug assignees: '' --- -## Bug Description +## 修复方式(必选) -A clear and concise description of what the bug is. +你希望这个问题如何被解决?(请勾选一项) -## Steps to Reproduce +- [ ] 需要维护者修复(我暂时无法提交 PR) +- [ ] 我可以自行修复并提交 PR +- [ ] 不确定 / 需要讨论 -1. Go to '...' -2. Configure '...' -3. Call method '...' -4. See error +## 缺陷描述 -## Expected Behavior +请用简洁清晰的语言描述问题现象。 -A clear and concise description of what you expected to happen. +## 复现步骤 -## Actual Behavior +1. 进入 '...' +2. 配置 '...' +3. 调用方法 '...' +4. 看到错误 -What actually happened. +## 期望行为 -## Environment +你期望发生什么? -- **OS**: [e.g., macOS 14.0, Ubuntu 22.04] -- **Java Version**: [e.g., OpenJDK 17.0.2] -- **Assistant Agent Version**: [e.g., 1.0.0] -- **Spring Boot Version**: [e.g., 3.4.0] +## 实际行为 -## Logs/Stack Trace +实际发生了什么? + +## 环境信息 + +- **操作系统**: [例如 macOS 14.0, Ubuntu 22.04] +- **Java 版本**: [例如 OpenJDK 17.0.2] +- **Assistant Agent 版本**: [例如 1.0.0] +- **Spring Boot 版本**: [例如 3.4.0] + +## 日志/堆栈 ``` -Paste relevant logs or stack trace here +请粘贴相关日志或堆栈信息(注意去除敏感信息) ``` -## Configuration +## 配置 ```yaml -# Relevant configuration (remove sensitive data) +# 相关配置(请去除敏感信息) spring: ai: alibaba: @@ -50,11 +58,10 @@ spring: # ... ``` -## Additional Context - -Add any other context about the problem here. +## 额外上下文 -## Possible Solution (optional) +补充任何其他有助于定位问题的信息(例如:相关链接、截图、录屏、最小复现仓库等)。 -If you have an idea of what might be causing this or how to fix it. +## 可能的解决方案(可选) +如果你已经有初步排查结果或修复思路,请写在这里;如果你愿意提交 PR,也可以说明预计修改点/模块。 diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..ee76ad7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,6 @@ +blank_issues_enabled: false + +contact_links: + - name: 使用问题 / Q&A + url: https://github.com///discussions + about: 使用咨询、安装问题、如何配置等,请优先在 Discussions 提问。 From fe2945f81498c84e168ff22bd6e4702f552ef981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E9=A3=8E?= Date: Wed, 14 Jan 2026 14:14:53 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(UnifiedSearchCodeactTool):=20=E9=98=B2?= =?UTF-8?q?=E6=AD=A2=E7=A9=BA=E6=8C=87=E9=92=88=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复了在处理搜索结果时未检查 `items` 是否为空导致的潜在空指针异常问题。 --- .../extension/search/tools/UnifiedSearchCodeactTool.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/UnifiedSearchCodeactTool.java b/assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/UnifiedSearchCodeactTool.java index d5b9927..55c6005 100644 --- a/assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/UnifiedSearchCodeactTool.java +++ b/assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/search/tools/UnifiedSearchCodeactTool.java @@ -174,7 +174,9 @@ private SearchResultSet executeUnifiedSearch(Map params, ToolCon SearchRequest request = buildSearchRequest(query, SearchSourceType.CUSTOM, limit); List items = provider.search(request); - allItems.addAll(items); + if (items != null) { + allItems.addAll(items); + } successCount++; log.debug("UnifiedSearchCodeactTool#executeUnifiedSearch - reason=指定Provider搜索成功, provider={}, resultCount={}", provider.getName(), items.size());