fix(tools): the parameters schema root is exactly "object" — strict providers reject the nullable array #2
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/tool-schema-root-type"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Caught live in Kagura by the new assistant logging (TeamAI/Kagura#172): switching the assistant to a Moonshot AI model failed every turn with
JsonSchemaExporter.GetJsonSchemaAsNodewithout exporter options treats a reference-typeTParamsroot as nullable and emits"type": ["object","null"]. Strict OpenAI-compatible providers validatetools[].function.parameters.typeas the literal string"object"and reject the whole request — the model never even sees the turn.Fix: pass
JsonSchemaExporterOptions { TreatNullObliviousAsNonNullable = true }, keeping the root a plain"type": "object". Regression test added (Schema_root_type_is_exactly_object_for_strict_providers), proven red before the fix; all 136 tests green.Scope note: property-level nullability (
string?→["string","null"]) is untouched — Moonshot's validator only rejected the root. If a provider ever chokes on nested type arrays too, that's a follow-up normalization pass.🤖 Generated with Claude Code
Summary
Summary
Coverage
OpenRouter.Net - 68.8%
43F954A3762D43C2CD5DCD5CDF29C19D3789DC49A7DCA1C47__Base64DataUriPattern_0
OpenRouter.Net.Agents - 81.7%
OpenRouter.Net.Imaging - 82.2%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh~! A live bug caught by the very logging I approved in Kagura#172? Now that's a delicious little butterfly effect! ✨ You traced a 400 all the way from "assistant turn failed" → "provider rejects the tool schema" → "the exporter emits
["object","null"]instead of"object"at the root." That's beautiful detective work, fufu~ ♡Verdict: ✅ Looks good to me~
This is a textbook minimal-precision fix. I'm satisfied~
Independent verification (I didn't just trust the green CI — I reproduced the red-green cycle myself):
Assert.Equal() Failure: Expected: String, Actual: Array— exactly the runtime symptom in the PR body. Then re-applied your fix: GREEN. That test is a real regression test, not a tautology. ♪✅ What I liked~
TreatNullObliviousAsNonNullable = trueis exactly the right knob — it says "reference-type roots are non-nullable" without touching the honeststring?→["string","null"]property-level nullability. Your test fixture'sGreetParams.Loudisbool?and the existingSchema_is_generated_from_TParams_shapetest still happily finds bothnameandloudprops, so property nullability is provably untouched.JsonSchemaExporterOptions. Future-Jibril thanks present-you. ♡GetJsonSchemaAsNode, so there's no "did you miss one?" footgun.["type"]arrays as a possible follow-up rather than over-reaching. Correct call — the root was the only thing Moonshot's validator complained about.e7198ce(forgejo-actions coverage comment), and the changed line sits insideParametersSchema's getter which reports 90% line coverage — the fix line is genuinely exercised, not just compiled.No blocking findings, no suggestions. It's clean, it's tested, and I personally confirmed the test bites. Ship it, fufu~ ♪
Automated review by Jibril · 2026-07-17
CI/CD: passed for head
e7198ce(coverage comment current) · Local checks: build 0/0, Agents suite 40/40, regression test independently proven red→green