griptape-nodes 0.62.0__py3-none-any.whl → 0.62.2__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.
@@ -46,7 +46,7 @@ class GriptapeCloudStorageDriver(BaseStorageDriver):
46
46
  response = httpx.post(url, json={"operation": "PUT"}, headers=self.headers)
47
47
  response.raise_for_status()
48
48
  except httpx.HTTPStatusError as e:
49
- msg = f"Failed to create presigned URL for file {path}: {e}"
49
+ msg = f"Failed to create presigned upload URL for file {path}: {e}"
50
50
  logger.error(msg)
51
51
  raise RuntimeError(msg) from e
52
52
 
@@ -60,7 +60,7 @@ class GriptapeCloudStorageDriver(BaseStorageDriver):
60
60
  response = httpx.post(url, json={"method": "GET"}, headers=self.headers)
61
61
  response.raise_for_status()
62
62
  except httpx.HTTPStatusError as e:
63
- msg = f"Failed to create presigned URL for file {path}: {e}"
63
+ msg = f"Failed to create presigned download URL for file {path}: {e}"
64
64
  logger.error(msg)
65
65
  raise RuntimeError(msg) from e
66
66
 
@@ -43,14 +43,14 @@ class LocalStorageDriver(BaseStorageDriver):
43
43
  response = httpx.post(static_url, json={"file_path": str(path)})
44
44
  response.raise_for_status()
45
45
  except httpx.HTTPStatusError as e:
46
- msg = f"Failed to create presigned URL for file {path}: {e}"
46
+ msg = f"Failed to create upload URL for file {path}: {e}"
47
47
  logger.error(msg)
48
48
  raise RuntimeError(msg) from e
49
49
 
50
50
  response_data = response.json()
51
51
  url = response_data.get("url")
52
52
  if url is None:
53
- msg = f"Failed to create presigned URL for file {path}: {response_data}"
53
+ msg = f"Failed to get upload URL for file {path}: {response_data}"
54
54
  logger.error(msg)
55
55
  raise ValueError(msg)
56
56
 
@@ -98,6 +98,19 @@ class EventManager:
98
98
  self._event_loop = None
99
99
  self._loop_thread_id = None
100
100
 
101
+ def _is_cross_thread_call(self) -> bool:
102
+ """Check if the current call is from a different thread than the event loop.
103
+
104
+ Returns:
105
+ True if we're on a different thread and need thread-safe operations
106
+ """
107
+ current_thread_id = threading.get_ident()
108
+ return (
109
+ self._loop_thread_id is not None
110
+ and current_thread_id != self._loop_thread_id
111
+ and self._event_loop is not None
112
+ )
113
+
101
114
  def put_event(self, event: Any) -> None:
102
115
  """Put event into async queue from sync context (non-blocking).
103
116
 
@@ -109,15 +122,9 @@ class EventManager:
109
122
  if self._event_queue is None:
110
123
  return
111
124
 
112
- # Check if we need thread-safe operation
113
- current_thread_id = threading.get_ident()
114
-
115
- if (
116
- self._loop_thread_id is not None
117
- and current_thread_id != self._loop_thread_id
118
- and self._event_loop is not None
119
- ):
125
+ if self._is_cross_thread_call() and self._event_loop is not None:
120
126
  # We're in a different thread from the event loop, use thread-safe method
127
+ # _is_cross_thread_call() guarantees _event_loop is not None
121
128
  self._event_loop.call_soon_threadsafe(self._event_queue.put_nowait, event)
122
129
  else:
123
130
  # We're on the same thread as the event loop or no loop thread tracked, use direct method
@@ -126,13 +133,21 @@ class EventManager:
126
133
  async def aput_event(self, event: Any) -> None:
127
134
  """Put event into async queue from async context.
128
135
 
136
+ Automatically detects if we're in a different thread and uses thread-safe operations.
137
+
129
138
  Args:
130
139
  event: The event to publish to the queue
131
140
  """
132
141
  if self._event_queue is None:
133
142
  return
134
143
 
135
- await self._event_queue.put(event)
144
+ if self._is_cross_thread_call() and self._event_loop is not None:
145
+ # We're in a different thread from the event loop, use thread-safe method
146
+ # _is_cross_thread_call() guarantees _event_loop is not None
147
+ self._event_loop.call_soon_threadsafe(self._event_queue.put_nowait, event)
148
+ else:
149
+ # We're on the same thread as the event loop or no loop thread tracked, use async method
150
+ await self._event_queue.put(event)
136
151
 
137
152
  def assign_manager_to_request_type(
138
153
  self,
@@ -822,6 +822,7 @@ class LibraryManager:
822
822
  logger.info(
823
823
  "Installing dependencies for library '%s' with pip in venv at %s", library_data.name, venv_path
824
824
  )
825
+ is_debug = config_manager.get_config_value("log_level").upper() == "DEBUG"
825
826
  await subprocess_run(
826
827
  [
827
828
  sys.executable,
@@ -835,7 +836,7 @@ class LibraryManager:
835
836
  str(library_venv_python_path),
836
837
  ],
837
838
  check=True,
838
- capture_output=True,
839
+ capture_output=not is_debug,
839
840
  text=True,
840
841
  )
841
842
  else:
@@ -955,6 +956,7 @@ class LibraryManager:
955
956
  uv_path = find_uv_bin()
956
957
 
957
958
  logger.info("Installing dependency '%s' with pip in venv at %s", package_name, venv_path)
959
+ is_debug = config_manager.get_config_value("log_level").upper() == "DEBUG"
958
960
  await subprocess_run(
959
961
  [
960
962
  uv_path,
@@ -965,7 +967,7 @@ class LibraryManager:
965
967
  str(library_python_venv_path),
966
968
  ],
967
969
  check=True,
968
- capture_output=True,
970
+ capture_output=not is_debug,
969
971
  text=True,
970
972
  )
971
973
  else:
@@ -1032,10 +1034,11 @@ class LibraryManager:
1032
1034
  try:
1033
1035
  uv_path = find_uv_bin()
1034
1036
  logger.info("Creating virtual environment at %s with Python %s", library_venv_path, python_version)
1037
+ is_debug = config_manager.get_config_value("log_level").upper() == "DEBUG"
1035
1038
  await subprocess_run(
1036
1039
  [uv_path, "venv", str(library_venv_path), "--python", python_version],
1037
1040
  check=True,
1038
- capture_output=True,
1041
+ capture_output=not is_debug,
1039
1042
  text=True,
1040
1043
  )
1041
1044
  except subprocess.CalledProcessError as e:
@@ -1639,6 +1642,13 @@ class LibraryManager:
1639
1642
  user_libraries_section = "app_events.on_app_initialization_complete.libraries_to_register"
1640
1643
  libraries_to_register: list[str] = config_mgr.get_config_value(user_libraries_section)
1641
1644
 
1645
+ # Filter out empty or whitespace-only entries
1646
+ original_count = len(libraries_to_register) if libraries_to_register else 0
1647
+ libraries_to_register = [path for path in (libraries_to_register or []) if path and path.strip()]
1648
+ filtered_count = original_count - len(libraries_to_register)
1649
+ if filtered_count > 0:
1650
+ logger.warning("Filtered out %d empty library path entries from configuration", filtered_count)
1651
+
1642
1652
  if not libraries_to_register:
1643
1653
  logger.info("No libraries to register from config")
1644
1654
  return
@@ -1986,24 +1996,6 @@ class LibraryManager:
1986
1996
  ret_val.append(file_path)
1987
1997
  return ret_val
1988
1998
 
1989
- def _load_libraries_from_config_category(self, config_category: str, *, load_as_default_library: bool) -> None:
1990
- config_mgr = GriptapeNodes.ConfigManager()
1991
- libraries_to_register_category: list[str] = config_mgr.get_config_value(config_category)
1992
-
1993
- if libraries_to_register_category is not None:
1994
- for library_to_register in libraries_to_register_category:
1995
- if library_to_register:
1996
- if library_to_register.endswith(".json"):
1997
- library_load_request = RegisterLibraryFromFileRequest(
1998
- file_path=library_to_register,
1999
- load_as_default_library=load_as_default_library,
2000
- )
2001
- else:
2002
- library_load_request = RegisterLibraryFromRequirementSpecifierRequest(
2003
- requirement_specifier=library_to_register
2004
- )
2005
- GriptapeNodes.handle_request(library_load_request)
2006
-
2007
1999
  def _remove_missing_libraries_from_config(self, config_category: str) -> None:
2008
2000
  # Now remove all libraries that were missing from the user's config.
2009
2001
  config_mgr = GriptapeNodes.ConfigManager()
@@ -2076,8 +2068,10 @@ class LibraryManager:
2076
2068
  # Add from config
2077
2069
  config_libraries = config_mgr.get_config_value(user_libraries_section, default=[])
2078
2070
  for library_path_str in config_libraries:
2079
- library_path = Path(library_path_str)
2080
- if library_path.exists():
2081
- process_path(library_path)
2071
+ # Filter out falsy values that will resolve to current directory
2072
+ if library_path_str:
2073
+ library_path = Path(library_path_str)
2074
+ if library_path.exists():
2075
+ process_path(library_path)
2082
2076
 
2083
2077
  return list(discovered_libraries)
@@ -104,14 +104,12 @@ class StaticFilesManager:
104
104
  content_bytes = base64.b64decode(request.content)
105
105
  except (binascii.Error, ValueError) as e:
106
106
  msg = f"Failed to decode base64 content for file {file_name}: {e}"
107
- logger.error(msg)
108
107
  return CreateStaticFileResultFailure(error=msg, result_details=msg)
109
108
 
110
109
  try:
111
110
  url = self.save_static_file(content_bytes, file_name)
112
111
  except Exception as e:
113
112
  msg = f"Failed to create static file for file {file_name}: {e}"
114
- logger.error(msg)
115
113
  return CreateStaticFileResultFailure(error=msg, result_details=msg)
116
114
 
117
115
  return CreateStaticFileResultSuccess(url=url, result_details=f"Successfully created static file: {url}")
@@ -137,7 +135,6 @@ class StaticFilesManager:
137
135
  response = self.storage_driver.create_signed_upload_url(full_file_path)
138
136
  except Exception as e:
139
137
  msg = f"Failed to create presigned URL for file {file_name}: {e}"
140
- logger.error(msg)
141
138
  return CreateStaticFileUploadUrlResultFailure(error=msg, result_details=msg)
142
139
 
143
140
  return CreateStaticFileUploadUrlResultSuccess(
@@ -168,7 +165,6 @@ class StaticFilesManager:
168
165
  url = self.storage_driver.create_signed_download_url(full_file_path)
169
166
  except Exception as e:
170
167
  msg = f"Failed to create presigned URL for file {file_name}: {e}"
171
- logger.error(msg)
172
168
  return CreateStaticFileDownloadUrlResultFailure(error=msg, result_details=msg)
173
169
 
174
170
  return CreateStaticFileDownloadUrlResultSuccess(
@@ -177,7 +173,7 @@ class StaticFilesManager:
177
173
 
178
174
  def on_app_initialization_complete(self, _payload: AppInitializationComplete) -> None:
179
175
  # Start static server in daemon thread if enabled
180
- if self.storage_backend == StorageBackend.LOCAL:
176
+ if isinstance(self.storage_driver, LocalStorageDriver):
181
177
  threading.Thread(target=start_static_server, daemon=True, name="static-server").start()
182
178
 
183
179
  def save_static_file(self, data: bytes, file_name: str) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: griptape-nodes
3
- Version: 0.62.0
3
+ Version: 0.62.2
4
4
  Summary: Add your description here
5
5
  Requires-Dist: griptape>=1.8.12
6
6
  Requires-Dist: pydantic>=2.10.6
@@ -54,8 +54,8 @@ griptape_nodes/common/project_templates/validation.py,sha256=LPm0gri05ZIbSfCqOM4
54
54
  griptape_nodes/drivers/__init__.py,sha256=tHmiFQn6uJyFVhC2PrqHgRUH3d3yDsqMQpWqRasmaqA,42
55
55
  griptape_nodes/drivers/storage/__init__.py,sha256=_7p8vJt3YnnF6sD3Uxxw38c-gazuMIHSS-m3G6sa2Qk,208
56
56
  griptape_nodes/drivers/storage/base_storage_driver.py,sha256=47PrMzxOuJhV2ee4CbPT7YOqR2MjlHr3VxhGON_ygio,3945
57
- griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py,sha256=wFAssDP4pE06-KJXzKfpykSDjwDWgPlz0hWfOfnL-zg,6854
58
- griptape_nodes/drivers/storage/local_storage_driver.py,sha256=6FqtT4I4lZTRSa_7gQG7hDHShVKYySWXaQUCe6i-RmM,3674
57
+ griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py,sha256=qQctInOvfKRJdqTiW8T3ycjre2FDGTb9-JtzEtiCHVM,6870
58
+ griptape_nodes/drivers/storage/local_storage_driver.py,sha256=FqiX1DmvpyKx444f74cFCsQ2Mfx6XiOezRcCGFOCSgQ,3665
59
59
  griptape_nodes/drivers/storage/storage_backend.py,sha256=3QBIwrgPc1krBIiPYLoK2swhIPDiKJnnucOEdyx7y3c,184
60
60
  griptape_nodes/exe_types/__init__.py,sha256=wGGwKGX9-TSarUFbXpDvdU_J7eXIbWTBl_NCLOZa-G8,32
61
61
  griptape_nodes/exe_types/connections.py,sha256=Cjt-RLjYhkTUHTrYlNIUZrYVzsyH7OXo6JO2O6exI8k,13853
@@ -131,7 +131,7 @@ griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py,sha256=LyWz
131
131
  griptape_nodes/retained_mode/managers/config_manager.py,sha256=WfzvFDPyboHgsCMpVGER6Ar1OHyPD_827LQx9xaUsMM,25573
132
132
  griptape_nodes/retained_mode/managers/context_manager.py,sha256=eb44_CAZhCg2iYIoodlAPpYc67tG3sHyq9dPNoiq_1s,23031
133
133
  griptape_nodes/retained_mode/managers/engine_identity_manager.py,sha256=-31364A03kU0YmAx3nM7nHdWfKnkej5Cawt_Plbwa68,10526
134
- griptape_nodes/retained_mode/managers/event_manager.py,sha256=vXvbLJf7vM2cR6HfUTHyxwIASJe_2FRqk3-_HpPnoF0,13508
134
+ griptape_nodes/retained_mode/managers/event_manager.py,sha256=a1V5lGP7B0Ts3hDvkZfmk33oESFTLP4STPUAgIU_tZU,14383
135
135
  griptape_nodes/retained_mode/managers/flow_manager.py,sha256=YgBIPix-bFA_Htwtur83obXJWnCh5KQ7SLC1dtd0KNQ,192102
136
136
  griptape_nodes/retained_mode/managers/library_lifecycle/__init__.py,sha256=Iq79VxTdETiExBfFWXceJggDZqS6X3OkzXE9XwFclVw,1340
137
137
  griptape_nodes/retained_mode/managers/library_lifecycle/data_models.py,sha256=fvAP0VaYGPHYl_Kg3RL4gdJlpqya8UTvpP-C49r950k,6723
@@ -145,7 +145,7 @@ griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/packa
145
145
  griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py,sha256=XgG7whE74zWDxX1pOvhASW0pwjOei1EDLvIH19xdzT0,6117
146
146
  griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py,sha256=cCGr-MQ1RlVBiUTZepYEKdVhPgC4ebcYrmpv8rI3VeM,894
147
147
  griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py,sha256=K3UEBzAdCY9wphyBbLxDYP0Q43aYvhLZ_Pz7_SzcPec,443
148
- griptape_nodes/retained_mode/managers/library_manager.py,sha256=LVQLon6kQ3KOW5RUknJZEXHpTpkXvYRrCCFWLX_F8ks,101413
148
+ griptape_nodes/retained_mode/managers/library_manager.py,sha256=Q8paiZR-0tfGhu7ZIJF7ofM1i1qk510dMrRHshl8x0w,101266
149
149
  griptape_nodes/retained_mode/managers/mcp_manager.py,sha256=Ezmn5_48r4JWYe-tFGqmw9dXLvvTiO1rw9b4MNCkw0U,15955
150
150
  griptape_nodes/retained_mode/managers/model_manager.py,sha256=Qc_FiqIJQ_ZuL5Yb7WiHCgUngKlbbJ_dUo7E5Ten5_g,45036
151
151
  griptape_nodes/retained_mode/managers/node_manager.py,sha256=7LQF3pWpTsGnQlgDu-CCeAmMk4E2VC-Ti-HiUELCkjE,196136
@@ -165,7 +165,7 @@ griptape_nodes/retained_mode/managers/resource_types/os_resource.py,sha256=ImgkO
165
165
  griptape_nodes/retained_mode/managers/secrets_manager.py,sha256=2DU2002dgr3XipnAhmjqLXH82ZFb8wlGpTWX8pl4f7E,7722
166
166
  griptape_nodes/retained_mode/managers/session_manager.py,sha256=u3OEir9rjwG7GFM4MA5crKwcwq6F-lCUKlFzxlFU4co,14085
167
167
  griptape_nodes/retained_mode/managers/settings.py,sha256=rvWjqt82_k6fLFXXbLS_cAKNqb57_iHoVOkgZG9mnPU,9626
168
- griptape_nodes/retained_mode/managers/static_files_manager.py,sha256=dDeX1Z5cmviNPkEBkF2MWYryLacJOh0TTpu-t7oCHps,11283
168
+ griptape_nodes/retained_mode/managers/static_files_manager.py,sha256=zTwlvLDub5siwNIAysrtWGbls5zC2amMSP2m-M7W4v0,11170
169
169
  griptape_nodes/retained_mode/managers/sync_manager.py,sha256=quKrg3pGEmPcoQDm5IqLHEFW64UmS4OT6o27dD57pFg,21395
170
170
  griptape_nodes/retained_mode/managers/user_manager.py,sha256=JAOOKDhUfIbj0CJ5EHRBcplmxheQTzeogbvGO23VqXQ,4508
171
171
  griptape_nodes/retained_mode/managers/variable_manager.py,sha256=TnuqHSRK9Yiu_EtKxQksF9SyyQb72lbFQuTQZdpBxeE,24116
@@ -210,7 +210,7 @@ griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_re
210
210
  griptape_nodes/version_compatibility/workflow_versions/__init__.py,sha256=z5XDgkizoNByCXpyo34hfsJKFsWlOHbD6hgzfYH9ubc,52
211
211
  griptape_nodes/version_compatibility/workflow_versions/v0_7_0/__init__.py,sha256=IzPPmGK86h2swfGGTOHyVcBIlOng6SjgWQzlbf3ngmo,51
212
212
  griptape_nodes/version_compatibility/workflow_versions/v0_7_0/local_executor_argument_addition.py,sha256=Y8n1wzI5a-ZCHK5eiwtnnD3zF5lN-52R67rxYn0hxyI,2069
213
- griptape_nodes-0.62.0.dist-info/WHEEL,sha256=5w2T7AS2mz1-rW9CNagNYWRCaB0iQqBMYLwKdlgiR4Q,78
214
- griptape_nodes-0.62.0.dist-info/entry_points.txt,sha256=qvevqd3BVbAV5TcantnAm0ouqaqYKhsRO3pkFymWLWM,82
215
- griptape_nodes-0.62.0.dist-info/METADATA,sha256=5z55_o8pWHcrNCr-maOqq4snyiRkv8r0JBzxu65jiVg,5178
216
- griptape_nodes-0.62.0.dist-info/RECORD,,
213
+ griptape_nodes-0.62.2.dist-info/WHEEL,sha256=DpNsHFUm_gffZe1FgzmqwuqiuPC6Y-uBCzibcJcdupM,78
214
+ griptape_nodes-0.62.2.dist-info/entry_points.txt,sha256=qvevqd3BVbAV5TcantnAm0ouqaqYKhsRO3pkFymWLWM,82
215
+ griptape_nodes-0.62.2.dist-info/METADATA,sha256=8482-2cbil_dFZHCWt1hShyQCmYZzHV94F5FEsZ9HwM,5178
216
+ griptape_nodes-0.62.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.9.7
2
+ Generator: uv 0.9.8
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any