griptape-nodes 0.51.2__py3-none-any.whl → 0.52.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.
- griptape_nodes/__init__.py +5 -4
- griptape_nodes/app/api.py +27 -24
- griptape_nodes/app/app.py +243 -221
- griptape_nodes/app/watch.py +17 -2
- griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +66 -103
- griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +16 -4
- griptape_nodes/exe_types/core_types.py +16 -4
- griptape_nodes/exe_types/node_types.py +74 -16
- griptape_nodes/machines/control_flow.py +21 -26
- griptape_nodes/machines/fsm.py +16 -16
- griptape_nodes/machines/node_resolution.py +30 -119
- griptape_nodes/mcp_server/server.py +14 -10
- griptape_nodes/mcp_server/ws_request_manager.py +2 -2
- griptape_nodes/node_library/workflow_registry.py +5 -0
- griptape_nodes/retained_mode/events/base_events.py +12 -7
- griptape_nodes/retained_mode/events/execution_events.py +0 -6
- griptape_nodes/retained_mode/events/node_events.py +38 -0
- griptape_nodes/retained_mode/events/parameter_events.py +11 -0
- griptape_nodes/retained_mode/events/variable_events.py +361 -0
- griptape_nodes/retained_mode/events/workflow_events.py +35 -0
- griptape_nodes/retained_mode/griptape_nodes.py +61 -26
- griptape_nodes/retained_mode/managers/agent_manager.py +8 -9
- griptape_nodes/retained_mode/managers/event_manager.py +215 -74
- griptape_nodes/retained_mode/managers/flow_manager.py +39 -33
- griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +14 -14
- griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +20 -20
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +1 -1
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +1 -1
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +4 -3
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +1 -1
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +1 -1
- griptape_nodes/retained_mode/managers/library_manager.py +20 -19
- griptape_nodes/retained_mode/managers/node_manager.py +83 -8
- griptape_nodes/retained_mode/managers/object_manager.py +4 -0
- griptape_nodes/retained_mode/managers/settings.py +1 -0
- griptape_nodes/retained_mode/managers/sync_manager.py +3 -9
- griptape_nodes/retained_mode/managers/variable_manager.py +529 -0
- griptape_nodes/retained_mode/managers/workflow_manager.py +156 -50
- griptape_nodes/retained_mode/variable_types.py +18 -0
- griptape_nodes/utils/__init__.py +4 -0
- griptape_nodes/utils/async_utils.py +89 -0
- {griptape_nodes-0.51.2.dist-info → griptape_nodes-0.52.0.dist-info}/METADATA +2 -3
- {griptape_nodes-0.51.2.dist-info → griptape_nodes-0.52.0.dist-info}/RECORD +45 -42
- {griptape_nodes-0.51.2.dist-info → griptape_nodes-0.52.0.dist-info}/WHEEL +1 -1
- griptape_nodes/bootstrap/workflow_executors/subprocess_workflow_executor.py +0 -90
- {griptape_nodes-0.51.2.dist-info → griptape_nodes-0.52.0.dist-info}/entry_points.txt +0 -0
|
@@ -95,6 +95,7 @@ from griptape_nodes.retained_mode.managers.library_lifecycle.library_provenance.
|
|
|
95
95
|
)
|
|
96
96
|
from griptape_nodes.retained_mode.managers.library_lifecycle.library_status import LibraryStatus
|
|
97
97
|
from griptape_nodes.retained_mode.managers.os_manager import OSManager
|
|
98
|
+
from griptape_nodes.utils.async_utils import subprocess_run
|
|
98
99
|
from griptape_nodes.utils.uv_utils import find_uv_bin
|
|
99
100
|
from griptape_nodes.utils.version_utils import get_complete_version_string
|
|
100
101
|
|
|
@@ -662,7 +663,7 @@ class LibraryManager:
|
|
|
662
663
|
result = ListCategoriesInLibraryResultSuccess(categories=categories)
|
|
663
664
|
return result
|
|
664
665
|
|
|
665
|
-
def register_library_from_file_request(self, request: RegisterLibraryFromFileRequest) -> ResultPayload: # noqa: C901, PLR0911, PLR0912, PLR0915 (complex logic needs branches)
|
|
666
|
+
async def register_library_from_file_request(self, request: RegisterLibraryFromFileRequest) -> ResultPayload: # noqa: C901, PLR0911, PLR0912, PLR0915 (complex logic needs branches)
|
|
666
667
|
file_path = request.file_path
|
|
667
668
|
|
|
668
669
|
# Convert to Path object if it's a string
|
|
@@ -781,7 +782,7 @@ class LibraryManager:
|
|
|
781
782
|
|
|
782
783
|
# Only install dependencies if conditions are met
|
|
783
784
|
try:
|
|
784
|
-
library_venv_python_path = self._init_library_venv(venv_path)
|
|
785
|
+
library_venv_python_path = await self._init_library_venv(venv_path)
|
|
785
786
|
except RuntimeError as e:
|
|
786
787
|
self._library_file_path_to_info[file_path] = LibraryManager.LibraryInfo(
|
|
787
788
|
library_path=file_path,
|
|
@@ -816,7 +817,7 @@ class LibraryManager:
|
|
|
816
817
|
logger.info(
|
|
817
818
|
"Installing dependencies for library '%s' with pip in venv at %s", library_data.name, venv_path
|
|
818
819
|
)
|
|
819
|
-
|
|
820
|
+
await subprocess_run(
|
|
820
821
|
[
|
|
821
822
|
sys.executable,
|
|
822
823
|
"-m",
|
|
@@ -920,7 +921,7 @@ class LibraryManager:
|
|
|
920
921
|
logger.error(details)
|
|
921
922
|
return RegisterLibraryFromFileResultFailure(result_details=details)
|
|
922
923
|
|
|
923
|
-
def register_library_from_requirement_specifier_request(
|
|
924
|
+
async def register_library_from_requirement_specifier_request(
|
|
924
925
|
self, request: RegisterLibraryFromRequirementSpecifierRequest
|
|
925
926
|
) -> ResultPayload:
|
|
926
927
|
try:
|
|
@@ -930,7 +931,7 @@ class LibraryManager:
|
|
|
930
931
|
|
|
931
932
|
# Only install dependencies if conditions are met
|
|
932
933
|
try:
|
|
933
|
-
library_python_venv_path = self._init_library_venv(venv_path)
|
|
934
|
+
library_python_venv_path = await self._init_library_venv(venv_path)
|
|
934
935
|
except RuntimeError as e:
|
|
935
936
|
details = f"Attempted to install library '{request.requirement_specifier}'. Failed when creating the virtual environment: {e}"
|
|
936
937
|
logger.error(details)
|
|
@@ -948,14 +949,14 @@ class LibraryManager:
|
|
|
948
949
|
uv_path = find_uv_bin()
|
|
949
950
|
|
|
950
951
|
logger.info("Installing dependency '%s' with pip in venv at %s", package_name, venv_path)
|
|
951
|
-
|
|
952
|
+
await subprocess_run(
|
|
952
953
|
[
|
|
953
954
|
uv_path,
|
|
954
955
|
"pip",
|
|
955
956
|
"install",
|
|
956
957
|
request.requirement_specifier,
|
|
957
958
|
"--python",
|
|
958
|
-
library_python_venv_path,
|
|
959
|
+
str(library_python_venv_path),
|
|
959
960
|
],
|
|
960
961
|
check=True,
|
|
961
962
|
capture_output=True,
|
|
@@ -986,7 +987,7 @@ class LibraryManager:
|
|
|
986
987
|
|
|
987
988
|
return RegisterLibraryFromRequirementSpecifierResultSuccess(library_name=request.requirement_specifier)
|
|
988
989
|
|
|
989
|
-
def _init_library_venv(self, library_venv_path: Path) -> Path:
|
|
990
|
+
async def _init_library_venv(self, library_venv_path: Path) -> Path:
|
|
990
991
|
"""Initialize a virtual environment for the library.
|
|
991
992
|
|
|
992
993
|
If the virtual environment already exists, it will not be recreated.
|
|
@@ -1022,7 +1023,7 @@ class LibraryManager:
|
|
|
1022
1023
|
try:
|
|
1023
1024
|
uv_path = find_uv_bin()
|
|
1024
1025
|
logger.info("Creating virtual environment at %s with Python %s", library_venv_path, python_version)
|
|
1025
|
-
|
|
1026
|
+
await subprocess_run(
|
|
1026
1027
|
[uv_path, "venv", str(library_venv_path), "--python", python_version],
|
|
1027
1028
|
check=True,
|
|
1028
1029
|
capture_output=True,
|
|
@@ -1491,7 +1492,7 @@ class LibraryManager:
|
|
|
1491
1492
|
|
|
1492
1493
|
return node_class
|
|
1493
1494
|
|
|
1494
|
-
def load_all_libraries_from_config(self) -> None:
|
|
1495
|
+
async def load_all_libraries_from_config(self) -> None:
|
|
1495
1496
|
# Comment out lines 1503-1545 and call the _load libraries from provenance system to test the other functionality.
|
|
1496
1497
|
|
|
1497
1498
|
# Load metadata for all libraries to determine which ones can be safely loaded
|
|
@@ -1527,7 +1528,7 @@ class LibraryManager:
|
|
|
1527
1528
|
register_request = RegisterLibraryFromFileRequest(
|
|
1528
1529
|
file_path=library_result.file_path, load_as_default_library=False
|
|
1529
1530
|
)
|
|
1530
|
-
register_result = self.register_library_from_file_request(register_request)
|
|
1531
|
+
register_result = await self.register_library_from_file_request(register_request)
|
|
1531
1532
|
if isinstance(register_result, RegisterLibraryFromFileResultFailure):
|
|
1532
1533
|
# Registration failed - the failure info is already recorded in _library_file_path_to_info
|
|
1533
1534
|
# by register_library_from_file_request, so we just log it here for visibility
|
|
@@ -1540,12 +1541,12 @@ class LibraryManager:
|
|
|
1540
1541
|
user_libraries_section = "app_events.on_app_initialization_complete.libraries_to_register"
|
|
1541
1542
|
self._remove_missing_libraries_from_config(config_category=user_libraries_section)
|
|
1542
1543
|
|
|
1543
|
-
def on_app_initialization_complete(self, _payload: AppInitializationComplete) -> None:
|
|
1544
|
+
async def on_app_initialization_complete(self, _payload: AppInitializationComplete) -> None:
|
|
1544
1545
|
GriptapeNodes.EngineIdentityManager().initialize_engine_id()
|
|
1545
1546
|
GriptapeNodes.SessionManager().get_saved_session_id()
|
|
1546
1547
|
|
|
1547
1548
|
# App just got init'd. See if there are library JSONs to load!
|
|
1548
|
-
self.load_all_libraries_from_config()
|
|
1549
|
+
await self.load_all_libraries_from_config()
|
|
1549
1550
|
|
|
1550
1551
|
# We have to load all libraries before we attempt to load workflows.
|
|
1551
1552
|
|
|
@@ -1603,7 +1604,7 @@ class LibraryManager:
|
|
|
1603
1604
|
)
|
|
1604
1605
|
console.print(message)
|
|
1605
1606
|
|
|
1606
|
-
def _load_libraries_from_provenance_system(self) -> None:
|
|
1607
|
+
async def _load_libraries_from_provenance_system(self) -> None:
|
|
1607
1608
|
"""Load libraries using the new provenance-based system with FSM.
|
|
1608
1609
|
|
|
1609
1610
|
This method converts libraries_to_register entries into LibraryProvenanceLocalFile
|
|
@@ -1632,7 +1633,7 @@ class LibraryManager:
|
|
|
1632
1633
|
|
|
1633
1634
|
# Add to directory as user candidate (defaults to active=True)
|
|
1634
1635
|
# This automatically creates FSM and runs evaluation
|
|
1635
|
-
self._library_directory.add_user_candidate(provenance)
|
|
1636
|
+
await self._library_directory.add_user_candidate(provenance)
|
|
1636
1637
|
|
|
1637
1638
|
logger.debug("Added library provenance: %s", provenance.get_display_name())
|
|
1638
1639
|
|
|
@@ -1661,8 +1662,8 @@ class LibraryManager:
|
|
|
1661
1662
|
|
|
1662
1663
|
# Process installable candidates through installation and loading
|
|
1663
1664
|
for candidate in installable_candidates:
|
|
1664
|
-
if self._library_directory.install_library(candidate.provenance):
|
|
1665
|
-
self._library_directory.load_library(candidate.provenance)
|
|
1665
|
+
if await self._library_directory.install_library(candidate.provenance):
|
|
1666
|
+
await self._library_directory.load_library(candidate.provenance)
|
|
1666
1667
|
|
|
1667
1668
|
def _report_library_name_conflicts(self) -> None:
|
|
1668
1669
|
"""Report on library name conflicts found during evaluation."""
|
|
@@ -1997,7 +1998,7 @@ class LibraryManager:
|
|
|
1997
1998
|
]
|
|
1998
1999
|
config_mgr.set_config_value(config_category, libraries_to_register_category)
|
|
1999
2000
|
|
|
2000
|
-
def reload_all_libraries_request(self, request: ReloadAllLibrariesRequest) -> ResultPayload: # noqa: ARG002
|
|
2001
|
+
async def reload_all_libraries_request(self, request: ReloadAllLibrariesRequest) -> ResultPayload: # noqa: ARG002
|
|
2001
2002
|
# Start with a clean slate.
|
|
2002
2003
|
clear_all_request = ClearAllObjectStateRequest(i_know_what_im_doing=True)
|
|
2003
2004
|
clear_all_result = GriptapeNodes.handle_request(clear_all_request)
|
|
@@ -2023,7 +2024,7 @@ class LibraryManager:
|
|
|
2023
2024
|
return ReloadAllLibrariesResultFailure(result_details=details)
|
|
2024
2025
|
|
|
2025
2026
|
# Load (or reload, which should trigger a hot reload) all libraries
|
|
2026
|
-
self.load_all_libraries_from_config()
|
|
2027
|
+
await self.load_all_libraries_from_config()
|
|
2027
2028
|
|
|
2028
2029
|
details = (
|
|
2029
2030
|
"Successfully reloaded all libraries. All object state was cleared and previous libraries were unloaded."
|
|
@@ -75,6 +75,9 @@ from griptape_nodes.retained_mode.events.node_events import (
|
|
|
75
75
|
GetAllNodeInfoRequest,
|
|
76
76
|
GetAllNodeInfoResultFailure,
|
|
77
77
|
GetAllNodeInfoResultSuccess,
|
|
78
|
+
GetFlowForNodeRequest,
|
|
79
|
+
GetFlowForNodeResultFailure,
|
|
80
|
+
GetFlowForNodeResultSuccess,
|
|
78
81
|
GetNodeMetadataRequest,
|
|
79
82
|
GetNodeMetadataResultFailure,
|
|
80
83
|
GetNodeMetadataResultSuccess,
|
|
@@ -199,6 +202,7 @@ class NodeManager:
|
|
|
199
202
|
)
|
|
200
203
|
event_manager.assign_manager_to_request_type(DuplicateSelectedNodesRequest, self.on_duplicate_selected_nodes)
|
|
201
204
|
event_manager.assign_manager_to_request_type(SetLockNodeStateRequest, self.on_toggle_lock_node_request)
|
|
205
|
+
event_manager.assign_manager_to_request_type(GetFlowForNodeRequest, self.on_get_flow_for_node_request)
|
|
202
206
|
|
|
203
207
|
def handle_node_rename(self, old_name: str, new_name: str) -> None:
|
|
204
208
|
# Get the node itself
|
|
@@ -705,7 +709,7 @@ class NodeManager:
|
|
|
705
709
|
else:
|
|
706
710
|
failed_nodes[actual_node_name] = result.result_details
|
|
707
711
|
|
|
708
|
-
if
|
|
712
|
+
if failed_nodes:
|
|
709
713
|
return BatchSetNodeMetadataResultFailure(
|
|
710
714
|
result_details=f"Failed to update any nodes. Failed nodes: {failed_nodes}"
|
|
711
715
|
)
|
|
@@ -961,6 +965,7 @@ class NodeManager:
|
|
|
961
965
|
allowed_modes=allowed_modes,
|
|
962
966
|
ui_options=request.ui_options,
|
|
963
967
|
parent_container_name=request.parent_container_name,
|
|
968
|
+
settable=request.settable,
|
|
964
969
|
)
|
|
965
970
|
try:
|
|
966
971
|
if request.parent_container_name and request.initial_setup:
|
|
@@ -968,7 +973,6 @@ class NodeManager:
|
|
|
968
973
|
if parameter_parent is not None:
|
|
969
974
|
parameter_parent.add_child(new_param)
|
|
970
975
|
else:
|
|
971
|
-
logger.info(new_param.name)
|
|
972
976
|
node.add_parameter(new_param)
|
|
973
977
|
except Exception as e:
|
|
974
978
|
details = f"Couldn't add parameter with name {request.parameter_name} to Node '{node_name}'. Error: {e}"
|
|
@@ -1168,6 +1172,7 @@ class NodeManager:
|
|
|
1168
1172
|
mode_allowed_property=allows_property,
|
|
1169
1173
|
mode_allowed_output=allows_output,
|
|
1170
1174
|
is_user_defined=getattr(element, "user_defined", False),
|
|
1175
|
+
settable=getattr(element, "settable", None),
|
|
1171
1176
|
ui_options=getattr(element, "ui_options", None),
|
|
1172
1177
|
)
|
|
1173
1178
|
return result
|
|
@@ -1257,7 +1262,7 @@ class NodeManager:
|
|
|
1257
1262
|
if request.ui_options is not None and hasattr(parameter, "ui_options"):
|
|
1258
1263
|
parameter.ui_options = request.ui_options # type: ignore[attr-defined]
|
|
1259
1264
|
|
|
1260
|
-
def modify_key_parameter_fields(self, request: AlterParameterDetailsRequest, parameter: Parameter) -> None:
|
|
1265
|
+
def modify_key_parameter_fields(self, request: AlterParameterDetailsRequest, parameter: Parameter) -> None: # noqa: C901, PLR0912
|
|
1261
1266
|
if request.type is not None:
|
|
1262
1267
|
parameter.type = request.type
|
|
1263
1268
|
if request.input_types is not None:
|
|
@@ -1282,6 +1287,8 @@ class NodeManager:
|
|
|
1282
1287
|
parameter.allowed_modes.add(ParameterMode.OUTPUT)
|
|
1283
1288
|
else:
|
|
1284
1289
|
parameter.allowed_modes.discard(ParameterMode.OUTPUT)
|
|
1290
|
+
if request.settable is not None:
|
|
1291
|
+
parameter.settable = request.settable
|
|
1285
1292
|
|
|
1286
1293
|
def _validate_and_break_invalid_connections(
|
|
1287
1294
|
self, node_name: str, parameter: Parameter, request: AlterParameterDetailsRequest
|
|
@@ -1549,7 +1556,50 @@ class NodeManager:
|
|
|
1549
1556
|
result = SetParameterValueResultFailure(result_details=details)
|
|
1550
1557
|
return result
|
|
1551
1558
|
|
|
1559
|
+
# Validate incoming connection source fields consistency
|
|
1560
|
+
incoming_node_set = request.incoming_connection_source_node_name is not None
|
|
1561
|
+
incoming_param_set = request.incoming_connection_source_parameter_name is not None
|
|
1562
|
+
if incoming_node_set != incoming_param_set:
|
|
1563
|
+
details = f"Attempted to set parameter value for '{node_name}.{request.parameter_name}'. Failed because incoming connection source fields must both be None or both be set. Got incoming_connection_source_node_name={request.incoming_connection_source_node_name}, incoming_connection_source_parameter_name={request.incoming_connection_source_parameter_name}."
|
|
1564
|
+
logger.error(details)
|
|
1565
|
+
result = SetParameterValueResultFailure(result_details=details)
|
|
1566
|
+
return result
|
|
1567
|
+
|
|
1568
|
+
# Prevent manual property setting on parameters that have both INPUT and PROPERTY modes when they have incoming connections
|
|
1569
|
+
# When a parameter can accept both input connections AND manual property values, having an active connection should
|
|
1570
|
+
# make the parameter non-settable as a property to avoid conflicts between connected values and manual values
|
|
1571
|
+
# Skip this check if: initial_setup (workflow loading), or incoming_connection_source fields are set (system passing upstream values)
|
|
1572
|
+
if (
|
|
1573
|
+
not request.initial_setup
|
|
1574
|
+
and not incoming_node_set # If incoming connection source fields are set, this is a legitimate upstream value pass
|
|
1575
|
+
and ParameterMode.INPUT in parameter.allowed_modes
|
|
1576
|
+
and ParameterMode.PROPERTY in parameter.allowed_modes
|
|
1577
|
+
):
|
|
1578
|
+
# Check if this parameter has any incoming connections
|
|
1579
|
+
connections = GriptapeNodes.FlowManager().get_connections()
|
|
1580
|
+
target_connections = connections.incoming_index.get(node_name)
|
|
1581
|
+
if target_connections is not None:
|
|
1582
|
+
param_connections = target_connections.get(request.parameter_name)
|
|
1583
|
+
if param_connections: # Has incoming connections
|
|
1584
|
+
# TODO: https://github.com/griptape-ai/griptape-nodes/issues/1965 Consider emitting UI events when parameters become settable/unsettable due to connection changes
|
|
1585
|
+
details = f"Attempted to set parameter value for '{node_name}.{request.parameter_name}'. Failed because this parameter has incoming connections and cannot be set as a property while connected."
|
|
1586
|
+
logger.error(details)
|
|
1587
|
+
result = SetParameterValueResultFailure(result_details=details)
|
|
1588
|
+
return result
|
|
1589
|
+
|
|
1590
|
+
# Call before_value_set hook (allows nodes to modify values and temporarily control settable state)
|
|
1591
|
+
try:
|
|
1592
|
+
modified_value = node.before_value_set(parameter, request.value)
|
|
1593
|
+
if modified_value is not None:
|
|
1594
|
+
request.value = modified_value
|
|
1595
|
+
except Exception as err:
|
|
1596
|
+
details = f"Attempted to set parameter value for '{node_name}.{request.parameter_name}'. Failed because before_value_set hook raised exception: {err}"
|
|
1597
|
+
logger.error(details)
|
|
1598
|
+
result = SetParameterValueResultFailure(result_details=details)
|
|
1599
|
+
return result
|
|
1600
|
+
|
|
1552
1601
|
# Validate that parameters can be set at all (note: we want the value to be set during initial setup, but not after)
|
|
1602
|
+
# This check comes after before_value_set to allow nodes to temporarily modify settable state
|
|
1553
1603
|
if not parameter.settable and not request.initial_setup:
|
|
1554
1604
|
details = f"Attempted to set parameter value for '{node_name}.{request.parameter_name}'. Failed because that Parameter was flagged as not settable."
|
|
1555
1605
|
logger.error(details)
|
|
@@ -1596,8 +1646,9 @@ class NodeManager:
|
|
|
1596
1646
|
# Mark node as unresolved, broadcast an event
|
|
1597
1647
|
node.make_node_unresolved(current_states_to_trigger_change_event=set({NodeResolutionState.RESOLVED}))
|
|
1598
1648
|
# Get the flow
|
|
1599
|
-
# Pass the value through!
|
|
1600
|
-
#
|
|
1649
|
+
# Pass the value through to connected downstream parameters!
|
|
1650
|
+
# Set incoming_connection_source fields to identify this as legitimate upstream value propagation
|
|
1651
|
+
# (not manual property setting) so it bypasses the INPUT+PROPERTY connection blocking logic
|
|
1601
1652
|
conn_output_nodes = parent_flow.get_connected_output_parameters(node, parameter)
|
|
1602
1653
|
for target_node, target_parameter in conn_output_nodes:
|
|
1603
1654
|
# Skip propagation for Control Parameters as they should not receive values
|
|
@@ -1608,6 +1659,8 @@ class NodeManager:
|
|
|
1608
1659
|
node_name=target_node.name,
|
|
1609
1660
|
value=finalized_value,
|
|
1610
1661
|
data_type=object_type, # Do type instead of output type, because it hasn't been processed.
|
|
1662
|
+
incoming_connection_source_node_name=node.name,
|
|
1663
|
+
incoming_connection_source_parameter_name=parameter.name,
|
|
1611
1664
|
)
|
|
1612
1665
|
)
|
|
1613
1666
|
|
|
@@ -1633,8 +1686,11 @@ class NodeManager:
|
|
|
1633
1686
|
node.parameter_output_values[request.parameter_name] = object_created
|
|
1634
1687
|
return NodeManager.ModifiedReturnValue(object_created, modified)
|
|
1635
1688
|
# Otherwise use set_parameter_value. This calls our converters and validators.
|
|
1689
|
+
# Skip before_value_set since we already called it earlier in the flow
|
|
1636
1690
|
old_value = node.get_parameter_value(request.parameter_name)
|
|
1637
|
-
node.set_parameter_value(
|
|
1691
|
+
node.set_parameter_value(
|
|
1692
|
+
request.parameter_name, object_created, initial_setup=request.initial_setup, skip_before_value_set=True
|
|
1693
|
+
)
|
|
1638
1694
|
# Get the "converted" value here.
|
|
1639
1695
|
finalized_value = node.get_parameter_value(request.parameter_name)
|
|
1640
1696
|
if old_value != finalized_value:
|
|
@@ -1867,7 +1923,7 @@ class NodeManager:
|
|
|
1867
1923
|
raise KeyError(msg)
|
|
1868
1924
|
return self._name_to_parent_flow_name[node_name]
|
|
1869
1925
|
|
|
1870
|
-
def on_resolve_from_node_request(self, request: ResolveNodeRequest) -> ResultPayload: # noqa: C901, PLR0911, PLR0915, PLR0912
|
|
1926
|
+
async def on_resolve_from_node_request(self, request: ResolveNodeRequest) -> ResultPayload: # noqa: C901, PLR0911, PLR0915, PLR0912
|
|
1871
1927
|
node_name = request.node_name
|
|
1872
1928
|
debug_mode = request.debug_mode
|
|
1873
1929
|
|
|
@@ -1935,7 +1991,7 @@ class NodeManager:
|
|
|
1935
1991
|
logger.error(details)
|
|
1936
1992
|
return StartFlowResultFailure(validation_exceptions=[e], result_details=details)
|
|
1937
1993
|
try:
|
|
1938
|
-
GriptapeNodes.FlowManager().resolve_singular_node(flow, node, debug_mode)
|
|
1994
|
+
await GriptapeNodes.FlowManager().resolve_singular_node(flow, node, debug_mode)
|
|
1939
1995
|
except Exception as e:
|
|
1940
1996
|
details = f'Failed to resolve "{node_name}". Error: {e}'
|
|
1941
1997
|
logger.error(details)
|
|
@@ -2636,6 +2692,12 @@ class NodeManager:
|
|
|
2636
2692
|
logger.error(details)
|
|
2637
2693
|
return RenameParameterResultFailure(result_details=details)
|
|
2638
2694
|
|
|
2695
|
+
# Only allow parameter rename for user-defined params
|
|
2696
|
+
if not parameter.user_defined:
|
|
2697
|
+
details = f"Attempted to rename Parameter '{request.parameter_name}' on Node '{node_name}'. Failed because the Parameter is not user-defined."
|
|
2698
|
+
logger.error(details)
|
|
2699
|
+
return RenameParameterResultFailure(result_details=details)
|
|
2700
|
+
|
|
2639
2701
|
# Validate the new parameter name
|
|
2640
2702
|
if any(char.isspace() for char in request.new_parameter_name):
|
|
2641
2703
|
details = f"Failed to rename Parameter '{request.parameter_name}' to '{request.new_parameter_name}'. Parameter names cannot contain any whitespace characters."
|
|
@@ -2765,3 +2827,16 @@ class NodeManager:
|
|
|
2765
2827
|
response=callback_result.response,
|
|
2766
2828
|
altered_workflow_state=callback_result.altered_workflow_state,
|
|
2767
2829
|
)
|
|
2830
|
+
|
|
2831
|
+
def on_get_flow_for_node_request(self, request: GetFlowForNodeRequest) -> ResultPayload:
|
|
2832
|
+
"""Get the flow name that contains a specific node."""
|
|
2833
|
+
try:
|
|
2834
|
+
flow_name = self.get_node_parent_flow_by_name(request.node_name)
|
|
2835
|
+
return GetFlowForNodeResultSuccess(
|
|
2836
|
+
flow_name=flow_name,
|
|
2837
|
+
result_details=f"Successfully retrieved flow '{flow_name}' for node '{request.node_name}'.",
|
|
2838
|
+
)
|
|
2839
|
+
except KeyError:
|
|
2840
|
+
return GetFlowForNodeResultFailure(
|
|
2841
|
+
result_details=f"Node '{request.node_name}' not found or not assigned to any flow.",
|
|
2842
|
+
)
|
|
@@ -143,6 +143,10 @@ class ObjectManager:
|
|
|
143
143
|
context_mgr.pop_flow()
|
|
144
144
|
context_mgr.pop_workflow()
|
|
145
145
|
context_mgr._clipboard.clear()
|
|
146
|
+
|
|
147
|
+
# Clear all local workflow variables
|
|
148
|
+
GriptapeNodes.VariablesManager().on_clear_object_state()
|
|
149
|
+
|
|
146
150
|
details = "Successfully cleared all object state (deleted everything)."
|
|
147
151
|
logger.debug(details)
|
|
148
152
|
return ClearAllObjectStateResultSuccess()
|
|
@@ -75,6 +75,7 @@ class Settings(BaseModel):
|
|
|
75
75
|
"Exa": {"EXA_API_KEY": "$EXA_API_KEY"},
|
|
76
76
|
"Grok": {"GROK_API_KEY": "$GROK_API_KEY"},
|
|
77
77
|
"Groq": {"GROQ_API_KEY": "$GROQ_API_KEY"},
|
|
78
|
+
"Nvidia": {"NVIDIA_API_KEY": "$NVIDIA_API_KEY"},
|
|
78
79
|
"Google": {"GOOGLE_API_KEY": "$GOOGLE_API_KEY", "GOOGLE_API_SEARCH_ID": "$GOOGLE_API_SEARCH_ID"},
|
|
79
80
|
"Huggingface": {"HUGGINGFACE_HUB_ACCESS_TOKEN": "$HUGGINGFACE_HUB_ACCESS_TOKEN"},
|
|
80
81
|
"LeonardoAI": {"LEONARDO_API_KEY": "$LEONARDO_API_KEY"},
|
|
@@ -24,6 +24,7 @@ from griptape_nodes.retained_mode.events.workflow_events import (
|
|
|
24
24
|
RegisterWorkflowsFromConfigRequest,
|
|
25
25
|
RegisterWorkflowsFromConfigResultSuccess,
|
|
26
26
|
)
|
|
27
|
+
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
27
28
|
|
|
28
29
|
if TYPE_CHECKING:
|
|
29
30
|
from griptape_nodes.retained_mode.events.base_events import ResultPayload
|
|
@@ -167,8 +168,6 @@ class SyncManager:
|
|
|
167
168
|
sync_request = StartSyncAllCloudWorkflowsRequest()
|
|
168
169
|
|
|
169
170
|
# Use handle_request to process through normal event system
|
|
170
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
171
|
-
|
|
172
171
|
result = GriptapeNodes.handle_request(sync_request)
|
|
173
172
|
|
|
174
173
|
if isinstance(result, StartSyncAllCloudWorkflowsResultSuccess):
|
|
@@ -193,8 +192,6 @@ class SyncManager:
|
|
|
193
192
|
Raises:
|
|
194
193
|
RuntimeError: If required cloud configuration is missing.
|
|
195
194
|
"""
|
|
196
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
197
|
-
|
|
198
195
|
secrets_manager = GriptapeNodes.SecretsManager()
|
|
199
196
|
|
|
200
197
|
# Get cloud storage configuration from secrets
|
|
@@ -428,8 +425,6 @@ class SyncManager:
|
|
|
428
425
|
self, sync_id: str, workflow_files: list[str], storage_driver: GriptapeCloudStorageDriver, sync_dir: Path
|
|
429
426
|
) -> None:
|
|
430
427
|
"""Background thread function to sync workflows."""
|
|
431
|
-
from griptape_nodes.app.app import event_queue
|
|
432
|
-
|
|
433
428
|
synced_workflows = []
|
|
434
429
|
failed_downloads = []
|
|
435
430
|
total_workflows = len(workflow_files)
|
|
@@ -470,14 +465,13 @@ class SyncManager:
|
|
|
470
465
|
failed_workflows=failed_downloads,
|
|
471
466
|
total_workflows=total_workflows,
|
|
472
467
|
)
|
|
473
|
-
|
|
468
|
+
|
|
469
|
+
GriptapeNodes.EventManager().put_event(AppEvent(payload=sync_complete_event))
|
|
474
470
|
|
|
475
471
|
# Register workflows from the synced directory
|
|
476
472
|
if synced_workflows:
|
|
477
473
|
logger.info("Registering %d synced workflows from configuration", len(synced_workflows))
|
|
478
474
|
try:
|
|
479
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
480
|
-
|
|
481
475
|
register_request = RegisterWorkflowsFromConfigRequest(
|
|
482
476
|
config_section="app_events.on_app_initialization_complete.workflows_to_register"
|
|
483
477
|
)
|