Repository navigation
Conversation
Preserve serializable Segment declarations when normalizing container values instead of inferring types from their raw values. Normalize variable subclasses to bare segments so outputs bind to their owning container selectors. Carry typed outputs through completion and loop reconciliation while keeping inputs and Loop/Iteration presentation values unwrapped. Retain declared loop-variable types during initialization. Document the container value contract and cover live completion, runtime snapshots, selector ownership, and the real Loop execution path. Refs #198
Promote integer variables when assignments produce floats so both assigner versions retain fractional values and variable identity through serialization. Keep Iteration outputs typed until aggregation, preserving matching array declarations and using array[any] for mixed declarations. Keep presentation outputs plain in both serial and parallel execution. Cover numeric updates, Loop completion, and Iteration aggregation; update the container and variable development guides. Refs #198
321a551 to
956f519
Compare
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.
| } | ||
| if isinstance(value, Mapping) and "value_type" in value: | ||
| return value | ||
| return build_segment(value) |
There was a problem hiding this comment.
This seems to be a code smell to me. Why on earth does the code convert an explicitly typed object to dict, then convert the dict back to another explicitly typed object?
Besides, the type annotation almost tells nothing about how this function is used.
| return build_segment(value.to_object()) | ||
| return { | ||
| "value_type": ( | ||
| SegmentType.STRING |
There was a problem hiding this comment.
Is the conversion from SECRET to STRING intentional, or is it just a workaround for the lack of SecretSegment in SerializableSegment?
Preserve declarations, secret sensitivity, and destination ownership while validating replacements and container values. Complete array aggregation and clear operations for preserved types. Refs #198
Important
!Related Issue
Refs #198
Also addresses the empty file output regression reported in Dify.
Summary
Container completion and output copying could erase declared types or retain a source variable's selector, causing later assignments to modify the source.
Preserve declared values through requests, snapshots, completion, and destination binding, including empty Iteration outputs and typed arrays.
Concrete segment variants now own their type tags and validation, including
SecretSegment; container conversion validates those variants directly.VariableBase.copy_with_valuevalidates replacements, preserves identity and metadata, and promotes integer values when arithmetic or assignment produces a float.The factory validates explicit declarations; raw inputs use inference.
Iteration preserves matching declarations when flattening, accepts typed sequences, and retains nested arrays and their element values.
File arrays can be cleared after their type is preserved.
File arrays stored as tuples serialize through the existing host file adapter.
Secret values retain their sensitivity through typed container transport and snapshot restoration.
Presentation payloads expose plain values; hosts own redaction after that boundary.
Validation:
just testpassed all 1124 tests, andjust checkpassed formatting, lint, types, dependency lock, and import checks.Regression coverage includes static tag narrowing, invalid assignments and typed payloads, snapshots, empty Iteration ownership, array aggregation, tuple inputs, secret masking, and clearing file arrays.
The Dify application was not run end to end.
Checklist
!