unique-sdk 2026.36.0.dev4__tar.gz → 2026.36.0.dev6__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 (89) hide show
  1. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/PKG-INFO +1 -1
  2. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/pyproject.toml +1 -1
  3. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_agentic_table.py +1 -0
  4. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/utils/file_io.py +50 -25
  5. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/README.md +0 -0
  6. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/__init__.py +0 -0
  7. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_api_requestor.py +0 -0
  8. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_api_resource.py +0 -0
  9. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_api_version.py +0 -0
  10. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_error.py +0 -0
  11. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_http_client.py +0 -0
  12. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_list_object.py +0 -0
  13. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_object_classes.py +0 -0
  14. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_request_options.py +0 -0
  15. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_unique_object.py +0 -0
  16. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_unique_ql.py +0 -0
  17. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_unique_response.py +0 -0
  18. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_util.py +0 -0
  19. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_version.py +0 -0
  20. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/_webhook.py +0 -0
  21. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/__init__.py +0 -0
  22. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_acronyms.py +0 -0
  23. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_analytics_order.py +0 -0
  24. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_benchmarking.py +0 -0
  25. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_briefing.py +0 -0
  26. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_chat_completion.py +0 -0
  27. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_content.py +0 -0
  28. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_elicitation.py +0 -0
  29. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_embedding.py +0 -0
  30. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_event.py +0 -0
  31. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_folder.py +0 -0
  32. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_group.py +0 -0
  33. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_integrated.py +0 -0
  34. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_llm_models.py +0 -0
  35. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_mcp.py +0 -0
  36. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_message.py +0 -0
  37. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_message_assessment.py +0 -0
  38. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_message_execution.py +0 -0
  39. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_message_log.py +0 -0
  40. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_message_tool.py +0 -0
  41. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_module.py +0 -0
  42. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_scheduled_task.py +0 -0
  43. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_search.py +0 -0
  44. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_search_string.py +0 -0
  45. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_short_term_memory.py +0 -0
  46. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_space.py +0 -0
  47. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_user.py +0 -0
  48. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/api_resources/_web_search.py +0 -0
  49. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/__init__.py +0 -0
  50. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/__main__.py +0 -0
  51. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/cli.py +0 -0
  52. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/__init__.py +0 -0
  53. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/_citation_manifest.py +0 -0
  54. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/agentic_table.py +0 -0
  55. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/agentic_table_write.py +0 -0
  56. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/browser.py +0 -0
  57. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/cite_file.py +0 -0
  58. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/elicitation.py +0 -0
  59. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/files.py +0 -0
  60. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/folders.py +0 -0
  61. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/mcp.py +0 -0
  62. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/navigation.py +0 -0
  63. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/read.py +0 -0
  64. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/scheduled_tasks.py +0 -0
  65. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/search.py +0 -0
  66. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/subagent.py +0 -0
  67. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/web_search.py +0 -0
  68. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/commands/web_search_config.py +0 -0
  69. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/config.py +0 -0
  70. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/formatting.py +0 -0
  71. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/identity.py +0 -0
  72. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/metadata_filter.py +0 -0
  73. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/shell.py +0 -0
  74. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-agentic-table/SKILL.md +0 -0
  75. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-elicitation/SKILL.md +0 -0
  76. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-file-management/SKILL.md +0 -0
  77. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-mcp/SKILL.md +0 -0
  78. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-scheduled-tasks/SKILL.md +0 -0
  79. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-search/SKILL.md +0 -0
  80. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-subagent/SKILL.md +0 -0
  81. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-uploaded-search/SKILL.md +0 -0
  82. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/skills/unique-cli-web-search/SKILL.md +0 -0
  83. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/cli/state.py +0 -0
  84. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/utils/analytics_order_run.py +0 -0
  85. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/utils/benchmarking_run.py +0 -0
  86. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/utils/chat_history.py +0 -0
  87. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/utils/chat_in_space.py +0 -0
  88. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/utils/sources.py +0 -0
  89. {unique_sdk-2026.36.0.dev4 → unique_sdk-2026.36.0.dev6}/unique_sdk/utils/token.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-sdk
3
- Version: 2026.36.0.dev4
3
+ Version: 2026.36.0.dev6
4
4
  Summary:
5
5
  Author: Martin Fadler, Konstantin Krauss, Andreas Hauri
6
6
  Author-email: Martin Fadler <martin.fadler@unique.ch>, Konstantin Krauss <konstantin@unique.ch>, Andreas Hauri <andreas@unique.ch>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unique_sdk"
3
- version = "2026.36.0.dev4"
3
+ version = "2026.36.0.dev6"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -286,6 +286,7 @@ class AgenticTable(APIResource["AgenticTable"]):
286
286
  includeRowMetadata: NotRequired[bool]
287
287
  startRow: NotRequired[int]
288
288
  endRow: NotRequired[int]
289
+ rowOrders: NotRequired[list[int]]
289
290
 
290
291
  class SetCellMetadata(RequestOptions):
291
292
  tableId: str
@@ -34,24 +34,48 @@ class _VersioningKwargs(TypedDict, total=False):
34
34
  versioningEnabled: bool
35
35
 
36
36
 
37
+ # Streaming chunk size for blob downloads. Downloads MUST stream to disk:
38
+ # buffering whole files via ``response.content`` peaks at ~2x the file size
39
+ # in RAM and has OOM'd memory-limited runtimes downloading many large chat
40
+ # files concurrently (UN-24862).
41
+ _DOWNLOAD_CHUNK_BYTES = 1024 * 1024
42
+
43
+
44
+ def _stream_response_to_file(response: requests.Response, file_path: Path) -> None:
45
+ """Write the response body to *file_path* chunk by chunk.
46
+
47
+ Removes the partially written file when the transfer fails mid-stream so
48
+ callers never observe a truncated download at the destination path.
49
+ """
50
+ # open() outside the cleanup scope: if it fails (permissions, EMFILE) the
51
+ # destination was never truncated, and a pre-existing complete file there
52
+ # must not be deleted.
53
+ file = open(file_path, "wb")
54
+ try:
55
+ with file:
56
+ for chunk in response.iter_content(chunk_size=_DOWNLOAD_CHUNK_BYTES):
57
+ file.write(chunk)
58
+ except BaseException:
59
+ file_path.unlink(missing_ok=True)
60
+ raise
61
+
62
+
37
63
  # download readUrl a random directory in /tmp
38
64
  def download_file(url: str, filename: str):
39
65
  # Guard for callers without a type checker: fail fast with a clear error before reaching requests.
40
66
  if not isinstance(url, str): # pyright: ignore[reportUnnecessaryIsInstance]
41
67
  raise ValueError("URL must be a string.") # pyright: ignore[reportUnreachable]
42
- # Create a random directory inside /tmp
43
- random_dir = tempfile.mkdtemp(dir="/tmp")
44
-
45
- # Create the full file path
46
- file_path = Path(random_dir) / filename
68
+ with requests.get(
69
+ url, timeout=unique_sdk.blob_transfer_timeout, stream=True
70
+ ) as response:
71
+ if response.status_code != 200:
72
+ raise Exception(
73
+ f"Error downloading file: Status code {response.status_code}"
74
+ )
47
75
 
48
- # Download the file and save it to the random directory
49
- response = requests.get(url, timeout=unique_sdk.blob_transfer_timeout)
50
- if response.status_code == 200:
51
- with open(file_path, "wb") as file:
52
- file.write(response.content)
53
- else:
54
- raise Exception(f"Error downloading file: Status code {response.status_code}")
76
+ random_dir = tempfile.mkdtemp(dir="/tmp")
77
+ file_path = Path(random_dir) / filename
78
+ _stream_response_to_file(response, file_path)
55
79
 
56
80
  return file_path
57
81
 
@@ -369,21 +393,22 @@ def download_content(
369
393
  # Issue the request before resolving the destination. A non-200
370
394
  # response should never leave a half-created directory or empty
371
395
  # file behind for callers who supplied ``target_path``.
372
- response = requests.get(
373
- url, headers=headers, timeout=unique_sdk.blob_transfer_timeout
374
- )
375
- if response.status_code != 200:
376
- raise Exception(f"Error downloading file: Status code {response.status_code}")
396
+ with requests.get(
397
+ url, headers=headers, timeout=unique_sdk.blob_transfer_timeout, stream=True
398
+ ) as response:
399
+ if response.status_code != 200:
400
+ raise Exception(
401
+ f"Error downloading file: Status code {response.status_code}"
402
+ )
377
403
 
378
- if target_path is not None:
379
- file_path = Path(target_path)
380
- file_path.parent.mkdir(parents=True, exist_ok=True)
381
- else:
382
- random_dir = tempfile.mkdtemp(dir="/tmp")
383
- file_path = Path(random_dir) / filename
404
+ if target_path is not None:
405
+ file_path = Path(target_path)
406
+ file_path.parent.mkdir(parents=True, exist_ok=True)
407
+ else:
408
+ random_dir = tempfile.mkdtemp(dir="/tmp")
409
+ file_path = Path(random_dir) / filename
384
410
 
385
- with open(file_path, "wb") as file:
386
- file.write(response.content)
411
+ _stream_response_to_file(response, file_path)
387
412
 
388
413
  return file_path
389
414