Repository navigation
Conversation
Amir-R25
left a comment
There was a problem hiding this comment.
Thanks, good overall direction. A few edge cases and code styles need a little work.
A few were happening before but this PR is a good place to address.
I left a few comments:
- Nested forward references such as list["Payload"] are still not fully resolved.
- Tuple handling loses the tuple container and turns its element types into top-level union options.
- I also had a question about changing all manifest type mismatches from errors to warnings, rather than only relaxing validation when inference is unreliable.
One general readability note: there are quite a few inline comments that narrate what the next line is doing. I’d trim those and keep comments for non-obvious constraints or reasoning. A few comments also overstate the behaviour, for example, “get_type_hints()’s exact behaviour” and `“nested generics keep their structure” so simplifying them would make the implementation easier to review and maintain.
Aryan-Railtown
left a comment
There was a problem hiding this comment.
Amazing Work Guan!!
Just 1-2 minor things that i could find
Resolve forward references at every nesting level, keep tuples as array containers under their own parameter name, align Literal[..., None] with Optional[Literal[...]], and reject manifests that contradict a reliable annotation while staying silent where inference is unreliable.
Walking a model through model_fields follows resolved field types, so a model that refers back to itself gives the walk an infinite annotation tree. Track the models already on the current path and stop at a repeat. Also covers the model_fields switch with tests: a dict field reached through a PEP 563 model, a dict field reached through inheritance, and a dict nested inside a self-referential model.
|
Closing in favour of #1580. Thanks @Amir-R25 and @Aryan-Railtown for the thorough reviews. Every round found a real edge case, and that is what convinced me this is the wrong shape for the fix. The core of this PR is a hand-rolled annotation resolver ( #1580 takes the stdlib route at a fraction of the size. I've left a review there with what it still needs, mainly the manifest escape hatch and a warning when resolution fails. Where the rest goes:
|
Closes #1458.
ParameterType.from_python_typeis an identity lookup over 8 types withOBJECTasthe default. Anything it doesn't recognise silently becomes
{"type": "object"}which under
from __future__ import annotationsis everything. This PR also fix a major bug where, if any unrecognized class is resolved to an object, it cannot be corrected with a manual manifest.Fixes
pattern: strunder PEP 563{"type": "object"}{"type": "string"}Literal["content", "files"]{"type": "object"}{"type": "string", "enum": [...]}List[str] | None{"anyOf": [{"type": "object"}]}{"type": "array", "items": {"type": "string"}}ToolManifestunder PEP 563NodeCreationErrorChanges
llm/tools/annotations.py(new):resolved_signature()evaluates string/ForwardRefannotations. Fast-paths to plain
inspect.signaturewhen nothing is deferred, so nobehaviour change for normal code. Unresolvable names warn and pass through.
llm/tools/parameter_handlers.py:UnionParameterHandlerandSequenceParameterHandlernow recurse through the handler chain so nested generics keep their structure.llm/tools/tool.py: two call-site swapsvalidation/node_creation/validation.py: resolve annotations before validating.Manifest type mismatches now warn instead of raising
For review
Optional[str]was{"anyOf": [{"type": "string"}]}, now{"type": "string"}. Single-branchanyOfisnoise to a provider and optionality already rides on
required. Nothing in-repodepended on the old shape.
_flatten_union_optionsis required, not cosmetic:UnionParameter.__init__raiseson a nested union, newly reachable now that union arms recurse (
Union[Tuple[str, int], bool]).