agentscope-runtime 1.0.4a1__py3-none-any.whl → 1.0.5.post1__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 (79) hide show
  1. agentscope_runtime/adapters/agentscope/stream.py +2 -8
  2. agentscope_runtime/adapters/langgraph/stream.py +120 -70
  3. agentscope_runtime/adapters/ms_agent_framework/__init__.py +0 -0
  4. agentscope_runtime/adapters/ms_agent_framework/message.py +205 -0
  5. agentscope_runtime/adapters/ms_agent_framework/stream.py +418 -0
  6. agentscope_runtime/adapters/utils.py +6 -0
  7. agentscope_runtime/cli/commands/deploy.py +836 -1
  8. agentscope_runtime/cli/commands/stop.py +16 -0
  9. agentscope_runtime/common/container_clients/__init__.py +52 -0
  10. agentscope_runtime/common/container_clients/agentrun_client.py +6 -4
  11. agentscope_runtime/common/container_clients/boxlite_client.py +442 -0
  12. agentscope_runtime/common/container_clients/docker_client.py +0 -20
  13. agentscope_runtime/common/container_clients/fc_client.py +6 -4
  14. agentscope_runtime/common/container_clients/gvisor_client.py +38 -0
  15. agentscope_runtime/common/container_clients/knative_client.py +467 -0
  16. agentscope_runtime/common/utils/deprecation.py +164 -0
  17. agentscope_runtime/engine/__init__.py +4 -0
  18. agentscope_runtime/engine/app/agent_app.py +16 -4
  19. agentscope_runtime/engine/constant.py +1 -0
  20. agentscope_runtime/engine/deployers/__init__.py +34 -11
  21. agentscope_runtime/engine/deployers/adapter/__init__.py +8 -0
  22. agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +26 -51
  23. agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +23 -13
  24. agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +4 -201
  25. agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +152 -25
  26. agentscope_runtime/engine/deployers/adapter/agui/__init__.py +8 -0
  27. agentscope_runtime/engine/deployers/adapter/agui/agui_adapter_utils.py +652 -0
  28. agentscope_runtime/engine/deployers/adapter/agui/agui_protocol_adapter.py +225 -0
  29. agentscope_runtime/engine/deployers/agentrun_deployer.py +2 -2
  30. agentscope_runtime/engine/deployers/fc_deployer.py +1506 -0
  31. agentscope_runtime/engine/deployers/knative_deployer.py +290 -0
  32. agentscope_runtime/engine/deployers/pai_deployer.py +2335 -0
  33. agentscope_runtime/engine/deployers/utils/net_utils.py +37 -0
  34. agentscope_runtime/engine/deployers/utils/oss_utils.py +38 -0
  35. agentscope_runtime/engine/deployers/utils/package.py +46 -42
  36. agentscope_runtime/engine/helpers/agent_api_client.py +372 -0
  37. agentscope_runtime/engine/runner.py +13 -0
  38. agentscope_runtime/engine/schemas/agent_schemas.py +9 -3
  39. agentscope_runtime/engine/services/agent_state/__init__.py +7 -0
  40. agentscope_runtime/engine/services/memory/__init__.py +7 -0
  41. agentscope_runtime/engine/services/memory/redis_memory_service.py +15 -16
  42. agentscope_runtime/engine/services/session_history/__init__.py +7 -0
  43. agentscope_runtime/engine/tracing/local_logging_handler.py +2 -3
  44. agentscope_runtime/engine/tracing/wrapper.py +18 -4
  45. agentscope_runtime/sandbox/__init__.py +14 -6
  46. agentscope_runtime/sandbox/box/base/__init__.py +2 -2
  47. agentscope_runtime/sandbox/box/base/base_sandbox.py +51 -1
  48. agentscope_runtime/sandbox/box/browser/__init__.py +2 -2
  49. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +198 -2
  50. agentscope_runtime/sandbox/box/filesystem/__init__.py +2 -2
  51. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +99 -2
  52. agentscope_runtime/sandbox/box/gui/__init__.py +2 -2
  53. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +117 -1
  54. agentscope_runtime/sandbox/box/mobile/__init__.py +2 -2
  55. agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +247 -100
  56. agentscope_runtime/sandbox/box/sandbox.py +102 -65
  57. agentscope_runtime/sandbox/box/shared/routers/generic.py +36 -29
  58. agentscope_runtime/sandbox/client/__init__.py +6 -1
  59. agentscope_runtime/sandbox/client/async_http_client.py +339 -0
  60. agentscope_runtime/sandbox/client/base.py +74 -0
  61. agentscope_runtime/sandbox/client/http_client.py +108 -329
  62. agentscope_runtime/sandbox/enums.py +7 -0
  63. agentscope_runtime/sandbox/manager/sandbox_manager.py +275 -29
  64. agentscope_runtime/sandbox/manager/server/app.py +7 -1
  65. agentscope_runtime/sandbox/manager/server/config.py +3 -1
  66. agentscope_runtime/sandbox/model/manager_config.py +11 -9
  67. agentscope_runtime/tools/modelstudio_memory/__init__.py +106 -0
  68. agentscope_runtime/tools/modelstudio_memory/base.py +220 -0
  69. agentscope_runtime/tools/modelstudio_memory/config.py +86 -0
  70. agentscope_runtime/tools/modelstudio_memory/core.py +594 -0
  71. agentscope_runtime/tools/modelstudio_memory/exceptions.py +60 -0
  72. agentscope_runtime/tools/modelstudio_memory/schemas.py +253 -0
  73. agentscope_runtime/version.py +1 -1
  74. {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/METADATA +187 -74
  75. {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/RECORD +79 -55
  76. {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/WHEEL +1 -1
  77. {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/entry_points.txt +0 -0
  78. {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/licenses/LICENSE +0 -0
  79. {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.post1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,594 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ ModelStudio Memory Components.
4
+
5
+ This module provides components for interacting with the ModelStudio Memory
6
+ service, enabling:
7
+ - Adding conversation memories
8
+ - Searching for relevant memories
9
+ - Listing and managing memory nodes
10
+ - Creating and retrieving user profiles
11
+
12
+ All components support async operations and follow the Component pattern.
13
+ """
14
+ import logging
15
+ from typing import Any, Optional
16
+
17
+ from ..base import Tool
18
+ from .base import ModelStudioMemoryBase
19
+ from .config import MemoryServiceConfig
20
+ from .schemas import (
21
+ AddMemoryInput,
22
+ AddMemoryOutput,
23
+ CreateProfileSchemaInput,
24
+ CreateProfileSchemaOutput,
25
+ DeleteMemoryInput,
26
+ DeleteMemoryOutput,
27
+ GetUserProfileInput,
28
+ GetUserProfileOutput,
29
+ ListMemoryInput,
30
+ ListMemoryOutput,
31
+ MemoryNode,
32
+ SearchMemoryInput,
33
+ SearchMemoryOutput,
34
+ UserProfile,
35
+ UserProfileAttribute,
36
+ )
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+
41
+ class AddMemory(
42
+ Tool[AddMemoryInput, AddMemoryOutput],
43
+ ModelStudioMemoryBase,
44
+ ):
45
+ """
46
+ Component for storing conversation history as memory nodes.
47
+
48
+ This component sends conversation messages to the ModelStudio Memory
49
+ to be processed and stored as searchable memory nodes. The service
50
+ automatically extracts and structures relevant information.
51
+
52
+ Environment Variables:
53
+ DASHSCOPE_API_KEY: Required. API key for authentication
54
+ MODELSTUDIO_SERVICE_ID: Optional. Service identifier
55
+ (default: "memory_service")
56
+ MEMORY_SERVICE_ENDPOINT: Optional. API endpoint URL
57
+ (default: https://dashscope.aliyuncs.com/api/v2/apps/memory)
58
+
59
+ Raises:
60
+ ValueError: If DASHSCOPE_API_KEY is not set
61
+ MemoryAPIError: If the API request fails
62
+ MemoryAuthenticationError: If authentication fails
63
+ MemoryNetworkError: If network communication fails
64
+ """
65
+
66
+ name = "add_memory"
67
+ description = "Store conversation messages as memory nodes"
68
+
69
+ def __init__(self, config: Optional[MemoryServiceConfig] = None) -> None:
70
+ """
71
+ Initialize the AddMemory component.
72
+
73
+ Args:
74
+ config: Optional configuration. If not provided, will be loaded
75
+ from environment variables.
76
+ """
77
+ Tool.__init__(self)
78
+ ModelStudioMemoryBase.__init__(self, config)
79
+
80
+ async def _arun(
81
+ self,
82
+ args: AddMemoryInput,
83
+ **kwargs: Any,
84
+ ) -> AddMemoryOutput:
85
+ """
86
+ Add memory nodes for the given conversation.
87
+
88
+ Args:
89
+ args: Input containing user_id, messages, timestamp, and optional
90
+ metadata
91
+ **kwargs: Additional parameters (currently unused)
92
+
93
+ Returns:
94
+ AddMemoryOutput containing the created memory nodes and request_id
95
+
96
+ Raises:
97
+ MemoryAPIError: If the API request fails
98
+ """
99
+ logger.info(f"Adding memory for user {args.user_id}")
100
+
101
+ try:
102
+ # Build request payload
103
+ payload = args.model_dump(exclude_none=True)
104
+
105
+ # Send request
106
+ result = await self._request(
107
+ "POST",
108
+ self.config.get_add_memory_url(),
109
+ json=payload,
110
+ )
111
+
112
+ # Debug: print API response structure
113
+ logger.debug(f"API Response: {result}")
114
+ logger.debug(
115
+ f"memory_nodes type: {type(result.get('memory_nodes'))}",
116
+ )
117
+ logger.debug(f"memory_nodes value: {result.get('memory_nodes')}")
118
+
119
+ # Parse response - handle both list and dict formats
120
+ memory_nodes_raw = result.get("memory_nodes", [])
121
+ if isinstance(memory_nodes_raw, dict):
122
+ # If it's a dict (single node), wrap it in a list
123
+ memory_nodes_list = [memory_nodes_raw]
124
+ elif isinstance(memory_nodes_raw, list):
125
+ memory_nodes_list = memory_nodes_raw
126
+ else:
127
+ memory_nodes_list = []
128
+
129
+ output = AddMemoryOutput(
130
+ memory_nodes=[
131
+ MemoryNode(**node) for node in memory_nodes_list
132
+ ],
133
+ request_id=result.get("request_id", ""),
134
+ )
135
+
136
+ logger.info(
137
+ f"Successfully added {len(output.memory_nodes)} memory nodes",
138
+ )
139
+ return output
140
+
141
+ except Exception:
142
+ logger.exception(f"Failed to add memory for user {args.user_id}")
143
+ raise
144
+
145
+
146
+ class SearchMemory(
147
+ Tool[SearchMemoryInput, SearchMemoryOutput],
148
+ ModelStudioMemoryBase,
149
+ ):
150
+ """
151
+ Component for searching relevant memories based on conversation context.
152
+
153
+ This component searches the memory database for relevant past conversations
154
+ and information based on the current conversation context.
155
+
156
+ Environment Variables:
157
+ DASHSCOPE_API_KEY: Required. API key for authentication
158
+ MODELSTUDIO_SERVICE_ID: Optional. Service identifier
159
+ MEMORY_SERVICE_ENDPOINT: Optional. API endpoint URL
160
+
161
+ Raises:
162
+ ValueError: If DASHSCOPE_API_KEY is not set
163
+ MemoryAPIError: If the API request fails
164
+ """
165
+
166
+ name = "search_memory"
167
+ description = "Search for relevant memories based on conversation context"
168
+
169
+ def __init__(self, config: Optional[MemoryServiceConfig] = None) -> None:
170
+ """
171
+ Initialize the SearchMemory component.
172
+
173
+ Args:
174
+ config: Optional configuration. If not provided, will be loaded
175
+ from environment variables.
176
+ """
177
+ Tool.__init__(self)
178
+ ModelStudioMemoryBase.__init__(self, config)
179
+
180
+ async def _arun(
181
+ self,
182
+ args: SearchMemoryInput,
183
+ **kwargs: Any,
184
+ ) -> SearchMemoryOutput:
185
+ """
186
+ Search for relevant memory nodes.
187
+
188
+ Args:
189
+ args: Input containing user_id, messages, top_k, and min_score
190
+ **kwargs: Additional parameters (currently unused)
191
+
192
+ Returns:
193
+ SearchMemoryOutput containing retrieved memory nodes and request_id
194
+
195
+ Raises:
196
+ MemoryAPIError: If the API request fails
197
+ """
198
+ logger.info(
199
+ f"Searching memory for user {args.user_id} "
200
+ f"(top_k={args.top_k}, min_score={args.min_score})",
201
+ )
202
+
203
+ try:
204
+ # Build request payload
205
+ payload = args.model_dump(exclude_none=True)
206
+
207
+ # Send request
208
+ result = await self._request(
209
+ "POST",
210
+ self.config.get_search_memory_url(),
211
+ json=payload,
212
+ )
213
+
214
+ # Parse response
215
+ output = SearchMemoryOutput(
216
+ memory_nodes=[
217
+ MemoryNode(**node)
218
+ for node in result.get("memory_nodes", [])
219
+ ],
220
+ request_id=result.get("request_id", ""),
221
+ )
222
+
223
+ logger.info(
224
+ f"Found {len(output.memory_nodes)} memory nodes for "
225
+ f"user {args.user_id}",
226
+ )
227
+ return output
228
+
229
+ except Exception:
230
+ logger.exception(
231
+ f"Failed to search memory for user {args.user_id}",
232
+ )
233
+ raise
234
+
235
+
236
+ class ListMemory(
237
+ Tool[ListMemoryInput, ListMemoryOutput],
238
+ ModelStudioMemoryBase,
239
+ ):
240
+ """
241
+ Component for listing memory nodes with pagination.
242
+
243
+ This component retrieves a paginated list of all memory nodes for a
244
+ specific user.
245
+
246
+ Environment Variables:
247
+ DASHSCOPE_API_KEY: Required. API key for authentication
248
+ MODELSTUDIO_SERVICE_ID: Optional. Service identifier
249
+ MEMORY_SERVICE_ENDPOINT: Optional. API endpoint URL
250
+
251
+ Raises:
252
+ ValueError: If DASHSCOPE_API_KEY is not set
253
+ MemoryAPIError: If the API request fails
254
+ """
255
+
256
+ name = "list_memory"
257
+ description = "List memory nodes for a user with pagination"
258
+
259
+ def __init__(self, config: Optional[MemoryServiceConfig] = None) -> None:
260
+ """
261
+ Initialize the ListMemory component.
262
+
263
+ Args:
264
+ config: Optional configuration. If not provided, will be loaded
265
+ from environment variables.
266
+ """
267
+ Tool.__init__(self)
268
+ ModelStudioMemoryBase.__init__(self, config)
269
+
270
+ async def _arun(
271
+ self,
272
+ args: ListMemoryInput,
273
+ **kwargs: Any,
274
+ ) -> ListMemoryOutput:
275
+ """
276
+ List memory nodes for a user with pagination.
277
+
278
+ Args:
279
+ args: Input containing user_id, page_num, and page_size
280
+ **kwargs: Additional parameters (currently unused)
281
+
282
+ Returns:
283
+ ListMemoryOutput containing memory nodes, pagination info,
284
+ and request_id
285
+
286
+ Raises:
287
+ MemoryAPIError: If the API request fails
288
+ """
289
+ logger.info(
290
+ f"Listing memory for user {args.user_id} "
291
+ f"(page {args.page_num}, size {args.page_size})",
292
+ )
293
+
294
+ try:
295
+ # Build request params
296
+ params = args.model_dump(exclude_none=True)
297
+
298
+ # Send request (GET with query parameters)
299
+ result = await self._request(
300
+ "GET",
301
+ self.config.get_list_memory_url(),
302
+ params=params,
303
+ )
304
+
305
+ # Parse response
306
+ output = ListMemoryOutput(
307
+ memory_nodes=[
308
+ MemoryNode(**node)
309
+ for node in result.get("memory_nodes", [])
310
+ ],
311
+ page_size=result.get("page_size", args.page_size or 10),
312
+ page_num=result.get("page_num", args.page_num or 1),
313
+ total=result.get("total", 0),
314
+ request_id=result.get("request_id", ""),
315
+ )
316
+
317
+ logger.info(
318
+ f"Retrieved {len(output.memory_nodes)} memory nodes "
319
+ f"(total: {output.total})",
320
+ )
321
+ return output
322
+
323
+ except Exception:
324
+ logger.exception(f"Failed to list memory for user {args.user_id}")
325
+ raise
326
+
327
+
328
+ class DeleteMemory(
329
+ Tool[DeleteMemoryInput, DeleteMemoryOutput],
330
+ ModelStudioMemoryBase,
331
+ ):
332
+ """
333
+ Component for deleting a specific memory node.
334
+
335
+ This component deletes a memory node by its ID.
336
+
337
+ Environment Variables:
338
+ DASHSCOPE_API_KEY: Required. API key for authentication
339
+ MODELSTUDIO_SERVICE_ID: Optional. Service identifier
340
+ MEMORY_SERVICE_ENDPOINT: Optional. API endpoint URL
341
+
342
+ Raises:
343
+ ValueError: If DASHSCOPE_API_KEY is not set
344
+ MemoryAPIError: If the API request fails
345
+ MemoryNotFoundError: If the memory node is not found
346
+ """
347
+
348
+ name = "delete_memory"
349
+ description = "Delete a specific memory node"
350
+
351
+ def __init__(self, config: Optional[MemoryServiceConfig] = None) -> None:
352
+ """
353
+ Initialize the DeleteMemory component.
354
+
355
+ Args:
356
+ config: Optional configuration. If not provided, will be loaded
357
+ from environment variables.
358
+ """
359
+ Tool.__init__(self)
360
+ ModelStudioMemoryBase.__init__(self, config)
361
+
362
+ async def _arun(
363
+ self,
364
+ args: DeleteMemoryInput,
365
+ **kwargs: Any,
366
+ ) -> DeleteMemoryOutput:
367
+ """
368
+ Delete a memory node.
369
+
370
+ Args:
371
+ args: Input containing user_id and memory_node_id
372
+ **kwargs: Additional parameters (currently unused)
373
+
374
+ Returns:
375
+ DeleteMemoryOutput containing the request_id
376
+
377
+ Raises:
378
+ MemoryAPIError: If the API request fails
379
+ MemoryNotFoundError: If the memory node is not found
380
+ """
381
+ logger.info(
382
+ f"Deleting memory node {args.memory_node_id} "
383
+ f"for user {args.user_id}",
384
+ )
385
+
386
+ try:
387
+ # Build URL with path parameter
388
+ url = self.config.get_delete_memory_url(args.memory_node_id)
389
+
390
+ # Send request
391
+ result = await self._request("DELETE", url)
392
+
393
+ # Parse response
394
+ output = DeleteMemoryOutput(
395
+ request_id=result.get("request_id", ""),
396
+ )
397
+
398
+ logger.info(
399
+ f"Successfully deleted memory node {args.memory_node_id}",
400
+ )
401
+ return output
402
+
403
+ except Exception:
404
+ logger.exception(
405
+ f"Failed to delete memory node {args.memory_node_id}",
406
+ )
407
+ raise
408
+
409
+
410
+ class CreateProfileSchema(
411
+ Tool[CreateProfileSchemaInput, CreateProfileSchemaOutput],
412
+ ModelStudioMemoryBase,
413
+ ):
414
+ """
415
+ Component for creating a user profile schema.
416
+
417
+ This component creates a schema that defines the structure of user profiles
418
+ including attribute definitions.
419
+
420
+ Environment Variables:
421
+ DASHSCOPE_API_KEY: Required. API key for authentication
422
+ MODELSTUDIO_SERVICE_ID: Optional. Service identifier
423
+ MEMORY_SERVICE_ENDPOINT: Optional. API endpoint URL
424
+
425
+ Raises:
426
+ ValueError: If DASHSCOPE_API_KEY is not set or if attributes list
427
+ is empty
428
+ MemoryAPIError: If the API request fails
429
+ """
430
+
431
+ name = "create_profile_schema"
432
+ description = "Create a profile schema with attribute definitions"
433
+
434
+ def __init__(self, config: Optional[MemoryServiceConfig] = None) -> None:
435
+ """
436
+ Initialize the CreateProfileSchema component.
437
+
438
+ Args:
439
+ config: Optional configuration. If not provided, will be loaded
440
+ from environment variables.
441
+ """
442
+ Tool.__init__(self)
443
+ ModelStudioMemoryBase.__init__(self, config)
444
+
445
+ async def _arun(
446
+ self,
447
+ args: CreateProfileSchemaInput,
448
+ **kwargs: Any,
449
+ ) -> CreateProfileSchemaOutput:
450
+ """
451
+ Create a profile schema.
452
+
453
+ Args:
454
+ args: Input containing name, description, and attributes
455
+ **kwargs: Additional parameters (currently unused)
456
+
457
+ Returns:
458
+ CreateProfileSchemaOutput containing profile_schema_id and
459
+ request_id
460
+
461
+ Raises:
462
+ MemoryAPIError: If the API request fails
463
+ """
464
+ logger.info(f"Creating profile schema: {args.name}")
465
+
466
+ try:
467
+ # Build request payload
468
+ payload = args.model_dump(exclude_none=True)
469
+
470
+ # Send request
471
+ result = await self._request(
472
+ "POST",
473
+ self.config.get_create_profile_schema_url(),
474
+ json=payload,
475
+ )
476
+
477
+ # Parse response
478
+ output = CreateProfileSchemaOutput(
479
+ profile_schema_id=result.get("profile_schema_id", ""),
480
+ request_id=result.get("request_id", ""),
481
+ )
482
+
483
+ logger.info(
484
+ f"Successfully created profile schema: "
485
+ f"{output.profile_schema_id}",
486
+ )
487
+ return output
488
+
489
+ except Exception:
490
+ logger.exception(f"Failed to create profile schema: {args.name}")
491
+ raise
492
+
493
+
494
+ class GetUserProfile(
495
+ Tool[GetUserProfileInput, GetUserProfileOutput],
496
+ ModelStudioMemoryBase,
497
+ ):
498
+ """
499
+ Component for retrieving a user profile.
500
+
501
+ This component retrieves a user's profile based on a schema ID and user ID.
502
+
503
+ Environment Variables:
504
+ DASHSCOPE_API_KEY: Required. API key for authentication
505
+ MODELSTUDIO_SERVICE_ID: Optional. Service identifier
506
+ MEMORY_SERVICE_ENDPOINT: Optional. API endpoint URL
507
+
508
+ Raises:
509
+ ValueError: If DASHSCOPE_API_KEY is not set
510
+ MemoryAPIError: If the API request fails
511
+ MemoryNotFoundError: If the profile is not found
512
+ """
513
+
514
+ name = "get_user_profile"
515
+ description = "Get user profile by schema id and user id"
516
+
517
+ def __init__(self, config: Optional[MemoryServiceConfig] = None) -> None:
518
+ """
519
+ Initialize the GetUserProfile component.
520
+
521
+ Args:
522
+ config: Optional configuration. If not provided, will be loaded
523
+ from environment variables.
524
+ """
525
+ Tool.__init__(self)
526
+ ModelStudioMemoryBase.__init__(self, config)
527
+
528
+ async def _arun(
529
+ self,
530
+ args: GetUserProfileInput,
531
+ **kwargs: Any,
532
+ ) -> GetUserProfileOutput:
533
+ """
534
+ Get a user profile.
535
+
536
+ Args:
537
+ args: Input containing schema_id and user_id
538
+ **kwargs: Additional parameters (currently unused)
539
+
540
+ Returns:
541
+ GetUserProfileOutput containing the profile and request_id
542
+
543
+ Raises:
544
+ MemoryAPIError: If the API request fails
545
+ MemoryNotFoundError: If the profile is not found
546
+ """
547
+ logger.info(
548
+ f"Getting user profile for user {args.user_id} "
549
+ f"with schema {args.schema_id}",
550
+ )
551
+
552
+ try:
553
+ # Build URL with path parameter
554
+ url = self.config.get_user_profile_url(args.schema_id)
555
+
556
+ # Send request with user_id as query parameter
557
+ result = await self._request(
558
+ "GET",
559
+ url,
560
+ params={"user_id": args.user_id},
561
+ )
562
+
563
+ # Parse response - handle API's camelCase field names
564
+ profile_raw = result.get("profile", {})
565
+ attributes = [
566
+ UserProfileAttribute(
567
+ name=item.get("name", ""),
568
+ id=item.get("id", ""),
569
+ value=item.get("value"),
570
+ )
571
+ for item in profile_raw.get("attributes", [])
572
+ ]
573
+
574
+ profile = UserProfile(
575
+ schema_description=profile_raw.get("schemaDescription"),
576
+ schema_name=profile_raw.get("schemaName"),
577
+ attributes=attributes,
578
+ )
579
+
580
+ output = GetUserProfileOutput(
581
+ profile=profile,
582
+ request_id=result.get("requestId", ""),
583
+ )
584
+
585
+ logger.info(
586
+ f"Successfully retrieved profile for user {args.user_id}",
587
+ )
588
+ return output
589
+
590
+ except Exception:
591
+ logger.exception(
592
+ f"Failed to get profile for user {args.user_id}",
593
+ )
594
+ raise
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Custom exceptions for ModelStudio Memory components.
4
+ """
5
+ from typing import Optional
6
+
7
+
8
+ class MemoryAPIError(Exception):
9
+ """
10
+ Base exception for Memory API errors.
11
+
12
+ Attributes:
13
+ message: Error message
14
+ status_code: HTTP status code
15
+ error_code: API error code (e.g., 'InvalidApiKey', 'InvalidParameter')
16
+ request_id: Request ID for tracking
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ message: str,
22
+ status_code: Optional[int] = None,
23
+ error_code: Optional[str] = None,
24
+ request_id: Optional[str] = None,
25
+ ):
26
+ self.status_code = status_code
27
+ self.error_code = error_code
28
+ self.request_id = request_id
29
+ super().__init__(message)
30
+
31
+ def __str__(self) -> str:
32
+ """Format error message with all available information."""
33
+ parts = [super().__str__()]
34
+
35
+ if self.error_code:
36
+ parts.append(f"Error Code: {self.error_code}")
37
+
38
+ if self.status_code:
39
+ parts.append(f"Status Code: {self.status_code}")
40
+
41
+ if self.request_id:
42
+ parts.append(f"Request ID: {self.request_id}")
43
+
44
+ return " | ".join(parts)
45
+
46
+
47
+ class MemoryAuthenticationError(MemoryAPIError):
48
+ """Raised when authentication fails (401, 403)."""
49
+
50
+
51
+ class MemoryNotFoundError(MemoryAPIError):
52
+ """Raised when a memory node is not found (404)."""
53
+
54
+
55
+ class MemoryValidationError(MemoryAPIError):
56
+ """Raised when input validation fails (400)."""
57
+
58
+
59
+ class MemoryNetworkError(MemoryAPIError):
60
+ """Raised when network communication fails."""