unique_toolkit 0.7.9__py3-none-any.whl → 1.33.3__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 (190) hide show
  1. unique_toolkit/__init__.py +36 -3
  2. unique_toolkit/_common/api_calling/human_verification_manager.py +357 -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 +225 -0
  14. unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
  15. unique_toolkit/_common/endpoint_builder.py +368 -0
  16. unique_toolkit/_common/endpoint_requestor.py +480 -0
  17. unique_toolkit/_common/exception.py +24 -0
  18. unique_toolkit/_common/experimental/endpoint_builder.py +368 -0
  19. unique_toolkit/_common/experimental/endpoint_requestor.py +488 -0
  20. unique_toolkit/_common/feature_flags/schema.py +9 -0
  21. unique_toolkit/_common/pydantic/rjsf_tags.py +936 -0
  22. unique_toolkit/_common/pydantic_helpers.py +174 -0
  23. unique_toolkit/_common/referencing.py +53 -0
  24. unique_toolkit/_common/string_utilities.py +140 -0
  25. unique_toolkit/_common/tests/test_referencing.py +521 -0
  26. unique_toolkit/_common/tests/test_string_utilities.py +506 -0
  27. unique_toolkit/_common/token/image_token_counting.py +67 -0
  28. unique_toolkit/_common/token/token_counting.py +204 -0
  29. unique_toolkit/_common/utils/__init__.py +1 -0
  30. unique_toolkit/_common/utils/files.py +43 -0
  31. unique_toolkit/_common/utils/image/encode.py +25 -0
  32. unique_toolkit/_common/utils/jinja/helpers.py +10 -0
  33. unique_toolkit/_common/utils/jinja/render.py +18 -0
  34. unique_toolkit/_common/utils/jinja/schema.py +65 -0
  35. unique_toolkit/_common/utils/jinja/utils.py +80 -0
  36. unique_toolkit/_common/utils/structured_output/__init__.py +1 -0
  37. unique_toolkit/_common/utils/structured_output/schema.py +5 -0
  38. unique_toolkit/_common/utils/write_configuration.py +51 -0
  39. unique_toolkit/_common/validators.py +101 -4
  40. unique_toolkit/agentic/__init__.py +1 -0
  41. unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +28 -0
  42. unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +278 -0
  43. unique_toolkit/agentic/evaluation/config.py +36 -0
  44. unique_toolkit/{evaluators → agentic/evaluation}/context_relevancy/prompts.py +25 -0
  45. unique_toolkit/agentic/evaluation/context_relevancy/schema.py +80 -0
  46. unique_toolkit/agentic/evaluation/context_relevancy/service.py +273 -0
  47. unique_toolkit/agentic/evaluation/evaluation_manager.py +218 -0
  48. unique_toolkit/agentic/evaluation/hallucination/constants.py +61 -0
  49. unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +112 -0
  50. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/prompts.py +1 -1
  51. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/service.py +20 -16
  52. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/utils.py +32 -21
  53. unique_toolkit/{evaluators → agentic/evaluation}/output_parser.py +20 -2
  54. unique_toolkit/{evaluators → agentic/evaluation}/schemas.py +27 -7
  55. unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +253 -0
  56. unique_toolkit/agentic/evaluation/tests/test_output_parser.py +87 -0
  57. unique_toolkit/agentic/history_manager/history_construction_with_contents.py +298 -0
  58. unique_toolkit/agentic/history_manager/history_manager.py +241 -0
  59. unique_toolkit/agentic/history_manager/loop_token_reducer.py +484 -0
  60. unique_toolkit/agentic/history_manager/utils.py +96 -0
  61. unique_toolkit/agentic/message_log_manager/__init__.py +5 -0
  62. unique_toolkit/agentic/message_log_manager/service.py +93 -0
  63. unique_toolkit/agentic/postprocessor/postprocessor_manager.py +212 -0
  64. unique_toolkit/agentic/reference_manager/reference_manager.py +103 -0
  65. unique_toolkit/agentic/responses_api/__init__.py +19 -0
  66. unique_toolkit/agentic/responses_api/postprocessors/code_display.py +71 -0
  67. unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +297 -0
  68. unique_toolkit/agentic/responses_api/stream_handler.py +15 -0
  69. unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +141 -0
  70. unique_toolkit/agentic/thinking_manager/thinking_manager.py +103 -0
  71. unique_toolkit/agentic/tools/__init__.py +1 -0
  72. unique_toolkit/agentic/tools/a2a/__init__.py +36 -0
  73. unique_toolkit/agentic/tools/a2a/config.py +17 -0
  74. unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +15 -0
  75. unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +66 -0
  76. unique_toolkit/agentic/tools/a2a/evaluation/config.py +55 -0
  77. unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +260 -0
  78. unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +9 -0
  79. unique_toolkit/agentic/tools/a2a/manager.py +55 -0
  80. unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +21 -0
  81. unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +240 -0
  82. unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +84 -0
  83. unique_toolkit/agentic/tools/a2a/postprocessing/config.py +78 -0
  84. unique_toolkit/agentic/tools/a2a/postprocessing/display.py +264 -0
  85. unique_toolkit/agentic/tools/a2a/postprocessing/references.py +101 -0
  86. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +421 -0
  87. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +2103 -0
  88. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +603 -0
  89. unique_toolkit/agentic/tools/a2a/prompts.py +46 -0
  90. unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +6 -0
  91. unique_toolkit/agentic/tools/a2a/response_watcher/service.py +91 -0
  92. unique_toolkit/agentic/tools/a2a/tool/__init__.py +4 -0
  93. unique_toolkit/agentic/tools/a2a/tool/_memory.py +26 -0
  94. unique_toolkit/agentic/tools/a2a/tool/_schema.py +9 -0
  95. unique_toolkit/agentic/tools/a2a/tool/config.py +158 -0
  96. unique_toolkit/agentic/tools/a2a/tool/service.py +393 -0
  97. unique_toolkit/agentic/tools/agent_chunks_hanlder.py +65 -0
  98. unique_toolkit/agentic/tools/config.py +128 -0
  99. unique_toolkit/agentic/tools/factory.py +44 -0
  100. unique_toolkit/agentic/tools/mcp/__init__.py +4 -0
  101. unique_toolkit/agentic/tools/mcp/manager.py +71 -0
  102. unique_toolkit/agentic/tools/mcp/models.py +28 -0
  103. unique_toolkit/agentic/tools/mcp/tool_wrapper.py +234 -0
  104. unique_toolkit/agentic/tools/openai_builtin/__init__.py +11 -0
  105. unique_toolkit/agentic/tools/openai_builtin/base.py +46 -0
  106. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +8 -0
  107. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +88 -0
  108. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +250 -0
  109. unique_toolkit/agentic/tools/openai_builtin/manager.py +79 -0
  110. unique_toolkit/agentic/tools/schemas.py +145 -0
  111. unique_toolkit/agentic/tools/test/test_mcp_manager.py +536 -0
  112. unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +445 -0
  113. unique_toolkit/agentic/tools/tool.py +187 -0
  114. unique_toolkit/agentic/tools/tool_manager.py +492 -0
  115. unique_toolkit/agentic/tools/tool_progress_reporter.py +285 -0
  116. unique_toolkit/agentic/tools/utils/__init__.py +19 -0
  117. unique_toolkit/agentic/tools/utils/execution/__init__.py +1 -0
  118. unique_toolkit/agentic/tools/utils/execution/execution.py +286 -0
  119. unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  120. unique_toolkit/agentic/tools/utils/source_handling/schema.py +21 -0
  121. unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +207 -0
  122. unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +216 -0
  123. unique_toolkit/app/__init__.py +9 -0
  124. unique_toolkit/app/dev_util.py +180 -0
  125. unique_toolkit/app/fast_api_factory.py +131 -0
  126. unique_toolkit/app/init_sdk.py +32 -1
  127. unique_toolkit/app/schemas.py +206 -31
  128. unique_toolkit/app/unique_settings.py +367 -0
  129. unique_toolkit/app/webhook.py +77 -0
  130. unique_toolkit/chat/__init__.py +8 -1
  131. unique_toolkit/chat/deprecated/service.py +232 -0
  132. unique_toolkit/chat/functions.py +648 -78
  133. unique_toolkit/chat/rendering.py +34 -0
  134. unique_toolkit/chat/responses_api.py +461 -0
  135. unique_toolkit/chat/schemas.py +134 -2
  136. unique_toolkit/chat/service.py +115 -767
  137. unique_toolkit/content/functions.py +353 -8
  138. unique_toolkit/content/schemas.py +128 -15
  139. unique_toolkit/content/service.py +321 -45
  140. unique_toolkit/content/smart_rules.py +301 -0
  141. unique_toolkit/content/utils.py +10 -3
  142. unique_toolkit/data_extraction/README.md +96 -0
  143. unique_toolkit/data_extraction/__init__.py +11 -0
  144. unique_toolkit/data_extraction/augmented/__init__.py +5 -0
  145. unique_toolkit/data_extraction/augmented/service.py +93 -0
  146. unique_toolkit/data_extraction/base.py +25 -0
  147. unique_toolkit/data_extraction/basic/__init__.py +11 -0
  148. unique_toolkit/data_extraction/basic/config.py +18 -0
  149. unique_toolkit/data_extraction/basic/prompt.py +13 -0
  150. unique_toolkit/data_extraction/basic/service.py +55 -0
  151. unique_toolkit/embedding/service.py +103 -12
  152. unique_toolkit/framework_utilities/__init__.py +1 -0
  153. unique_toolkit/framework_utilities/langchain/__init__.py +10 -0
  154. unique_toolkit/framework_utilities/langchain/client.py +71 -0
  155. unique_toolkit/framework_utilities/langchain/history.py +19 -0
  156. unique_toolkit/framework_utilities/openai/__init__.py +6 -0
  157. unique_toolkit/framework_utilities/openai/client.py +84 -0
  158. unique_toolkit/framework_utilities/openai/message_builder.py +229 -0
  159. unique_toolkit/framework_utilities/utils.py +23 -0
  160. unique_toolkit/language_model/__init__.py +3 -0
  161. unique_toolkit/language_model/_responses_api_utils.py +93 -0
  162. unique_toolkit/language_model/builder.py +27 -11
  163. unique_toolkit/language_model/default_language_model.py +3 -0
  164. unique_toolkit/language_model/functions.py +345 -43
  165. unique_toolkit/language_model/infos.py +1288 -46
  166. unique_toolkit/language_model/reference.py +242 -0
  167. unique_toolkit/language_model/schemas.py +481 -49
  168. unique_toolkit/language_model/service.py +229 -28
  169. unique_toolkit/protocols/support.py +145 -0
  170. unique_toolkit/services/__init__.py +7 -0
  171. unique_toolkit/services/chat_service.py +1631 -0
  172. unique_toolkit/services/knowledge_base.py +1094 -0
  173. unique_toolkit/short_term_memory/service.py +178 -41
  174. unique_toolkit/smart_rules/__init__.py +0 -0
  175. unique_toolkit/smart_rules/compile.py +56 -0
  176. unique_toolkit/test_utilities/events.py +197 -0
  177. unique_toolkit-1.33.3.dist-info/METADATA +1145 -0
  178. unique_toolkit-1.33.3.dist-info/RECORD +205 -0
  179. unique_toolkit/evaluators/__init__.py +0 -1
  180. unique_toolkit/evaluators/config.py +0 -35
  181. unique_toolkit/evaluators/constants.py +0 -1
  182. unique_toolkit/evaluators/context_relevancy/constants.py +0 -32
  183. unique_toolkit/evaluators/context_relevancy/service.py +0 -53
  184. unique_toolkit/evaluators/context_relevancy/utils.py +0 -142
  185. unique_toolkit/evaluators/hallucination/constants.py +0 -41
  186. unique_toolkit-0.7.9.dist-info/METADATA +0 -413
  187. unique_toolkit-0.7.9.dist-info/RECORD +0 -64
  188. /unique_toolkit/{evaluators → agentic/evaluation}/exception.py +0 -0
  189. {unique_toolkit-0.7.9.dist-info → unique_toolkit-1.33.3.dist-info}/LICENSE +0 -0
  190. {unique_toolkit-0.7.9.dist-info → unique_toolkit-1.33.3.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:
@@ -225,9 +263,8 @@ def create_message(
225
263
  references: list[ContentReference] | None = None,
226
264
  debug_info: dict | None = None,
227
265
  set_completed_at: bool | None = False,
228
- ):
229
- """
230
- Creates a message in the chat session synchronously.
266
+ ) -> ChatMessage:
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,21 @@ 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] "
518
+ roles_to_filter = [ChatMessageRole.SYSTEM.value.lower()]
470
519
 
471
520
  # Remove the last two messages
472
521
  messages = messages["data"][:-2] # type: ignore
473
522
  filtered_messages = []
474
523
  for message in messages:
475
- if message["text"] is None:
476
- continue
477
- elif SYSTEM_MESSAGE_PREFIX in message["text"]:
524
+ if (
525
+ message["text"] is None
526
+ or SYSTEM_MESSAGE_PREFIX in message["text"]
527
+ or message["role"].lower() in roles_to_filter
528
+ ):
478
529
  continue
479
- else:
480
- filtered_messages.append(message)
530
+ filtered_messages.append(message)
481
531
 
482
532
  return filtered_messages
483
533
 
@@ -493,8 +543,7 @@ def create_message_assessment(
493
543
  label: ChatMessageAssessmentLabel | None = None,
494
544
  is_visible: bool = True,
495
545
  ) -> ChatMessageAssessment:
496
- """
497
- Creates a message assessment for an assistant message synchronously.
546
+ """Creates a message assessment for an assistant message synchronously.
498
547
 
499
548
  Args:
500
549
  user_id (str): The user ID.
@@ -512,6 +561,7 @@ def create_message_assessment(
512
561
 
513
562
  Raises:
514
563
  Exception: If the creation fails
564
+
515
565
  """
516
566
  try:
517
567
  assessment = unique_sdk.MessageAssessment.create(
@@ -542,8 +592,7 @@ async def create_message_assessment_async(
542
592
  label: ChatMessageAssessmentLabel | None = None,
543
593
  is_visible: bool = True,
544
594
  ) -> ChatMessageAssessment:
545
- """
546
- Creates a message assessment for an assistant message asynchronously.
595
+ """Creates a message assessment for an assistant message asynchronously.
547
596
 
548
597
  Args:
549
598
  user_id (str): The user ID.
@@ -561,6 +610,7 @@ async def create_message_assessment_async(
561
610
 
562
611
  Raises:
563
612
  Exception: If the creation fails
613
+
564
614
  """
565
615
  try:
566
616
  assessment = await unique_sdk.MessageAssessment.create_async(
@@ -590,8 +640,7 @@ def modify_message_assessment(
590
640
  explanation: str | None = None,
591
641
  label: ChatMessageAssessmentLabel | None = None,
592
642
  ) -> ChatMessageAssessment:
593
- """
594
- Modifies a message assessment for an assistant message synchronously.
643
+ """Modifies a message assessment for an assistant message synchronously.
595
644
 
596
645
  Args:
597
646
  user_id (str): The user ID.
@@ -608,6 +657,7 @@ def modify_message_assessment(
608
657
 
609
658
  Raises:
610
659
  Exception: If the modification fails
660
+
611
661
  """
612
662
  try:
613
663
  assessment = unique_sdk.MessageAssessment.modify(
@@ -636,8 +686,7 @@ async def modify_message_assessment_async(
636
686
  explanation: str | None = None,
637
687
  label: ChatMessageAssessmentLabel | None = None,
638
688
  ) -> ChatMessageAssessment:
639
- """
640
- Modifies a message assessment for an assistant message asynchronously.
689
+ """Modifies a message assessment for an assistant message asynchronously.
641
690
 
642
691
  Args:
643
692
  user_id (str): The user ID.
@@ -654,6 +703,7 @@ async def modify_message_assessment_async(
654
703
 
655
704
  Raises:
656
705
  Exception: If the modification fails
706
+
657
707
  """
658
708
  try:
659
709
  assessment = await unique_sdk.MessageAssessment.modify_async(
@@ -672,6 +722,7 @@ async def modify_message_assessment_async(
672
722
  raise e
673
723
 
674
724
 
725
+ @deprecated("Use stream_complete_with_references instead")
675
726
  def stream_complete_to_chat(
676
727
  company_id: str,
677
728
  user_id: str,
@@ -679,18 +730,54 @@ def stream_complete_to_chat(
679
730
  user_message_id: str,
680
731
  chat_id: str,
681
732
  assistant_id: str,
682
- messages: LanguageModelMessages,
733
+ messages: LanguageModelMessages | list[ChatCompletionMessageParam],
683
734
  model_name: LanguageModelName | str,
684
- content_chunks: list[ContentChunk] = [],
735
+ content_chunks: list[ContentChunk] | None = None,
685
736
  debug_info: dict = {},
686
737
  temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
687
738
  timeout: int = DEFAULT_COMPLETE_TIMEOUT,
688
- tools: list[LanguageModelTool] | None = None,
739
+ tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
689
740
  start_text: str | None = None,
690
741
  other_options: dict | None = None,
691
742
  ) -> LanguageModelStreamResponse:
692
- """
693
- Streams a completion synchronously.
743
+ return stream_complete_with_references(
744
+ company_id=company_id,
745
+ user_id=user_id,
746
+ assistant_message_id=assistant_message_id,
747
+ user_message_id=user_message_id,
748
+ chat_id=chat_id,
749
+ assistant_id=assistant_id,
750
+ messages=messages,
751
+ model_name=model_name,
752
+ content_chunks=content_chunks,
753
+ debug_info=debug_info,
754
+ temperature=temperature,
755
+ timeout=timeout,
756
+ tools=tools,
757
+ start_text=start_text,
758
+ other_options=other_options,
759
+ )
760
+
761
+
762
+ def stream_complete_with_references(
763
+ company_id: str,
764
+ user_id: str,
765
+ assistant_message_id: str,
766
+ user_message_id: str,
767
+ chat_id: str,
768
+ assistant_id: str,
769
+ messages: LanguageModelMessages | list[ChatCompletionMessageParam],
770
+ model_name: LanguageModelName | str,
771
+ content_chunks: list[ContentChunk] | None = None,
772
+ debug_info: dict | None = None,
773
+ temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
774
+ timeout: int = DEFAULT_COMPLETE_TIMEOUT,
775
+ tools: Sequence[LanguageModelTool | LanguageModelToolDescription] | None = None,
776
+ start_text: str | None = None,
777
+ tool_choice: ChatCompletionToolChoiceOptionParam | None = None,
778
+ other_options: dict | None = None,
779
+ ) -> LanguageModelStreamResponse:
780
+ """Streams a completion synchronously.
694
781
 
695
782
  Args:
696
783
  company_id (str): The company ID associated with the request.
@@ -705,20 +792,24 @@ def stream_complete_to_chat(
705
792
  debug_info (dict): Debug information.
706
793
  temperature (float): Temperature setting.
707
794
  timeout (int): Timeout in milliseconds.
708
- tools (Optional[list[LanguageModelTool]]): Optional tools.
795
+ tools (Optional[list[LanguageModelTool | LanguageModelToolDescription ]]): Optional tools.
709
796
  start_text (Optional[str]): Starting text.
710
797
  other_options (Optional[dict]): Additional options.
711
798
 
712
799
  Returns:
713
800
  LanguageModelStreamResponse: The streaming response object.
801
+
714
802
  """
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,
803
+ options, model, messages_dict, search_context = (
804
+ _prepare_all_completions_params_util(
805
+ messages=messages,
806
+ model_name=model_name,
807
+ temperature=temperature,
808
+ tools=tools,
809
+ other_options=other_options,
810
+ tool_choice=tool_choice,
811
+ content_chunks=content_chunks or [],
812
+ )
722
813
  )
723
814
 
724
815
  try:
@@ -727,16 +818,13 @@ def stream_complete_to_chat(
727
818
  company_id=company_id,
728
819
  assistantMessageId=assistant_message_id,
729
820
  userMessageId=user_message_id,
730
- messages=cast(
731
- list[unique_sdk.Integrated.ChatCompletionRequestMessage],
732
- messages_dict,
733
- ),
821
+ messages=messages_dict,
734
822
  chatId=chat_id,
735
823
  searchContext=search_context,
736
824
  model=model,
737
825
  timeout=timeout,
738
826
  assistantId=assistant_id,
739
- debugInfo=debug_info,
827
+ debugInfo=debug_info or {},
740
828
  options=options, # type: ignore
741
829
  startText=start_text,
742
830
  )
@@ -746,6 +834,7 @@ def stream_complete_to_chat(
746
834
  raise e
747
835
 
748
836
 
837
+ @deprecated("Use stream_complete_with_references_async instead")
749
838
  async def stream_complete_to_chat_async(
750
839
  company_id: str,
751
840
  user_id: str,
@@ -753,31 +842,71 @@ async def stream_complete_to_chat_async(
753
842
  user_message_id: str,
754
843
  chat_id: str,
755
844
  assistant_id: str,
756
- messages: LanguageModelMessages,
845
+ messages: LanguageModelMessages | list[ChatCompletionMessageParam],
757
846
  model_name: LanguageModelName | str,
758
- content_chunks: list[ContentChunk] = [],
847
+ content_chunks: list[ContentChunk] | None = None,
759
848
  debug_info: dict = {},
760
849
  temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
761
850
  timeout: int = DEFAULT_COMPLETE_TIMEOUT,
762
- tools: list[LanguageModelTool] | None = None,
851
+ tools: list[LanguageModelTool | LanguageModelToolDescription] | None = None,
763
852
  start_text: str | None = None,
764
853
  other_options: dict | None = None,
765
854
  ) -> LanguageModelStreamResponse:
766
- """
767
- Streams a completion asynchronously.
855
+ return await stream_complete_with_references_async(
856
+ company_id=company_id,
857
+ user_id=user_id,
858
+ assistant_message_id=assistant_message_id,
859
+ user_message_id=user_message_id,
860
+ chat_id=chat_id,
861
+ assistant_id=assistant_id,
862
+ messages=messages,
863
+ model_name=model_name,
864
+ content_chunks=content_chunks,
865
+ debug_info=debug_info,
866
+ temperature=temperature,
867
+ timeout=timeout,
868
+ tools=tools,
869
+ start_text=start_text,
870
+ other_options=other_options,
871
+ )
872
+
873
+
874
+ async def stream_complete_with_references_async(
875
+ company_id: str,
876
+ user_id: str,
877
+ assistant_message_id: str,
878
+ user_message_id: str,
879
+ chat_id: str,
880
+ assistant_id: str,
881
+ messages: LanguageModelMessages | list[ChatCompletionMessageParam],
882
+ model_name: LanguageModelName | str,
883
+ content_chunks: list[ContentChunk] | None = None,
884
+ debug_info: dict | None = None,
885
+ temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
886
+ timeout: int = DEFAULT_COMPLETE_TIMEOUT,
887
+ tools: Sequence[LanguageModelTool | LanguageModelToolDescription] | None = None,
888
+ tool_choice: ChatCompletionToolChoiceOptionParam | None = None,
889
+ start_text: str | None = None,
890
+ other_options: dict | None = None,
891
+ ) -> LanguageModelStreamResponse:
892
+ """Streams a completion asynchronously.
768
893
 
769
894
  Args: [same as stream_complete]
770
895
 
771
896
  Returns:
772
897
  LanguageModelStreamResponse: The streaming response object.
898
+
773
899
  """
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,
900
+ options, model, messages_dict, search_context = (
901
+ _prepare_all_completions_params_util(
902
+ messages=messages,
903
+ model_name=model_name,
904
+ temperature=temperature,
905
+ tools=tools,
906
+ tool_choice=tool_choice,
907
+ other_options=other_options,
908
+ content_chunks=content_chunks or [],
909
+ )
781
910
  )
782
911
 
783
912
  try:
@@ -786,16 +915,13 @@ async def stream_complete_to_chat_async(
786
915
  company_id=company_id,
787
916
  assistantMessageId=assistant_message_id,
788
917
  userMessageId=user_message_id,
789
- messages=cast(
790
- list[unique_sdk.Integrated.ChatCompletionRequestMessage],
791
- messages_dict,
792
- ),
918
+ messages=messages_dict,
793
919
  chatId=chat_id,
794
920
  searchContext=search_context,
795
921
  model=model,
796
922
  timeout=timeout,
797
923
  assistantId=assistant_id,
798
- debugInfo=debug_info,
924
+ debugInfo=debug_info or {},
799
925
  options=options, # type: ignore
800
926
  startText=start_text,
801
927
  )
@@ -803,3 +929,447 @@ async def stream_complete_to_chat_async(
803
929
  except Exception as e:
804
930
  logger.error(f"Error streaming completion: {e}")
805
931
  raise e
932
+
933
+
934
+ def _get_model_dump_or_none(model: BaseModel | None) -> dict | None:
935
+ if model is None:
936
+ return None
937
+ return model.model_dump()
938
+
939
+
940
+ def create_message_log(
941
+ user_id: str,
942
+ company_id: str,
943
+ message_id: str,
944
+ text: str,
945
+ status: MessageLogStatus,
946
+ order: int,
947
+ details: MessageLogDetails | None = None,
948
+ uncited_references: MessageLogUncitedReferences | None = None,
949
+ references: list[ContentReference] | None = None,
950
+ ) -> MessageLog:
951
+ """Creates a message log synchronously.
952
+
953
+ Args:
954
+ user_id (str): The user ID.
955
+ company_id (str): The company ID.
956
+ message_id (str): The ID of the message this log belongs to.
957
+ text (str): The log text content.
958
+ status (MessageLogStatus): The status of this log entry.
959
+ order (int): The order/sequence number of this log entry.
960
+ details (MessageLogDetails | None): Additional details about this log entry.
961
+ uncited_references (MessageLogUncitedReferences | None): References that are not cited.
962
+ references (list[ContentReference] | None): List of references for this log.
963
+
964
+ Returns:
965
+ MessageLog: The created message log.
966
+
967
+ Raises:
968
+ Exception: If the creation fails.
969
+
970
+ """
971
+ try:
972
+ references_list = (
973
+ map_references_with_original_index(references) if references else None
974
+ )
975
+ message_log = unique_sdk.MessageLog.create(
976
+ user_id=user_id,
977
+ company_id=company_id,
978
+ messageId=message_id,
979
+ text=text,
980
+ status=status.value,
981
+ order=order,
982
+ details=_get_model_dump_or_none(details),
983
+ uncitedReferences=_get_model_dump_or_none(uncited_references),
984
+ references=references_list, # type: ignore
985
+ )
986
+ return MessageLog(**message_log)
987
+ except Exception as e:
988
+ logger.error(f"Failed to create message log: {e}")
989
+ raise e
990
+
991
+
992
+ async def create_message_log_async(
993
+ user_id: str,
994
+ company_id: str,
995
+ message_id: str,
996
+ text: str,
997
+ status: MessageLogStatus,
998
+ order: int,
999
+ details: MessageLogDetails | None = None,
1000
+ uncited_references: MessageLogUncitedReferences | None = None,
1001
+ references: list[ContentReference] | None = None,
1002
+ ) -> MessageLog:
1003
+ """Creates a message log asynchronously.
1004
+
1005
+ Args:
1006
+ user_id (str): The user ID.
1007
+ company_id (str): The company ID.
1008
+ message_id (str): The ID of the message this log belongs to.
1009
+ text (str): The log text content.
1010
+ status (MessageLogStatus): The status of this log entry.
1011
+ order (int): The order/sequence number of this log entry.
1012
+ details (MessageLogDetails | None): Additional details about this log entry.
1013
+ uncited_references (MessageLogUncitedReferences | None): References that are not cited.
1014
+ references (list[ContentReference] | None): List of references for this log.
1015
+
1016
+ Returns:
1017
+ MessageLog: The created message log.
1018
+
1019
+ Raises:
1020
+ Exception: If the creation fails.
1021
+
1022
+ """
1023
+ try:
1024
+ references_list = (
1025
+ map_references_with_original_index(references) if references else None
1026
+ )
1027
+ message_log = await unique_sdk.MessageLog.create_async(
1028
+ user_id=user_id,
1029
+ company_id=company_id,
1030
+ messageId=message_id,
1031
+ text=text,
1032
+ status=status.value,
1033
+ order=order,
1034
+ details=_get_model_dump_or_none(details),
1035
+ uncitedReferences=_get_model_dump_or_none(uncited_references),
1036
+ references=references_list, # type: ignore
1037
+ )
1038
+ return MessageLog(**message_log)
1039
+ except Exception as e:
1040
+ logger.error(f"Failed to create message log: {e}")
1041
+ raise e
1042
+
1043
+
1044
+ def update_message_log(
1045
+ user_id: str,
1046
+ company_id: str,
1047
+ message_log_id: str,
1048
+ order: int,
1049
+ text: str | None = None,
1050
+ status: MessageLogStatus | None = None,
1051
+ details: MessageLogDetails | None = None,
1052
+ uncited_references: MessageLogUncitedReferences | None = None,
1053
+ references: list[ContentReference] | None = None,
1054
+ ) -> MessageLog:
1055
+ """Updates a message log synchronously.
1056
+
1057
+ Args:
1058
+ user_id (str): The user ID.
1059
+ company_id (str): The company ID.
1060
+ message_log_id (str): The ID of the message log to update.
1061
+ order (int): The order/sequence number (required).
1062
+ text (str | None): The updated log text content.
1063
+ status (MessageLogStatus | None): The updated status.
1064
+ details (MessageLogDetails | None): Updated additional details.
1065
+ uncited_references (MessageLogUncitedReferences | None): Updated uncited references.
1066
+ references (list[ContentReference] | None): Updated list of references.
1067
+
1068
+ Returns:
1069
+ MessageLog: The updated message log.
1070
+
1071
+ Raises:
1072
+ Exception: If the update fails.
1073
+
1074
+ """
1075
+ try:
1076
+ references_list = (
1077
+ map_references_with_original_index(references) if references else None
1078
+ )
1079
+ message_log = unique_sdk.MessageLog.update(
1080
+ user_id=user_id,
1081
+ company_id=company_id,
1082
+ message_log_id=message_log_id,
1083
+ text=text,
1084
+ status=status.value if status else None,
1085
+ order=order,
1086
+ details=_get_model_dump_or_none(details),
1087
+ uncitedReferences=_get_model_dump_or_none(uncited_references),
1088
+ references=references_list, # type: ignore
1089
+ )
1090
+ return MessageLog(**message_log)
1091
+ except Exception as e:
1092
+ logger.error(f"Failed to update message log: {e}")
1093
+ raise e
1094
+
1095
+
1096
+ async def update_message_log_async(
1097
+ user_id: str,
1098
+ company_id: str,
1099
+ message_log_id: str,
1100
+ order: int,
1101
+ text: str | None = None,
1102
+ status: MessageLogStatus | None = None,
1103
+ details: MessageLogDetails | None = None,
1104
+ uncited_references: MessageLogUncitedReferences | None = None,
1105
+ references: list[ContentReference] | None = None,
1106
+ ) -> MessageLog:
1107
+ """Updates a message log asynchronously.
1108
+
1109
+ Args:
1110
+ user_id (str): The user ID.
1111
+ company_id (str): The company ID.
1112
+ message_log_id (str): The ID of the message log to update.
1113
+ order (int): The order/sequence number (required).
1114
+ text (str | None): The updated log text content.
1115
+ status (MessageLogStatus | None): The updated status.
1116
+ details (MessageLogDetails | None): Updated additional details.
1117
+ uncited_references (MessageLogUncitedReferences | None): Updated uncited references.
1118
+ references (list[ContentReference] | None): Updated list of references.
1119
+
1120
+ Returns:
1121
+ MessageLog: The updated message log.
1122
+
1123
+ Raises:
1124
+ Exception: If the update fails.
1125
+
1126
+ """
1127
+ try:
1128
+ references_list = (
1129
+ map_references_with_original_index(references) if references else None
1130
+ )
1131
+ message_log = await unique_sdk.MessageLog.update_async(
1132
+ user_id=user_id,
1133
+ company_id=company_id,
1134
+ message_log_id=message_log_id,
1135
+ text=text,
1136
+ status=status.value if status else None,
1137
+ order=order,
1138
+ details=_get_model_dump_or_none(details),
1139
+ uncitedReferences=_get_model_dump_or_none(uncited_references),
1140
+ references=references_list, # type: ignore
1141
+ )
1142
+ return MessageLog(**message_log)
1143
+ except Exception as e:
1144
+ logger.error(f"Failed to update message log: {e}")
1145
+ raise e
1146
+
1147
+
1148
+ def create_message_execution(
1149
+ user_id: str,
1150
+ company_id: str,
1151
+ message_id: str,
1152
+ chat_id: str,
1153
+ type: MessageExecutionType = MessageExecutionType.DEEP_RESEARCH,
1154
+ seconds_remaining: int | None = None,
1155
+ percentage_completed: int | None = None,
1156
+ ) -> MessageExecution:
1157
+ """Creates a message execution synchronously.
1158
+
1159
+ Args:
1160
+ user_id (str): The user ID.
1161
+ company_id (str): The company ID.
1162
+ message_id (str): The ID of the message this execution belongs to.
1163
+ chat_id (str): The chat ID.
1164
+ type (MessageExecutionType): The type of execution. Defaults to DEEP_RESEARCH.
1165
+ seconds_remaining (int | None): Estimated seconds remaining for completion.
1166
+ percentage_completed (int | None): Percentage of completion (0-100).
1167
+
1168
+ Returns:
1169
+ MessageExecution: The created message execution.
1170
+
1171
+ Raises:
1172
+ Exception: If the creation fails.
1173
+
1174
+ """
1175
+ try:
1176
+ message_execution = unique_sdk.MessageExecution.create(
1177
+ user_id=user_id,
1178
+ company_id=company_id,
1179
+ messageId=message_id,
1180
+ chatId=chat_id,
1181
+ type=type.value,
1182
+ secondsRemaining=seconds_remaining,
1183
+ percentageCompleted=percentage_completed,
1184
+ )
1185
+ return MessageExecution(**message_execution)
1186
+ except Exception as e:
1187
+ logger.error(f"Failed to create message execution: {e}")
1188
+ raise e
1189
+
1190
+
1191
+ async def create_message_execution_async(
1192
+ user_id: str,
1193
+ company_id: str,
1194
+ message_id: str,
1195
+ chat_id: str,
1196
+ type: MessageExecutionType = MessageExecutionType.DEEP_RESEARCH,
1197
+ seconds_remaining: int | None = None,
1198
+ percentage_completed: int | None = None,
1199
+ ) -> MessageExecution:
1200
+ """Creates a message execution asynchronously.
1201
+
1202
+ Args:
1203
+ user_id (str): The user ID.
1204
+ company_id (str): The company ID.
1205
+ message_id (str): The ID of the message this execution belongs to.
1206
+ chat_id (str): The chat ID.
1207
+ type (MessageExecutionType): The type of execution. Defaults to DEEP_RESEARCH.
1208
+ seconds_remaining (int | None): Estimated seconds remaining for completion.
1209
+ percentage_completed (int | None): Percentage of completion (0-100).
1210
+
1211
+ Returns:
1212
+ MessageExecution: The created message execution.
1213
+
1214
+ Raises:
1215
+ Exception: If the creation fails.
1216
+
1217
+ """
1218
+ try:
1219
+ message_execution = await unique_sdk.MessageExecution.create_async(
1220
+ user_id=user_id,
1221
+ company_id=company_id,
1222
+ messageId=message_id,
1223
+ chatId=chat_id,
1224
+ type=type.value,
1225
+ secondsRemaining=seconds_remaining,
1226
+ percentageCompleted=percentage_completed,
1227
+ )
1228
+ return MessageExecution(**message_execution)
1229
+ except Exception as e:
1230
+ logger.error(f"Failed to create message execution: {e}")
1231
+ raise e
1232
+
1233
+
1234
+ def get_message_execution(
1235
+ user_id: str,
1236
+ company_id: str,
1237
+ message_id: str,
1238
+ ) -> MessageExecution:
1239
+ """Gets a message execution by message ID synchronously.
1240
+
1241
+ Args:
1242
+ user_id (str): The user ID.
1243
+ company_id (str): The company ID.
1244
+ message_id (str): The ID of the message to get execution for.
1245
+
1246
+ Returns:
1247
+ MessageExecution: The message execution.
1248
+
1249
+ Raises:
1250
+ Exception: If the retrieval fails.
1251
+
1252
+ """
1253
+ try:
1254
+ message_execution = unique_sdk.MessageExecution.get(
1255
+ user_id=user_id,
1256
+ company_id=company_id,
1257
+ messageId=message_id,
1258
+ )
1259
+ return MessageExecution(**message_execution)
1260
+ except Exception as e:
1261
+ logger.error(f"Failed to get message execution: {e}")
1262
+ raise e
1263
+
1264
+
1265
+ async def get_message_execution_async(
1266
+ user_id: str,
1267
+ company_id: str,
1268
+ message_id: str,
1269
+ ) -> MessageExecution:
1270
+ """Gets a message execution by message ID asynchronously.
1271
+
1272
+ Args:
1273
+ user_id (str): The user ID.
1274
+ company_id (str): The company ID.
1275
+ message_id (str): The ID of the message to get execution for.
1276
+
1277
+ Returns:
1278
+ MessageExecution: The message execution.
1279
+
1280
+ Raises:
1281
+ Exception: If the retrieval fails.
1282
+
1283
+ """
1284
+ try:
1285
+ message_execution = await unique_sdk.MessageExecution.get_async(
1286
+ user_id=user_id,
1287
+ company_id=company_id,
1288
+ messageId=message_id,
1289
+ )
1290
+ return MessageExecution(**message_execution)
1291
+ except Exception as e:
1292
+ logger.error(f"Failed to get message execution: {e}")
1293
+ raise e
1294
+
1295
+
1296
+ def update_message_execution(
1297
+ user_id: str,
1298
+ company_id: str,
1299
+ message_id: str,
1300
+ status: MessageExecutionUpdateStatus | None = None,
1301
+ seconds_remaining: int | None = None,
1302
+ percentage_completed: int | None = None,
1303
+ ) -> MessageExecution:
1304
+ """Updates a message execution synchronously.
1305
+
1306
+ Args:
1307
+ user_id (str): The user ID.
1308
+ company_id (str): The company ID.
1309
+ message_id (str): The ID of the message to update execution for.
1310
+ status (MessageExecutionUpdateStatus | None): The updated status (COMPLETED or FAILED). Defaults to None.
1311
+ seconds_remaining (int | None): Updated estimated seconds remaining.
1312
+ percentage_completed (int | None): Updated percentage of completion (0-100).
1313
+
1314
+ Returns:
1315
+ MessageExecution: The updated message execution.
1316
+
1317
+ Raises:
1318
+ Exception: If the update fails.
1319
+
1320
+ """
1321
+ try:
1322
+ status_value = status.value if status else None
1323
+ message_execution = unique_sdk.MessageExecution.update(
1324
+ user_id=user_id,
1325
+ company_id=company_id,
1326
+ messageId=message_id,
1327
+ status=status_value,
1328
+ secondsRemaining=seconds_remaining,
1329
+ percentageCompleted=percentage_completed,
1330
+ )
1331
+ return MessageExecution(**message_execution)
1332
+ except Exception as e:
1333
+ logger.error(f"Failed to update message execution: {e}")
1334
+ raise e
1335
+
1336
+
1337
+ async def update_message_execution_async(
1338
+ user_id: str,
1339
+ company_id: str,
1340
+ message_id: str,
1341
+ status: MessageExecutionUpdateStatus | None = None,
1342
+ seconds_remaining: int | None = None,
1343
+ percentage_completed: int | None = None,
1344
+ ) -> MessageExecution:
1345
+ """Updates a message execution asynchronously.
1346
+
1347
+ Args:
1348
+ user_id (str): The user ID.
1349
+ company_id (str): The company ID.
1350
+ message_id (str): The ID of the message to update execution for.
1351
+ status (MessageExecutionUpdateStatus | None): The updated status (COMPLETED or FAILED). Defaults to None.
1352
+ seconds_remaining (int | None): Updated estimated seconds remaining.
1353
+ percentage_completed (int | None): Updated percentage of completion (0-100).
1354
+
1355
+ Returns:
1356
+ MessageExecution: The updated message execution.
1357
+
1358
+ Raises:
1359
+ Exception: If the update fails.
1360
+
1361
+ """
1362
+ try:
1363
+ status_value = status.value if status else None
1364
+ message_execution = await unique_sdk.MessageExecution.update_async(
1365
+ user_id=user_id,
1366
+ company_id=company_id,
1367
+ messageId=message_id,
1368
+ status=status_value,
1369
+ secondsRemaining=seconds_remaining,
1370
+ percentageCompleted=percentage_completed,
1371
+ )
1372
+ return MessageExecution(**message_execution)
1373
+ except Exception as e:
1374
+ logger.error(f"Failed to update message execution: {e}")
1375
+ raise e