unique_sdk 0.10.7__py3-none-any.whl → 0.10.9__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_sdk might be problematic. Click here for more details.

unique_sdk/__init__.py CHANGED
@@ -7,15 +7,15 @@ from typing import Literal, Optional
7
7
  # Konstantin Krauss<konstantin@unique.ch>
8
8
  from unique_sdk._api_version import _ApiVersion
9
9
 
10
- api_key: Optional[str] = None
11
- app_id: Optional[str] = None
10
+ api_key: str | None = None
11
+ app_id: str | None = None
12
12
  api_base: str = "https://gateway.unique.app/public/chat-gen2"
13
13
  api_version: str = _ApiVersion.CURRENT
14
14
  api_verify_mode: bool = True
15
15
  default_http_client: Optional["HTTPClient"] = None
16
16
 
17
17
  # Set to either 'debug' or 'info', controls console logging
18
- log: Optional[Literal["debug", "info"]] = None
18
+ log: Literal["debug", "info"] | None = None
19
19
 
20
20
  # Webhooks
21
21
  from unique_sdk._api_requestor import APIRequestor as APIRequestor
@@ -92,3 +92,18 @@ from unique_sdk.api_resources._mcp import MCP as MCP
92
92
  # Unique QL
93
93
  from unique_sdk._unique_ql import UQLOperator as UQLOperator
94
94
  from unique_sdk._unique_ql import UQLCombinator as UQLCombinator
95
+
96
+ # Agentic Table
97
+ from .api_resources._agentic_table import (
98
+ AgenticTable as AgenticTable,
99
+ AgenticTableCell as AgenticTableCell,
100
+ AgenticTableSheet as AgenticTableSheet,
101
+ AgenticTableSheetState as AgenticTableSheetState,
102
+ LogEntry as LogEntry,
103
+ LogDetail as LogDetail,
104
+ FilterTypes as FilterTypes,
105
+ CellRendererTypes as CellRendererTypes,
106
+ SelectionMethod as SelectionMethod,
107
+ AgreementStatus as AgreementStatus,
108
+ RowVerificationStatus as RowVerificationStatus,
109
+ )
@@ -0,0 +1,367 @@
1
+ from enum import StrEnum
2
+ from typing import (
3
+ Literal,
4
+ NotRequired,
5
+ TypedDict,
6
+ cast,
7
+ )
8
+
9
+ from typing_extensions import Unpack
10
+
11
+ from unique_sdk._api_resource import APIResource
12
+ from unique_sdk._request_options import RequestOptions
13
+
14
+
15
+ class AgenticTableSheetState(StrEnum):
16
+ STOPPED_BY_USER = "STOPPED_BY_USER"
17
+ PROCESSING = "PROCESSING"
18
+ IDLE = "IDLE"
19
+
20
+
21
+ class LogDetail(TypedDict, total=False):
22
+ text: str
23
+ messageId: str | None
24
+
25
+
26
+ class LogEntry(TypedDict):
27
+ text: str
28
+ createdAt: str
29
+ actorType: Literal["USER", "SYSTEM", "ASSISTANT", "TOOL"]
30
+ messageId: NotRequired[str]
31
+ details: NotRequired[list[LogDetail]]
32
+
33
+
34
+ class AgenticTableCell(TypedDict, total=False):
35
+ sheetId: str
36
+ rowOrder: int
37
+ columnOrder: int
38
+ rowLocked: bool
39
+ text: str
40
+ logEntries: list[LogEntry]
41
+
42
+
43
+ class ColumnMetadataUpdateStatus(TypedDict, total=False):
44
+ status: bool
45
+ message: str | None
46
+
47
+
48
+ class AgenticTableSheet(TypedDict):
49
+ sheetId: str
50
+ name: str
51
+ state: AgenticTableSheetState
52
+ chatId: str
53
+ createdBy: str
54
+ companyId: str
55
+ createdAt: str
56
+ magicTableRowCount: int
57
+ magicTableCells: NotRequired[list[AgenticTableCell]]
58
+
59
+
60
+ class FilterTypes(StrEnum):
61
+ VALUE_MATCH_FILTER = "ValueMatchFilter"
62
+ PARTIAL_MATCH_FILTER = "PartialMatchFilter"
63
+ REFERENCE_FILTER = "ReferenceFilter"
64
+ HALLUCINATION_FILTER = "HallucinationFilter"
65
+ REVIEW_STATUS_FILTER = "ReviewStatusFilter"
66
+ ASSIGNEE_FILTER = "AssigneeFilter"
67
+
68
+
69
+ class CellRendererTypes(StrEnum):
70
+ CHECKBOX_LOCK_CELL_RENDERER = "CheckboxLockCellRenderer"
71
+ COLLABORATOR_DROPDOWN = "CollaboratorDropdown"
72
+ REVIEW_STATUS_DROPDOWN = "ReviewStatusDropdown"
73
+ CUSTOM_CELL_RENDERER = "CustomCellRenderer"
74
+ SELECTABLE_CELL_RENDERER = "SelectableCellRenderer"
75
+
76
+
77
+ class SelectionMethod(StrEnum):
78
+ DEFAULT = "DEFAULT"
79
+ MANUAL = "MANUAL"
80
+
81
+
82
+ class AgreementStatus(StrEnum):
83
+ MATCH = "MATCH"
84
+ NO_MATCH = "NO_MATCH"
85
+
86
+
87
+ class RowVerificationStatus(StrEnum):
88
+ NEED_REVIEW = "NEED_REVIEW"
89
+ READY_FOR_VERIFICATION = "READY_FOR_VERIFICATION"
90
+ VERIFIED = "VERIFIED"
91
+
92
+
93
+ class AgenticTable(APIResource["AgenticTable"]):
94
+ """
95
+ This object represents the magic table route. It is used to run complex APIs on the Unique platform
96
+ """
97
+
98
+ class SetCell(RequestOptions):
99
+ tableId: str
100
+ rowOrder: int
101
+ columnOrder: int
102
+ text: str
103
+ logEntries: NotRequired[list[LogEntry]]
104
+
105
+ class GetCell(RequestOptions):
106
+ tableId: str
107
+ rowOrder: int
108
+ columnOrder: int
109
+
110
+ class SetActivityStatus(RequestOptions):
111
+ tableId: str
112
+ activity: Literal[
113
+ "DeleteRow",
114
+ "DeleteColumn",
115
+ "UpdateCell",
116
+ "AddQuestionText",
117
+ "AddMetaData",
118
+ "GenerateArtifact",
119
+ "SheetCompleted",
120
+ "LibrarySheetRowVerified",
121
+ ]
122
+ status: Literal[
123
+ "IN_PROGRESS",
124
+ "COMPLETED",
125
+ "FAILED",
126
+ ]
127
+ text: str
128
+
129
+ class SetArtifact(RequestOptions):
130
+ tableId: str
131
+ name: str
132
+ contentId: str
133
+ mimeType: str
134
+ artifactType: Literal["QUESTIONS", "FULL_REPORT"]
135
+
136
+ class UpdateSheet(RequestOptions):
137
+ tableId: str
138
+ state: NotRequired[AgenticTableSheetState]
139
+ name: NotRequired[str]
140
+
141
+ class UpdateSheetResponse(RequestOptions):
142
+ status: bool
143
+ message: str
144
+
145
+ class SetColumnMetadata(RequestOptions):
146
+ tableId: str
147
+ columnOrder: int
148
+ columnWidth: NotRequired[int]
149
+ filter: NotRequired[FilterTypes]
150
+ cellRenderer: NotRequired[str]
151
+ editable: NotRequired[bool]
152
+
153
+ class GetSheetData(RequestOptions):
154
+ tableId: str
155
+ includeCells: NotRequired[bool]
156
+ includeLogHistory: NotRequired[bool]
157
+ includeRowCount: NotRequired[bool]
158
+ includeCellMetaData: NotRequired[bool]
159
+ startRow: NotRequired[int]
160
+ endRow: NotRequired[int]
161
+
162
+ class SetCellMetadata(RequestOptions):
163
+ tableId: str
164
+ rowOrder: int
165
+ columnOrder: int
166
+ selected: NotRequired[bool]
167
+ selectionMethod: NotRequired[SelectionMethod]
168
+ agreementStatus: NotRequired[AgreementStatus]
169
+
170
+ class BulkUpdateStatus(RequestOptions):
171
+ tableId: str
172
+ rowOrders: list[int]
173
+ status: RowVerificationStatus
174
+
175
+ @classmethod
176
+ async def set_cell(
177
+ cls,
178
+ user_id: str,
179
+ company_id: str,
180
+ **params: Unpack["AgenticTable.SetCell"],
181
+ ) -> "AgenticTableCell":
182
+ """ """
183
+ url = f"/magic-table/{params['tableId']}/cell"
184
+ return cast(
185
+ "AgenticTableCell",
186
+ cls._static_request(
187
+ "post",
188
+ url,
189
+ user_id,
190
+ company_id,
191
+ params,
192
+ ),
193
+ )
194
+
195
+ @classmethod
196
+ async def get_cell(
197
+ cls,
198
+ user_id: str,
199
+ company_id: str,
200
+ **params: Unpack["AgenticTable.GetCell"],
201
+ ) -> "AgenticTableCell":
202
+ """ """
203
+ url = f"/magic-table/{params['tableId']}/cell?rowOrder={params['rowOrder']}&columnOrder={params['columnOrder']}"
204
+ return cast(
205
+ "AgenticTableCell",
206
+ await cls._static_request_async(
207
+ "get",
208
+ url,
209
+ user_id,
210
+ company_id,
211
+ params={},
212
+ ),
213
+ )
214
+
215
+ @classmethod
216
+ async def set_activity(
217
+ cls,
218
+ user_id: str,
219
+ company_id: str,
220
+ **params: Unpack["AgenticTable.SetActivityStatus"],
221
+ ) -> "AgenticTableCell":
222
+ """ """
223
+ url = f"/magic-table/{params['tableId']}/activity"
224
+ return cast(
225
+ "AgenticTableCell",
226
+ cls._static_request(
227
+ "post",
228
+ url,
229
+ user_id,
230
+ company_id,
231
+ params,
232
+ ),
233
+ )
234
+
235
+ @classmethod
236
+ async def set_artifact(
237
+ cls,
238
+ user_id: str,
239
+ company_id: str,
240
+ **params: Unpack["AgenticTable.SetArtifact"],
241
+ ) -> "AgenticTableCell":
242
+ """ """
243
+ url = f"/magic-table/{params['tableId']}/artifact"
244
+ return cast(
245
+ "AgenticTableCell",
246
+ cls._static_request(
247
+ "post",
248
+ url,
249
+ user_id,
250
+ company_id,
251
+ params,
252
+ ),
253
+ )
254
+
255
+ @classmethod
256
+ async def update_sheet_state(
257
+ cls,
258
+ user_id: str,
259
+ company_id: str,
260
+ **params: Unpack["AgenticTable.UpdateSheet"],
261
+ ) -> "AgenticTable.UpdateSheetResponse":
262
+ url = f"/magic-table/{params['tableId']}"
263
+ return cast(
264
+ "AgenticTable.UpdateSheetResponse",
265
+ cls._static_request("post", url, user_id, company_id, params),
266
+ )
267
+
268
+ @classmethod
269
+ async def set_column_metadata(
270
+ cls,
271
+ user_id: str,
272
+ company_id: str,
273
+ **params: Unpack["AgenticTable.SetColumnMetadata"],
274
+ ) -> ColumnMetadataUpdateStatus:
275
+ url = f"/magic-table/{params['tableId']}/column/metadata"
276
+ # Remove tableId from params
277
+ params.pop("tableId")
278
+ response = cls._static_request("post", url, user_id, company_id, params)
279
+ return cast(
280
+ ColumnMetadataUpdateStatus,
281
+ response,
282
+ )
283
+
284
+ @classmethod
285
+ async def get_sheet_data(
286
+ cls,
287
+ user_id: str,
288
+ company_id: str,
289
+ **params: Unpack["AgenticTable.GetSheetData"],
290
+ ) -> AgenticTableSheet:
291
+ url = f"/magic-table/{params['tableId']}"
292
+ return cast(
293
+ AgenticTableSheet,
294
+ cls._static_request("get", url, user_id, company_id, params),
295
+ )
296
+
297
+ @classmethod
298
+ async def get_sheet_state(
299
+ cls, user_id: str, company_id: str, tableId: str
300
+ ) -> AgenticTableSheetState:
301
+ sheet = await cls.get_sheet_data(
302
+ user_id=user_id,
303
+ company_id=company_id,
304
+ tableId=tableId,
305
+ includeCells=False,
306
+ )
307
+ return sheet["state"]
308
+
309
+ @classmethod
310
+ async def set_cell_metadata(
311
+ cls,
312
+ user_id: str,
313
+ company_id: str,
314
+ **params: Unpack["AgenticTable.SetCellMetadata"],
315
+ ) -> ColumnMetadataUpdateStatus:
316
+ url = f"/magic-table/{params['tableId']}/cell/metadata"
317
+ return cast(
318
+ "ColumnMetadataUpdateStatus",
319
+ cls._static_request("post", url, user_id, company_id, params),
320
+ )
321
+
322
+ @classmethod
323
+ async def set_multiple_cells(
324
+ cls,
325
+ user_id: str,
326
+ company_id: str,
327
+ tableId: str,
328
+ cells: list[AgenticTableCell],
329
+ ) -> ColumnMetadataUpdateStatus:
330
+ url = f"/magic-table/{tableId}/cells/bulk-upsert"
331
+ # Map AgenticTableCell to PublicAgenticTableCellDto
332
+ try:
333
+ params_api = {
334
+ "cells": [
335
+ {
336
+ "rowOrder": cell["rowOrder"],
337
+ "columnOrder": cell["columnOrder"],
338
+ "data": cell["text"],
339
+ }
340
+ for cell in cells
341
+ ]
342
+ }
343
+ except Exception as e:
344
+ raise ValueError(f"Invalid data or missing required fields: {e}")
345
+ return cast(
346
+ "ColumnMetadataUpdateStatus",
347
+ cls._static_request("post", url, user_id, company_id, params=params_api),
348
+ )
349
+
350
+ @classmethod
351
+ async def bulk_update_status(
352
+ cls,
353
+ user_id: str,
354
+ company_id: str,
355
+ **params: Unpack["AgenticTable.BulkUpdateStatus"],
356
+ ) -> ColumnMetadataUpdateStatus:
357
+ url = f"/magic-table/{params['tableId']}/rows/bulk-update-status"
358
+ return cast(
359
+ "ColumnMetadataUpdateStatus",
360
+ cls._static_request(
361
+ "post",
362
+ url,
363
+ user_id,
364
+ company_id,
365
+ params,
366
+ ),
367
+ )
@@ -139,12 +139,12 @@ async def wait_for_ingestion_completion(
139
139
  user_id: str,
140
140
  company_id: str,
141
141
  content_id: str,
142
- chat_id: str,
142
+ chat_id: str = None,
143
143
  poll_interval: float = 1.0,
144
144
  max_wait: float = 60.0,
145
145
  ):
146
146
  """
147
- Waits until the content ingestionState is FINISHED or the maximum wait time is reached and throws if case of failed status.
147
+ Polls until the content ingestion is finished or the maximum wait time is reached and throws in case ingestion fails. The function assumes that the content exists.
148
148
  """
149
149
  max_attempts = int(max_wait // poll_interval)
150
150
  for _ in range(max_attempts):
@@ -158,7 +158,7 @@ async def wait_for_ingestion_completion(
158
158
  if searched_content:
159
159
  ingestion_state = searched_content[0].get("ingestionState")
160
160
  if ingestion_state == "FINISHED":
161
- return
161
+ return ingestion_state
162
162
  if isinstance(ingestion_state, str) and ingestion_state.startswith(
163
163
  "FAILED"
164
164
  ):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_sdk
3
- Version: 0.10.7
3
+ Version: 0.10.9
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: Martin Fadler
@@ -1447,6 +1447,30 @@ latest_message = await unique_sdk.utils.chat_in_space.chat_against_file(
1447
1447
  )
1448
1448
  ```
1449
1449
 
1450
+ #### `unique_sdk.utils.chat_in_space.wait_for_ingestion_completion`
1451
+
1452
+ The following script enables you to wait for the ingestion of a file. This should be used carefully as it continuously polls for the status. In case of bigger files, adjust the `poll_interval` and `max_waits`.
1453
+
1454
+ You must provide the following parameter:
1455
+ - `content_id`: The id of the content to check.
1456
+
1457
+ The script polls until the content ingestion is finished or the maximum wait time is reached and throws in case ingestion fails. The function assumes that the content exists.
1458
+
1459
+ **Optional parameters:**
1460
+ - `chat_id`: In case the content is uploaded to a chat, the `chat_id` must be provided.
1461
+ - `poll_interval`: The number of seconds to wait between polling attempts (default: `1` second).
1462
+ - `max_wait`: The maximum number of seconds to wait for the message to complete (default: `60` seconds).
1463
+
1464
+ Example of waiting for the ingestion of a file in the Knowledge Base.
1465
+
1466
+ ```python
1467
+ await unique_sdk.utils.chat_in_space.wait_for_ingestion_completion(
1468
+ user_id=user_id,
1469
+ company_id=company_id,
1470
+ content_id="cont_ddlezvag4kzxudfr24lrjc5mx",
1471
+ )
1472
+ ```
1473
+
1450
1474
  ## Error Handling
1451
1475
 
1452
1476
  ## Examples
@@ -1464,6 +1488,12 @@ All notable changes to this project will be documented in this file.
1464
1488
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1465
1489
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1466
1490
 
1491
+ ## [0.10.9] - 2025-08-15
1492
+ - Add script to wait for content ingestion finished.
1493
+
1494
+ ## [0.10.8] - 2025-08-13
1495
+ - Add support for Agentic Table.
1496
+
1467
1497
  ## [0.10.7] - 2025-08-13
1468
1498
  - Make metadata optional when uploading a file.
1469
1499
 
@@ -1,4 +1,4 @@
1
- unique_sdk/__init__.py,sha256=n_drdw9PkmJpQUt-7DjeUFinRl95gBSks2xsMLEeE9M,3350
1
+ unique_sdk/__init__.py,sha256=kD6dQiLHr0eJKy5yzN0iRNO7N2v4n9TDv6h6DTHMzoo,3840
2
2
  unique_sdk/_api_requestor.py,sha256=i4gCpzx8zP95sv-AhJfpQxKvWR0U-I6lclHyV55RPtg,14397
3
3
  unique_sdk/_api_resource.py,sha256=ytjomI-IVJwsbvdPyuZCfF-bl-Abgf66bu1D34YxCu8,6244
4
4
  unique_sdk/_api_version.py,sha256=Ku4JPdeyJtnX5eJJvRCEc1_u44UObdVrvrL1T-WwWCs,46
@@ -15,6 +15,7 @@ unique_sdk/_version.py,sha256=j4_tPC6t3enRds7LqiRuWSyfrYHfEo6CXIDARAWW98I,19
15
15
  unique_sdk/_webhook.py,sha256=GYxbUibQN_W4XlNTHaMIksT9FQJk4LJmlKcxOu3jqiU,2855
16
16
  unique_sdk/api_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  unique_sdk/api_resources/_acronyms.py,sha256=GIU1XH1flGWQYcpsFqTYwg4ioIGxVmb15tux84nmhEg,891
18
+ unique_sdk/api_resources/_agentic_table.py,sha256=8-_f7t-m_iiiOj2835iESoxz91YRxl4-tkxpzQbgdcI,9958
18
19
  unique_sdk/api_resources/_chat_completion.py,sha256=ILCAffxkbkfh2iV9L4KKnfe80gZmT9pWfkNmf3mq68U,2172
19
20
  unique_sdk/api_resources/_content.py,sha256=KnrfH8UFItNjnNejyWpvxBb9kABwjaxSiK9J8CPf67o,10725
20
21
  unique_sdk/api_resources/_embedding.py,sha256=C6qak7cCUBMBINfPhgH8taCJZ9n6w1MUElqDJJ8dG10,1281
@@ -29,11 +30,11 @@ unique_sdk/api_resources/_search_string.py,sha256=4Idw6exgZdA8qksz9WkiA68k1hTU-7
29
30
  unique_sdk/api_resources/_short_term_memory.py,sha256=vPRN-Y0WPx74E6y-A3LocGc0TxJdzT-xGL66WzZwKRg,2820
30
31
  unique_sdk/api_resources/_space.py,sha256=Mzl1EUn7RrfjB8fKC6f-TW9GAOl5M6JncYLrKMDa-pQ,4933
31
32
  unique_sdk/utils/chat_history.py,sha256=5UqL9hF1O9pV7skbNOlEibF5rHdYsmG3m5-YEPUowOs,3037
32
- unique_sdk/utils/chat_in_space.py,sha256=nYmgQYhIxqQex_6zjdCfNuGnjoU14WkxUN6_zmSOiCQ,5169
33
+ unique_sdk/utils/chat_in_space.py,sha256=3NeBjOu7p43V_6PrjwxyaTkgknUS10KE4QRuTlFDU_4,5232
33
34
  unique_sdk/utils/file_io.py,sha256=YY8B7VJcTLOPmCXByiOfNerXGlAtjCC5EVNmAbQJ3dQ,4306
34
35
  unique_sdk/utils/sources.py,sha256=wfboE-neMKa0Wuq9QzfAEFMkNLrIrmm0v-QF33sLo6k,4952
35
36
  unique_sdk/utils/token.py,sha256=AzKuAA1AwBtnvSFxGcsHLpxXr_wWE5Mj4jYBbOz2ljA,1740
36
- unique_sdk-0.10.7.dist-info/LICENSE,sha256=EJCWoHgrXVBUb47PnjeV4MFIEOR71MAdCOIgv61J-4k,1065
37
- unique_sdk-0.10.7.dist-info/METADATA,sha256=79pPucHAbyeI3kp8Y2bmWCDs350XiTLqAQQtxF2Ygbg,49144
38
- unique_sdk-0.10.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
39
- unique_sdk-0.10.7.dist-info/RECORD,,
37
+ unique_sdk-0.10.9.dist-info/LICENSE,sha256=EJCWoHgrXVBUb47PnjeV4MFIEOR71MAdCOIgv61J-4k,1065
38
+ unique_sdk-0.10.9.dist-info/METADATA,sha256=HkLlEA2qV_xJPt5i7obS1trzOhzdZL0aEw4mexrODP4,50398
39
+ unique_sdk-0.10.9.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
40
+ unique_sdk-0.10.9.dist-info/RECORD,,