fix: 修复技能调用白名单、脚本参数解析与工具失败结果回流问题 - #2849
Open
Greenplumwine wants to merge 4 commits into
Open
Conversation
ModelToolResultForTool 在工具失败时只回 Error 短信息,丢弃 Output。 execute_skill_script 把非零退出的 stdout/stderr 写进 Output,导致 AI 拿不到报错正文,无法诊断失败。失败且 Output 非空时将其拼到 Error 之后;对失败时不设 Output 的工具零影响。 Co-Authored-By: Claude <noreply@anthropic.com>
部分模型供应商把 execute_skill_script 的 args(schema 为 []string) emit 成 JSON 字符串,内容本身是个 JSON 数组("[\"--project-name\",\"X\"]")。 原 UnmarshalJSON 兜底用 strings.Fields 拆这种字符串,把方括号/引号拆成 垃圾 token,脚本 argv 全是乱码,argparse 永远报参数缺失,模型无论如何 调整格式都失败。改为先把字符串内容当 JSON 数组解析,成功即用;否则再 退回 strings.Fields。补 UnmarshalJSON 各形态单测。 Co-Authored-By: Claude <noreply@anthropic.com>
applyPerRequestSkillScope 原把 @mention 实现为收窄 AllowedSkills, 导致用户提及技能 A 后,智能体提示词要求调用未提及的技能 B 时 read_skill(B) 返回 "skill not allowed"。改为 @mention 只生成 <must_use> pin 提示,不动门控:智能体配置的全部技能始终可用, pin 仅记录被提及且当前允许的技能(空 AllowedSkills 视为全允许, 与 Manager.isSkillAllowed 一致)。 Co-Authored-By: Claude <noreply@anthropic.com>
handleToolResult 在 !success 时把 SSE 事件类型从 tool_result 改成 error,导致工具失败与模型流/pipeline 真错误共用 error 通道,前端只能 靠 tool_name 有无隐式区分。改为工具失败始终发 tool_result(success= false 区分成败),error 事件留给流程中断错误。 前端 useChatStreamHandler 同步收敛:error 事件短路到致命处理,不再 走无意义的 pending 工具卡匹配;tool_result 失败时显示完整 output (含 stdout/stderr)而非短 error 标签。 Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
本 PR 修复了技能调用与工具失败结果处理中的若干缺陷,按子系统拆分为 4 个独立提交:
1. 技能调用白名单(
internal/application/service/session_agent_qa.go)@mention原先被实现为收窄AllowedSkills,导致用户提及技能 A 后,智能体提示词要求调用未提及的技能 B 时read_skill(B)返回 "skill not allowed"。改为@mention只生成<must_use>pin 提示,不再改动门控:智能体配置的全部技能始终可用,pin 仅记录被提及且当前允许的技能(空AllowedSkills视为全允许,与Manager.isSkillAllowed一致)。2. 脚本参数解析(
internal/agent/tools/skill_execute.go)部分模型供应商把
execute_skill_script的args(schema 为[]string)emit 成 JSON 字符串,内容本身是个 JSON 数组(如"[\"--project-name\",\"X\"]")。原UnmarshalJSON兜底用strings.Fields拆分,把方括号/引号拆成垃圾 token,脚本 argv 全是乱码,argparse 永远报参数缺失。改为先把字符串内容当 JSON 数组解析,成功即用;否则再退回strings.Fields。3. 工具失败结果保留诊断信息(
internal/modelcontext/registry.go)ModelToolResultForTool在工具失败时只回 Error 短信息,丢弃Output。execute_skill_script把非零退出的 stdout/stderr 写进Output,导致 AI 拿不到报错正文,无法诊断失败。失败且Output非空时将其拼到 Error 之后;对失败时不设Output的工具零影响。4. 工具失败走 tool_result 而非 error 事件(
internal/handler/session/agent_stream_handler.go+frontend/src/composables/useChatStreamHandler.ts)handleToolResult在!success时把 SSE 事件类型从tool_result改成error,导致工具失败与流程中断错误共用error通道,前端只能靠tool_name有无隐式区分。改为工具失败始终发tool_result(success=false区分成败),error事件留给流程中断错误。前端useChatStreamHandler同步收敛:error事件短路到致命处理,tool_result失败时显示完整 output(含 stdout/stderr)。Type of Change
Related Issue
Fixes #
Testing
每个修复均附带或增强了单元测试,覆盖对应的边界形态:
internal/agent/tools/skill_execute_test.go:新增UnmarshalJSON各形态单测(JSON 数组字符串、普通空格分隔字符串、原生数组),验证 stringified JSON 数组可正确还原为 argv。internal/modelcontext/registry_test.go:验证工具失败时Output非空会被拼接到 Error 之后;失败时无Output的工具行为不变。internal/application/service/session_agent_qa_scope_test.go:验证@mention不再收窄AllowedSkills,pin 仅记录被提及且允许的技能。本地验证命令与结果:
Checklist
git diff --check origin/main...HEADpassesgofmt -l无输出)golangci-lint run --new-from-rev=upstream/main ./...针对变更包 0 issues)go build ./...通过;无关cmd/desktop|server的-lc++链接警告不影响)docs/, Swagger annotations, etc.) — 本 PR 无文档/接口契约变更,无需更新error收敛为tool_result(success=false),属行为修复,不破坏对外接口契约Screenshots / Recordings