griptape-nodes 0.37.1__py3-none-any.whl → 0.38.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 +292 -132
- griptape_nodes/app/__init__.py +1 -6
- griptape_nodes/app/app.py +108 -76
- griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +80 -5
- griptape_nodes/drivers/storage/local_storage_driver.py +5 -1
- griptape_nodes/exe_types/core_types.py +84 -3
- griptape_nodes/exe_types/node_types.py +260 -50
- griptape_nodes/machines/node_resolution.py +2 -14
- griptape_nodes/retained_mode/events/agent_events.py +7 -0
- griptape_nodes/retained_mode/events/base_events.py +16 -0
- griptape_nodes/retained_mode/events/library_events.py +26 -0
- griptape_nodes/retained_mode/events/parameter_events.py +31 -0
- griptape_nodes/retained_mode/griptape_nodes.py +32 -0
- griptape_nodes/retained_mode/managers/agent_manager.py +25 -12
- griptape_nodes/retained_mode/managers/config_manager.py +37 -4
- griptape_nodes/retained_mode/managers/event_manager.py +15 -0
- griptape_nodes/retained_mode/managers/flow_manager.py +64 -61
- griptape_nodes/retained_mode/managers/library_manager.py +215 -45
- griptape_nodes/retained_mode/managers/node_manager.py +344 -147
- griptape_nodes/retained_mode/managers/operation_manager.py +6 -0
- griptape_nodes/retained_mode/managers/os_manager.py +6 -1
- griptape_nodes/retained_mode/managers/secrets_manager.py +7 -2
- griptape_nodes/retained_mode/managers/settings.py +2 -11
- griptape_nodes/retained_mode/managers/static_files_manager.py +12 -3
- griptape_nodes/retained_mode/managers/version_compatibility_manager.py +105 -0
- griptape_nodes/retained_mode/managers/workflow_manager.py +4 -4
- griptape_nodes/updater/__init__.py +14 -8
- griptape_nodes/version_compatibility/__init__.py +1 -0
- griptape_nodes/version_compatibility/versions/__init__.py +1 -0
- griptape_nodes/version_compatibility/versions/v0_39_0/__init__.py +1 -0
- griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +77 -0
- {griptape_nodes-0.37.1.dist-info → griptape_nodes-0.38.0.dist-info}/METADATA +4 -1
- {griptape_nodes-0.37.1.dist-info → griptape_nodes-0.38.0.dist-info}/RECORD +36 -33
- griptape_nodes/app/app_websocket.py +0 -481
- griptape_nodes/app/nodes_api_socket_manager.py +0 -117
- {griptape_nodes-0.37.1.dist-info → griptape_nodes-0.38.0.dist-info}/WHEEL +0 -0
- {griptape_nodes-0.37.1.dist-info → griptape_nodes-0.38.0.dist-info}/entry_points.txt +0 -0
- {griptape_nodes-0.37.1.dist-info → griptape_nodes-0.38.0.dist-info}/licenses/LICENSE +0 -0
griptape_nodes/__init__.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"""Griptape Nodes package."""
|
|
2
|
-
# ruff: noqa: S603, S607
|
|
3
2
|
|
|
4
3
|
from rich.console import Console
|
|
5
4
|
|
|
@@ -14,6 +13,7 @@ with console.status("Loading Griptape Nodes...") as status:
|
|
|
14
13
|
import sys
|
|
15
14
|
import tarfile
|
|
16
15
|
import tempfile
|
|
16
|
+
from dataclasses import dataclass
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import Any, Literal
|
|
19
19
|
|
|
@@ -27,7 +27,8 @@ with console.status("Loading Griptape Nodes...") as status:
|
|
|
27
27
|
from xdg_base_dirs import xdg_config_home, xdg_data_home
|
|
28
28
|
|
|
29
29
|
from griptape_nodes.app import start_app
|
|
30
|
-
from griptape_nodes.
|
|
30
|
+
from griptape_nodes.drivers.storage.griptape_cloud_storage_driver import GriptapeCloudStorageDriver
|
|
31
|
+
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes, engine_version
|
|
31
32
|
from griptape_nodes.retained_mode.managers.config_manager import ConfigManager
|
|
32
33
|
from griptape_nodes.retained_mode.managers.os_manager import OSManager
|
|
33
34
|
from griptape_nodes.retained_mode.managers.secrets_manager import SecretsManager
|
|
@@ -48,12 +49,31 @@ GT_CLOUD_BASE_URL = os.getenv("GT_CLOUD_BASE_URL", "https://cloud.griptape.ai")
|
|
|
48
49
|
ENV_WORKSPACE_DIRECTORY = os.getenv("GTN_WORKSPACE_DIRECTORY")
|
|
49
50
|
ENV_API_KEY = os.getenv("GTN_API_KEY")
|
|
50
51
|
ENV_STORAGE_BACKEND = os.getenv("GTN_STORAGE_BACKEND")
|
|
51
|
-
ENV_STORAGE_BACKEND_BUCKET_ID = os.getenv("GTN_STORAGE_BACKEND_BUCKET_ID")
|
|
52
52
|
ENV_REGISTER_ADVANCED_LIBRARY = (
|
|
53
53
|
os.getenv("GTN_REGISTER_ADVANCED_LIBRARY", "false").lower() == "true"
|
|
54
54
|
if os.getenv("GTN_REGISTER_ADVANCED_LIBRARY") is not None
|
|
55
55
|
else None
|
|
56
56
|
)
|
|
57
|
+
ENV_LIBRARIES_SYNC = (
|
|
58
|
+
os.getenv("GTN_LIBRARIES_SYNC", "false").lower() == "true" if os.getenv("GTN_LIBRARIES_SYNC") is not None else None
|
|
59
|
+
)
|
|
60
|
+
ENV_GTN_BUCKET_NAME = os.getenv("GTN_BUCKET_NAME")
|
|
61
|
+
ENV_LIBRARIES_BASE_DIR = os.getenv("GTN_LIBRARIES_BASE_DIR", str(DATA_DIR / "libraries"))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass
|
|
65
|
+
class InitConfig:
|
|
66
|
+
"""Configuration for initialization."""
|
|
67
|
+
|
|
68
|
+
interactive: bool = True
|
|
69
|
+
workspace_directory: str | None = None
|
|
70
|
+
api_key: str | None = None
|
|
71
|
+
storage_backend: str | None = None
|
|
72
|
+
register_advanced_library: bool | None = None
|
|
73
|
+
config_values: dict[str, Any] | None = None
|
|
74
|
+
secret_values: dict[str, str] | None = None
|
|
75
|
+
libraries_sync: bool | None = None
|
|
76
|
+
bucket_name: str | None = None
|
|
57
77
|
|
|
58
78
|
|
|
59
79
|
config_manager = ConfigManager()
|
|
@@ -75,60 +95,92 @@ def main() -> None:
|
|
|
75
95
|
_process_args(args)
|
|
76
96
|
|
|
77
97
|
|
|
78
|
-
def _run_init(
|
|
79
|
-
*,
|
|
80
|
-
interactive: bool = True,
|
|
81
|
-
workspace_directory: str | None = None,
|
|
82
|
-
api_key: str | None = None,
|
|
83
|
-
storage_backend: str | None = None,
|
|
84
|
-
storage_backend_bucket_id: str | None = None,
|
|
85
|
-
register_advanced_library: bool | None = None,
|
|
86
|
-
config_values: dict[str, Any] | None = None,
|
|
87
|
-
secret_values: dict[str, str] | None = None,
|
|
88
|
-
) -> None:
|
|
98
|
+
def _run_init(config: InitConfig) -> None:
|
|
89
99
|
"""Runs through the engine init steps.
|
|
90
100
|
|
|
91
101
|
Args:
|
|
92
|
-
|
|
93
|
-
workspace_directory (str | None): The workspace directory to set.
|
|
94
|
-
api_key (str | None): The API key to set.
|
|
95
|
-
storage_backend (str | None): The storage backend to set.
|
|
96
|
-
storage_backend_bucket_id (str | None): The storage backend bucket ID to set.
|
|
97
|
-
register_advanced_library (bool | None): Whether to register the advanced library.
|
|
98
|
-
config_values (dict[str, any] | None): Arbitrary config key-value pairs to set.
|
|
99
|
-
secret_values (dict[str, str] | None): Arbitrary secret key-value pairs to set.
|
|
102
|
+
config: Initialization configuration.
|
|
100
103
|
"""
|
|
101
104
|
__init_system_config()
|
|
102
105
|
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
# Run configuration flow
|
|
107
|
+
_run_init_configuration(config)
|
|
108
|
+
|
|
109
|
+
# Sync libraries
|
|
110
|
+
if config.libraries_sync is not False:
|
|
111
|
+
_sync_libraries()
|
|
112
|
+
|
|
113
|
+
console.print("[bold green]Initialization complete![/bold green]")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _handle_api_key_config(config: InitConfig) -> str | None:
|
|
117
|
+
"""Handle API key configuration step."""
|
|
118
|
+
api_key = config.api_key
|
|
119
|
+
|
|
120
|
+
if config.interactive:
|
|
105
121
|
api_key = _prompt_for_api_key(default_api_key=api_key)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
|
|
123
|
+
if api_key is not None:
|
|
124
|
+
secrets_manager.set_secret("GT_CLOUD_API_KEY", api_key)
|
|
125
|
+
console.print("[bold green]Griptape API Key set")
|
|
126
|
+
|
|
127
|
+
return api_key
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _handle_workspace_config(config: InitConfig) -> str | None:
|
|
131
|
+
"""Handle workspace directory configuration step."""
|
|
132
|
+
workspace_directory = config.workspace_directory
|
|
133
|
+
|
|
134
|
+
if config.interactive:
|
|
135
|
+
workspace_directory = _prompt_for_workspace(default_workspace_directory=workspace_directory)
|
|
115
136
|
|
|
116
137
|
if workspace_directory is not None:
|
|
117
138
|
config_manager.set_config_value("workspace_directory", workspace_directory)
|
|
118
139
|
console.print(f"[bold green]Workspace directory set to: {workspace_directory}[/bold green]")
|
|
119
140
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
141
|
+
return workspace_directory
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _handle_storage_backend_config(config: InitConfig) -> str | None:
|
|
145
|
+
"""Handle storage backend configuration step."""
|
|
146
|
+
storage_backend = config.storage_backend
|
|
147
|
+
|
|
148
|
+
if config.interactive:
|
|
149
|
+
storage_backend = _prompt_for_storage_backend(default_storage_backend=storage_backend)
|
|
123
150
|
|
|
124
151
|
if storage_backend is not None:
|
|
125
152
|
config_manager.set_config_value("storage_backend", storage_backend)
|
|
126
153
|
console.print(f"[bold green]Storage backend set to: {storage_backend}")
|
|
127
154
|
|
|
155
|
+
return storage_backend
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _handle_bucket_config(config: InitConfig, storage_backend: str | None) -> str | None:
|
|
159
|
+
"""Handle bucket configuration step (depends on API key and storage backend)."""
|
|
160
|
+
storage_backend_bucket_id = None
|
|
161
|
+
|
|
162
|
+
if storage_backend == "gtc":
|
|
163
|
+
if config.interactive:
|
|
164
|
+
storage_backend_bucket_id = _prompt_for_gtc_bucket_name(default_bucket_name=config.bucket_name)
|
|
165
|
+
elif config.bucket_name is not None:
|
|
166
|
+
storage_backend_bucket_id = _get_or_create_bucket_id(config.bucket_name)
|
|
167
|
+
|
|
128
168
|
if storage_backend_bucket_id is not None:
|
|
129
169
|
secrets_manager.set_secret("GT_CLOUD_BUCKET_ID", storage_backend_bucket_id)
|
|
130
170
|
console.print(f"[bold green]Storage backend bucket ID set to: {storage_backend_bucket_id}[/bold green]")
|
|
131
171
|
|
|
172
|
+
return storage_backend_bucket_id
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _handle_advanced_library_config(config: InitConfig) -> bool | None:
|
|
176
|
+
"""Handle advanced library configuration step."""
|
|
177
|
+
register_advanced_library = config.register_advanced_library
|
|
178
|
+
|
|
179
|
+
if config.interactive:
|
|
180
|
+
register_advanced_library = _prompt_for_advanced_media_library(
|
|
181
|
+
default_prompt_for_advanced_media_library=register_advanced_library
|
|
182
|
+
)
|
|
183
|
+
|
|
132
184
|
if register_advanced_library is not None:
|
|
133
185
|
libraries_to_register = __build_libraries_list(register_advanced_library=register_advanced_library)
|
|
134
186
|
config_manager.set_config_value(
|
|
@@ -136,20 +188,37 @@ def _run_init( # noqa: PLR0913, C901
|
|
|
136
188
|
)
|
|
137
189
|
console.print(f"[bold green]Libraries to register set to: {', '.join(libraries_to_register)}[/bold green]")
|
|
138
190
|
|
|
191
|
+
return register_advanced_library
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _handle_arbitrary_configs(config: InitConfig) -> None:
|
|
195
|
+
"""Handle arbitrary config and secret values."""
|
|
139
196
|
# Set arbitrary config values
|
|
140
|
-
if config_values:
|
|
141
|
-
for key, value in config_values.items():
|
|
197
|
+
if config.config_values:
|
|
198
|
+
for key, value in config.config_values.items():
|
|
142
199
|
config_manager.set_config_value(key, value)
|
|
143
200
|
console.print(f"[bold green]Config '{key}' set to: {value}[/bold green]")
|
|
144
201
|
|
|
145
202
|
# Set arbitrary secret values
|
|
146
|
-
if secret_values:
|
|
147
|
-
for key, value in secret_values.items():
|
|
203
|
+
if config.secret_values:
|
|
204
|
+
for key, value in config.secret_values.items():
|
|
148
205
|
secrets_manager.set_secret(key, value)
|
|
149
206
|
console.print(f"[bold green]Secret '{key}' set[/bold green]")
|
|
150
207
|
|
|
151
|
-
|
|
152
|
-
|
|
208
|
+
|
|
209
|
+
def _run_init_configuration(config: InitConfig) -> None:
|
|
210
|
+
"""Handle initialization with proper dependency ordering."""
|
|
211
|
+
_handle_api_key_config(config)
|
|
212
|
+
|
|
213
|
+
_handle_workspace_config(config)
|
|
214
|
+
|
|
215
|
+
storage_backend = _handle_storage_backend_config(config)
|
|
216
|
+
|
|
217
|
+
_handle_bucket_config(config, storage_backend)
|
|
218
|
+
|
|
219
|
+
_handle_advanced_library_config(config)
|
|
220
|
+
|
|
221
|
+
_handle_arbitrary_configs(config)
|
|
153
222
|
|
|
154
223
|
|
|
155
224
|
def _start_engine(*, no_update: bool = False) -> None:
|
|
@@ -162,14 +231,17 @@ def _start_engine(*, no_update: bool = False) -> None:
|
|
|
162
231
|
# Default init flow if there is no config directory
|
|
163
232
|
console.print("[bold green]Config directory not found. Initializing...[/bold green]")
|
|
164
233
|
_run_init(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
234
|
+
InitConfig(
|
|
235
|
+
workspace_directory=ENV_WORKSPACE_DIRECTORY,
|
|
236
|
+
api_key=ENV_API_KEY,
|
|
237
|
+
storage_backend=ENV_STORAGE_BACKEND,
|
|
238
|
+
register_advanced_library=ENV_REGISTER_ADVANCED_LIBRARY,
|
|
239
|
+
interactive=True,
|
|
240
|
+
config_values=None,
|
|
241
|
+
secret_values=None,
|
|
242
|
+
libraries_sync=ENV_LIBRARIES_SYNC,
|
|
243
|
+
bucket_name=ENV_GTN_BUCKET_NAME,
|
|
244
|
+
)
|
|
173
245
|
)
|
|
174
246
|
|
|
175
247
|
# Confusing double negation -- If `no_update` is set, we want to skip the update
|
|
@@ -218,15 +290,20 @@ def _get_args() -> argparse.Namespace:
|
|
|
218
290
|
default=ENV_STORAGE_BACKEND,
|
|
219
291
|
)
|
|
220
292
|
init_parser.add_argument(
|
|
221
|
-
"--
|
|
222
|
-
help="
|
|
223
|
-
default=
|
|
293
|
+
"--bucket-name",
|
|
294
|
+
help="Name for the bucket (existing or new) when using 'gtc' storage backend.",
|
|
295
|
+
default=ENV_GTN_BUCKET_NAME,
|
|
224
296
|
)
|
|
225
297
|
init_parser.add_argument(
|
|
226
298
|
"--register-advanced-library",
|
|
227
299
|
help="Install the Griptape Nodes Advanced Image Library.",
|
|
228
300
|
default=ENV_REGISTER_ADVANCED_LIBRARY,
|
|
229
301
|
)
|
|
302
|
+
init_parser.add_argument(
|
|
303
|
+
"--libraries-sync",
|
|
304
|
+
help="Sync the Griptape Nodes libraries.",
|
|
305
|
+
default=ENV_LIBRARIES_SYNC,
|
|
306
|
+
)
|
|
230
307
|
init_parser.add_argument(
|
|
231
308
|
"--no-interactive",
|
|
232
309
|
action="store_true",
|
|
@@ -270,14 +347,14 @@ def _get_args() -> argparse.Namespace:
|
|
|
270
347
|
self_subparsers.add_parser("uninstall", help="Uninstall the CLI.")
|
|
271
348
|
self_subparsers.add_parser("version", help="Print the CLI version.")
|
|
272
349
|
|
|
273
|
-
#
|
|
274
|
-
|
|
275
|
-
|
|
350
|
+
# libraries
|
|
351
|
+
libraries_parser = subparsers.add_parser("libraries", help="Manage local libraries.")
|
|
352
|
+
libraries_subparsers = libraries_parser.add_subparsers(
|
|
276
353
|
dest="subcommand",
|
|
277
354
|
metavar="SUBCOMMAND",
|
|
278
355
|
required=True,
|
|
279
356
|
)
|
|
280
|
-
|
|
357
|
+
libraries_subparsers.add_parser("sync", help="Sync libraries with your current engine version.")
|
|
281
358
|
|
|
282
359
|
args = parser.parse_args()
|
|
283
360
|
|
|
@@ -364,66 +441,95 @@ Enter 'gtc' to use Griptape Cloud Bucket Storage, or press Return to accept the
|
|
|
364
441
|
return storage_backend
|
|
365
442
|
|
|
366
443
|
|
|
367
|
-
def
|
|
368
|
-
"""Fetches the list of Griptape Cloud
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
444
|
+
def _get_griptape_cloud_buckets_and_display_table() -> tuple[list[str], dict[str, str], Table]:
|
|
445
|
+
"""Fetches the list of Griptape Cloud Buckets from the API.
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
tuple: (bucket_names, name_to_id_mapping, display_table)
|
|
449
|
+
"""
|
|
450
|
+
api_key = secrets_manager.get_secret("GT_CLOUD_API_KEY")
|
|
451
|
+
bucket_names: list[str] = []
|
|
452
|
+
name_to_id: dict[str, str] = {}
|
|
453
|
+
|
|
454
|
+
if api_key is None:
|
|
455
|
+
msg = "Griptape Cloud API Key not found."
|
|
456
|
+
raise RuntimeError(msg)
|
|
374
457
|
|
|
375
458
|
table = Table(show_header=True, box=HEAVY_EDGE, show_lines=True, expand=True)
|
|
376
459
|
table.add_column("Bucket Name", style="green")
|
|
377
460
|
table.add_column("Bucket ID", style="green")
|
|
378
461
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
console.print(f"[red]Error fetching bucket IDs: {e}[/red]")
|
|
462
|
+
try:
|
|
463
|
+
buckets = GriptapeCloudStorageDriver.list_buckets(base_url=GT_CLOUD_BASE_URL, api_key=api_key)
|
|
464
|
+
for bucket in buckets:
|
|
465
|
+
bucket_name = bucket["name"]
|
|
466
|
+
bucket_id = bucket["bucket_id"]
|
|
467
|
+
bucket_names.append(bucket_name)
|
|
468
|
+
name_to_id[bucket_name] = bucket_id
|
|
469
|
+
table.add_row(bucket_name, bucket_id)
|
|
470
|
+
except RuntimeError as e:
|
|
471
|
+
console.print(f"[red]Error fetching buckets: {e}[/red]")
|
|
390
472
|
|
|
391
|
-
return
|
|
473
|
+
return bucket_names, name_to_id, table
|
|
392
474
|
|
|
393
475
|
|
|
394
|
-
def
|
|
395
|
-
"""Prompts the user for
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
"GT_CLOUD_BUCKET_ID", should_error_on_not_found=False
|
|
399
|
-
)
|
|
400
|
-
explainer = """[bold cyan]Storage Backend Bucket ID[/bold cyan]
|
|
401
|
-
Enter the Griptape Cloud Bucket ID to use for Griptape Cloud Storage. This is the location where Griptape Nodes will store your static files."""
|
|
476
|
+
def _prompt_for_gtc_bucket_name(default_bucket_name: str | None = None) -> str:
|
|
477
|
+
"""Prompts the user for a GTC bucket and returns the bucket ID."""
|
|
478
|
+
explainer = """[bold cyan]Storage Backend Bucket Selection[/bold cyan]
|
|
479
|
+
Select a Griptape Cloud Bucket to use for storage. This is the location where Griptape Nodes will store your static files."""
|
|
402
480
|
console.print(Panel(explainer, expand=False))
|
|
403
481
|
|
|
404
|
-
|
|
482
|
+
# Fetch existing buckets
|
|
483
|
+
bucket_names, name_to_id, table = _get_griptape_cloud_buckets_and_display_table()
|
|
484
|
+
if default_bucket_name is None:
|
|
485
|
+
# Default to "default" bucket if it exists
|
|
486
|
+
default_bucket_name = "default" if "default" in name_to_id else None
|
|
405
487
|
|
|
406
|
-
#
|
|
407
|
-
if len(
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
console.print(table)
|
|
488
|
+
# Display existing buckets if any
|
|
489
|
+
if len(bucket_names) > 0:
|
|
490
|
+
console.print(table)
|
|
491
|
+
console.print("\n[dim]You can enter an existing bucket by name, or enter a new name to create one.[/dim]")
|
|
412
492
|
|
|
413
493
|
while True:
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
494
|
+
# Prompt user for bucket name
|
|
495
|
+
selected_bucket_name = Prompt.ask(
|
|
496
|
+
"Enter bucket name",
|
|
497
|
+
default=default_bucket_name,
|
|
498
|
+
show_default=bool(default_bucket_name),
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
if selected_bucket_name:
|
|
502
|
+
# Check if it's an existing bucket
|
|
503
|
+
if selected_bucket_name in name_to_id:
|
|
504
|
+
return name_to_id[selected_bucket_name]
|
|
505
|
+
# It's a new bucket name, confirm creation
|
|
506
|
+
create_bucket = Confirm.ask(
|
|
507
|
+
f"Bucket '{selected_bucket_name}' doesn't exist. Create it?",
|
|
508
|
+
default=True,
|
|
420
509
|
)
|
|
421
|
-
if
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
console.print(f"[bold red]Error reading config file: {e}[/bold red]")
|
|
510
|
+
if create_bucket:
|
|
511
|
+
return __create_new_bucket(selected_bucket_name)
|
|
512
|
+
# If they don't want to create, continue the loop to ask again
|
|
425
513
|
|
|
426
|
-
|
|
514
|
+
|
|
515
|
+
def _get_or_create_bucket_id(bucket_name: str) -> str:
|
|
516
|
+
"""Gets the bucket ID for an existing bucket or creates a new one.
|
|
517
|
+
|
|
518
|
+
Args:
|
|
519
|
+
bucket_name: Name of the bucket to lookup or create
|
|
520
|
+
|
|
521
|
+
Returns:
|
|
522
|
+
The bucket ID
|
|
523
|
+
"""
|
|
524
|
+
# Fetch existing buckets to check if bucket_name exists
|
|
525
|
+
_, name_to_id, _ = _get_griptape_cloud_buckets_and_display_table()
|
|
526
|
+
|
|
527
|
+
# Check if bucket already exists
|
|
528
|
+
if bucket_name in name_to_id:
|
|
529
|
+
return name_to_id[bucket_name]
|
|
530
|
+
|
|
531
|
+
# Create the bucket
|
|
532
|
+
return __create_new_bucket(bucket_name)
|
|
427
533
|
|
|
428
534
|
|
|
429
535
|
def _prompt_for_advanced_media_library(*, default_prompt_for_advanced_media_library: bool | None = None) -> bool:
|
|
@@ -446,29 +552,40 @@ def __build_libraries_list(*, register_advanced_library: bool) -> list[str]:
|
|
|
446
552
|
"""Builds the list of libraries to register based on the advanced library setting."""
|
|
447
553
|
# TODO: https://github.com/griptape-ai/griptape-nodes/issues/929
|
|
448
554
|
libraries_key = "app_events.on_app_initialization_complete.libraries_to_register"
|
|
449
|
-
library_base_dir =
|
|
555
|
+
library_base_dir = Path(ENV_LIBRARIES_BASE_DIR)
|
|
450
556
|
|
|
451
557
|
current_libraries = config_manager.get_config_value(
|
|
452
558
|
libraries_key,
|
|
453
559
|
config_source="user_config",
|
|
454
560
|
default=config_manager.get_config_value(libraries_key, config_source="default_config", default=[]),
|
|
455
561
|
)
|
|
456
|
-
new_libraries = current_libraries
|
|
562
|
+
new_libraries = current_libraries.copy()
|
|
563
|
+
|
|
564
|
+
def _get_library_identifier(library_path: str) -> str:
|
|
565
|
+
"""Get the unique identifier for a library based on parent/filename."""
|
|
566
|
+
path = Path(library_path)
|
|
567
|
+
return f"{path.parent.name}/{path.name}"
|
|
568
|
+
|
|
569
|
+
# Create a set of current library identifiers for fast lookup
|
|
570
|
+
current_identifiers = {_get_library_identifier(lib) for lib in current_libraries}
|
|
457
571
|
|
|
458
572
|
default_library = str(library_base_dir / "griptape_nodes_library/griptape_nodes_library.json")
|
|
573
|
+
default_identifier = _get_library_identifier(default_library)
|
|
459
574
|
# If somehow the user removed the default library, add it back
|
|
460
|
-
if
|
|
461
|
-
|
|
575
|
+
if default_identifier not in current_identifiers:
|
|
576
|
+
new_libraries.append(default_library)
|
|
462
577
|
|
|
463
578
|
advanced_media_library = str(library_base_dir / "griptape_nodes_advanced_media_library/griptape_nodes_library.json")
|
|
579
|
+
advanced_identifier = _get_library_identifier(advanced_media_library)
|
|
464
580
|
if register_advanced_library:
|
|
465
581
|
# If the advanced media library is not registered, add it
|
|
466
|
-
if
|
|
582
|
+
if advanced_identifier not in current_identifiers:
|
|
467
583
|
new_libraries.append(advanced_media_library)
|
|
468
|
-
else:
|
|
584
|
+
else:
|
|
469
585
|
# If the advanced media library is registered, remove it
|
|
470
|
-
|
|
471
|
-
|
|
586
|
+
libraries_to_remove = [lib for lib in new_libraries if _get_library_identifier(lib) == advanced_identifier]
|
|
587
|
+
for lib in libraries_to_remove:
|
|
588
|
+
new_libraries.remove(lib)
|
|
472
589
|
|
|
473
590
|
return new_libraries
|
|
474
591
|
|
|
@@ -540,26 +657,26 @@ def _auto_update_self() -> None:
|
|
|
540
657
|
|
|
541
658
|
|
|
542
659
|
def _update_self() -> None:
|
|
543
|
-
"""Installs the latest release of the CLI *and* refreshes bundled
|
|
660
|
+
"""Installs the latest release of the CLI *and* refreshes bundled libraries."""
|
|
544
661
|
console.print("[bold green]Starting updater...[/bold green]")
|
|
545
662
|
|
|
546
663
|
os_manager.replace_process([sys.executable, "-m", "griptape_nodes.updater"])
|
|
547
664
|
|
|
548
665
|
|
|
549
|
-
def
|
|
550
|
-
"""Download and
|
|
666
|
+
def _sync_libraries() -> None:
|
|
667
|
+
"""Download and sync Griptape Nodes libraries, copying only directories from synced libraries."""
|
|
551
668
|
install_source, _ = __get_install_source()
|
|
552
|
-
# Unless we're installed from PyPi, grab
|
|
669
|
+
# Unless we're installed from PyPi, grab libraries from the 'latest' tag
|
|
553
670
|
if install_source == "pypi":
|
|
554
671
|
version = __get_current_version()
|
|
555
672
|
else:
|
|
556
673
|
version = LATEST_TAG
|
|
557
674
|
|
|
558
|
-
console.print(f"[bold cyan]Fetching Griptape Nodes
|
|
675
|
+
console.print(f"[bold cyan]Fetching Griptape Nodes libraries ({version})...[/bold cyan]")
|
|
559
676
|
|
|
560
677
|
tar_url = NODES_TARBALL_URL.format(tag=version)
|
|
561
678
|
console.print(f"[green]Downloading from {tar_url}[/green]")
|
|
562
|
-
dest_nodes =
|
|
679
|
+
dest_nodes = Path(ENV_LIBRARIES_BASE_DIR)
|
|
563
680
|
|
|
564
681
|
with tempfile.TemporaryDirectory() as tmp:
|
|
565
682
|
tar_path = Path(tmp) / "nodes.tar.gz"
|
|
@@ -569,7 +686,7 @@ def _sync_assets() -> None:
|
|
|
569
686
|
try:
|
|
570
687
|
r.raise_for_status()
|
|
571
688
|
except httpx.HTTPStatusError as e:
|
|
572
|
-
console.print(f"[red]Error fetching
|
|
689
|
+
console.print(f"[red]Error fetching libraries: {e}[/red]")
|
|
573
690
|
return
|
|
574
691
|
task = progress.add_task("[green]Downloading...", total=int(r.headers.get("Content-Length", 0)))
|
|
575
692
|
with tar_path.open("wb") as f:
|
|
@@ -585,12 +702,26 @@ def _sync_assets() -> None:
|
|
|
585
702
|
extracted_root = next(Path(tmp).glob("griptape-nodes-*"))
|
|
586
703
|
extracted_libs = extracted_root / "libraries"
|
|
587
704
|
|
|
588
|
-
#
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
705
|
+
# Copy directories from synced libraries without removing existing content
|
|
706
|
+
dest_nodes.mkdir(parents=True, exist_ok=True)
|
|
707
|
+
|
|
708
|
+
for library_dir in extracted_libs.iterdir():
|
|
709
|
+
if library_dir.is_dir():
|
|
710
|
+
dest_library_dir = dest_nodes / library_dir.name
|
|
711
|
+
if dest_library_dir.exists():
|
|
712
|
+
shutil.rmtree(dest_library_dir)
|
|
713
|
+
shutil.copytree(library_dir, dest_library_dir)
|
|
714
|
+
console.print(f"[green]Synced library: {library_dir.name}[/green]")
|
|
715
|
+
|
|
716
|
+
# Re-initialize all libraries from config
|
|
717
|
+
console.print("[bold cyan]Initializing libraries...[/bold cyan]")
|
|
718
|
+
try:
|
|
719
|
+
GriptapeNodes.LibraryManager().load_all_libraries_from_config()
|
|
720
|
+
console.print("[bold green]Libraries Initialized successfully.[/bold green]")
|
|
721
|
+
except Exception as e:
|
|
722
|
+
console.print(f"[red]Error initializing libraries: {e}[/red]")
|
|
592
723
|
|
|
593
|
-
console.print("[bold green]
|
|
724
|
+
console.print("[bold green]Libraries synced.[/bold green]")
|
|
594
725
|
|
|
595
726
|
|
|
596
727
|
def _print_current_version() -> None:
|
|
@@ -702,14 +833,17 @@ def _process_args(args: argparse.Namespace) -> None: # noqa: C901, PLR0912
|
|
|
702
833
|
secret_values = _parse_key_value_pairs(getattr(args, "secret", None))
|
|
703
834
|
|
|
704
835
|
_run_init(
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
836
|
+
InitConfig(
|
|
837
|
+
interactive=not args.no_interactive,
|
|
838
|
+
workspace_directory=args.workspace_directory,
|
|
839
|
+
api_key=args.api_key,
|
|
840
|
+
storage_backend=args.storage_backend,
|
|
841
|
+
register_advanced_library=args.register_advanced_library,
|
|
842
|
+
config_values=config_values,
|
|
843
|
+
secret_values=secret_values,
|
|
844
|
+
libraries_sync=args.libraries_sync,
|
|
845
|
+
bucket_name=args.bucket_name,
|
|
846
|
+
)
|
|
713
847
|
)
|
|
714
848
|
elif args.command == "engine":
|
|
715
849
|
_start_engine(no_update=args.no_update)
|
|
@@ -727,9 +861,9 @@ def _process_args(args: argparse.Namespace) -> None: # noqa: C901, PLR0912
|
|
|
727
861
|
_uninstall_self()
|
|
728
862
|
elif args.subcommand == "version":
|
|
729
863
|
_print_current_version()
|
|
730
|
-
elif args.command == "
|
|
864
|
+
elif args.command == "libraries":
|
|
731
865
|
if args.subcommand == "sync":
|
|
732
|
-
|
|
866
|
+
_sync_libraries()
|
|
733
867
|
else:
|
|
734
868
|
msg = f"Unknown command: {args.command}"
|
|
735
869
|
raise ValueError(msg)
|
|
@@ -779,5 +913,31 @@ def __init_system_config() -> None:
|
|
|
779
913
|
file.write(file_name[1])
|
|
780
914
|
|
|
781
915
|
|
|
916
|
+
def __create_new_bucket(bucket_name: str) -> str:
|
|
917
|
+
"""Create a new Griptape Cloud bucket.
|
|
918
|
+
|
|
919
|
+
Args:
|
|
920
|
+
bucket_name: Name for the bucket
|
|
921
|
+
|
|
922
|
+
Returns:
|
|
923
|
+
The bucket ID of the created bucket.
|
|
924
|
+
"""
|
|
925
|
+
api_key = secrets_manager.get_secret("GT_CLOUD_API_KEY")
|
|
926
|
+
if api_key is None:
|
|
927
|
+
msg = "GT_CLOUD_API_KEY secret is required to create a bucket."
|
|
928
|
+
raise ValueError(msg)
|
|
929
|
+
|
|
930
|
+
try:
|
|
931
|
+
bucket_id = GriptapeCloudStorageDriver.create_bucket(
|
|
932
|
+
bucket_name=bucket_name, base_url=GT_CLOUD_BASE_URL, api_key=api_key
|
|
933
|
+
)
|
|
934
|
+
except Exception as e:
|
|
935
|
+
console.print(f"[bold red]Failed to create bucket: {e}[/bold red]")
|
|
936
|
+
raise
|
|
937
|
+
else:
|
|
938
|
+
console.print(f"[bold green]Successfully created bucket '{bucket_name}' with ID: {bucket_id}[/bold green]")
|
|
939
|
+
return bucket_id
|
|
940
|
+
|
|
941
|
+
|
|
782
942
|
if __name__ == "__main__":
|
|
783
943
|
main()
|
griptape_nodes/app/__init__.py
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
"""App package."""
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
if os.getenv("GTN_USE_WEBSOCKETS", "true").lower() == "true":
|
|
6
|
-
from griptape_nodes.app.app_websocket import start_app
|
|
7
|
-
else:
|
|
8
|
-
from griptape_nodes.app.app import start_app
|
|
3
|
+
from griptape_nodes.app.app import start_app
|
|
9
4
|
|
|
10
5
|
__all__ = ["start_app"]
|