griptape-nodes 0.42.0__py3-none-any.whl → 0.43.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 +0 -0
- griptape_nodes/app/.python-version +0 -0
- griptape_nodes/app/__init__.py +1 -6
- griptape_nodes/app/api.py +199 -0
- griptape_nodes/app/app.py +140 -225
- griptape_nodes/app/watch.py +1 -1
- griptape_nodes/bootstrap/__init__.py +0 -0
- griptape_nodes/bootstrap/bootstrap_script.py +0 -0
- griptape_nodes/bootstrap/register_libraries_script.py +0 -0
- griptape_nodes/bootstrap/structure_config.yaml +0 -0
- griptape_nodes/bootstrap/workflow_executors/__init__.py +0 -0
- griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +0 -0
- griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +0 -0
- griptape_nodes/bootstrap/workflow_runners/__init__.py +0 -0
- griptape_nodes/bootstrap/workflow_runners/bootstrap_workflow_runner.py +0 -0
- griptape_nodes/bootstrap/workflow_runners/local_workflow_runner.py +0 -0
- griptape_nodes/bootstrap/workflow_runners/subprocess_workflow_runner.py +6 -2
- griptape_nodes/bootstrap/workflow_runners/workflow_runner.py +0 -0
- griptape_nodes/drivers/__init__.py +0 -0
- griptape_nodes/drivers/storage/__init__.py +0 -0
- griptape_nodes/drivers/storage/base_storage_driver.py +0 -0
- griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +0 -0
- griptape_nodes/drivers/storage/local_storage_driver.py +2 -1
- griptape_nodes/drivers/storage/storage_backend.py +0 -0
- griptape_nodes/exe_types/__init__.py +0 -0
- griptape_nodes/exe_types/connections.py +0 -0
- griptape_nodes/exe_types/core_types.py +0 -0
- griptape_nodes/exe_types/flow.py +0 -0
- griptape_nodes/exe_types/node_types.py +17 -1
- griptape_nodes/exe_types/type_validator.py +0 -0
- griptape_nodes/machines/__init__.py +0 -0
- griptape_nodes/machines/control_flow.py +41 -12
- griptape_nodes/machines/fsm.py +16 -2
- griptape_nodes/machines/node_resolution.py +0 -0
- griptape_nodes/mcp_server/__init__.py +1 -0
- griptape_nodes/mcp_server/server.py +126 -0
- griptape_nodes/mcp_server/ws_request_manager.py +268 -0
- griptape_nodes/node_library/__init__.py +0 -0
- griptape_nodes/node_library/advanced_node_library.py +0 -0
- griptape_nodes/node_library/library_registry.py +0 -0
- griptape_nodes/node_library/workflow_registry.py +1 -1
- griptape_nodes/py.typed +0 -0
- griptape_nodes/retained_mode/__init__.py +0 -0
- griptape_nodes/retained_mode/events/__init__.py +0 -0
- griptape_nodes/retained_mode/events/agent_events.py +0 -0
- griptape_nodes/retained_mode/events/app_events.py +6 -2
- griptape_nodes/retained_mode/events/arbitrary_python_events.py +0 -0
- griptape_nodes/retained_mode/events/base_events.py +6 -6
- griptape_nodes/retained_mode/events/config_events.py +0 -0
- griptape_nodes/retained_mode/events/connection_events.py +0 -0
- griptape_nodes/retained_mode/events/context_events.py +0 -0
- griptape_nodes/retained_mode/events/execution_events.py +0 -0
- griptape_nodes/retained_mode/events/flow_events.py +0 -0
- griptape_nodes/retained_mode/events/generate_request_payload_schemas.py +0 -0
- griptape_nodes/retained_mode/events/library_events.py +2 -2
- griptape_nodes/retained_mode/events/logger_events.py +0 -0
- griptape_nodes/retained_mode/events/node_events.py +0 -0
- griptape_nodes/retained_mode/events/object_events.py +0 -0
- griptape_nodes/retained_mode/events/os_events.py +104 -2
- griptape_nodes/retained_mode/events/parameter_events.py +0 -0
- griptape_nodes/retained_mode/events/payload_registry.py +0 -0
- griptape_nodes/retained_mode/events/secrets_events.py +0 -0
- griptape_nodes/retained_mode/events/static_file_events.py +0 -0
- griptape_nodes/retained_mode/events/validation_events.py +0 -0
- griptape_nodes/retained_mode/events/workflow_events.py +0 -0
- griptape_nodes/retained_mode/griptape_nodes.py +43 -40
- griptape_nodes/retained_mode/managers/__init__.py +0 -0
- griptape_nodes/retained_mode/managers/agent_manager.py +48 -22
- griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +0 -0
- griptape_nodes/retained_mode/managers/config_manager.py +0 -0
- griptape_nodes/retained_mode/managers/context_manager.py +0 -0
- griptape_nodes/retained_mode/managers/engine_identity_manager.py +0 -0
- griptape_nodes/retained_mode/managers/event_manager.py +0 -0
- griptape_nodes/retained_mode/managers/flow_manager.py +2 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/__init__.py +45 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/data_models.py +191 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +346 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +439 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/__init__.py +17 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +82 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +116 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +352 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +104 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +155 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py +18 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py +12 -0
- griptape_nodes/retained_mode/managers/library_manager.py +144 -39
- griptape_nodes/retained_mode/managers/node_manager.py +86 -72
- griptape_nodes/retained_mode/managers/object_manager.py +0 -0
- griptape_nodes/retained_mode/managers/operation_manager.py +0 -0
- griptape_nodes/retained_mode/managers/os_manager.py +517 -12
- griptape_nodes/retained_mode/managers/secrets_manager.py +0 -0
- griptape_nodes/retained_mode/managers/session_manager.py +0 -0
- griptape_nodes/retained_mode/managers/settings.py +0 -0
- griptape_nodes/retained_mode/managers/static_files_manager.py +0 -0
- griptape_nodes/retained_mode/managers/version_compatibility_manager.py +2 -2
- griptape_nodes/retained_mode/managers/workflow_manager.py +199 -2
- griptape_nodes/retained_mode/retained_mode.py +0 -0
- griptape_nodes/retained_mode/utils/__init__.py +0 -0
- griptape_nodes/retained_mode/utils/engine_identity.py +0 -0
- griptape_nodes/retained_mode/utils/name_generator.py +0 -0
- griptape_nodes/traits/__init__.py +0 -0
- griptape_nodes/traits/add_param_button.py +0 -0
- griptape_nodes/traits/button.py +0 -0
- griptape_nodes/traits/clamp.py +0 -0
- griptape_nodes/traits/compare.py +0 -0
- griptape_nodes/traits/compare_images.py +0 -0
- griptape_nodes/traits/file_system_picker.py +127 -0
- griptape_nodes/traits/minmax.py +0 -0
- griptape_nodes/traits/options.py +0 -0
- griptape_nodes/traits/slider.py +0 -0
- griptape_nodes/traits/trait_registry.py +0 -0
- griptape_nodes/traits/traits.json +0 -0
- griptape_nodes/updater/__init__.py +2 -2
- griptape_nodes/updater/__main__.py +0 -0
- griptape_nodes/utils/__init__.py +0 -0
- griptape_nodes/utils/dict_utils.py +0 -0
- griptape_nodes/utils/image_preview.py +128 -0
- griptape_nodes/utils/metaclasses.py +0 -0
- griptape_nodes/version_compatibility/__init__.py +0 -0
- griptape_nodes/version_compatibility/versions/__init__.py +0 -0
- griptape_nodes/version_compatibility/versions/v0_39_0/__init__.py +0 -0
- griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +5 -5
- griptape_nodes-0.43.0.dist-info/METADATA +90 -0
- griptape_nodes-0.43.0.dist-info/RECORD +129 -0
- griptape_nodes-0.43.0.dist-info/WHEEL +4 -0
- {griptape_nodes-0.42.0.dist-info → griptape_nodes-0.43.0.dist-info}/entry_points.txt +1 -0
- griptape_nodes/app/app_sessions.py +0 -554
- griptape_nodes-0.42.0.dist-info/METADATA +0 -78
- griptape_nodes-0.42.0.dist-info/RECORD +0 -113
- griptape_nodes-0.42.0.dist-info/WHEEL +0 -4
- griptape_nodes-0.42.0.dist-info/licenses/LICENSE +0 -201
|
@@ -1332,6 +1332,9 @@ class WorkflowManager:
|
|
|
1332
1332
|
right=ast.Constant(value=None),
|
|
1333
1333
|
)
|
|
1334
1334
|
|
|
1335
|
+
# Generate the ensure flow context function call
|
|
1336
|
+
ensure_context_call = self._generate_ensure_flow_context_call()
|
|
1337
|
+
|
|
1335
1338
|
# Create conditional logic: workflow_executor = workflow_executor or LocalWorkflowExecutor()
|
|
1336
1339
|
executor_assign = ast.Assign(
|
|
1337
1340
|
targets=[ast.Name(id="workflow_executor", ctx=ast.Store())],
|
|
@@ -1373,7 +1376,7 @@ class WorkflowManager:
|
|
|
1373
1376
|
func_def = ast.FunctionDef(
|
|
1374
1377
|
name="execute_workflow",
|
|
1375
1378
|
args=args,
|
|
1376
|
-
body=[executor_assign, run_call, return_stmt],
|
|
1379
|
+
body=[ensure_context_call, executor_assign, run_call, return_stmt],
|
|
1377
1380
|
decorator_list=[],
|
|
1378
1381
|
returns=return_annotation,
|
|
1379
1382
|
type_params=[],
|
|
@@ -1592,7 +1595,201 @@ class WorkflowManager:
|
|
|
1592
1595
|
)
|
|
1593
1596
|
ast.fix_missing_locations(if_node)
|
|
1594
1597
|
|
|
1595
|
-
|
|
1598
|
+
# Generate the ensure flow context function
|
|
1599
|
+
ensure_context_func = self._generate_ensure_flow_context_function(import_recorder)
|
|
1600
|
+
|
|
1601
|
+
return [ensure_context_func, func_def, if_node]
|
|
1602
|
+
|
|
1603
|
+
def _generate_ensure_flow_context_function(
|
|
1604
|
+
self,
|
|
1605
|
+
import_recorder: ImportRecorder,
|
|
1606
|
+
) -> ast.FunctionDef:
|
|
1607
|
+
"""Generates the _ensure_workflow_context function for the serialized workflow file."""
|
|
1608
|
+
import_recorder.add_from_import("griptape_nodes.retained_mode.events.flow_events", "GetTopLevelFlowRequest")
|
|
1609
|
+
import_recorder.add_from_import(
|
|
1610
|
+
"griptape_nodes.retained_mode.events.flow_events", "GetTopLevelFlowResultSuccess"
|
|
1611
|
+
)
|
|
1612
|
+
|
|
1613
|
+
# Function signature: def _ensure_workflow_context():
|
|
1614
|
+
func_def = ast.FunctionDef(
|
|
1615
|
+
name="_ensure_workflow_context",
|
|
1616
|
+
args=ast.arguments(
|
|
1617
|
+
posonlyargs=[],
|
|
1618
|
+
args=[],
|
|
1619
|
+
vararg=None,
|
|
1620
|
+
kwonlyargs=[],
|
|
1621
|
+
kw_defaults=[],
|
|
1622
|
+
kwarg=None,
|
|
1623
|
+
defaults=[],
|
|
1624
|
+
),
|
|
1625
|
+
body=[],
|
|
1626
|
+
decorator_list=[],
|
|
1627
|
+
returns=None,
|
|
1628
|
+
type_params=[],
|
|
1629
|
+
)
|
|
1630
|
+
|
|
1631
|
+
context_manager_assign = ast.Assign(
|
|
1632
|
+
targets=[ast.Name(id="context_manager", ctx=ast.Store())],
|
|
1633
|
+
value=ast.Call(
|
|
1634
|
+
func=ast.Attribute(
|
|
1635
|
+
value=ast.Name(id="GriptapeNodes", ctx=ast.Load()),
|
|
1636
|
+
attr="ContextManager",
|
|
1637
|
+
ctx=ast.Load(),
|
|
1638
|
+
),
|
|
1639
|
+
args=[],
|
|
1640
|
+
keywords=[],
|
|
1641
|
+
),
|
|
1642
|
+
)
|
|
1643
|
+
|
|
1644
|
+
# if not context_manager.has_current_flow():
|
|
1645
|
+
has_flow_check = ast.UnaryOp(
|
|
1646
|
+
op=ast.Not(),
|
|
1647
|
+
operand=ast.Call(
|
|
1648
|
+
func=ast.Attribute(
|
|
1649
|
+
value=ast.Name(id="context_manager", ctx=ast.Load()),
|
|
1650
|
+
attr="has_current_flow",
|
|
1651
|
+
ctx=ast.Load(),
|
|
1652
|
+
),
|
|
1653
|
+
args=[],
|
|
1654
|
+
keywords=[],
|
|
1655
|
+
),
|
|
1656
|
+
)
|
|
1657
|
+
|
|
1658
|
+
# top_level_flow_request = GetTopLevelFlowRequest() # noqa: ERA001
|
|
1659
|
+
flow_request_assign = ast.Assign(
|
|
1660
|
+
targets=[ast.Name(id="top_level_flow_request", ctx=ast.Store())],
|
|
1661
|
+
value=ast.Call(
|
|
1662
|
+
func=ast.Name(id="GetTopLevelFlowRequest", ctx=ast.Load()),
|
|
1663
|
+
args=[],
|
|
1664
|
+
keywords=[],
|
|
1665
|
+
),
|
|
1666
|
+
)
|
|
1667
|
+
|
|
1668
|
+
# top_level_flow_result = GriptapeNodes.handle_request(top_level_flow_request) # noqa: ERA001
|
|
1669
|
+
flow_result_assign = ast.Assign(
|
|
1670
|
+
targets=[ast.Name(id="top_level_flow_result", ctx=ast.Store())],
|
|
1671
|
+
value=ast.Call(
|
|
1672
|
+
func=ast.Attribute(
|
|
1673
|
+
value=ast.Name(id="GriptapeNodes", ctx=ast.Load()),
|
|
1674
|
+
attr="handle_request",
|
|
1675
|
+
ctx=ast.Load(),
|
|
1676
|
+
),
|
|
1677
|
+
args=[ast.Name(id="top_level_flow_request", ctx=ast.Load())],
|
|
1678
|
+
keywords=[],
|
|
1679
|
+
),
|
|
1680
|
+
)
|
|
1681
|
+
|
|
1682
|
+
# isinstance check and flow_name is not None
|
|
1683
|
+
isinstance_check = ast.Call(
|
|
1684
|
+
func=ast.Name(id="isinstance", ctx=ast.Load()),
|
|
1685
|
+
args=[
|
|
1686
|
+
ast.Name(id="top_level_flow_result", ctx=ast.Load()),
|
|
1687
|
+
ast.Name(id="GetTopLevelFlowResultSuccess", ctx=ast.Load()),
|
|
1688
|
+
],
|
|
1689
|
+
keywords=[],
|
|
1690
|
+
)
|
|
1691
|
+
|
|
1692
|
+
flow_name_check = ast.Compare(
|
|
1693
|
+
left=ast.Attribute(
|
|
1694
|
+
value=ast.Name(id="top_level_flow_result", ctx=ast.Load()),
|
|
1695
|
+
attr="flow_name",
|
|
1696
|
+
ctx=ast.Load(),
|
|
1697
|
+
),
|
|
1698
|
+
ops=[ast.IsNot()],
|
|
1699
|
+
comparators=[ast.Constant(value=None)],
|
|
1700
|
+
)
|
|
1701
|
+
|
|
1702
|
+
success_condition = ast.BoolOp(
|
|
1703
|
+
op=ast.And(),
|
|
1704
|
+
values=[isinstance_check, flow_name_check],
|
|
1705
|
+
)
|
|
1706
|
+
|
|
1707
|
+
# flow_manager = GriptapeNodes.FlowManager() # noqa: ERA001
|
|
1708
|
+
flow_manager_assign = ast.Assign(
|
|
1709
|
+
targets=[ast.Name(id="flow_manager", ctx=ast.Store())],
|
|
1710
|
+
value=ast.Call(
|
|
1711
|
+
func=ast.Attribute(
|
|
1712
|
+
value=ast.Name(id="GriptapeNodes", ctx=ast.Load()),
|
|
1713
|
+
attr="FlowManager",
|
|
1714
|
+
ctx=ast.Load(),
|
|
1715
|
+
),
|
|
1716
|
+
args=[],
|
|
1717
|
+
keywords=[],
|
|
1718
|
+
),
|
|
1719
|
+
)
|
|
1720
|
+
|
|
1721
|
+
# flow_obj = flow_manager.get_flow_by_name(top_level_flow_result.flow_name) # noqa: ERA001
|
|
1722
|
+
flow_obj_assign = ast.Assign(
|
|
1723
|
+
targets=[ast.Name(id="flow_obj", ctx=ast.Store())],
|
|
1724
|
+
value=ast.Call(
|
|
1725
|
+
func=ast.Attribute(
|
|
1726
|
+
value=ast.Name(id="flow_manager", ctx=ast.Load()),
|
|
1727
|
+
attr="get_flow_by_name",
|
|
1728
|
+
ctx=ast.Load(),
|
|
1729
|
+
),
|
|
1730
|
+
args=[
|
|
1731
|
+
ast.Attribute(
|
|
1732
|
+
value=ast.Name(id="top_level_flow_result", ctx=ast.Load()),
|
|
1733
|
+
attr="flow_name",
|
|
1734
|
+
ctx=ast.Load(),
|
|
1735
|
+
)
|
|
1736
|
+
],
|
|
1737
|
+
keywords=[],
|
|
1738
|
+
),
|
|
1739
|
+
)
|
|
1740
|
+
|
|
1741
|
+
# context_manager.push_flow(flow_obj) # noqa: ERA001
|
|
1742
|
+
push_flow_call = ast.Expr(
|
|
1743
|
+
value=ast.Call(
|
|
1744
|
+
func=ast.Attribute(
|
|
1745
|
+
value=ast.Name(id="context_manager", ctx=ast.Load()),
|
|
1746
|
+
attr="push_flow",
|
|
1747
|
+
ctx=ast.Load(),
|
|
1748
|
+
),
|
|
1749
|
+
args=[ast.Name(id="flow_obj", ctx=ast.Load())],
|
|
1750
|
+
keywords=[],
|
|
1751
|
+
),
|
|
1752
|
+
)
|
|
1753
|
+
|
|
1754
|
+
# Build the inner if statement for success condition
|
|
1755
|
+
success_if = ast.If(
|
|
1756
|
+
test=success_condition,
|
|
1757
|
+
body=[
|
|
1758
|
+
flow_manager_assign,
|
|
1759
|
+
flow_obj_assign,
|
|
1760
|
+
push_flow_call,
|
|
1761
|
+
],
|
|
1762
|
+
orelse=[],
|
|
1763
|
+
)
|
|
1764
|
+
|
|
1765
|
+
# Build the main if statement
|
|
1766
|
+
main_if = ast.If(
|
|
1767
|
+
test=has_flow_check,
|
|
1768
|
+
body=[
|
|
1769
|
+
flow_request_assign,
|
|
1770
|
+
flow_result_assign,
|
|
1771
|
+
success_if,
|
|
1772
|
+
],
|
|
1773
|
+
orelse=[],
|
|
1774
|
+
)
|
|
1775
|
+
|
|
1776
|
+
# Set the function body
|
|
1777
|
+
func_def.body = [context_manager_assign, main_if]
|
|
1778
|
+
ast.fix_missing_locations(func_def)
|
|
1779
|
+
|
|
1780
|
+
return func_def
|
|
1781
|
+
|
|
1782
|
+
def _generate_ensure_flow_context_call(
|
|
1783
|
+
self,
|
|
1784
|
+
) -> ast.Expr:
|
|
1785
|
+
"""Generates the call to _ensure_workflow_context() function."""
|
|
1786
|
+
return ast.Expr(
|
|
1787
|
+
value=ast.Call(
|
|
1788
|
+
func=ast.Name(id="_ensure_workflow_context", ctx=ast.Load()),
|
|
1789
|
+
args=[],
|
|
1790
|
+
keywords=[],
|
|
1791
|
+
)
|
|
1792
|
+
)
|
|
1596
1793
|
|
|
1597
1794
|
def _generate_workflow_run_prerequisite_code(
|
|
1598
1795
|
self,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
griptape_nodes/traits/button.py
CHANGED
|
File without changes
|
griptape_nodes/traits/clamp.py
CHANGED
|
File without changes
|
griptape_nodes/traits/compare.py
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from griptape_nodes.exe_types.core_types import Parameter, Trait
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(eq=False)
|
|
9
|
+
class FileSystemPicker(Trait):
|
|
10
|
+
allow_files: bool = False
|
|
11
|
+
allow_directories: bool = True
|
|
12
|
+
multiple: bool = False
|
|
13
|
+
file_types: list[str] = field(default_factory=list)
|
|
14
|
+
file_extensions: list[str] = field(default_factory=list)
|
|
15
|
+
exclude_patterns: list[str] = field(default_factory=list)
|
|
16
|
+
include_patterns: list[str] = field(default_factory=list)
|
|
17
|
+
max_file_size: int | None = None
|
|
18
|
+
min_file_size: int | None = None
|
|
19
|
+
workspace_only: bool = True
|
|
20
|
+
initial_path: str | None = None
|
|
21
|
+
element_id: str = field(default_factory=lambda: "FileSystemPicker")
|
|
22
|
+
|
|
23
|
+
def __init__( # noqa: PLR0913
|
|
24
|
+
self,
|
|
25
|
+
*,
|
|
26
|
+
allow_files: bool = False,
|
|
27
|
+
allow_directories: bool = True,
|
|
28
|
+
multiple: bool = False,
|
|
29
|
+
file_types: list[str] | None = None,
|
|
30
|
+
file_extensions: list[str] | None = None,
|
|
31
|
+
exclude_patterns: list[str] | None = None,
|
|
32
|
+
include_patterns: list[str] | None = None,
|
|
33
|
+
max_file_size: int | None = None,
|
|
34
|
+
min_file_size: int | None = None,
|
|
35
|
+
workspace_only: bool = True,
|
|
36
|
+
initial_path: str | None = None,
|
|
37
|
+
) -> None:
|
|
38
|
+
super().__init__()
|
|
39
|
+
self.allow_files = allow_files
|
|
40
|
+
self.allow_directories = allow_directories
|
|
41
|
+
self.multiple = multiple
|
|
42
|
+
self.file_types = file_types or []
|
|
43
|
+
self.file_extensions = file_extensions or []
|
|
44
|
+
self.exclude_patterns = exclude_patterns or []
|
|
45
|
+
self.include_patterns = include_patterns or []
|
|
46
|
+
self.max_file_size = max_file_size
|
|
47
|
+
self.min_file_size = min_file_size
|
|
48
|
+
self.workspace_only = workspace_only
|
|
49
|
+
self.initial_path = initial_path
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def get_trait_keys(cls) -> list[str]:
|
|
53
|
+
return ["fileSystemPicker", "file_picker", "folder_picker"]
|
|
54
|
+
|
|
55
|
+
def ui_options_for_trait(self) -> dict[str, Any]:
|
|
56
|
+
"""Generate the fileSystemPicker UI options dictionary."""
|
|
57
|
+
options: dict[str, Any] = {
|
|
58
|
+
"allowFiles": self.allow_files,
|
|
59
|
+
"allowDirectories": self.allow_directories,
|
|
60
|
+
"multiple": self.multiple,
|
|
61
|
+
"workspaceOnly": self.workspace_only,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Add file types/extensions
|
|
65
|
+
if self.file_types:
|
|
66
|
+
options["fileTypes"] = self.file_types
|
|
67
|
+
elif self.file_extensions:
|
|
68
|
+
options["fileExtensions"] = self.file_extensions
|
|
69
|
+
|
|
70
|
+
# Add patterns
|
|
71
|
+
if self.exclude_patterns:
|
|
72
|
+
options["excludePatterns"] = self.exclude_patterns
|
|
73
|
+
if self.include_patterns:
|
|
74
|
+
options["includePatterns"] = self.include_patterns
|
|
75
|
+
|
|
76
|
+
# Add size limits
|
|
77
|
+
if self.max_file_size is not None:
|
|
78
|
+
options["maxFileSize"] = self.max_file_size
|
|
79
|
+
if self.min_file_size is not None:
|
|
80
|
+
options["minFileSize"] = self.min_file_size
|
|
81
|
+
|
|
82
|
+
# Add initial path
|
|
83
|
+
if self.initial_path:
|
|
84
|
+
options["initialPath"] = self.initial_path
|
|
85
|
+
|
|
86
|
+
return {"fileSystemPicker": options}
|
|
87
|
+
|
|
88
|
+
def validators_for_trait(self) -> list[Callable[[Parameter, Any], Any]]:
|
|
89
|
+
"""Validate file system picker configuration."""
|
|
90
|
+
|
|
91
|
+
def validate(param: Parameter, value: Any) -> None: # noqa: ARG001
|
|
92
|
+
# Validate that at least one selection type is enabled
|
|
93
|
+
if not self.allow_files and not self.allow_directories:
|
|
94
|
+
msg = "At least one of allow_files or allow_directories must be True"
|
|
95
|
+
raise ValueError(msg)
|
|
96
|
+
|
|
97
|
+
# Validate file size limits
|
|
98
|
+
if (
|
|
99
|
+
self.max_file_size is not None
|
|
100
|
+
and self.min_file_size is not None
|
|
101
|
+
and self.max_file_size < self.min_file_size
|
|
102
|
+
):
|
|
103
|
+
msg = "max_file_size cannot be less than min_file_size"
|
|
104
|
+
raise ValueError(msg)
|
|
105
|
+
|
|
106
|
+
# Validate that file types/extensions are valid
|
|
107
|
+
all_file_types = self.file_types + self.file_extensions
|
|
108
|
+
for file_type in all_file_types:
|
|
109
|
+
if not file_type.startswith("."):
|
|
110
|
+
msg = f"File type '{file_type}' must start with a dot (e.g., '.py')"
|
|
111
|
+
raise ValueError(msg)
|
|
112
|
+
|
|
113
|
+
return [validate]
|
|
114
|
+
|
|
115
|
+
def converters_for_trait(self) -> list[Callable]:
|
|
116
|
+
"""Convert file system picker values if needed."""
|
|
117
|
+
|
|
118
|
+
def converter(value: Any) -> Any:
|
|
119
|
+
# If value is a string and we expect a list, convert it
|
|
120
|
+
if isinstance(value, str) and self.multiple:
|
|
121
|
+
return [value] if value else []
|
|
122
|
+
return value
|
|
123
|
+
|
|
124
|
+
return [converter]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# These Traits get added to a list on the parameter. When they are added they apply their functions to the parameter.
|
griptape_nodes/traits/minmax.py
CHANGED
|
File without changes
|
griptape_nodes/traits/options.py
CHANGED
|
File without changes
|
griptape_nodes/traits/slider.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -38,7 +38,7 @@ def _download_and_run_installer() -> None:
|
|
|
38
38
|
"""Runs the update commands for the engine."""
|
|
39
39
|
console.print("[bold green]Updating self...[/bold green]")
|
|
40
40
|
try:
|
|
41
|
-
subprocess.run(
|
|
41
|
+
subprocess.run(
|
|
42
42
|
["uv", "tool", "upgrade", "griptape-nodes"], # noqa: S607
|
|
43
43
|
text=True,
|
|
44
44
|
capture_output=True,
|
|
@@ -57,7 +57,7 @@ def _sync_libraries() -> None:
|
|
|
57
57
|
"""Syncs the libraries for the engine."""
|
|
58
58
|
console.print("[bold green]Syncing libraries...[/bold green]")
|
|
59
59
|
try:
|
|
60
|
-
subprocess.run(
|
|
60
|
+
subprocess.run(
|
|
61
61
|
["griptape-nodes", "libraries", "sync"], # noqa: S607
|
|
62
62
|
text=True,
|
|
63
63
|
capture_output=True,
|
|
File without changes
|
griptape_nodes/utils/__init__.py
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Image preview utilities for generating thumbnails and previews."""
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import io
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from PIL import Image
|
|
8
|
+
|
|
9
|
+
from griptape_nodes.retained_mode.griptape_nodes import logger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_image_preview(
|
|
13
|
+
image_path: Path, max_width: int = 512, max_height: int = 512, quality: int = 85, image_format: str = "WEBP"
|
|
14
|
+
) -> str | None:
|
|
15
|
+
"""Create a small preview image from a file path.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
image_path: Path to the image file
|
|
19
|
+
max_width: Maximum width for the preview
|
|
20
|
+
max_height: Maximum height for the preview
|
|
21
|
+
quality: WebP quality (1-100)
|
|
22
|
+
image_format: Output format (WEBP, JPEG, PNG, etc.)
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Base64 encoded data URL of the preview, or None if failed
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
# Open and resize the image
|
|
29
|
+
with Image.open(image_path) as img:
|
|
30
|
+
# Convert to RGB if necessary (for WebP/JPEG output)
|
|
31
|
+
if image_format.upper() in ("WEBP", "JPEG") and img.mode in ("RGBA", "LA", "P"):
|
|
32
|
+
converted_img = img.convert("RGB")
|
|
33
|
+
else:
|
|
34
|
+
converted_img = img
|
|
35
|
+
|
|
36
|
+
# Calculate new size maintaining aspect ratio
|
|
37
|
+
converted_img.thumbnail((max_width, max_height), Image.Resampling.LANCZOS)
|
|
38
|
+
|
|
39
|
+
# Save to bytes buffer
|
|
40
|
+
buffer = io.BytesIO()
|
|
41
|
+
converted_img.save(buffer, format=image_format, quality=quality, optimize=True)
|
|
42
|
+
buffer.seek(0)
|
|
43
|
+
|
|
44
|
+
# Convert to base64
|
|
45
|
+
image_bytes = buffer.getvalue()
|
|
46
|
+
base64_data = base64.b64encode(image_bytes).decode("utf-8")
|
|
47
|
+
|
|
48
|
+
# Create data URL
|
|
49
|
+
mime_type = f"image/{image_format.lower()}"
|
|
50
|
+
data_url = f"data:{mime_type};base64,{base64_data}"
|
|
51
|
+
|
|
52
|
+
logger.debug(f"Created preview for {image_path}: {img.size} -> {len(image_bytes)} bytes")
|
|
53
|
+
return data_url
|
|
54
|
+
|
|
55
|
+
except Exception as e:
|
|
56
|
+
logger.warning(f"Failed to create preview for {image_path}: {e}")
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def create_image_preview_from_bytes(
|
|
61
|
+
image_bytes: bytes, max_width: int = 512, max_height: int = 512, quality: int = 85, image_format: str = "WEBP"
|
|
62
|
+
) -> str | None:
|
|
63
|
+
"""Create a small preview image from bytes.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
image_bytes: Raw image bytes
|
|
67
|
+
max_width: Maximum width for the preview
|
|
68
|
+
max_height: Maximum height for the preview
|
|
69
|
+
quality: WebP quality (1-100)
|
|
70
|
+
image_format: Output format (WEBP, JPEG, PNG, etc.)
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Base64 encoded data URL of the preview, or None if failed
|
|
74
|
+
"""
|
|
75
|
+
try:
|
|
76
|
+
# Open image from bytes
|
|
77
|
+
with Image.open(io.BytesIO(image_bytes)) as img:
|
|
78
|
+
# Convert to RGB if necessary (for WebP/JPEG output)
|
|
79
|
+
if image_format.upper() in ("WEBP", "JPEG") and img.mode in ("RGBA", "LA", "P"):
|
|
80
|
+
converted_img = img.convert("RGB")
|
|
81
|
+
else:
|
|
82
|
+
converted_img = img
|
|
83
|
+
|
|
84
|
+
# Calculate new size maintaining aspect ratio
|
|
85
|
+
converted_img.thumbnail((max_width, max_height), Image.Resampling.LANCZOS)
|
|
86
|
+
|
|
87
|
+
# Save to bytes buffer
|
|
88
|
+
buffer = io.BytesIO()
|
|
89
|
+
converted_img.save(buffer, format=image_format, quality=quality, optimize=True)
|
|
90
|
+
buffer.seek(0)
|
|
91
|
+
|
|
92
|
+
# Convert to base64
|
|
93
|
+
preview_bytes = buffer.getvalue()
|
|
94
|
+
base64_data = base64.b64encode(preview_bytes).decode("utf-8")
|
|
95
|
+
|
|
96
|
+
# Create data URL
|
|
97
|
+
mime_type = f"image/{image_format.lower()}"
|
|
98
|
+
data_url = f"data:{mime_type};base64,{base64_data}"
|
|
99
|
+
|
|
100
|
+
logger.debug(f"Created preview from bytes: {len(image_bytes)} -> {len(preview_bytes)} bytes")
|
|
101
|
+
return data_url
|
|
102
|
+
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.warning(f"Failed to create preview from bytes: {e}")
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_image_info(image_path: Path) -> dict | None:
|
|
109
|
+
"""Get basic information about an image file.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
image_path: Path to the image file
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Dictionary with image info (width, height, format, mode), or None if failed
|
|
116
|
+
"""
|
|
117
|
+
try:
|
|
118
|
+
with Image.open(image_path) as img:
|
|
119
|
+
return {
|
|
120
|
+
"width": img.width,
|
|
121
|
+
"height": img.height,
|
|
122
|
+
"format": img.format,
|
|
123
|
+
"mode": img.mode,
|
|
124
|
+
"size_bytes": image_path.stat().st_size,
|
|
125
|
+
}
|
|
126
|
+
except Exception as e:
|
|
127
|
+
logger.warning(f"Failed to get image info for {image_path}: {e}")
|
|
128
|
+
return None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -7,7 +7,7 @@ from griptape_nodes.retained_mode.events.app_events import (
|
|
|
7
7
|
GetEngineVersionResultSuccess,
|
|
8
8
|
)
|
|
9
9
|
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes, Version
|
|
10
|
-
from griptape_nodes.retained_mode.managers.
|
|
10
|
+
from griptape_nodes.retained_mode.managers.library_lifecycle.library_status import LibraryStatus
|
|
11
11
|
from griptape_nodes.retained_mode.managers.version_compatibility_manager import (
|
|
12
12
|
LibraryVersionCompatibilityCheck,
|
|
13
13
|
LibraryVersionCompatibilityIssue,
|
|
@@ -47,13 +47,13 @@ class ModifiedParametersSetRemovalCheck(LibraryVersionCompatibilityCheck):
|
|
|
47
47
|
message=f"This library (built for engine version {library_version_str}) is incompatible with Griptape Nodes 0.39+. "
|
|
48
48
|
"The 'modified_parameters_set' parameter has been removed from BaseNode methods: 'after_incoming_connection', 'after_outgoing_connection', 'after_incoming_connection_removed', 'after_outgoing_connection_removed', 'before_value_set', and 'after_value_set'. "
|
|
49
49
|
"If this library overrides any of these methods, it will not load or function properly. Please update to a newer version of this library or contact the library author immediately.",
|
|
50
|
-
severity=
|
|
50
|
+
severity=LibraryStatus.UNUSABLE,
|
|
51
51
|
),
|
|
52
52
|
LibraryVersionCompatibilityIssue(
|
|
53
53
|
message=f"This library (built for engine version {library_version_str}) is incompatible with Griptape Nodes 0.39+."
|
|
54
54
|
"The 'ui_options' field has been modified on all Elements. In order to function properly, all nodes must update ui_options by setting its value to a new dictionary. Updating ui_options by accessing the private field _ui_options will no longer create UI updates in the editor."
|
|
55
55
|
"If this library accesses the private _ui_options field, it will not update the editor properly. Please update to a newer version of this library or contact the library author immediately.",
|
|
56
|
-
severity=
|
|
56
|
+
severity=LibraryStatus.UNUSABLE,
|
|
57
57
|
),
|
|
58
58
|
]
|
|
59
59
|
if current_engine_version >= Version(0, 38, 0):
|
|
@@ -63,13 +63,13 @@ class ModifiedParametersSetRemovalCheck(LibraryVersionCompatibilityCheck):
|
|
|
63
63
|
message=f"WARNING: The 'modified_parameters_set' parameter will be removed in Griptape Nodes 0.39 from BaseNode methods: 'after_incoming_connection', 'after_outgoing_connection', 'after_incoming_connection_removed', 'after_outgoing_connection_removed', 'before_value_set', and 'after_value_set'. "
|
|
64
64
|
f"This library (built for engine version {library_version_str}) must be updated before the 0.39 release. "
|
|
65
65
|
"If this library overrides any of these methods, it will fail to load in 0.39. If not, no action is necessary. Please contact the library author to confirm whether this library is impacted.",
|
|
66
|
-
severity=
|
|
66
|
+
severity=LibraryStatus.FLAWED,
|
|
67
67
|
),
|
|
68
68
|
LibraryVersionCompatibilityIssue(
|
|
69
69
|
message="WARNING: The 'ui_options' field has been modified in Griptape Nodes 0.38 on all BaseNodeElements."
|
|
70
70
|
"In order to function properly, all nodes must update ui_options by setting its value to a new dictionary. Updating ui_options by accessing the private field _ui_options will no longer create UI updates in the editor."
|
|
71
71
|
"If this library accesses the private _ui_options field, it will not update the editor properly. Please update to a newer version of this library or contact the library author immediately.",
|
|
72
|
-
severity=
|
|
72
|
+
severity=LibraryStatus.FLAWED,
|
|
73
73
|
),
|
|
74
74
|
]
|
|
75
75
|
|