griptape-nodes 0.59.3__py3-none-any.whl → 0.60.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. griptape_nodes/common/macro_parser/__init__.py +28 -0
  2. griptape_nodes/common/macro_parser/core.py +230 -0
  3. griptape_nodes/common/macro_parser/exceptions.py +23 -0
  4. griptape_nodes/common/macro_parser/formats.py +170 -0
  5. griptape_nodes/common/macro_parser/matching.py +134 -0
  6. griptape_nodes/common/macro_parser/parsing.py +172 -0
  7. griptape_nodes/common/macro_parser/resolution.py +168 -0
  8. griptape_nodes/common/macro_parser/segments.py +42 -0
  9. griptape_nodes/exe_types/core_types.py +241 -4
  10. griptape_nodes/exe_types/node_types.py +7 -1
  11. griptape_nodes/exe_types/param_components/huggingface/__init__.py +1 -0
  12. griptape_nodes/exe_types/param_components/huggingface/huggingface_model_parameter.py +168 -0
  13. griptape_nodes/exe_types/param_components/huggingface/huggingface_repo_file_parameter.py +38 -0
  14. griptape_nodes/exe_types/param_components/huggingface/huggingface_repo_parameter.py +33 -0
  15. griptape_nodes/exe_types/param_components/huggingface/huggingface_utils.py +136 -0
  16. griptape_nodes/exe_types/param_components/log_parameter.py +136 -0
  17. griptape_nodes/exe_types/param_components/seed_parameter.py +59 -0
  18. griptape_nodes/exe_types/param_types/__init__.py +1 -0
  19. griptape_nodes/exe_types/param_types/parameter_bool.py +221 -0
  20. griptape_nodes/exe_types/param_types/parameter_float.py +179 -0
  21. griptape_nodes/exe_types/param_types/parameter_int.py +183 -0
  22. griptape_nodes/exe_types/param_types/parameter_number.py +380 -0
  23. griptape_nodes/exe_types/param_types/parameter_string.py +232 -0
  24. griptape_nodes/node_library/library_registry.py +2 -1
  25. griptape_nodes/retained_mode/events/app_events.py +21 -0
  26. griptape_nodes/retained_mode/events/os_events.py +142 -6
  27. griptape_nodes/retained_mode/events/parameter_events.py +2 -0
  28. griptape_nodes/retained_mode/griptape_nodes.py +14 -0
  29. griptape_nodes/retained_mode/managers/agent_manager.py +5 -3
  30. griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +19 -1
  31. griptape_nodes/retained_mode/managers/library_manager.py +8 -1
  32. griptape_nodes/retained_mode/managers/node_manager.py +14 -1
  33. griptape_nodes/retained_mode/managers/os_manager.py +403 -124
  34. griptape_nodes/retained_mode/managers/user_manager.py +120 -0
  35. griptape_nodes/retained_mode/managers/workflow_manager.py +44 -34
  36. griptape_nodes/traits/multi_options.py +26 -2
  37. griptape_nodes/utils/huggingface_utils.py +136 -0
  38. {griptape_nodes-0.59.3.dist-info → griptape_nodes-0.60.0.dist-info}/METADATA +1 -1
  39. {griptape_nodes-0.59.3.dist-info → griptape_nodes-0.60.0.dist-info}/RECORD +41 -18
  40. {griptape_nodes-0.59.3.dist-info → griptape_nodes-0.60.0.dist-info}/WHEEL +1 -1
  41. {griptape_nodes-0.59.3.dist-info → griptape_nodes-0.60.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,120 @@
1
+ """Manages user information from Griptape Cloud.
2
+
3
+ Handles fetching and caching user information (email, organization) from the Griptape Cloud API
4
+ to display in the engine and editor.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import logging
10
+ import os
11
+ from functools import cached_property
12
+ from typing import TYPE_CHECKING
13
+
14
+ import httpx
15
+
16
+ from griptape_nodes.retained_mode.events.app_events import OrganizationInfo, UserInfo
17
+
18
+ if TYPE_CHECKING:
19
+ from griptape_nodes.retained_mode.managers.secrets_manager import SecretsManager
20
+
21
+ logger = logging.getLogger("griptape_nodes")
22
+
23
+
24
+ class UserManager:
25
+ """Manages user information from Griptape Cloud."""
26
+
27
+ def __init__(self, secrets_manager: SecretsManager) -> None:
28
+ """Initialize the UserManager.
29
+
30
+ Args:
31
+ secrets_manager: The SecretsManager instance to use for API key retrieval.
32
+ """
33
+ self._secrets_manager = secrets_manager
34
+
35
+ @cached_property
36
+ def user(self) -> UserInfo | None:
37
+ """Get the user's information from Griptape Cloud.
38
+
39
+ This property is cached after the first access.
40
+
41
+ Returns:
42
+ UserInfo | None: The user information or None if not available/not logged in.
43
+ """
44
+ try:
45
+ api_key = self._secrets_manager.get_secret("GT_CLOUD_API_KEY")
46
+ if not api_key:
47
+ logger.debug("No GT_CLOUD_API_KEY found, skipping user fetch")
48
+ return None
49
+
50
+ base_url = os.environ.get("GT_CLOUD_BASE_URL", "https://cloud.griptape.ai")
51
+ url = f"{base_url}/api/users"
52
+ headers = {"Authorization": f"Bearer {api_key}"}
53
+
54
+ response = httpx.get(url, headers=headers, timeout=5.0)
55
+ response.raise_for_status()
56
+
57
+ data = response.json()
58
+ users = data.get("users", [])
59
+ if users and len(users) > 0:
60
+ user = users[0]
61
+ user_id = user.get("user_id")
62
+ email = user.get("email")
63
+ name = user.get("name")
64
+ if user_id and email:
65
+ logger.debug("Fetched user: %s (ID: %s)", email, user_id)
66
+ return UserInfo(id=user_id, email=email, name=name)
67
+
68
+ logger.debug("No users found in API response")
69
+
70
+ except httpx.HTTPStatusError as e:
71
+ logger.warning("Failed to fetch user (HTTP %s): %s", e.response.status_code, e)
72
+ except httpx.RequestError as e:
73
+ logger.warning("Failed to fetch user (request error): %s", e)
74
+ except Exception as e:
75
+ logger.warning("Failed to fetch user (unexpected error): %s", e)
76
+
77
+ return None
78
+
79
+ @cached_property
80
+ def user_organization(self) -> OrganizationInfo | None:
81
+ """Get the user's organization information from Griptape Cloud.
82
+
83
+ This property is cached after the first access.
84
+
85
+ Returns:
86
+ OrganizationInfo | None: The organization information or None if not available/not logged in.
87
+ """
88
+ try:
89
+ api_key = self._secrets_manager.get_secret("GT_CLOUD_API_KEY")
90
+ if not api_key:
91
+ logger.debug("No GT_CLOUD_API_KEY found, skipping user organization fetch")
92
+ return None
93
+
94
+ base_url = os.environ.get("GT_CLOUD_BASE_URL", "https://cloud.griptape.ai")
95
+ url = f"{base_url}/api/organizations"
96
+ headers = {"Authorization": f"Bearer {api_key}"}
97
+
98
+ response = httpx.get(url, headers=headers, timeout=5.0)
99
+ response.raise_for_status()
100
+
101
+ data = response.json()
102
+ organizations = data.get("organizations", [])
103
+ if organizations and len(organizations) > 0:
104
+ org = organizations[0]
105
+ org_id = org.get("organization_id")
106
+ org_name = org.get("name")
107
+ if org_id and org_name:
108
+ logger.debug("Fetched user organization: %s (ID: %s)", org_name, org_id)
109
+ return OrganizationInfo(id=org_id, name=org_name)
110
+
111
+ logger.debug("No organizations found in API response")
112
+
113
+ except httpx.HTTPStatusError as e:
114
+ logger.warning("Failed to fetch user organization (HTTP %s): %s", e.response.status_code, e)
115
+ except httpx.RequestError as e:
116
+ logger.warning("Failed to fetch user organization (request error): %s", e)
117
+ except Exception as e:
118
+ logger.warning("Failed to fetch user organization (unexpected error): %s", e)
119
+
120
+ return None
@@ -262,6 +262,7 @@ class WorkflowManager:
262
262
  self._workflow_file_path_to_info = {}
263
263
  self._squelch_workflow_altered_count = 0
264
264
  self._referenced_workflow_stack = []
265
+ self._workflows_loading_complete = asyncio.Event()
265
266
 
266
267
  event_manager.assign_manager_to_request_type(
267
268
  RunWorkflowFromScratchRequest, self.on_run_workflow_from_scratch_request
@@ -352,39 +353,44 @@ class WorkflowManager:
352
353
  def on_libraries_initialization_complete(self) -> None:
353
354
  # All of the libraries have loaded, and any workflows they came with have been registered.
354
355
  # Discover workflows from both config and workspace.
355
- default_workflow_section = "app_events.on_app_initialization_complete.workflows_to_register"
356
- config_mgr = GriptapeNodes.ConfigManager()
357
-
358
- workflows_to_register = []
359
-
360
- # Add from config
361
- config_workflows = config_mgr.get_config_value(default_workflow_section, default=[])
362
- workflows_to_register.extend(config_workflows)
363
-
364
- # Add from workspace (avoiding duplicates)
365
- workspace_path = config_mgr.workspace_path
366
- workflows_to_register.extend([workspace_path])
367
-
368
- # Register all discovered workflows at once if any were found
369
- self._process_workflows_for_registration(workflows_to_register)
356
+ self._workflows_loading_complete.clear()
370
357
 
371
- # Print it all out nicely.
372
- self.print_workflow_load_status()
373
-
374
- # Now remove any workflows that were missing files.
375
- paths_to_remove = set()
376
- for workflow_path, workflow_info in self._workflow_file_path_to_info.items():
377
- if workflow_info.status == WorkflowManager.WorkflowStatus.MISSING:
378
- # Remove this file path from the config.
379
- paths_to_remove.add(workflow_path.lower())
380
-
381
- if paths_to_remove:
382
- workflows_to_register = config_mgr.get_config_value(default_workflow_section)
383
- if workflows_to_register:
384
- workflows_to_register = [
385
- workflow for workflow in workflows_to_register if workflow.lower() not in paths_to_remove
386
- ]
387
- config_mgr.set_config_value(default_workflow_section, workflows_to_register)
358
+ try:
359
+ default_workflow_section = "app_events.on_app_initialization_complete.workflows_to_register"
360
+ config_mgr = GriptapeNodes.ConfigManager()
361
+
362
+ workflows_to_register = []
363
+
364
+ # Add from config
365
+ config_workflows = config_mgr.get_config_value(default_workflow_section, default=[])
366
+ workflows_to_register.extend(config_workflows)
367
+
368
+ # Add from workspace (avoiding duplicates)
369
+ workspace_path = config_mgr.workspace_path
370
+ workflows_to_register.extend([workspace_path])
371
+
372
+ # Register all discovered workflows at once if any were found
373
+ self._process_workflows_for_registration(workflows_to_register)
374
+
375
+ # Print it all out nicely.
376
+ self.print_workflow_load_status()
377
+
378
+ # Now remove any workflows that were missing files.
379
+ paths_to_remove = set()
380
+ for workflow_path, workflow_info in self._workflow_file_path_to_info.items():
381
+ if workflow_info.status == WorkflowManager.WorkflowStatus.MISSING:
382
+ # Remove this file path from the config.
383
+ paths_to_remove.add(workflow_path.lower())
384
+
385
+ if paths_to_remove:
386
+ workflows_to_register = config_mgr.get_config_value(default_workflow_section)
387
+ if workflows_to_register:
388
+ workflows_to_register = [
389
+ workflow for workflow in workflows_to_register if workflow.lower() not in paths_to_remove
390
+ ]
391
+ config_mgr.set_config_value(default_workflow_section, workflows_to_register)
392
+ finally:
393
+ self._workflows_loading_complete.set()
388
394
 
389
395
  def get_workflow_metadata(self, workflow_file_path: Path, block_name: str) -> list[re.Match[str]]:
390
396
  """Get the workflow metadata for a given workflow file path.
@@ -609,6 +615,8 @@ class WorkflowManager:
609
615
  return RunWorkflowWithCurrentStateResultFailure(result_details=execution_result.execution_details)
610
616
 
611
617
  async def on_run_workflow_from_registry_request(self, request: RunWorkflowFromRegistryRequest) -> ResultPayload:
618
+ await self._workflows_loading_complete.wait()
619
+
612
620
  # get workflow from registry
613
621
  try:
614
622
  workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
@@ -716,7 +724,9 @@ class WorkflowManager:
716
724
  ),
717
725
  )
718
726
 
719
- def on_list_all_workflows_request(self, _request: ListAllWorkflowsRequest) -> ResultPayload:
727
+ async def on_list_all_workflows_request(self, _request: ListAllWorkflowsRequest) -> ResultPayload:
728
+ await self._workflows_loading_complete.wait()
729
+
720
730
  try:
721
731
  workflows = WorkflowRegistry.list_workflows()
722
732
  except Exception:
@@ -1699,7 +1709,7 @@ class WorkflowManager:
1699
1709
  """Generates execute_workflow(...) and the __main__ guard."""
1700
1710
  # Use workflow shape from metadata if available, otherwise skip execution block
1701
1711
  if workflow_metadata.workflow_shape is None:
1702
- logger.info("Workflow shape does not have required Start or End Nodes. Skipping local execution block.")
1712
+ logger.debug("Workflow shape does not have required Start or End Nodes. Skipping local execution block.")
1703
1713
  return None
1704
1714
 
1705
1715
  # Convert WorkflowShape to dict format expected by the rest of the method
@@ -31,6 +31,7 @@ class MultiOptions(Trait):
31
31
  show_search: bool = field(default=True)
32
32
  search_filter: str = field(default="")
33
33
  icon_size: str = field(default="small")
34
+ allow_user_created_options: bool = field(default=False)
34
35
 
35
36
  def __init__( # noqa: PLR0913
36
37
  self,
@@ -41,6 +42,7 @@ class MultiOptions(Trait):
41
42
  show_search: bool = True,
42
43
  search_filter: str = "",
43
44
  icon_size: str = "small",
45
+ allow_user_created_options: bool = False,
44
46
  ) -> None:
45
47
  super().__init__()
46
48
  # Set choices through property to ensure dual sync from the start
@@ -51,6 +53,7 @@ class MultiOptions(Trait):
51
53
  self.max_selected_display = max_selected_display
52
54
  self.show_search = show_search
53
55
  self.search_filter = search_filter
56
+ self.allow_user_created_options = allow_user_created_options
54
57
 
55
58
  # Validate icon_size
56
59
  if icon_size not in ["small", "large"]:
@@ -135,7 +138,14 @@ class MultiOptions(Trait):
135
138
  return []
136
139
  value = [value]
137
140
 
138
- # Filter out invalid choices and return valid ones
141
+ # When allow_user_created_options is enabled, accept any string values
142
+ # without validating against predefined choices
143
+ if self.allow_user_created_options:
144
+ # Filter out non-string values and ensure all options are valid strings
145
+ valid_options = [str(v) for v in value if v is not None and str(v).strip()]
146
+ return valid_options
147
+
148
+ # Standard multi-options mode: filter out invalid choices and return valid ones
139
149
  valid_choices = [v for v in value if v in self.choices]
140
150
 
141
151
  # If no valid choices, return empty list (allow empty selection)
@@ -157,7 +167,20 @@ class MultiOptions(Trait):
157
167
  msg = "MultiOptions value must be a list"
158
168
  raise TypeError(msg)
159
169
 
160
- # Check that all selected values are valid choices
170
+ # When allow_user_created_options is enabled, validate that all values are strings
171
+ # but don't validate against predefined choices
172
+ if self.allow_user_created_options:
173
+ for option in value:
174
+ if not isinstance(option, str):
175
+ msg = f"All options must be strings, found: {type(option).__name__}"
176
+ raise TypeError(msg)
177
+
178
+ if not option.strip():
179
+ msg = "Options cannot be empty strings"
180
+ raise ValueError(msg)
181
+ return
182
+
183
+ # Standard multi-options mode: check that all selected values are valid choices
161
184
  invalid_choices = [v for v in value if v not in self.choices]
162
185
  if invalid_choices:
163
186
  msg = f"Invalid choices: {invalid_choices}"
@@ -188,5 +211,6 @@ class MultiOptions(Trait):
188
211
  "show_search": self.show_search,
189
212
  "search_filter": self.search_filter,
190
213
  "icon_size": self.icon_size,
214
+ "allow_user_created_options": self.allow_user_created_options,
191
215
  }
192
216
  }
@@ -0,0 +1,136 @@
1
+ import logging
2
+ from pathlib import Path
3
+ from typing import Any
4
+
5
+ from huggingface_hub import scan_cache_dir # pyright: ignore[reportMissingImports]
6
+ from huggingface_hub.constants import HF_HUB_CACHE
7
+
8
+ logger = logging.getLogger("griptape_nodes")
9
+
10
+
11
+ def list_all_repo_revisions_in_cache() -> list[tuple[str, str]]:
12
+ """Returns a list of (repo_id, revision) tuples for all repos in the huggingface cache."""
13
+ # Use quick scan for diffuser repos, fallback to scan_cache_dir only on errors
14
+ try:
15
+ repos = quick_scan_diffuser_repos(HF_HUB_CACHE)
16
+ results = [(repo["name"], repo["hash"]) for repo in repos]
17
+ except Exception:
18
+ logger.exception("Failed to quick scan diffuser repos, falling back to scan_cache_dir.")
19
+ else:
20
+ return results
21
+
22
+ # Fallback to original implementation
23
+ cache_info = scan_cache_dir()
24
+ results = []
25
+ for repo in cache_info.repos:
26
+ for revision in repo.revisions:
27
+ results.append((repo.repo_id, revision.commit_hash))
28
+ return results
29
+
30
+
31
+ def list_repo_revisions_in_cache(repo_id: str) -> list[tuple[str, str]]:
32
+ """Returns a list of (repo_id, revision) tuples matching repo_id in the huggingface cache."""
33
+ # Use quick scan for diffuser repos, fallback to scan_cache_dir only on errors
34
+ try:
35
+ repos = quick_scan_diffuser_repos(HF_HUB_CACHE)
36
+ results = [(repo["name"], repo["hash"]) for repo in repos if repo["name"] == repo_id]
37
+ except Exception:
38
+ logger.exception("Failed to quick scan diffuser repos, falling back to scan_cache_dir.")
39
+ else:
40
+ return results
41
+
42
+ # Fallback to original implementation
43
+ cache_info = scan_cache_dir()
44
+ results = []
45
+ for repo in cache_info.repos:
46
+ if repo.repo_id == repo_id:
47
+ for revision in repo.revisions:
48
+ results.append((repo.repo_id, revision.commit_hash))
49
+ return results
50
+
51
+
52
+ def list_repo_revisions_with_file_in_cache(repo_id: str, file: str) -> list[tuple[str, str]]:
53
+ """Returns a list of (repo_id, revision) tuples matching repo_id in the huggingface cache if it contains file."""
54
+ # Use quick scan for diffuser repos, check if file exists
55
+ try:
56
+ repos = quick_scan_diffuser_repos(HF_HUB_CACHE)
57
+ results = [
58
+ (repo["name"], repo["hash"])
59
+ for repo in repos
60
+ if repo["name"] == repo_id and (Path(repo["path"]) / file).exists()
61
+ ]
62
+ except Exception:
63
+ logger.exception("Failed to quick scan diffuser repos, falling back to scan_cache_dir.")
64
+ else:
65
+ return results
66
+
67
+ # Fallback to original implementation
68
+ cache_info = scan_cache_dir()
69
+ results = []
70
+ for repo in cache_info.repos:
71
+ if repo.repo_id == repo_id:
72
+ for revision in repo.revisions:
73
+ if any(f.file_name == file for f in revision.files):
74
+ results.append((repo.repo_id, revision.commit_hash))
75
+ return results
76
+
77
+
78
+ def quick_scan_diffuser_repos(cache_dir: str) -> list[dict[str, Any]]:
79
+ """Quick scan of diffuser repositories in huggingface cache directory.
80
+
81
+ Adapted from https://github.com/huggingface/huggingface_hub/issues/1564#issuecomment-1710764361
82
+
83
+ Args:
84
+ cache_dir: Path to huggingface cache directory
85
+
86
+ Returns:
87
+ List of dictionaries containing repo info with keys:
88
+ - name: Repository name
89
+ - filename: Repository name (alias for name)
90
+ - path: Path to the snapshot folder
91
+ - hash: Commit hash
92
+ - mtime: Modification time
93
+ - model_info: Path to model_info.json file
94
+ """
95
+ diffuser_repos = []
96
+ cache_path = Path(cache_dir)
97
+
98
+ if not cache_path.exists():
99
+ return diffuser_repos
100
+
101
+ for folder_path in cache_path.iterdir():
102
+ folder = folder_path.name
103
+ if not folder_path.is_dir() or "--" not in folder:
104
+ continue
105
+ _, name = folder.split("--", maxsplit=1)
106
+ name = name.replace("--", "/")
107
+
108
+ snapshots_dir = folder_path / "snapshots"
109
+ if not snapshots_dir.exists():
110
+ continue
111
+
112
+ snapshots = [p.name for p in snapshots_dir.iterdir() if p.is_dir()]
113
+ if len(snapshots) == 0:
114
+ continue
115
+
116
+ commit = snapshots[-1]
117
+ snapshot_path = snapshots_dir / commit
118
+
119
+ if (snapshot_path / "hidden").exists():
120
+ continue
121
+
122
+ mtime = snapshot_path.stat().st_mtime
123
+ info = snapshot_path / "model_info.json"
124
+
125
+ diffuser_repos.append(
126
+ {
127
+ "name": name,
128
+ "filename": name,
129
+ "path": str(snapshot_path),
130
+ "hash": commit,
131
+ "mtime": mtime,
132
+ "model_info": str(info),
133
+ }
134
+ )
135
+
136
+ return diffuser_repos
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: griptape-nodes
3
- Version: 0.59.3
3
+ Version: 0.60.0
4
4
  Summary: Add your description here
5
5
  Requires-Dist: griptape>=1.8.8
6
6
  Requires-Dist: pydantic>=2.10.6
@@ -34,6 +34,14 @@ griptape_nodes/cli/main.py,sha256=A9k-4vdxOrm3Z0NNtDWLmvSW5ecvtIXInLR0zn2AERA,17
34
34
  griptape_nodes/cli/shared.py,sha256=ciuqFxls18HXxNOaqK6QObmb3i7OLbw_DkUxX2g0rL0,2656
35
35
  griptape_nodes/common/__init__.py,sha256=HTbJfTpu6-nU91zFCZW2qUNeW6bitNWNDayWqH6fpbA,22
36
36
  griptape_nodes/common/directed_graph.py,sha256=hk3C_S4GiG4FZOmufjebb-6_2SwQrbyTidYTSbCDWMU,2361
37
+ griptape_nodes/common/macro_parser/__init__.py,sha256=31c6Ak9j0VwGHIqgMMxF_GzNKCO5lneIFaUXQiL7gKk,796
38
+ griptape_nodes/common/macro_parser/core.py,sha256=khJp09GsNbOU2BPForV9jM2jgOEXTThvtWRvZyWRGZs,11343
39
+ griptape_nodes/common/macro_parser/exceptions.py,sha256=5PvVJmn1qHsizrhbXWlc-cvgMDBkMFWRNKPa-bWRevw,709
40
+ griptape_nodes/common/macro_parser/formats.py,sha256=-7_QLo7pqBRR7HKMcW_LZAT_JxFIxqC20284YeGtWoo,4968
41
+ griptape_nodes/common/macro_parser/matching.py,sha256=bGGJrIY0nwpVZmhRAQwru1SETaBWg_Sw5U86wozVtFQ,4395
42
+ griptape_nodes/common/macro_parser/parsing.py,sha256=kk5lQx-wJ6GZ2H9BI2yJBOYYN3aLsie9iIJYgp1BDC8,5761
43
+ griptape_nodes/common/macro_parser/resolution.py,sha256=FvXGUiHheX2nFEbyxxVqxvTYfbUlM4e_L1d-3l8Nwkw,6116
44
+ griptape_nodes/common/macro_parser/segments.py,sha256=r-WbZas1nSc-PlEdAZ7DycNoD6IUf3R_nhGo3T9vIa8,1010
37
45
  griptape_nodes/common/node_executor.py,sha256=d96vYMMpdvGK-ol3priQjveYs7kTcz0A6WXhgnyQttE,29204
38
46
  griptape_nodes/drivers/__init__.py,sha256=tHmiFQn6uJyFVhC2PrqHgRUH3d3yDsqMQpWqRasmaqA,42
39
47
  griptape_nodes/drivers/storage/__init__.py,sha256=_7p8vJt3YnnF6sD3Uxxw38c-gazuMIHSS-m3G6sa2Qk,208
@@ -43,11 +51,24 @@ griptape_nodes/drivers/storage/local_storage_driver.py,sha256=6FqtT4I4lZTRSa_7gQ
43
51
  griptape_nodes/drivers/storage/storage_backend.py,sha256=3QBIwrgPc1krBIiPYLoK2swhIPDiKJnnucOEdyx7y3c,184
44
52
  griptape_nodes/exe_types/__init__.py,sha256=wGGwKGX9-TSarUFbXpDvdU_J7eXIbWTBl_NCLOZa-G8,32
45
53
  griptape_nodes/exe_types/connections.py,sha256=Cjt-RLjYhkTUHTrYlNIUZrYVzsyH7OXo6JO2O6exI8k,13853
46
- griptape_nodes/exe_types/core_types.py,sha256=bedZQcu0z4GvN9TazmXFAjdhM9GlS4HrTf1jog6ME04,83073
54
+ griptape_nodes/exe_types/core_types.py,sha256=pZdjMs_i9nj5y24Pt0UbAYKVc9nYsI3ewrgcZ9WQfsA,91217
47
55
  griptape_nodes/exe_types/flow.py,sha256=pCeTrx8yrUgLw1U9yQxC7arzJjyP2vag-pG0QTKut-M,5716
48
- griptape_nodes/exe_types/node_types.py,sha256=B74U5Qi3LE7AcU3pUiX49hvCT5dXk77qZ-lp_wPSl5M,94466
56
+ griptape_nodes/exe_types/node_types.py,sha256=4idQIcnE0Ju-wlibY0swGOYcy2PfF9OyGPeXfZ3ct84,94722
49
57
  griptape_nodes/exe_types/param_components/__init__.py,sha256=ocm75WnsgiD6ozKVGFhoH9cQe_FEzeF2osxrRujOes0,60
50
58
  griptape_nodes/exe_types/param_components/execution_status_component.py,sha256=eeUcUOOraGa6sDH_zg_QnGPoP0K-pm3fu90-KAtrmq8,5532
59
+ griptape_nodes/exe_types/param_components/huggingface/__init__.py,sha256=YeVFck-9C341Bt7TiWEvPdD63o9qkaNu2KjmzT9CQOI,39
60
+ griptape_nodes/exe_types/param_components/huggingface/huggingface_model_parameter.py,sha256=KXTAUyW0yxBN40BbIVg9dZfdUeNDGeX-jmFUoCJwapQ,6352
61
+ griptape_nodes/exe_types/param_components/huggingface/huggingface_repo_file_parameter.py,sha256=QmpE8JH45D52DePePff0uNp2s8lnAdp4ileJ0GpeOB4,1517
62
+ griptape_nodes/exe_types/param_components/huggingface/huggingface_repo_parameter.py,sha256=zcBRQP0eZJloSdPQwJFw89B6QDHECnrosRZUy8mE2fM,1401
63
+ griptape_nodes/exe_types/param_components/huggingface/huggingface_utils.py,sha256=cE0Ht81kDcZjlN_2VoRirCA4zMlrG9GFlcptn-gC2tU,4696
64
+ griptape_nodes/exe_types/param_components/log_parameter.py,sha256=K6XRWVIpL9MtQ6IZG3hYYwIv3sNqFxONxbVnKcA_Oes,4160
65
+ griptape_nodes/exe_types/param_components/seed_parameter.py,sha256=nXyi9bPCK9LuRB6s4Q2ezwdboIaivEObglNrSFn0y-0,2045
66
+ griptape_nodes/exe_types/param_types/__init__.py,sha256=xEEmKvIFF6M7zVjQZCupbbv6SZKt-itD-rPtfRhxJVg,53
67
+ griptape_nodes/exe_types/param_types/parameter_bool.py,sha256=MyJlYYKAyRtu-V8GqFdV6jAtwRk8NRjj6LO8SZ9BQo8,8094
68
+ griptape_nodes/exe_types/param_types/parameter_float.py,sha256=W_n4__XHOYppRD3-2RSLmxFcrcCBRex15oMyhShNyUU,6672
69
+ griptape_nodes/exe_types/param_types/parameter_int.py,sha256=OmyuGeo6P4ZWxp1Ms9kQRhI2Ar-igDqUQPmH_0XtxUI,6821
70
+ griptape_nodes/exe_types/param_types/parameter_number.py,sha256=tzACjVQos8nDCirQSxBPaDfDciigiA_OHgSKZW43gVA,15251
71
+ griptape_nodes/exe_types/param_types/parameter_string.py,sha256=xdoVK_XslPrYOwiQ_IhSYiqAV0CPd8nBkHHw7ySYXmc,8533
51
72
  griptape_nodes/exe_types/type_validator.py,sha256=RTz1vX09jzQpHhozITMJ0siOZUXvsERDhrApjdaM1WM,1120
52
73
  griptape_nodes/machines/__init__.py,sha256=v0jkwr-CFOLmfEYUQvX8BKQLOdvhSsA6toXkdHcPGUE,30
53
74
  griptape_nodes/machines/control_flow.py,sha256=6C-M9yLcpQImNLUvO2l_lhyL7afesfrtnXNWe57NtdM,27098
@@ -58,13 +79,13 @@ griptape_nodes/machines/sequential_resolution.py,sha256=x0qi21iCtb6rkc5keeuAk0_M
58
79
  griptape_nodes/mcp_server/__init__.py,sha256=GSpJWqE4lICaryhsQR1okeMH2x6j1bBL0HVxtr52WLg,42
59
80
  griptape_nodes/node_library/__init__.py,sha256=U3FcSdmq6UW7qt6E3Up3NWKvUEn5_5lqL-u5qbzfxMQ,28
60
81
  griptape_nodes/node_library/advanced_node_library.py,sha256=B1ZaxuFIzQ6tx_3MLIxlsHuahthEC1Hw_t6K_ByIdzs,2104
61
- griptape_nodes/node_library/library_registry.py,sha256=s77u0NbESOzaB29-PzQ1EKrR1WyQKOQTRGaKx3ORXoY,13888
82
+ griptape_nodes/node_library/library_registry.py,sha256=0PCofxvPh8r1r-me8Y04aIQvVjeO55hvvv7uj5QC9Dw,13951
62
83
  griptape_nodes/node_library/workflow_registry.py,sha256=OmBv_1SImABVBZgtMaZq3ZJHaoRgwv3Na8if5uKmfHw,10523
63
84
  griptape_nodes/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
85
  griptape_nodes/retained_mode/__init__.py,sha256=X12DKL6KhLsiRTPIlrPj2h76_sJ0q0eH4r0kMQkodm0,29
65
86
  griptape_nodes/retained_mode/events/__init__.py,sha256=7B1C-c0jVvnShtHJ2lfX6BZPE0U1DgQwg1e4DorhKG0,22
66
87
  griptape_nodes/retained_mode/events/agent_events.py,sha256=FtE9AA0yD4O2cblIO5g2_xBlU1XWwnK4BhcDJxlQDTU,5027
67
- griptape_nodes/retained_mode/events/app_events.py,sha256=EEZhiCFFcgUKK7p7uniZMCZUPW12Kt5xzduUsrpxii8,8622
88
+ griptape_nodes/retained_mode/events/app_events.py,sha256=1ushpyLnIxMQLx7YEfK5USPVCBrtDO84ku8JPBufmcc,9138
68
89
  griptape_nodes/retained_mode/events/arbitrary_python_events.py,sha256=uhep1c1xjUc-YQO5nIStAE48PS6rFZLTDQIr_Qb3we8,1460
69
90
  griptape_nodes/retained_mode/events/base_events.py,sha256=UPEMkoU7lUtm8L_wdeTp8YRLSAFFgxJIVRasdqtuQfQ,23223
70
91
  griptape_nodes/retained_mode/events/config_events.py,sha256=Y03YMLoJTXy0Sz6tq-6lOIs37CmXn1Br3GYAinl02nY,7070
@@ -79,8 +100,8 @@ griptape_nodes/retained_mode/events/mcp_events.py,sha256=51OlMZVcabdcIxBb_ojvrHt
79
100
  griptape_nodes/retained_mode/events/model_events.py,sha256=EbSjIpJrQi2RuRRFJsoioAyMchAba-vEOXvLBCR0xi0,9227
80
101
  griptape_nodes/retained_mode/events/node_events.py,sha256=jTcO5-Mw52fAJUzVc6UaXwRKHfO2HO0hnNYcGg9phVo,30321
81
102
  griptape_nodes/retained_mode/events/object_events.py,sha256=cJaqEU73Lzf1RRxJrFqEpl8eTr-gDhKpXKywJ-vVCJQ,2631
82
- griptape_nodes/retained_mode/events/os_events.py,sha256=X0mmyk_r5t6upaQ8eWClD7J25AiX2ggsAuxMZSW9Vx0,8085
83
- griptape_nodes/retained_mode/events/parameter_events.py,sha256=TZdJLF3ZHVZapgoX0vH8tCB413eDblcsRG1tJXdtxuE,23798
103
+ griptape_nodes/retained_mode/events/os_events.py,sha256=cve-CfzvQmTa6kbMMqT4UA_LXFVag_8opmTx2l08ESY,12712
104
+ griptape_nodes/retained_mode/events/parameter_events.py,sha256=FA5GY-sUkLSGgEH6NsAeRYse-jCk1D9qrN5RMzdOOqU,23903
84
105
  griptape_nodes/retained_mode/events/payload_registry.py,sha256=q-wxUqp63vhNj-Pl1JGJHnBkhUefcCArPoMN3KBREEI,1691
85
106
  griptape_nodes/retained_mode/events/resource_events.py,sha256=K47UK92wvaRtHu3ByfhkQEMyorrV0ArGewrFSJuVMiI,9015
86
107
  griptape_nodes/retained_mode/events/secrets_events.py,sha256=fCw3OMFfxB8FTZs4ybojm1nqNvhcjtoNylQhX75-jkM,4156
@@ -89,10 +110,10 @@ griptape_nodes/retained_mode/events/sync_events.py,sha256=AoxBZLPPdzx4S5CiOJVRDe
89
110
  griptape_nodes/retained_mode/events/validation_events.py,sha256=H2yWoHp2t7QwGV_fDQXRy7JojYnK4k6SOAlEvRYST_Q,3062
90
111
  griptape_nodes/retained_mode/events/variable_events.py,sha256=fnl_sY8GWI_R4UJQTEJSlmsyCD9TiEW0U2UD2seBabs,10587
91
112
  griptape_nodes/retained_mode/events/workflow_events.py,sha256=FjARlC9wwWFMqtugEkPOEf_y9eyEhfzP-MZSl4TGRBI,22530
92
- griptape_nodes/retained_mode/griptape_nodes.py,sha256=jB8Ufn13JbanahY3pc_43C9-DS-p4YAX_h8OvkOLgSw,18826
113
+ griptape_nodes/retained_mode/griptape_nodes.py,sha256=SY99PBz7kJoCDClueww5gi1GOT-C2W-ledvNZgkNQ3E,19455
93
114
  griptape_nodes/retained_mode/managers/__init__.py,sha256=OTXysKusqYCQeAYwnVj4PbE3MxvAUTq9xOZT6vUE3JA,24
94
- griptape_nodes/retained_mode/managers/agent_manager.py,sha256=r1tFMIt9vUMFooQT5jmg1I5wBzm0Calie5dVuIXmeDY,15486
95
- griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py,sha256=3IRIrpKR62MvTdGWfQa1ARUVxCmMUNtzUU4xMcQdlCY,1891
115
+ griptape_nodes/retained_mode/managers/agent_manager.py,sha256=8GznO1Xzl-D48eIibHJeEsT1WvecX1YNkZdHJ5kiv4s,15550
116
+ griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py,sha256=LyWzHQKmyDh-2zh2PIahdYyAthf_rMYs4zvhtVo-LsU,3423
96
117
  griptape_nodes/retained_mode/managers/config_manager.py,sha256=WfzvFDPyboHgsCMpVGER6Ar1OHyPD_827LQx9xaUsMM,25573
97
118
  griptape_nodes/retained_mode/managers/context_manager.py,sha256=eb44_CAZhCg2iYIoodlAPpYc67tG3sHyq9dPNoiq_1s,23031
98
119
  griptape_nodes/retained_mode/managers/engine_identity_manager.py,sha256=-31364A03kU0YmAx3nM7nHdWfKnkej5Cawt_Plbwa68,10526
@@ -110,13 +131,13 @@ griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/packa
110
131
  griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py,sha256=XgG7whE74zWDxX1pOvhASW0pwjOei1EDLvIH19xdzT0,6117
111
132
  griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py,sha256=cCGr-MQ1RlVBiUTZepYEKdVhPgC4ebcYrmpv8rI3VeM,894
112
133
  griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py,sha256=K3UEBzAdCY9wphyBbLxDYP0Q43aYvhLZ_Pz7_SzcPec,443
113
- griptape_nodes/retained_mode/managers/library_manager.py,sha256=CO4mZEPgYQPGRbqJz8R5NYYp1RgLCb38q14bssdyb14,100111
134
+ griptape_nodes/retained_mode/managers/library_manager.py,sha256=BELBl0IUgbPOe_J-7muyXXwJDobKPFf0yfQn9lL8DK0,100472
114
135
  griptape_nodes/retained_mode/managers/mcp_manager.py,sha256=BxNVDYUAn5-iylGzURqVZq1DRintrIK5T6q2X_rxm_U,15596
115
136
  griptape_nodes/retained_mode/managers/model_manager.py,sha256=Qc_FiqIJQ_ZuL5Yb7WiHCgUngKlbbJ_dUo7E5Ten5_g,45036
116
- griptape_nodes/retained_mode/managers/node_manager.py,sha256=PO6m-ny3exswCqHx2LV4y56qpbBUnh6U01wT1AX24CQ,183596
137
+ griptape_nodes/retained_mode/managers/node_manager.py,sha256=p_Q9_JLnJ7Uz5VsSmuzKO34BYcEGMiQYN8I_p-Ca2lQ,184514
117
138
  griptape_nodes/retained_mode/managers/object_manager.py,sha256=w6T5UPUJRcYF90F1MuWhZVDgRrMc1uQ-6wt84Oz8OQA,12827
118
139
  griptape_nodes/retained_mode/managers/operation_manager.py,sha256=lTkMZlaacTgtV5oV-YF6HG8xsx9V_LwX1eg074WTs2k,20137
119
- griptape_nodes/retained_mode/managers/os_manager.py,sha256=uQ0jRGXOimdmcdnwZUMAJnEdqvE33p7w5bBXjPN20fw,40128
140
+ griptape_nodes/retained_mode/managers/os_manager.py,sha256=Zq5hZqvt5rw8XH9Wuy4puW-Q3c6YbCZraQ1cTm7RhPM,54709
120
141
  griptape_nodes/retained_mode/managers/resource_components/__init__.py,sha256=2FHpZFw2N1-oHfMCfrnB_XpF8_-2aSNtAZWh5zQTGL0,35
121
142
  griptape_nodes/retained_mode/managers/resource_components/capability_field.py,sha256=jZ5ONfdYVd5_MKlSKvUch1X2n1oHzMSeZW8UZ1a_RsU,1504
122
143
  griptape_nodes/retained_mode/managers/resource_components/comparator.py,sha256=02SiAiOatEnCgZOoMvpDhLsMpiOeNdtg9_HbrW4gS2k,609
@@ -131,9 +152,10 @@ griptape_nodes/retained_mode/managers/session_manager.py,sha256=u3OEir9rjwG7GFM4
131
152
  griptape_nodes/retained_mode/managers/settings.py,sha256=4wJte850nr_M4laXFbEjWkmN5Ysuo18t5fujBofktOc,9343
132
153
  griptape_nodes/retained_mode/managers/static_files_manager.py,sha256=dDeX1Z5cmviNPkEBkF2MWYryLacJOh0TTpu-t7oCHps,11283
133
154
  griptape_nodes/retained_mode/managers/sync_manager.py,sha256=-m2krEh2YtGs8iAPc8bhFGX8JqjeM5kEV1rnCmcj_yk,21247
155
+ griptape_nodes/retained_mode/managers/user_manager.py,sha256=JAOOKDhUfIbj0CJ5EHRBcplmxheQTzeogbvGO23VqXQ,4508
134
156
  griptape_nodes/retained_mode/managers/variable_manager.py,sha256=TnuqHSRK9Yiu_EtKxQksF9SyyQb72lbFQuTQZdpBxeE,24116
135
157
  griptape_nodes/retained_mode/managers/version_compatibility_manager.py,sha256=3GEsJs1yNub8NP_ZNBgUEbaqHJXte8-u3Uapim_x0OU,14709
136
- griptape_nodes/retained_mode/managers/workflow_manager.py,sha256=Up-riPtDl9dy_IQqgUNk4q6TvpaZnfSLB2kgWtO57fY,199969
158
+ griptape_nodes/retained_mode/managers/workflow_manager.py,sha256=jgr8p6hr03wgVrSaJYJHqgFmQJ0igVU2pdLADg_T3rY,200380
137
159
  griptape_nodes/retained_mode/retained_mode.py,sha256=nBjLGz1y6ZEtAL5g81_gA93Y0r5va-Hdq4Rbqdk2XqM,71749
138
160
  griptape_nodes/retained_mode/utils/__init__.py,sha256=W5dvv8YwvVVq_8eVTgMd3Z_VB_Dtq1sIIVq8745QH_I,52
139
161
  griptape_nodes/retained_mode/utils/name_generator.py,sha256=IZLahtfP3XC79XApLdGoZ0IKKUkgiITpd16RK7NbyEs,2524
@@ -150,7 +172,7 @@ griptape_nodes/traits/compare.py,sha256=X-BXGemRDxQV4EX8X24LdtcwMWwfQ1jGqDvH2bSi
150
172
  griptape_nodes/traits/compare_images.py,sha256=KW0WlwsJP6nBoC1irdeRnUWUnZIJvlROlDhyWhX8iEs,1594
151
173
  griptape_nodes/traits/file_system_picker.py,sha256=p-RaH4xwb2Fo0wuFsYbsiL66W23KdESX0Qq6EAtDFj8,5806
152
174
  griptape_nodes/traits/minmax.py,sha256=eVySrz02WPvpwbSrqW7FRTmetNBOBKyf8YrXrzyOGnk,1312
153
- griptape_nodes/traits/multi_options.py,sha256=0iI5nTyZL1u4XSTqp27noddNy88Oizd8nQB3U25zB84,8467
175
+ griptape_nodes/traits/multi_options.py,sha256=lCPAkeJc_kjH9abam4zcnCkxLXMKzv0dgjyIcHxkVh8,9800
154
176
  griptape_nodes/traits/numbers_selector.py,sha256=Zos40TBqffWFVlgPJ1f1UtKGhl-mpfJbIid8YWeSLzI,2618
155
177
  griptape_nodes/traits/options.py,sha256=20pByxnOh_A0bzqWr2I21OCMOFowFLbHNXUn4SPv4jI,6318
156
178
  griptape_nodes/traits/slider.py,sha256=bLe46gtCmjhMCHaGzUstIWMJv2Zl2Yee7fkT6g4Q6Rk,1236
@@ -161,6 +183,7 @@ griptape_nodes/updater/__main__.py,sha256=lhMMctbBeni57ximitvkwqJ1TQzk79Jg9w0rkK
161
183
  griptape_nodes/utils/__init__.py,sha256=kzDZW_VPyxWJFonM3kYTl7A91_JmtHPK0Io4KPLTYT4,122
162
184
  griptape_nodes/utils/async_utils.py,sha256=4IrW8Ub8iJ2QB9yguZtfN1EB9B5nXHS7jbDaLOHWso0,4844
163
185
  griptape_nodes/utils/dict_utils.py,sha256=1VP2EoyOP0nswoAgjPehpA0izpkygWRX7L--ArN6LV8,7314
186
+ griptape_nodes/utils/huggingface_utils.py,sha256=txR5XS_01W3TvsH4SQ3AJrFy8oS8Ah9M-ePRSs3jHYA,4737
164
187
  griptape_nodes/utils/image_preview.py,sha256=NhYIqohRF9vbFpWIEvZHdPLLPK_JdUBvC4RvNAsSa1w,4480
165
188
  griptape_nodes/utils/metaclasses.py,sha256=RSKyAvZppH_hbMugmUmIr8QqOg1sYY4uRNfQybD4O8Q,287
166
189
  griptape_nodes/utils/uv_utils.py,sha256=ZK37LmacKfxMVKkcIOyJ35HOXgV6sFWE9CzgKPmaRU0,519
@@ -172,7 +195,7 @@ griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_re
172
195
  griptape_nodes/version_compatibility/workflow_versions/__init__.py,sha256=z5XDgkizoNByCXpyo34hfsJKFsWlOHbD6hgzfYH9ubc,52
173
196
  griptape_nodes/version_compatibility/workflow_versions/v0_7_0/__init__.py,sha256=IzPPmGK86h2swfGGTOHyVcBIlOng6SjgWQzlbf3ngmo,51
174
197
  griptape_nodes/version_compatibility/workflow_versions/v0_7_0/local_executor_argument_addition.py,sha256=Y8n1wzI5a-ZCHK5eiwtnnD3zF5lN-52R67rxYn0hxyI,2069
175
- griptape_nodes-0.59.3.dist-info/WHEEL,sha256=ELhySV62sOro8I5wRaLaF3TWxhBpkcDkdZUdAYLy_Hk,78
176
- griptape_nodes-0.59.3.dist-info/entry_points.txt,sha256=qvevqd3BVbAV5TcantnAm0ouqaqYKhsRO3pkFymWLWM,82
177
- griptape_nodes-0.59.3.dist-info/METADATA,sha256=264LN9kJJRslObEYiVjsdTysFJtVHTwKwxoFDb_bdf0,5108
178
- griptape_nodes-0.59.3.dist-info/RECORD,,
198
+ griptape_nodes-0.60.0.dist-info/WHEEL,sha256=M6du7VZflc4UPsGphmOXHANdgk8zessdJG0DBUuoA-U,78
199
+ griptape_nodes-0.60.0.dist-info/entry_points.txt,sha256=qvevqd3BVbAV5TcantnAm0ouqaqYKhsRO3pkFymWLWM,82
200
+ griptape_nodes-0.60.0.dist-info/METADATA,sha256=diiu5wfFAdS4NQbQtNgqvMkKkFmd_BCb9lk0tADIB6c,5108
201
+ griptape_nodes-0.60.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.9.3
2
+ Generator: uv 0.9.5
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any