fix(ai): fixed CCA schema stripping for properties named properties
- Updated `normalizeSchemaNode` to keep `insideProperties` active only when entering an outer `properties` map, not when the key appears within an existing properties object. - Added a regression test for `google-tool-schema` ensuring `propertyNames` and `additionalProperties` are removed from a schema property literally named `properties`.
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed Cloud Code Assist (Gemini / Antigravity) rejecting tool schemas with `Invalid JSON payload received. Unknown name "propertyNames"` (HTTP 400) when a tool exposed a property literally named `properties` (e.g. the Resend MCP `create_contact` tool). The schema normalizer's `insideProperties` flag was re-asserted when descending into such a property's value schema, so Google-unsupported keywords (`propertyNames`, `additionalProperties`, …) nested inside it were never stripped. The flag is now only set when entering a real `properties` map from a schema node, not from within another `properties` map.
|
||||
- Fixed local/self-hosted providers leaking machine-specific endpoints into the bundled `models.json`. A `generate-models` run on a machine with a LiteLLM proxy baked 1202 `litellm` models pinned to `http://localhost:4000/v1` into the committed catalog. `litellm` (and `lm-studio`) now join `ollama`/`vllm` in the generator's discovery-only exclusion set, so local providers are never fetched during generation nor written to `models.json` — they are discovered dynamically at runtime instead. LiteLLM model discovery now enriches metadata against models.dev (the same reference source the other gateway providers use) rather than a bundled reference map. Added a regression test pinning the invariant (no local provider blocks, no loopback/private-network `baseUrl`s in the bundled catalog).
|
||||
|
||||
## [15.8.2] - 2026-06-03
|
||||
|
||||
@@ -280,7 +280,7 @@ function normalizeSchemaNode(value: unknown, options: NormalizeSchemaWalkOptions
|
||||
if (options.stripNullableKeyword && key === "nullable") continue;
|
||||
result[key] = normalizeSchemaNode(entry, {
|
||||
...options,
|
||||
insideProperties: key === "properties",
|
||||
insideProperties: !options.insideProperties && key === "properties",
|
||||
});
|
||||
}
|
||||
applyDescriptionSpill(result, spill, options);
|
||||
@@ -302,7 +302,7 @@ function normalizeSchemaNode(value: unknown, options: NormalizeSchemaWalkOptions
|
||||
}
|
||||
result[key] = normalizeSchemaNode(entry, {
|
||||
...options,
|
||||
insideProperties: key === "properties",
|
||||
insideProperties: !options.insideProperties && key === "properties",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,37 @@ describe("Cloud Code Assist Claude tool schema conversion", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("strips schema keywords inside a property literally named properties", () => {
|
||||
// Regression: the Resend MCP `create_contact` tool exposes a property
|
||||
// literally named `properties`. The walker must not treat that property's
|
||||
// value schema as a properties map — otherwise nested `propertyNames` /
|
||||
// `additionalProperties` keywords leak to the CCA wire and get rejected
|
||||
// with `Unknown name "propertyNames"` (HTTP 400).
|
||||
const schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
properties: {
|
||||
description: "Custom property key-value pairs",
|
||||
type: "object",
|
||||
propertyNames: { type: "string" },
|
||||
additionalProperties: { type: "string" },
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
} as unknown;
|
||||
|
||||
expect(normalizeSchemaForCCA(schema)).toEqual({
|
||||
type: "object",
|
||||
properties: {
|
||||
properties: {
|
||||
description: "Custom property key-value pairs",
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("uses sanitized parameters for claude models with deterministic output", () => {
|
||||
const parameters = {
|
||||
type: "object",
|
||||
|
||||
Reference in New Issue
Block a user