griptape-nodes 0.55.1__py3-none-any.whl → 0.56.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. griptape_nodes/app/app.py +10 -15
  2. griptape_nodes/app/watch.py +35 -67
  3. griptape_nodes/bootstrap/utils/__init__.py +1 -0
  4. griptape_nodes/bootstrap/utils/python_subprocess_executor.py +122 -0
  5. griptape_nodes/bootstrap/workflow_executors/local_session_workflow_executor.py +418 -0
  6. griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +37 -8
  7. griptape_nodes/bootstrap/workflow_executors/subprocess_workflow_executor.py +326 -0
  8. griptape_nodes/bootstrap/workflow_executors/utils/__init__.py +1 -0
  9. griptape_nodes/bootstrap/workflow_executors/utils/subprocess_script.py +51 -0
  10. griptape_nodes/bootstrap/workflow_publishers/__init__.py +1 -0
  11. griptape_nodes/bootstrap/workflow_publishers/local_workflow_publisher.py +43 -0
  12. griptape_nodes/bootstrap/workflow_publishers/subprocess_workflow_publisher.py +84 -0
  13. griptape_nodes/bootstrap/workflow_publishers/utils/__init__.py +1 -0
  14. griptape_nodes/bootstrap/workflow_publishers/utils/subprocess_script.py +54 -0
  15. griptape_nodes/cli/commands/engine.py +4 -15
  16. griptape_nodes/cli/commands/init.py +88 -0
  17. griptape_nodes/cli/commands/models.py +2 -0
  18. griptape_nodes/cli/main.py +6 -1
  19. griptape_nodes/cli/shared.py +1 -0
  20. griptape_nodes/exe_types/core_types.py +130 -0
  21. griptape_nodes/exe_types/node_types.py +125 -13
  22. griptape_nodes/machines/control_flow.py +10 -0
  23. griptape_nodes/machines/dag_builder.py +21 -2
  24. griptape_nodes/machines/parallel_resolution.py +25 -10
  25. griptape_nodes/node_library/workflow_registry.py +73 -3
  26. griptape_nodes/retained_mode/events/agent_events.py +2 -0
  27. griptape_nodes/retained_mode/events/base_events.py +18 -17
  28. griptape_nodes/retained_mode/events/execution_events.py +15 -3
  29. griptape_nodes/retained_mode/events/flow_events.py +63 -7
  30. griptape_nodes/retained_mode/events/mcp_events.py +363 -0
  31. griptape_nodes/retained_mode/events/node_events.py +3 -4
  32. griptape_nodes/retained_mode/events/resource_events.py +290 -0
  33. griptape_nodes/retained_mode/events/workflow_events.py +57 -2
  34. griptape_nodes/retained_mode/griptape_nodes.py +17 -1
  35. griptape_nodes/retained_mode/managers/agent_manager.py +67 -4
  36. griptape_nodes/retained_mode/managers/event_manager.py +31 -13
  37. griptape_nodes/retained_mode/managers/flow_manager.py +731 -33
  38. griptape_nodes/retained_mode/managers/library_manager.py +15 -23
  39. griptape_nodes/retained_mode/managers/mcp_manager.py +364 -0
  40. griptape_nodes/retained_mode/managers/model_manager.py +184 -83
  41. griptape_nodes/retained_mode/managers/node_manager.py +15 -4
  42. griptape_nodes/retained_mode/managers/os_manager.py +118 -1
  43. griptape_nodes/retained_mode/managers/resource_components/__init__.py +1 -0
  44. griptape_nodes/retained_mode/managers/resource_components/capability_field.py +41 -0
  45. griptape_nodes/retained_mode/managers/resource_components/comparator.py +18 -0
  46. griptape_nodes/retained_mode/managers/resource_components/resource_instance.py +236 -0
  47. griptape_nodes/retained_mode/managers/resource_components/resource_type.py +79 -0
  48. griptape_nodes/retained_mode/managers/resource_manager.py +306 -0
  49. griptape_nodes/retained_mode/managers/resource_types/__init__.py +1 -0
  50. griptape_nodes/retained_mode/managers/resource_types/cpu_resource.py +108 -0
  51. griptape_nodes/retained_mode/managers/resource_types/os_resource.py +87 -0
  52. griptape_nodes/retained_mode/managers/settings.py +45 -0
  53. griptape_nodes/retained_mode/managers/sync_manager.py +10 -3
  54. griptape_nodes/retained_mode/managers/workflow_manager.py +447 -263
  55. griptape_nodes/traits/multi_options.py +5 -1
  56. griptape_nodes/traits/options.py +10 -2
  57. {griptape_nodes-0.55.1.dist-info → griptape_nodes-0.56.1.dist-info}/METADATA +2 -2
  58. {griptape_nodes-0.55.1.dist-info → griptape_nodes-0.56.1.dist-info}/RECORD +60 -37
  59. {griptape_nodes-0.55.1.dist-info → griptape_nodes-0.56.1.dist-info}/WHEEL +1 -1
  60. {griptape_nodes-0.55.1.dist-info → griptape_nodes-0.56.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,363 @@
1
+ """MCP (Model Context Protocol) server management events."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any, TypedDict
5
+
6
+ from griptape_nodes.retained_mode.events.base_events import (
7
+ RequestPayload,
8
+ ResultPayloadFailure,
9
+ ResultPayloadSuccess,
10
+ WorkflowAlteredMixin,
11
+ WorkflowNotAlteredMixin,
12
+ )
13
+ from griptape_nodes.retained_mode.events.payload_registry import PayloadRegistry
14
+
15
+
16
+ # Type definitions for better clarity
17
+ class MCPServerConfig(TypedDict, total=False):
18
+ """Configuration for an MCP server."""
19
+
20
+ name: str
21
+ transport: str # Transport protocol type
22
+ enabled: bool
23
+ command: str | None # Process command for stdio transport
24
+ args: list[str] | None # Process arguments for stdio transport
25
+ env: dict[str, str] | None # Environment variables for stdio transport
26
+ cwd: str | None # Working directory for stdio transport
27
+ encoding: str # Text encoding for stdio transport
28
+ encoding_error_handler: str # Error handling strategy for stdio transport
29
+ url: str | None # Connection URL for HTTP-based transports
30
+ headers: dict[str, str] | None # HTTP headers for HTTP-based transports
31
+ timeout: float | None # Connection timeout for HTTP-based transports
32
+ sse_read_timeout: float | None # Read timeout for SSE transport
33
+ terminate_on_close: bool # Session termination behavior for streamable HTTP transport
34
+ description: str | None
35
+ capabilities: list[str] | None
36
+
37
+
38
+ class MCPServerCapability(TypedDict):
39
+ """Information about an MCP server capability."""
40
+
41
+ name: str
42
+ description: str | None
43
+ input_schema: dict[str, Any] | None # JSON schema for capability inputs
44
+ output_schema: dict[str, Any] | None # JSON schema for capability outputs
45
+
46
+
47
+ class MCPServerInfo(TypedDict, total=False):
48
+ """Information about an MCP server."""
49
+
50
+ name: str
51
+ version: str | None # Server version identifier
52
+ description: str | None # Human-readable server description
53
+ capabilities: list[str] | None # List of supported capability names
54
+
55
+
56
+ # MCP Server Management Events
57
+
58
+
59
+ # Capability Discovery Events
60
+ @dataclass
61
+ @PayloadRegistry.register
62
+ class DiscoverMCPServerCapabilitiesRequest(RequestPayload):
63
+ """Discover capabilities from a running MCP server.
64
+
65
+ Args:
66
+ name: The MCP server identifier to discover capabilities from
67
+ timeout: Maximum time to wait for server response in seconds
68
+ """
69
+
70
+ name: str
71
+ timeout: int = 30
72
+
73
+
74
+ @dataclass
75
+ @PayloadRegistry.register
76
+ class DiscoverMCPServerCapabilitiesResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
77
+ """MCP server capabilities discovered successfully."""
78
+
79
+ name: str
80
+ capabilities: list[str]
81
+ detailed_tools: list[MCPServerCapability] | None = None
82
+ server_info: MCPServerInfo | None = None
83
+
84
+
85
+ @dataclass
86
+ @PayloadRegistry.register
87
+ class DiscoverMCPServerCapabilitiesResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
88
+ """Failed to discover MCP server capabilities."""
89
+
90
+
91
+ @dataclass
92
+ @PayloadRegistry.register
93
+ class ListMCPServersRequest(RequestPayload):
94
+ """List all configured MCP servers.
95
+
96
+ Args:
97
+ include_disabled: Whether to include disabled servers in the results
98
+ """
99
+
100
+ include_disabled: bool = False
101
+
102
+
103
+ @dataclass
104
+ @PayloadRegistry.register
105
+ class ListMCPServersResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
106
+ """MCP servers listed successfully."""
107
+
108
+ servers: dict[str, MCPServerConfig]
109
+
110
+
111
+ @dataclass
112
+ @PayloadRegistry.register
113
+ class ListMCPServersResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
114
+ """Failed to list MCP servers."""
115
+
116
+
117
+ @dataclass
118
+ @PayloadRegistry.register
119
+ class GetMCPServerRequest(RequestPayload):
120
+ """Get configuration for a specific MCP server.
121
+
122
+ Args:
123
+ name: The unique identifier for the MCP server
124
+ """
125
+
126
+ name: str
127
+
128
+
129
+ @dataclass
130
+ @PayloadRegistry.register
131
+ class GetMCPServerResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
132
+ """MCP server configuration retrieved successfully."""
133
+
134
+ server_config: MCPServerConfig
135
+
136
+
137
+ @dataclass
138
+ @PayloadRegistry.register
139
+ class GetMCPServerResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
140
+ """Failed to get MCP server configuration."""
141
+
142
+
143
+ @dataclass
144
+ @PayloadRegistry.register
145
+ class CreateMCPServerRequest(RequestPayload):
146
+ """Create a new MCP server configuration.
147
+
148
+ Args:
149
+ name: Unique identifier for the server
150
+ transport: Transport protocol type
151
+ command: Process command to start the server (required for stdio transport)
152
+ args: Process arguments to pass to the command (stdio transport)
153
+ env: Environment variables for the server process (stdio transport)
154
+ cwd: Working directory for the server process (stdio transport)
155
+ encoding: Text encoding for stdio communication
156
+ encoding_error_handler: Encoding error handling strategy for stdio
157
+ url: Connection URL for HTTP-based transports
158
+ headers: HTTP headers for HTTP-based connections
159
+ timeout: Connection timeout in seconds
160
+ sse_read_timeout: SSE read timeout in seconds
161
+ terminate_on_close: Session termination behavior for streamable HTTP transport
162
+ description: Optional description of the server
163
+ capabilities: List of server capabilities
164
+ enabled: Whether the server is enabled by default
165
+ """
166
+
167
+ name: str
168
+ transport: str = "stdio"
169
+ enabled: bool = True
170
+
171
+ # StdioConnection fields
172
+ command: str | None = None
173
+ args: list[str] | None = None
174
+ env: dict[str, str] | None = None
175
+ cwd: str | None = None
176
+ encoding: str = "utf-8"
177
+ encoding_error_handler: str = "strict"
178
+
179
+ # HTTP-based connection fields
180
+ url: str | None = None
181
+ headers: dict[str, str] | None = None
182
+ timeout: float | None = None
183
+ sse_read_timeout: float | None = None
184
+ terminate_on_close: bool = True
185
+
186
+ # Common fields
187
+ description: str | None = None
188
+ capabilities: list[str] | None = None
189
+
190
+
191
+ @dataclass
192
+ @PayloadRegistry.register
193
+ class CreateMCPServerResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
194
+ """MCP server created successfully."""
195
+
196
+ name: str
197
+
198
+
199
+ @dataclass
200
+ @PayloadRegistry.register
201
+ class CreateMCPServerResultFailure(WorkflowAlteredMixin, ResultPayloadFailure):
202
+ """Failed to create MCP server."""
203
+
204
+
205
+ @dataclass
206
+ @PayloadRegistry.register
207
+ class UpdateMCPServerRequest(RequestPayload):
208
+ """Update an existing MCP server configuration.
209
+
210
+ Args:
211
+ name: The unique identifier for the MCP server
212
+ new_name: Updated display name for the server
213
+ transport: Updated transport protocol type
214
+ command: Updated process command to start the server (stdio transport)
215
+ args: Updated process arguments to pass to the command (stdio transport)
216
+ env: Updated environment variables for the server process (stdio transport)
217
+ cwd: Updated working directory for the server process (stdio transport)
218
+ encoding: Updated text encoding for stdio communication
219
+ encoding_error_handler: Updated encoding error handling strategy for stdio
220
+ url: Updated connection URL for HTTP-based transports
221
+ headers: Updated HTTP headers for HTTP-based connections
222
+ timeout: Updated connection timeout in seconds
223
+ sse_read_timeout: Updated SSE read timeout in seconds
224
+ terminate_on_close: Updated session termination behavior for streamable HTTP transport
225
+ description: Updated description of the server
226
+ capabilities: Updated list of server capabilities
227
+ """
228
+
229
+ name: str
230
+ new_name: str | None = None
231
+ transport: str | None = None
232
+ enabled: bool | None = None
233
+
234
+ # StdioConnection fields
235
+ command: str | None = None
236
+ args: list[str] | None = None
237
+ env: dict[str, str] | None = None
238
+ cwd: str | None = None
239
+ encoding: str | None = None
240
+ encoding_error_handler: str | None = None
241
+
242
+ # HTTP-based connection fields
243
+ url: str | None = None
244
+ headers: dict[str, str] | None = None
245
+ timeout: float | None = None
246
+ sse_read_timeout: float | None = None
247
+ terminate_on_close: bool | None = None
248
+
249
+ # Common fields
250
+ description: str | None = None
251
+ capabilities: list[str] | None = None
252
+
253
+
254
+ @dataclass
255
+ @PayloadRegistry.register
256
+ class UpdateMCPServerResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
257
+ """MCP server updated successfully."""
258
+
259
+ name: str
260
+
261
+
262
+ @dataclass
263
+ @PayloadRegistry.register
264
+ class UpdateMCPServerResultFailure(WorkflowAlteredMixin, ResultPayloadFailure):
265
+ """Failed to update MCP server."""
266
+
267
+
268
+ @dataclass
269
+ @PayloadRegistry.register
270
+ class DeleteMCPServerRequest(RequestPayload):
271
+ """Delete an MCP server configuration.
272
+
273
+ Args:
274
+ name: The unique identifier for the MCP server to delete
275
+ """
276
+
277
+ name: str
278
+
279
+
280
+ @dataclass
281
+ @PayloadRegistry.register
282
+ class DeleteMCPServerResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
283
+ """MCP server deleted successfully."""
284
+
285
+ name: str
286
+
287
+
288
+ @dataclass
289
+ @PayloadRegistry.register
290
+ class DeleteMCPServerResultFailure(WorkflowAlteredMixin, ResultPayloadFailure):
291
+ """Failed to delete MCP server."""
292
+
293
+
294
+ @dataclass
295
+ @PayloadRegistry.register
296
+ class EnableMCPServerRequest(RequestPayload):
297
+ """Enable an MCP server.
298
+
299
+ Args:
300
+ name: The unique identifier for the MCP server to enable
301
+ """
302
+
303
+ name: str
304
+
305
+
306
+ @dataclass
307
+ @PayloadRegistry.register
308
+ class EnableMCPServerResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
309
+ """MCP server enabled successfully."""
310
+
311
+ name: str
312
+
313
+
314
+ @dataclass
315
+ @PayloadRegistry.register
316
+ class EnableMCPServerResultFailure(WorkflowAlteredMixin, ResultPayloadFailure):
317
+ """Failed to enable MCP server."""
318
+
319
+
320
+ @dataclass
321
+ @PayloadRegistry.register
322
+ class DisableMCPServerRequest(RequestPayload):
323
+ """Disable an MCP server.
324
+
325
+ Args:
326
+ name: The unique identifier for the MCP server to disable
327
+ """
328
+
329
+ name: str
330
+
331
+
332
+ @dataclass
333
+ @PayloadRegistry.register
334
+ class DisableMCPServerResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
335
+ """MCP server disabled successfully."""
336
+
337
+ name: str
338
+
339
+
340
+ @dataclass
341
+ @PayloadRegistry.register
342
+ class DisableMCPServerResultFailure(WorkflowAlteredMixin, ResultPayloadFailure):
343
+ """Failed to disable MCP server."""
344
+
345
+
346
+ @dataclass
347
+ @PayloadRegistry.register
348
+ class GetEnabledMCPServersRequest(RequestPayload):
349
+ """Get all enabled MCP servers."""
350
+
351
+
352
+ @dataclass
353
+ @PayloadRegistry.register
354
+ class GetEnabledMCPServersResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
355
+ """Enabled MCP servers retrieved successfully."""
356
+
357
+ servers: dict[str, MCPServerConfig]
358
+
359
+
360
+ @dataclass
361
+ @PayloadRegistry.register
362
+ class GetEnabledMCPServersResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
363
+ """Failed to get enabled MCP servers."""
@@ -4,8 +4,7 @@ from typing import Any, NamedTuple, NewType
4
4
  from uuid import uuid4
5
5
 
6
6
  from griptape_nodes.exe_types.core_types import NodeMessagePayload
7
- from griptape_nodes.exe_types.node_types import NodeResolutionState
8
- from griptape_nodes.node_library.library_registry import LibraryNameAndVersion
7
+ from griptape_nodes.exe_types.node_types import NodeDependencies, NodeResolutionState
9
8
  from griptape_nodes.retained_mode.events.base_events import (
10
9
  RequestPayload,
11
10
  ResultPayloadFailure,
@@ -409,7 +408,7 @@ class SerializedNodeCommands:
409
408
  Attributes:
410
409
  create_node_command (CreateNodeRequest): The command to create the node.
411
410
  element_modification_commands (list[RequestPayload]): A list of commands to create or modify the elements (including Parameters) of the node.
412
- node_library_details (LibraryNameAndVersion): Details of the library and version used by the node.
411
+ node_dependencies (NodeDependencies): Dependencies that this node has on external resources (workflows, files, imports, libraries).
413
412
  node_uuid (NodeUUID): The UUID of this particular node. During deserialization, this UUID will be used to correlate this node's instance
414
413
  with the connections and parameter values necessary. We cannot use node name because Griptape Nodes enforces unique names, and we cannot
415
414
  predict the name that will be selected upon instantiation. Similarly, the same serialized node may be deserialized multiple times, such
@@ -435,7 +434,7 @@ class SerializedNodeCommands:
435
434
 
436
435
  create_node_command: CreateNodeRequest
437
436
  element_modification_commands: list[RequestPayload]
438
- node_library_details: LibraryNameAndVersion
437
+ node_dependencies: NodeDependencies
439
438
  lock_node_command: SetLockNodeStateRequest | None = None
440
439
  node_uuid: NodeUUID = field(default_factory=lambda: SerializedNodeCommands.NodeUUID(str(uuid4())))
441
440
 
@@ -0,0 +1,290 @@
1
+ from dataclasses import dataclass
2
+ from typing import TYPE_CHECKING, Any
3
+
4
+ from griptape_nodes.retained_mode.events.base_events import (
5
+ RequestPayload,
6
+ ResultPayloadFailure,
7
+ ResultPayloadSuccess,
8
+ WorkflowNotAlteredMixin,
9
+ )
10
+ from griptape_nodes.retained_mode.events.payload_registry import PayloadRegistry
11
+
12
+ if TYPE_CHECKING:
13
+ from griptape_nodes.retained_mode.managers.resource_components.resource_instance import Requirements
14
+ from griptape_nodes.retained_mode.managers.resource_components.resource_type import ResourceType
15
+ from griptape_nodes.retained_mode.managers.resource_manager import ResourceStatus
16
+
17
+
18
+ # List Registered Resource Types Events
19
+ @dataclass
20
+ @PayloadRegistry.register
21
+ class ListRegisteredResourceTypesRequest(RequestPayload):
22
+ """List all registered resource types.
23
+
24
+ Use when: Discovering what types of resources are available for allocation
25
+ and management.
26
+ """
27
+
28
+
29
+ @dataclass
30
+ @PayloadRegistry.register
31
+ class ListRegisteredResourceTypesResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
32
+ """Registered resource types listed successfully."""
33
+
34
+ resource_type_names: list[str]
35
+
36
+
37
+ @dataclass
38
+ @PayloadRegistry.register
39
+ class ListRegisteredResourceTypesResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
40
+ """Registered resource types listing failed."""
41
+
42
+
43
+ # Register Resource Type Events
44
+ @dataclass
45
+ @PayloadRegistry.register
46
+ class RegisterResourceTypeRequest(RequestPayload):
47
+ """Register a new resource type handler.
48
+
49
+ Use when: Adding support for a new type of resource (GPU, CPU, Pipeline, etc.)
50
+ that the ResourceManager should be able to allocate and manage.
51
+
52
+ Args:
53
+ resource_type: The ResourceType instance to register
54
+ """
55
+
56
+ resource_type: "ResourceType"
57
+
58
+
59
+ @dataclass
60
+ @PayloadRegistry.register
61
+ class RegisterResourceTypeResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
62
+ """Resource type registered successfully."""
63
+
64
+
65
+ @dataclass
66
+ @PayloadRegistry.register
67
+ class RegisterResourceTypeResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
68
+ """Resource type registration failed. Common causes: resource type already registered, invalid resource type."""
69
+
70
+
71
+ # Create Resource Instance Events
72
+ @dataclass
73
+ @PayloadRegistry.register
74
+ class CreateResourceInstanceRequest(RequestPayload):
75
+ """Create a new resource instance.
76
+
77
+ Use when: Creating a new instance of a resource that can be tracked, locked,
78
+ and managed by the ResourceManager.
79
+
80
+ Args:
81
+ resource_type_name: The name of the resource type to create an instance of
82
+ capabilities: Dict of capabilities for the new instance
83
+ """
84
+
85
+ resource_type_name: str
86
+ capabilities: dict[str, Any]
87
+
88
+
89
+ @dataclass
90
+ @PayloadRegistry.register
91
+ class CreateResourceInstanceResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
92
+ """Resource instance created successfully."""
93
+
94
+ instance_id: str
95
+
96
+
97
+ @dataclass
98
+ @PayloadRegistry.register
99
+ class CreateResourceInstanceResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
100
+ """Resource instance creation failed. Common causes: invalid capabilities, resource creation error."""
101
+
102
+
103
+ # Free Resource Instance Events
104
+ @dataclass
105
+ @PayloadRegistry.register
106
+ class FreeResourceInstanceRequest(RequestPayload):
107
+ """Free a resource instance.
108
+
109
+ Use when: Permanently removing a resource instance from tracking and freeing
110
+ its resources.
111
+
112
+ Args:
113
+ instance_id: The ID of the instance to free
114
+ force_unlock: If True, force unlock locked instances. If False, raise exception for locked instances.
115
+ """
116
+
117
+ instance_id: str
118
+ force_unlock: bool = False
119
+
120
+
121
+ @dataclass
122
+ @PayloadRegistry.register
123
+ class FreeResourceInstanceResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
124
+ """Resource instance freed successfully."""
125
+
126
+
127
+ @dataclass
128
+ @PayloadRegistry.register
129
+ class FreeResourceInstanceResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
130
+ """Resource instance freeing failed. Common causes: instance not found, instance locked and force_unlock=False."""
131
+
132
+
133
+ # Acquire Resource Lock Events
134
+ @dataclass
135
+ @PayloadRegistry.register
136
+ class AcquireResourceInstanceLockRequest(RequestPayload):
137
+ """Acquire a lock on an existing resource instance.
138
+
139
+ Use when: Attempting to acquire exclusive access to a resource instance that
140
+ matches specific requirements.
141
+
142
+ Args:
143
+ owner_id: The ID of the entity requesting the lock
144
+ resource_type_name: The name of the resource type to acquire
145
+ requirements: Optional requirements the resource must satisfy
146
+ """
147
+
148
+ owner_id: str
149
+ resource_type_name: str
150
+ requirements: "Requirements | None" = None
151
+
152
+
153
+ @dataclass
154
+ @PayloadRegistry.register
155
+ class AcquireResourceInstanceLockResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
156
+ """Resource instance lock acquired successfully."""
157
+
158
+ instance_id: str
159
+
160
+
161
+ @dataclass
162
+ @PayloadRegistry.register
163
+ class AcquireResourceInstanceLockResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
164
+ """Resource instance lock acquisition failed. Common causes: no compatible instances available, all instances locked."""
165
+
166
+
167
+ # Release Resource Lock Events
168
+ @dataclass
169
+ @PayloadRegistry.register
170
+ class ReleaseResourceInstanceLockRequest(RequestPayload):
171
+ """Release a lock on a resource instance.
172
+
173
+ Use when: Releasing exclusive access to a resource instance that was
174
+ previously acquired.
175
+
176
+ Args:
177
+ instance_id: The ID of the resource instance to release
178
+ owner_id: The ID of the entity releasing the lock
179
+ """
180
+
181
+ instance_id: str
182
+ owner_id: str
183
+
184
+
185
+ @dataclass
186
+ @PayloadRegistry.register
187
+ class ReleaseResourceInstanceLockResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
188
+ """Resource instance lock released successfully."""
189
+
190
+
191
+ @dataclass
192
+ @PayloadRegistry.register
193
+ class ReleaseResourceInstanceLockResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
194
+ """Resource instance lock release failed. Common causes: instance not found, not locked by specified owner."""
195
+
196
+
197
+ # List Compatible Resource Instances Events
198
+ @dataclass
199
+ @PayloadRegistry.register
200
+ class ListCompatibleResourceInstancesRequest(RequestPayload):
201
+ """List resource instances compatible with requirements.
202
+
203
+ Use when: Discovering what resource instances are available that match
204
+ specific criteria, without acquiring locks.
205
+
206
+ Args:
207
+ resource_type_name: The name of the resource type to filter by
208
+ requirements: Optional requirements to match. If None, returns all instances of the type.
209
+ include_locked: If True, also include locked instances
210
+ """
211
+
212
+ resource_type_name: str
213
+ requirements: "Requirements | None" = None
214
+ include_locked: bool = False
215
+
216
+
217
+ @dataclass
218
+ @PayloadRegistry.register
219
+ class ListCompatibleResourceInstancesResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
220
+ """Compatible resource instances listed successfully."""
221
+
222
+ instance_ids: list[str]
223
+
224
+
225
+ @dataclass
226
+ @PayloadRegistry.register
227
+ class ListCompatibleResourceInstancesResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
228
+ """Compatible resource instances listing failed. Common causes: invalid resource type, invalid requirements."""
229
+
230
+
231
+ # Get Resource Instance Status Events
232
+ @dataclass
233
+ @PayloadRegistry.register
234
+ class GetResourceInstanceStatusRequest(RequestPayload):
235
+ """Get status information for a resource instance.
236
+
237
+ Use when: Checking the current state of a specific resource instance,
238
+ including capabilities and lock status.
239
+
240
+ Args:
241
+ instance_id: The ID of the instance to get status for
242
+ """
243
+
244
+ instance_id: str
245
+
246
+
247
+ @dataclass
248
+ @PayloadRegistry.register
249
+ class GetResourceInstanceStatusResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
250
+ """Resource instance status retrieved successfully."""
251
+
252
+ status: "ResourceStatus"
253
+
254
+
255
+ @dataclass
256
+ @PayloadRegistry.register
257
+ class GetResourceInstanceStatusResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
258
+ """Resource instance status retrieval failed. Common causes: instance not found."""
259
+
260
+
261
+ # List Resource Instances By Type Events
262
+ @dataclass
263
+ @PayloadRegistry.register
264
+ class ListResourceInstancesByTypeRequest(RequestPayload):
265
+ """List resource instances of a specific type.
266
+
267
+ Use when: Listing all instances of a particular resource type for
268
+ management or monitoring purposes.
269
+
270
+ Args:
271
+ resource_type_name: The name of the resource type to list instances for
272
+ include_locked: If True, also include locked instances
273
+ """
274
+
275
+ resource_type_name: str
276
+ include_locked: bool = True
277
+
278
+
279
+ @dataclass
280
+ @PayloadRegistry.register
281
+ class ListResourceInstancesByTypeResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
282
+ """Resource instances by type listed successfully."""
283
+
284
+ instance_ids: list[str]
285
+
286
+
287
+ @dataclass
288
+ @PayloadRegistry.register
289
+ class ListResourceInstancesByTypeResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
290
+ """Resource instances by type listing failed. Common causes: invalid resource type."""