griptape-nodes 0.69.0__py3-none-any.whl → 0.70.1__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/api_client/client.py +5 -1
- griptape_nodes/app/app.py +51 -0
- griptape_nodes/exe_types/param_components/execution_status_component.py +10 -2
- griptape_nodes/exe_types/param_components/log_parameter.py +5 -1
- griptape_nodes/exe_types/param_types/parameter_number.py +22 -16
- griptape_nodes/retained_mode/events/node_events.py +5 -1
- griptape_nodes/retained_mode/managers/context_manager.py +1 -27
- griptape_nodes/retained_mode/managers/node_manager.py +78 -23
- griptape_nodes/retained_mode/managers/object_manager.py +0 -1
- griptape_nodes/traits/clamp.py +52 -9
- {griptape_nodes-0.69.0.dist-info → griptape_nodes-0.70.1.dist-info}/METADATA +1 -1
- {griptape_nodes-0.69.0.dist-info → griptape_nodes-0.70.1.dist-info}/RECORD +14 -14
- {griptape_nodes-0.69.0.dist-info → griptape_nodes-0.70.1.dist-info}/WHEEL +2 -2
- {griptape_nodes-0.69.0.dist-info → griptape_nodes-0.70.1.dist-info}/entry_points.txt +0 -0
|
@@ -168,7 +168,11 @@ class Client:
|
|
|
168
168
|
logger.debug("WebSocket client connected")
|
|
169
169
|
except TimeoutError as e:
|
|
170
170
|
logger.error("Failed to connect WebSocket client: timeout")
|
|
171
|
-
msg =
|
|
171
|
+
msg = (
|
|
172
|
+
"Connection timeout - failed to connect to Nodes API. "
|
|
173
|
+
"This usually indicates an invalid or missing GT_CLOUD_API_KEY. "
|
|
174
|
+
"Please verify your API key is correct."
|
|
175
|
+
)
|
|
172
176
|
raise ConnectionError(msg) from e
|
|
173
177
|
|
|
174
178
|
async def _disconnect(self) -> None:
|
griptape_nodes/app/app.py
CHANGED
|
@@ -3,11 +3,14 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import json
|
|
5
5
|
import logging
|
|
6
|
+
import sys
|
|
6
7
|
import threading
|
|
7
8
|
from dataclasses import dataclass
|
|
8
9
|
|
|
10
|
+
from rich.align import Align
|
|
9
11
|
from rich.console import Console
|
|
10
12
|
from rich.logging import RichHandler
|
|
13
|
+
from rich.panel import Panel
|
|
11
14
|
|
|
12
15
|
from griptape_nodes.api_client import Client
|
|
13
16
|
from griptape_nodes.retained_mode.events import app_events, execution_events
|
|
@@ -113,6 +116,35 @@ logging.basicConfig(
|
|
|
113
116
|
console = Console()
|
|
114
117
|
|
|
115
118
|
|
|
119
|
+
def _ensure_api_key() -> str:
|
|
120
|
+
"""Verify that GT_CLOUD_API_KEY is set, exit with clear error message if not.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
The API key value
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
SystemExit: If API key is missing or empty
|
|
127
|
+
"""
|
|
128
|
+
secrets_manager = griptape_nodes.SecretsManager()
|
|
129
|
+
api_key = secrets_manager.get_secret("GT_CLOUD_API_KEY", should_error_on_not_found=False)
|
|
130
|
+
|
|
131
|
+
if not api_key:
|
|
132
|
+
message = Panel(
|
|
133
|
+
Align.center(
|
|
134
|
+
"[bold red]Nodes API key is not set, please run [code]gtn init[/code] with a valid key:[/bold red]\n"
|
|
135
|
+
"[code]gtn init --api-key <your key>[/code]\n\n"
|
|
136
|
+
"[bold red]You can generate a new key from [/bold red][bold blue][link=https://nodes.griptape.ai]https://nodes.griptape.ai[/link][/bold blue]",
|
|
137
|
+
),
|
|
138
|
+
title="[red]X[/red] Missing Nodes API Key",
|
|
139
|
+
border_style="red",
|
|
140
|
+
padding=(1, 4),
|
|
141
|
+
)
|
|
142
|
+
console.print(message)
|
|
143
|
+
sys.exit(1)
|
|
144
|
+
|
|
145
|
+
return api_key
|
|
146
|
+
|
|
147
|
+
|
|
116
148
|
def start_app() -> None:
|
|
117
149
|
"""Legacy sync entry point - runs async app."""
|
|
118
150
|
try:
|
|
@@ -125,6 +157,9 @@ def start_app() -> None:
|
|
|
125
157
|
|
|
126
158
|
async def astart_app() -> None:
|
|
127
159
|
"""New async app entry point."""
|
|
160
|
+
# Verify API key is set before starting
|
|
161
|
+
_ensure_api_key()
|
|
162
|
+
|
|
128
163
|
# Initialize event queue in main thread
|
|
129
164
|
griptape_nodes.EventManager().initialize_queue()
|
|
130
165
|
|
|
@@ -154,6 +189,22 @@ def _start_websocket_connection() -> None:
|
|
|
154
189
|
|
|
155
190
|
# Run the async WebSocket tasks
|
|
156
191
|
loop.run_until_complete(_run_websocket_tasks())
|
|
192
|
+
except ConnectionError:
|
|
193
|
+
# Connection failed - likely due to invalid/missing API key
|
|
194
|
+
message = Panel(
|
|
195
|
+
Align.center(
|
|
196
|
+
"[bold red]Failed to connect to Nodes API.[/bold red]\n\n"
|
|
197
|
+
"This usually indicates an invalid or missing [code]GT_CLOUD_API_KEY[/code].\n\n"
|
|
198
|
+
"[bold red]Please verify your API key:[/bold red]\n"
|
|
199
|
+
"[code]gtn init --api-key <your key>[/code]\n\n"
|
|
200
|
+
"[bold red]You can generate a new key from [/bold red][bold blue][link=https://nodes.griptape.ai]https://nodes.griptape.ai[/link][/bold blue]",
|
|
201
|
+
),
|
|
202
|
+
title="[red]X[/red] Connection Failed",
|
|
203
|
+
border_style="red",
|
|
204
|
+
padding=(1, 4),
|
|
205
|
+
)
|
|
206
|
+
console.print(message)
|
|
207
|
+
sys.exit(1)
|
|
157
208
|
except Exception as e:
|
|
158
209
|
logger.error("WebSocket thread error: %s", e)
|
|
159
210
|
raise
|
|
@@ -103,8 +103,16 @@ class ExecutionStatusComponent:
|
|
|
103
103
|
"""
|
|
104
104
|
self._update_parameter_value(self._was_successful, was_successful)
|
|
105
105
|
self._update_parameter_value(self._result_details, result_details)
|
|
106
|
-
# Update display label: show warning emoji on failure
|
|
107
|
-
|
|
106
|
+
# Update display label: show warning emoji only on actual failure (not placeholder/initialization messages)
|
|
107
|
+
# While string matching is not the best practice, it's currently the only way to check for placeholder messages.
|
|
108
|
+
# TODO: use a better approach to check for placeholder messages. https://github.com/griptape-ai/griptape-nodes/issues/3686
|
|
109
|
+
is_placeholder = result_details in (
|
|
110
|
+
"<Results will appear when the node executes>",
|
|
111
|
+
"Beginning execution...",
|
|
112
|
+
"",
|
|
113
|
+
)
|
|
114
|
+
show_warning = not was_successful and not is_placeholder
|
|
115
|
+
self._update_status_group_display_label(show_warning=show_warning)
|
|
108
116
|
|
|
109
117
|
def clear_execution_status(self, initial_message: str | None = None) -> None:
|
|
110
118
|
"""Clear execution status and reset parameters.
|
|
@@ -20,7 +20,7 @@ class LogParameter:
|
|
|
20
20
|
output_type="str",
|
|
21
21
|
allowed_modes={ParameterMode.OUTPUT},
|
|
22
22
|
tooltip="logs",
|
|
23
|
-
ui_options={"multiline": True},
|
|
23
|
+
ui_options={"multiline": True, "placeholder_text": ""},
|
|
24
24
|
)
|
|
25
25
|
)
|
|
26
26
|
|
|
@@ -68,6 +68,10 @@ class StdoutCapture:
|
|
|
68
68
|
def flush(self) -> None:
|
|
69
69
|
self._original_stdout.flush()
|
|
70
70
|
|
|
71
|
+
def isatty(self) -> bool:
|
|
72
|
+
# Return False to prevent libraries from outputting ANSI color codes
|
|
73
|
+
return False
|
|
74
|
+
|
|
71
75
|
def __enter__(self) -> "StdoutCapture":
|
|
72
76
|
sys.stdout = self
|
|
73
77
|
return self
|
|
@@ -235,12 +235,6 @@ class ParameterNumber(Parameter):
|
|
|
235
235
|
validate_min_max: Whether to validate min/max with error
|
|
236
236
|
"""
|
|
237
237
|
# Validation rules
|
|
238
|
-
if min_val is not None and max_val is None:
|
|
239
|
-
msg = f"{name}: If min_val is provided, max_val must also be provided"
|
|
240
|
-
raise ValueError(msg)
|
|
241
|
-
if max_val is not None and min_val is None:
|
|
242
|
-
msg = f"{name}: If max_val is provided, min_val must also be provided"
|
|
243
|
-
raise ValueError(msg)
|
|
244
238
|
if slider and (min_val is None or max_val is None):
|
|
245
239
|
msg = f"{name}: If slider is True, both min_val and max_val must be provided"
|
|
246
240
|
raise ValueError(msg)
|
|
@@ -259,7 +253,7 @@ class ParameterNumber(Parameter):
|
|
|
259
253
|
traits.add(Slider(min_val=min_val, max_val=max_val))
|
|
260
254
|
elif validate_min_max and min_val is not None and max_val is not None:
|
|
261
255
|
traits.add(MinMax(min_val=min_val, max_val=max_val))
|
|
262
|
-
elif min_val is not None
|
|
256
|
+
elif min_val is not None or max_val is not None:
|
|
263
257
|
traits.add(Clamp(min_val=min_val, max_val=max_val))
|
|
264
258
|
|
|
265
259
|
# Store traits for later use
|
|
@@ -304,9 +298,6 @@ class ParameterNumber(Parameter):
|
|
|
304
298
|
@min_val.setter
|
|
305
299
|
def min_val(self, value: float | None) -> None:
|
|
306
300
|
"""Set minimum value and update constraint traits."""
|
|
307
|
-
if value is not None and self.max_val is None:
|
|
308
|
-
msg = f"{self.name}: Cannot set min_val without max_val"
|
|
309
|
-
raise ValueError(msg)
|
|
310
301
|
self._min_val = value
|
|
311
302
|
self._update_constraint_traits()
|
|
312
303
|
|
|
@@ -321,9 +312,6 @@ class ParameterNumber(Parameter):
|
|
|
321
312
|
@max_val.setter
|
|
322
313
|
def max_val(self, value: float | None) -> None:
|
|
323
314
|
"""Set maximum value and update constraint traits."""
|
|
324
|
-
if value is not None and self.min_val is None:
|
|
325
|
-
msg = f"{self.name}: Cannot set max_val without min_val"
|
|
326
|
-
raise ValueError(msg)
|
|
327
315
|
self._max_val = value
|
|
328
316
|
self._update_constraint_traits()
|
|
329
317
|
|
|
@@ -367,17 +355,35 @@ class ParameterNumber(Parameter):
|
|
|
367
355
|
min_val = getattr(self, "_min_val", None)
|
|
368
356
|
max_val = getattr(self, "_max_val", None)
|
|
369
357
|
|
|
370
|
-
if min_val is None
|
|
358
|
+
if min_val is None and max_val is None:
|
|
371
359
|
self._remove_constraint_traits()
|
|
372
360
|
return
|
|
373
361
|
|
|
362
|
+
if self.slider and (min_val is None or max_val is None):
|
|
363
|
+
msg = f"{self.name}: Cannot enable slider without min_val and max_val"
|
|
364
|
+
raise ValueError(msg)
|
|
365
|
+
|
|
366
|
+
if self.validate_min_max and (min_val is None or max_val is None):
|
|
367
|
+
msg = f"{self.name}: Cannot enable validate_min_max without min_val and max_val"
|
|
368
|
+
raise ValueError(msg)
|
|
369
|
+
|
|
374
370
|
# Determine which trait to use based on current state
|
|
375
371
|
if self.slider:
|
|
372
|
+
# Checked above: both min_val and max_val are available when slider is enabled.
|
|
373
|
+
# Type narrowing: assign to variables after None check so type checker understands
|
|
374
|
+
min_val_float: float = min_val # type: ignore[assignment]
|
|
375
|
+
max_val_float: float = max_val # type: ignore[assignment]
|
|
376
|
+
# Python will naturally coerce int to float if needed (no precision loss for reasonable values)
|
|
376
377
|
self._remove_constraint_traits()
|
|
377
|
-
self.add_trait(Slider(min_val=
|
|
378
|
+
self.add_trait(Slider(min_val=min_val_float, max_val=max_val_float))
|
|
378
379
|
elif self.validate_min_max:
|
|
380
|
+
# Checked above: both min_val and max_val are available when validate_min_max is enabled.
|
|
381
|
+
# Type narrowing: assign to variables after None check so type checker understands
|
|
382
|
+
min_val_float: float = min_val # type: ignore[assignment]
|
|
383
|
+
max_val_float: float = max_val # type: ignore[assignment]
|
|
384
|
+
# Python will naturally coerce int to float if needed (no precision loss for reasonable values)
|
|
379
385
|
self._remove_constraint_traits()
|
|
380
|
-
self.add_trait(MinMax(min_val=
|
|
386
|
+
self.add_trait(MinMax(min_val=min_val_float, max_val=max_val_float))
|
|
381
387
|
else:
|
|
382
388
|
self._remove_constraint_traits()
|
|
383
389
|
self.add_trait(Clamp(min_val=min_val, max_val=max_val))
|
|
@@ -564,6 +564,7 @@ class SerializeNodeToCommandsRequest(RequestPayload):
|
|
|
564
564
|
serialized_parameter_value_tracker: SerializedParameterValueTracker = field(
|
|
565
565
|
default_factory=SerializedParameterValueTracker
|
|
566
566
|
)
|
|
567
|
+
use_pickling: bool = False
|
|
567
568
|
|
|
568
569
|
|
|
569
570
|
@dataclass
|
|
@@ -648,7 +649,8 @@ class SerializeSelectedNodesToCommandsResultSuccess(WorkflowNotAlteredMixin, Res
|
|
|
648
649
|
|
|
649
650
|
# They will be passed with node_name, timestamp
|
|
650
651
|
# Could be a flow command if it's all nodes in a flow.
|
|
651
|
-
serialized_selected_node_commands:
|
|
652
|
+
serialized_selected_node_commands: str
|
|
653
|
+
pickled_values: dict[str, str]
|
|
652
654
|
|
|
653
655
|
|
|
654
656
|
@dataclass
|
|
@@ -674,6 +676,8 @@ class DeserializeSelectedNodesFromCommandsRequest(WorkflowNotAlteredMixin, Reque
|
|
|
674
676
|
Results: DeserializeSelectedNodesFromCommandsResultSuccess (with node names) | DeserializeSelectedNodesFromCommandsResultFailure (deserialization error)
|
|
675
677
|
"""
|
|
676
678
|
|
|
679
|
+
deserialize_commands: str
|
|
680
|
+
pickled_values: dict[str, str]
|
|
677
681
|
positions: list[NewPosition] | None = None
|
|
678
682
|
|
|
679
683
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from griptape_nodes.exe_types.flow import ControlFlow
|
|
7
7
|
from griptape_nodes.retained_mode.events.context_events import (
|
|
@@ -18,8 +18,6 @@ if TYPE_CHECKING:
|
|
|
18
18
|
from griptape_nodes.exe_types.core_types import BaseNodeElement
|
|
19
19
|
from griptape_nodes.exe_types.node_types import BaseNode
|
|
20
20
|
from griptape_nodes.retained_mode.events.base_events import ResultPayload
|
|
21
|
-
from griptape_nodes.retained_mode.events.flow_events import SerializedFlowCommands
|
|
22
|
-
from griptape_nodes.retained_mode.events.node_events import SerializedSelectedNodesCommands
|
|
23
21
|
from griptape_nodes.retained_mode.managers.event_manager import EventManager
|
|
24
22
|
|
|
25
23
|
logger = logging.getLogger("griptape_nodes")
|
|
@@ -34,7 +32,6 @@ class ContextManager:
|
|
|
34
32
|
"""
|
|
35
33
|
|
|
36
34
|
_workflow_stack: list[ContextManager.WorkflowContextState]
|
|
37
|
-
_clipboard: ClipBoard
|
|
38
35
|
|
|
39
36
|
class WorkflowContextError(Exception):
|
|
40
37
|
"""Base exception for workflow context errors."""
|
|
@@ -242,32 +239,9 @@ class ContextManager:
|
|
|
242
239
|
) -> None:
|
|
243
240
|
self._manager.pop_element()
|
|
244
241
|
|
|
245
|
-
class ClipBoard:
|
|
246
|
-
"""Keeps Commands for Copying or Pasting."""
|
|
247
|
-
|
|
248
|
-
# Contains flow, node, parameter, connections
|
|
249
|
-
flow_commands: SerializedFlowCommands | None
|
|
250
|
-
# Contains node and Parameter and relevant connections
|
|
251
|
-
node_commands: SerializedSelectedNodesCommands | None
|
|
252
|
-
parameter_uuid_to_values: dict[str, Any] | None
|
|
253
|
-
|
|
254
|
-
def __init__(self) -> None:
|
|
255
|
-
self.flow_commands = None
|
|
256
|
-
self.node_commands = None
|
|
257
|
-
self.parameter_uuid_to_values = None
|
|
258
|
-
|
|
259
|
-
def clear(self) -> None:
|
|
260
|
-
del self.flow_commands
|
|
261
|
-
self.flow_commands = None
|
|
262
|
-
del self.node_commands
|
|
263
|
-
self.node_commands = None
|
|
264
|
-
if self.parameter_uuid_to_values is not None:
|
|
265
|
-
self.parameter_uuid_to_values.clear()
|
|
266
|
-
|
|
267
242
|
def __init__(self, event_manager: EventManager) -> None:
|
|
268
243
|
"""Initialize the context manager with empty workflow and flow stacks."""
|
|
269
244
|
self._workflow_stack = []
|
|
270
|
-
self._clipboard = self.ClipBoard()
|
|
271
245
|
event_manager.assign_manager_to_request_type(
|
|
272
246
|
request_type=SetWorkflowContextRequest, callback=self.on_set_workflow_context_request
|
|
273
247
|
)
|
|
@@ -2781,6 +2781,7 @@ class NodeManager:
|
|
|
2781
2781
|
unique_parameter_uuid_to_values=request.unique_parameter_uuid_to_values,
|
|
2782
2782
|
serialized_parameter_value_tracker=request.serialized_parameter_value_tracker,
|
|
2783
2783
|
create_node_request=create_node_request,
|
|
2784
|
+
use_pickling=request.use_pickling,
|
|
2784
2785
|
)
|
|
2785
2786
|
if set_param_value_requests is not None:
|
|
2786
2787
|
set_value_commands.extend(set_param_value_requests)
|
|
@@ -2983,6 +2984,7 @@ class NodeManager:
|
|
|
2983
2984
|
node_name=node_name,
|
|
2984
2985
|
unique_parameter_uuid_to_values=unique_uuid_to_values,
|
|
2985
2986
|
serialized_parameter_value_tracker=serialized_parameter_value_tracker,
|
|
2987
|
+
use_pickling=True,
|
|
2986
2988
|
)
|
|
2987
2989
|
)
|
|
2988
2990
|
if not isinstance(result, SerializeNodeToCommandsResultSuccess):
|
|
@@ -3029,22 +3031,55 @@ class NodeManager:
|
|
|
3029
3031
|
set_parameter_value_commands=parameter_commands,
|
|
3030
3032
|
set_lock_commands_per_node=lock_commands,
|
|
3031
3033
|
)
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3034
|
+
|
|
3035
|
+
# Encode pickled bytes to latin-1 strings for JSON serialization
|
|
3036
|
+
encoded_values = {}
|
|
3037
|
+
for uuid, value in unique_uuid_to_values.items():
|
|
3038
|
+
if isinstance(value, bytes):
|
|
3039
|
+
# Pickled bytes - encode as latin-1 string for transport
|
|
3040
|
+
encoded_values[uuid] = value.decode("latin1")
|
|
3041
|
+
else:
|
|
3042
|
+
# Non-pickled value - keep as-is (for backward compatibility)
|
|
3043
|
+
encoded_values[uuid] = value
|
|
3044
|
+
|
|
3045
|
+
# Pickle the commands object and encode as latin-1 string for transport
|
|
3046
|
+
pickled_commands_bytes = pickle.dumps(final_result)
|
|
3047
|
+
pickled_commands_string = pickled_commands_bytes.decode("latin1")
|
|
3036
3048
|
return SerializeSelectedNodesToCommandsResultSuccess(
|
|
3037
|
-
|
|
3049
|
+
pickled_commands_string, # Send pickled string instead of object
|
|
3050
|
+
pickled_values=encoded_values,
|
|
3038
3051
|
result_details=f"Successfully serialized {len(request.nodes_to_serialize)} selected nodes to commands.",
|
|
3039
3052
|
)
|
|
3040
3053
|
|
|
3041
|
-
def on_deserialize_selected_nodes_from_commands( # noqa: C901, PLR0912
|
|
3054
|
+
def on_deserialize_selected_nodes_from_commands( # noqa: C901, PLR0912, PLR0915
|
|
3042
3055
|
self,
|
|
3043
3056
|
request: DeserializeSelectedNodesFromCommandsRequest,
|
|
3044
3057
|
) -> ResultPayload:
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3058
|
+
# Decode latin-1 encoded pickled strings back to Python objects
|
|
3059
|
+
decoded_values = {}
|
|
3060
|
+
if request.pickled_values:
|
|
3061
|
+
for uuid, latin1_string in request.pickled_values.items():
|
|
3062
|
+
if isinstance(latin1_string, str):
|
|
3063
|
+
try:
|
|
3064
|
+
# Decode: latin-1 string → bytes → unpickled object
|
|
3065
|
+
pickled_bytes = latin1_string.encode("latin1")
|
|
3066
|
+
decoded_values[uuid] = pickle.loads(pickled_bytes) # noqa: S301 Expecting this from the GUI.
|
|
3067
|
+
except Exception:
|
|
3068
|
+
details = f"Failed to unpickle parameter value for UUID {uuid}"
|
|
3069
|
+
logger.warning(details)
|
|
3070
|
+
# Keep original value if unpickling fails
|
|
3071
|
+
decoded_values[uuid] = latin1_string
|
|
3072
|
+
else:
|
|
3073
|
+
# Not a string, keep as-is
|
|
3074
|
+
decoded_values[uuid] = latin1_string
|
|
3075
|
+
|
|
3076
|
+
# Unpickle the commands string into SerializedSelectedNodesCommands
|
|
3077
|
+
try:
|
|
3078
|
+
pickled_commands_bytes = request.deserialize_commands.encode("latin1")
|
|
3079
|
+
commands = pickle.loads(pickled_commands_bytes) # noqa: S301 Expecting this from the GUI.
|
|
3080
|
+
except Exception as e:
|
|
3081
|
+
details = f"Failed to unpickle commands: {e}"
|
|
3082
|
+
return DeserializeSelectedNodesFromCommandsResultFailure(result_details=details)
|
|
3048
3083
|
connections = commands.serialized_connection_commands
|
|
3049
3084
|
node_uuid_to_name = {}
|
|
3050
3085
|
# Enumerate because positions is in the same order as the node commands.
|
|
@@ -3078,10 +3113,9 @@ class NodeManager:
|
|
|
3078
3113
|
param_request = parameter_command.set_parameter_value_command
|
|
3079
3114
|
# Set the Node name
|
|
3080
3115
|
param_request.node_name = result.node_name
|
|
3081
|
-
# Set the new value
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
value = table[parameter_command.unique_value_uuid]
|
|
3116
|
+
# Set the new value from decoded_values
|
|
3117
|
+
if decoded_values and parameter_command.unique_value_uuid in decoded_values:
|
|
3118
|
+
value = decoded_values[parameter_command.unique_value_uuid]
|
|
3085
3119
|
# Using try-except-pass instead of contextlib.suppress because it's clearer.
|
|
3086
3120
|
try: # noqa: SIM105
|
|
3087
3121
|
# If we're pasting multiple times - we need to create a new copy for each paste so they don't all have the same reference.
|
|
@@ -3119,13 +3153,20 @@ class NodeManager:
|
|
|
3119
3153
|
)
|
|
3120
3154
|
|
|
3121
3155
|
def on_duplicate_selected_nodes(self, request: DuplicateSelectedNodesRequest) -> ResultPayload:
|
|
3122
|
-
|
|
3156
|
+
serialize_result = GriptapeNodes.handle_request(
|
|
3123
3157
|
SerializeSelectedNodesToCommandsRequest(nodes_to_serialize=request.nodes_to_duplicate)
|
|
3124
3158
|
)
|
|
3125
|
-
if
|
|
3159
|
+
if not isinstance(serialize_result, SerializeSelectedNodesToCommandsResultSuccess):
|
|
3126
3160
|
details = "Failed to serialized selected nodes."
|
|
3127
3161
|
return DuplicateSelectedNodesResultFailure(result_details=details)
|
|
3128
|
-
|
|
3162
|
+
|
|
3163
|
+
# Pass the pickled commands and values to deserialization
|
|
3164
|
+
deserialize_request = DeserializeSelectedNodesFromCommandsRequest(
|
|
3165
|
+
deserialize_commands=serialize_result.serialized_selected_node_commands,
|
|
3166
|
+
pickled_values=serialize_result.pickled_values,
|
|
3167
|
+
positions=request.positions,
|
|
3168
|
+
)
|
|
3169
|
+
result = GriptapeNodes.handle_request(deserialize_request)
|
|
3129
3170
|
if not isinstance(result, DeserializeSelectedNodesFromCommandsResultSuccess):
|
|
3130
3171
|
details = "Failed to deserialize selected nodes."
|
|
3131
3172
|
return DuplicateSelectedNodesResultFailure(result_details=details)
|
|
@@ -3177,6 +3218,7 @@ class NodeManager:
|
|
|
3177
3218
|
node_name: str,
|
|
3178
3219
|
*,
|
|
3179
3220
|
is_output: bool,
|
|
3221
|
+
use_pickling: bool = False,
|
|
3180
3222
|
) -> SerializedNodeCommands.IndirectSetParameterValueCommand | None:
|
|
3181
3223
|
try:
|
|
3182
3224
|
hash(value)
|
|
@@ -3211,12 +3253,20 @@ class NodeManager:
|
|
|
3211
3253
|
return None
|
|
3212
3254
|
# The value should be serialized. Add it to the map of uniques.
|
|
3213
3255
|
unique_uuid = SerializedNodeCommands.UniqueParameterValueUUID(str(uuid4()))
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
unique_parameter_uuid_to_values[unique_uuid] =
|
|
3256
|
+
|
|
3257
|
+
if use_pickling:
|
|
3258
|
+
# Use pickle serialization via WorkflowManager
|
|
3259
|
+
workflow_manager = GriptapeNodes.WorkflowManager()
|
|
3260
|
+
pickled_bytes = workflow_manager._patch_and_pickle_object(value)
|
|
3261
|
+
unique_parameter_uuid_to_values[unique_uuid] = pickled_bytes
|
|
3262
|
+
else:
|
|
3263
|
+
# Use existing deep copy approach
|
|
3264
|
+
try:
|
|
3265
|
+
unique_parameter_uuid_to_values[unique_uuid] = copy.deepcopy(value)
|
|
3266
|
+
except Exception:
|
|
3267
|
+
details = f"Attempted to serialize parameter '{parameter_name}` on node '{node_name}'. The parameter value could not be copied. It will be serialized by value. If problems arise from this, ensure the type '{type(value)}' works with copy.deepcopy()."
|
|
3268
|
+
logger.warning(details)
|
|
3269
|
+
unique_parameter_uuid_to_values[unique_uuid] = value
|
|
3220
3270
|
serialized_parameter_value_tracker.add_as_serializable(value_id, unique_uuid)
|
|
3221
3271
|
|
|
3222
3272
|
# Serialize it
|
|
@@ -3233,12 +3283,14 @@ class NodeManager:
|
|
|
3233
3283
|
return indirect_set_value_command
|
|
3234
3284
|
|
|
3235
3285
|
@staticmethod
|
|
3236
|
-
def handle_parameter_value_saving(
|
|
3286
|
+
def handle_parameter_value_saving( # noqa: PLR0913
|
|
3237
3287
|
parameter: Parameter,
|
|
3238
3288
|
node: BaseNode,
|
|
3239
3289
|
unique_parameter_uuid_to_values: dict[SerializedNodeCommands.UniqueParameterValueUUID, Any],
|
|
3240
3290
|
serialized_parameter_value_tracker: SerializedParameterValueTracker,
|
|
3241
3291
|
create_node_request: CreateNodeRequest,
|
|
3292
|
+
*,
|
|
3293
|
+
use_pickling: bool = False,
|
|
3242
3294
|
) -> list[SerializedNodeCommands.IndirectSetParameterValueCommand] | None:
|
|
3243
3295
|
"""Generates code to save a parameter value for a node in a Griptape workflow.
|
|
3244
3296
|
|
|
@@ -3256,6 +3308,7 @@ class NodeManager:
|
|
|
3256
3308
|
unique_parameter_uuid_to_values (dict[SerializedNodeCommands.UniqueParameterValueUUID, Any]): Dictionary mapping unique value UUIDs to values
|
|
3257
3309
|
serialized_parameter_value_tracker (SerializedParameterValueTracker): Object mapping maintaining value hashes to unique value UUIDs, and non-serializable values
|
|
3258
3310
|
create_node_request (CreateNodeRequest): The node creation request that will be modified if serialization fails
|
|
3311
|
+
use_pickling (bool): If True, use pickle-based serialization; if False, use deep copy
|
|
3259
3312
|
|
|
3260
3313
|
Returns:
|
|
3261
3314
|
None (if no value to be serialized) or an IndirectSetParameterValueCommand linking the value to the unique value map
|
|
@@ -3292,6 +3345,7 @@ class NodeManager:
|
|
|
3292
3345
|
is_output=False,
|
|
3293
3346
|
parameter_name=parameter.name,
|
|
3294
3347
|
node_name=node.name,
|
|
3348
|
+
use_pickling=use_pickling,
|
|
3295
3349
|
)
|
|
3296
3350
|
if internal_command is None:
|
|
3297
3351
|
details = f"Attempted to serialize set value for parameter '{parameter.name}' on node '{node.name}'. The set value will not be restored in anything that attempts to deserialize or save this node. The value for this parameter was not serialized because it did not match Griptape Nodes' criteria for serializability. To remedy, either update the value's type to support serializability or mark the parameter as not serializable by setting serializable=False when creating the parameter."
|
|
@@ -3310,6 +3364,7 @@ class NodeManager:
|
|
|
3310
3364
|
is_output=True,
|
|
3311
3365
|
parameter_name=parameter.name,
|
|
3312
3366
|
node_name=node.name,
|
|
3367
|
+
use_pickling=use_pickling,
|
|
3313
3368
|
)
|
|
3314
3369
|
if output_command is None:
|
|
3315
3370
|
details = f"Attempted to serialize output value for parameter '{parameter.name}' on node '{node.name}'. The output value will not be restored in anything that attempts to deserialize or save this node. The value for this parameter was not serialized because it did not match Griptape Nodes' criteria for serializability. To remedy, either update the value's type to support serializability or mark the parameter as not serializable by setting serializable=False when creating the parameter."
|
griptape_nodes/traits/clamp.py
CHANGED
|
@@ -11,7 +11,7 @@ class Clamp(Trait):
|
|
|
11
11
|
max: Any = 10
|
|
12
12
|
element_id: str = field(default_factory=lambda: "ClampTrait")
|
|
13
13
|
|
|
14
|
-
def __init__(self, min_val: float, max_val: float) -> None:
|
|
14
|
+
def __init__(self, min_val: float | None = None, max_val: float | None = None) -> None:
|
|
15
15
|
super().__init__()
|
|
16
16
|
self.min = min_val
|
|
17
17
|
self.max = max_val
|
|
@@ -20,17 +20,60 @@ class Clamp(Trait):
|
|
|
20
20
|
def get_trait_keys(cls) -> list[str]:
|
|
21
21
|
return ["clamp"]
|
|
22
22
|
|
|
23
|
+
def _clamp_number(self, value: float) -> float:
|
|
24
|
+
# Keep this as a tiny helper so the converter stays readable and so we can
|
|
25
|
+
# consistently apply one-sided bounds (min-only or max-only) everywhere.
|
|
26
|
+
if self.max is not None and value > self.max:
|
|
27
|
+
value = self.max
|
|
28
|
+
if self.min is not None and value < self.min:
|
|
29
|
+
value = self.min
|
|
30
|
+
return value
|
|
31
|
+
|
|
32
|
+
def _clamp_sequence(self, value: list[Any]) -> list[Any]:
|
|
33
|
+
# Clamp historically applied to strings/lists by max length; we keep list handling
|
|
34
|
+
# explicit here so bounds semantics remain obvious.
|
|
35
|
+
if self.max is None:
|
|
36
|
+
return value
|
|
37
|
+
if len(value) <= self.max:
|
|
38
|
+
return value
|
|
39
|
+
return value[: self.max]
|
|
40
|
+
|
|
41
|
+
def _try_parse_numeric_string(self, value: str) -> float | None:
|
|
42
|
+
# Trait converters run BEFORE parameter-level converters (e.g. ParameterInt/Float
|
|
43
|
+
# parsing). That means UI inputs often arrive as strings here; to make min/max
|
|
44
|
+
# clamping actually work with typical UI inputs, we parse numeric strings when
|
|
45
|
+
# bounds are configured.
|
|
46
|
+
if self.min is None and self.max is None:
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
stripped = value.strip()
|
|
50
|
+
if not stripped:
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
return float(stripped)
|
|
55
|
+
except ValueError:
|
|
56
|
+
return None
|
|
57
|
+
|
|
23
58
|
def converters_for_trait(self) -> list[Callable]:
|
|
24
59
|
def clamp(value: Any) -> Any:
|
|
25
|
-
if isinstance(value,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
60
|
+
if isinstance(value, list):
|
|
61
|
+
return self._clamp_sequence(value)
|
|
62
|
+
|
|
63
|
+
if isinstance(value, str):
|
|
64
|
+
parsed = self._try_parse_numeric_string(value)
|
|
65
|
+
if parsed is not None:
|
|
66
|
+
return self._clamp_number(parsed)
|
|
67
|
+
|
|
68
|
+
# If it's not a numeric string (or no bounds configured), preserve the
|
|
69
|
+
# historical string behavior: max length clamping only.
|
|
70
|
+
if self.max is None or len(value) <= self.max:
|
|
71
|
+
return value
|
|
72
|
+
return value[: self.max]
|
|
73
|
+
|
|
29
74
|
if isinstance(value, (int, float)):
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if value < self.min:
|
|
33
|
-
return self.min
|
|
75
|
+
return self._clamp_number(float(value))
|
|
76
|
+
|
|
34
77
|
return value
|
|
35
78
|
|
|
36
79
|
return [clamp]
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
griptape_nodes/__init__.py,sha256=WxWjICLxwuyZGDpPUyCmj047GbN7PIspi4YMWgmrrQc,671
|
|
2
2
|
griptape_nodes/__main__.py,sha256=fJhor6_1A27abwbnceyNheONP1iXkPzjjsV5jBEfF2M,144
|
|
3
3
|
griptape_nodes/api_client/__init__.py,sha256=9iyLcPbcXjxxLhhCSYQ5zgvlwxceyrNXDE8YhOIVH8g,216
|
|
4
|
-
griptape_nodes/api_client/client.py,sha256=
|
|
4
|
+
griptape_nodes/api_client/client.py,sha256=fNTs-xJL8deRWceGKBGOCeKwMt6Rd0vi-jCxniZk79E,9870
|
|
5
5
|
griptape_nodes/api_client/request_client.py,sha256=Z5lJVoG2a9hudTAQTnniaCHbBko0X1FyoakiQMimq7g,9713
|
|
6
6
|
griptape_nodes/app/.python-version,sha256=e1X45ntWI8S-8_ppEojalDfXnTq6FW3kjUgdsyrH0W0,5
|
|
7
7
|
griptape_nodes/app/__init__.py,sha256=DB-DTsgcNnbmEClXEouwzGhrmo3gHBCWXB9BkPGpdQI,90
|
|
8
|
-
griptape_nodes/app/app.py,sha256=
|
|
8
|
+
griptape_nodes/app/app.py,sha256=bbaRe1khQNRZ1fziDdeokkR-M3K7tvKDpCl4eVm-R4g,18014
|
|
9
9
|
griptape_nodes/app/watch.py,sha256=hKVP_SuV9C17bH1h9o4uIVTKH-IL_-0iyHaNYmILTWU,1594
|
|
10
10
|
griptape_nodes/bootstrap/__init__.py,sha256=ENv3SIzQ9TtlRrg1y4e4CnoBpJaFpFSkNpTFBV8X5Ls,25
|
|
11
11
|
griptape_nodes/bootstrap/utils/__init__.py,sha256=tlNEApJLZazcBNhxkTdup4URwznnz4nZxjSaRfFrTBM,31
|
|
@@ -77,14 +77,14 @@ griptape_nodes/exe_types/param_components/__init__.py,sha256=ocm75WnsgiD6ozKVGFh
|
|
|
77
77
|
griptape_nodes/exe_types/param_components/api_key_provider_parameter.py,sha256=MHn5zYb2vEf4bGBfbnTjCfVYEbpZtXThb8JJAAMpuR8,7766
|
|
78
78
|
griptape_nodes/exe_types/param_components/artifact_url/__init__.py,sha256=LKAGdP8VBSOTx8iq8kEvxZVDgMIS5TXSLntZqBEJ7yk,40
|
|
79
79
|
griptape_nodes/exe_types/param_components/artifact_url/public_artifact_url_parameter.py,sha256=2A4Jn7Xgi6KPM087wnVhoH3k5GnqxLFt3MV56SwYIYI,6610
|
|
80
|
-
griptape_nodes/exe_types/param_components/execution_status_component.py,sha256=
|
|
80
|
+
griptape_nodes/exe_types/param_components/execution_status_component.py,sha256=OBKTNW9q3-Ges6hxH--dyh1qbwU2O8WnwTNVRU_wW8s,6863
|
|
81
81
|
griptape_nodes/exe_types/param_components/huggingface/__init__.py,sha256=YeVFck-9C341Bt7TiWEvPdD63o9qkaNu2KjmzT9CQOI,39
|
|
82
82
|
griptape_nodes/exe_types/param_components/huggingface/huggingface_model_parameter.py,sha256=rEGN4kvblSAlRh7pD73U__wzAtVzDYWYlDC-k1nKtyM,6395
|
|
83
83
|
griptape_nodes/exe_types/param_components/huggingface/huggingface_repo_file_parameter.py,sha256=c61de3mbkc5FvVkf5vubtD0XfThDInTfibAtYhZKcKA,4265
|
|
84
84
|
griptape_nodes/exe_types/param_components/huggingface/huggingface_repo_parameter.py,sha256=zcBRQP0eZJloSdPQwJFw89B6QDHECnrosRZUy8mE2fM,1401
|
|
85
85
|
griptape_nodes/exe_types/param_components/huggingface/huggingface_repo_variant_parameter.py,sha256=FaaDZ4dvZJCnpqSOKfJ5nR1klgl07JZto2A7gxhUi3o,5290
|
|
86
86
|
griptape_nodes/exe_types/param_components/huggingface/huggingface_utils.py,sha256=cE0Ht81kDcZjlN_2VoRirCA4zMlrG9GFlcptn-gC2tU,4696
|
|
87
|
-
griptape_nodes/exe_types/param_components/log_parameter.py,sha256=
|
|
87
|
+
griptape_nodes/exe_types/param_components/log_parameter.py,sha256=_v6NH1lz9FrEKf2uMIOlwxzKTy5Vl3EAZai54lAMF1g,4313
|
|
88
88
|
griptape_nodes/exe_types/param_components/progress_bar_component.py,sha256=GrAFTOrLNAx6q9zfOqiioPTG_NLHKhTe9NiZOo6zGSc,1949
|
|
89
89
|
griptape_nodes/exe_types/param_components/seed_parameter.py,sha256=I48cVAojrD5oX4CT7v0x9LX6MrKVklywkp8IjE5pGIo,2321
|
|
90
90
|
griptape_nodes/exe_types/param_types/__init__.py,sha256=xEEmKvIFF6M7zVjQZCupbbv6SZKt-itD-rPtfRhxJVg,53
|
|
@@ -96,7 +96,7 @@ griptape_nodes/exe_types/param_types/parameter_float.py,sha256=9msvMnmzYGNpqFpGy
|
|
|
96
96
|
griptape_nodes/exe_types/param_types/parameter_image.py,sha256=FeoqQdr1dj0F60WK0pVyNyzYsZCDjt4JiZQn252Oz3I,9433
|
|
97
97
|
griptape_nodes/exe_types/param_types/parameter_int.py,sha256=06h1QpWaWLeP2tlRRW5IOGO-t_ZlxsWqnezlgoyBKaE,6942
|
|
98
98
|
griptape_nodes/exe_types/param_types/parameter_json.py,sha256=M5A0_XhTKZ8qVBd1db55UA23H3nmaqryaITeN2-GwB0,9961
|
|
99
|
-
griptape_nodes/exe_types/param_types/parameter_number.py,sha256=
|
|
99
|
+
griptape_nodes/exe_types/param_types/parameter_number.py,sha256=GuQ6jbs8LQByl4UUBhgY_INdCWeNM7qOlDMYC-SZsK8,16012
|
|
100
100
|
griptape_nodes/exe_types/param_types/parameter_range.py,sha256=fkCBN0X09fAfTG9AhKQ3Nxkit_8NrFi4IGQPpmOQR8k,14689
|
|
101
101
|
griptape_nodes/exe_types/param_types/parameter_string.py,sha256=-Q_9FwPtCXzpbv1C5FixLEET0c9WLJ228168IaSlZEU,9583
|
|
102
102
|
griptape_nodes/exe_types/param_types/parameter_three_d.py,sha256=wbUeWJUVPJW5JJrkckzGnTM6SsWPSQNupyHGVoBjrOA,8393
|
|
@@ -130,7 +130,7 @@ griptape_nodes/retained_mode/events/library_events.py,sha256=4NUc3uoLgofo1X9nrCV
|
|
|
130
130
|
griptape_nodes/retained_mode/events/logger_events.py,sha256=jYlxzPomgCsJuPtJ0znWBhD8QJfC8qC4xfChDiuVuyg,705
|
|
131
131
|
griptape_nodes/retained_mode/events/mcp_events.py,sha256=fs83jAQamhwNC9Zt8UNkBKd6iTids8531V_RMnGj__o,11008
|
|
132
132
|
griptape_nodes/retained_mode/events/model_events.py,sha256=jXm-v-_Uxysn4MJ7a80_uIphrxTHgua3BGgHGyy3T_Y,9232
|
|
133
|
-
griptape_nodes/retained_mode/events/node_events.py,sha256=
|
|
133
|
+
griptape_nodes/retained_mode/events/node_events.py,sha256=9yTdTrFNd5JATvHk5x3ucznMou3ZzYxgpCgNjAF-GuU,38760
|
|
134
134
|
griptape_nodes/retained_mode/events/object_events.py,sha256=cJaqEU73Lzf1RRxJrFqEpl8eTr-gDhKpXKywJ-vVCJQ,2631
|
|
135
135
|
griptape_nodes/retained_mode/events/os_events.py,sha256=fVraPXCz48kDpCTttJFtsyfTfkaLSfTX57hexYSD7I8,23429
|
|
136
136
|
griptape_nodes/retained_mode/events/parameter_events.py,sha256=TazVXxvfv64n3XJzToOQKiWQ1UIzrUAB4ri_QIvZ2ng,26968
|
|
@@ -148,7 +148,7 @@ griptape_nodes/retained_mode/managers/__init__.py,sha256=OTXysKusqYCQeAYwnVj4PbE
|
|
|
148
148
|
griptape_nodes/retained_mode/managers/agent_manager.py,sha256=FOKrcHEBw6M-RmfWTWEQmV-9iy9cD1zHiiDUDMqJHE4,28307
|
|
149
149
|
griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py,sha256=LyWzHQKmyDh-2zh2PIahdYyAthf_rMYs4zvhtVo-LsU,3423
|
|
150
150
|
griptape_nodes/retained_mode/managers/config_manager.py,sha256=74AMeaCS0eOeFbzMk5I54MtB7-SNQbwlx_-O6zBBQRo,26739
|
|
151
|
-
griptape_nodes/retained_mode/managers/context_manager.py,sha256=
|
|
151
|
+
griptape_nodes/retained_mode/managers/context_manager.py,sha256=n-r6-Zzyq3-9QBAyIZO7w7YC7PGBuIouFLH44ef06E8,21956
|
|
152
152
|
griptape_nodes/retained_mode/managers/engine_identity_manager.py,sha256=-31364A03kU0YmAx3nM7nHdWfKnkej5Cawt_Plbwa68,10526
|
|
153
153
|
griptape_nodes/retained_mode/managers/event_manager.py,sha256=jiUX3WW6Hz0Z4Y1dK1X7fMwZawT3_BOKl_Dbiui-iNQ,26933
|
|
154
154
|
griptape_nodes/retained_mode/managers/fitness_problems/__init__.py,sha256=H_Wwfn1k_IaxwRxgbw3-seb1HWbcxl2Cvhw7wB7bCo8,75
|
|
@@ -205,8 +205,8 @@ griptape_nodes/retained_mode/managers/flow_manager.py,sha256=BKWLpc-udlZ4n1rlKIN
|
|
|
205
205
|
griptape_nodes/retained_mode/managers/library_manager.py,sha256=paogGavZj2MDOYvfUklhjORQg16YdpVGBxBncVSxtR0,192265
|
|
206
206
|
griptape_nodes/retained_mode/managers/mcp_manager.py,sha256=AEHG1SqFc3g5hOImOHaH7ZjOkmgNAavmQgG9osXVGkE,16018
|
|
207
207
|
griptape_nodes/retained_mode/managers/model_manager.py,sha256=3lj2X8vIvDSERPtR2VEXNFEWy_D8H6muxRvD-PEx8U8,44845
|
|
208
|
-
griptape_nodes/retained_mode/managers/node_manager.py,sha256=
|
|
209
|
-
griptape_nodes/retained_mode/managers/object_manager.py,sha256=
|
|
208
|
+
griptape_nodes/retained_mode/managers/node_manager.py,sha256=BG0-z2-pDjzgS5VC3u3p7-jGUJ5nGSGSShbSv9WseoA,229244
|
|
209
|
+
griptape_nodes/retained_mode/managers/object_manager.py,sha256=ZpovmhnBKG_JCn4Pde9idlx2eBZjKvR7k9DHUYqD-r4,12882
|
|
210
210
|
griptape_nodes/retained_mode/managers/operation_manager.py,sha256=4Vn_79vHrawy3wJVUx52tfblO4mURww58nb5RtCTpKU,20190
|
|
211
211
|
griptape_nodes/retained_mode/managers/os_manager.py,sha256=Ttgj6R063p2Yf1lcdeSTB2xOTg94MIDCMPxO8FDczEQ,142397
|
|
212
212
|
griptape_nodes/retained_mode/managers/project_manager.py,sha256=-K-anrxEVKInFMPLY-cV3ipqEh8hMELGHKbecJJJVa8,49035
|
|
@@ -239,7 +239,7 @@ griptape_nodes/servers/static.py,sha256=R0nnMUCRDE0BxygZ-kdxhROAXgJPsIJBAEp7H_sJ
|
|
|
239
239
|
griptape_nodes/traits/__init__.py,sha256=bTLXTiZTJz2z15RRLoPI4nvLnNW9FiLcKL_2pT4E10g,32
|
|
240
240
|
griptape_nodes/traits/add_param_button.py,sha256=27RZDVLMD0HmRF6hjfz7iV7LBau92vMc_d2eD2Ey8fA,649
|
|
241
241
|
griptape_nodes/traits/button.py,sha256=Nweq5oGdPpSTfyX3Dr2mjgBYwLUrokxtergnOCTiPpU,15962
|
|
242
|
-
griptape_nodes/traits/clamp.py,sha256=
|
|
242
|
+
griptape_nodes/traits/clamp.py,sha256=hBteNZ4CF4k-5zkWDJnnkWQxOnB0G9_BEa9YwWEgdII,2780
|
|
243
243
|
griptape_nodes/traits/color_picker.py,sha256=ySKaoZw319yfuTSEtkVT2vSR6Goy9pBm4rusjx95F0c,3024
|
|
244
244
|
griptape_nodes/traits/compare.py,sha256=X-BXGemRDxQV4EX8X24LdtcwMWwfQ1jGqDvH2bSiSuc,521
|
|
245
245
|
griptape_nodes/traits/compare_images.py,sha256=KW0WlwsJP6nBoC1irdeRnUWUnZIJvlROlDhyWhX8iEs,1594
|
|
@@ -276,7 +276,7 @@ griptape_nodes/version_compatibility/versions/v0_65_5/__init__.py,sha256=4UyspOV
|
|
|
276
276
|
griptape_nodes/version_compatibility/versions/v0_65_5/flux_2_removed_parameters.py,sha256=jOlmY5kKHXh8HPzAUtvwMJqzD4bP7pkE--yHUb7jTRA,3305
|
|
277
277
|
griptape_nodes/version_compatibility/versions/v0_7_0/__init__.py,sha256=IzPPmGK86h2swfGGTOHyVcBIlOng6SjgWQzlbf3ngmo,51
|
|
278
278
|
griptape_nodes/version_compatibility/versions/v0_7_0/local_executor_argument_addition.py,sha256=Thx8acnbw5OychhwEEj9aFxvbPe7Wgn4V9ZmZ7KRZqc,2082
|
|
279
|
-
griptape_nodes-0.
|
|
280
|
-
griptape_nodes-0.
|
|
281
|
-
griptape_nodes-0.
|
|
282
|
-
griptape_nodes-0.
|
|
279
|
+
griptape_nodes-0.70.1.dist-info/WHEEL,sha256=e_m4S054HL0hyR3CpOk-b7Q7fDX6BuFkgL5OjAExXas,80
|
|
280
|
+
griptape_nodes-0.70.1.dist-info/entry_points.txt,sha256=qvevqd3BVbAV5TcantnAm0ouqaqYKhsRO3pkFymWLWM,82
|
|
281
|
+
griptape_nodes-0.70.1.dist-info/METADATA,sha256=VBszlO8g-vdr1HhL7NWUBo6_AF9Q5qh0rThNdfxtA1g,5373
|
|
282
|
+
griptape_nodes-0.70.1.dist-info/RECORD,,
|
|
File without changes
|