unique-sdk 2026.32.0.dev6__tar.gz → 2026.32.0.dev7__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 (91) hide show
  1. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/PKG-INFO +1 -1
  2. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/pyproject.toml +1 -1
  3. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_api_requestor.py +8 -8
  4. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_util.py +98 -0
  5. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/README.md +0 -0
  6. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/__init__.py +0 -0
  7. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_api_resource.py +0 -0
  8. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_api_version.py +0 -0
  9. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_error.py +0 -0
  10. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_http_client.py +0 -0
  11. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_list_object.py +0 -0
  12. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_object_classes.py +0 -0
  13. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_request_options.py +0 -0
  14. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_unique_object.py +0 -0
  15. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_unique_ql.py +0 -0
  16. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_unique_response.py +0 -0
  17. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_version.py +0 -0
  18. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/_webhook.py +0 -0
  19. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/__init__.py +0 -0
  20. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_acronyms.py +0 -0
  21. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_agentic_table.py +0 -0
  22. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_analytics_order.py +0 -0
  23. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_benchmarking.py +0 -0
  24. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_briefing.py +0 -0
  25. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_chat_completion.py +0 -0
  26. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_content.py +0 -0
  27. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_dynamic_frontend.py +0 -0
  28. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_elicitation.py +0 -0
  29. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_embedding.py +0 -0
  30. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_event.py +0 -0
  31. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_folder.py +0 -0
  32. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_group.py +0 -0
  33. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_integrated.py +0 -0
  34. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_llm_models.py +0 -0
  35. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_mcp.py +0 -0
  36. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_message.py +0 -0
  37. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_message_assessment.py +0 -0
  38. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_message_execution.py +0 -0
  39. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_message_log.py +0 -0
  40. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_message_tool.py +0 -0
  41. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_module.py +0 -0
  42. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_scheduled_task.py +0 -0
  43. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_search.py +0 -0
  44. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_search_string.py +0 -0
  45. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_short_term_memory.py +0 -0
  46. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_space.py +0 -0
  47. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_user.py +0 -0
  48. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/api_resources/_web_search.py +0 -0
  49. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/__init__.py +0 -0
  50. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/__main__.py +0 -0
  51. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/cli.py +0 -0
  52. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/__init__.py +0 -0
  53. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/_citation_manifest.py +0 -0
  54. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/agentic_table.py +0 -0
  55. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/browser.py +0 -0
  56. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/cite_file.py +0 -0
  57. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/dynamic_frontend.py +0 -0
  58. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/elicitation.py +0 -0
  59. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/files.py +0 -0
  60. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/folders.py +0 -0
  61. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/mcp.py +0 -0
  62. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/navigation.py +0 -0
  63. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/read.py +0 -0
  64. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/scheduled_tasks.py +0 -0
  65. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/search.py +0 -0
  66. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/subagent.py +0 -0
  67. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/web_search.py +0 -0
  68. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/commands/web_search_config.py +0 -0
  69. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/config.py +0 -0
  70. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/formatting.py +0 -0
  71. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/identity.py +0 -0
  72. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/metadata_filter.py +0 -0
  73. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/shell.py +0 -0
  74. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-agentic-table/SKILL.md +0 -0
  75. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-dynamic-frontend/SKILL.md +0 -0
  76. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-elicitation/SKILL.md +0 -0
  77. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-file-management/SKILL.md +0 -0
  78. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-mcp/SKILL.md +0 -0
  79. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-scheduled-tasks/SKILL.md +0 -0
  80. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-search/SKILL.md +0 -0
  81. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-subagent/SKILL.md +0 -0
  82. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-uploaded-search/SKILL.md +0 -0
  83. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/skills/unique-cli-web-search/SKILL.md +0 -0
  84. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/cli/state.py +0 -0
  85. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/utils/analytics_order_run.py +0 -0
  86. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/utils/benchmarking_run.py +0 -0
  87. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/utils/chat_history.py +0 -0
  88. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/utils/chat_in_space.py +0 -0
  89. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/utils/file_io.py +0 -0
  90. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/unique_sdk/utils/sources.py +0 -0
  91. {unique_sdk-2026.32.0.dev6 → unique_sdk-2026.32.0.dev7}/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.32.0.dev6
3
+ Version: 2026.32.0.dev7
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.32.0.dev6"
3
+ version = "2026.32.0.dev7"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -194,8 +194,7 @@ class APIRequestor(object):
194
194
  )
195
195
 
196
196
  _util.log_info("Request to Unique", method=method, path=abs_url)
197
- _util.log_debug(
198
- "Request details",
197
+ _util.log_request_details(
199
198
  data=post_data,
200
199
  headers=headers,
201
200
  api_version=self.api_version,
@@ -206,7 +205,7 @@ class APIRequestor(object):
206
205
  )
207
206
 
208
207
  _util.log_info("Unique response", path=abs_url, status=rcode)
209
- _util.log_debug("Unique response body", body=rcontent)
208
+ _util.log_response_body(body=rcontent)
210
209
 
211
210
  if "Request-Id" in rheaders:
212
211
  request_id = rheaders["Request-Id"]
@@ -230,11 +229,11 @@ class APIRequestor(object):
230
229
  )
231
230
 
232
231
  _util.log_info("Async request to Unique", method=method, path=abs_url)
233
- _util.log_debug(
234
- "Async request details",
232
+ _util.log_request_details(
235
233
  data=post_data,
236
234
  headers=headers,
237
235
  api_version=self.api_version,
236
+ message="Async request details",
238
237
  )
239
238
 
240
239
  rcontent, rcode, rheaders = await self._client.request_async(
@@ -242,7 +241,7 @@ class APIRequestor(object):
242
241
  )
243
242
 
244
243
  _util.log_info("Unique response", path=abs_url, status=rcode)
245
- _util.log_debug("Unique response body", body=rcontent)
244
+ _util.log_response_body(body=rcontent)
246
245
 
247
246
  if "Request-Id" in rheaders:
248
247
  request_id = rheaders["Request-Id"]
@@ -364,7 +363,8 @@ class APIRequestor(object):
364
363
  except Exception as e:
365
364
  raise _error.APIError(
366
365
  "Invalid response body from API: %s "
367
- "(HTTP response code was %d)" % (rbody, rcode),
366
+ "(HTTP response code was %d)"
367
+ % (_util.redacted_body_for_error_message(rbody), rcode),
368
368
  cast(bytes, rbody),
369
369
  rcode,
370
370
  rheaders,
@@ -399,7 +399,7 @@ class APIRequestor(object):
399
399
  error_code=status,
400
400
  error_type=error_data.get("type"),
401
401
  error_message=error_data.get("message"),
402
- error_params=error_data.get("params"),
402
+ error_params=_util.redacted_error_params(error_data.get("params")),
403
403
  )
404
404
 
405
405
  error = cause.get("error", {}) if cause else {}
@@ -9,6 +9,7 @@ import random
9
9
  import re
10
10
  import sys
11
11
  import time
12
+ from collections.abc import Mapping
12
13
  from functools import wraps
13
14
  from typing import (
14
15
  Any,
@@ -33,6 +34,8 @@ UNIQUE_LOG = os.environ.get("UNIQUE_LOG")
33
34
 
34
35
  logger: logging.Logger = logging.getLogger("unique")
35
36
 
37
+ _REDACTED = "<redacted>"
38
+
36
39
 
37
40
  def _console_log_level():
38
41
  if unique_sdk.log in ["debug", "info"]:
@@ -42,6 +45,42 @@ def _console_log_level():
42
45
  return None
43
46
 
44
47
 
48
+ def _insecure_log_payloads_enabled() -> bool:
49
+ return os.environ.get("INSECURE_UNIQUE_SDK_LOG_PAYLOADS") == "true"
50
+
51
+
52
+ def _payload_byte_size(value: Any) -> int:
53
+ if value is None:
54
+ return 0
55
+ if isinstance(value, (bytes, bytearray)):
56
+ return len(value)
57
+ if isinstance(value, str):
58
+ return len(value.encode("utf-8"))
59
+ return len(str(value).encode("utf-8"))
60
+
61
+
62
+ def _headers_for_log(headers: Mapping[str, str] | None) -> dict[str, str] | str | None:
63
+ """Return headers for debug logs; Authorization is always redacted."""
64
+ if not _insecure_log_payloads_enabled():
65
+ return _REDACTED
66
+ if headers is None:
67
+ return None
68
+ try:
69
+ sanitized = dict(headers)
70
+ except (TypeError, ValueError):
71
+ return _REDACTED
72
+ for key in list(sanitized):
73
+ if str(key).lower() == "authorization":
74
+ sanitized[key] = _REDACTED
75
+ return sanitized
76
+
77
+
78
+ def _body_for_log(body: Any) -> Any:
79
+ if _insecure_log_payloads_enabled():
80
+ return body
81
+ return _REDACTED
82
+
83
+
45
84
  def log_debug(message, **params):
46
85
  msg = logfmt(dict(message=message, **params))
47
86
  if _console_log_level() == "debug":
@@ -56,6 +95,65 @@ def log_info(message, **params):
56
95
  logger.info(msg)
57
96
 
58
97
 
98
+ def log_request_details(
99
+ *,
100
+ data: Any,
101
+ headers: Mapping[str, str] | None,
102
+ api_version: str | None,
103
+ message: str = "Request details",
104
+ ) -> None:
105
+ if _insecure_log_payloads_enabled():
106
+ log_debug(
107
+ message,
108
+ data=data,
109
+ headers=_headers_for_log(headers),
110
+ api_version=api_version,
111
+ )
112
+ return
113
+ log_debug(
114
+ message,
115
+ data=_REDACTED,
116
+ headers=_REDACTED,
117
+ api_version=api_version,
118
+ payload_bytes=_payload_byte_size(data),
119
+ )
120
+
121
+
122
+ def log_response_body(*, body: Any) -> None:
123
+ if _insecure_log_payloads_enabled():
124
+ log_debug("Unique response body", body=body)
125
+ return
126
+ log_debug(
127
+ "Unique response body",
128
+ body=_body_for_log(body),
129
+ payload_bytes=_payload_byte_size(body),
130
+ )
131
+
132
+
133
+ def redacted_body_for_error_message(body: Any) -> Any:
134
+ """Body representation safe to embed in exception *messages*.
135
+
136
+ Exception messages surface at ERROR (retry logs, tracebacks) regardless
137
+ of LOG_LEVEL, so the raw body must not be embedded unless the insecure
138
+ opt-in is set. The full body stays available programmatically on the
139
+ exception's ``http_body`` attribute.
140
+ """
141
+ if _insecure_log_payloads_enabled():
142
+ return body
143
+ return f"<redacted {_payload_byte_size(body)} bytes>"
144
+
145
+
146
+ def redacted_error_params(params: Any) -> Any:
147
+ """Error ``params`` for the INFO-level 'Unique error received' log.
148
+
149
+ API validation errors commonly echo submitted values in ``params``, so
150
+ they are redacted unless the insecure opt-in is set.
151
+ """
152
+ if params is None or _insecure_log_payloads_enabled():
153
+ return params
154
+ return _REDACTED
155
+
156
+
59
157
  def logfmt(props):
60
158
  def fmt(key, val):
61
159
  # Handle case where val is a bytes or bytesarray