griptape-nodes 0.52.1__py3-none-any.whl → 0.53.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 +6 -943
- griptape_nodes/__main__.py +6 -0
- griptape_nodes/app/app.py +45 -61
- griptape_nodes/cli/__init__.py +1 -0
- griptape_nodes/cli/commands/__init__.py +1 -0
- griptape_nodes/cli/commands/config.py +71 -0
- griptape_nodes/cli/commands/engine.py +80 -0
- griptape_nodes/cli/commands/init.py +548 -0
- griptape_nodes/cli/commands/libraries.py +90 -0
- griptape_nodes/cli/commands/self.py +117 -0
- griptape_nodes/cli/main.py +46 -0
- griptape_nodes/cli/shared.py +84 -0
- griptape_nodes/common/__init__.py +1 -0
- griptape_nodes/common/directed_graph.py +55 -0
- griptape_nodes/drivers/storage/local_storage_driver.py +7 -2
- griptape_nodes/exe_types/core_types.py +60 -2
- griptape_nodes/exe_types/node_types.py +38 -24
- griptape_nodes/machines/control_flow.py +86 -22
- griptape_nodes/machines/fsm.py +10 -1
- griptape_nodes/machines/parallel_resolution.py +570 -0
- griptape_nodes/machines/{node_resolution.py → sequential_resolution.py} +22 -51
- griptape_nodes/retained_mode/events/base_events.py +2 -2
- griptape_nodes/retained_mode/events/node_events.py +4 -3
- griptape_nodes/retained_mode/griptape_nodes.py +25 -12
- griptape_nodes/retained_mode/managers/agent_manager.py +9 -5
- griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +3 -1
- griptape_nodes/retained_mode/managers/context_manager.py +6 -5
- griptape_nodes/retained_mode/managers/flow_manager.py +117 -204
- griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +1 -1
- griptape_nodes/retained_mode/managers/library_manager.py +35 -25
- griptape_nodes/retained_mode/managers/node_manager.py +81 -199
- griptape_nodes/retained_mode/managers/object_manager.py +11 -5
- griptape_nodes/retained_mode/managers/os_manager.py +24 -9
- griptape_nodes/retained_mode/managers/secrets_manager.py +8 -4
- griptape_nodes/retained_mode/managers/settings.py +32 -1
- griptape_nodes/retained_mode/managers/static_files_manager.py +8 -3
- griptape_nodes/retained_mode/managers/sync_manager.py +8 -5
- griptape_nodes/retained_mode/managers/workflow_manager.py +110 -122
- griptape_nodes/traits/add_param_button.py +1 -1
- griptape_nodes/traits/button.py +216 -6
- griptape_nodes/traits/color_picker.py +66 -0
- griptape_nodes/traits/traits.json +4 -0
- {griptape_nodes-0.52.1.dist-info → griptape_nodes-0.53.0.dist-info}/METADATA +2 -1
- {griptape_nodes-0.52.1.dist-info → griptape_nodes-0.53.0.dist-info}/RECORD +46 -32
- {griptape_nodes-0.52.1.dist-info → griptape_nodes-0.53.0.dist-info}/WHEEL +0 -0
- {griptape_nodes-0.52.1.dist-info → griptape_nodes-0.53.0.dist-info}/entry_points.txt +0 -0
|
@@ -9,7 +9,8 @@ from griptape_nodes.exe_types.core_types import Parameter
|
|
|
9
9
|
from griptape_nodes.exe_types.node_types import BaseNode, NodeResolutionState
|
|
10
10
|
from griptape_nodes.exe_types.type_validator import TypeValidator
|
|
11
11
|
from griptape_nodes.machines.fsm import FSM, State
|
|
12
|
-
from griptape_nodes.machines.
|
|
12
|
+
from griptape_nodes.machines.parallel_resolution import ParallelResolutionMachine
|
|
13
|
+
from griptape_nodes.machines.sequential_resolution import SequentialResolutionMachine
|
|
13
14
|
from griptape_nodes.retained_mode.events.base_events import ExecutionEvent, ExecutionGriptapeNodeEvent
|
|
14
15
|
from griptape_nodes.retained_mode.events.execution_events import (
|
|
15
16
|
ControlFlowResolvedEvent,
|
|
@@ -17,6 +18,7 @@ from griptape_nodes.retained_mode.events.execution_events import (
|
|
|
17
18
|
SelectedControlOutputEvent,
|
|
18
19
|
)
|
|
19
20
|
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
21
|
+
from griptape_nodes.retained_mode.managers.settings import WorkflowExecutionMode
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
@dataclass
|
|
@@ -38,12 +40,23 @@ logger = logging.getLogger("griptape_nodes")
|
|
|
38
40
|
class ControlFlowContext:
|
|
39
41
|
flow: ControlFlow
|
|
40
42
|
current_node: BaseNode | None
|
|
41
|
-
resolution_machine:
|
|
43
|
+
resolution_machine: ParallelResolutionMachine | SequentialResolutionMachine
|
|
42
44
|
selected_output: Parameter | None
|
|
43
45
|
paused: bool = False
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
flow_name: str
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
flow_name: str,
|
|
51
|
+
max_nodes_in_parallel: int,
|
|
52
|
+
*,
|
|
53
|
+
execution_type: WorkflowExecutionMode = WorkflowExecutionMode.SEQUENTIAL,
|
|
54
|
+
) -> None:
|
|
55
|
+
self.flow_name = flow_name
|
|
56
|
+
if execution_type == WorkflowExecutionMode.PARALLEL:
|
|
57
|
+
self.resolution_machine = ParallelResolutionMachine(flow_name, max_nodes_in_parallel)
|
|
58
|
+
else:
|
|
59
|
+
self.resolution_machine = SequentialResolutionMachine()
|
|
47
60
|
self.current_node = None
|
|
48
61
|
|
|
49
62
|
def get_next_node(self, output_parameter: Parameter) -> NextNodeInfo | None:
|
|
@@ -66,11 +79,11 @@ class ControlFlowContext:
|
|
|
66
79
|
return NextNodeInfo(node=node, entry_parameter=None)
|
|
67
80
|
return None
|
|
68
81
|
|
|
69
|
-
def reset(self) -> None:
|
|
82
|
+
def reset(self, *, cancel: bool = False) -> None:
|
|
70
83
|
if self.current_node:
|
|
71
84
|
self.current_node.clear_node()
|
|
72
85
|
self.current_node = None
|
|
73
|
-
self.resolution_machine.reset_machine()
|
|
86
|
+
self.resolution_machine.reset_machine(cancel=cancel)
|
|
74
87
|
self.selected_output = None
|
|
75
88
|
self.paused = False
|
|
76
89
|
|
|
@@ -194,11 +207,18 @@ class CompleteState(State):
|
|
|
194
207
|
|
|
195
208
|
# MACHINE TIME!!!
|
|
196
209
|
class ControlFlowMachine(FSM[ControlFlowContext]):
|
|
197
|
-
def __init__(self) -> None:
|
|
198
|
-
|
|
210
|
+
def __init__(self, flow_name: str) -> None:
|
|
211
|
+
execution_type = GriptapeNodes.ConfigManager().get_config_value(
|
|
212
|
+
"workflow_execution_mode", default=WorkflowExecutionMode.SEQUENTIAL
|
|
213
|
+
)
|
|
214
|
+
max_nodes_in_parallel = GriptapeNodes.ConfigManager().get_config_value("max_nodes_in_parallel", default=5)
|
|
215
|
+
context = ControlFlowContext(flow_name, max_nodes_in_parallel, execution_type=execution_type)
|
|
199
216
|
super().__init__(context)
|
|
200
217
|
|
|
201
218
|
async def start_flow(self, start_node: BaseNode, debug_mode: bool = False) -> None: # noqa: FBT001, FBT002
|
|
219
|
+
# If using DAG resolution, process data_nodes from queue first
|
|
220
|
+
if isinstance(self._context.resolution_machine, ParallelResolutionMachine):
|
|
221
|
+
await self._process_data_nodes_for_dag()
|
|
202
222
|
self._context.current_node = start_node
|
|
203
223
|
# Set entry control parameter for initial node (None for workflow start)
|
|
204
224
|
start_node.set_entry_control_parameter(None)
|
|
@@ -214,31 +234,75 @@ class ControlFlowMachine(FSM[ControlFlowContext]):
|
|
|
214
234
|
|
|
215
235
|
def change_debug_mode(self, debug_mode: bool) -> None: # noqa: FBT001
|
|
216
236
|
self._context.paused = debug_mode
|
|
217
|
-
self._context.resolution_machine.change_debug_mode(debug_mode)
|
|
237
|
+
self._context.resolution_machine.change_debug_mode(debug_mode=debug_mode)
|
|
218
238
|
|
|
219
239
|
async def granular_step(self, change_debug_mode: bool) -> None: # noqa: FBT001
|
|
220
240
|
resolution_machine = self._context.resolution_machine
|
|
241
|
+
|
|
221
242
|
if change_debug_mode:
|
|
222
|
-
resolution_machine.change_debug_mode(True)
|
|
243
|
+
resolution_machine.change_debug_mode(debug_mode=True)
|
|
223
244
|
await resolution_machine.update()
|
|
224
245
|
|
|
225
|
-
# Tick the control flow if the
|
|
226
|
-
if
|
|
246
|
+
# Tick the control flow if the current machine isn't busy
|
|
247
|
+
if self._current_state is ResolveNodeState and ( # noqa: SIM102
|
|
248
|
+
resolution_machine.is_complete() or not resolution_machine.is_started()
|
|
249
|
+
):
|
|
227
250
|
# Don't tick ourselves if we are already complete.
|
|
228
251
|
if self._current_state is not None:
|
|
229
252
|
await self.update()
|
|
230
253
|
|
|
231
254
|
async def node_step(self) -> None:
|
|
232
255
|
resolution_machine = self._context.resolution_machine
|
|
233
|
-
resolution_machine.change_debug_mode(False)
|
|
234
|
-
await resolution_machine.update()
|
|
235
256
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
257
|
+
resolution_machine.change_debug_mode(debug_mode=False)
|
|
258
|
+
|
|
259
|
+
# If we're in the resolution phase, step the resolution machine
|
|
260
|
+
if self._current_state is ResolveNodeState:
|
|
261
|
+
await resolution_machine.update()
|
|
262
|
+
|
|
263
|
+
# Tick the control flow if the current machine isn't busy
|
|
264
|
+
if self._current_state is ResolveNodeState and (
|
|
265
|
+
resolution_machine.is_complete() or not resolution_machine.is_started()
|
|
266
|
+
):
|
|
267
|
+
await self.update()
|
|
241
268
|
|
|
242
|
-
def
|
|
243
|
-
|
|
269
|
+
async def _process_data_nodes_for_dag(self) -> None:
|
|
270
|
+
"""Process data_nodes from the global queue to build unified DAG.
|
|
271
|
+
|
|
272
|
+
This method identifies data_nodes in the execution queue and processes
|
|
273
|
+
their dependencies into the DAG resolution machine.
|
|
274
|
+
"""
|
|
275
|
+
if not isinstance(self._context.resolution_machine, ParallelResolutionMachine):
|
|
276
|
+
return
|
|
277
|
+
# Get the global flow queue
|
|
278
|
+
flow_manager = GriptapeNodes.FlowManager()
|
|
279
|
+
queue_items = list(flow_manager.global_flow_queue.queue)
|
|
280
|
+
|
|
281
|
+
# Find data_nodes and remove them from queue
|
|
282
|
+
data_nodes = []
|
|
283
|
+
for item in queue_items:
|
|
284
|
+
from griptape_nodes.retained_mode.managers.flow_manager import DagExecutionType
|
|
285
|
+
|
|
286
|
+
if item.dag_execution_type == DagExecutionType.DATA_NODE:
|
|
287
|
+
data_nodes.append(item.node)
|
|
288
|
+
flow_manager.global_flow_queue.queue.remove(item)
|
|
289
|
+
|
|
290
|
+
# Build DAG for each data node
|
|
291
|
+
for node in data_nodes:
|
|
292
|
+
node.state = NodeResolutionState.UNRESOLVED
|
|
293
|
+
await self._context.resolution_machine.resolve_node(node, build_only=True)
|
|
294
|
+
|
|
295
|
+
# Run resolution until complete for this node's subgraph
|
|
296
|
+
while not self._context.resolution_machine.is_complete():
|
|
297
|
+
await self._context.resolution_machine.update()
|
|
298
|
+
|
|
299
|
+
# Reset the machine state to allow adding more nodes
|
|
300
|
+
self._context.resolution_machine.current_state = None
|
|
301
|
+
|
|
302
|
+
def reset_machine(self, *, cancel: bool = False) -> None:
|
|
303
|
+
self._context.reset(cancel=cancel)
|
|
244
304
|
self._current_state = None
|
|
305
|
+
|
|
306
|
+
@property
|
|
307
|
+
def resolution_machine(self) -> ParallelResolutionMachine | SequentialResolutionMachine:
|
|
308
|
+
return self._context.resolution_machine
|
griptape_nodes/machines/fsm.py
CHANGED
|
@@ -34,9 +34,18 @@ class FSM[T]:
|
|
|
34
34
|
# Enter the initial state.
|
|
35
35
|
await self.transition_state(initial_state)
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
@property
|
|
38
|
+
def current_state(self) -> type[State] | None:
|
|
38
39
|
return self._current_state
|
|
39
40
|
|
|
41
|
+
@current_state.setter
|
|
42
|
+
def current_state(self, value: type[State] | None) -> None:
|
|
43
|
+
self._current_state = value
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def context(self) -> T:
|
|
47
|
+
return self._context
|
|
48
|
+
|
|
40
49
|
async def transition_state(self, new_state: type[State] | None) -> None:
|
|
41
50
|
while new_state is not None:
|
|
42
51
|
# Exit the current state.
|