griptape-nodes 0.65.6__py3-none-any.whl → 0.66.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. griptape_nodes/common/node_executor.py +352 -27
  2. griptape_nodes/drivers/storage/base_storage_driver.py +12 -3
  3. griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +18 -2
  4. griptape_nodes/drivers/storage/local_storage_driver.py +42 -5
  5. griptape_nodes/exe_types/base_iterative_nodes.py +0 -1
  6. griptape_nodes/exe_types/connections.py +42 -0
  7. griptape_nodes/exe_types/core_types.py +2 -2
  8. griptape_nodes/exe_types/node_groups/__init__.py +2 -1
  9. griptape_nodes/exe_types/node_groups/base_iterative_node_group.py +177 -0
  10. griptape_nodes/exe_types/node_groups/base_node_group.py +1 -0
  11. griptape_nodes/exe_types/node_groups/subflow_node_group.py +35 -2
  12. griptape_nodes/exe_types/param_types/parameter_audio.py +1 -1
  13. griptape_nodes/exe_types/param_types/parameter_bool.py +1 -1
  14. griptape_nodes/exe_types/param_types/parameter_button.py +1 -1
  15. griptape_nodes/exe_types/param_types/parameter_float.py +1 -1
  16. griptape_nodes/exe_types/param_types/parameter_image.py +1 -1
  17. griptape_nodes/exe_types/param_types/parameter_int.py +1 -1
  18. griptape_nodes/exe_types/param_types/parameter_number.py +1 -1
  19. griptape_nodes/exe_types/param_types/parameter_string.py +1 -1
  20. griptape_nodes/exe_types/param_types/parameter_three_d.py +1 -1
  21. griptape_nodes/exe_types/param_types/parameter_video.py +1 -1
  22. griptape_nodes/machines/control_flow.py +5 -4
  23. griptape_nodes/machines/dag_builder.py +121 -55
  24. griptape_nodes/machines/fsm.py +10 -0
  25. griptape_nodes/machines/parallel_resolution.py +39 -38
  26. griptape_nodes/machines/sequential_resolution.py +29 -3
  27. griptape_nodes/node_library/library_registry.py +41 -2
  28. griptape_nodes/retained_mode/events/library_events.py +147 -8
  29. griptape_nodes/retained_mode/events/os_events.py +12 -4
  30. griptape_nodes/retained_mode/managers/fitness_problems/libraries/__init__.py +2 -0
  31. griptape_nodes/retained_mode/managers/fitness_problems/libraries/incompatible_requirements_problem.py +34 -0
  32. griptape_nodes/retained_mode/managers/flow_manager.py +133 -20
  33. griptape_nodes/retained_mode/managers/library_manager.py +1324 -564
  34. griptape_nodes/retained_mode/managers/node_manager.py +9 -3
  35. griptape_nodes/retained_mode/managers/os_manager.py +429 -65
  36. griptape_nodes/retained_mode/managers/resource_types/compute_resource.py +82 -0
  37. griptape_nodes/retained_mode/managers/resource_types/os_resource.py +17 -0
  38. griptape_nodes/retained_mode/managers/static_files_manager.py +21 -8
  39. griptape_nodes/retained_mode/managers/version_compatibility_manager.py +3 -3
  40. griptape_nodes/utils/git_utils.py +2 -17
  41. griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +5 -5
  42. griptape_nodes/version_compatibility/versions/v0_65_4/__init__.py +5 -0
  43. griptape_nodes/version_compatibility/versions/v0_65_4/run_in_parallel_to_run_in_order.py +79 -0
  44. griptape_nodes/version_compatibility/versions/v0_65_5/__init__.py +5 -0
  45. griptape_nodes/version_compatibility/versions/v0_65_5/flux_2_removed_parameters.py +85 -0
  46. {griptape_nodes-0.65.6.dist-info → griptape_nodes-0.66.0.dist-info}/METADATA +1 -1
  47. {griptape_nodes-0.65.6.dist-info → griptape_nodes-0.66.0.dist-info}/RECORD +49 -54
  48. griptape_nodes/retained_mode/managers/library_lifecycle/__init__.py +0 -45
  49. griptape_nodes/retained_mode/managers/library_lifecycle/data_models.py +0 -191
  50. griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +0 -346
  51. griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +0 -439
  52. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/__init__.py +0 -17
  53. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +0 -82
  54. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +0 -116
  55. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +0 -367
  56. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +0 -104
  57. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +0 -155
  58. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py +0 -18
  59. griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py +0 -12
  60. {griptape_nodes-0.65.6.dist-info → griptape_nodes-0.66.0.dist-info}/WHEEL +0 -0
  61. {griptape_nodes-0.65.6.dist-info → griptape_nodes-0.66.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,82 @@
1
+ import logging
2
+ from enum import StrEnum
3
+ from typing import TYPE_CHECKING, Any, Literal
4
+
5
+ from griptape_nodes.retained_mode.managers.resource_components.capability_field import (
6
+ CapabilityField,
7
+ validate_capabilities,
8
+ )
9
+ from griptape_nodes.retained_mode.managers.resource_components.resource_instance import ResourceInstance
10
+ from griptape_nodes.retained_mode.managers.resource_components.resource_type import ResourceType
11
+
12
+ if TYPE_CHECKING:
13
+ from griptape_nodes.retained_mode.managers.resource_components.resource_instance import Requirements
14
+
15
+ logger = logging.getLogger("griptape_nodes")
16
+
17
+
18
+ class ComputeBackend(StrEnum):
19
+ """Supported compute backends."""
20
+
21
+ CPU = "cpu"
22
+ CUDA = "cuda" # NVIDIA GPU
23
+ MPS = "mps" # Apple Metal Performance Shaders
24
+
25
+
26
+ # Compute capability field names
27
+ ComputeCapability = Literal[
28
+ "compute", # List of available compute backends: ["cpu", "cuda", "mps"]
29
+ ]
30
+
31
+
32
+ class ComputeInstance(ResourceInstance):
33
+ """Resource instance representing available compute backends."""
34
+
35
+ def can_be_freed(self) -> bool:
36
+ """Compute resources can be freed when no longer needed."""
37
+ return True
38
+
39
+ def free(self) -> None:
40
+ """Free compute resource instance."""
41
+ logger.debug("Freeing compute resource instance %s", self.get_instance_id())
42
+
43
+ def get_capability_typed(self, key: ComputeCapability) -> Any:
44
+ """Type-safe capability getter using Literal types."""
45
+ return self.get_capability_value(key)
46
+
47
+
48
+ class ComputeResourceType(ResourceType):
49
+ """Resource type for compute backend availability."""
50
+
51
+ def get_capability_schema(self) -> list[CapabilityField]:
52
+ """Get the capability schema for compute resources."""
53
+ return [
54
+ CapabilityField(
55
+ name="compute",
56
+ type_hint=list,
57
+ description="List of available compute backends: 'cpu', 'cuda', 'mps'",
58
+ required=True,
59
+ ),
60
+ ]
61
+
62
+ def create_instance(self, capabilities: dict[str, Any]) -> ResourceInstance:
63
+ """Create a new compute resource instance."""
64
+ # Validate capabilities against schema
65
+ validation_errors = validate_capabilities(self.get_capability_schema(), capabilities)
66
+ if validation_errors:
67
+ error_msg = f"Invalid compute capabilities: {', '.join(validation_errors)}"
68
+ raise ValueError(error_msg)
69
+
70
+ return ComputeInstance(resource_type=self, instance_id_prefix="compute", capabilities=capabilities)
71
+
72
+ def select_best_compatible_instance(
73
+ self, compatible_instances: list[ResourceInstance], _requirements: "Requirements | None" = None
74
+ ) -> ResourceInstance | None:
75
+ """Select the best compute instance from compatible ones.
76
+
77
+ Returns the first compatible instance (no special selection criteria).
78
+ """
79
+ if not compatible_instances:
80
+ return None
81
+
82
+ return compatible_instances[0]
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from enum import StrEnum
2
3
  from typing import TYPE_CHECKING, Any, Literal
3
4
 
4
5
  from griptape_nodes.retained_mode.managers.resource_components.capability_field import (
@@ -14,6 +15,22 @@ if TYPE_CHECKING:
14
15
  logger = logging.getLogger("griptape_nodes")
15
16
 
16
17
 
18
+ class Platform(StrEnum):
19
+ """Supported operating system platforms."""
20
+
21
+ WINDOWS = "windows"
22
+ DARWIN = "darwin" # macOS
23
+ LINUX = "linux"
24
+
25
+
26
+ class Architecture(StrEnum):
27
+ """Supported system architectures."""
28
+
29
+ X86_64 = "x86_64" # Also known as amd64
30
+ ARM64 = "arm64"
31
+ AARCH64 = "aarch64" # ARM64 on Linux
32
+
33
+
17
34
  # OS capability field names
18
35
  OSCapability = Literal[
19
36
  "platform",
@@ -11,6 +11,7 @@ from griptape_nodes.drivers.storage import StorageBackend
11
11
  from griptape_nodes.drivers.storage.griptape_cloud_storage_driver import GriptapeCloudStorageDriver
12
12
  from griptape_nodes.drivers.storage.local_storage_driver import LocalStorageDriver
13
13
  from griptape_nodes.retained_mode.events.app_events import AppInitializationComplete
14
+ from griptape_nodes.retained_mode.events.os_events import ExistingFilePolicy
14
15
  from griptape_nodes.retained_mode.events.static_file_events import (
15
16
  CreateStaticFileDownloadUrlRequest,
16
17
  CreateStaticFileDownloadUrlResultFailure,
@@ -182,7 +183,9 @@ class StaticFilesManager:
182
183
  if isinstance(self.storage_driver, LocalStorageDriver):
183
184
  threading.Thread(target=start_static_server, daemon=True, name="static-server").start()
184
185
 
185
- def save_static_file(self, data: bytes, file_name: str) -> str:
186
+ def save_static_file(
187
+ self, data: bytes, file_name: str, existing_file_policy: ExistingFilePolicy = ExistingFilePolicy.OVERWRITE
188
+ ) -> str:
186
189
  """Saves a static file to the workspace directory.
187
190
 
188
191
  This is used to save files that are generated by the node, such as images or other artifacts.
@@ -190,27 +193,37 @@ class StaticFilesManager:
190
193
  Args:
191
194
  data: The file data to save.
192
195
  file_name: The name of the file to save.
196
+ existing_file_policy: How to handle existing files. Defaults to OVERWRITE for backward compatibility.
197
+ - OVERWRITE: Replace existing file content (default)
198
+ - CREATE_NEW: Auto-generate unique filename (e.g., file_1.txt, file_2.txt)
199
+ - FAIL: Raise FileExistsError if file exists
193
200
 
194
201
  Returns:
195
- The URL of the saved file.
202
+ The URL of the saved file. Note: the actual filename may differ from the requested
203
+ file_name when using CREATE_NEW policy.
204
+
205
+ Raises:
206
+ FileExistsError: When existing_file_policy is FAIL and file already exists.
196
207
  """
197
208
  resolved_directory = self._get_static_files_directory()
198
209
  file_path = Path(resolved_directory) / file_name
199
210
 
200
- response = self.storage_driver.create_signed_upload_url(file_path)
211
+ # Pass the existing_file_policy to the storage driver
212
+ response = self.storage_driver.create_signed_upload_url(file_path, existing_file_policy)
213
+
214
+ resolved_file_path = Path(response["file_path"])
201
215
 
202
216
  try:
203
- response = httpx.request(
217
+ upload_response = httpx.request(
204
218
  response["method"], response["url"], content=data, headers=response["headers"], timeout=60
205
219
  )
206
- response.raise_for_status()
220
+ upload_response.raise_for_status()
207
221
  except httpx.HTTPStatusError as e:
208
- msg = str(e.response.json())
222
+ msg = str(e.response.json()) if hasattr(e, "response") else str(e)
209
223
  logger.error(msg)
210
224
  raise ValueError(msg) from e
211
225
 
212
- url = self.storage_driver.create_signed_download_url(file_path)
213
-
226
+ url = self.storage_driver.create_signed_download_url(resolved_file_path)
214
227
  return url
215
228
 
216
229
  def _get_static_files_directory(self) -> str:
@@ -32,7 +32,7 @@ from griptape_nodes.retained_mode.managers.fitness_problems.workflows.deprecated
32
32
  from griptape_nodes.retained_mode.managers.fitness_problems.workflows.node_type_not_found_problem import (
33
33
  NodeTypeNotFoundProblem,
34
34
  )
35
- from griptape_nodes.retained_mode.managers.library_lifecycle.library_status import LibraryStatus
35
+ from griptape_nodes.retained_mode.managers.library_manager import LibraryManager
36
36
 
37
37
  if TYPE_CHECKING:
38
38
  from griptape_nodes.exe_types.node_types import BaseNode
@@ -54,7 +54,7 @@ class LibraryVersionCompatibilityIssue(NamedTuple):
54
54
  """Represents a library version compatibility issue found in a library."""
55
55
 
56
56
  problem: LibraryProblem
57
- severity: LibraryStatus
57
+ severity: LibraryManager.LibraryFitness
58
58
 
59
59
 
60
60
  class LibraryVersionCompatibilityCheck(ABC):
@@ -208,7 +208,7 @@ class VersionCompatibilityManager:
208
208
  removal_version=node.metadata.deprecation.removal_version,
209
209
  deprecation_message=node.metadata.deprecation.deprecation_message,
210
210
  ),
211
- severity=LibraryStatus.FLAWED,
211
+ severity=LibraryManager.LibraryFitness.FLAWED,
212
212
  )
213
213
  for node in library_data.nodes
214
214
  if node.metadata.deprecation is not None
@@ -1171,34 +1171,19 @@ def _shallow_clone_with_pygit2(remote_url: str, ref: str) -> tuple[str, str, dic
1171
1171
  callbacks = _get_ssh_callbacks()
1172
1172
 
1173
1173
  # Shallow clone with depth=1
1174
- # Note: We don't use checkout_branch here because it only works with branches,
1175
- # not tags or commit SHAs. Instead, we'll fetch and checkout the ref manually.
1174
+ checkout_branch = ref if ref != "HEAD" else None
1176
1175
  repo = pygit2.clone_repository(
1177
1176
  remote_url,
1178
1177
  str(temp_path),
1179
1178
  callbacks=callbacks,
1180
1179
  depth=1,
1180
+ checkout_branch=checkout_branch,
1181
1181
  )
1182
1182
 
1183
1183
  if repo is None:
1184
1184
  msg = f"Failed to clone repository from {remote_url}"
1185
1185
  raise GitCloneError(msg)
1186
1186
 
1187
- # If a specific ref was requested (not HEAD), fetch and checkout that ref
1188
- if ref != "HEAD":
1189
- try:
1190
- # Fetch the specific ref (works for branches, tags, and commits)
1191
- remote = repo.remotes["origin"]
1192
- remote.fetch([ref], callbacks=callbacks, depth=1)
1193
-
1194
- # Now resolve and checkout the ref
1195
- resolved_ref = repo.revparse_single(ref)
1196
- repo.checkout_tree(resolved_ref)
1197
- repo.set_head(resolved_ref.id)
1198
- except (KeyError, pygit2.GitError) as e:
1199
- msg = f"Failed to fetch and checkout ref '{ref}' in clone from {remote_url}: {e}"
1200
- raise GitCloneError(msg) from e
1201
-
1202
1187
  # Find the library JSON file
1203
1188
  library_json_path = find_file_in_directory(temp_path, "griptape[-_]nodes[-_]library.json")
1204
1189
  if library_json_path is None:
@@ -21,7 +21,7 @@ from griptape_nodes.retained_mode.managers.fitness_problems.libraries.ui_options
21
21
  from griptape_nodes.retained_mode.managers.fitness_problems.libraries.ui_options_field_modified_warning_problem import (
22
22
  UiOptionsFieldModifiedWarningProblem,
23
23
  )
24
- from griptape_nodes.retained_mode.managers.library_lifecycle.library_status import LibraryStatus
24
+ from griptape_nodes.retained_mode.managers.library_manager import LibraryManager
25
25
  from griptape_nodes.retained_mode.managers.version_compatibility_manager import (
26
26
  LibraryVersionCompatibilityCheck,
27
27
  LibraryVersionCompatibilityIssue,
@@ -62,11 +62,11 @@ class ModifiedParametersSetRemovalCheck(LibraryVersionCompatibilityCheck):
62
62
  return [
63
63
  LibraryVersionCompatibilityIssue(
64
64
  problem=ModifiedParametersSetRemovedProblem(library_engine_version=library_version_str),
65
- severity=LibraryStatus.UNUSABLE,
65
+ severity=LibraryManager.LibraryFitness.UNUSABLE,
66
66
  ),
67
67
  LibraryVersionCompatibilityIssue(
68
68
  problem=UiOptionsFieldModifiedIncompatibleProblem(library_engine_version=library_version_str),
69
- severity=LibraryStatus.UNUSABLE,
69
+ severity=LibraryManager.LibraryFitness.UNUSABLE,
70
70
  ),
71
71
  ]
72
72
  if current_engine_version >= semver.VersionInfo(0, 38, 0):
@@ -74,11 +74,11 @@ class ModifiedParametersSetRemovalCheck(LibraryVersionCompatibilityCheck):
74
74
  return [
75
75
  LibraryVersionCompatibilityIssue(
76
76
  problem=ModifiedParametersSetDeprecationWarningProblem(library_engine_version=library_version_str),
77
- severity=LibraryStatus.FLAWED,
77
+ severity=LibraryManager.LibraryFitness.FLAWED,
78
78
  ),
79
79
  LibraryVersionCompatibilityIssue(
80
80
  problem=UiOptionsFieldModifiedWarningProblem(),
81
- severity=LibraryStatus.FLAWED,
81
+ severity=LibraryManager.LibraryFitness.FLAWED,
82
82
  ),
83
83
  ]
84
84
 
@@ -0,0 +1,5 @@
1
+ """Version 0.65.4 backward compatibility checks.
2
+
3
+ This version includes backward compatibility for the parameter name change from
4
+ 'run_in_parallel' to 'run_in_order' in ForLoopStartNode and ForEachStartNode.
5
+ """
@@ -0,0 +1,79 @@
1
+ """Backward compatibility for run_in_parallel to run_in_order parameter change.
2
+
3
+ This module handles the parameter name change from 'run_in_parallel' to 'run_in_order'
4
+ in ForLoopStartNode and ForEachStartNode. The logic is inverted: run_in_parallel=True
5
+ becomes run_in_order=False (run in parallel means NOT run in order).
6
+
7
+ TODO: Remove this compatibility check once all workflows have been migrated and we no
8
+ longer need to support loading old workflows with the run_in_parallel parameter.
9
+ Link: https://github.com/griptape-ai/griptape-nodes/issues/XXXX
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import TYPE_CHECKING, Any
15
+
16
+ from griptape_nodes.retained_mode.events.parameter_events import SetParameterValueResultSuccess
17
+ from griptape_nodes.retained_mode.managers.version_compatibility_manager import (
18
+ SetParameterVersionCompatibilityCheck,
19
+ )
20
+
21
+ if TYPE_CHECKING:
22
+ from griptape_nodes.exe_types.node_types import BaseNode
23
+
24
+
25
+ class RunInParallelToRunInOrderCheck(SetParameterVersionCompatibilityCheck):
26
+ """Handle migration from run_in_parallel to run_in_order parameter.
27
+
28
+ This check intercepts attempts to set the old 'run_in_parallel' parameter
29
+ and converts it to the new 'run_in_order' parameter with inverted boolean logic.
30
+
31
+ Applies to:
32
+ - ForLoopStartNode
33
+ - ForEachStartNode
34
+
35
+ Migration logic:
36
+ - run_in_parallel=True → run_in_order=False (run in parallel)
37
+ - run_in_parallel=False → run_in_order=True (run sequentially)
38
+ """
39
+
40
+ def applies_to_set_parameter(self, node: BaseNode, parameter_name: str, _value: Any) -> bool:
41
+ """Return True if this is the old run_in_parallel parameter on an affected node.
42
+
43
+ Args:
44
+ node: The node instance
45
+ parameter_name: Name of the parameter being set
46
+ _value: The value being set (unused)
47
+
48
+ Returns:
49
+ True if this check should handle this parameter
50
+ """
51
+ if parameter_name != "run_in_parallel":
52
+ return False
53
+
54
+ node_type_name = type(node).__name__
55
+ return node_type_name in ("ForLoopStartNode", "ForEachStartNode")
56
+
57
+ def set_parameter_value(self, node: BaseNode, parameter_name: str, value: Any) -> SetParameterValueResultSuccess:
58
+ """Migrate run_in_parallel to run_in_order with inverted boolean value.
59
+
60
+ Args:
61
+ node: The node instance
62
+ parameter_name: Name of the parameter being set (should be "run_in_parallel")
63
+ value: The value being set (boolean)
64
+
65
+ Returns:
66
+ SetParameterValueResultSuccess indicating the migration was successful
67
+ """
68
+ if value is None:
69
+ inverted_value = True
70
+ else:
71
+ inverted_value = not bool(value)
72
+
73
+ node.set_parameter_value("run_in_order", inverted_value)
74
+
75
+ return SetParameterValueResultSuccess(
76
+ finalized_value=inverted_value,
77
+ data_type="bool",
78
+ result_details=f"Migrated deprecated '{parameter_name}' parameter to 'run_in_order' with inverted value",
79
+ )
@@ -0,0 +1,5 @@
1
+ """Version 0.65.5 backward compatibility checks.
2
+
3
+ This version includes backward compatibility for removed parameters in
4
+ Flux2ImageGeneration: 'prompt_upsampling' and 'aspect_ratio'.
5
+ """
@@ -0,0 +1,85 @@
1
+ """Backward compatibility for removed Flux2ImageGeneration parameters.
2
+
3
+ This module handles removed parameters from Flux2ImageGeneration when adding
4
+ FLUX.2[max] support:
5
+ - prompt_upsampling: removed entirely
6
+ - aspect_ratio: replaced with explicit width/height parameters
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import logging
12
+ from typing import TYPE_CHECKING, Any, ClassVar
13
+
14
+ from griptape_nodes.retained_mode.events.parameter_events import SetParameterValueResultSuccess
15
+ from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
16
+ from griptape_nodes.retained_mode.managers.version_compatibility_manager import (
17
+ SetParameterVersionCompatibilityCheck,
18
+ )
19
+
20
+ if TYPE_CHECKING:
21
+ from griptape_nodes.exe_types.node_types import BaseNode
22
+
23
+ logger = logging.getLogger("griptape_nodes")
24
+
25
+
26
+ class Flux2RemovedParametersCheck(SetParameterVersionCompatibilityCheck):
27
+ """Handle removed prompt_upsampling and aspect_ratio parameters.
28
+
29
+ These parameters were removed in engine version 0.65.5 when adding FLUX.2[max] support.
30
+ This check intercepts attempts to set these parameters and logs a warning prompting
31
+ users to resave their workflows.
32
+ """
33
+
34
+ REMOVED_PARAMETERS: ClassVar[set[str]] = {"prompt_upsampling", "aspect_ratio"}
35
+
36
+ def __init__(self) -> None:
37
+ """Initialize the check with an empty set of warned workflows."""
38
+ super().__init__()
39
+ self._warned_workflows: set[str] = set()
40
+
41
+ def applies_to_set_parameter(self, node: BaseNode, parameter_name: str, _value: Any) -> bool:
42
+ """Return True if this is a removed parameter on a Flux2ImageGeneration node.
43
+
44
+ Args:
45
+ node: The node instance
46
+ parameter_name: Name of the parameter being set
47
+ _value: The value being set (unused)
48
+
49
+ Returns:
50
+ True if this check should handle this parameter
51
+ """
52
+ if parameter_name not in self.REMOVED_PARAMETERS:
53
+ return False
54
+
55
+ return type(node).__name__ == "Flux2ImageGeneration"
56
+
57
+ def set_parameter_value(self, _node: BaseNode, parameter_name: str, _value: Any) -> SetParameterValueResultSuccess:
58
+ """Handle the removed parameter by logging a warning and returning success.
59
+
60
+ Args:
61
+ _node: The node instance (unused)
62
+ parameter_name: Name of the parameter being set
63
+ _value: The value being set (unused)
64
+
65
+ Returns:
66
+ SetParameterValueResultSuccess with None value
67
+ """
68
+ workflow_name = GriptapeNodes.ContextManager().get_current_workflow_name()
69
+
70
+ if workflow_name not in self._warned_workflows:
71
+ self._warned_workflows.add(workflow_name)
72
+
73
+ removed_params_list = ", ".join(f"'{param}'" for param in self.REMOVED_PARAMETERS)
74
+ logger.warning(
75
+ "This workflow uses removed Flux2ImageGeneration parameters (%s) that were "
76
+ "replaced in engine version 0.65.5. Please resave your workflow and this "
77
+ "warning will go away.",
78
+ removed_params_list,
79
+ )
80
+
81
+ return SetParameterValueResultSuccess(
82
+ finalized_value=None,
83
+ data_type="any",
84
+ result_details=f"Parameter '{parameter_name}' was removed in v0.65.5. Please resave this workflow.",
85
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: griptape-nodes
3
- Version: 0.65.6
3
+ Version: 0.66.0
4
4
  Summary: Add your description here
5
5
  Requires-Dist: griptape>=1.8.12
6
6
  Requires-Dist: pydantic>=2.10.6