Skip to content

bug(antigravity): 工具 Schema 转换静默删除 $ref 结果约束 #465

Description

@tt-a1i

问题

Antigravity 的工具 schema 转换会静默删除本地 $ref 指向的完整结果合同。引用字段最后可能变成 {},模型看不到原 schema 要求的嵌套字段、类型和枚举。

Direct Subagent 的 output_schema 和 Workflow 的 structured output 接受 JSON Schema。相同合同在本地参数校验和模型收到的工具声明之间发生语义漂移。

价值

让模型看到能够满足的结果合同,减少因隐藏要求而产生的校验失败和纠错回合。对于 provider 无法表达的 schema,调用前明确报错比悄悄删空约束更容易定位和修复。

审计边界

  • 检查日期:2026-09-08。
  • 固定源码:ed9dbc1018f890fd54375f5371990ddfee8af5df
  • 已验证:实际仓库本地 convertTools(..., true)sanitizeSchemaForCca 完整纯转换链。
  • 验证使用本地 converter 与从同一固定源码提取的 sanitizer;没有只凭 sanitizer 单点输出来推断上游转换结果。
  • 未验证:Antigravity 线上请求、HTTP 响应、真实模型任务或 provider 内部处理;不声称已经观察到 HTTP 400、重试次数或成功率变化。

触发条件

  1. 通过 Antigravity route 使用具有本地 $ref 的工具参数 schema,例如 Direct/Workflow 的结构化结果。
  2. 被引用的定义承载模型必须满足的结构或约束。
  3. 出站工具转换先删除定义,再删除引用;该字段变成无结构说明的空 schema。

最小输入

{
  "type": "object",
  "properties": {
    "answer": { "$ref": "#/$defs/Answer" }
  },
  "required": ["answer"],
  "$defs": {
    "Answer": {
      "type": "object",
      "properties": {
        "verdict": { "type": "string", "enum": ["pass", "fail"] }
      },
      "required": ["verdict"]
    }
  }
}

将该 schema 作为一个工具的 parameters,依照 buildTools 的顺序执行:

const declarations = convertTools([{
  name: "structured_output",
  description: "Return the final result",
  parameters: schema,
}], true);
const converted = declarations[0].functionDeclarations[0].parameters;
const wire = sanitizeSchemaForCca(converted);

已验证的完整链输出为:

{
  "converted": {
    "type": "object",
    "properties": { "answer": { "$ref": "#/$defs/Answer" } },
    "required": ["answer"]
  },
  "wire": {
    "type": "object",
    "properties": { "answer": {} },
    "required": ["answer"]
  }
}

verdict、它的类型、枚举和嵌套 required 已全部不在出站工具声明中。这里的 wire 指客户端转换后的声明,不是线上 provider 接收回执。

源码证据

已有保护与建议范围

结构化工具仍保留原 schema 供 Pi 参数校验使用,因此本问题不等于“错误 JSON 会被当作有效结果”。当前代码也会把部分不支持的长度/数值约束写入 description;这些保护不能恢复已删除的引用结构。

建议转换前有界展开能够表达的本地引用;递归引用、外部引用或超出边界的展开明确拒绝并说明原因。实现选择应保持 provider 适配边界,不复制一套子任务执行或校验 Runtime。

验收

  • 同一 fixture 同时验证原始 schema、完整出站转换链和参数校验,至少覆盖上面的嵌套对象、required、enum。
  • 可表达的本地引用在最终声明中保留结构含义,不能静默变成 {}
  • 递归引用、外部引用、过深或过大的展开在发起模型请求前明确失败,且转换成本有界。
  • 普通无引用 schema 和已有 description spill 行为保持兼容。
  • 验证记录区分纯 schema 转换、Pi 参数校验和真实 provider 验收;未运行的层次明确列出。

Related: #234 Antigravity/Cursor provider#155 Direct Subagent 结构化结果合同。本 Issue 跟踪两者交界处的具体 schema 转换缺陷。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions