feat(isolation): wheel support for isolated custom nodes#12959
Merged
pollockjj merged 1 commit intoComfy-Org:pyisolate-supportfrom Mar 15, 2026
Merged
feat(isolation): wheel support for isolated custom nodes#12959pollockjj merged 1 commit intoComfy-Org:pyisolate-supportfrom
pollockjj merged 1 commit intoComfy-Org:pyisolate-supportfrom
Conversation
Extends pyisolate process isolation with wheel-based dependency management, sandbox mode policy, and compatibility fixes validated against DA3 as the first complex isolated custom node. - Add sandbox_mode policy (required/disabled) with COMFY_HOST_POLICY_PATH env override for host security configuration - Plumb cuda_wheels config and standardize child environment detection - Add PLY, NPZ, File3D, VIDEO serializers for core save nodes - Register isolated extension web directories on host side (sandbox_mode=disabled) for frontend JS widget serving - Capture ACCEPT_ALL_INPUTS from child node class to prevent @classproperty trigger on proxy class - Serialize NodeOutput with ui/expand/block_execution through JSON-RPC - Cherry-pick V3 python_module metadata fix (e459219) - Remove improperly committed cache artifacts
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends the process-isolation subsystem to support a host-controlled sandbox policy (sandbox_mode) and improves isolated node compatibility by preserving richer execution results and registering extension web assets when sandboxing is disabled.
Changes:
- Add
sandbox_modeto host policy with TOML +COMFY_HOST_POLICY_PATHoverride and propagate it into isolated extension configs. - Preserve V3
NodeOutputmetadata across isolation boundaries (includingui/expand/block_execution) and captureaccept_all_inputsfor stub class generation. - Register isolated extension web directories on the host when sandboxing is disabled; remove accidentally committed cache artifacts.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
comfy/isolation/host_policy.py |
Introduces sandbox_mode, env override for policy path, and enhanced logging. |
comfy/isolation/extension_loader.py |
Plumbs sandbox_mode into extension config and adds host-side web dir registration (sandbox-disabled only). |
comfy/isolation/extension_wrapper.py |
Wraps execution with inference mode and introduces NodeOutput envelope serialization. |
comfy/isolation/runtime_helpers.py |
Reconstructs NodeOutput on host and normalizes V3 python_module metadata; captures ACCEPT_ALL_INPUTS. |
pyproject.toml |
Sets default host sandbox_mode = "required". |
tests/isolation/test_host_policy.py |
Adds coverage for sandbox_mode parsing, invalid values, and env override path. |
tests/isolation/test_cuda_wheels_and_env_flags.py |
Updates isolation manifest plumbing tests to assert sandbox_mode propagation. |
.pyisolate_venvs/ComfyUI-IsolationToolkit/cache/cache_key |
Removes committed cache artifact. |
.pyisolate_venvs/ComfyUI-DepthAnythingV2/cache/node_info.json |
Removes committed cache artifact. |
.pyisolate_venvs/ComfyUI-DepthAnythingV2/cache/cache_key |
Removes committed cache artifact. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Comment on lines
399
to
+410
| if type(result).__name__ == "NodeOutput": | ||
| result = result.args | ||
| node_output_dict = { | ||
| "__node_output__": True, | ||
| "args": self._wrap_unpicklable_objects(result.args), | ||
| } | ||
| if result.ui is not None: | ||
| node_output_dict["ui"] = result.ui | ||
| if getattr(result, "expand", None) is not None: | ||
| node_output_dict["expand"] = result.expand | ||
| if getattr(result, "block_execution", None) is not None: | ||
| node_output_dict["block_execution"] = result.block_execution | ||
| return node_output_dict |
| node_info = copy.deepcopy(info.get("schema_v1", {})) | ||
| relative_python_module = node_info.get("python_module") | ||
| if not isinstance(relative_python_module, str) or not relative_python_module: | ||
| relative_python_module = f"custom_nodes.{extension.name}" |
Comment on lines
+55
to
+60
| for line in source.splitlines(): | ||
| stripped = line.strip() | ||
| if stripped.startswith("WEB_DIRECTORY"): | ||
| # Parse: WEB_DIRECTORY = "./web" or WEB_DIRECTORY = "web" | ||
| _, _, value = stripped.partition("=") | ||
| value = value.strip().strip("\"'") |
Comment on lines
399
to
+410
| if type(result).__name__ == "NodeOutput": | ||
| result = result.args | ||
| node_output_dict = { | ||
| "__node_output__": True, | ||
| "args": self._wrap_unpicklable_objects(result.args), | ||
| } | ||
| if result.ui is not None: | ||
| node_output_dict["ui"] = result.ui | ||
| if getattr(result, "expand", None) is not None: | ||
| node_output_dict["expand"] = result.expand | ||
| if getattr(result, "block_execution", None) is not None: | ||
| node_output_dict["block_execution"] = result.block_execution | ||
| return node_output_dict |
Comment on lines
+224
to
+228
| scan_shm_forensics("RUNTIME:post_execute", refresh_model_context=True) | ||
| return latest_io.NodeOutput( | ||
| *deserialized_args, | ||
| ui=result.get("ui"), | ||
| expand=result.get("expand"), |
Comment on lines
+377
to
+378
| with torch.inference_mode(): | ||
| result = await handler(**resolved_inputs) |
Comment on lines
+404
to
+407
| if result.ui is not None: | ||
| node_output_dict["ui"] = result.ui | ||
| if getattr(result, "expand", None) is not None: | ||
| node_output_dict["expand"] = result.expand |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
sandbox_mode(required/disabled) host policy withCOMFY_HOST_POLICY_PATHenv overridecuda_wheelsconfig and standardizes child environment detectionACCEPT_ALL_INPUTScapture preventing@classpropertytrigger on proxyNodeOutputserialization preservingui/expand/block_executionthrough JSON-RPCpython_modulemetadata fix (cherry-pick of e459219)Validated against
sandbox_mode=disabled)bas_reliefwithda3_large(~781MB) completes without OOM on RTX 3090Test plan
--use-process-isolation --disable-cuda-malloc