unique_toolkit 0.7.7__py3-none-any.whl → 1.23.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.

Potentially problematic release.


This version of unique_toolkit might be problematic. Click here for more details.

Files changed (166) hide show
  1. unique_toolkit/__init__.py +28 -1
  2. unique_toolkit/_common/api_calling/human_verification_manager.py +343 -0
  3. unique_toolkit/_common/base_model_type_attribute.py +303 -0
  4. unique_toolkit/_common/chunk_relevancy_sorter/config.py +49 -0
  5. unique_toolkit/_common/chunk_relevancy_sorter/exception.py +5 -0
  6. unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +46 -0
  7. unique_toolkit/_common/chunk_relevancy_sorter/service.py +374 -0
  8. unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +275 -0
  9. unique_toolkit/_common/default_language_model.py +12 -0
  10. unique_toolkit/_common/docx_generator/__init__.py +7 -0
  11. unique_toolkit/_common/docx_generator/config.py +12 -0
  12. unique_toolkit/_common/docx_generator/schemas.py +80 -0
  13. unique_toolkit/_common/docx_generator/service.py +252 -0
  14. unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
  15. unique_toolkit/_common/endpoint_builder.py +305 -0
  16. unique_toolkit/_common/endpoint_requestor.py +430 -0
  17. unique_toolkit/_common/exception.py +24 -0
  18. unique_toolkit/_common/feature_flags/schema.py +9 -0
  19. unique_toolkit/_common/pydantic/rjsf_tags.py +936 -0
  20. unique_toolkit/_common/pydantic_helpers.py +154 -0
  21. unique_toolkit/_common/referencing.py +53 -0
  22. unique_toolkit/_common/string_utilities.py +140 -0
  23. unique_toolkit/_common/tests/test_referencing.py +521 -0
  24. unique_toolkit/_common/tests/test_string_utilities.py +506 -0
  25. unique_toolkit/_common/token/image_token_counting.py +67 -0
  26. unique_toolkit/_common/token/token_counting.py +204 -0
  27. unique_toolkit/_common/utils/__init__.py +1 -0
  28. unique_toolkit/_common/utils/files.py +43 -0
  29. unique_toolkit/_common/utils/structured_output/__init__.py +1 -0
  30. unique_toolkit/_common/utils/structured_output/schema.py +5 -0
  31. unique_toolkit/_common/utils/write_configuration.py +51 -0
  32. unique_toolkit/_common/validators.py +101 -4
  33. unique_toolkit/agentic/__init__.py +1 -0
  34. unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +28 -0
  35. unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +278 -0
  36. unique_toolkit/agentic/evaluation/config.py +36 -0
  37. unique_toolkit/{evaluators → agentic/evaluation}/context_relevancy/prompts.py +25 -0
  38. unique_toolkit/agentic/evaluation/context_relevancy/schema.py +80 -0
  39. unique_toolkit/agentic/evaluation/context_relevancy/service.py +273 -0
  40. unique_toolkit/agentic/evaluation/evaluation_manager.py +218 -0
  41. unique_toolkit/agentic/evaluation/hallucination/constants.py +61 -0
  42. unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +111 -0
  43. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/prompts.py +1 -1
  44. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/service.py +16 -15
  45. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/utils.py +30 -20
  46. unique_toolkit/{evaluators → agentic/evaluation}/output_parser.py +20 -2
  47. unique_toolkit/{evaluators → agentic/evaluation}/schemas.py +27 -7
  48. unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +253 -0
  49. unique_toolkit/agentic/evaluation/tests/test_output_parser.py +87 -0
  50. unique_toolkit/agentic/history_manager/history_construction_with_contents.py +297 -0
  51. unique_toolkit/agentic/history_manager/history_manager.py +242 -0
  52. unique_toolkit/agentic/history_manager/loop_token_reducer.py +484 -0
  53. unique_toolkit/agentic/history_manager/utils.py +96 -0
  54. unique_toolkit/agentic/postprocessor/postprocessor_manager.py +212 -0
  55. unique_toolkit/agentic/reference_manager/reference_manager.py +103 -0
  56. unique_toolkit/agentic/responses_api/__init__.py +19 -0
  57. unique_toolkit/agentic/responses_api/postprocessors/code_display.py +63 -0
  58. unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +145 -0
  59. unique_toolkit/agentic/responses_api/stream_handler.py +15 -0
  60. unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +141 -0
  61. unique_toolkit/agentic/thinking_manager/thinking_manager.py +103 -0
  62. unique_toolkit/agentic/tools/__init__.py +1 -0
  63. unique_toolkit/agentic/tools/a2a/__init__.py +36 -0
  64. unique_toolkit/agentic/tools/a2a/config.py +17 -0
  65. unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +15 -0
  66. unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +66 -0
  67. unique_toolkit/agentic/tools/a2a/evaluation/config.py +55 -0
  68. unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +260 -0
  69. unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +9 -0
  70. unique_toolkit/agentic/tools/a2a/manager.py +55 -0
  71. unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +21 -0
  72. unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +185 -0
  73. unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +73 -0
  74. unique_toolkit/agentic/tools/a2a/postprocessing/config.py +45 -0
  75. unique_toolkit/agentic/tools/a2a/postprocessing/display.py +180 -0
  76. unique_toolkit/agentic/tools/a2a/postprocessing/references.py +101 -0
  77. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +1335 -0
  78. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +603 -0
  79. unique_toolkit/agentic/tools/a2a/prompts.py +46 -0
  80. unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +6 -0
  81. unique_toolkit/agentic/tools/a2a/response_watcher/service.py +91 -0
  82. unique_toolkit/agentic/tools/a2a/tool/__init__.py +4 -0
  83. unique_toolkit/agentic/tools/a2a/tool/_memory.py +26 -0
  84. unique_toolkit/agentic/tools/a2a/tool/_schema.py +9 -0
  85. unique_toolkit/agentic/tools/a2a/tool/config.py +73 -0
  86. unique_toolkit/agentic/tools/a2a/tool/service.py +306 -0
  87. unique_toolkit/agentic/tools/agent_chunks_hanlder.py +65 -0
  88. unique_toolkit/agentic/tools/config.py +167 -0
  89. unique_toolkit/agentic/tools/factory.py +44 -0
  90. unique_toolkit/agentic/tools/mcp/__init__.py +4 -0
  91. unique_toolkit/agentic/tools/mcp/manager.py +71 -0
  92. unique_toolkit/agentic/tools/mcp/models.py +28 -0
  93. unique_toolkit/agentic/tools/mcp/tool_wrapper.py +234 -0
  94. unique_toolkit/agentic/tools/openai_builtin/__init__.py +11 -0
  95. unique_toolkit/agentic/tools/openai_builtin/base.py +30 -0
  96. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +8 -0
  97. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +57 -0
  98. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +230 -0
  99. unique_toolkit/agentic/tools/openai_builtin/manager.py +62 -0
  100. unique_toolkit/agentic/tools/schemas.py +141 -0
  101. unique_toolkit/agentic/tools/test/test_mcp_manager.py +536 -0
  102. unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +445 -0
  103. unique_toolkit/agentic/tools/tool.py +183 -0
  104. unique_toolkit/agentic/tools/tool_manager.py +523 -0
  105. unique_toolkit/agentic/tools/tool_progress_reporter.py +285 -0
  106. unique_toolkit/agentic/tools/utils/__init__.py +19 -0
  107. unique_toolkit/agentic/tools/utils/execution/__init__.py +1 -0
  108. unique_toolkit/agentic/tools/utils/execution/execution.py +286 -0
  109. unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  110. unique_toolkit/agentic/tools/utils/source_handling/schema.py +21 -0
  111. unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +207 -0
  112. unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +216 -0
  113. unique_toolkit/app/__init__.py +6 -0
  114. unique_toolkit/app/dev_util.py +180 -0
  115. unique_toolkit/app/init_sdk.py +32 -1
  116. unique_toolkit/app/schemas.py +198 -31
  117. unique_toolkit/app/unique_settings.py +367 -0
  118. unique_toolkit/chat/__init__.py +8 -1
  119. unique_toolkit/chat/deprecated/service.py +232 -0
  120. unique_toolkit/chat/functions.py +642 -77
  121. unique_toolkit/chat/rendering.py +34 -0
  122. unique_toolkit/chat/responses_api.py +461 -0
  123. unique_toolkit/chat/schemas.py +133 -2
  124. unique_toolkit/chat/service.py +115 -767
  125. unique_toolkit/content/functions.py +153 -4
  126. unique_toolkit/content/schemas.py +122 -15
  127. unique_toolkit/content/service.py +278 -44
  128. unique_toolkit/content/smart_rules.py +301 -0
  129. unique_toolkit/content/utils.py +8 -3
  130. unique_toolkit/embedding/service.py +102 -11
  131. unique_toolkit/framework_utilities/__init__.py +1 -0
  132. unique_toolkit/framework_utilities/langchain/client.py +71 -0
  133. unique_toolkit/framework_utilities/langchain/history.py +19 -0
  134. unique_toolkit/framework_utilities/openai/__init__.py +6 -0
  135. unique_toolkit/framework_utilities/openai/client.py +83 -0
  136. unique_toolkit/framework_utilities/openai/message_builder.py +229 -0
  137. unique_toolkit/framework_utilities/utils.py +23 -0
  138. unique_toolkit/language_model/__init__.py +3 -0
  139. unique_toolkit/language_model/builder.py +27 -11
  140. unique_toolkit/language_model/default_language_model.py +3 -0
  141. unique_toolkit/language_model/functions.py +327 -43
  142. unique_toolkit/language_model/infos.py +992 -50
  143. unique_toolkit/language_model/reference.py +242 -0
  144. unique_toolkit/language_model/schemas.py +475 -48
  145. unique_toolkit/language_model/service.py +228 -27
  146. unique_toolkit/protocols/support.py +145 -0
  147. unique_toolkit/services/__init__.py +7 -0
  148. unique_toolkit/services/chat_service.py +1630 -0
  149. unique_toolkit/services/knowledge_base.py +861 -0
  150. unique_toolkit/short_term_memory/service.py +178 -41
  151. unique_toolkit/smart_rules/__init__.py +0 -0
  152. unique_toolkit/smart_rules/compile.py +56 -0
  153. unique_toolkit/test_utilities/events.py +197 -0
  154. {unique_toolkit-0.7.7.dist-info → unique_toolkit-1.23.0.dist-info}/METADATA +606 -7
  155. unique_toolkit-1.23.0.dist-info/RECORD +182 -0
  156. unique_toolkit/evaluators/__init__.py +0 -1
  157. unique_toolkit/evaluators/config.py +0 -35
  158. unique_toolkit/evaluators/constants.py +0 -1
  159. unique_toolkit/evaluators/context_relevancy/constants.py +0 -32
  160. unique_toolkit/evaluators/context_relevancy/service.py +0 -53
  161. unique_toolkit/evaluators/context_relevancy/utils.py +0 -142
  162. unique_toolkit/evaluators/hallucination/constants.py +0 -41
  163. unique_toolkit-0.7.7.dist-info/RECORD +0 -64
  164. /unique_toolkit/{evaluators → agentic/evaluation}/exception.py +0 -0
  165. {unique_toolkit-0.7.7.dist-info → unique_toolkit-1.23.0.dist-info}/LICENSE +0 -0
  166. {unique_toolkit-0.7.7.dist-info → unique_toolkit-1.23.0.dist-info}/WHEEL +0 -0
@@ -1,12 +1,18 @@
1
1
  import logging
2
2
  import re
3
- from typing import Any, Dict, List, cast
3
+ from typing import Any, Sequence
4
4
 
5
5
  import unique_sdk
6
+ from openai.types.chat import ChatCompletionToolChoiceOptionParam
7
+ from openai.types.chat.chat_completion_message_param import ChatCompletionMessageParam
8
+ from pydantic import BaseModel
9
+ from typing_extensions import deprecated
6
10
  from unique_sdk._list_object import ListObject
7
11
 
8
12
  from unique_toolkit._common import _time_utils
9
- from unique_toolkit.chat.constants import DEFAULT_MAX_MESSAGES
13
+ from unique_toolkit.chat.constants import (
14
+ DEFAULT_MAX_MESSAGES,
15
+ )
10
16
  from unique_toolkit.chat.schemas import (
11
17
  ChatMessage,
12
18
  ChatMessageAssessment,
@@ -14,6 +20,13 @@ from unique_toolkit.chat.schemas import (
14
20
  ChatMessageAssessmentStatus,
15
21
  ChatMessageAssessmentType,
16
22
  ChatMessageRole,
23
+ MessageExecution,
24
+ MessageExecutionType,
25
+ MessageExecutionUpdateStatus,
26
+ MessageLog,
27
+ MessageLogDetails,
28
+ MessageLogStatus,
29
+ MessageLogUncitedReferences,
17
30
  )
18
31
  from unique_toolkit.content.schemas import ContentChunk, ContentReference
19
32
  from unique_toolkit.content.utils import count_tokens
@@ -21,12 +34,17 @@ from unique_toolkit.language_model.constants import (
21
34
  DEFAULT_COMPLETE_TEMPERATURE,
22
35
  DEFAULT_COMPLETE_TIMEOUT,
23
36
  )
24
- from unique_toolkit.language_model.functions import _prepare_completion_params_util
25
- from unique_toolkit.language_model.infos import LanguageModelName
37
+ from unique_toolkit.language_model.functions import (
38
+ _prepare_all_completions_params_util,
39
+ )
40
+ from unique_toolkit.language_model.infos import (
41
+ LanguageModelName,
42
+ )
26
43
  from unique_toolkit.language_model.schemas import (
27
44
  LanguageModelMessages,
28
45
  LanguageModelStreamResponse,
29
46
  LanguageModelTool,
47
+ LanguageModelToolDescription,
30
48
  )
31
49
 
32
50
  logger = logging.getLogger(__name__)
@@ -47,8 +65,7 @@ def modify_message(
47
65
  message_id: str | None = None,
48
66
  set_completed_at: bool = False,
49
67
  ) -> ChatMessage:
50
- """
51
- Modifies a chat message synchronously.
68
+ """Modifies a chat message synchronously.
52
69
 
53
70
  Args:
54
71
  user_id (str): The user ID.
@@ -70,6 +87,7 @@ def modify_message(
70
87
 
71
88
  Raises:
72
89
  Exception: If the modification fails.
90
+
73
91
  """
74
92
  try:
75
93
  params = _construct_message_modify_params(
@@ -109,8 +127,7 @@ async def modify_message_async(
109
127
  message_id: str | None = None,
110
128
  set_completed_at: bool = False,
111
129
  ) -> ChatMessage:
112
- """
113
- Modifies a chat message asynchronously.
130
+ """Modifies a chat message asynchronously.
114
131
 
115
132
  Args:
116
133
  user_id (str): The user ID.
@@ -132,6 +149,7 @@ async def modify_message_async(
132
149
 
133
150
  Raises:
134
151
  Exception: If the modification fails.
152
+
135
153
  """
136
154
  try:
137
155
  params = _construct_message_modify_params(
@@ -156,7 +174,26 @@ async def modify_message_async(
156
174
  raise e
157
175
 
158
176
 
159
- def map_references(references: List[ContentReference]) -> List[Dict[str, Any]]:
177
+ def map_references(references: list[ContentReference]) -> list[dict[str, Any]]:
178
+ return [
179
+ {
180
+ "name": ref.name,
181
+ "url": ref.url,
182
+ "sequenceNumber": ref.sequence_number,
183
+ "sourceId": ref.source_id,
184
+ "source": ref.source,
185
+ }
186
+ for ref in references
187
+ ]
188
+
189
+
190
+ def map_references_with_original_index(
191
+ references: list[ContentReference],
192
+ ) -> list[dict[str, Any]]:
193
+ """Maps ContentReference objects to dict format for MessageLog API (complete format).
194
+
195
+ This function includes all fields including originalIndex for APIs that support it.
196
+ """
160
197
  return [
161
198
  {
162
199
  "name": ref.name,
@@ -164,6 +201,7 @@ def map_references(references: List[ContentReference]) -> List[Dict[str, Any]]:
164
201
  "sequenceNumber": ref.sequence_number,
165
202
  "sourceId": ref.source_id,
166
203
  "source": ref.source,
204
+ "originalIndex": ref.original_index,
167
205
  }
168
206
  for ref in references
169
207
  ]
@@ -183,7 +221,7 @@ def _construct_message_modify_params(
183
221
  debug_info: dict | None = None,
184
222
  message_id: str | None = None,
185
223
  set_completed_at: bool = False,
186
- ) -> Dict[str, Any]:
224
+ ) -> dict[str, Any]:
187
225
  completed_at_datetime = None
188
226
 
189
227
  if message_id:
@@ -226,8 +264,7 @@ def create_message(
226
264
  debug_info: dict | None = None,
227
265
  set_completed_at: bool | None = False,
228
266
  ):
229
- """
230
- Creates a message in the chat session synchronously.
267
+ """Creates a message in the chat session synchronously.
231
268
 
232
269
  Args:
233
270
  user_id (str): The user ID.
@@ -246,6 +283,7 @@ def create_message(
246
283
 
247
284
  Raises:
248
285
  Exception: If the creation fails.
286
+
249
287
  """
250
288
  if original_content is None:
251
289
  original_content = content
@@ -283,8 +321,7 @@ async def create_message_async(
283
321
  debug_info: dict | None = None,
284
322
  set_completed_at: bool | None = False,
285
323
  ):
286
- """
287
- Creates a message in the chat session synchronously.
324
+ """Creates a message in the chat session synchronously.
288
325
 
289
326
  Args:
290
327
  user_id (str): The user ID.
@@ -303,6 +340,7 @@ async def create_message_async(
303
340
 
304
341
  Raises:
305
342
  Exception: If the creation fails.
343
+
306
344
  """
307
345
  if original_content is None:
308
346
  original_content = content
@@ -339,7 +377,7 @@ def _construct_message_create_params(
339
377
  references: list[ContentReference] | None = None,
340
378
  debug_info: dict | None = None,
341
379
  set_completed_at: bool | None = False,
342
- ) -> Dict[str, Any]:
380
+ ) -> dict[str, Any]:
343
381
  if original_content is None:
344
382
  original_content = content
345
383
 
@@ -352,7 +390,7 @@ def _construct_message_create_params(
352
390
  "text": content,
353
391
  "originalText": original_content,
354
392
  "references": map_references(references) if references else [],
355
- "debugInfo": debug_info,
393
+ "debugInfo": debug_info or {},
356
394
  "completedAt": _time_utils.get_datetime_now() if set_completed_at else None,
357
395
  }
358
396
 
@@ -361,7 +399,7 @@ def get_selection_from_history(
361
399
  full_history: list[ChatMessage],
362
400
  max_tokens: int,
363
401
  max_messages=DEFAULT_MAX_MESSAGES,
364
- ) -> List[ChatMessage]:
402
+ ) -> list[ChatMessage]:
365
403
  messages = full_history[-max_messages:]
366
404
  filtered_messages = [m for m in messages if m.content]
367
405
  mapped_messages = []
@@ -381,14 +419,14 @@ def get_selection_from_history(
381
419
  )
382
420
 
383
421
 
384
- def map_to_chat_messages(messages: list[dict]) -> List[ChatMessage]:
422
+ def map_to_chat_messages(messages: list[dict]) -> list[ChatMessage]:
385
423
  return [ChatMessage(**msg) for msg in messages]
386
424
 
387
425
 
388
426
  def pick_messages_in_reverse_for_token_window(
389
427
  messages: list[ChatMessage],
390
428
  limit: int,
391
- ) -> List[ChatMessage]:
429
+ ) -> list[ChatMessage]:
392
430
  if len(messages) < 1 or limit < 1:
393
431
  return []
394
432
 
@@ -396,7 +434,7 @@ def pick_messages_in_reverse_for_token_window(
396
434
  token_count = count_tokens(messages[last_index].content or "")
397
435
  while token_count > limit:
398
436
  logger.debug(
399
- f"Limit too low for the initial message. Last message TokenCount {token_count} available tokens {limit} - cutting message in half until it fits"
437
+ f"Limit too low for the initial message. Last message TokenCount {token_count} available tokens {limit} - cutting message in half until it fits",
400
438
  )
401
439
  content = messages[last_index].content or ""
402
440
  messages[last_index].content = content[: len(content) // 2] + "..."
@@ -404,7 +442,7 @@ def pick_messages_in_reverse_for_token_window(
404
442
 
405
443
  while token_count <= limit and last_index > 0:
406
444
  token_count = count_tokens(
407
- "".join([msg.content or "" for msg in messages[:last_index]])
445
+ "".join([msg.content or "" for msg in messages[:last_index]]),
408
446
  )
409
447
  if token_count <= limit:
410
448
  last_index -= 1
@@ -414,7 +452,9 @@ def pick_messages_in_reverse_for_token_window(
414
452
 
415
453
 
416
454
  def list_messages(
417
- event_user_id, event_company_id, chat_id: str
455
+ event_user_id: str,
456
+ event_company_id: str,
457
+ chat_id: str,
418
458
  ) -> ListObject[unique_sdk.Message]:
419
459
  try:
420
460
  messages = unique_sdk.Message.list(
@@ -429,7 +469,9 @@ def list_messages(
429
469
 
430
470
 
431
471
  async def list_messages_async(
432
- event_user_id: str, event_company_id: str, chat_id: str
472
+ event_user_id: str,
473
+ event_company_id: str,
474
+ chat_id: str,
433
475
  ) -> ListObject[unique_sdk.Message]:
434
476
  try:
435
477
  messages = await unique_sdk.Message.list_async(
@@ -444,8 +486,10 @@ async def list_messages_async(
444
486
 
445
487
 
446
488
  def get_full_history(
447
- event_user_id, event_company_id, event_payload_chat_id
448
- ) -> List[ChatMessage]:
489
+ event_user_id: str,
490
+ event_company_id: str,
491
+ event_payload_chat_id: str,
492
+ ) -> list[ChatMessage]:
449
493
  messages = list_messages(event_user_id, event_company_id, event_payload_chat_id)
450
494
  messages = filter_valid_messages(messages)
451
495
 
@@ -453,10 +497,14 @@ def get_full_history(
453
497
 
454
498
 
455
499
  async def get_full_history_async(
456
- event_user_id, event_company_id, event_payload_chat_id
457
- ) -> List[ChatMessage]:
500
+ event_user_id: str,
501
+ event_company_id: str,
502
+ event_payload_chat_id: str,
503
+ ) -> list[ChatMessage]:
458
504
  messages = await list_messages_async(
459
- event_user_id, event_company_id, event_payload_chat_id
505
+ event_user_id,
506
+ event_company_id,
507
+ event_payload_chat_id,
460
508
  )
461
509
  messages = filter_valid_messages(messages)
462
510
 
@@ -465,19 +513,16 @@ async def get_full_history_async(
465
513
 
466
514
  def filter_valid_messages(
467
515
  messages: ListObject[unique_sdk.Message],
468
- ) -> List[Dict[str, Any]]:
516
+ ) -> list[dict[str, Any]]:
469
517
  SYSTEM_MESSAGE_PREFIX = "[SYSTEM] "
470
518
 
471
519
  # Remove the last two messages
472
520
  messages = messages["data"][:-2] # type: ignore
473
521
  filtered_messages = []
474
522
  for message in messages:
475
- if message["text"] is None:
523
+ if message["text"] is None or SYSTEM_MESSAGE_PREFIX in message["text"]:
476
524
  continue
477
- elif SYSTEM_MESSAGE_PREFIX in message["text"]:
478
- continue
479
- else:
480
- filtered_messages.append(message)
525
+ filtered_messages.append(message)
481
526
 
482
527
  return filtered_messages
483
528
 
@@ -493,8 +538,7 @@ def create_message_assessment(
493
538
  label: ChatMessageAssessmentLabel | None = None,
494
539
  is_visible: bool = True,
495
540
  ) -> ChatMessageAssessment:
496
- """
497
- Creates a message assessment for an assistant message synchronously.
541
+ """Creates a message assessment for an assistant message synchronously.
498
542
 
499
543
  Args:
500
544
  user_id (str): The user ID.
@@ -512,6 +556,7 @@ def create_message_assessment(
512
556
 
513
557
  Raises:
514
558
  Exception: If the creation fails
559
+
515
560
  """
516
561
  try:
517
562
  assessment = unique_sdk.MessageAssessment.create(
@@ -542,8 +587,7 @@ async def create_message_assessment_async(
542
587
  label: ChatMessageAssessmentLabel | None = None,
543
588
  is_visible: bool = True,
544
589
  ) -> ChatMessageAssessment:
545
- """
546
- Creates a message assessment for an assistant message asynchronously.
590
+ """Creates a message assessment for an assistant message asynchronously.
547
591
 
548
592
  Args:
549
593
  user_id (str): The user ID.
@@ -561,6 +605,7 @@ async def create_message_assessment_async(
561
605
 
562
606
  Raises:
563
607
  Exception: If the creation fails
608
+
564
609
  """
565
610
  try:
566
611
  assessment = await unique_sdk.MessageAssessment.create_async(
@@ -590,8 +635,7 @@ def modify_message_assessment(
590
635
  explanation: str | None = None,
591
636
  label: ChatMessageAssessmentLabel | None = None,
592
637
  ) -> ChatMessageAssessment:
593
- """
594
- Modifies a message assessment for an assistant message synchronously.
638
+ """Modifies a message assessment for an assistant message synchronously.
595
639
 
596
640
  Args:
597
641
  user_id (str): The user ID.
@@ -608,6 +652,7 @@ def modify_message_assessment(
608
652
 
609
653
  Raises:
610
654
  Exception: If the modification fails
655
+
611
656
  """
612
657
  try:
613
658
  assessment = unique_sdk.MessageAssessment.modify(
@@ -636,8 +681,7 @@ async def modify_message_assessment_async(
636
681
  explanation: str | None = None,
637
682
  label: ChatMessageAssessmentLabel | None = None,
638
683
  ) -> ChatMessageAssessment:
639
- """
640
- Modifies a message assessment for an assistant message asynchronously.
684
+ """Modifies a message assessment for an assistant message asynchronously.
641
685
 
642
686
  Args:
643
687
  user_id (str): The user ID.
@@ -654,6 +698,7 @@ async def modify_message_assessment_async(
654
698
 
655
699
  Raises:
656
700
  Exception: If the modification fails
701
+
657
702
  """
658
703
  try:
659
704
  assessment = await unique_sdk.MessageAssessment.modify_async(
@@ -672,6 +717,7 @@ async def modify_message_assessment_async(
672
717
  raise e
673
718
 
674
719
 
720
+ @deprecated("Use stream_complete_with_references instead")
675
721
  def stream_complete_to_chat(
676
722
  company_id: str,
677
723
  user_id: str,
@@ -679,18 +725,54 @@ def stream_complete_to_chat(
679
725
  user_message_id: str,
680
726
  chat_id: str,
681
727
  assistant_id: str,
682
- messages: LanguageModelMessages,
728
+ messages: LanguageModelMessages | list[ChatCompletionMessageParam],
683
729
  model_name: LanguageModelName | str,
684
- content_chunks: list[ContentChunk] = [],
730
+ content_chunks: list[ContentChunk] | None = None,
685
731
  debug_info: dict = {},
686
732
  temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
687
733
  timeout: int = DEFAULT_COMPLETE_TIMEOUT,
688
- tools: list[LanguageModelTool] | None = None,
734
+ tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
689
735
  start_text: str | None = None,
690
736
  other_options: dict | None = None,
691
737
  ) -> LanguageModelStreamResponse:
692
- """
693
- Streams a completion synchronously.
738
+ return stream_complete_with_references(
739
+ company_id=company_id,
740
+ user_id=user_id,
741
+ assistant_message_id=assistant_message_id,
742
+ user_message_id=user_message_id,
743
+ chat_id=chat_id,
744
+ assistant_id=assistant_id,
745
+ messages=messages,
746
+ model_name=model_name,
747
+ content_chunks=content_chunks,
748
+ debug_info=debug_info,
749
+ temperature=temperature,
750
+ timeout=timeout,
751
+ tools=tools,
752
+ start_text=start_text,
753
+ other_options=other_options,
754
+ )
755
+
756
+
757
+ def stream_complete_with_references(
758
+ company_id: str,
759
+ user_id: str,
760
+ assistant_message_id: str,
761
+ user_message_id: str,
762
+ chat_id: str,
763
+ assistant_id: str,
764
+ messages: LanguageModelMessages | list[ChatCompletionMessageParam],
765
+ model_name: LanguageModelName | str,
766
+ content_chunks: list[ContentChunk] | None = None,
767
+ debug_info: dict | None = None,
768
+ temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
769
+ timeout: int = DEFAULT_COMPLETE_TIMEOUT,
770
+ tools: Sequence[LanguageModelTool | LanguageModelToolDescription] | None = None,
771
+ start_text: str | None = None,
772
+ tool_choice: ChatCompletionToolChoiceOptionParam | None = None,
773
+ other_options: dict | None = None,
774
+ ) -> LanguageModelStreamResponse:
775
+ """Streams a completion synchronously.
694
776
 
695
777
  Args:
696
778
  company_id (str): The company ID associated with the request.
@@ -705,20 +787,24 @@ def stream_complete_to_chat(
705
787
  debug_info (dict): Debug information.
706
788
  temperature (float): Temperature setting.
707
789
  timeout (int): Timeout in milliseconds.
708
- tools (Optional[list[LanguageModelTool]]): Optional tools.
790
+ tools (Optional[list[LanguageModelTool | LanguageModelToolDescription ]]): Optional tools.
709
791
  start_text (Optional[str]): Starting text.
710
792
  other_options (Optional[dict]): Additional options.
711
793
 
712
794
  Returns:
713
795
  LanguageModelStreamResponse: The streaming response object.
796
+
714
797
  """
715
- options, model, messages_dict, search_context = _prepare_completion_params_util(
716
- messages=messages,
717
- model_name=model_name,
718
- temperature=temperature,
719
- tools=tools,
720
- other_options=other_options,
721
- content_chunks=content_chunks,
798
+ options, model, messages_dict, search_context = (
799
+ _prepare_all_completions_params_util(
800
+ messages=messages,
801
+ model_name=model_name,
802
+ temperature=temperature,
803
+ tools=tools,
804
+ other_options=other_options,
805
+ tool_choice=tool_choice,
806
+ content_chunks=content_chunks or [],
807
+ )
722
808
  )
723
809
 
724
810
  try:
@@ -727,16 +813,13 @@ def stream_complete_to_chat(
727
813
  company_id=company_id,
728
814
  assistantMessageId=assistant_message_id,
729
815
  userMessageId=user_message_id,
730
- messages=cast(
731
- list[unique_sdk.Integrated.ChatCompletionRequestMessage],
732
- messages_dict,
733
- ),
816
+ messages=messages_dict,
734
817
  chatId=chat_id,
735
818
  searchContext=search_context,
736
819
  model=model,
737
820
  timeout=timeout,
738
821
  assistantId=assistant_id,
739
- debugInfo=debug_info,
822
+ debugInfo=debug_info or {},
740
823
  options=options, # type: ignore
741
824
  startText=start_text,
742
825
  )
@@ -746,6 +829,7 @@ def stream_complete_to_chat(
746
829
  raise e
747
830
 
748
831
 
832
+ @deprecated("Use stream_complete_with_references_async instead")
749
833
  async def stream_complete_to_chat_async(
750
834
  company_id: str,
751
835
  user_id: str,
@@ -753,31 +837,71 @@ async def stream_complete_to_chat_async(
753
837
  user_message_id: str,
754
838
  chat_id: str,
755
839
  assistant_id: str,
756
- messages: LanguageModelMessages,
840
+ messages: LanguageModelMessages | list[ChatCompletionMessageParam],
757
841
  model_name: LanguageModelName | str,
758
- content_chunks: list[ContentChunk] = [],
842
+ content_chunks: list[ContentChunk] | None = None,
759
843
  debug_info: dict = {},
760
844
  temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
761
845
  timeout: int = DEFAULT_COMPLETE_TIMEOUT,
762
- tools: list[LanguageModelTool] | None = None,
846
+ tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
763
847
  start_text: str | None = None,
764
848
  other_options: dict | None = None,
765
849
  ) -> LanguageModelStreamResponse:
766
- """
767
- Streams a completion asynchronously.
850
+ return await stream_complete_with_references_async(
851
+ company_id=company_id,
852
+ user_id=user_id,
853
+ assistant_message_id=assistant_message_id,
854
+ user_message_id=user_message_id,
855
+ chat_id=chat_id,
856
+ assistant_id=assistant_id,
857
+ messages=messages,
858
+ model_name=model_name,
859
+ content_chunks=content_chunks,
860
+ debug_info=debug_info,
861
+ temperature=temperature,
862
+ timeout=timeout,
863
+ tools=tools,
864
+ start_text=start_text,
865
+ other_options=other_options,
866
+ )
867
+
868
+
869
+ async def stream_complete_with_references_async(
870
+ company_id: str,
871
+ user_id: str,
872
+ assistant_message_id: str,
873
+ user_message_id: str,
874
+ chat_id: str,
875
+ assistant_id: str,
876
+ messages: LanguageModelMessages | list[ChatCompletionMessageParam],
877
+ model_name: LanguageModelName | str,
878
+ content_chunks: list[ContentChunk] | None = None,
879
+ debug_info: dict | None = None,
880
+ temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
881
+ timeout: int = DEFAULT_COMPLETE_TIMEOUT,
882
+ tools: Sequence[LanguageModelTool | LanguageModelToolDescription] | None = None,
883
+ tool_choice: ChatCompletionToolChoiceOptionParam | None = None,
884
+ start_text: str | None = None,
885
+ other_options: dict | None = None,
886
+ ) -> LanguageModelStreamResponse:
887
+ """Streams a completion asynchronously.
768
888
 
769
889
  Args: [same as stream_complete]
770
890
 
771
891
  Returns:
772
892
  LanguageModelStreamResponse: The streaming response object.
893
+
773
894
  """
774
- options, model, messages_dict, search_context = _prepare_completion_params_util(
775
- messages=messages,
776
- model_name=model_name,
777
- temperature=temperature,
778
- tools=tools,
779
- other_options=other_options,
780
- content_chunks=content_chunks,
895
+ options, model, messages_dict, search_context = (
896
+ _prepare_all_completions_params_util(
897
+ messages=messages,
898
+ model_name=model_name,
899
+ temperature=temperature,
900
+ tools=tools,
901
+ tool_choice=tool_choice,
902
+ other_options=other_options,
903
+ content_chunks=content_chunks or [],
904
+ )
781
905
  )
782
906
 
783
907
  try:
@@ -786,16 +910,13 @@ async def stream_complete_to_chat_async(
786
910
  company_id=company_id,
787
911
  assistantMessageId=assistant_message_id,
788
912
  userMessageId=user_message_id,
789
- messages=cast(
790
- list[unique_sdk.Integrated.ChatCompletionRequestMessage],
791
- messages_dict,
792
- ),
913
+ messages=messages_dict,
793
914
  chatId=chat_id,
794
915
  searchContext=search_context,
795
916
  model=model,
796
917
  timeout=timeout,
797
918
  assistantId=assistant_id,
798
- debugInfo=debug_info,
919
+ debugInfo=debug_info or {},
799
920
  options=options, # type: ignore
800
921
  startText=start_text,
801
922
  )
@@ -803,3 +924,447 @@ async def stream_complete_to_chat_async(
803
924
  except Exception as e:
804
925
  logger.error(f"Error streaming completion: {e}")
805
926
  raise e
927
+
928
+
929
+ def _get_model_dump_or_none(model: BaseModel | None) -> dict | None:
930
+ if model is None:
931
+ return None
932
+ return model.model_dump()
933
+
934
+
935
+ def create_message_log(
936
+ user_id: str,
937
+ company_id: str,
938
+ message_id: str,
939
+ text: str,
940
+ status: MessageLogStatus,
941
+ order: int,
942
+ details: MessageLogDetails | None = None,
943
+ uncited_references: MessageLogUncitedReferences | None = None,
944
+ references: list[ContentReference] | None = None,
945
+ ) -> MessageLog:
946
+ """Creates a message log synchronously.
947
+
948
+ Args:
949
+ user_id (str): The user ID.
950
+ company_id (str): The company ID.
951
+ message_id (str): The ID of the message this log belongs to.
952
+ text (str): The log text content.
953
+ status (MessageLogStatus): The status of this log entry.
954
+ order (int): The order/sequence number of this log entry.
955
+ details (MessageLogDetails | None): Additional details about this log entry.
956
+ uncited_references (MessageLogUncitedReferences | None): References that are not cited.
957
+ references (list[ContentReference] | None): List of references for this log.
958
+
959
+ Returns:
960
+ MessageLog: The created message log.
961
+
962
+ Raises:
963
+ Exception: If the creation fails.
964
+
965
+ """
966
+ try:
967
+ references_list = (
968
+ map_references_with_original_index(references) if references else None
969
+ )
970
+ message_log = unique_sdk.MessageLog.create(
971
+ user_id=user_id,
972
+ company_id=company_id,
973
+ messageId=message_id,
974
+ text=text,
975
+ status=status.value,
976
+ order=order,
977
+ details=_get_model_dump_or_none(details),
978
+ uncitedReferences=_get_model_dump_or_none(uncited_references),
979
+ references=references_list, # type: ignore
980
+ )
981
+ return MessageLog(**message_log)
982
+ except Exception as e:
983
+ logger.error(f"Failed to create message log: {e}")
984
+ raise e
985
+
986
+
987
+ async def create_message_log_async(
988
+ user_id: str,
989
+ company_id: str,
990
+ message_id: str,
991
+ text: str,
992
+ status: MessageLogStatus,
993
+ order: int,
994
+ details: MessageLogDetails | None = None,
995
+ uncited_references: MessageLogUncitedReferences | None = None,
996
+ references: list[ContentReference] | None = None,
997
+ ) -> MessageLog:
998
+ """Creates a message log asynchronously.
999
+
1000
+ Args:
1001
+ user_id (str): The user ID.
1002
+ company_id (str): The company ID.
1003
+ message_id (str): The ID of the message this log belongs to.
1004
+ text (str): The log text content.
1005
+ status (MessageLogStatus): The status of this log entry.
1006
+ order (int): The order/sequence number of this log entry.
1007
+ details (MessageLogDetails | None): Additional details about this log entry.
1008
+ uncited_references (MessageLogUncitedReferences | None): References that are not cited.
1009
+ references (list[ContentReference] | None): List of references for this log.
1010
+
1011
+ Returns:
1012
+ MessageLog: The created message log.
1013
+
1014
+ Raises:
1015
+ Exception: If the creation fails.
1016
+
1017
+ """
1018
+ try:
1019
+ references_list = (
1020
+ map_references_with_original_index(references) if references else None
1021
+ )
1022
+ message_log = await unique_sdk.MessageLog.create_async(
1023
+ user_id=user_id,
1024
+ company_id=company_id,
1025
+ messageId=message_id,
1026
+ text=text,
1027
+ status=status.value,
1028
+ order=order,
1029
+ details=_get_model_dump_or_none(details),
1030
+ uncitedReferences=_get_model_dump_or_none(uncited_references),
1031
+ references=references_list, # type: ignore
1032
+ )
1033
+ return MessageLog(**message_log)
1034
+ except Exception as e:
1035
+ logger.error(f"Failed to create message log: {e}")
1036
+ raise e
1037
+
1038
+
1039
+ def update_message_log(
1040
+ user_id: str,
1041
+ company_id: str,
1042
+ message_log_id: str,
1043
+ order: int,
1044
+ text: str | None = None,
1045
+ status: MessageLogStatus | None = None,
1046
+ details: MessageLogDetails | None = None,
1047
+ uncited_references: MessageLogUncitedReferences | None = None,
1048
+ references: list[ContentReference] | None = None,
1049
+ ) -> MessageLog:
1050
+ """Updates a message log synchronously.
1051
+
1052
+ Args:
1053
+ user_id (str): The user ID.
1054
+ company_id (str): The company ID.
1055
+ message_log_id (str): The ID of the message log to update.
1056
+ order (int): The order/sequence number (required).
1057
+ text (str | None): The updated log text content.
1058
+ status (MessageLogStatus | None): The updated status.
1059
+ details (MessageLogDetails | None): Updated additional details.
1060
+ uncited_references (MessageLogUncitedReferences | None): Updated uncited references.
1061
+ references (list[ContentReference] | None): Updated list of references.
1062
+
1063
+ Returns:
1064
+ MessageLog: The updated message log.
1065
+
1066
+ Raises:
1067
+ Exception: If the update fails.
1068
+
1069
+ """
1070
+ try:
1071
+ references_list = (
1072
+ map_references_with_original_index(references) if references else None
1073
+ )
1074
+ message_log = unique_sdk.MessageLog.update(
1075
+ user_id=user_id,
1076
+ company_id=company_id,
1077
+ message_log_id=message_log_id,
1078
+ text=text,
1079
+ status=status.value if status else None,
1080
+ order=order,
1081
+ details=_get_model_dump_or_none(details),
1082
+ uncitedReferences=_get_model_dump_or_none(uncited_references),
1083
+ references=references_list, # type: ignore
1084
+ )
1085
+ return MessageLog(**message_log)
1086
+ except Exception as e:
1087
+ logger.error(f"Failed to update message log: {e}")
1088
+ raise e
1089
+
1090
+
1091
+ async def update_message_log_async(
1092
+ user_id: str,
1093
+ company_id: str,
1094
+ message_log_id: str,
1095
+ order: int,
1096
+ text: str | None = None,
1097
+ status: MessageLogStatus | None = None,
1098
+ details: MessageLogDetails | None = None,
1099
+ uncited_references: MessageLogUncitedReferences | None = None,
1100
+ references: list[ContentReference] | None = None,
1101
+ ) -> MessageLog:
1102
+ """Updates a message log asynchronously.
1103
+
1104
+ Args:
1105
+ user_id (str): The user ID.
1106
+ company_id (str): The company ID.
1107
+ message_log_id (str): The ID of the message log to update.
1108
+ order (int): The order/sequence number (required).
1109
+ text (str | None): The updated log text content.
1110
+ status (MessageLogStatus | None): The updated status.
1111
+ details (MessageLogDetails | None): Updated additional details.
1112
+ uncited_references (MessageLogUncitedReferences | None): Updated uncited references.
1113
+ references (list[ContentReference] | None): Updated list of references.
1114
+
1115
+ Returns:
1116
+ MessageLog: The updated message log.
1117
+
1118
+ Raises:
1119
+ Exception: If the update fails.
1120
+
1121
+ """
1122
+ try:
1123
+ references_list = (
1124
+ map_references_with_original_index(references) if references else None
1125
+ )
1126
+ message_log = await unique_sdk.MessageLog.update_async(
1127
+ user_id=user_id,
1128
+ company_id=company_id,
1129
+ message_log_id=message_log_id,
1130
+ text=text,
1131
+ status=status.value if status else None,
1132
+ order=order,
1133
+ details=_get_model_dump_or_none(details),
1134
+ uncitedReferences=_get_model_dump_or_none(uncited_references),
1135
+ references=references_list, # type: ignore
1136
+ )
1137
+ return MessageLog(**message_log)
1138
+ except Exception as e:
1139
+ logger.error(f"Failed to update message log: {e}")
1140
+ raise e
1141
+
1142
+
1143
+ def create_message_execution(
1144
+ user_id: str,
1145
+ company_id: str,
1146
+ message_id: str,
1147
+ chat_id: str,
1148
+ type: MessageExecutionType = MessageExecutionType.DEEP_RESEARCH,
1149
+ seconds_remaining: int | None = None,
1150
+ percentage_completed: int | None = None,
1151
+ ) -> MessageExecution:
1152
+ """Creates a message execution synchronously.
1153
+
1154
+ Args:
1155
+ user_id (str): The user ID.
1156
+ company_id (str): The company ID.
1157
+ message_id (str): The ID of the message this execution belongs to.
1158
+ chat_id (str): The chat ID.
1159
+ type (MessageExecutionType): The type of execution. Defaults to DEEP_RESEARCH.
1160
+ seconds_remaining (int | None): Estimated seconds remaining for completion.
1161
+ percentage_completed (int | None): Percentage of completion (0-100).
1162
+
1163
+ Returns:
1164
+ MessageExecution: The created message execution.
1165
+
1166
+ Raises:
1167
+ Exception: If the creation fails.
1168
+
1169
+ """
1170
+ try:
1171
+ message_execution = unique_sdk.MessageExecution.create(
1172
+ user_id=user_id,
1173
+ company_id=company_id,
1174
+ messageId=message_id,
1175
+ chatId=chat_id,
1176
+ type=type.value,
1177
+ secondsRemaining=seconds_remaining,
1178
+ percentageCompleted=percentage_completed,
1179
+ )
1180
+ return MessageExecution(**message_execution)
1181
+ except Exception as e:
1182
+ logger.error(f"Failed to create message execution: {e}")
1183
+ raise e
1184
+
1185
+
1186
+ async def create_message_execution_async(
1187
+ user_id: str,
1188
+ company_id: str,
1189
+ message_id: str,
1190
+ chat_id: str,
1191
+ type: MessageExecutionType = MessageExecutionType.DEEP_RESEARCH,
1192
+ seconds_remaining: int | None = None,
1193
+ percentage_completed: int | None = None,
1194
+ ) -> MessageExecution:
1195
+ """Creates a message execution asynchronously.
1196
+
1197
+ Args:
1198
+ user_id (str): The user ID.
1199
+ company_id (str): The company ID.
1200
+ message_id (str): The ID of the message this execution belongs to.
1201
+ chat_id (str): The chat ID.
1202
+ type (MessageExecutionType): The type of execution. Defaults to DEEP_RESEARCH.
1203
+ seconds_remaining (int | None): Estimated seconds remaining for completion.
1204
+ percentage_completed (int | None): Percentage of completion (0-100).
1205
+
1206
+ Returns:
1207
+ MessageExecution: The created message execution.
1208
+
1209
+ Raises:
1210
+ Exception: If the creation fails.
1211
+
1212
+ """
1213
+ try:
1214
+ message_execution = await unique_sdk.MessageExecution.create_async(
1215
+ user_id=user_id,
1216
+ company_id=company_id,
1217
+ messageId=message_id,
1218
+ chatId=chat_id,
1219
+ type=type.value,
1220
+ secondsRemaining=seconds_remaining,
1221
+ percentageCompleted=percentage_completed,
1222
+ )
1223
+ return MessageExecution(**message_execution)
1224
+ except Exception as e:
1225
+ logger.error(f"Failed to create message execution: {e}")
1226
+ raise e
1227
+
1228
+
1229
+ def get_message_execution(
1230
+ user_id: str,
1231
+ company_id: str,
1232
+ message_id: str,
1233
+ ) -> MessageExecution:
1234
+ """Gets a message execution by message ID synchronously.
1235
+
1236
+ Args:
1237
+ user_id (str): The user ID.
1238
+ company_id (str): The company ID.
1239
+ message_id (str): The ID of the message to get execution for.
1240
+
1241
+ Returns:
1242
+ MessageExecution: The message execution.
1243
+
1244
+ Raises:
1245
+ Exception: If the retrieval fails.
1246
+
1247
+ """
1248
+ try:
1249
+ message_execution = unique_sdk.MessageExecution.get(
1250
+ user_id=user_id,
1251
+ company_id=company_id,
1252
+ messageId=message_id,
1253
+ )
1254
+ return MessageExecution(**message_execution)
1255
+ except Exception as e:
1256
+ logger.error(f"Failed to get message execution: {e}")
1257
+ raise e
1258
+
1259
+
1260
+ async def get_message_execution_async(
1261
+ user_id: str,
1262
+ company_id: str,
1263
+ message_id: str,
1264
+ ) -> MessageExecution:
1265
+ """Gets a message execution by message ID asynchronously.
1266
+
1267
+ Args:
1268
+ user_id (str): The user ID.
1269
+ company_id (str): The company ID.
1270
+ message_id (str): The ID of the message to get execution for.
1271
+
1272
+ Returns:
1273
+ MessageExecution: The message execution.
1274
+
1275
+ Raises:
1276
+ Exception: If the retrieval fails.
1277
+
1278
+ """
1279
+ try:
1280
+ message_execution = await unique_sdk.MessageExecution.get_async(
1281
+ user_id=user_id,
1282
+ company_id=company_id,
1283
+ messageId=message_id,
1284
+ )
1285
+ return MessageExecution(**message_execution)
1286
+ except Exception as e:
1287
+ logger.error(f"Failed to get message execution: {e}")
1288
+ raise e
1289
+
1290
+
1291
+ def update_message_execution(
1292
+ user_id: str,
1293
+ company_id: str,
1294
+ message_id: str,
1295
+ status: MessageExecutionUpdateStatus | None = None,
1296
+ seconds_remaining: int | None = None,
1297
+ percentage_completed: int | None = None,
1298
+ ) -> MessageExecution:
1299
+ """Updates a message execution synchronously.
1300
+
1301
+ Args:
1302
+ user_id (str): The user ID.
1303
+ company_id (str): The company ID.
1304
+ message_id (str): The ID of the message to update execution for.
1305
+ status (MessageExecutionUpdateStatus | None): The updated status (COMPLETED or FAILED). Defaults to None.
1306
+ seconds_remaining (int | None): Updated estimated seconds remaining.
1307
+ percentage_completed (int | None): Updated percentage of completion (0-100).
1308
+
1309
+ Returns:
1310
+ MessageExecution: The updated message execution.
1311
+
1312
+ Raises:
1313
+ Exception: If the update fails.
1314
+
1315
+ """
1316
+ try:
1317
+ status_value = status.value if status else None
1318
+ message_execution = unique_sdk.MessageExecution.update(
1319
+ user_id=user_id,
1320
+ company_id=company_id,
1321
+ messageId=message_id,
1322
+ status=status_value,
1323
+ secondsRemaining=seconds_remaining,
1324
+ percentageCompleted=percentage_completed,
1325
+ )
1326
+ return MessageExecution(**message_execution)
1327
+ except Exception as e:
1328
+ logger.error(f"Failed to update message execution: {e}")
1329
+ raise e
1330
+
1331
+
1332
+ async def update_message_execution_async(
1333
+ user_id: str,
1334
+ company_id: str,
1335
+ message_id: str,
1336
+ status: MessageExecutionUpdateStatus | None = None,
1337
+ seconds_remaining: int | None = None,
1338
+ percentage_completed: int | None = None,
1339
+ ) -> MessageExecution:
1340
+ """Updates a message execution asynchronously.
1341
+
1342
+ Args:
1343
+ user_id (str): The user ID.
1344
+ company_id (str): The company ID.
1345
+ message_id (str): The ID of the message to update execution for.
1346
+ status (MessageExecutionUpdateStatus | None): The updated status (COMPLETED or FAILED). Defaults to None.
1347
+ seconds_remaining (int | None): Updated estimated seconds remaining.
1348
+ percentage_completed (int | None): Updated percentage of completion (0-100).
1349
+
1350
+ Returns:
1351
+ MessageExecution: The updated message execution.
1352
+
1353
+ Raises:
1354
+ Exception: If the update fails.
1355
+
1356
+ """
1357
+ try:
1358
+ status_value = status.value if status else None
1359
+ message_execution = await unique_sdk.MessageExecution.update_async(
1360
+ user_id=user_id,
1361
+ company_id=company_id,
1362
+ messageId=message_id,
1363
+ status=status_value,
1364
+ secondsRemaining=seconds_remaining,
1365
+ percentageCompleted=percentage_completed,
1366
+ )
1367
+ return MessageExecution(**message_execution)
1368
+ except Exception as e:
1369
+ logger.error(f"Failed to update message execution: {e}")
1370
+ raise e