unique_sdk 0.10.1__tar.gz → 0.10.2__tar.gz

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 (41) hide show
  1. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/CHANGELOG.md +3 -0
  2. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/PKG-INFO +68 -28
  3. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/README.md +64 -27
  4. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/pyproject.toml +1 -1
  5. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_content.py +11 -10
  6. unique_sdk-0.10.2/unique_sdk/utils/chat_in_space.py +167 -0
  7. unique_sdk-0.10.1/unique_sdk/utils/chat_in_space.py +0 -53
  8. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/LICENSE +0 -0
  9. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/__init__.py +0 -0
  10. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_api_requestor.py +0 -0
  11. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_api_resource.py +0 -0
  12. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_api_version.py +0 -0
  13. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_error.py +0 -0
  14. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_http_client.py +0 -0
  15. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_list_object.py +0 -0
  16. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_object_classes.py +0 -0
  17. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_request_options.py +0 -0
  18. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_unique_object.py +0 -0
  19. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_unique_ql.py +0 -0
  20. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_unique_response.py +0 -0
  21. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_util.py +0 -0
  22. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_version.py +0 -0
  23. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/_webhook.py +0 -0
  24. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/__init__.py +0 -0
  25. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_acronyms.py +0 -0
  26. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_chat_completion.py +0 -0
  27. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_embedding.py +0 -0
  28. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_event.py +0 -0
  29. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_folder.py +0 -0
  30. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_integrated.py +0 -0
  31. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_mcp.py +0 -0
  32. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_message.py +0 -0
  33. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_message_assessment.py +0 -0
  34. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_search.py +0 -0
  35. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_search_string.py +0 -0
  36. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_short_term_memory.py +0 -0
  37. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/api_resources/_space.py +0 -0
  38. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/utils/chat_history.py +0 -0
  39. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/utils/file_io.py +0 -0
  40. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/utils/sources.py +0 -0
  41. {unique_sdk-0.10.1 → unique_sdk-0.10.2}/unique_sdk/utils/token.py +0 -0
@@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.10.2] - 2025-08-05
9
+ - Add script to chat against file.
10
+
8
11
  ## [0.10.1] - 2025-08-05
9
12
  - Allow deletion of a space chat.
10
13
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_sdk
3
- Version: 0.10.1
3
+ Version: 0.10.2
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: Martin Fadler
@@ -1024,6 +1024,12 @@ A metadata filter such as the one designed above can be used in a `Search.create
1024
1024
 
1025
1025
  ## Utils
1026
1026
 
1027
+ - [Chat History](#chat-history)
1028
+ - [File Io](#file-io)
1029
+ - [Sources](#sources)
1030
+ - [token](#token)
1031
+ - [Chat In Space](#chat-in-space)
1032
+
1027
1033
  ### Chat History
1028
1034
 
1029
1035
  #### `unique_sdk.utils.chat_history.load_history`
@@ -1253,33 +1259,64 @@ The script ensures you can flexibly interact with spaces in new or ongoing chats
1253
1259
 
1254
1260
  ```python
1255
1261
  latest_message = await unique_sdk.utils.chat_in_space.send_message_and_wait_for_completion(
1256
- user_id=user_id,
1257
- company_id=company_id,
1258
- assistant_id=assistant_id,
1259
- text="Tell me a short story.",
1260
- chat_id=chat_id, # Optional - if no chat id is specified, a new chat will be created
1261
- tool_choices=["WebSearch"],
1262
- scope_rules={
1263
- "or": [
1264
- {
1265
- "operator": "in",
1266
- "path": [
1267
- "contentId"
1268
- ],
1269
- "value": [
1270
- "cont_u888z7cazxxm4lugfdjq7pks"
1271
- ]
1272
- },
1273
- {
1274
- "operator": "contains",
1275
- "path": [
1276
- "folderIdPath"
1277
- ],
1278
- "value": "uniquepathid://scope_btfo28b3eeelwh5obwgea71bl/scope_fn56ta67knd6w4medgq3028fx"
1279
- }
1280
- ]
1281
- },
1282
- )
1262
+ user_id=user_id,
1263
+ company_id=company_id,
1264
+ assistant_id=assistant_id,
1265
+ text="Tell me a short story.",
1266
+ chat_id=chat_id, # Optional - if no chat id is specified, a new chat will be created
1267
+ tool_choices=["WebSearch"],
1268
+ scope_rules={
1269
+ "or": [
1270
+ {
1271
+ "operator": "in",
1272
+ "path": [
1273
+ "contentId"
1274
+ ],
1275
+ "value": [
1276
+ "cont_u888z7cazxxm4lugfdjq7pks"
1277
+ ]
1278
+ },
1279
+ {
1280
+ "operator": "contains",
1281
+ "path": [
1282
+ "folderIdPath"
1283
+ ],
1284
+ "value": "uniquepathid://scope_btfo28b3eeelwh5obwgea71bl/scope_fn56ta67knd6w4medgq3028fx"
1285
+ }
1286
+ ]
1287
+ },
1288
+ )
1289
+ ```
1290
+
1291
+ #### `unique_sdk.utils.chat_in_space.chat_against_file`
1292
+
1293
+ The following script enables you to chat against a file.
1294
+
1295
+ You must provide the following parameters:
1296
+ - `assistantId`: The assistant to be used for the chat.
1297
+ - `path_to_file`: The local path of the file to be uploaded.
1298
+ - `displayed_filename`: The name of the file to be displayed.
1299
+ - `mime_type`: The mime type of the ifle to be uploaded.
1300
+ - `text`: The text to be sent to the chat for chatting against the file.
1301
+
1302
+ The script creates a chat and uploads the file to it. It then keeps polling the `ingestionState` field of the message, waiting for it to reach `FINISHED`, signaling the upload is complete. Once the file uploads successfully, the script sends the text, continues polling for completion, and finally retrieves the response message.
1303
+
1304
+ **Optional parameters:**
1305
+ - `poll_interval`: The number of seconds to wait between polling attempts (default: `1` second).
1306
+ - `max_wait`: The maximum number of seconds to wait for the message to complete (default: `60` seconds).
1307
+
1308
+ Example of chatting against a PDF. (The usage can be extended to any supported file type)
1309
+
1310
+ ```python
1311
+ latest_message = await unique_sdk.utils.chat_in_space.chat_against_file(
1312
+ user_id=user_id,
1313
+ company_id=company_id,
1314
+ assistant_id="assistant_hjcdga64bkcjnhu4",
1315
+ path_to_file="/files/hello.pdf",
1316
+ displayed_filename="hello.pdf"
1317
+ mime_type="application/pdf"
1318
+ text="Give me a bullet point summary of the file.",
1319
+ )
1283
1320
  ```
1284
1321
 
1285
1322
  ## Error Handling
@@ -1299,6 +1336,9 @@ All notable changes to this project will be documented in this file.
1299
1336
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1300
1337
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1301
1338
 
1339
+ ## [0.10.2] - 2025-08-05
1340
+ - Add script to chat against file.
1341
+
1302
1342
  ## [0.10.1] - 2025-08-05
1303
1343
  - Allow deletion of a space chat.
1304
1344
 
@@ -1008,6 +1008,12 @@ A metadata filter such as the one designed above can be used in a `Search.create
1008
1008
 
1009
1009
  ## Utils
1010
1010
 
1011
+ - [Chat History](#chat-history)
1012
+ - [File Io](#file-io)
1013
+ - [Sources](#sources)
1014
+ - [token](#token)
1015
+ - [Chat In Space](#chat-in-space)
1016
+
1011
1017
  ### Chat History
1012
1018
 
1013
1019
  #### `unique_sdk.utils.chat_history.load_history`
@@ -1237,33 +1243,64 @@ The script ensures you can flexibly interact with spaces in new or ongoing chats
1237
1243
 
1238
1244
  ```python
1239
1245
  latest_message = await unique_sdk.utils.chat_in_space.send_message_and_wait_for_completion(
1240
- user_id=user_id,
1241
- company_id=company_id,
1242
- assistant_id=assistant_id,
1243
- text="Tell me a short story.",
1244
- chat_id=chat_id, # Optional - if no chat id is specified, a new chat will be created
1245
- tool_choices=["WebSearch"],
1246
- scope_rules={
1247
- "or": [
1248
- {
1249
- "operator": "in",
1250
- "path": [
1251
- "contentId"
1252
- ],
1253
- "value": [
1254
- "cont_u888z7cazxxm4lugfdjq7pks"
1255
- ]
1256
- },
1257
- {
1258
- "operator": "contains",
1259
- "path": [
1260
- "folderIdPath"
1261
- ],
1262
- "value": "uniquepathid://scope_btfo28b3eeelwh5obwgea71bl/scope_fn56ta67knd6w4medgq3028fx"
1263
- }
1264
- ]
1265
- },
1266
- )
1246
+ user_id=user_id,
1247
+ company_id=company_id,
1248
+ assistant_id=assistant_id,
1249
+ text="Tell me a short story.",
1250
+ chat_id=chat_id, # Optional - if no chat id is specified, a new chat will be created
1251
+ tool_choices=["WebSearch"],
1252
+ scope_rules={
1253
+ "or": [
1254
+ {
1255
+ "operator": "in",
1256
+ "path": [
1257
+ "contentId"
1258
+ ],
1259
+ "value": [
1260
+ "cont_u888z7cazxxm4lugfdjq7pks"
1261
+ ]
1262
+ },
1263
+ {
1264
+ "operator": "contains",
1265
+ "path": [
1266
+ "folderIdPath"
1267
+ ],
1268
+ "value": "uniquepathid://scope_btfo28b3eeelwh5obwgea71bl/scope_fn56ta67knd6w4medgq3028fx"
1269
+ }
1270
+ ]
1271
+ },
1272
+ )
1273
+ ```
1274
+
1275
+ #### `unique_sdk.utils.chat_in_space.chat_against_file`
1276
+
1277
+ The following script enables you to chat against a file.
1278
+
1279
+ You must provide the following parameters:
1280
+ - `assistantId`: The assistant to be used for the chat.
1281
+ - `path_to_file`: The local path of the file to be uploaded.
1282
+ - `displayed_filename`: The name of the file to be displayed.
1283
+ - `mime_type`: The mime type of the ifle to be uploaded.
1284
+ - `text`: The text to be sent to the chat for chatting against the file.
1285
+
1286
+ The script creates a chat and uploads the file to it. It then keeps polling the `ingestionState` field of the message, waiting for it to reach `FINISHED`, signaling the upload is complete. Once the file uploads successfully, the script sends the text, continues polling for completion, and finally retrieves the response message.
1287
+
1288
+ **Optional parameters:**
1289
+ - `poll_interval`: The number of seconds to wait between polling attempts (default: `1` second).
1290
+ - `max_wait`: The maximum number of seconds to wait for the message to complete (default: `60` seconds).
1291
+
1292
+ Example of chatting against a PDF. (The usage can be extended to any supported file type)
1293
+
1294
+ ```python
1295
+ latest_message = await unique_sdk.utils.chat_in_space.chat_against_file(
1296
+ user_id=user_id,
1297
+ company_id=company_id,
1298
+ assistant_id="assistant_hjcdga64bkcjnhu4",
1299
+ path_to_file="/files/hello.pdf",
1300
+ displayed_filename="hello.pdf"
1301
+ mime_type="application/pdf"
1302
+ text="Give me a bullet point summary of the file.",
1303
+ )
1267
1304
  ```
1268
1305
 
1269
1306
  ## Error Handling
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "unique_sdk"
3
- version = "0.10.1"
3
+ version = "0.10.2"
4
4
  description = ""
5
5
  authors = [
6
6
  "Martin Fadler <martin.fadler@unique.ch>",
@@ -64,6 +64,7 @@ class Content(APIResource["Content"]):
64
64
  class SearchParams(RequestOptions):
65
65
  where: "Content.ContentWhereInput"
66
66
  chatId: NotRequired[str]
67
+ includeFailedContent: NotRequired[bool]
67
68
 
68
69
  class ContentInfoParams(TypedDict):
69
70
  """
@@ -163,11 +164,11 @@ class Content(APIResource["Content"]):
163
164
  class MagicTableSheetTable(TypedDict):
164
165
  rowId: str
165
166
  columns: List["Content.MagicTableSheetTableColumn"]
166
-
167
+
167
168
  class MagicTableSheetIngestionConfiguration(TypedDict):
168
169
  columnIdsInMetadata: List[str]
169
170
  columnIdsInChunkText: List[str]
170
-
171
+
171
172
  class MagicTableSheetIngestParams(TypedDict):
172
173
  data: List["Content.MagicTableSheetTable"]
173
174
  ingestionConfiguration: "Content.MagicTableSheetIngestionConfiguration"
@@ -298,10 +299,10 @@ class Content(APIResource["Content"]):
298
299
 
299
300
  @classmethod
300
301
  def ingest_magic_table_sheets(
301
- cls,
302
- user_id: str,
303
- company_id: str,
304
- **params: Unpack["Content.MagicTableSheetIngestParams"]
302
+ cls,
303
+ user_id: str,
304
+ company_id: str,
305
+ **params: Unpack["Content.MagicTableSheetIngestParams"],
305
306
  ) -> "Content.MagicTableSheetResponse":
306
307
  return cast(
307
308
  Content.MagicTableSheetResponse,
@@ -316,10 +317,10 @@ class Content(APIResource["Content"]):
316
317
 
317
318
  @classmethod
318
319
  async def ingest_magic_table_sheets_async(
319
- cls,
320
- user_id: str,
321
- company_id: str,
322
- **params: Unpack["Content.MagicTableSheetIngestParams"]
320
+ cls,
321
+ user_id: str,
322
+ company_id: str,
323
+ **params: Unpack["Content.MagicTableSheetIngestParams"],
323
324
  ) -> "Content.MagicTableSheetResponse":
324
325
  return cast(
325
326
  Content.MagicTableSheetResponse,
@@ -0,0 +1,167 @@
1
+ import asyncio
2
+ from typing import List
3
+
4
+ from unique_sdk.api_resources._content import Content
5
+ from unique_sdk.api_resources._space import Space
6
+ from unique_sdk.utils.file_io import upload_file
7
+
8
+
9
+ async def send_message_and_wait_for_completion(
10
+ user_id: str,
11
+ company_id: str,
12
+ assistant_id: str,
13
+ text: str,
14
+ tool_choices: List[str] = None,
15
+ scope_rules: dict | None = None,
16
+ chat_id: str = None,
17
+ poll_interval: float = 1.0,
18
+ max_wait: float = 60.0,
19
+ ) -> "Space.Message":
20
+ """
21
+ Sends a prompt asynchronously and polls for completion. (until stoppedStreamingAt is not None)
22
+
23
+ Args:
24
+ user_id: The user ID.
25
+ company_id: The company ID.
26
+ assistant_id: The assistant ID.
27
+ text: The prompt text.
28
+ poll_interval: Seconds between polls.
29
+ max_wait: Maximum seconds to wait for completion.
30
+ **kwargs: Additional parameters for the prompt.
31
+
32
+ Returns:
33
+ The completed Space.Message.
34
+ """
35
+ response = await Space.create_message_async(
36
+ user_id=user_id,
37
+ company_id=company_id,
38
+ assistantId=assistant_id,
39
+ chatId=chat_id,
40
+ text=text,
41
+ toolChoices=tool_choices,
42
+ scopeRules=scope_rules,
43
+ )
44
+ chat_id = response.get("chatId")
45
+
46
+ max_attempts = int(max_wait // poll_interval)
47
+ for _ in range(max_attempts):
48
+ answer = Space.get_latest_message(user_id, company_id, chat_id)
49
+ if answer.get("stoppedStreamingAt") is not None:
50
+ return answer
51
+ await asyncio.sleep(poll_interval)
52
+
53
+ raise TimeoutError("Timed out waiting for prompt completion.")
54
+
55
+
56
+ async def chat_against_file(
57
+ user_id: str,
58
+ company_id: str,
59
+ assistant_id: str,
60
+ path_to_file: str,
61
+ displayed_filename: str,
62
+ mime_type: str,
63
+ text: str,
64
+ poll_interval: float = 1.0,
65
+ max_wait: float = 60.0,
66
+ ) -> "Space.Message":
67
+ """
68
+ Chat against a file by uploading it, sending a message and waiting for a reply.
69
+ Args:
70
+
71
+ user_id: The user ID.
72
+ company_id: The company ID.
73
+ assistant_id: The assistant ID.
74
+ path_to_file: Path to the PDF file to upload.
75
+ displayed_filename: Name to display for the uploaded file.
76
+ mime_type: MIME type of the file (e.g., "application/pdf").
77
+ text: Text to send after uploading the file and chat against.
78
+ poll_interval: Seconds between polls for file ingestion.
79
+ max_wait: Maximum seconds to wait for the final response.
80
+
81
+ Returns:
82
+ The final message response.
83
+ """
84
+ chat_id = None
85
+
86
+ try:
87
+ response = await send_message_and_wait_for_completion(
88
+ user_id=user_id,
89
+ company_id=company_id,
90
+ assistant_id=assistant_id,
91
+ text="I'm going to upload a file for analysis.",
92
+ )
93
+ chat_id = response.get("chatId")
94
+
95
+ upload_response = upload_file(
96
+ userId=user_id,
97
+ companyId=company_id,
98
+ path_to_file=path_to_file,
99
+ displayed_filename=displayed_filename,
100
+ mime_type=mime_type,
101
+ chat_id=chat_id,
102
+ )
103
+ content_id = upload_response.get("id")
104
+
105
+ await wait_for_ingestion_completion(
106
+ user_id=user_id,
107
+ company_id=company_id,
108
+ content_id=content_id,
109
+ chat_id=chat_id,
110
+ poll_interval=poll_interval,
111
+ max_wait=max_wait,
112
+ )
113
+
114
+ final_response = await send_message_and_wait_for_completion(
115
+ user_id=user_id,
116
+ company_id=company_id,
117
+ assistant_id=assistant_id,
118
+ text=text,
119
+ chat_id=chat_id,
120
+ poll_interval=poll_interval,
121
+ max_wait=max_wait,
122
+ )
123
+
124
+ return final_response
125
+
126
+ except Exception as err:
127
+ print(f"Error during chat against file: {err}")
128
+ raise
129
+ finally:
130
+ if chat_id:
131
+ Space.delete_chat(
132
+ user_id=user_id,
133
+ company_id=company_id,
134
+ chat_id=chat_id,
135
+ )
136
+
137
+
138
+ async def wait_for_ingestion_completion(
139
+ user_id: str,
140
+ company_id: str,
141
+ content_id: str,
142
+ chat_id: str,
143
+ poll_interval: float = 1.0,
144
+ max_wait: float = 60.0,
145
+ ):
146
+ """
147
+ Waits until the content ingestionState is FINISHED or the maximum wait time is reached and throws if case of failed status.
148
+ """
149
+ max_attempts = int(max_wait // poll_interval)
150
+ for _ in range(max_attempts):
151
+ searched_content = Content.search(
152
+ user_id=user_id,
153
+ company_id=company_id,
154
+ where={"id": {"equals": content_id}},
155
+ chatId=chat_id,
156
+ includeFailedContent=True,
157
+ )
158
+ if searched_content:
159
+ ingestion_state = searched_content[0].get("ingestionState")
160
+ if ingestion_state == "FINISHED":
161
+ return
162
+ if isinstance(ingestion_state, str) and ingestion_state.startswith(
163
+ "FAILED"
164
+ ):
165
+ raise RuntimeError(f"Ingestion failed with state: {ingestion_state}")
166
+ await asyncio.sleep(poll_interval)
167
+ raise TimeoutError("Timed out waiting for file ingestion to finish.")
@@ -1,53 +0,0 @@
1
- import asyncio
2
- from typing import List
3
-
4
- from unique_sdk.api_resources._space import Space
5
-
6
-
7
- async def send_message_and_wait_for_completion(
8
- user_id: str,
9
- company_id: str,
10
- assistant_id: str,
11
- text: str,
12
- tool_choices: List[str] = None,
13
- scope_rules: dict | None = None,
14
- chat_id: str = None,
15
- poll_interval: float = 1.0,
16
- max_wait: float = 60.0,
17
- ) -> "Space.Message":
18
- """
19
- Sends a prompt asynchronously and polls for completion. (until stoppedStreamingAt is not None)
20
-
21
- Args:
22
- user_id: The user ID.
23
- company_id: The company ID.
24
- assistant_id: The assistant ID.
25
- text: The prompt text.
26
- poll_interval: Seconds between polls.
27
- max_wait: Maximum seconds to wait for completion.
28
- **kwargs: Additional parameters for the prompt.
29
-
30
- Returns:
31
- The completed Space.Message.
32
- """
33
- # Send the prompt asynchronously
34
- response = await Space.create_message_async(
35
- user_id=user_id,
36
- company_id=company_id,
37
- assistantId=assistant_id,
38
- chatId=chat_id,
39
- text=text,
40
- toolChoices=tool_choices,
41
- scopeRules=scope_rules,
42
- )
43
- chat_id = response.get("chatId")
44
-
45
- max_attempts = int(max_wait // poll_interval)
46
- for _ in range(max_attempts):
47
- # Poll for the answer
48
- answer = Space.get_latest_message(user_id, company_id, chat_id)
49
- if answer.get("stoppedStreamingAt") is not None:
50
- return answer
51
- await asyncio.sleep(poll_interval)
52
-
53
- raise TimeoutError("Timed out waiting for prompt completion.")
File without changes