Skip to content

fix: 修复 Playground-only Agent 工具 Schema 与联合类型兼容 - #47

Merged
Mag1cFall merged 2 commits into
Mag1cFall:mainfrom
anon0v0:fix/playground-schema-fallback
Oct 5, 2026
Merged

Mag1cFall merged 2 commits into
Mag1cFall:mainfrom
anon0v0:fix/playground-schema-fallback

Conversation

@anon0v0

@anon0v0 anon0v0 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

问题:一个辅助工具的 Schema 阻断整个 Agent 任务

v0.2.4 为保留开放 Schema 的语义,遇到 TYPE_UNSPECIFIED 节点时选择 Build。这对仅启用 Playground 的已有部署形成兼容变化。此 PR 最初加入显式开启的旧版缺省类型回退,但仍拒绝混合 anyOf;实际文件/代码任务因此继续在生成前失败。

本次基于真实失败请求的脱敏结构定位:工具列表中的 asktool 参数路径为:

questions.items.properties.options.items.anyOf

选项同时支持字符串与 {label, description} 对象:

{
  "anyOf": [
    {"type": "string"},
    {
      "type": "object",
      "properties": {
        "label": {"type": "string"},
        "description": {"type": "string"}
      },
      "required": ["label"]
    }
  ]
}

生成请求会携带整套工具,而不是只携带即将执行的 Read/Write。因此,即使任务只是操作文件、不准备提问,也会在本地收到:

function ... parameters 无法回退 Playground:
properties.questions: items: properties.options: items:
含 anyOf 的无类型节点需要显式类型或 Build 通道

此时尚未发起上游生成,模型没有机会选择文件工具。

修复内容与边界

保留 PLAYGROUND_SCHEMA_FALLBACK=false 默认关闭,不更改官方严格模式。显式开启且 Build 未启用时:

  1. 保留最初的缺省类型兼容:无约束缺省节点补 string,缺少 items 的普通数组补字符串元素类型。
  2. 对没有根类型的单个 anyOf/oneOf,首个分支可推导出具体类型时,补充该根类型。不删除任意分支,也不删除分支上的 required、enum、数值限制或 oneOf 排他条件。 首分支为 array 时还需明确、可编码的 items,并保留它的类型。
  3. 在整个请求的私有副本上处理;所有工具通过且最终不再需要 Build 才放行。原工具声明、历史消息、工具返回和非相关 Read/Write 工具均不修改。
  4. 无法确定首分支类型、无类型的组合/否定约束、无法编码的数组分支、原生布尔 Schema 仍明确报错;不通过删除限制来“修复”。不改写 response schema。
  5. Build 已启用时保留原生路由,包括暂时忙碌或无可用账户的情况;不自动开启 Build,不因冷却跨通道降级。tool_choice:none 忽略的工具不触发兼容处理。
  6. 配置、管理 API、设置页中英文风险提示、持久化、重启标记和 WARN 信息已一致更新。

这是有损的旧版兼容模式,不是任意 JSON Schema 的无损转换。 上例会在保留原 anyOf 的同时增加 type:string,从而使用客户端本就接受的纯文本选项;对象选项不再由这条兼容请求生成。优先建议明确工具实际类型,或使用可完整表达原 Schema 的通道。

关闭开关并重启生成服务即可恢复严格模式,无需账号/聊天数据迁移。

验证结果

修复前后同形对照

  • 修改前新增回归测试在 asktool.questions[].options[] 的混合 Schema 上失败。
  • 线上旧补丁+原始混合 Schema:受限文件任务返回 400,任何工具都未执行。
  • 相同任务仅手工补联合根类型:Read(input.json) → Write(result.json) → 最终回复 成功,结果文件解析为 {"sum":10,"count":3}。用于确认该字段确是阻断点,不作为新程序验收替代。
  • 部署新代码后,使用未手工改写的原始混合 Schema:同一文件任务完成,结果文件内容验证通过。
  • 经 OpenAI 兼容中转链路再次执行该任务也通过。测试仅允许在临时目录中读 input.json、写 result.json,不允许任意 shell 或触碰原有文件。
  • 用户保持原模型/工具设置重试原来的文件/代码任务后确认恢复;服务侧原先失败的长上下文请求已返回 200,并继续多轮工具调用。用户产物完成情况来自用户确认,未将自动小任务的成功冒充对用户全部产物的独立检查。

自动回归与构建

  • go test -count=1 ./...
  • go vet ./...
  • CGO_ENABLED=1 go test -race ./internal/aistudio ./internal/config ./internal/app
  • npm run lint、npm run build(含 vue-tsc)
  • Linux amd64 交叉构建,git diff --check

回归覆盖原错误结构、string/object 分支顺序、oneOf 重叠条件保留、数组首分支元素类型、nullable 联合、未知/布尔/冲突组合拒绝、原请求不变、非相关文件工具不变、严格模式与 Build 路由、response schema 保留,以及原有配置往返/并发隔离测试。

已有缺省 items 工具调用、第二轮工具结果、流式输出、显式 false 仍拒绝、管理登录/退出与权限保护均实测通过。

PR 范围整理

  • 在同一 PR 中补充一个 Schema 修复提交,保留可审阅的演进历史,不强推重写。
  • PR 不包含独立的 assistant 尾轮续写补丁、部署脚本、诊断观察器、服务器设置、账号凭据、真实聊天或产物数据。部署环境另行保留了既有尾轮修复,未将它混入此 Schema PR。
  • 未修改额度算法、WAA 后端、模型目录、账号路由或依赖版本。
  • 未验证所有模型及任意 JSON Schema;现场验证针对本次 string/object 工具组合,其他组合由明确的边界和回归测试约束。

@anon0v0 anon0v0 changed the title feat: 为 Playground-only 增加显式工具 Schema 兼容回退 fix: 修复 Playground-only Agent 工具 Schema 与联合类型兼容 Oct 5, 2026
@Mag1cFall
Mag1cFall merged commit 1489dfa into Mag1cFall:main Oct 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants