Skip to content

fix(containers): preserve declared output types - #344

Open
laipz8200 wants to merge 5 commits into
mainfrom
laipz8200/preserve-container-output-types
Open

laipz8200 wants to merge 5 commits into
mainfrom
laipz8200/preserve-container-output-types

Conversation

@laipz8200

@laipz8200 laipz8200 commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Important

  1. Make sure you have read our contribution guidelines
  2. Search existing issues and pull requests to confirm this change is not a duplicate
  3. Open or identify the issue this pull request resolves or advances
  4. Use a Conventional Commits title for this pull request, and mark breaking changes with !
  5. Remember that the pull request title will become the squash merge commit message
  6. If CLA Assistant prompts you, sign CLA.md in the pull request conversation

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_value validates 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.
Files nested in array[any] retain their runtime type after snapshot restoration, including nested lists and objects, so host adapters continue to render file URLs.
Serialized file markers use the existing file validation; ordinary objects retain their values.
Secret values retain their sensitivity through typed container transport and snapshot restoration.
Loop variables initialized from secrets support assignment and clearing while retaining their secret type and masking.
Presentation payloads expose plain values; hosts own redaction after that boundary.

Validation: just test passed all 1132 tests, and just check passed 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 assignment and masking, nested file restoration, invalid file markers, and clearing file arrays.
The Dify application was not run end to end.

Checklist

  • This pull request links the issue it resolves or advances
  • This pull request title follows Conventional Commits, and any breaking change is marked with !
  • If CLA Assistant prompted me, I signed CLA.md in the pull request conversation

laipz8200 and others added 2 commits October 29, 2026 11:25
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
@WH-2099
WH-2099 force-pushed the laipz8200/preserve-container-output-types branch from 321a551 to 956f519 Compare October 29, 2026 11:45
@WH-2099
WH-2099 marked this pull request as ready for review October 29, 2026 12:03
Copilot AI balanced review requested due to automatic review settings October 29, 2026 12:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@QuantumGhost QuantumGhost self-assigned this Oct 30, 2026
}
if isinstance(value, Mapping) and "value_type" in value:
return value
return build_segment(value)

@QuantumGhost QuantumGhost Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/graphon/nodes/container_effects.py Outdated
return build_segment(value.to_object())
return {
"value_type": (
SegmentType.STRING

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the conversion from SECRET to STRING intentional, or is it just a workaround for the lack of SecretSegment in SerializableSegment?

WH-2099 and others added 3 commits October 30, 2026 16:05
Preserve declarations, secret sensitivity, and destination ownership while validating replacements and container values.
Complete array aggregation and clear operations for preserved types.

Refs #198
Keep secret loop variables assignable and clearable without losing their type.
Restore nested files in array[any] snapshots through existing file validation.

Refs #198

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants