unique_toolkit 2026.42.0.dev7__py3-none-any.whl → 2026.42.0.dev8__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.
- unique_toolkit/agentic_table/service.py +142 -1
- {unique_toolkit-2026.42.0.dev7.dist-info → unique_toolkit-2026.42.0.dev8.dist-info}/METADATA +2 -2
- {unique_toolkit-2026.42.0.dev7.dist-info → unique_toolkit-2026.42.0.dev8.dist-info}/RECORD +4 -4
- {unique_toolkit-2026.42.0.dev7.dist-info → unique_toolkit-2026.42.0.dev8.dist-info}/WHEEL +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
3
|
import time
|
|
4
|
+
from collections.abc import Collection
|
|
4
5
|
from datetime import datetime
|
|
5
6
|
from typing import Any, NamedTuple, cast
|
|
6
7
|
|
|
@@ -252,7 +253,11 @@ class AgenticTableService:
|
|
|
252
253
|
return MagicTableCell.model_validate(cell_data)
|
|
253
254
|
|
|
254
255
|
async def set_multiple_cells(
|
|
255
|
-
self,
|
|
256
|
+
self,
|
|
257
|
+
cells: list[MagicTableCell],
|
|
258
|
+
batch_size: int = 4000,
|
|
259
|
+
*,
|
|
260
|
+
overwrite_library_rows: bool | None = None,
|
|
256
261
|
):
|
|
257
262
|
"""
|
|
258
263
|
Sets the values of multiple cells in the Agentic Table.
|
|
@@ -260,6 +265,14 @@ class AgenticTableService:
|
|
|
260
265
|
Args:
|
|
261
266
|
cells (list[MagicTableCell]): The cells to set sorted by row and column.
|
|
262
267
|
batch_size (int): Number of cells to set in a single request.
|
|
268
|
+
overwrite_library_rows (bool | None): When set, forwarded as
|
|
269
|
+
``overwriteLibraryRows``. ``True`` lets updates to existing cells on
|
|
270
|
+
library-sheet rows go through instead of being dropped; the server
|
|
271
|
+
only honors it on library sheets, for rows where the caller can read
|
|
272
|
+
every sheet named in the row's ``sourceSheetId`` metadata. Locked rows still
|
|
273
|
+
need unlocking first (``update_row_verification_status`` with
|
|
274
|
+
``locked=False``). ``None`` omits the field; servers that predate
|
|
275
|
+
it reject it with a 400.
|
|
263
276
|
"""
|
|
264
277
|
for i in range(0, len(cells), batch_size):
|
|
265
278
|
batch = cells[i : i + batch_size]
|
|
@@ -275,6 +288,7 @@ class AgenticTableService:
|
|
|
275
288
|
)
|
|
276
289
|
for cell in batch
|
|
277
290
|
],
|
|
291
|
+
overwriteLibraryRows=overwrite_library_rows,
|
|
278
292
|
)
|
|
279
293
|
|
|
280
294
|
async def set_activity(
|
|
@@ -875,6 +889,133 @@ class AgenticTableService:
|
|
|
875
889
|
if not result.get("status"):
|
|
876
890
|
raise Exception(result.get("message") or "Failed to create row metadata")
|
|
877
891
|
|
|
892
|
+
async def update_row_metadata(
|
|
893
|
+
self,
|
|
894
|
+
metadata_id: str,
|
|
895
|
+
entry: RowMetadataEntryInput,
|
|
896
|
+
) -> None:
|
|
897
|
+
"""Update a single row metadata entry, addressed by its id.
|
|
898
|
+
|
|
899
|
+
Args:
|
|
900
|
+
metadata_id (str): The ``id`` of the row metadata entry to update.
|
|
901
|
+
entry (RowMetadataEntryInput): The new key, value and filter flag.
|
|
902
|
+
|
|
903
|
+
Raises:
|
|
904
|
+
Exception: If the API reports a non-success status.
|
|
905
|
+
"""
|
|
906
|
+
result = await AgenticTable.update_row_metadata(
|
|
907
|
+
user_id=self._user_id,
|
|
908
|
+
company_id=self._company_id,
|
|
909
|
+
tableId=self.table_id,
|
|
910
|
+
metadataId=metadata_id,
|
|
911
|
+
key=entry.key,
|
|
912
|
+
value=entry.value,
|
|
913
|
+
exactFilter=entry.exact_filter,
|
|
914
|
+
)
|
|
915
|
+
if not result.get("status"):
|
|
916
|
+
raise Exception(result.get("message") or "Failed to update row metadata")
|
|
917
|
+
|
|
918
|
+
async def delete_row_metadata(self, metadata_id: str) -> None:
|
|
919
|
+
"""Delete a single row metadata entry, addressed by its id.
|
|
920
|
+
|
|
921
|
+
Raises:
|
|
922
|
+
Exception: If the API reports a non-success status.
|
|
923
|
+
"""
|
|
924
|
+
result = await AgenticTable.delete_row_metadata(
|
|
925
|
+
user_id=self._user_id,
|
|
926
|
+
company_id=self._company_id,
|
|
927
|
+
tableId=self.table_id,
|
|
928
|
+
metadataId=metadata_id,
|
|
929
|
+
)
|
|
930
|
+
if not result.get("status"):
|
|
931
|
+
raise Exception(result.get("message") or "Failed to delete row metadata")
|
|
932
|
+
|
|
933
|
+
async def set_row_metadata_by_key(
|
|
934
|
+
self,
|
|
935
|
+
row: int,
|
|
936
|
+
entries: list[RowMetadataEntryInput],
|
|
937
|
+
row_id: str | None = None,
|
|
938
|
+
existing: list[RowMetadataEntry] | None = None,
|
|
939
|
+
managed_keys: Collection[str] | None = None,
|
|
940
|
+
) -> None:
|
|
941
|
+
"""Merge row metadata by key, and optionally remove keys the caller owns.
|
|
942
|
+
|
|
943
|
+
For each entry: a key the row lacks is created; a key the row holds with
|
|
944
|
+
a different value or filter flag is updated in place; a key that already
|
|
945
|
+
matches is left alone. If the row holds the key more than once, one entry
|
|
946
|
+
is kept and the others are deleted, so the key ends up with exactly the
|
|
947
|
+
given value.
|
|
948
|
+
|
|
949
|
+
Keys not in ``entries`` are only removed when listed in ``managed_keys``.
|
|
950
|
+
This is not a full replace: rows also carry metadata the caller does not
|
|
951
|
+
own (e.g. the ``sourceSheetId`` stamp that library overwrites are checked
|
|
952
|
+
against), which must survive.
|
|
953
|
+
|
|
954
|
+
Args:
|
|
955
|
+
row (int): The row index (row order).
|
|
956
|
+
entries (list[RowMetadataEntryInput]): Key/value entries to set. Keys
|
|
957
|
+
must be unique.
|
|
958
|
+
row_id (str | None): The backend row id, used when creating keys.
|
|
959
|
+
existing (list[RowMetadataEntry] | None): The row's current metadata,
|
|
960
|
+
when the caller already read it (e.g. ``get_sheet`` with
|
|
961
|
+
``include_row_metadata=True``). When ``None``, the row's metadata
|
|
962
|
+
and id are read with ``get_cell``.
|
|
963
|
+
managed_keys (Collection[str] | None): Keys the caller owns. Every
|
|
964
|
+
entry key must be in it. Any of these keys missing from
|
|
965
|
+
``entries`` is deleted from the row, duplicates included. ``None``
|
|
966
|
+
deletes nothing beyond duplicates of keys in ``entries``.
|
|
967
|
+
|
|
968
|
+
Raises:
|
|
969
|
+
ValueError: If ``entries`` repeats a key, an entry key is not in
|
|
970
|
+
``managed_keys``, or a key must be created and the row id cannot
|
|
971
|
+
be resolved.
|
|
972
|
+
Exception: If the API reports a non-success status.
|
|
973
|
+
"""
|
|
974
|
+
keys = [entry.key for entry in entries]
|
|
975
|
+
if len(set(keys)) != len(keys):
|
|
976
|
+
raise ValueError(f"Duplicate row metadata keys in {keys}")
|
|
977
|
+
if managed_keys is not None:
|
|
978
|
+
unmanaged = sorted(set(keys) - set(managed_keys))
|
|
979
|
+
if unmanaged:
|
|
980
|
+
raise ValueError(f"Row metadata keys {unmanaged} not in managed_keys")
|
|
981
|
+
if not entries and not managed_keys:
|
|
982
|
+
return
|
|
983
|
+
if existing is None:
|
|
984
|
+
cell = await self.get_cell(row, 0, include_row_metadata=True)
|
|
985
|
+
existing = cell.row_metadata
|
|
986
|
+
row_id = row_id or cell.row_id
|
|
987
|
+
|
|
988
|
+
existing_by_key: dict[str, list[RowMetadataEntry]] = {}
|
|
989
|
+
for current in existing:
|
|
990
|
+
existing_by_key.setdefault(current.key, []).append(current)
|
|
991
|
+
|
|
992
|
+
to_create: list[RowMetadataEntryInput] = []
|
|
993
|
+
for entry in entries:
|
|
994
|
+
matches = existing_by_key.get(entry.key)
|
|
995
|
+
if not matches:
|
|
996
|
+
to_create.append(entry)
|
|
997
|
+
continue
|
|
998
|
+
keep = next(
|
|
999
|
+
(
|
|
1000
|
+
m
|
|
1001
|
+
for m in matches
|
|
1002
|
+
if m.value == entry.value and m.exact_filter == entry.exact_filter
|
|
1003
|
+
),
|
|
1004
|
+
None,
|
|
1005
|
+
)
|
|
1006
|
+
if keep is None:
|
|
1007
|
+
keep = matches[0]
|
|
1008
|
+
await self.update_row_metadata(keep.id, entry)
|
|
1009
|
+
for duplicate in matches:
|
|
1010
|
+
if duplicate.id != keep.id:
|
|
1011
|
+
await self.delete_row_metadata(duplicate.id)
|
|
1012
|
+
|
|
1013
|
+
for key in set(managed_keys or ()) - set(keys):
|
|
1014
|
+
for stale in existing_by_key.get(key, []):
|
|
1015
|
+
await self.delete_row_metadata(stale.id)
|
|
1016
|
+
|
|
1017
|
+
await self.create_row_metadata(row, to_create, row_id=row_id)
|
|
1018
|
+
|
|
878
1019
|
async def delete_sheet_metadata(self, metadata_id: str) -> None:
|
|
879
1020
|
"""Delete a sheet metadata entry by its id.
|
|
880
1021
|
|
{unique_toolkit-2026.42.0.dev7.dist-info → unique_toolkit-2026.42.0.dev8.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-toolkit
|
|
3
|
-
Version: 2026.42.0.
|
|
3
|
+
Version: 2026.42.0.dev8
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Cedric Klinkert, Martin Fadler, Sadique Sheik, Fabian Schläpfer, Pascal Hauri, Ejiroghene Oki-Peter, Rami Azouz, Ricardo Visini, Sanzio Monti
|
|
6
6
|
Author-email: Cedric Klinkert <cedric.klinkert@unique.ch>, Martin Fadler <martin.fadler@unique.ch>, Sadique Sheik <sadique@unique.ch>, Fabian Schläpfer <fabian@unique.ch>, Pascal Hauri <pascal@unique.ch>, Ejiroghene Oki-Peter <oki-peter.ejiroghene@unique.ai>, Rami Azouz <rami.ext@unique.ch>, Ricardo Visini <ricardo.visini@unique.ch>, Sanzio Monti <sanzio.monti@unique.ai>
|
|
@@ -16,7 +16,7 @@ Requires-Dist: sseclient>=0.0.27,<0.0.28
|
|
|
16
16
|
Requires-Dist: openai>=1.105.0,<3
|
|
17
17
|
Requires-Dist: platformdirs>=4.0.0,<5
|
|
18
18
|
Requires-Dist: pillow>=12.1.1
|
|
19
|
-
Requires-Dist: unique-sdk>=2026.42.0.
|
|
19
|
+
Requires-Dist: unique-sdk>=2026.42.0.dev3,<2026.42.0rc0
|
|
20
20
|
Requires-Dist: jambo>=0.1.2,<0.2
|
|
21
21
|
Requires-Dist: jinja2>=3.1.6,<4
|
|
22
22
|
Requires-Dist: docxtpl>=0.20.1,<0.21
|
|
@@ -242,7 +242,7 @@ unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py,sha256=u
|
|
|
242
242
|
unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py,sha256=EA8iVvb3L91OFk2XMbGcFuhe2etqm3Sx9QCYDGiOSOM,6995
|
|
243
243
|
unique_toolkit/agentic_table/__init__.py,sha256=RwBShHaD15R3117mU3ZLVzjgPz2ngdbzif7WJwhm8zw,2552
|
|
244
244
|
unique_toolkit/agentic_table/schemas.py,sha256=hi4vUn95ct2dm3nbkvke7j8RVVCp_nTlzSzLro1OT34,18663
|
|
245
|
-
unique_toolkit/agentic_table/service.py,sha256=
|
|
245
|
+
unique_toolkit/agentic_table/service.py,sha256=_aDjxux1Dvdf11-jHzVvEw0PSDNDSjZ-DzKuoxJd09Y,49059
|
|
246
246
|
unique_toolkit/agentic_table/synthetic_chat_event.py,sha256=MylvYuhx5CVt2DbPetzV0sR8GlkL218DmNFi7A6RYVs,2373
|
|
247
247
|
unique_toolkit/app/__init__.py,sha256=qear5ErW3smLDATxtnUsgkX3f177zsn65ixVW8T0JVE,1641
|
|
248
248
|
unique_toolkit/app/chat_event_filter_options_settings.py,sha256=W0Ydio1UeED5_xqaTzbcGzK2tH4EpA1WHUzdF-iWpqI,364
|
|
@@ -426,6 +426,6 @@ unique_toolkit/short_term_memory/service.py,sha256=2JMBEBn6GoyK-a0xvdcWpPft-3C74
|
|
|
426
426
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
427
427
|
unique_toolkit/smart_rules/compile.py,sha256=vRe0aMJWuVIK-VsqomgxQImzke7MDmwgSxxJfYCa7zw,1386
|
|
428
428
|
unique_toolkit/test_utilities/events.py,sha256=FLrhMh0A_mQutAUjoD0FdMcVQ4Gq31r35OVGzRjvLro,6760
|
|
429
|
-
unique_toolkit-2026.42.0.
|
|
430
|
-
unique_toolkit-2026.42.0.
|
|
431
|
-
unique_toolkit-2026.42.0.
|
|
429
|
+
unique_toolkit-2026.42.0.dev8.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
430
|
+
unique_toolkit-2026.42.0.dev8.dist-info/METADATA,sha256=ahv1aNL9F18iHC057Ry2rFbO6X6zaOb1-TZ080dzbSg,7821
|
|
431
|
+
unique_toolkit-2026.42.0.dev8.dist-info/RECORD,,
|
|
File without changes
|